public ChapterObject ParseChapterObject(string content) { HtmlDocument ChapterObjectDocument = new HtmlDocument(); ChapterObjectDocument.LoadHtml(content); ChapterObject ParsedChapterObject = new ChapterObject(); HtmlNodeCollection PageNodes = ChapterObjectDocument.GetElementbyId("page_select").SelectNodes(".//option"); if (PageNodes != null && PageNodes.Count > 0) { foreach (HtmlNode PageNode in PageNodes) { HtmlNode PrevNode = PageNode.SelectSingleNode(".//preceding-sibling::option"), NextNode = PageNode.SelectSingleNode(".//following-sibling::option"); UInt32 PageNumber = UInt32.Parse(PageNode.NextSibling.InnerText.Substring(5)); String PageUrl = PageNode.Attributes["value"].Value, NextPageUrl = (NextNode != null) ? NextNode.Attributes["value"].Value : null, PrevPageUrl = (PrevNode != null) ? PrevNode.Attributes["value"].Value : null; if (!PageUrl.Contains("?")) { PageUrl += "?supress_webtoon=t"; } else if (PageUrl.Contains("?")) { PageUrl += "&supress_webtoon=t"; } if (NextPageUrl == null) { } else if (!NextPageUrl.Contains("?")) { NextPageUrl += "?supress_webtoon=t"; } else if (NextPageUrl.Contains("?")) { NextPageUrl += "&supress_webtoon=t"; } if (PrevPageUrl == null) { } else if (!PrevPageUrl.Contains("?")) { PrevPageUrl += "?supress_webtoon=t"; } else if (PrevPageUrl.Contains("?")) { PrevPageUrl += "&supress_webtoon=t"; } ParsedChapterObject.Pages.Add(new PageObject() { PageNumber = PageNumber, Url = PageUrl, NextUrl = NextPageUrl, PrevUrl = PrevPageUrl }); } } return ParsedChapterObject; }
private void OpenChapter(MangaObject MangaObject, ChapterObject ChapterObject) { this.MangaObject = MangaObject; this.ChapterObject = ChapterObject; String base_path = Path.Combine(App.CHAPTER_ARCHIVE_DIRECTORY, MangaObject.MangaFileName()); this.ArchiveFilePath = Path.Combine(base_path, ChapterObject.ChapterArchiveName(App.CHAPTER_ARCHIVE_EXTENSION)); ChapterObjectPreloadDictionary.Clear(); try { ChapterObject PrevChapter = this.MangaObject.PrevChapterObject(this.ChapterObject); ChapterObjectPreloadDictionary.Add(this.PrevArchiveFilePath = Path.Combine(base_path, PrevChapter.ChapterArchiveName(App.CHAPTER_ARCHIVE_EXTENSION)), PrevChapter); } catch { this.PrevArchiveFilePath = null; } try { ChapterObject NextChapter = this.MangaObject.NextChapterObject(this.ChapterObject); ChapterObjectPreloadDictionary.Add(this.NextArchiveFilePath = Path.Combine(base_path, NextChapter.ChapterArchiveName(App.CHAPTER_ARCHIVE_EXTENSION)), NextChapter); } catch { this.NextArchiveFilePath = null; } LoadChapterObject(); LoadBookmarkObject(); this.ContinueReading = false; ChapterGarbageCollector(); this.PullFocus(); // TODO: Fix bug when loading still loading manga... // VerifyArchiveFile.VerifyArchive(App.ZipStorage, this.ArchiveFilePath); }
public MangaObject ParseMangaObject(string content) { HtmlDocument MangaObjectDocument = new HtmlDocument(); MangaObjectDocument.LoadHtml(content); HtmlNode InformationNode = MangaObjectDocument.DocumentNode.SelectSingleNode("//div[contains(@class,'ipsBox')]/div"); String MangaCover = InformationNode.SelectSingleNode(".//div[1]/img").Attributes["src"].Value; HtmlNode MangaProperties = InformationNode.SelectSingleNode(".//table[contains(@class,'ipb_table')]"), ChapterListing = MangaObjectDocument.DocumentNode.SelectSingleNode("//table[contains(@class,'chapters_list')]"); String MangaName = HtmlEntity.DeEntitize(MangaObjectDocument.DocumentNode.SelectSingleNode("//h1[contains(@class,'ipsType_pagetitle')]").InnerText.Trim()), MangaTypeProp = HtmlEntity.DeEntitize(MangaProperties.SelectSingleNode(".//tr[5]/td[2]").InnerText), Desciption = HtmlEntity.DeEntitize(MangaProperties.SelectSingleNode(".//tr[7]/td[2]").InnerText.Replace("<br>", "\n")); MangaObjectType MangaType = MangaObjectType.Unknown; FlowDirection PageFlowDirection = FlowDirection.RightToLeft; switch (MangaTypeProp.ToLower()) { default: MangaType = MangaObjectType.Unknown; PageFlowDirection = FlowDirection.RightToLeft; break; case "manga (japanese)": MangaType = MangaObjectType.Manga; PageFlowDirection = FlowDirection.RightToLeft; break; case "manhwa (korean)": MangaType = MangaObjectType.Manhwa; PageFlowDirection = FlowDirection.LeftToRight; break; case "manhua (chinese)": MangaType = MangaObjectType.Manhua; PageFlowDirection = FlowDirection.LeftToRight; break; } HtmlNodeCollection AlternateNameNodes = MangaProperties.SelectSingleNode(".//tr[1]/td[2]").SelectNodes(".//span"), GenreNodes = MangaProperties.SelectSingleNode(".//tr[4]/td[2]").SelectNodes(".//a/span"); String[] AlternateNames = { }, Authors = { HtmlEntity.DeEntitize(MangaProperties.SelectSingleNode(".//tr[2]/td[2]/a").InnerText) }, Artists = { HtmlEntity.DeEntitize(MangaProperties.SelectSingleNode(".//tr[3]/td[2]/a").InnerText) }, Genres = { }; if (AlternateNameNodes != null && AlternateNameNodes.Count > 0) AlternateNames = (from HtmlNode AltNameNode in AlternateNameNodes select HtmlEntity.DeEntitize(AltNameNode.InnerText.Trim())).ToArray(); if (GenreNodes != null && GenreNodes.Count > 0) Genres = (from HtmlNode GenreNode in GenreNodes select HtmlEntity.DeEntitize(GenreNode.InnerText.Trim())).ToArray(); List<ChapterObject> Chapters = new List<ChapterObject>(); HtmlNodeCollection ChapterNodes = ChapterListing.SelectNodes(String.Format(".//tr[contains(@class,'lang_{0} chapter_row')]", SiteExtensionDescriptionAttribute.Language)); if (ChapterNodes != null && ChapterNodes.Count > 0) { foreach (HtmlNode ChapterNode in ChapterNodes) { HtmlNode VolChapNameNode = ChapterNode.SelectSingleNode("td[1]/a"); Match VolChapMatch = Regex.Match(VolChapNameNode.InnerText, @"(Vol\.(?<Volume>\d+)\s)?(Ch\.(?<Chapter>\d+))(\.(?<SubChapter>\d+))?"); String ChapterName = VolChapNameNode.InnerText.Substring(VolChapMatch.Length + 2).Trim(), ReleaseData = ReleaseData = ChapterNode.SelectSingleNode("td[5]").InnerText; ChapterObject PrevChapter = Chapters.LastOrDefault(); UInt32 Volume = 0, Chapter = 0, SubChapter = 0; if (VolChapMatch.Groups["Volume"].Success) UInt32.TryParse(VolChapMatch.Groups["Volume"].Value, out Volume); if (VolChapMatch.Groups["Chapter"].Success) UInt32.TryParse(VolChapMatch.Groups["Chapter"].Value, out Chapter); if (VolChapMatch.Groups["SubChapter"].Success) UInt32.TryParse(VolChapMatch.Groups["SubChapter"].Value, out SubChapter); DateTime Released = DateTime.MinValue; if (ReleaseData.Contains("-")) ReleaseData = ReleaseData.Split(new String[] { " - " }, StringSplitOptions.RemoveEmptyEntries)[0]; DateTime.TryParse(ReleaseData, out Released); String ChapterUrl = VolChapNameNode.Attributes["href"].Value; if (!ChapterUrl.Contains("?")) { ChapterUrl += "?supress_webtoon=t"; } else if (ChapterUrl.Contains("?")) { ChapterUrl += "&supress_webtoon=t"; } ChapterObject chapterObject = new ChapterObject() { Name = HtmlEntity.DeEntitize(ChapterName), Volume = Volume, Chapter = Chapter, SubChapter = SubChapter, Released = Released, Locations = { new LocationObject() { ExtensionName = SiteExtensionDescriptionAttribute.Name, Url = ChapterUrl } } }; if (!Chapters.Any(o => o.Chapter == chapterObject.Chapter && ((Int32)o.SubChapter - chapterObject.SubChapter).InRange(-4, 4))) Chapters.Add(chapterObject); else Chapters.Find(o => o.Chapter == chapterObject.Chapter && ((Int32)o.SubChapter - chapterObject.SubChapter).InRange(-4, 4)).Merge(chapterObject); } } Chapters.Reverse(); Double Rating = -1; try { HtmlNode RatingNode = MangaObjectDocument.DocumentNode.SelectSingleNode("//div[contains(@class,'rating')]"); String RatingText = new String(RatingNode.InnerText.Trim().Substring(1, 4).Where(IsValidRatingChar).ToArray()); Double.TryParse(RatingText, out Rating); } catch { } return new MangaObject() { Name = MangaName, MangaType = MangaType, PageFlowDirection = PageFlowDirection, Description = HtmlEntity.DeEntitize(Desciption), AlternateNames = AlternateNames.ToList(), Covers = new List<String>(new String[] { MangaCover }), Authors = Authors.ToList(), Artists = Artists.ToList(), Genres = Genres.ToList(), Released = (Chapters.FirstOrDefault() ?? new ChapterObject()).Released, Chapters = Chapters, Rating = Rating }; }
public MangaObject ParseMangaObject(string content) { if (content.ToLower().Contains("has been licensed, it is not available in MangaHere.".ToLower())) return null; HtmlDocument MangaObjectDocument = new HtmlDocument(); MangaObjectDocument.LoadHtml(content); HtmlNode TitleNode = MangaObjectDocument.DocumentNode.SelectSingleNode("//h1[contains(@class,'title')]"), MangaDetailsNode = MangaObjectDocument.DocumentNode.SelectSingleNode("//div[contains(@class,'manga_detail')]"), MangaPropertiesNode = MangaDetailsNode.SelectSingleNode(".//div[1]"), MangaDesciptionNode = MangaObjectDocument.GetElementbyId("show"), AuthorsNode = MangaPropertiesNode.SelectSingleNode(".//ul/li[5]"), ArtistsNode = MangaPropertiesNode.SelectSingleNode(".//ul/li[6]"), GenresNode = MangaPropertiesNode.SelectSingleNode(".//ul/li[4]"); HtmlNodeCollection AuthorsNodeCollection = AuthorsNode.SelectNodes(".//a"), ArtistsNodeCollection = ArtistsNode.SelectNodes(".//a"); String Desciption = MangaDesciptionNode != null ? MangaDesciptionNode.FirstChild.InnerText : String.Empty, MangaName = HtmlEntity.DeEntitize(System.Threading.Thread.CurrentThread.CurrentCulture.TextInfo.ToTitleCase(TitleNode.LastChild.InnerText.ToLower())); String[] AlternateNames = MangaPropertiesNode.SelectSingleNode(".//ul/li[3]").LastChild.InnerText.Split(new String[] { "; " }, StringSplitOptions.RemoveEmptyEntries), Authors = { }, Artists = { }, Genres = MangaPropertiesNode.SelectSingleNode(".//ul/li[4]").LastChild.InnerText.Split(new String[] { ", " }, StringSplitOptions.RemoveEmptyEntries); if (AuthorsNodeCollection != null) Authors = (from HtmlNode AuthorNode in AuthorsNodeCollection select AuthorNode.InnerText).ToArray(); if (ArtistsNodeCollection != null) Artists = (from HtmlNode ArtistNode in ArtistsNodeCollection select ArtistNode.InnerText).ToArray(); List<ChapterObject> Chapters = new List<ChapterObject>(); HtmlNodeCollection RawChapterList = MangaDetailsNode.SelectNodes(".//div[contains(@class,'detail_list')]/ul[1]/li"); foreach (HtmlNode ChapterNode in RawChapterList) { String volNode = ChapterNode.SelectSingleNode(".//span[1]/span").InnerText; String[] volChapSub = { (volNode != null && volNode.Length > 0) ? volNode.Substring(4).Trim() : "0" }; String ChapterTitle = ChapterNode.SelectSingleNode(".//span[1]/a").InnerText.Trim(); String ChapterNumber = ChapterTitle.Substring(ChapterTitle.LastIndexOf(' ') + 1).Trim(); volChapSub = volChapSub.Concat(ChapterNumber.Split(new char[] { '.' }, StringSplitOptions.RemoveEmptyEntries)).ToArray(); ChapterObject Chapter = new ChapterObject() { Name = ChapterTitle, Volume = UInt32.Parse(volChapSub[0]), Chapter = UInt32.Parse(volChapSub[1]), Locations = { new LocationObject() { ExtensionName = SiteExtensionDescriptionAttribute.Name, Url = ChapterNode.SelectSingleNode(".//span[1]/a").Attributes["href"].Value } }, Released = ChapterNode.SelectSingleNode(".//span[2]").InnerText.ToLower().Equals("today") ? DateTime.Today : (ChapterNode.SelectSingleNode(".//span[2]").InnerText.ToLower().Equals("yesterday") ? DateTime.Today.AddDays(-1) : DateTime.Parse(ChapterNode.SelectSingleNode(".//span[2]").InnerText)) }; if (volChapSub.Length == 3) Chapter.SubChapter = UInt32.Parse(volChapSub[2]); Chapters.Add(Chapter); } Chapters.Reverse(); String Cover = MangaPropertiesNode.SelectSingleNode(".//img[1]/@src").Attributes["src"].Value; Cover = Cover.Substring(0, Cover.LastIndexOf('?')); MangaObject MangaObj = new MangaObject() { Name = MangaName, Description = HtmlEntity.DeEntitize(Desciption), AlternateNames = AlternateNames.ToList(), Covers = { Cover }, Authors = Authors.ToList(), Artists = Artists.ToList(), Genres = Genres.ToList(), Released = Chapters.First().Released, Chapters = Chapters }; MangaObj.AlternateNames.RemoveAll(an => an.ToLower().Equals("none")); MangaObj.Genres.RemoveAll(g => g.ToLower().Equals("none")); return MangaObj; }
static ChapterObject LoadChapterObject(ChapterObject chapterObject, Int32 LocationId = 0) { ChapterObject ChapterObj = null; ISiteExtension ise = SiteExtentions[chapterObject.Locations[LocationId].ExtensionName]; ISiteExtensionDescriptionAttribute isea = ise.GetType().GetCustomAttribute<ISiteExtensionDescriptionAttribute>(false); HttpWebRequest request = WebRequest.Create(chapterObject.Locations[LocationId].Url) as HttpWebRequest; request.Referer = isea.RefererHeader ?? request.Host; request.AutomaticDecompression = DecompressionMethods.Deflate | DecompressionMethods.GZip; using (HttpWebResponse response = request.GetResponse() as HttpWebResponse) { using (StreamReader streamReader = new StreamReader(response.GetResponseStream())) { ChapterObj = ise.ParseChapterObject(streamReader.ReadToEnd()); } } return ChapterObj; }
public static Int32 IndexOfChapterObject(this MangaObject value, ChapterObject chapter_object) { return value.Chapters.FindIndex(c => c.Volume == chapter_object.Volume && c.Chapter == chapter_object.Chapter && c.SubChapter == chapter_object.SubChapter); }
public static ChapterObject PrevChapterObject(this MangaObject value, ChapterObject chapter_object) { Int32 index = value.IndexOfChapterObject(chapter_object) - 1; if (index < 0) return null; return value.Chapters[index]; }
public static ChapterObject NextChapterObject(this MangaObject value, ChapterObject chapter_object) { Int32 index = value.IndexOfChapterObject(chapter_object) + 1; if (index >= value.Chapters.Count) return null; return value.Chapters[index]; }
public MangaObject ParseMangaObject(String content) { Int32 MangaInformationContentStart = content.IndexOf("<!-- Intro Series -->"), MangaInformationContentEnd = content.IndexOf("<!-- **END: Intro Series -->", MangaInformationContentStart); String MangaInformationContent = content.Substring(MangaInformationContentStart, MangaInformationContentEnd - MangaInformationContentStart); Int32 MangaChaptersContentStart = content.IndexOf("<!-- Main Content -->"), MangaChaptersContentEnd = content.IndexOf("<!-- **END: Main Content -->", MangaChaptersContentStart); String MangaChaptersContent = content.Substring(MangaChaptersContentStart, MangaChaptersContentEnd - MangaChaptersContentStart); HtmlDocument MangaObjectDocument = new HtmlDocument(); MangaObjectDocument.LoadHtml(MangaInformationContent); HtmlNode MangaObjectNode = MangaObjectDocument.DocumentNode.SelectSingleNode(".//div/div"); String MangaName = String.Empty, Description = String.Empty; List<String> AlternateNames = new List<String>(), AuthorsArtists = new List<String>(), Genres = new List<String>(); foreach (HtmlNode DetailNode in MangaObjectNode.SelectNodes(".//div[2]/div[contains(@class,'row')]")) { HtmlNode DetailTypeNode = DetailNode.SelectSingleNode(".//div[1]/b[1] | .//div[1]/strong[1]"), DetailTextNode = (DetailTypeNode != null) ? DetailTypeNode.NextSibling : null, DetailDescriptionNode = (DetailTextNode != null) ? DetailTextNode.NextSibling : null, MangaNameNode = DetailNode.SelectSingleNode(".//div[1]/h1"); HtmlNodeCollection DetailLinkNodes = DetailNode.SelectNodes(".//div[1]/a"); String DetailType = (DetailTypeNode != null) ? DetailTypeNode.InnerText.Trim().TrimEnd(':') : "MangaName", DetailValue = String.Empty; String[] DetailValues = { }; if (DetailLinkNodes != null) { DetailValues = (from HtmlNode LinkNode in DetailLinkNodes select LinkNode.InnerText).ToArray(); } else if (MangaNameNode != null) { DetailValue = HtmlEntity.DeEntitize(MangaNameNode.InnerText.Trim()); } else if (DetailDescriptionNode != null) { DetailValue = HtmlEntity.DeEntitize(DetailDescriptionNode.InnerText.Trim()); } else if (DetailTextNode != null) { DetailValue = HtmlEntity.DeEntitize(DetailTextNode.InnerText.Trim()); } switch (DetailType) { default: break; case "MangaName": MangaName = DetailValue; break; case "Alternate Names": AlternateNames = (from String AltName in DetailValue.Split(',') select AltName.Trim()).ToList(); break; case "Author": AuthorsArtists = DetailValues.ToList(); break; case "Genre": Genres = DetailValues.ToList(); break; case "Description": Description = DetailValue; break; } } String Cover = SiteExtensionDescriptionAttribute.RootUrl + MangaObjectNode.SelectSingleNode(".//div[1]/img/@src").Attributes["src"].Value; List<ChapterObject> Chapters = new List<ChapterObject>(); MangaObjectDocument.LoadHtml(MangaChaptersContent); HtmlNodeCollection RawChapterList = MangaObjectDocument.DocumentNode.SelectNodes(".//div[contains(@class,'row')]"); foreach (HtmlNode RawChapterNode in RawChapterList.Skip(1)) { HtmlNode ChapterNumberNode = RawChapterNode.SelectSingleNode(".//div[1]/a"), ReleaseDate = RawChapterNode.SelectSingleNode(".//div[2]/time"); String ChapterNumber = Regex.Match(ChapterNumberNode.InnerText, @"\d+(\.\d+)?").Value; String[] ChapterSub = ChapterNumber.Trim().Split('.'); ChapterObject Chapter = new ChapterObject() { Name = HtmlEntity.DeEntitize(RawChapterNode.SelectSingleNode(".//div[1]/gray").InnerText), Chapter = UInt32.Parse(ChapterSub[0]), Locations = { new LocationObject(){ ExtensionName = SiteExtensionDescriptionAttribute.Name, Url = SiteExtensionDescriptionAttribute.RootUrl + ChapterNumberNode.Attributes["href"].Value }, }, Released = ReleaseDate.InnerText.ToLower().StartsWith("today") ? DateTime.Today : ReleaseDate.InnerText.ToLower().StartsWith("yesterday") ? DateTime.Today.AddDays(-1) : DateTime.Parse(ReleaseDate.InnerText.ToLower()) }; if (ChapterSub.Length == 2) Chapter.SubChapter = UInt32.Parse(ChapterSub[1]); Chapters.Add(Chapter); } Chapters.Reverse(); MangaObject MangaObj = new MangaObject() { Name = MangaName, Description = Description, AlternateNames = AlternateNames.ToList(), Covers = { Cover }, Authors = AuthorsArtists.ToList(), Artists = AuthorsArtists.ToList(), Genres = Genres.ToList(), Released = Chapters.First().Released, Chapters = Chapters }; MangaObj.AlternateNames.RemoveAll(an => an.ToLower().Equals("none")); MangaObj.Genres.RemoveAll(g => g.ToLower().Equals("none")); return MangaObj; }
public ReadChapterRequestObject(MangaObject MangaObject, ChapterObject ChapterObject) { this.MangaObject = MangaObject; this.ChapterObject = ChapterObject; }