public Decision IsSatisfiedBy(LocalTrack localTrack) { var downloadPropersAndRepacks = _configService.DownloadPropersAndRepacks; var qualityComparer = new QualityModelComparer(localTrack.Artist.QualityProfile); foreach (var track in localTrack.Tracks.Where(e => e.TrackFileId > 0)) { var trackFile = track.TrackFile.Value; var qualityCompare = qualityComparer.Compare(localTrack.Quality.Quality, trackFile.Quality.Quality); if (qualityCompare < 0) { _logger.Debug("This file isn't a quality upgrade for all tracks. Skipping {0}", localTrack.Path); return(Decision.Reject("Not an upgrade for existing track file(s)")); } if (qualityCompare == 0 && downloadPropersAndRepacks != ProperDownloadTypes.DoNotPrefer && localTrack.Quality.Revision.CompareTo(trackFile.Quality.Revision) < 0) { _logger.Debug("This file isn't a quality upgrade for all tracks. Skipping {0}", localTrack.Path); return(Decision.Reject("Not an upgrade for existing track file(s)")); } } return(Decision.Accept()); }
public Decision IsSatisfiedBy(LocalAlbumRelease item, DownloadClientItem downloadClientItem) { // check if we are changing release var currentRelease = item.AlbumRelease.Album.Value.AlbumReleases.Value.Single(x => x.Monitored); var newRelease = item.AlbumRelease; // if we are, check we are upgrading if (newRelease.Id != currentRelease.Id) { var qualityComparer = new QualityModelComparer(item.AlbumRelease.Album.Value.Artist.Value.QualityProfile); // min quality of all new tracks var newMinQuality = item.LocalTracks.Select(x => x.Quality).OrderBy(x => x, qualityComparer).First(); _logger.Debug("Min quality of new files: {0}", newMinQuality); // get minimum quality of existing release var existingQualities = currentRelease.Tracks.Value.Where(x => x.TrackFileId != 0).Select(x => x.TrackFile.Value.Quality); if (existingQualities.Any()) { var existingMinQuality = existingQualities.OrderBy(x => x, qualityComparer).First(); _logger.Debug("Min quality of existing files: {0}", existingMinQuality); if (qualityComparer.Compare(existingMinQuality, newMinQuality) > 0) { _logger.Debug("This album isn't a quality upgrade for all tracks. Skipping {0}", item); return(Decision.Reject("Not an upgrade for existing album file(s)")); } } } return(Decision.Accept()); }
public Decision IsSatisfiedBy(LocalMovie localMovie, DownloadClientItem downloadClientItem) { var qualityComparer = new QualityModelComparer(localMovie.Movie.Profile); if (localMovie.Movie.MovieFileId > 0) { var movieFile = localMovie.Movie.MovieFile; if (movieFile == null) { _logger.Trace("Unable to get movie file details from the DB. MovieId: {0} MovieFileId: {1}", localMovie.Movie.Id, localMovie.Movie.MovieFileId); return(Decision.Accept()); } var qualityCompare = qualityComparer.Compare(localMovie.Quality.Quality, movieFile.Quality.Quality); if (qualityCompare < 0) { _logger.Debug("This file isn't a quality upgrade for movie. Skipping {0}", localMovie.Path); return(Decision.Reject("Not an upgrade for existing movie file(s)")); } } return(Decision.Accept()); }
public bool IsUpgradable(QualityProfile qualityProfile, LanguageProfile languageProfile, QualityModel currentQuality, Language currentLanguage, int currentScore, QualityModel newQuality, Language newLanguage, int newScore) { var qualityComparer = new QualityModelComparer(qualityProfile); var qualityCompare = qualityComparer.Compare(newQuality?.Quality, currentQuality.Quality); var downloadPropersAndRepacks = _configService.DownloadPropersAndRepacks; if (qualityCompare > 0) { _logger.Debug("New item has a better quality"); return(true); } if (qualityCompare < 0) { _logger.Debug("Existing item has better quality, skipping"); return(false); } var qualityRevisionComapre = newQuality?.Revision.CompareTo(currentQuality.Revision); // Accept unless the user doesn't want to prefer propers, optionally they can // use preferred words to prefer propers/repacks over non-propers/repacks. if (downloadPropersAndRepacks != ProperDownloadTypes.DoNotPrefer && qualityRevisionComapre > 0) { _logger.Debug("New item has a better quality revision"); return(true); } // Reject unless the user does not prefer propers/repacks and it's a revision downgrade. if (downloadPropersAndRepacks != ProperDownloadTypes.DoNotPrefer && qualityRevisionComapre < 0) { _logger.Debug("Existing item has a better quality revision, skipping"); return(false); } var languageCompare = new LanguageComparer(languageProfile).Compare(newLanguage, currentLanguage); if (languageCompare > 0) { _logger.Debug("New item has a more preferred language"); return(true); } if (languageCompare < 0) { _logger.Debug("Existing item has better language, skipping"); return(false); } if (!IsPreferredWordUpgradable(currentScore, newScore)) { _logger.Debug("Existing item has an equal or better preferred word score, skipping"); return(false); } _logger.Debug("New item has a better preferred word score"); return(true); }
public Decision IsSatisfiedBy(LocalEpisode localEpisode, DownloadClientItem downloadClientItem) { var downloadPropersAndRepacks = _configService.DownloadPropersAndRepacks; var qualityComparer = new QualityModelComparer(localEpisode.Series.QualityProfile); var languageComparer = new LanguageComparer(localEpisode.Series.LanguageProfile); var preferredWordScore = localEpisode.PreferredWordScore; foreach (var episode in localEpisode.Episodes.Where(e => e.EpisodeFileId > 0)) { var episodeFile = episode.EpisodeFile.Value; if (episodeFile == null) { _logger.Trace("Unable to get episode file details from the DB. EpisodeId: {0} EpisodeFileId: {1}", episode.Id, episode.EpisodeFileId); continue; } var qualityCompare = qualityComparer.Compare(localEpisode.Quality.Quality, episodeFile.Quality.Quality); var languageCompare = languageComparer.Compare(localEpisode.Language, episodeFile.Language); if (qualityCompare < 0) { _logger.Debug("This file isn't a quality upgrade for all episodes. Skipping {0}", localEpisode.Path); return(Decision.Reject("Not an upgrade for existing episode file(s)")); } // Same quality, is not a language upgrade, propers/repacks are preferred and it is not a revision update // This will allow language upgrades of a lower revision to be imported, which are allowed to be grabbed, // they just don't import automatically. if (qualityCompare == 0 && languageCompare <= 0 && downloadPropersAndRepacks != ProperDownloadTypes.DoNotPrefer && localEpisode.Quality.Revision.CompareTo(episodeFile.Quality.Revision) < 0) { _logger.Debug("This file isn't a quality revision upgrade for all episodes. Skipping {0}", localEpisode.Path); return(Decision.Reject("Not a quality revision upgrade for existing episode file(s)")); } if (languageCompare < 0 && qualityCompare == 0) { _logger.Debug("This file isn't a language upgrade for all episodes. Skipping {0}", localEpisode.Path); return(Decision.Reject("Not a language upgrade for existing episode file(s)")); } var episodeFilePreferredWordScore = _episodeFilePreferredWordCalculator.Calculate(localEpisode.Series, episodeFile); if (qualityCompare == 0 && languageCompare == 0 && preferredWordScore < episodeFilePreferredWordScore) { _logger.Debug("This file isn't a preferred word upgrade for all episodes. Skipping {0}", localEpisode.Path); return(Decision.Reject("Not a preferred word upgrade for existing episode file(s)")); } } return(Decision.Accept()); }
public Decision IsSatisfiedBy(LocalEpisode localEpisode) { var qualityComparer = new QualityModelComparer(localEpisode.Series.Profile); if (localEpisode.Episodes.Any(e => e.EpisodeFileId != 0 && qualityComparer.Compare(e.EpisodeFile.Value.Quality, localEpisode.Quality) > 0)) { _logger.Debug("This file isn't an upgrade for all episodes. Skipping {0}", localEpisode.Path); return Decision.Reject("Not an upgrade for existing episode file(s)"); } return Decision.Accept(); }
public bool IsSatisfiedBy(LocalEpisode localEpisode) { var qualityComparer = new QualityModelComparer(localEpisode.Series.QualityProfile); if (localEpisode.Episodes.Any(e => e.EpisodeFileId != 0 && qualityComparer.Compare(e.EpisodeFile.Value.Quality, localEpisode.Quality) > 0)) { _logger.Trace("This file isn't an upgrade for all episodes. Skipping {0}", localEpisode.Path); return false; } return true; }
public Decision IsSatisfiedBy(LocalEpisode localEpisode) { var qualityComparer = new QualityModelComparer(localEpisode.Series.Profile); if (localEpisode.Episodes.Any(e => e.EpisodeFileId != 0 && qualityComparer.Compare(e.EpisodeFile.Value.Quality, localEpisode.Quality) > 0)) { _logger.Debug("This file isn't an upgrade for all episodes. Skipping {0}", localEpisode.Path); return(Decision.Reject("Not an upgrade for existing episode file(s)")); } return(Decision.Accept()); }
public Decision IsSatisfiedBy(LocalMovie localMovie, DownloadClientItem downloadClientItem) { var qualityComparer = new QualityModelComparer(localMovie.Movie.Profile); if (localMovie.Movie.MovieFile != null && qualityComparer.Compare(localMovie.Movie.MovieFile.Quality, localMovie.Quality) > 0) { _logger.Debug("This file isn't an upgrade for movie. Skipping {0}", localMovie.Path); return(Decision.Reject("Not an upgrade for existing movie file")); } return(Decision.Accept()); }
public bool IsSatisfiedBy(LocalEpisode localEpisode) { var qualityComparer = new QualityModelComparer(localEpisode.Series.Profile); if (localEpisode.Episodes.Any(e => e.EpisodeFileId != 0 && qualityComparer.Compare(e.EpisodeFile.Value.Quality, localEpisode.Quality) > 0)) { _logger.Debug("This file isn't an upgrade for all episodes. Skipping {0}", localEpisode.Path); return(false); } return(true); }
public bool CutoffNotMet(Profile profile, QualityModel currentQuality, QualityModel newQuality = null) { var comparer = new QualityModelComparer(profile); var compare = comparer.Compare(currentQuality.Quality, profile.Cutoff); if (compare < 0) { return(true); } if (comparer.Compare(currentQuality.CustomFormats, profile.FormatCutoff) < 0) { return(true); } if (newQuality != null && IsRevisionUpgrade(currentQuality, newQuality)) { return(true); } return(false); }
public bool IsUpgradable(Profile profile, QualityModel currentQuality, List <CustomFormat> currentCustomFormats, QualityModel newQuality, List <CustomFormat> newCustomFormats) { var qualityComparer = new QualityModelComparer(profile); var qualityCompare = qualityComparer.Compare(newQuality?.Quality, currentQuality.Quality); var downloadPropersAndRepacks = _configService.DownloadPropersAndRepacks; if (qualityCompare > 0) { _logger.Debug("New item has a better quality"); return(true); } if (qualityCompare < 0) { _logger.Debug("Existing item has better quality, skipping"); return(false); } var qualityRevisionCompare = newQuality?.Revision.CompareTo(currentQuality.Revision); // Accept unless the user doesn't want to prefer propers, optionally they can // use preferred words to prefer propers/repacks over non-propers/repacks. if (downloadPropersAndRepacks != ProperDownloadTypes.DoNotPrefer && qualityRevisionCompare > 0) { return(true); } var currentFormatScore = profile.CalculateCustomFormatScore(currentCustomFormats); var newFormatScore = profile.CalculateCustomFormatScore(newCustomFormats); // Reject unless the user does not prefer propers/repacks and it's a revision downgrade. if (downloadPropersAndRepacks != ProperDownloadTypes.DoNotPrefer && qualityRevisionCompare < 0) { _logger.Debug("Existing item has a better quality revision, skipping"); return(false); } if (newFormatScore <= currentFormatScore) { _logger.Debug("New item's custom formats [{0}] do not improve on [{1}], skipping", newCustomFormats.ConcatToString(), currentCustomFormats.ConcatToString()); return(false); } _logger.Debug("New item has a custom format upgrade"); return(true); }
public Decision IsSatisfiedBy(LocalEpisode localEpisode, DownloadClientItem downloadClientItem) { var downloadPropersAndRepacks = _configService.DownloadPropersAndRepacks; var qualityComparer = new QualityModelComparer(localEpisode.Series.QualityProfile); var languageComparer = new LanguageComparer(localEpisode.Series.LanguageProfile); foreach (var episode in localEpisode.Episodes.Where(e => e.EpisodeFileId > 0)) { var episodeFile = episode.EpisodeFile.Value; if (episodeFile == null) { _logger.Trace("Unable to get episode file details from the DB. EpisodeId: {0} EpisodeFileId: {1}", episode.Id, episode.EpisodeFileId); continue; } var qualityCompare = qualityComparer.Compare(localEpisode.Quality.Quality, episodeFile.Quality.Quality); if (qualityCompare < 0) { _logger.Debug("This file isn't a quality upgrade for all episodes. Skipping {0}", localEpisode.Path); return(Decision.Reject("Not an upgrade for existing episode file(s)")); } if (qualityCompare == 0 && downloadPropersAndRepacks != ProperDownloadTypes.DoNotPrefer && localEpisode.Quality.Revision.CompareTo(episodeFile.Quality.Revision) < 0) { _logger.Debug("This file isn't a quality upgrade for all episodes. Skipping {0}", localEpisode.Path); return(Decision.Reject("Not an upgrade for existing episode file(s)")); } if (languageComparer.Compare(localEpisode.Language, episodeFile.Language) < 0 && qualityCompare == 0) { _logger.Debug("This file isn't a language upgrade for all episodes. Skipping {0}", localEpisode.Path); return(Decision.Reject("Not an upgrade for existing episode file(s)")); } } return(Decision.Accept()); }
public Decision IsSatisfiedBy(LocalTrack item, DownloadClientItem downloadClientItem) { if (!item.Tracks.Any(e => e.TrackFileId > 0)) { // No existing tracks, skip. This guards against new artists not having a QualityProfile. return(Decision.Accept()); } var downloadPropersAndRepacks = _configService.DownloadPropersAndRepacks; var qualityComparer = new QualityModelComparer(item.Artist.QualityProfile); foreach (var track in item.Tracks.Where(e => e.TrackFileId > 0)) { var trackFile = track.TrackFile.Value; if (trackFile == null) { _logger.Trace("Unable to get track file details from the DB. TrackId: {0} TrackFileId: {1}", track.Id, track.TrackFileId); continue; } var qualityCompare = qualityComparer.Compare(item.Quality.Quality, trackFile.Quality.Quality); if (qualityCompare < 0) { _logger.Debug("This file isn't a quality upgrade for all tracks. Skipping {0}", item.Path); return(Decision.Reject("Not an upgrade for existing track file(s)")); } if (qualityCompare == 0 && downloadPropersAndRepacks != ProperDownloadTypes.DoNotPrefer && item.Quality.Revision.CompareTo(trackFile.Quality.Revision) < 0) { _logger.Debug("This file isn't a quality upgrade for all tracks. Skipping {0}", item.Path); return(Decision.Reject("Not an upgrade for existing track file(s)")); } } return(Decision.Accept()); }
public virtual Decision IsSatisfiedBy(RemoteEpisode subject, SearchCriteriaBase searchCriteria) { //How do we want to handle drone being off and the automatic search being triggered? //TODO: Add a flag to the search to state it is a "scheduled" search if (searchCriteria != null) { _logger.Debug("Ignore delay for searches"); return Decision.Accept(); } var profile = subject.Series.Profile.Value; var delayProfile = _delayProfileService.BestForTags(subject.Series.Tags); var delay = delayProfile.GetProtocolDelay(subject.Release.DownloadProtocol); var isPreferredProtocol = subject.Release.DownloadProtocol == delayProfile.PreferredProtocol; if (delay == 0) { _logger.Debug("Profile does not require a waiting period before download for {0}.", subject.Release.DownloadProtocol); return Decision.Accept(); } var comparer = new QualityModelComparer(profile); if (isPreferredProtocol) { foreach (var file in subject.Episodes.Where(c => c.EpisodeFileId != 0).Select(c => c.EpisodeFile.Value)) { var upgradable = _qualityUpgradableSpecification.IsUpgradable(profile, file.Quality, subject.ParsedEpisodeInfo.Quality); if (upgradable) { var revisionUpgrade = _qualityUpgradableSpecification.IsRevisionUpgrade(file.Quality, subject.ParsedEpisodeInfo.Quality); if (revisionUpgrade) { _logger.Debug("New quality is a better revision for existing quality, skipping delay"); return Decision.Accept(); } } } } //If quality meets or exceeds the best allowed quality in the profile accept it immediately var bestQualityInProfile = new QualityModel(profile.LastAllowedQuality()); var isBestInProfile = comparer.Compare(subject.ParsedEpisodeInfo.Quality, bestQualityInProfile) >= 0; if (isBestInProfile && isPreferredProtocol) { _logger.Debug("Quality is highest in profile for preferred protocol, will not delay"); return Decision.Accept(); } var episodeIds = subject.Episodes.Select(e => e.Id); var oldest = _pendingReleaseService.OldestPendingRelease(subject.Series.Id, episodeIds); if (oldest != null && oldest.Release.AgeMinutes > delay) { return Decision.Accept(); } if (subject.Release.AgeMinutes < delay) { _logger.Debug("Waiting for better quality release, There is a {0} minute delay on {1}", delay, subject.Release.DownloadProtocol); return Decision.Reject("Waiting for better quality release"); } return Decision.Accept(); }
public virtual Decision IsSatisfiedBy(RemoteBook subject, SearchCriteriaBase searchCriteria) { if (searchCriteria != null && searchCriteria.UserInvokedSearch) { _logger.Debug("Ignoring delay for user invoked search"); return(Decision.Accept()); } var qualityProfile = subject.Author.QualityProfile.Value; var delayProfile = _delayProfileService.BestForTags(subject.Author.Tags); var delay = delayProfile.GetProtocolDelay(subject.Release.DownloadProtocol); var isPreferredProtocol = subject.Release.DownloadProtocol == delayProfile.PreferredProtocol; if (delay == 0) { _logger.Debug("Profile does not require a waiting period before download for {0}.", subject.Release.DownloadProtocol); return(Decision.Accept()); } var qualityComparer = new QualityModelComparer(qualityProfile); if (isPreferredProtocol) { foreach (var book in subject.Books) { var bookFiles = _mediaFileService.GetFilesByBook(book.Id); foreach (var file in bookFiles) { var currentQuality = file.Quality; var newQuality = subject.ParsedBookInfo.Quality; var qualityCompare = qualityComparer.Compare(newQuality?.Quality, currentQuality.Quality); if (qualityCompare == 0 && newQuality?.Revision.CompareTo(currentQuality.Revision) > 0) { _logger.Debug("New quality is a better revision for existing quality, skipping delay"); return(Decision.Accept()); } } } } // If quality meets or exceeds the best allowed quality in the profile accept it immediately var bestQualityInProfile = qualityProfile.LastAllowedQuality(); var isBestInProfile = qualityComparer.Compare(subject.ParsedBookInfo.Quality.Quality, bestQualityInProfile) >= 0; if (isBestInProfile && isPreferredProtocol) { _logger.Debug("Quality is highest in profile for preferred protocol, will not delay"); return(Decision.Accept()); } var bookIds = subject.Books.Select(e => e.Id); var oldest = _pendingReleaseService.OldestPendingRelease(subject.Author.Id, bookIds.ToArray()); if (oldest != null && oldest.Release.AgeMinutes > delay) { return(Decision.Accept()); } if (subject.Release.AgeMinutes < delay) { _logger.Debug("Waiting for better quality release, There is a {0} minute delay on {1}", delay, subject.Release.DownloadProtocol); return(Decision.Reject("Waiting for better quality release")); } return(Decision.Accept()); }
public virtual Decision IsSatisfiedBy(RemoteMovie subject, SearchCriteriaBase searchCriteria) { if (searchCriteria != null && searchCriteria.UserInvokedSearch) { _logger.Debug("Ignoring delay for user invoked search"); return(Decision.Accept()); } var profile = subject.Movie.Profile; var delayProfile = _delayProfileService.BestForTags(subject.Movie.Tags); var delay = delayProfile.GetProtocolDelay(subject.Release.DownloadProtocol); var isPreferredProtocol = subject.Release.DownloadProtocol == delayProfile.PreferredProtocol; if (delay == 0) { _logger.Debug("Profile does not require a waiting period before download for {0}.", subject.Release.DownloadProtocol); return(Decision.Accept()); } var comparer = new QualityModelComparer(profile); var file = subject.Movie.MovieFile; if (isPreferredProtocol && (subject.Movie.MovieFileId != 0 && file != null)) { var customFormats = _formatService.ParseCustomFormat(file); var upgradable = _qualityUpgradableSpecification.IsUpgradable(profile, file.Quality, customFormats, subject.ParsedMovieInfo.Quality, subject.CustomFormats); if (upgradable) { var revisionUpgrade = _qualityUpgradableSpecification.IsRevisionUpgrade(subject.Movie.MovieFile.Quality, subject.ParsedMovieInfo.Quality); if (revisionUpgrade) { _logger.Debug("New quality is a better revision for existing quality, skipping delay"); return(Decision.Accept()); } } } // If quality meets or exceeds the best allowed quality in the profile accept it immediately var bestQualityInProfile = profile.LastAllowedQuality(); var isBestInProfile = comparer.Compare(subject.ParsedMovieInfo.Quality.Quality, bestQualityInProfile) >= 0; if (isBestInProfile && isPreferredProtocol) { _logger.Debug("Quality is highest in profile for preferred protocol, will not delay."); return(Decision.Accept()); } var oldest = _pendingReleaseService.OldestPendingRelease(subject.Movie.Id); if (oldest != null && oldest.Release.AgeMinutes > delay) { return(Decision.Accept()); } if (subject.Release.AgeMinutes < delay) { _logger.Debug("Waiting for better quality release, There is a {0} minute delay on {1}", delay, subject.Release.DownloadProtocol); return(Decision.Reject("Waiting for better quality release")); } return(Decision.Accept()); }
public virtual Decision IsSatisfiedBy(RemoteEpisode subject, SearchCriteriaBase searchCriteria) { //How do we want to handle drone being off and the automatic search being triggered? //TODO: Add a flag to the search to state it is a "scheduled" search if (searchCriteria != null) { _logger.Debug("Ignore delay for searches"); return(Decision.Accept()); } var profile = subject.Series.Profile.Value; var delayProfile = _delayProfileService.BestForTags(subject.Series.Tags); var delay = delayProfile.GetProtocolDelay(subject.Release.DownloadProtocol); var isPreferredProtocol = subject.Release.DownloadProtocol == delayProfile.PreferredProtocol; if (delay == 0) { _logger.Debug("Profile does not require a waiting period before download for {0}.", subject.Release.DownloadProtocol); return(Decision.Accept()); } var comparer = new QualityModelComparer(profile); if (isPreferredProtocol) { foreach (var file in subject.Episodes.Where(c => c.EpisodeFileId != 0).Select(c => c.EpisodeFile.Value)) { var upgradable = _qualityUpgradableSpecification.IsUpgradable(profile, file.Quality, subject.ParsedEpisodeInfo.Quality); if (upgradable) { var revisionUpgrade = _qualityUpgradableSpecification.IsRevisionUpgrade(file.Quality, subject.ParsedEpisodeInfo.Quality); if (revisionUpgrade) { _logger.Debug("New quality is a better revision for existing quality, skipping delay"); return(Decision.Accept()); } } } } //If quality meets or exceeds the best allowed quality in the profile accept it immediately var bestQualityInProfile = new QualityModel(profile.LastAllowedQuality()); var isBestInProfile = comparer.Compare(subject.ParsedEpisodeInfo.Quality, bestQualityInProfile) >= 0; if (isBestInProfile && isPreferredProtocol) { _logger.Debug("Quality is highest in profile for preferred protocol, will not delay"); return(Decision.Accept()); } var episodeIds = subject.Episodes.Select(e => e.Id); var oldest = _pendingReleaseService.OldestPendingRelease(subject.Series.Id, episodeIds); if (oldest != null && oldest.Release.AgeMinutes > delay) { return(Decision.Accept()); } if (subject.Release.AgeMinutes < delay) { _logger.Debug("Waiting for better quality release, There is a {0} minute delay on {1}", delay, subject.Release.DownloadProtocol); return(Decision.Reject("Waiting for better quality release")); } return(Decision.Accept()); }
public virtual Decision IsSatisfiedBy(RemoteMovie subject, SearchCriteriaBase searchCriteria) { if (searchCriteria != null && searchCriteria.UserInvokedSearch) { _logger.Debug("Ignoring delay for user invoked search"); return(Decision.Accept()); } var profile = subject.Movie.Profile.Value; var delayProfile = _delayProfileService.BestForTags(subject.Movie.Tags); var delay = delayProfile.GetProtocolDelay(subject.Release.DownloadProtocol); var isPreferredProtocol = subject.Release.DownloadProtocol == delayProfile.PreferredProtocol; // Preferred word count var title = subject.Release.Title; var preferredWords = subject.Movie.Profile.Value.PreferredTags; var preferredCount = 0; if (preferredWords == null) { preferredCount = 1; _logger.Debug("Preferred words is null, setting preffered count to 1."); } else { preferredCount = preferredWords.AsEnumerable().Count(w => title.ToLower().Contains(w.ToLower())); } if (delay == 0) { _logger.Debug("Profile does not require a waiting period before download for {0}.", subject.Release.DownloadProtocol); return(Decision.Accept()); } var comparer = new QualityModelComparer(profile); if (isPreferredProtocol && (subject.Movie.MovieFileId != 0 && subject.Movie.MovieFile != null) && (preferredCount > 0 || preferredWords == null)) { var upgradable = _qualityUpgradableSpecification.IsUpgradable(profile, subject.Movie.MovieFile.Value.Quality, subject.ParsedMovieInfo.Quality); if (upgradable) { var revisionUpgrade = _qualityUpgradableSpecification.IsRevisionUpgrade(subject.Movie.MovieFile.Value.Quality, subject.ParsedMovieInfo.Quality); if (revisionUpgrade) { _logger.Debug("New quality is a better revision for existing quality and preferred word count is {0}, skipping delay", preferredCount); return(Decision.Accept()); } } } // If quality meets or exceeds the best allowed quality in the profile accept it immediately var bestQualityInProfile = new QualityModel(profile.LastAllowedQuality()); var isBestInProfile = comparer.Compare(subject.ParsedMovieInfo.Quality, bestQualityInProfile) >= 0; if (isBestInProfile && isPreferredProtocol && (preferredCount > 0 || preferredWords == null)) { _logger.Debug("Quality is highest in profile for preferred protocol and preferred word count is {0}, will not delay.", preferredCount); return(Decision.Accept()); } var oldest = _pendingReleaseService.OldestPendingRelease(subject.Movie.Id); if (oldest != null && oldest.Release.AgeMinutes > delay) { return(Decision.Accept()); } if (subject.Release.AgeMinutes < delay) { _logger.Debug("Waiting for better quality release, There is a {0} minute delay on {1}", delay, subject.Release.DownloadProtocol); return(Decision.Reject("Waiting for better quality release")); } return(Decision.Accept()); }
public virtual bool IsSatisfiedBy(RemoteEpisode subject, SearchCriteriaBase searchCriteria) { //How do we want to handle drone being off and the automatic search being triggered? //TODO: Add a flag to the search to state it is a "scheduled" search if (searchCriteria != null) { _logger.Debug("Ignore delay for searches"); return(true); } var profile = subject.Series.Profile.Value; if (profile.GrabDelay == 0) { _logger.Debug("Profile does not delay before download"); return(true); } var comparer = new QualityModelComparer(profile); foreach (var file in subject.Episodes.Where(c => c.EpisodeFileId != 0).Select(c => c.EpisodeFile.Value)) { var upgradable = _qualityUpgradableSpecification.IsUpgradable(profile, file.Quality, subject.ParsedEpisodeInfo.Quality); if (upgradable) { var revisionUpgrade = _qualityUpgradableSpecification.IsRevisionUpgrade(file.Quality, subject.ParsedEpisodeInfo.Quality); if (revisionUpgrade) { _logger.Debug("New quality is a better revision for existing quality, skipping delay"); return(true); } } } //If quality meets or exceeds the best allowed quality in the profile accept it immediately var bestQualityInProfile = new QualityModel(profile.Items.Last(q => q.Allowed).Quality); var bestCompare = comparer.Compare(subject.ParsedEpisodeInfo.Quality, bestQualityInProfile); if (bestCompare >= 0) { _logger.Debug("Quality is highest in profile, will not delay"); return(true); } if (profile.GrabDelayMode == GrabDelayMode.Cutoff) { var cutoff = new QualityModel(profile.Cutoff); var cutoffCompare = comparer.Compare(subject.ParsedEpisodeInfo.Quality, cutoff); if (cutoffCompare >= 0) { _logger.Debug("Quality meets or exceeds the cutoff, will not delay"); return(true); } } if (profile.GrabDelayMode == GrabDelayMode.First) { var episodeIds = subject.Episodes.Select(e => e.Id); var oldest = _pendingReleaseService.GetPendingRemoteEpisodes(subject.Series.Id) .Where(r => r.Episodes.Select(e => e.Id).Intersect(episodeIds).Any()) .OrderByDescending(p => p.Release.AgeHours) .FirstOrDefault(); if (oldest != null && oldest.Release.AgeHours > profile.GrabDelay) { return(true); } } if (subject.Release.AgeHours < profile.GrabDelay) { _logger.Debug("Age ({0}) is less than delay {1}, delaying", subject.Release.AgeHours, profile.GrabDelay); return(false); } return(true); }
public virtual Decision IsSatisfiedBy(RemoteAlbum subject, SearchCriteriaBase searchCriteria) { if (searchCriteria != null && searchCriteria.UserInvokedSearch) { _logger.Debug("Ignoring delay for user invoked search"); return(Decision.Accept()); } var qualityProfile = subject.Artist.QualityProfile.Value; var delayProfile = _delayProfileService.BestForTags(subject.Artist.Tags); var delay = delayProfile.GetProtocolDelay(subject.Release.DownloadProtocol); var isPreferredProtocol = subject.Release.DownloadProtocol == delayProfile.PreferredProtocol; if (delay == 0) { _logger.Debug("Profile does not require a waiting period before download for {0}.", subject.Release.DownloadProtocol); return(Decision.Accept()); } var qualityComparer = new QualityModelComparer(qualityProfile); if (isPreferredProtocol) { foreach (var album in subject.Albums) { var trackFiles = _mediaFileService.GetFilesByAlbum(album.Id); if (trackFiles.Any()) { var currentQualities = trackFiles.Select(c => c.Quality).Distinct().ToList(); var upgradable = _upgradableSpecification.IsUpgradable(qualityProfile, currentQualities, _preferredWordServiceCalculator.Calculate(subject.Artist, trackFiles[0].GetSceneOrFileName()), subject.ParsedAlbumInfo.Quality, subject.PreferredWordScore); if (upgradable) { _logger.Debug("New quality is a better revision for existing quality, skipping delay"); return(Decision.Accept()); } } } } // If quality meets or exceeds the best allowed quality in the profile accept it immediately var bestQualityInProfile = qualityProfile.LastAllowedQuality(); var isBestInProfile = qualityComparer.Compare(subject.ParsedAlbumInfo.Quality.Quality, bestQualityInProfile) >= 0; if (isBestInProfile && isPreferredProtocol) { _logger.Debug("Quality is highest in profile for preferred protocol, will not delay"); return(Decision.Accept()); } var albumIds = subject.Albums.Select(e => e.Id); var oldest = _pendingReleaseService.OldestPendingRelease(subject.Artist.Id, albumIds.ToArray()); if (oldest != null && oldest.Release.AgeMinutes > delay) { return(Decision.Accept()); } if (subject.Release.AgeMinutes < delay) { _logger.Debug("Waiting for better quality release, There is a {0} minute delay on {1}", delay, subject.Release.DownloadProtocol); return(Decision.Reject("Waiting for better quality release")); } return(Decision.Accept()); }