public virtual bool IsSatisfiedBy(EpisodeParseResult subject)
        {
            var series = _seriesProvider.FindSeries(subject.CleanTitle);

            if (series == null)
            {
                logger.Trace("{0} is not mapped to any series in DB. skipping", subject.CleanTitle);
                return false;
            }

            subject.Series = series;

            if (!series.Monitored)
            {
                logger.Debug("{0} is present in the DB but not tracked. skipping.", subject.CleanTitle);
                return false;
            }

            var episodes = _episodeProvider.GetEpisodesByParseResult(subject);

            //return monitored if any of the episodes are monitored
            if (episodes.Any(episode => !episode.Ignored))
            {
                return true;
            }

            logger.Debug("All episodes are ignored. skipping.");
            return false;
        }
        public void Setup()
        {
            Mocker.Resolve<QualityUpgradeSpecification>();
            _upgradeDisk = Mocker.Resolve<UpgradeDiskSpecification>();

            firstFile = new EpisodeFile { Quality = QualityTypes.Bluray1080p, Proper = true };
            secondFile = new EpisodeFile { Quality = QualityTypes.Bluray1080p, Proper = true };

            var singleEpisodeList = new List<Episode> { new Episode { EpisodeFile = firstFile }, new Episode { EpisodeFile = null } };
            var doubleEpisodeList = new List<Episode> { new Episode { EpisodeFile = firstFile }, new Episode { EpisodeFile = secondFile }, new Episode { EpisodeFile = null } };

            var fakeSeries = Builder<Series>.CreateNew()
                         .With(c => c.QualityProfile = new QualityProfile { Cutoff = QualityTypes.Bluray1080p })
                         .Build();

            parseResultMulti = new EpisodeParseResult
            {
                Series = fakeSeries,
                Quality = new QualityModel(QualityTypes.DVD, true),
                EpisodeNumbers = new List<int> { 3, 4 },
                SeasonNumber = 12,
                Episodes = doubleEpisodeList
            };

            parseResultSingle = new EpisodeParseResult
            {
                Series = fakeSeries,
                Quality = new QualityModel(QualityTypes.DVD, true),
                EpisodeNumbers = new List<int> { 3 },
                SeasonNumber = 12,
                Episodes = singleEpisodeList
            };
        }
Пример #3
0
        public virtual bool IsInQueue(EpisodeParseResult newParseResult)
        {
            try
            {
                var queue = GetQueue().Where(c => c.ParseResult != null);

                var matchigTitle = queue.Where(q => String.Equals(q.ParseResult.CleanTitle, newParseResult.Series.CleanTitle, StringComparison.InvariantCultureIgnoreCase));

                var matchingTitleWithQuality = matchigTitle.Where(q => q.ParseResult.Quality >= newParseResult.Quality);


                if (newParseResult.Series.IsDaily)
                {
                    return matchingTitleWithQuality.Any(q => q.ParseResult.AirDate.Value.Date == newParseResult.AirDate.Value.Date);
                }

                var matchingSeason = matchingTitleWithQuality.Where(q => q.ParseResult.SeasonNumber == newParseResult.SeasonNumber);

                if (newParseResult.FullSeason)
                {
                    return matchingSeason.Any();
                }

                return matchingSeason.Any(q => q.ParseResult.EpisodeNumbers != null && q.ParseResult.EpisodeNumbers.Any(e => newParseResult.EpisodeNumbers.Contains(e)));
            }

            catch (Exception ex)
            {
                logger.WarnException("Unable to connect to Nzbget to check queue.", ex);
                return false;
            }
        }
Пример #4
0
        public virtual bool DownloadReport(EpisodeParseResult parseResult)
        {
            var downloadTitle = GetDownloadTitle(parseResult);

            var provider = GetActiveDownloadClient();

            bool success = provider.DownloadNzb(parseResult.NzbUrl, GetDownloadTitle(parseResult));

            if (success)
            {
                logger.Trace("Download added to Queue: {0}", downloadTitle);


                foreach (var episode in _episodeProvider.GetEpisodesByParseResult(parseResult))
                {
                    var history = new History();
                    history.Date = DateTime.Now;
                    history.Indexer = parseResult.Indexer;
                    history.IsProper = parseResult.Quality.Proper;
                    history.Quality = parseResult.Quality.QualityType;
                    history.NzbTitle = parseResult.OriginalString;
                    history.EpisodeId = episode.EpisodeId;
                    history.SeriesId = episode.SeriesId;

                    _historyProvider.Add(history);
                    _episodeProvider.MarkEpisodeAsFetched(episode.EpisodeId);

                    _signalRProvider.UpdateEpisodeStatus(episode.EpisodeId, EpisodeStatusType.Downloading);
                }

                _externalNotificationProvider.OnGrab(downloadTitle);
            }

            return success;
        }
 private void WithGermanRelease()
 {
     parseResult = Builder<EpisodeParseResult>
             .CreateNew()
             .With(p => p.Language = LanguageType.German)
             .Build();
 }
        public void Setup()
        {
            spec = Mocker.Resolve<AllowedDownloadSpecification>();
            parseResult = new EpisodeParseResult();

            Mocker.GetMock<QualityAllowedByProfileSpecification>()
                    .Setup(c => c.IsSatisfiedBy(It.IsAny<EpisodeParseResult>()))
                    .Returns(true);

            Mocker.GetMock<AcceptableSizeSpecification>()
                    .Setup(c => c.IsSatisfiedBy(It.IsAny<EpisodeParseResult>()))
                    .Returns(true);

            Mocker.GetMock<UpgradeDiskSpecification>()
                    .Setup(c => c.IsSatisfiedBy(It.IsAny<EpisodeParseResult>()))
                    .Returns(true);

            Mocker.GetMock<AlreadyInQueueSpecification>()
                    .Setup(c => c.IsSatisfiedBy(It.IsAny<EpisodeParseResult>()))
                    .Returns(false);

            Mocker.GetMock<RetentionSpecification>()
                    .Setup(c => c.IsSatisfiedBy(It.IsAny<EpisodeParseResult>()))
                    .Returns(true);
        }
 private void WithEnglishRelease()
 {
     parseResult = Builder<EpisodeParseResult>
             .CreateNew()
             .With(p => p.Language = LanguageType.English)
             .Build();
 }
        public void Setup()
        {
            _customStartDateSpecification = Mocker.Resolve<CustomStartDateSpecification>();

            firstEpisode = new Episode { AirDate = DateTime.Today };
            secondEpisode = new Episode { AirDate = DateTime.Today };

            fakeSeries = Builder<Series>.CreateNew()
                .With(c => c.Monitored = true)
                .With(c => c.CustomStartDate = null)
                .Build();

            parseResultMulti = new EpisodeParseResult
            {
                SeriesTitle = "Title",
                Series = fakeSeries,
                EpisodeNumbers = new List<int> { 3, 4 },
                SeasonNumber = 12,
                Episodes = new List<Episode> { firstEpisode, secondEpisode }
            };

            parseResultSingle = new EpisodeParseResult
            {
                SeriesTitle = "Title",
                Series = fakeSeries,
                EpisodeNumbers = new List<int> { 3 },
                SeasonNumber = 12,
                Episodes = new List<Episode> { firstEpisode }
            };
        }
Пример #9
0
        protected override EpisodeParseResult CustomParser(SyndicationItem item, EpisodeParseResult currentResult)
        {
            if (currentResult != null)
            {
                currentResult.Size = 0;
            }

            return currentResult;
        }
        public void Setup()
        {
            retentionSpecification = Mocker.Resolve<RetentionSpecification>();

            parseResult = new EpisodeParseResult
            {
                Age = 100
            };
        }
Пример #11
0
        protected override EpisodeParseResult CustomParser(SyndicationItem item, EpisodeParseResult currentResult)
        {
            if (currentResult != null)
            {
                var sizeString = Regex.Match(item.Summary.Text, @"\d+\.\d{1,2} \w{3}", RegexOptions.IgnoreCase).Value;
                currentResult.Size = Parser.GetReportSize(sizeString);
            }

            return currentResult;
        }
        public virtual bool IsSatisfiedBy(EpisodeParseResult subject)
        {
            logger.Trace("Checking if report meets quality requirements. {0}", subject.Quality);
            if (!subject.Series.QualityProfile.Allowed.Contains(subject.Quality.Quality))
            {
                logger.Trace("Quality {0} rejected by Series' quality profile", subject.Quality);
                return false;
            }

            return true;
        }
Пример #13
0
        public virtual bool IsSatisfiedBy(EpisodeParseResult subject)
        {
            logger.Trace("Checking if report meets language requirements. {0}", subject.Language);
            if (subject.Language != LanguageType.English)
            {
                logger.Trace("Report Language: {0} rejected because it is not english", subject.Language);
                return false;
            }

            return true;
        }
        public virtual bool IsSatisfiedBy(EpisodeParseResult subject)
        {
            foreach (var file in _episodeProvider.GetEpisodesByParseResult(subject).Select(c => c.EpisodeFile).Where(c => c != null))
            {
                logger.Trace("Comparing file quality with report. Existing file is {0} proper:{1}", file.Quality, file.Proper);
                if (!_qualityUpgradeSpecification.IsSatisfiedBy(new Quality { QualityType = file.Quality, Proper = file.Proper }, subject.Quality, subject.Series.QualityProfile.Cutoff))
                    return false;
            }

            return true;
        }
Пример #15
0
        public virtual bool IsSatisfiedBy(EpisodeParseResult subject)
        {
            logger.Trace("Checking if report meets retention requirements. {0}", subject.Age);
            if (_configProvider.Retention > 0 && subject.Age > _configProvider.Retention)
            {
                logger.Trace("Quality {0} rejected by user's retention limit", subject.Age);
                return false;
            }

            return true;
        }
        public virtual bool IsSatisfiedBy(EpisodeParseResult subject)
        {
            if (!_qualityAllowedByProfileSpecification.IsSatisfiedBy(subject)) return false;
            if (!_upgradeDiskSpecification.IsSatisfiedBy(subject)) return false;
            if (!_retentionSpecification.IsSatisfiedBy(subject)) return false;
            if (!_acceptableSizeSpecification.IsSatisfiedBy(subject)) return false;
            if (_alreadyInQueueSpecification.IsSatisfiedBy(subject)) return false;

            logger.Debug("Episode {0} is needed", subject);
            return true;
        }
Пример #17
0
        public void tostring_full_season()
        {
            var parseResult = new EpisodeParseResult();
            parseResult.SeriesTitle = "My Series";
            parseResult.SeasonNumber = 12;
            parseResult.FullSeason = true;
            parseResult.AirDate = null;
            parseResult.Quality = new Quality(QualityTypes.HDTV, false);


            parseResult.ToString().Should().Be("My Series - Season 12 HDTV");
        }
Пример #18
0
        public override SearchHistoryItem CheckReport(Series series, dynamic options, EpisodeParseResult episodeParseResult,
                                                                SearchHistoryItem item)
        {
            if(options.SeasonNumber != episodeParseResult.SeasonNumber)
            {
                logger.Trace("Season number does not match searched season number, skipping.");
                item.SearchError = ReportRejectionType.WrongSeason;

                return item;
            }

            return item;
        }
Пример #19
0
        public void tostring_multi_season_episode_proper()
        {
            var parseResult = new EpisodeParseResult();
            parseResult.SeriesTitle = "My Series";
            parseResult.SeasonNumber = 12;
            parseResult.EpisodeNumbers = new List<int> { 3, 4, 5 };
            parseResult.FullSeason = false;
            parseResult.AirDate = null;
            parseResult.Quality = new Quality(QualityTypes.HDTV, true);


            parseResult.ToString().Should().Be("My Series - S12E03-04-05 HDTV [proper]");
        }
Пример #20
0
        public void tostring_single_season_episode()
        {
            var parseResult = new EpisodeParseResult();
            parseResult.SeriesTitle = "My Series";
            parseResult.SeasonNumber = 12;
            parseResult.EpisodeNumbers = new List<int> { 3 };
            parseResult.FullSeason = false;
            parseResult.AirDate = null;
            parseResult.Quality = new Quality(QualityTypes.HDTV, false);


            parseResult.ToString().Should().Be("My Series - S12E03 HDTV");
        }
 public virtual ReportRejectionType IsSatisfiedBy(EpisodeParseResult subject)
 {
     if (!_qualityAllowedByProfileSpecification.IsSatisfiedBy(subject)) return ReportRejectionType.QualityNotWanted;
     if (!_customStartDateSpecification.IsSatisfiedBy(subject)) return ReportRejectionType.AiredAfterCustomStartDate;
     if (!_upgradeDiskSpecification.IsSatisfiedBy(subject)) return ReportRejectionType.ExistingQualityIsEqualOrBetter;
     if (!_languageSpecification.IsSatisfiedBy(subject)) return ReportRejectionType.LanguageNotWanted;
     if (!_retentionSpecification.IsSatisfiedBy(subject)) return ReportRejectionType.Retention;
     if (!_acceptableSizeSpecification.IsSatisfiedBy(subject)) return ReportRejectionType.Size;
     if (!_allowedReleaseGroupSpecification.IsSatisfiedBy(subject)) return ReportRejectionType.ReleaseGroupNotWanted;
     if (_alreadyInQueueSpecification.IsSatisfiedBy(subject)) return ReportRejectionType.AlreadyInQueue;
     
     logger.Debug("Episode {0} is needed", subject);
     return ReportRejectionType.None;
 }
        public virtual bool IsSatisfiedBy(EpisodeParseResult subject)
        {
            foreach (var episode in subject.Episodes)
            {
                var bestQualityInHistory = _historyProvider.GetBestQualityInHistory(subject.Series.SeriesId, episode.SeasonNumber, episode.EpisodeNumber);
                if (bestQualityInHistory != null)
                {
                    logger.Trace("Comparing history quality with report. History is {0}", bestQualityInHistory);
                    if (!_qualityUpgradeSpecification.IsSatisfiedBy(bestQualityInHistory, subject.Quality, subject.Series.QualityProfile.Cutoff))
                        return false;
                }
            }

            return true;
        }
Пример #23
0
        public override SearchHistoryItem CheckReport(Series series, dynamic options, EpisodeParseResult episodeParseResult,
                                                                SearchHistoryItem item)
        {
            Episode episode = options.Episode;

            if (!episodeParseResult.AirDate.HasValue || episodeParseResult.AirDate.Value != episode.AirDate.Value)
            {
                logger.Trace("Episode AirDate does not match searched episode number, skipping.");
                item.SearchError = ReportRejectionType.WrongEpisode;

                return item;
            }

            return item;
        }
        public virtual bool IsSatisfiedBy(EpisodeParseResult subject)
        {
            logger.Trace("Beginning size check for: {0}", subject);

            if(subject.Quality.Quality == QualityTypes.RAWHD)
            {
                logger.Trace("Raw-HD release found, skipping size check.");
                return true;
            }

            var qualityType = _qualityTypeProvider.Get((int)subject.Quality.Quality);

            if (qualityType.MaxSize == 0)
            {
                logger.Trace("Max size is 0 (unlimited) - skipping check.");
                return true;
            }

            var maxSize = qualityType.MaxSize.Megabytes();
            var series = subject.Series;

            //Multiply maxSize by Series.Runtime
            maxSize = maxSize * series.Runtime;

            //Multiply maxSize by the number of episodes parsed (if EpisodeNumbers is null it will be treated as a single episode)
            //TODO: is this check really necessary? shouldn't we blowup?
            if (subject.EpisodeNumbers != null)
                maxSize = maxSize * subject.EpisodeNumbers.Count;

            //Check if there was only one episode parsed
            //and it is the first or last episode of the season
            if (subject.EpisodeNumbers != null && subject.EpisodeNumbers.Count == 1 &&
                _episodeProvider.IsFirstOrLastEpisodeOfSeason(series.SeriesId,
                subject.SeasonNumber, subject.EpisodeNumbers[0]))
            {
                maxSize = maxSize * 2;
            }

            //If the parsed size is greater than maxSize we don't want it
            if (subject.Size > maxSize)
            {
                logger.Trace("Item: {0}, Size: {1} is greater than maximum allowed size ({2}), rejecting.", subject, subject.Size, maxSize);
                return false;
            }
                
            logger.Trace("Item: {0}, meets size contraints.", subject);
            return true;
        }
        public void Setup()
        {
            _qualityAllowedByProfile = Mocker.Resolve<QualityAllowedByProfileSpecification>();

            var fakeSeries = Builder<Series>.CreateNew()
                         .With(c => c.QualityProfile = new QualityProfile { Cutoff = QualityTypes.Bluray1080p })
                         .Build();

            parseResult = new EpisodeParseResult
            {
                Series = fakeSeries,
                Quality = new QualityModel(QualityTypes.DVD, true),
                EpisodeNumbers = new List<int> { 3 },
                SeasonNumber = 12,
            };
        }
        public virtual bool IsSatisfiedBy(EpisodeParseResult subject)
        {
            foreach (var file in subject.Episodes.Select(c => c.EpisodeFile).Where(c => c != null))
            {
                logger.Trace("Comparing file quality with report. Existing file is {0} proper:{1}", file.Quality, file.Proper);
                if (!_qualityUpgradeSpecification.IsSatisfiedBy(new QualityModel { Quality = file.Quality, Proper = file.Proper }, subject.Quality, subject.Series.QualityProfile.Cutoff))
                    return false;

                if(subject.Quality.Proper && file.DateAdded < DateTime.Today.AddDays(-7))
                {
                    logger.Trace("Proper for old file, skipping: {0}", subject);
                    return false;
                }
            }

            return true;
        }
        public virtual bool IsSatisfiedBy(EpisodeParseResult subject)
        {
            if (!subject.Series.CustomStartDate.HasValue)
            {
                logger.Debug("{0} does not restrict downloads before date.", subject.Series.Title);
                return true;
            }

            if (subject.Episodes.Any(episode => episode.AirDate >= subject.Series.CustomStartDate.Value))
            {
                logger.Debug("One or more episodes aired after cutoff, downloading.");
                return true;
            }

            logger.Debug("Episodes aired before cutoff date: {0}", subject.Series.CustomStartDate);
            return false;
        }
        public void existing_single_episode_should_return_single_existing_episode()
        {
            Db.Insert(fakeEpisode);
            Db.Insert(fakeSeries);

            var parseResult = new EpisodeParseResult
                                  {
                                      Series = fakeSeries,
                                      SeasonNumber = fakeEpisode.SeasonNumber,
                                      EpisodeNumbers = new List<int> { fakeEpisode.EpisodeNumber }
                                  };

            var ep = episodeProvider.GetEpisodesByParseResult(parseResult);

            ep.Should().HaveCount(1);
            parseResult.EpisodeTitle.Should().Be(fakeEpisode.Title);
            VerifyEpisode(ep[0], fakeEpisode);
            Db.Fetch<Episode>().Should().HaveCount(1);
        }
Пример #29
0
        public override SearchHistoryItem CheckReport(Series series, dynamic options, EpisodeParseResult episodeParseResult,
                                                                SearchHistoryItem item)
        {
            if(series.UseSceneNumbering && options.Episode.SeasonNumber > 0 && options.Episode.EpisodeNumber > 0)
            {
                if (options.Episode.SceneSeasonNumber != episodeParseResult.SeasonNumber)
                {
                    logger.Trace("Season number does not match searched season number, skipping.");
                    item.SearchError = ReportRejectionType.WrongSeason;

                    return item;
                }

                if (!episodeParseResult.EpisodeNumbers.Contains(options.Episode.SceneEpisodeNumber))
                {
                    logger.Trace("Episode number does not match searched episode number, skipping.");
                    item.SearchError = ReportRejectionType.WrongEpisode;

                    return item;
                }

                return item;
            }

            if(options.Episode.SeasonNumber != episodeParseResult.SeasonNumber)
            {
                logger.Trace("Season number does not match searched season number, skipping.");
                item.SearchError = ReportRejectionType.WrongSeason;

                return item;
            }

            if (!episodeParseResult.EpisodeNumbers.Contains(options.Episode.EpisodeNumber))
            {
                logger.Trace("Episode number does not match searched episode number, skipping.");
                item.SearchError = ReportRejectionType.WrongEpisode;

                return item;
            }

            return item;
        }
        public void Setup()
        {
            Mocker.Resolve<QualityUpgradeSpecification>();
            _upgradeHistory = Mocker.Resolve<UpgradeHistorySpecification>();

            var fakeSeries = Builder<Series>.CreateNew()
                         .With(c => c.QualityProfile = new QualityProfile { Cutoff = QualityTypes.Bluray1080p })
                         .Build();

            parseResultMulti = new EpisodeParseResult
            {
                Series = fakeSeries,
                Quality = new Quality(QualityTypes.DVD, true),
                EpisodeNumbers = new List<int> { 3, 4 },
                SeasonNumber = 12,
            };

            parseResultSingle = new EpisodeParseResult
            {
                Series = fakeSeries,
                Quality = new Quality(QualityTypes.DVD, true),
                EpisodeNumbers = new List<int> { 3 },
                SeasonNumber = 12,
            };

            firstQuality = new Quality(QualityTypes.Bluray1080p, true);
            secondQuality = new Quality(QualityTypes.Bluray1080p, true);

            var singleEpisodeList = new List<Episode> { new Episode { SeasonNumber = 12, EpisodeNumber = 3 } };
            var doubleEpisodeList = new List<Episode> { 
                                                            new Episode { SeasonNumber = 12, EpisodeNumber = 3 }, 
                                                            new Episode { SeasonNumber = 12, EpisodeNumber = 4 }, 
                                                            new Episode { SeasonNumber = 12, EpisodeNumber = 5 }
                                                       };

            Mocker.GetMock<EpisodeProvider>().Setup(c => c.GetEpisodesByParseResult(parseResultSingle)).Returns(singleEpisodeList);
            Mocker.GetMock<EpisodeProvider>().Setup(c => c.GetEpisodesByParseResult(parseResultMulti)).Returns(doubleEpisodeList);

            Mocker.GetMock<HistoryProvider>().Setup(c => c.GetBestQualityInHistory(fakeSeries.SeriesId, 12, 3)).Returns(firstQuality);
            Mocker.GetMock<HistoryProvider>().Setup(c => c.GetBestQualityInHistory(fakeSeries.SeriesId, 12, 4)).Returns(secondQuality);
            Mocker.GetMock<HistoryProvider>().Setup(c => c.GetBestQualityInHistory(fakeSeries.SeriesId, 12, 5)).Returns<Quality>(null);
        }