Example #1
0
        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());
        }
Example #2
0
        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());
        }
Example #3
0
        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());
        }
Example #4
0
        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);
        }
Example #5
0
        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());
        }
Example #6
0
        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;
        }
Example #8
0
        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());
        }
Example #9
0
        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());
        }
Example #10
0
        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);
        }
Example #11
0
        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);
        }
Example #13
0
        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());
        }
Example #15
0
        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();
        }
Example #16
0
        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());
        }
Example #17
0
        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());
        }
Example #18
0
        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());
        }
Example #19
0
        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());
        }
Example #20
0
        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);
        }
Example #21
0
        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());
        }