/// <summary> /// Acquire a list of page loading tasks for the pages that are intended /// to be tallied. /// </summary> /// <param name="quest">The quest for which the tally is being run.</param> /// <param name="adapter">The forum adapter that handles the quest's thread.</param> /// <param name="threadRangeInfo">The range of posts that are wanted in the tally.</param> /// <param name="token">A cancellation token.</param> /// <returns>Returns a list of page loading tasks.</returns> private async Task <List <Task <HtmlDocument?> > > LoadQuestPagesAsync( IQuest quest, IForumAdapter2 adapter, ThreadRangeInfo threadRangeInfo, IPageProvider pageProvider, CancellationToken token) { int firstPageNumber = threadRangeInfo.GetStartPage(quest); // Get the first page in order to find out how many pages are in the thread // Keep it as a task. Task <HtmlDocument?> firstPage = GetFirstPage(firstPageNumber, quest, adapter, pageProvider, token); // Get the last page number. int lastPageNumber = await GetLastPageNumber(quest, adapter, threadRangeInfo, firstPage).ConfigureAwait(false); // Initiate tasks for any remaining pages IEnumerable <Task <HtmlDocument?> > remainingPages = GetRemainingPages(firstPageNumber, lastPageNumber, quest, adapter, pageProvider, token); // Collect all the page load tasks (including the finished first page) to return to caller. List <Task <HtmlDocument?> > pagesToLoad = new List <Task <HtmlDocument?> >() { firstPage }; pagesToLoad.AddRange(remainingPages); return(pagesToLoad); }
/// <summary> /// Determines the page number range that will be loaded for the quest. /// Returns a tuple of first page number, last page number, and pages to scan. /// </summary> /// <param name="quest">The quest being tallied.</param> /// <param name="adapter">The forum adapter for the quest.</param> /// <param name="threadRangeInfo">The thread range info, as provided by the adapter.</param> /// <param name="token">The cancellation token.</param> /// <returns>Returns a tuple of the page number info that was determined.</returns> private async Task <Tuple <int, int, int> > GetPagesToScanAsync( IQuest quest, IForumAdapter adapter, ThreadRangeInfo threadRangeInfo, CancellationToken token) { IPageProvider pageProvider = ViewModels.ViewModelService.MainViewModel.PageProvider; int firstPageNumber = threadRangeInfo.GetStartPage(quest); int lastPageNumber = 0; int pagesToScan = 0; if (threadRangeInfo.Pages > 0) { // If the startInfo obtained the thread pages info, just use that. lastPageNumber = threadRangeInfo.Pages; } else if (quest.ReadToEndOfThread || threadRangeInfo.IsThreadmarkSearchResult) { // If we're reading to the end of the thread (end post 0, or based on a threadmark), // then we need to load the first page to find out how many pages there are in the thread. // Make sure to bypass the cache, since it may have changed since the last load. string firstPageUrl = adapter.GetUrlForPage(firstPageNumber, quest.PostsPerPage); HtmlDocument page = await pageProvider.GetPage(firstPageUrl, $"Page {firstPageNumber}", CachingMode.BypassCache, ShouldCache.Yes, SuppressNotifications.No, token) .ConfigureAwait(false); if (page == null) { throw new InvalidOperationException($"Unable to load web page: {firstPageUrl}"); } lastPageNumber = adapter.GetThreadInfo(page).Pages; } else { // If we're not reading to the end of the thread, just calculate // what the last page number will be. Pages to scan will be the // difference in pages +1. lastPageNumber = quest.GetPageNumberOf(quest.EndPost); } pagesToScan = lastPageNumber - firstPageNumber + 1; Tuple <int, int, int> result = new Tuple <int, int, int>(firstPageNumber, lastPageNumber, pagesToScan); return(result); }
/// <summary> /// Gets all posts from the provided pages list. /// </summary> /// <param name="loadingPages">The pages that are being loaded for the tally.</param> /// <param name="quest">The quest being tallied.</param> /// <param name="adapter">The forum adapter that handles the quest's thread.</param> /// <returns>Returns all posts extracted from all pages provided, /// and the thread title.</returns> private async Task <(ThreadInfo threadInfo, List <Post> posts)> GetPostsFromPagesAsync( List <Task <HtmlDocument?> > loadingPages, IQuest quest, IForumAdapter2 adapter, ThreadRangeInfo threadRangeInfo) { ThreadInfo? threadInfo = null; List <Post> postsList = new List <Post>(); int pageNumber = threadRangeInfo.GetStartPage(quest) - 1; bool incomplete = false; foreach (var loadingPage in loadingPages) { var page = await loadingPage.ConfigureAwait(false); pageNumber++; if (page == null) { incomplete = true; continue; } if (threadInfo == null) { threadInfo = adapter.GetThreadInfo(page); } postsList.AddRange(adapter.GetPosts(page, quest, pageNumber)); } if (incomplete) { InvalidOperationException e = new InvalidOperationException("Unable to load all pages."); e.Data["Application"] = true; throw e; } if (threadInfo == null) { threadInfo = new ThreadInfo("Unknown", "Unknown", 0); } return(threadInfo, postsList); }