예제 #1
0
        public virtual Decision IsSatisfiedBy(RemoteBook subject, SearchCriteriaBase searchCriteria)
        {
            var qualityProfile = subject.Author.QualityProfile.Value;

            foreach (var file in subject.Books.SelectMany(b => b.BookFiles.Value))
            {
                // Get a distinct list of all current track qualities for a given book
                var currentQualities = new List <QualityModel> {
                    file.Quality
                };

                _logger.Debug("Comparing file quality with report. Existing files contain {0}", currentQualities.ConcatToString());

                if (!_upgradableSpecification.CutoffNotMet(qualityProfile,
                                                           currentQualities,
                                                           _preferredWordServiceCalculator.Calculate(subject.Author, file.GetSceneOrFileName()),
                                                           subject.ParsedBookInfo.Quality,
                                                           subject.PreferredWordScore))
                {
                    _logger.Debug("Cutoff already met by existing files, rejecting.");

                    var qualityCutoffIndex = qualityProfile.GetIndex(qualityProfile.Cutoff);
                    var qualityCutoff      = qualityProfile.Items[qualityCutoffIndex.Index];

                    return(Decision.Reject("Existing files meets cutoff: {0}", qualityCutoff));
                }
            }

            return(Decision.Accept());
        }
예제 #2
0
        public virtual Decision IsSatisfiedBy(RemoteEpisode subject, SearchCriteriaBase searchCriteria)
        {
            if (searchCriteria != null)
            {
                if ((searchCriteria as SeasonSearchCriteria) == null)
                {
                    _logger.Debug("Skipping monitored check during search");
                    return(Decision.Accept());
                }
            }

            if (!subject.Series.Monitored)
            {
                _logger.Debug("{0} is present in the DB but not tracked. skipping.", subject.Series);
                return(Decision.Reject("Series is not monitored"));
            }

            var monitoredCount = subject.Episodes.Count(episode => episode.Monitored);

            if (monitoredCount == subject.Episodes.Count)
            {
                return(Decision.Accept());
            }

            _logger.Debug("Only {0}/{1} episodes are monitored. skipping.", monitoredCount, subject.Episodes);
            return(Decision.Reject("Episode is not monitored"));
        }
예제 #3
0
        public Decision IsSatisfiedBy(LocalAlbumRelease localAlbumRelease)
        {
            var artist          = localAlbumRelease.AlbumRelease.Album.Value.Artist.Value;
            var qualityComparer = new QualityModelComparer(artist.QualityProfile);

            // check if we are changing release
            var currentRelease = localAlbumRelease.AlbumRelease.Album.Value.AlbumReleases.Value.Single(x => x.Monitored);
            var newRelease     = localAlbumRelease.AlbumRelease;

            // if we are, check we are upgrading
            if (newRelease.Id != currentRelease.Id)
            {
                // min quality of all new tracks
                var newMinQuality = localAlbumRelease.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}", localAlbumRelease);
                        return(Decision.Reject("Not an upgrade for existing album file(s)"));
                    }
                }
            }

            return(Decision.Accept());
        }
예제 #4
0
        public virtual Decision IsSatisfiedBy(RemoteMovie subject, SearchCriteriaBase searchCriteria)
        {
            if (subject.Release == null)
            {
                return(Decision.Accept());
            }

            foreach (var regex in DiscRegex)
            {
                if (regex.IsMatch(subject.Release.Title))
                {
                    _logger.Debug("Release contains raw Bluray, rejecting.");
                    return(Decision.Reject("Raw Bluray release"));
                }
            }

            if (subject.Release.Container.IsNullOrWhiteSpace())
            {
                return(Decision.Accept());
            }

            if (_dvdContainerTypes.Contains(subject.Release.Container.ToLower()))
            {
                _logger.Debug("Release contains raw DVD, rejecting.");
                return(Decision.Reject("Raw DVD release"));
            }

            if (_blurayContainerTypes.Contains(subject.Release.Container.ToLower()))
            {
                _logger.Debug("Release contains raw Bluray, rejecting.");
                return(Decision.Reject("Raw Bluray release"));
            }

            return(Decision.Accept());
        }
예제 #5
0
        public Decision IsSatisfiedBy(RemoteMovie subject, SearchCriteriaBase searchCriteria)
        {
            var queue = _queueService.GetQueue()
                        .Select(q => q.RemoteMovie).ToList();

            var matchingSeries = queue.Where(q => q.Movie.Id == subject.Movie.Id);

            foreach (var remoteEpisode in matchingSeries)
            {
                _logger.Debug("Checking if existing release in queue meets cutoff. Queued quality is: {0}", remoteEpisode.ParsedMovieInfo.Quality);

                if (!_qualityUpgradableSpecification.CutoffNotMet(subject.Movie.Profile, remoteEpisode.ParsedMovieInfo.Quality, subject.ParsedMovieInfo.Quality))
                {
                    return(Decision.Reject("Quality for release in queue already meets cutoff: {0}", remoteEpisode.ParsedMovieInfo.Quality));
                }

                _logger.Debug("Checking if release is higher quality than queued release. Queued quality is: {0}", remoteEpisode.ParsedMovieInfo.Quality);

                if (!_qualityUpgradableSpecification.IsUpgradable(subject.Movie.Profile, remoteEpisode.ParsedMovieInfo.Quality, subject.ParsedMovieInfo.Quality))
                {
                    return(Decision.Reject("Quality for release in queue is of equal or higher preference: {0}", remoteEpisode.ParsedMovieInfo.Quality));
                }
            }

            return(Decision.Accept());
        }
예제 #6
0
        public Decision IsSatisfiedBy(RemoteMovie subject, SearchCriteriaBase searchCriteria)
        {
            var torrentInfo = subject.Release as TorrentInfo;

            IIndexerSettings indexerSettings = null;

            try {
                indexerSettings = _indexerFactory.Get(subject.Release.IndexerId)?.Settings as IIndexerSettings;
            }
            catch (Exception e)
            {
                _logger.Debug("Indexer with id {0} does not exist, skipping minimum seeder checks.", subject.Release.IndexerId);
            }


            if (torrentInfo == null || indexerSettings == null)
            {
                return(Decision.Accept());
            }

            if (indexerSettings is ITorrentIndexerSettings torrentIndexerSettings)
            {
                var minimumSeeders = torrentIndexerSettings.MinimumSeeders;

                if (torrentInfo.Seeders.HasValue && torrentInfo.Seeders.Value < minimumSeeders)
                {
                    _logger.Debug("Not enough seeders: {0}. Minimum seeders: {1}", torrentInfo.Seeders, minimumSeeders);
                    return(Decision.Reject("Not enough seeders: {0}. Minimum seeders: {1}", torrentInfo.Seeders, minimumSeeders));
                }
            }

            return(Decision.Accept());
        }
예제 #7
0
        public Decision IsSatisfiedBy(LocalEpisode localEpisode, DownloadClientItem downloadClientItem)
        {
            if (downloadClientItem == null)
            {
                _logger.Debug("No download client item provided, skipping.");
                return(Decision.Accept());
            }

            var grabbedHistory = _historyService.FindByDownloadId(downloadClientItem.DownloadId)
                                 .Where(h => h.EventType == HistoryEventType.Grabbed)
                                 .ToList();

            if (grabbedHistory.Empty())
            {
                _logger.Debug("No grabbed history for this download client item");
                return(Decision.Accept());
            }

            foreach (var item in grabbedHistory)
            {
                if (item.Quality != localEpisode.Quality)
                {
                    _logger.Debug("Quality for grabbed release ({0}) does not match the quality of the file ({1})", item.Quality, localEpisode.Quality);
                    return(Decision.Reject("File quality does not match quality of the grabbed release"));
                }
            }

            return(Decision.Accept());
        }
예제 #8
0
        public virtual Decision IsSatisfiedBy(RemoteEpisode subject, SearchCriteriaBase searchCriteria)
        {
            var releaseGroup = subject.ParsedEpisodeInfo.ReleaseGroup;

            if (subject.Series.SeriesType != SeriesTypes.Anime)
            {
                return(Decision.Accept());
            }

            foreach (var file in subject.Episodes.Where(c => c.EpisodeFileId != 0).Select(c => c.EpisodeFile.Value))
            {
                if (_qualityUpgradableSpecification.IsRevisionUpgrade(file.Quality, subject.ParsedEpisodeInfo.Quality))
                {
                    if (file.ReleaseGroup.IsNullOrWhiteSpace())
                    {
                        _logger.Debug("Unable to compare release group, existing file's release group is unknown");
                        return(Decision.Reject("Existing release group is unknown"));
                    }

                    if (releaseGroup.IsNullOrWhiteSpace())
                    {
                        _logger.Debug("Unable to compare release group, release's release group is unknown");
                        return(Decision.Reject("Release group is unknown"));
                    }

                    if (file.ReleaseGroup != releaseGroup)
                    {
                        _logger.Debug("Existing Release group is: {0} - release's release group is: {1}", file.ReleaseGroup, releaseGroup);
                        return(Decision.Reject("{0} does not match existing release group {1}", releaseGroup, file.ReleaseGroup));
                    }
                }
            }

            return(Decision.Accept());
        }
예제 #9
0
        public virtual Decision IsSatisfiedBy(RemoteMovie subject, SearchCriteriaBase searchCriteria)
        {
            var profile = subject.Movie.Profile;
            var file    = subject.Movie.MovieFile;

            if (file != null)
            {
                file.Movie = subject.Movie;
                _logger.Debug("Comparing file quality with report. Existing file is {0}", file.Quality);

                var customFormats = _formatService.ParseCustomFormat(file);

                if (!_upgradableSpecification.CutoffNotMet(profile,
                                                           file.Quality,
                                                           customFormats,
                                                           subject.ParsedMovieInfo.Quality))
                {
                    _logger.Debug("Existing custom formats {0} meet cutoff",
                                  customFormats.ConcatToString());

                    var qualityCutoffIndex = profile.GetIndex(profile.Cutoff);
                    var qualityCutoff      = profile.Items[qualityCutoffIndex.Index];

                    return(Decision.Reject("Existing file meets cutoff: {0}", qualityCutoff));
                }
            }

            return(Decision.Accept());
        }
예제 #10
0
        public virtual Decision IsSatisfiedBy(RemoteMovie subject, SearchCriteriaBase searchCriteria)
        {
            if (subject.Release == null || subject.Movie?.Tags == null || subject.Release.IndexerId == 0)
            {
                return(Decision.Accept());
            }

            IndexerDefinition indexer;

            try
            {
                indexer = _indexerFactory.Get(subject.Release.IndexerId);
            }
            catch (ModelNotFoundException)
            {
                _logger.Debug("Indexer with id {0} does not exist, skipping indexer tags check", subject.Release.IndexerId);
                return(Decision.Accept());
            }

            // If indexer has tags, check that at least one of them is present on the series
            var indexerTags = indexer.Tags;

            if (indexerTags.Any() && indexerTags.Intersect(subject.Movie.Tags).Empty())
            {
                _logger.Debug("Indexer {0} has tags. None of these are present on movie {1}. Rejecting", subject.Release.Indexer, subject.Movie);

                return(Decision.Reject("Movie tags do not match any of the indexer tags"));
            }

            return(Decision.Accept());
        }
예제 #11
0
        public Decision IsSatisfiedBy(LocalMovie localMovie, DownloadClientItem downloadClientItem)
        {
            if (localMovie.ExistingFile)
            {
                return(Decision.Accept());
            }

            var dirInfo = new FileInfo(localMovie.Path).Directory;

            if (dirInfo == null)
            {
                return(Decision.Accept());
            }

            //TODO: Actually implement this!!!!

            /*var folderInfo = Parser.Parser.ParseMovieTitle(dirInfo.Name, false);
             *
             * if (folderInfo == null)
             * {
             *  return Decision.Accept();
             * }*/

            return(Decision.Accept());
        }
예제 #12
0
        public Decision IsSatisfiedBy(LocalMovie localMovie, DownloadClientItem downloadClientItem)
        {
            if (localMovie.ExistingFile)
            {
                _logger.Debug("{0} is in movie folder, skipping unpacking check", localMovie.Path);
                return(Decision.Accept());
            }

            foreach (var workingFolder in _configService.DownloadClientWorkingFolders.Split('|'))
            {
                DirectoryInfo parent = Directory.GetParent(localMovie.Path);
                while (parent != null)
                {
                    if (parent.Name.StartsWith(workingFolder))
                    {
                        if (OsInfo.IsNotWindows)
                        {
                            _logger.Debug("{0} is still being unpacked", localMovie.Path);
                            return(Decision.Reject("File is still being unpacked"));
                        }

                        if (_diskProvider.FileGetLastWrite(localMovie.Path) > DateTime.UtcNow.AddMinutes(-5))
                        {
                            _logger.Debug("{0} appears to be unpacking still", localMovie.Path);
                            return(Decision.Reject("File is still being unpacked"));
                        }
                    }

                    parent = parent.Parent;
                }
            }

            return(Decision.Accept());
        }
예제 #13
0
        public Decision IsSatisfiedBy(LocalEpisode localEpisode, DownloadClientItem downloadClientItem)
        {
            var episodeFiles = localEpisode.Episodes.Where(e => e.EpisodeFileId != 0).Select(e => e.EpisodeFile).ToList();

            if (episodeFiles.Count == 0)
            {
                _logger.Debug("No existing episode file, skipping");
                return(Decision.Accept());
            }

            if (episodeFiles.Count > 1)
            {
                _logger.Debug("More than one existing episode file, skipping.");
                return(Decision.Accept());
            }

            var episodeFile = episodeFiles.First().Value;

            if (episodeFile == null)
            {
                var episode = localEpisode.Episodes.First();
                _logger.Trace("Unable to get episode file details from the DB. EpisodeId: {0} EpisodeFileId: {1}", episode.Id, episode.EpisodeFileId);

                return(Decision.Accept());
            }

            if (episodeFiles.First().Value.Size == localEpisode.Size)
            {
                _logger.Debug("'{0}' Has the same filesize as existing file", localEpisode.Path);
                return(Decision.Reject("Has the same filesize as existing file"));
            }

            return(Decision.Accept());
        }
예제 #14
0
        public virtual Decision IsSatisfiedBy(RemoteBook subject, SearchCriteriaBase searchCriteria)
        {
            var qualityProfile = subject.Author.QualityProfile.Value;

            foreach (var file in subject.Books.SelectMany(b => b.BookFiles.Value))
            {
                if (file == null)
                {
                    _logger.Debug("File is no longer available, skipping this file.");
                    continue;
                }

                _logger.Debug("Comparing file quality with report. Existing files contain {0}", file.Quality);

                if (!_upgradableSpecification.IsUpgradeAllowed(qualityProfile,
                                                               file.Quality,
                                                               subject.ParsedBookInfo.Quality))
                {
                    _logger.Debug("Upgrading is not allowed by the quality profile");

                    return(Decision.Reject("Existing files and the Quality profile does not allow upgrades"));
                }
            }

            return(Decision.Accept());
        }
예제 #15
0
        public Decision IsSatisfiedBy(LocalTrack localTrack, DownloadClientItem downloadClientItem)
        {
            var trackFiles = localTrack.Tracks.Where(e => e.TrackFileId != 0).Select(e => e.TrackFile).ToList();

            if (trackFiles.Count == 0)
            {
                _logger.Debug("No existing track file, skipping");
                return(Decision.Accept());
            }

            if (trackFiles.Count > 1)
            {
                _logger.Debug("More than one existing track file, skipping.");
                return(Decision.Accept());
            }

            var trackFile = trackFiles.First().Value;

            if (trackFile == null)
            {
                var track = localTrack.Tracks.First();
                _logger.Trace("Unable to get track file details from the DB. TrackId: {0} TrackFileId: {1}", track.Id, track.TrackFileId);

                return(Decision.Accept());
            }

            if (trackFiles.First().Value.Size == localTrack.Size)
            {
                _logger.Debug("'{0}' Has the same filesize as existing file", localTrack.Path);
                return(Decision.Reject("Has the same filesize as existing file"));
            }

            return(Decision.Accept());
        }
예제 #16
0
        public Decision IsSatisfiedBy(LocalMovie localMovie)
        {
            if (localMovie.ExistingFile)
            {
                return(Decision.Accept());
            }

            var dirInfo = new FileInfo(localMovie.Path).Directory;

            if (dirInfo == null)
            {
                return(Decision.Accept());
            }

            var folderInfo = Parser.Parser.ParseTitle(dirInfo.Name);

            if (folderInfo == null)
            {
                return(Decision.Accept());
            }

            if (folderInfo.FullSeason)
            {
                return(Decision.Accept());
            }

            return(Decision.Accept());
        }
예제 #17
0
        public virtual Decision IsSatisfiedBy(RemoteAlbum subject, SearchCriteriaBase searchCriteria)
        {
            var qualityProfile = subject.Artist.QualityProfile.Value;

            foreach (var album in subject.Albums)
            {
                var tracksMissing = _missingFilesCache.Get(album.Id.ToString(), () => _trackService.TracksWithoutFiles(album.Id).Any(),
                                                           TimeSpan.FromSeconds(30));
                var trackFiles = _mediaFileService.GetFilesByAlbum(album.Id);

                if (!tracksMissing && trackFiles.Any())
                {
                    // Get a distinct list of all current track qualities for a given album
                    var currentQualities = trackFiles.Select(c => c.Quality).Distinct().ToList();

                    _logger.Debug("Comparing file quality with report. Existing files contain {0}", currentQualities.ConcatToString());

                    if (!_upgradableSpecification.CutoffNotMet(qualityProfile,
                                                               currentQualities,
                                                               _preferredWordServiceCalculator.Calculate(subject.Artist, trackFiles[0].GetSceneOrFileName()),
                                                               subject.ParsedAlbumInfo.Quality,
                                                               subject.PreferredWordScore))
                    {
                        _logger.Debug("Cutoff already met by existing files, rejecting.");

                        var qualityCutoffIndex = qualityProfile.GetIndex(qualityProfile.Cutoff);
                        var qualityCutoff      = qualityProfile.Items[qualityCutoffIndex.Index];

                        return(Decision.Reject("Existing files meets cutoff: {0}", qualityCutoff));
                    }
                }
            }

            return(Decision.Accept());
        }
        public virtual Decision IsSatisfiedBy(RemoteBook subject, SearchCriteriaBase searchCriteria)
        {
            if (!_configService.AutoUnmonitorPreviouslyDownloadedBooks)
            {
                return(Decision.Accept());
            }

            if (searchCriteria != null)
            {
                _logger.Debug("Skipping deleted bookfile check during search");
                return(Decision.Accept());
            }

            var missingTrackFiles = subject.Books
                                    .SelectMany(v => _bookService.GetFilesByBook(v.Id))
                                    .DistinctBy(v => v.Id)
                                    .Where(v => IsTrackFileMissing(subject.Author, v))
                                    .ToArray();

            if (missingTrackFiles.Any())
            {
                foreach (var missingTrackFile in missingTrackFiles)
                {
                    _logger.Trace("Book file {0} is missing from disk.", missingTrackFile.Path);
                }

                _logger.Debug("Files for this book exist in the database but not on disk, will be unmonitored on next diskscan. skipping.");
                return(Decision.Reject("Author is not monitored"));
            }

            return(Decision.Accept());
        }
예제 #19
0
        public virtual Decision IsSatisfiedBy(RemoteEpisode subject, SearchCriteriaBase searchCriteria)
        {
            _logger.Debug("Checking if release meets restrictions: {0}", subject);

            var title        = subject.Release.Title;
            var restrictions = _restrictionService.AllForTags(subject.Series.Tags);

            var required = restrictions.Where(r => r.Required.IsNotNullOrWhiteSpace());
            var ignored  = restrictions.Where(r => r.Ignored.IsNotNullOrWhiteSpace());

            foreach (var r in required)
            {
                var split = r.Required.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).ToList();

                if (!ContainsAny(split, title))
                {
                    _logger.Debug("[{0}] does not contain one of the required terms: {1}", title, r.Required);
                    return(Decision.Reject("Does not contain one of the required terms: {0}", r.Required));
                }
            }

            foreach (var r in ignored)
            {
                var split = r.Ignored.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).ToList();

                if (ContainsAny(split, title))
                {
                    _logger.Debug("[{0}] contains one or more ignored terms: {1}", title, r.Ignored);
                    return(Decision.Reject("Contains one or more ignored terms: {0}", r.Ignored));
                }
            }

            _logger.Debug("[{0}] No restrictions apply, allowing", subject);
            return(Decision.Accept());
        }
예제 #20
0
        public virtual Decision IsSatisfiedBy(RemoteMovie subject, SearchCriteriaBase searchCriteria)
        {
            if (subject.Movie.MovieFile == null)
            {
                return(Decision.Accept());
            }

            var profile = subject.Movie.Profile;
            var file    = subject.Movie.MovieFile;

            file.Movie = subject.Movie;
            var customFormats = _formatService.ParseCustomFormat(file);

            _logger.Debug("Comparing file quality with report. Existing file is {0} [{1}]", file.Quality, customFormats.ConcatToString());

            if (!_qualityUpgradableSpecification.IsUpgradable(profile,
                                                              file.Quality,
                                                              customFormats,
                                                              subject.ParsedMovieInfo.Quality,
                                                              subject.CustomFormats))
            {
                return(Decision.Reject("Quality for existing file on disk is of equal or higher preference: {0} [{1}]", file.Quality, customFormats.ConcatToString()));
            }

            return(Decision.Accept());
        }
예제 #21
0
        public Decision IsSatisfiedBy(RemoteEpisode subject, SearchCriteriaBase searchCriteria)
        {
            var size        = subject.Release.Size;
            var maximumSize = _configService.MaximumSize.Megabytes();

            if (maximumSize == 0)
            {
                _logger.Debug("Maximum size is not set.");
                return(Decision.Accept());
            }

            if (size == 0)
            {
                _logger.Debug("Release has unknown size, skipping size check.");
                return(Decision.Accept());
            }

            _logger.Debug("Checking if release meets maximum size requirements. {0}", size.SizeSuffix());

            if (size > maximumSize)
            {
                var message = $"{size.SizeSuffix()} is too big, maximum size is {maximumSize.SizeSuffix()}";

                _logger.Debug(message);
                return(Decision.Reject(message));
            }

            return(Decision.Accept());
        }
예제 #22
0
        public virtual Decision IsSatisfiedBy(RemoteEpisode subject, SearchCriteriaBase searchCriteria)
        {
            var qualityProfile  = subject.Series.QualityProfile.Value;
            var languageProfile = subject.Series.LanguageProfile.Value;

            foreach (var file in subject.Episodes.Where(c => c.EpisodeFileId != 0).Select(c => c.EpisodeFile.Value))
            {
                if (file == null)
                {
                    _logger.Debug("File is no longer available, skipping this file.");
                    continue;
                }

                _logger.Debug("Comparing file quality and language with report. Existing file is {0} - {1}", file.Quality, file.Language);

                if (!_upgradableSpecification.CutoffNotMet(qualityProfile,
                                                           languageProfile,
                                                           file.Quality,
                                                           file.Language,
                                                           _episodeFilePreferredWordCalculator.Calculate(subject.Series, file),
                                                           subject.ParsedEpisodeInfo.Quality,
                                                           subject.PreferredWordScore))
                {
                    _logger.Debug("Cutoff already met, rejecting.");

                    var qualityCutoffIndex = qualityProfile.GetIndex(qualityProfile.Cutoff);
                    var qualityCutoff      = qualityProfile.Items[qualityCutoffIndex.Index];

                    return(Decision.Reject("Existing file meets cutoff: {0} - {1}", qualityCutoff, languageProfile.Cutoff));
                }
            }

            return(Decision.Accept());
        }
예제 #23
0
        public Decision IsSatisfiedBy(RemoteEpisode remoteEpisode, SearchCriteriaBase searchCriteria)
        {
            if (searchCriteria == null)
            {
                return(Decision.Accept());
            }

            var criteriaEpisodes = searchCriteria.Episodes.Select(v => v.Id).ToList();
            var remoteEpisodes   = remoteEpisode.Episodes.Select(v => v.Id).ToList();

            if (!criteriaEpisodes.Intersect(remoteEpisodes).Any())
            {
                _logger.Debug("Release rejected since the episode wasn't requested: {0}", remoteEpisode.ParsedEpisodeInfo);

                if (remoteEpisodes.Any())
                {
                    var episodes = remoteEpisode.Episodes.OrderBy(v => v.SeasonNumber).ThenBy(v => v.EpisodeNumber).ToList();

                    if (episodes.Count > 1)
                    {
                        return(Decision.Reject($"Episode wasn't requested: {episodes.First().SeasonNumber}x{episodes.First().EpisodeNumber}-{episodes.Last().EpisodeNumber}"));
                    }
                    else
                    {
                        return(Decision.Reject($"Episode wasn't requested: {episodes.First().SeasonNumber}x{episodes.First().EpisodeNumber}"));
                    }
                }
                else
                {
                    return(Decision.Reject("Episode wasn't requested"));
                }
            }

            return(Decision.Accept());
        }
예제 #24
0
        public virtual Decision IsSatisfiedBy(RemoteEpisode subject, SearchCriteriaBase searchCriteria)
        {
            if (searchCriteria != null)
            {
                return(Decision.Accept());
            }

            foreach (var file in subject.Episodes.Where(c => c.EpisodeFileId != 0).Select(c => c.EpisodeFile.Value))
            {
                if (_qualityUpgradableSpecification.IsRevisionUpgrade(file.Quality, subject.ParsedEpisodeInfo.Quality))
                {
                    if (file.DateAdded < DateTime.Today.AddDays(-7))
                    {
                        _logger.Debug("Proper for old file, rejecting: {0}", subject);
                        return(Decision.Reject("Proper for old file"));
                    }

                    if (!_configService.AutoDownloadPropers)
                    {
                        _logger.Debug("Auto downloading of propers is disabled");
                        return(Decision.Reject("Proper downloading is disabled"));
                    }
                }
            }

            return(Decision.Accept());
        }
예제 #25
0
        public virtual Decision IsSatisfiedBy(RemoteAlbum remoteAlbum, SearchCriteriaBase searchCriteria)
        {
            if (searchCriteria == null)
            {
                return(Decision.Accept());
            }

            var singleAlbumSpec = searchCriteria as AlbumSearchCriteria;

            if (singleAlbumSpec == null)
            {
                return(Decision.Accept());
            }

            if (Parser.Parser.CleanArtistName(singleAlbumSpec.AlbumTitle) != Parser.Parser.CleanArtistName(remoteAlbum.ParsedAlbumInfo.AlbumTitle))
            {
                _logger.Debug("Album does not match searched album title, skipping.");
                return(Decision.Reject("Wrong album"));
            }

            if (!remoteAlbum.ParsedAlbumInfo.AlbumTitle.Any())
            {
                _logger.Debug("Full discography result during single album search, skipping.");
                return(Decision.Reject("Full artist pack"));
            }

            return(Decision.Accept());
        }
        public Decision IsSatisfiedBy(RemoteEpisode remoteEpisode, SearchCriteriaBase searchCriteria)
        {
            if (searchCriteria == null)
            {
                return(Decision.Accept());
            }

            var singleEpisodeSpec = searchCriteria as SingleEpisodeSearchCriteria;

            if (singleEpisodeSpec == null)
            {
                return(Decision.Accept());
            }

            if (singleEpisodeSpec.SeasonNumber != remoteEpisode.ParsedEpisodeInfo.SeasonNumber)
            {
                _logger.Debug("Season number does not match searched season number, skipping.");
                return(Decision.Reject("Wrong season"));
            }

            if (!remoteEpisode.ParsedEpisodeInfo.EpisodeNumbers.Any())
            {
                _logger.Debug("Full season result during single episode search, skipping.");
                return(Decision.Reject("Full season pack"));
            }

            if (!remoteEpisode.ParsedEpisodeInfo.EpisodeNumbers.Contains(singleEpisodeSpec.EpisodeNumber))
            {
                _logger.Debug("Episode number does not match searched episode number, skipping.");
                return(Decision.Reject("Wrong episode"));
            }

            return(Decision.Accept());
        }
예제 #27
0
        public virtual Decision IsSatisfiedBy(RemoteAlbum subject, SearchCriteriaBase searchCriteria)
        {
            foreach (var album in subject.Albums)
            {
                var tracksMissing = _missingFilesCache.Get(album.Id.ToString(),
                                                           () => _trackService.TracksWithoutFiles(album.Id).Any(),
                                                           TimeSpan.FromSeconds(30));
                var trackFiles = _mediaFileService.GetFilesByAlbum(album.Id);

                if (!tracksMissing && trackFiles.Any())
                {
                    var currentQualities = trackFiles.Select(c => c.Quality).Distinct().ToList();

                    if (!_upgradableSpecification.IsUpgradable(subject.Artist.QualityProfile,
                                                               currentQualities,
                                                               _preferredWordServiceCalculator.Calculate(subject.Artist, trackFiles[0].GetSceneOrFileName(), subject.Release?.IndexerId ?? 0),
                                                               subject.ParsedAlbumInfo.Quality,
                                                               subject.PreferredWordScore))
                    {
                        return(Decision.Reject("Existing files on disk is of equal or higher preference: {0}", currentQualities.ConcatToString()));
                    }
                }
            }

            return(Decision.Accept());
        }
예제 #28
0
        public Decision IsSatisfiedBy(LocalBook item, DownloadClientItem downloadClientItem)
        {
            var files = item.Book?.BookFiles?.Value;

            if (files == null || !files.Any())
            {
                // No existing books, skip.  This guards against new authors not having a QualityProfile.
                return(Decision.Accept());
            }

            var downloadPropersAndRepacks = _configService.DownloadPropersAndRepacks;
            var qualityComparer           = new QualityModelComparer(item.Author.QualityProfile);

            foreach (var bookFile in files)
            {
                var qualityCompare = qualityComparer.Compare(item.Quality.Quality, bookFile.Quality.Quality);

                if (qualityCompare < 0)
                {
                    _logger.Debug("This file isn't a quality upgrade for all books. Skipping {0}", item.Path);
                    return(Decision.Reject("Not an upgrade for existing book file(s)"));
                }

                if (qualityCompare == 0 && downloadPropersAndRepacks != ProperDownloadTypes.DoNotPrefer &&
                    item.Quality.Revision.CompareTo(bookFile.Quality.Revision) < 0)
                {
                    _logger.Debug("This file isn't a quality upgrade for all books. Skipping {0}", item.Path);
                    return(Decision.Reject("Not an upgrade for existing book file(s)"));
                }
            }

            return(Decision.Accept());
        }
예제 #29
0
        public virtual Decision IsSatisfiedBy(RemoteMovie subject, SearchCriteriaBase searchCriteria)
        {
            if (subject.Release.DownloadProtocol != Indexers.DownloadProtocol.Usenet)
            {
                _logger.Debug("Not checking minimum age requirement for non-usenet report");
                return(Decision.Accept());
            }

            var age        = subject.Release.AgeMinutes;
            var minimumAge = _configService.MinimumAge;

            if (minimumAge == 0)
            {
                _logger.Debug("Minimum age is not set.");
                return(Decision.Accept());
            }


            _logger.Debug("Checking if report meets minimum age requirements. {0}", age);

            if (age < minimumAge)
            {
                _logger.Debug("Only {0} minutes old, minimum age is {1} minutes", age, minimumAge);
                return(Decision.Reject("Only {0} minutes old, minimum age is {1} minutes", age, minimumAge));
            }

            _logger.Debug("Release is {0} minutes old, greater than minimum age of {1} minutes", age, minimumAge);

            return(Decision.Accept());
        }
예제 #30
0
        public virtual Decision IsSatisfiedBy(RemoteEpisode subject, SearchCriteriaBase searchCriteria)
        {
            var qualityProfile  = subject.Series.QualityProfile.Value;
            var languageProfile = subject.Series.LanguageProfile.Value;

            foreach (var file in subject.Episodes.Where(c => c.EpisodeFileId != 0).Select(c => c.EpisodeFile.Value))
            {
                if (file == null)
                {
                    _logger.Debug("File is no longer available, skipping this file.");
                    continue;
                }

                _logger.Debug("Comparing file quality and language with report. Existing file is {0} - {1}", file.Quality, file.Language);

                if (!_upgradableSpecification.IsUpgradeAllowed(qualityProfile,
                                                               languageProfile,
                                                               file.Quality,
                                                               file.Language,
                                                               subject.ParsedEpisodeInfo.Quality,
                                                               subject.ParsedEpisodeInfo.Language))
                {
                    _logger.Debug("Upgrading is not allowed by the quality or language profile");

                    return(Decision.Reject("Existing file and the Quality or Language profile does not allow upgrades"));
                }
            }

            return(Decision.Accept());
        }