public virtual Decision IsSatisfiedBy(RemoteBook 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; var ageRounded = Math.Round(age, 1); if (minimumAge == 0) { _logger.Debug("Minimum age is not set."); return(Decision.Accept()); } _logger.Debug("Checking if report meets minimum age requirements. {0}", ageRounded); if (age < minimumAge) { _logger.Debug("Only {0} minutes old, minimum age is {1} minutes", ageRounded, minimumAge); return(Decision.Reject("Only {0} minutes old, minimum age is {1} minutes", ageRounded, minimumAge)); } _logger.Debug("Release is {0} minutes old, greater than minimum age of {1} minutes", ageRounded, minimumAge); return(Decision.Accept()); }
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()); }
protected override string AddFromTorrentFile(RemoteBook remoteBook, string hash, string filename, byte[] fileContent) { var actualHash = _proxy.AddTorrentFromFile(filename, fileContent, Settings); if (actualHash.IsNullOrWhiteSpace()) { throw new DownloadClientException("Deluge failed to add torrent " + filename); } _proxy.SetTorrentSeedingConfiguration(actualHash, remoteBook.SeedConfiguration, Settings); if (Settings.MusicCategory.IsNotNullOrWhiteSpace()) { _proxy.SetTorrentLabel(actualHash, Settings.MusicCategory, Settings); } var isRecentBook = remoteBook.IsRecentBook(); if ((isRecentBook && Settings.RecentTvPriority == (int)DelugePriority.First) || (!isRecentBook && Settings.OlderTvPriority == (int)DelugePriority.First)) { _proxy.MoveTorrentToTopInQueue(actualHash, Settings); } return(actualHash.ToUpper()); }
public void Setup() { _remoteBook = new RemoteBook() { Release = new ReleaseInfo() }; }
public void Setup() { var completed = Builder <DownloadClientItem> .CreateNew() .With(h => h.Status = DownloadItemStatus.Completed) .With(h => h.OutputPath = new OsPath(@"C:\DropFolder\MyDownload".AsOsAgnostic())) .With(h => h.Title = "Drone.DroneTheBook.FLAC") .Build(); _grabHistory = Builder <EntityHistory> .CreateListOfSize(2).BuildList(); var remoteBook = new RemoteBook { Author = new Author(), Books = new List <Book> { new Book { Id = 1 } } }; _trackedDownload = Builder <TrackedDownload> .CreateNew() .With(c => c.State = TrackedDownloadState.Downloading) .With(c => c.DownloadItem = completed) .With(c => c.RemoteBook = remoteBook) .Build(); Mocker.GetMock <IHistoryService>() .Setup(s => s.Find(_trackedDownload.DownloadItem.DownloadId, EntityHistoryEventType.Grabbed)) .Returns(_grabHistory); }
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()); }
protected override string AddFromMagnetLink(RemoteBook remoteBook, string hash, string magnetLink) { if (!Proxy.GetConfig(Settings).DhtEnabled&& !magnetLink.Contains("&tr=")) { throw new NotSupportedException("Magnet Links without trackers not supported if DHT is disabled"); } Proxy.AddTorrentFromUrl(magnetLink, Settings); var isRecentBook = remoteBook.IsRecentBook(); if ((isRecentBook && Settings.RecentTvPriority == (int)QBittorrentPriority.First) || (!isRecentBook && Settings.OlderTvPriority == (int)QBittorrentPriority.First)) { Proxy.MoveTorrentToTopInQueue(hash.ToLower(), Settings); } SetInitialState(hash.ToLower()); if (remoteBook.SeedConfiguration != null && (remoteBook.SeedConfiguration.Ratio.HasValue || remoteBook.SeedConfiguration.SeedTime.HasValue)) { Proxy.SetTorrentSeedingConfiguration(hash.ToLower(), remoteBook.SeedConfiguration, Settings); } return(hash); }
private Rejection EvaluateSpec(IDecisionEngineSpecification spec, RemoteBook remoteBook, SearchCriteriaBase searchCriteriaBase = null) { try { var result = spec.IsSatisfiedBy(remoteBook, searchCriteriaBase); if (!result.Accepted) { return(new Rejection(result.Reason, spec.Type)); } } catch (NotImplementedException) { _logger.Trace("Spec " + spec.GetType().Name + " not implemented."); } catch (Exception e) { e.Data.Add("report", remoteBook.Release.ToJson()); e.Data.Add("parsed", remoteBook.ParsedBookInfo.ToJson()); _logger.Error(e, "Couldn't evaluate decision on {0}", remoteBook.Release.Title); return(new Rejection($"{spec.GetType().Name}: {e.Message}")); } return(null); }
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()); }
public void Setup() { var author = Builder <Author> .CreateNew().With(s => s.Id = 1234).Build(); _remoteBook = new RemoteBook { ParsedBookInfo = new ParsedBookInfo { Discography = true }, Books = Builder <Book> .CreateListOfSize(3) .All() .With(e => e.ReleaseDate = DateTime.UtcNow.AddDays(-8)) .With(s => s.AuthorId = author.Id) .BuildList(), Author = author, Release = new ReleaseInfo { Title = "Author.Discography.1978.2005.FLAC-RlsGrp" } }; Mocker.GetMock <IBookService>().Setup(s => s.BooksBetweenDates(It.IsAny <DateTime>(), It.IsAny <DateTime>(), false)) .Returns(new List <Book>()); }
private RemoteBook GivenRemoteAlbum(List <Book> albums, QualityModel quality, int age = 0, long size = 0, DownloadProtocol downloadProtocol = DownloadProtocol.Usenet, int indexerPriority = 25) { var remoteBook = new RemoteBook(); remoteBook.ParsedBookInfo = new ParsedBookInfo(); remoteBook.ParsedBookInfo.Quality = quality; remoteBook.Books = new List <Book>(); remoteBook.Books.AddRange(albums); remoteBook.Release = new ReleaseInfo(); remoteBook.Release.PublishDate = DateTime.Now.AddDays(-age); remoteBook.Release.Size = size; remoteBook.Release.DownloadProtocol = downloadProtocol; remoteBook.Release.IndexerPriority = indexerPriority; remoteBook.Author = Builder <Author> .CreateNew() .With(e => e.QualityProfile = new QualityProfile { Items = Qualities.QualityFixture.GetDefaultQualities() }).Build(); remoteBook.DownloadAllowed = true; return(remoteBook); }
public void Setup() { _author = Builder <Author> .CreateNew().With(s => s.Id = 1).Build(); _book1 = Builder <Book> .CreateNew().With(s => s.ReleaseDate = DateTime.Today).Build(); _book2 = Builder <Book> .CreateNew().With(s => s.ReleaseDate = DateTime.Today).Build(); _remoteBook = new RemoteBook { Author = _author, Books = new List <Book> { _book1 }, Release = new TorrentInfo { IndexerId = 1, Title = "Author - Book [FLAC-RlsGrp]", PublishDate = DateTime.Today } }; _indexerDefinition = new IndexerDefinition { Settings = new TorrentRssIndexerSettings { EarlyReleaseLimit = 5 } }; Mocker.GetMock <IIndexerFactory>() .Setup(v => v.Get(1)) .Returns(_indexerDefinition); }
private void RemoveGrabbed(RemoteBook remoteBook) { var pendingReleases = GetPendingReleases(remoteBook.Author.Id); var bookIds = remoteBook.Books.Select(e => e.Id); var existingReports = pendingReleases.Where(r => r.RemoteBook.Books.Select(e => e.Id) .Intersect(bookIds) .Any()) .ToList(); if (existingReports.Empty()) { return; } var profile = remoteBook.Author.QualityProfile.Value; foreach (var existingReport in existingReports) { var compare = new QualityModelComparer(profile).Compare(remoteBook.ParsedBookInfo.Quality, existingReport.RemoteBook.ParsedBookInfo.Quality); //Only remove lower/equal quality pending releases //It is safer to retry these releases on the next round than remove it and try to re-add it (if its still in the feed) if (compare >= 0) { _logger.Debug("Removing previously pending release, as it was grabbed."); Delete(existingReport); } } }
public void Setup() { _artist = Builder <Author> .CreateNew().With(s => s.Id = 1).Build(); _remoteBook = new RemoteBook { Author = _artist, Release = new TorrentInfo { IndexerId = 1, Title = "Artist - Album [FLAC-RlsGrp]", Seeders = 0 } }; _indexerDefinition = new IndexerDefinition { Settings = new TorrentRssIndexerSettings { MinimumSeeders = 5 } }; Mocker.GetMock <IIndexerFactory>() .Setup(v => v.Get(1)) .Returns(_indexerDefinition); }
public virtual Decision IsSatisfiedBy(RemoteBook remoteBook, SearchCriteriaBase searchCriteria) { if (searchCriteria == null) { return(Decision.Accept()); } var singleBookSpec = searchCriteria as BookSearchCriteria; if (singleBookSpec == null) { return(Decision.Accept()); } if (Parser.Parser.CleanAuthorName(singleBookSpec.BookTitle) != Parser.Parser.CleanAuthorName(remoteBook.ParsedBookInfo.BookTitle)) { _logger.Debug("Book does not match searched book title, skipping."); return(Decision.Reject("Wrong book")); } if (!remoteBook.ParsedBookInfo.BookTitle.Any()) { _logger.Debug("Full discography result during single book search, skipping."); return(Decision.Reject("Full author pack")); } return(Decision.Accept()); }
protected override string AddFromTorrentFile(RemoteBook remoteBook, string hash, string filename, byte[] fileContent) { Proxy.AddTorrentFromFile(filename, fileContent, Settings); try { var isRecentBook = remoteBook.IsRecentBook(); if ((isRecentBook && Settings.RecentTvPriority == (int)QBittorrentPriority.First) || (!isRecentBook && Settings.OlderTvPriority == (int)QBittorrentPriority.First)) { Proxy.MoveTorrentToTopInQueue(hash.ToLower(), Settings); } } catch (Exception ex) { _logger.Warn(ex, "Failed to set the torrent priority for {0}.", filename); } SetInitialState(hash.ToLower()); if (remoteBook.SeedConfiguration != null && (remoteBook.SeedConfiguration.Ratio.HasValue || remoteBook.SeedConfiguration.SeedTime.HasValue)) { Proxy.SetTorrentSeedingConfiguration(hash.ToLower(), remoteBook.SeedConfiguration, Settings); } return(hash); }
private string DownloadFromMagnetUrl(RemoteBook remoteBook, string magnetUrl) { string hash = null; string actualHash = null; try { hash = MagnetLink.Parse(magnetUrl).InfoHash.ToHex(); } catch (FormatException ex) { _logger.Error(ex, "Failed to parse magnetlink for release '{0}': '{1}'", remoteBook.Release.Title, magnetUrl); return(null); } if (hash != null) { actualHash = AddFromMagnetLink(remoteBook, hash, magnetUrl); } if (actualHash.IsNotNullOrWhiteSpace() && hash != actualHash) { _logger.Debug( "{0} did not return the expected InfoHash for '{1}', Readarr could potentially lose track of the download in progress.", Definition.Implementation, remoteBook.Release.DownloadUrl); } return(actualHash); }
public virtual Decision IsSatisfiedBy(RemoteBook subject, SearchCriteriaBase searchCriteria) { foreach (var file in subject.Books.SelectMany(c => c.BookFiles.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}", file.Quality); if (!_upgradableSpecification.IsUpgradable(subject.Author.QualityProfile, new List <QualityModel> { file.Quality }, _preferredWordServiceCalculator.Calculate(subject.Author, file.GetSceneOrFileName()), subject.ParsedBookInfo.Quality, subject.PreferredWordScore)) { return(Decision.Reject("Existing file on disk is of equal or higher preference: {0}", file.Quality)); } } return(Decision.Accept()); }
public void Setup() { _downloadClients = new List <IDownloadClient>(); Mocker.GetMock <IProvideDownloadClient>() .Setup(v => v.GetDownloadClients()) .Returns(_downloadClients); Mocker.GetMock <IProvideDownloadClient>() .Setup(v => v.GetDownloadClient(It.IsAny <DownloadProtocol>())) .Returns <DownloadProtocol>(v => _downloadClients.FirstOrDefault(d => d.Protocol == v)); var episodes = Builder <Book> .CreateListOfSize(2) .TheFirst(1).With(s => s.Id = 12) .TheNext(1).With(s => s.Id = 99) .All().With(s => s.AuthorId = 5) .Build().ToList(); var releaseInfo = Builder <ReleaseInfo> .CreateNew() .With(v => v.DownloadProtocol = DownloadProtocol.Usenet) .With(v => v.DownloadUrl = "http://test.site/download1.ext") .Build(); _parseResult = Builder <RemoteBook> .CreateNew() .With(c => c.Author = Builder <Author> .CreateNew().Build()) .With(c => c.Release = releaseInfo) .With(c => c.Books = episodes) .Build(); }
public Decision IsSatisfiedBy(RemoteBook 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 (subject.Release.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()} (Settings->Indexers->Maximum Size)"; _logger.Debug(message); return(Decision.Reject(message)); } return(Decision.Accept()); }
public void Setup() { _monitoredAlbumSpecification = Mocker.Resolve <MonitoredBookSpecification>(); _fakeArtist = Builder <Author> .CreateNew() .With(c => c.Monitored = true) .Build(); _firstAlbum = new Book { Monitored = true }; _secondAlbum = new Book { Monitored = true }; var singleAlbumList = new List <Book> { _firstAlbum }; var doubleAlbumList = new List <Book> { _firstAlbum, _secondAlbum }; _parseResultMulti = new RemoteBook { Author = _fakeArtist, Books = doubleAlbumList }; _parseResultSingle = new RemoteBook { Author = _fakeArtist, Books = singleAlbumList }; }
public void Setup() { _pneumaticFolder = @"d:\nzb\pneumatic\".AsOsAgnostic(); _nzbPath = Path.Combine(_pneumaticFolder, _title + ".nzb").AsOsAgnostic(); _strmFolder = @"d:\unsorted tv\".AsOsAgnostic(); _remoteBook = new RemoteBook(); _remoteBook.Release = new ReleaseInfo(); _remoteBook.Release.Title = _title; _remoteBook.Release.DownloadUrl = _nzbUrl; _remoteBook.ParsedBookInfo = new ParsedBookInfo(); _downloadClientItem = Builder <DownloadClientItem> .CreateNew().With(d => d.DownloadId = "_Droned.S01E01.Pilot.1080p.WEB-DL-DRONE_0") .Build(); Subject.Definition = new DownloadClientDefinition(); Subject.Definition.Settings = new PneumaticSettings { NzbFolder = _pneumaticFolder, StrmFolder = _strmFolder }; }
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; } // 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.IsUpgradeAllowed(qualityProfile, currentQualities, 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()); }
public void Setup() { Mocker.Resolve <UpgradableSpecification>(); _firstFile = new BookFile { Quality = new QualityModel(Quality.FLAC, new Revision(version: 2)), DateAdded = DateTime.Now }; _secondFile = new BookFile { Quality = new QualityModel(Quality.FLAC, new Revision(version: 2)), DateAdded = DateTime.Now }; var singleBookList = new List <Book> { new Book { BookFiles = new List <BookFile>() } }; var doubleBookList = new List <Book> { new Book { BookFiles = new List <BookFile>() }, new Book { BookFiles = new List <BookFile>() }, new Book { BookFiles = new List <BookFile>() } }; var fakeAuthor = Builder <Author> .CreateNew() .With(c => c.QualityProfile = new QualityProfile { UpgradeAllowed = true, Cutoff = Quality.MP3_320.Id, Items = Qualities.QualityFixture.GetDefaultQualities() }) .Build(); Mocker.GetMock <IMediaFileService>() .Setup(c => c.GetFilesByBook(It.IsAny <int>())) .Returns(new List <BookFile> { _firstFile, _secondFile }); _parseResultMulti = new RemoteBook { Author = fakeAuthor, ParsedBookInfo = new ParsedBookInfo { Quality = new QualityModel(Quality.MP3_320, new Revision(version: 2)) }, Books = doubleBookList }; _parseResultSingle = new RemoteBook { Author = fakeAuthor, ParsedBookInfo = new ParsedBookInfo { Quality = new QualityModel(Quality.MP3_320, new Revision(version: 2)) }, Books = singleBookList }; }
public Decision IsSatisfiedBy(RemoteBook subject, SearchCriteriaBase searchCriteria) { var queue = _queueService.GetQueue(); var matchingBook = queue.Where(q => q.RemoteBook?.Author != null && q.RemoteBook.Author.Id == subject.Author.Id && q.RemoteBook.Books.Select(e => e.Id).Intersect(subject.Books.Select(e => e.Id)).Any()) .ToList(); foreach (var queueItem in matchingBook) { var remoteBook = queueItem.RemoteBook; var qualityProfile = subject.Author.QualityProfile.Value; // To avoid a race make sure it's not FailedPending (failed awaiting removal/search). // Failed items (already searching for a replacement) won't be part of the queue since // it's a copy, of the tracked download, not a reference. if (queueItem.TrackedDownloadState == TrackedDownloadState.DownloadFailedPending) { continue; } _logger.Debug("Checking if existing release in queue meets cutoff. Queued quality is: {0}", remoteBook.ParsedBookInfo.Quality); var queuedItemPreferredWordScore = _preferredWordServiceCalculator.Calculate(subject.Author, queueItem.Title, subject.Release?.IndexerId ?? 0); if (!_upgradableSpecification.CutoffNotMet(qualityProfile, new List <QualityModel> { remoteBook.ParsedBookInfo.Quality }, queuedItemPreferredWordScore, subject.ParsedBookInfo.Quality, subject.PreferredWordScore)) { return(Decision.Reject("Release in queue already meets cutoff: {0}", remoteBook.ParsedBookInfo.Quality)); } _logger.Debug("Checking if release is higher quality than queued release. Queued: {0}", remoteBook.ParsedBookInfo.Quality); if (!_upgradableSpecification.IsUpgradable(qualityProfile, remoteBook.ParsedBookInfo.Quality, queuedItemPreferredWordScore, subject.ParsedBookInfo.Quality, subject.PreferredWordScore)) { return(Decision.Reject("Release in queue is of equal or higher preference: {0}", remoteBook.ParsedBookInfo.Quality)); } _logger.Debug("Checking if profiles allow upgrading. Queued: {0}", remoteBook.ParsedBookInfo.Quality); if (!_upgradableSpecification.IsUpgradeAllowed(qualityProfile, remoteBook.ParsedBookInfo.Quality, subject.ParsedBookInfo.Quality)) { return(Decision.Reject("Another release is queued and the Quality profile does not allow upgrades")); } } return(Decision.Accept()); }
private int GetDelay(RemoteBook remoteBook) { var delayProfile = _delayProfileService.AllForTags(remoteBook.Author.Tags).OrderBy(d => d.Order).First(); var delay = delayProfile.GetProtocolDelay(remoteBook.Release.DownloadProtocol); var minimumAge = _configService.MinimumAge; return(new[] { delay, minimumAge }.Max()); }
public WebhookRelease(QualityModel quality, RemoteBook remoteBook) { Quality = quality.Quality.Name; QualityVersion = quality.Revision.Version; ReleaseGroup = remoteBook.ParsedBookInfo.ReleaseGroup; ReleaseTitle = remoteBook.Release.Title; Indexer = remoteBook.Release.Indexer; Size = remoteBook.Release.Size; }
public void should_unmap_tracked_download_if_album_deleted() { GivenDownloadHistory(); var remoteBook = new RemoteBook { Author = new Author() { Id = 5 }, Books = new List <Book> { new Book { Id = 4 } }, ParsedBookInfo = new ParsedBookInfo() { BookTitle = "Audio Album", AuthorName = "Audio Artist" } }; Mocker.GetMock <IParsingService>() .Setup(s => s.Map(It.Is <ParsedBookInfo>(i => i.BookTitle == "Audio Album" && i.AuthorName == "Audio Artist"), It.IsAny <int>(), It.IsAny <IEnumerable <int> >())) .Returns(remoteBook); var client = new DownloadClientDefinition() { Id = 1, Protocol = DownloadProtocol.Torrent }; var item = new DownloadClientItem() { Title = "Audio Artist - Audio Album [2018 - FLAC]", DownloadId = "35238", }; // get a tracked download in place var trackedDownload = Subject.TrackDownload(client, item); Subject.GetTrackedDownloads().Should().HaveCount(1); // simulate deletion - album no longer maps Mocker.GetMock <IParsingService>() .Setup(s => s.Map(It.Is <ParsedBookInfo>(i => i.BookTitle == "Audio Album" && i.AuthorName == "Audio Artist"), It.IsAny <int>(), It.IsAny <IEnumerable <int> >())) .Returns(default(RemoteBook)); // handle deletion event Subject.Handle(new BookDeletedEvent(remoteBook.Books.First(), false, false)); // verify download has null remote album var trackedDownloads = Subject.GetTrackedDownloads(); trackedDownloads.Should().HaveCount(1); trackedDownloads.First().RemoteBook.Should().BeNull(); }
public void Setup() { Mocker.Resolve <UpgradableSpecification>(); _upgradeHistory = Mocker.Resolve <HistorySpecification>(); var singleBookList = new List <Book> { new Book { Id = FIRST_ALBUM_ID } }; var doubleBookList = new List <Book> { new Book { Id = FIRST_ALBUM_ID }, new Book { Id = SECOND_ALBUM_ID }, new Book { Id = 3 } }; _fakeAuthor = Builder <Author> .CreateNew() .With(c => c.QualityProfile = new QualityProfile { UpgradeAllowed = true, Cutoff = Quality.MP3.Id, Items = Qualities.QualityFixture.GetDefaultQualities() }) .Build(); _parseResultMulti = new RemoteBook { Author = _fakeAuthor, ParsedBookInfo = new ParsedBookInfo { Quality = new QualityModel(Quality.MP3, new Revision(version: 2)) }, Books = doubleBookList }; _parseResultSingle = new RemoteBook { Author = _fakeAuthor, ParsedBookInfo = new ParsedBookInfo { Quality = new QualityModel(Quality.MP3, new Revision(version: 2)) }, Books = singleBookList }; _upgradableQuality = new QualityModel(Quality.MP3, new Revision(version: 1)); _notupgradableQuality = new QualityModel(Quality.MP3, new Revision(version: 2)); Mocker.GetMock <IConfigService>() .SetupGet(s => s.EnableCompletedDownloadHandling) .Returns(true); }
protected override string AddFromTorrentFile(RemoteBook remoteBook, string hash, string filename, byte[] fileContent) { var setShareLimits = remoteBook.SeedConfiguration != null && (remoteBook.SeedConfiguration.Ratio.HasValue || remoteBook.SeedConfiguration.SeedTime.HasValue); var addHasSetShareLimits = setShareLimits && ProxyApiVersion >= new Version(2, 8, 1); var isRecentBook = remoteBook.IsRecentBook(); var moveToTop = (isRecentBook && Settings.RecentTvPriority == (int)QBittorrentPriority.First) || (!isRecentBook && Settings.OlderTvPriority == (int)QBittorrentPriority.First); var forceStart = (QBittorrentState)Settings.InitialState == QBittorrentState.ForceStart; Proxy.AddTorrentFromFile(filename, fileContent, addHasSetShareLimits ? remoteBook.SeedConfiguration : null, Settings); if ((!addHasSetShareLimits && setShareLimits) || moveToTop || forceStart) { if (!WaitForTorrent(hash)) { return(hash); } if (!addHasSetShareLimits && setShareLimits) { try { Proxy.SetTorrentSeedingConfiguration(hash.ToLower(), remoteBook.SeedConfiguration, Settings); } catch (Exception ex) { _logger.Warn(ex, "Failed to set the torrent seed criteria for {0}.", hash); } } if (moveToTop) { try { Proxy.MoveTorrentToTopInQueue(hash.ToLower(), Settings); } catch (Exception ex) { _logger.Warn(ex, "Failed to set the torrent priority for {0}.", hash); } } if (forceStart) { try { Proxy.SetForceStart(hash.ToLower(), true, Settings); } catch (Exception ex) { _logger.Warn(ex, "Failed to set ForceStart for {0}.", hash); } } } return(hash); }