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; } }
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>"); } }
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."); } }
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); }
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)); }