Esempio n. 1
0
        /// <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);
        }
Esempio n. 2
0
        /// <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);
        }
Esempio n. 3
0
        /// <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);
        }