private async Task SyncChapter(WdcInteractiveStory story, WdcInteractiveChapter chapter)
        {
            var ct = _ctSource.Token;

            ct.ThrowIfCancellationRequested();

            _log.Debug($"Syncing story '{story.ID}' chapter '{chapter.Path}'");

            // Update the story status
            // TODO

            // If the last synced value is minimum (always update) or chapter refreshing is enabled and this chapter needs a refresh
            if (
                chapter.LastSynced == DateTime.MinValue ||
                (GetSettings().UpdateKnownChapters&& chapter.LastSynced <= DateTime.Now + new TimeSpan(0, 0, GetSettings().SyncChapterIntervalSeconds, 0))
                )
            {
                var remoteChapter = await _wdcReader.GetInteractiveChaper(story.ID, chapter.Path, _wdcClient, ct);

                ct.ThrowIfCancellationRequested();

                // Bring over changes
                chapter.Author            = remoteChapter.Author;
                chapter.Choices           = remoteChapter.Choices;
                chapter.Content           = remoteChapter.Content;
                chapter.IsEnd             = remoteChapter.IsEnd;
                chapter.SourceChoiceTitle = remoteChapter.SourceChoiceTitle;
                chapter.Title             = remoteChapter.Title;

                chapter.LastSynced = DateTime.Now;
            }
        }
Ejemplo n.º 2
0
        public async Task WdcReaderInteractiveChapterFirstPageLoggedIn()
        {
            // Expected results
            var expectedChapter = new WdcInteractiveChapter();

            expectedChapter.Path              = "1";
            expectedChapter.Title             = "The Great War";
            expectedChapter.SourceChoiceTitle = string.Empty;
            expectedChapter.Content           = TestUtil.GetDataFile("expected_set_13_06_2019.WdcReaderInteractiveChapter1_Content.txt");
            expectedChapter.IsEnd             = false;
            expectedChapter.Author            = new WdcAuthor()
            {
                Name     = "The Nameless Hermit",
                Username = "******",
            };
            expectedChapter.Choices.Add(new WdcInteractiveChapterChoice()
            {
                PathLink = "11", Name = "Be Jace"
            });
            expectedChapter.Choices.Add(new WdcInteractiveChapterChoice()
            {
                PathLink = "12", Name = "Be Rhea"
            });
            expectedChapter.Choices.Add(new WdcInteractiveChapterChoice()
            {
                PathLink = "13", Name = "Be Marek"
            });
            expectedChapter.Choices.Add(new WdcInteractiveChapterChoice()
            {
                PathLink = "14", Name = "Be Tara"
            });

            WdcResponse payload = new WdcResponse();

            payload.WebResponse = TestUtil.GetDataFile("sample_set_13_06_2019.Looking for adventure - chapter 1 - logged in.html");
            payload.Address     = "https://www.writing.com/main/interact/item_id/209084-Looking-for-adventure/map/1";

            WdcInteractiveChapter testChapter = _reader.GetInteractiveChaper("TEST", expectedChapter.Path, payload);



            // Tests
            //Assert.AreEqual(expectedChapterTitle, chapterResult.Title);
            //Assert.AreEqual(expectedChapterSourceTitle, chapterResult.SourceChoiceTitle);
            //Assert.AreEqual(expectedChapterContent, chapterResult.Content);
            //Assert.AreEqual(expectedIsEnd, chapterResult.IsEnd);
            //Assert.AreEqual(expectedAuthorName, chapterResult.Author.Name);
            //Assert.AreEqual(expectedAuthorUsername, chapterResult.Author.Username);
            //for (var i=0; i < chapterResult.Choices.Count; i++)
            //{
            //    Assert.AreEqual(expectedChoices[i].Name, chapterResult.Choices[i].Name, "Chapter choice name doesn't match");
            //    Assert.AreEqual(expectedChoices[i].PathLink, chapterResult.Choices[i].PathLink, "Chapter choice path doesn't match");
            //}
            CompareInteractiveChapters(expectedChapter, testChapter);
        }
 private string GetPreviousChapterLink(WdcInteractiveStory story, WdcInteractiveChapter chapter)
 {
     if (chapter.Path.Length > 1)
     {
         // E.g. 15524
         var previousChapterPath = _chapterPathFilename[chapter.Path.Substring(0, chapter.Path.Length - 1)];
         return($"This choice: <b>{chapter.SourceChoiceTitle}</b> <a href='{previousChapterPath}'>Go back</a>");
     }
     else
     {
         // E.g. 1
         return($"<a href='{STORY_HOMEPAGE_FILENAME}'>Go back</a>");
     }
 }
Ejemplo n.º 4
0
        private void CompareInteractiveChapters(WdcInteractiveChapter expectedChapter, WdcInteractiveChapter testChapter)
        {
            Assert.AreEqual(expectedChapter.Path, testChapter.Path);
            Assert.AreEqual(expectedChapter.Content, testChapter.Content);
            Assert.AreEqual(expectedChapter.IsEnd, testChapter.IsEnd);
            Assert.AreEqual(expectedChapter.SourceChoiceTitle, testChapter.SourceChoiceTitle);
            Assert.AreEqual(expectedChapter.Title, testChapter.Title);
            Assert.AreEqual(expectedChapter.Author.Name, testChapter.Author.Name);
            Assert.AreEqual(expectedChapter.Author.Username, testChapter.Author.Username);

            Assert.AreEqual(expectedChapter.Choices.Count, testChapter.Choices.Count, "Chapters do not have the same number of choices.");

            for (var i = 0; i < expectedChapter.Choices.Count; i++)
            {
                Assert.AreEqual(expectedChapter.Choices[i].Name, testChapter.Choices[i].Name, "Chapter choice name doesn't match.");
                Assert.AreEqual(expectedChapter.Choices[i].PathLink, testChapter.Choices[i].PathLink, "Chapter choice path doesn't match.");
            }
        }
Ejemplo n.º 5
0
        public async Task WdcReaderInteractiveChapterFirstPageLoggedOut()
        {
            // Expected results
            var expectedChapter = new WdcInteractiveChapter();

            expectedChapter.Path              = "1";
            expectedChapter.Title             = "The Great War";
            expectedChapter.SourceChoiceTitle = string.Empty;
            expectedChapter.Content           = TestUtil.GetDataFile("expected_set_13_06_2019.WdcReaderInteractiveChapter1_Content.txt");
            expectedChapter.IsEnd             = false;
            expectedChapter.Author            = new WdcAuthor()
            {
                Name     = "The Nameless Hermit",
                Username = "******",
            };
            expectedChapter.Choices.Add(new WdcInteractiveChapterChoice()
            {
                PathLink = "11", Name = "Be Jace"
            });
            expectedChapter.Choices.Add(new WdcInteractiveChapterChoice()
            {
                PathLink = "12", Name = "Be Rhea"
            });
            expectedChapter.Choices.Add(new WdcInteractiveChapterChoice()
            {
                PathLink = "13", Name = "Be Marek"
            });
            expectedChapter.Choices.Add(new WdcInteractiveChapterChoice()
            {
                PathLink = "14", Name = "Be Tara"
            });

            // Set things up
            WdcResponse payload = new WdcResponse();

            payload.WebResponse = TestUtil.GetDataFile("sample_set_13_06_2019.Looking for adventure - chapter 1 - logged out.html");
            payload.Address     = "https://www.writing.com/main/interact/item_id/209084-Looking-for-adventure/map/1";

            WdcInteractiveChapter testChapter = _reader.GetInteractiveChaper("TEST", expectedChapter.Path, payload);

            // Compare
            CompareInteractiveChapters(expectedChapter, testChapter);
        }
        // Check the list of chapters in WDC. If there are some that we haven't seen before, add placeholder chapters to the story.
        private async Task SyncStoryChapterList(WdcInteractiveStory story)
        {
            var ct = _ctSource.Token;

            ct.ThrowIfCancellationRequested();

            _log.Debug($"Syncing chapter outline for story '{story.ID}'");

            this.SetCurrentStatus(StorySyncWorkerState.WorkingOutline, $"Updating story chapter list: {story.ID}");

            var remoteChapterList = await _wdcReader.GetInteractiveChapterList(story.ID, _wdcClient, ct);

            ct.ThrowIfCancellationRequested();

            foreach (var uri in remoteChapterList)
            {
                var chapterPath = WdcUtil.GetFinalParmFromUrl(uri.ToString()); // Just want the final digits

                // Do we already have that chapter?
                if (!story.Chapters.Exists(c => c.Path == chapterPath))
                {
                    ct.ThrowIfCancellationRequested();

                    _log.InfoFormat("Creating placeholder for new chapter: {0}", chapterPath);

                    var newChapter = new WdcInteractiveChapter()
                    {
                        Path       = chapterPath,
                        LastSynced = DateTime.MinValue,
                        FirstSeen  = DateTime.Now
                    };

                    story.Chapters.Add(newChapter);
                }
            }

            ct.ThrowIfCancellationRequested();

            // Save changes
            story.LastUpdatedChapterOutline = DateTime.Now;
            _storyContainer.UpdateStory(story);
        }
        private string GetChapterChoices(WdcInteractiveStory story, WdcInteractiveChapter chapter)
        {
            if (chapter.IsEnd || chapter.Choices.Count < 1)
            {
                // Is end
                return(GetTemplate("ChapterChoiceEnd.html"));
            }
            else
            {
                // There are choices
                var sbChapterChoices = new StringBuilder();
                foreach (var choice in chapter.Choices)
                {
                    // Does this choice lead to a valid chapter?
                    bool isChoiceValid = story.Chapters.SingleOrDefault(c => c.Path == choice.PathLink) != null;

                    var choiceHtml = String.Empty;

                    // Choice links to a chapter that exists, choice is valid

                    if (isChoiceValid && _chapterPathFilename != null)
                    {
                        choiceHtml = GetTemplate("ChapterChoiceItemValid.html")
                                     .Replace("{ChoicePath}", choice.PathLink)
                                     .Replace("{ChoiceLink}", _chapterPathFilename[choice.PathLink])
                                     .Replace("{ChoiceName}", choice.Name);
                    }
                    else
                    {
                        // Is either an invalid choice, or the path / filename lookup is missing (could be for a once-off chapter export)
                        choiceHtml = GetTemplate("ChapterChoiceItemInvalid.html")
                                     .Replace("{ChoiceName}", choice.Name);
                    }

                    sbChapterChoices.AppendLine(choiceHtml);
                }

                return(GetTemplate("ChapterChoiceList.html")
                       .Replace("{ChoiceList}", sbChapterChoices.ToString()));
            }
        }
        public void ExportStoryChapter(WdcInteractiveStory story, WdcInteractiveChapter chapter, string filename)
        {
            _log.DebugFormat("Exporting chapter: {0}", chapter.Path);

            var chapterIsReady = IsChapterReady(chapter);
            var htmlContent    = GetTemplate("Chapter.html")
                                 .Replace("{AuthorName}", chapter.Author.Name)
                                 .Replace("{ChapterPath}", chapter.Path)
                                 .Replace("{ChapterPathDisplay}", GetPrettyChapterPath(chapter.Path))
                                 .Replace("{SourceChapterChunk}", GetPreviousChapterLink(story, chapter))
                                 .Replace("{ChapterChoices}", GetChapterChoices(story, chapter))
                                 .Replace("{ChapterContent}", chapter.Content)
                                 .Replace("{ChapterTitle", chapter.Title)
                                 .Replace("{HomeLink}", GetHomepageFileName());

            var html = GetPageTemplate($"{story.Name} - {chapter.Title}", chapter.Title, htmlContent);

            // TODO: Fix the "Go back" link


            File.WriteAllText(Path.Combine(_outputDir, filename), html);
        }
Ejemplo n.º 9
0
        public WdcInteractiveChapter GetInteractiveChaper(string interactiveID, string chapterPath, WdcResponse payload)
        {
            if (!WdcUtil.IsValidChapterPath(chapterPath))
            {
                throw new ArgumentException($"Chapter '{chapterPath}' is not a valid chapter path", nameof(chapterPath));
            }

            var chapter = new WdcInteractiveChapter();

            chapter.Path    = chapterPath;
            chapter.Title   = GetInteractiveChapterTitle(payload);
            chapter.Content = GetInteractiveChapterContent(payload);
            if (chapterPath != "1")
            {
                chapter.SourceChoiceTitle = GetInteractiveChapterSourceChoice(payload);                     // Only get the source choice if it's not the first chapter
            }
            else
            {
                chapter.SourceChoiceTitle = "";
            }
            chapter.LastUpdated = DateTime.Now;
            // TODO chapter author
            chapter.Author = GetInteractiveChapterAuthor(payload);

            var choices = GetInteractiveChapterChoices(payload);

            if (choices == null)
            {
                chapter.IsEnd = true;
            }
            else
            {
                chapter.Choices.AddRange(choices);
            }

            return(chapter);
        }
 public bool CheckIfChapterNeedsSync(WdcInteractiveChapter chapter)
 {
     return(chapter.LastSynced == DateTime.MinValue ||
            (GetSettings().UpdateKnownChapters&& DateTime.Now >= chapter.LastSynced + new TimeSpan(0, 0, GetSettings().SyncChapterIntervalSeconds, 0)));
 }
 private bool IsChapterReady(WdcInteractiveChapter chapter)
 {
     return(chapter.LastSynced != DateTime.MinValue);
 }
 public string GetChapterFileName(WdcInteractiveChapter chapter)
 {
     return(string.Format(STORY_CHAPTER_FILENAME, chapter.Path));
 }