private MangaInfomation GetInfomationWorker(HttpClientEx hc, int retries, out HttpStatusCode statusCode) { var mangaInfo = new MangaInfomation(); var doc = new HtmlDocument(); string html; using (var res = hc.GetAsync(this.Uri).Exec()) { statusCode = res.StatusCode; if (this.WaitFromHttpStatusCode(retries, statusCode)) { return(null); } html = res.Content.ReadAsStringAsync().Exec(); if (string.IsNullOrWhiteSpace(html)) { return(null); } mangaInfo.NewUri = res.RequestMessage.RequestUri ?? this.Uri; } doc.LoadHtml(html); #region 폴더 이름은 Detail 에서 설정 { // /bbs/page.php?hid=manga_detail&manga_id=9495 var toonNav = doc.DocumentNode.SelectSingleNode("//div[contains(@class, 'toon-nav')]"); if (toonNav == null) { return(null); } string detailCode = null; foreach (HtmlNode node in toonNav.SelectNodes(".//a[@href]").ToArray()) { var href = node.GetAttributeValue("href", ""); if (string.IsNullOrWhiteSpace(href)) { continue; } var code = DaruUriParser.Detail.GetCode(new Uri(this.Uri, href)); if (string.IsNullOrWhiteSpace(code)) { continue; } detailCode = code; break; } var detailEntry = ArchiveManager.GetDetail(detailCode); if (detailEntry == null) { var detailUri = DaruUriParser.Detail.GetUri(detailCode); DetailPage.DetailInfomation detailInfo = null; var detailResult = Utility.Retry((retries2) => { using (var res = hc.GetAsync(detailUri).Exec()) { if (this.WaitFromHttpStatusCode(retries2, res.StatusCode)) { return(false); } var htmlDetail = res.Content.ReadAsStringAsync().Exec(); if (string.IsNullOrWhiteSpace(html)) { return(false); } detailInfo = DetailPage.GetDetailInfomation(hc, detailUri, htmlDetail); return(detailInfo != null); } }); if (!detailResult) { return(null); } ArchiveManager.UpdateDetail(detailCode, detailInfo.Title, detailInfo.MangaList.Select(e => e.MangaCode).ToArray()); detailEntry = ArchiveManager.GetDetail(detailCode); if (detailEntry == null) { return(null); } } this.Title = detailEntry.Title; } #endregion #region Detail.Title + xx화 { var titleNode = doc.DocumentNode.SelectSingleNode(".//div[contains(@class, 'toon-title')]"); if (titleNode == null) { return(null); } foreach (var titleNodeChild in titleNode.ChildNodes.ToArray()) { if (titleNodeChild.NodeType == HtmlNodeType.Element) { titleNodeChild.Remove(); } } var title = Utility.ReplaceHtmlTagAndRemoveTab(titleNode.InnerText ?? string.Empty); if (string.IsNullOrWhiteSpace(title)) { return(null); } if (string.IsNullOrWhiteSpace(title)) { return(null); } this.TitleWithNo = title; } #endregion #region 이미지 정보 가져오는 부분 { // /js/viewer.b.js?v=90 var chapter = int.Parse(Regex.Match(doc.DocumentNode.InnerHtml, "var *chapter *= *(\\d+)")?.Groups[1].Value ?? "0"); var catchArr = new Func <string, IEnumerable <string> >(e => { var m = Regex.Match(doc.DocumentNode.InnerHtml, $"var {e} *= *((?:[^;\\\\]|\\\\.)*)"); if (!m.Success) { return(new string[0]); } return(Regex.Matches(m.Groups[1].Value, @"""((?:[^""\\]|\\.)*)""") .Cast <Match>() .Select(le => Regex.Replace(le.Groups[1].Value, @"\\(.)", lm => lm.Groups[1].Value))); }); var cdnList = catchArr("cdn_domains") .ToArray(); var imgList = catchArr("img_list") .Select(e => new Uri(this.Uri, e + "?quick")) .ToArray(); var imgList1 = catchArr("img_list1") .Select(e => new Uri(this.Uri, e)) .ToArray(); var lst = new HashSet <Uri>(new UriIEqualityComparer()); for (var i = 0; i < imgList.Length; i++) { lst.Clear(); var addList = new Action <Uri>(uri => { var host = uri.Host; if (cdnList?.Length > 0) { if (host.Contains("cdntigermask.xyz") || host.Contains("cdnmadmax.xyz") || host.Contains("filecdn.xyz")) { lst.Add(new UriBuilder(uri) { Host = cdnList[(chapter + 4 * i) % cdnList.Length] }.Uri); for (var cdnPeek = 0; cdnPeek < CDNPeekCount; cdnPeek++) { lst.Add(new UriBuilder(uri) { Host = cdnList[Random.Next(cdnList.Length)] }.Uri); lst.Add(new UriBuilder(uri) { Host = cdnList[Random.Next(cdnList.Length)] }.Uri); lst.Add(new UriBuilder(uri) { Host = cdnList[Random.Next(cdnList.Length)] }.Uri); } } } lst.Add(imgList[i]); if (!host.Contains("google.") | !host.Contains("blogspot.")) { lst.Add(new UriBuilder(uri) { Host = "s3." + host }.Uri); lst.Add(new UriBuilder(uri) { Host = host.Replace("img.", "s3.") }.Uri); } }); if (i < imgList1.Length) { addList(imgList1[i]); } addList(imgList[i]); var imageInfo = new ImageInfomation() { Index = i + 1, ImageUri = lst.Distinct().ToArray(), }; mangaInfo.Images.Add(imageInfo); } } #endregion this.m_decryptor = new ImageDecryptor(html, mangaInfo.NewUri); return(mangaInfo); }
private MangaInfomation GetInfomationWorker(HttpClientEx hc, int retries, out HttpStatusCode statusCode) { var mangaInfo = new MangaInfomation(); var doc = new HtmlDocument(); string html; using (var req = new HttpRequestMessage(HttpMethod.Get, this.Uri)) using (var res = this.CallRequest(hc, req)) { statusCode = res.StatusCode; if (this.WaitFromHttpStatusCode(retries, statusCode)) { return(null); } html = res.Content.ReadAsStringAsync().Exec(); if (string.IsNullOrWhiteSpace(html)) { return(null); } mangaInfo.NewUri = res.RequestMessage.RequestUri ?? this.Uri; } doc.LoadHtml(html); #region 폴더 이름은 Detail 에서 설정 { // /bbs/page.php?hid=manga_detail&manga_id=9495 var toonNav = doc.DocumentNode.SelectSingleNode("//div[contains(@class, 'toon-nav')]"); if (toonNav == null) { return(null); } string detailCode = null; foreach (HtmlNode node in toonNav.SelectNodes(".//a[@href]").ToArray()) { var href = node.GetAttributeValue("href", ""); if (string.IsNullOrWhiteSpace(href)) { continue; } var code = DaruUriParser.Detail.GetCode(new Uri(this.Uri, href)); if (string.IsNullOrWhiteSpace(code)) { continue; } detailCode = code; break; } var detailEntry = ArchiveManager.GetDetail(detailCode); if (detailEntry == null) { var detailUri = DaruUriParser.Detail.GetUri(detailCode); DetailPage.DetailInfomation detailInfo = null; var detailResult = Utility.Retry((retries2) => { using (var req = new HttpRequestMessage(HttpMethod.Get, detailUri)) using (var res = this.CallRequest(hc, req)) { if (this.WaitFromHttpStatusCode(retries2, res.StatusCode)) { return(false); } var htmlDetail = res.Content.ReadAsStringAsync().Exec(); if (string.IsNullOrWhiteSpace(html)) { return(false); } detailInfo = DetailPage.GetDetailInfomation(hc, detailUri, htmlDetail); return(detailInfo != null); } }); if (!detailResult) { return(null); } ArchiveManager.UpdateDetail(detailCode, detailInfo.Title, detailInfo.MangaList.Select(e => e.MangaCode).ToArray()); detailEntry = ArchiveManager.GetDetail(detailCode); if (detailEntry == null) { return(null); } } this.Title = detailEntry.Title; } #endregion #region Detail.Title + xx화 { var titleNode = doc.DocumentNode.SelectSingleNode(".//div[contains(@class, 'toon-title')]"); if (titleNode == null) { return(null); } foreach (var titleNodeChild in titleNode.ChildNodes.ToArray()) { if (titleNodeChild.NodeType == HtmlNodeType.Element) { titleNodeChild.Remove(); } } var title = Utility.ReplaceHtmlTagAndRemoveTab(titleNode.InnerText ?? string.Empty); if (string.IsNullOrWhiteSpace(title)) { return(null); } if (string.IsNullOrWhiteSpace(title)) { return(null); } this.TitleWithNo = title; } #endregion #region 이미지 정보 가져오는 부분 { var imgList = Regex.Matches(Regex.Match(doc.DocumentNode.InnerHtml, "var img_list = [^;]+").Groups[0].Value, "\"([^\"]+)\"") .Cast <Match>() .Select(e => e.Groups[1].Value.Replace("\\", "")) .Select(e => new Uri(this.Uri, e)) .ToArray(); var imgList1 = Regex.Matches(Regex.Match(html, "var img_list1 = [^;]+").Groups[0].Value, "\"([^\"]+)\"") .Cast <Match>() .Select(e => e.Groups[1].Value.Replace("\\", "")) .Select(e => new Uri(this.Uri, e)) .ToArray(); for (var i = 0; i < imgList.Length; i++) { var imageInfo = new ImageInfomation() { Index = i + 1, }; if (i < imgList1.Length) { imageInfo.ImageUri = new Uri[] { new Uri(imgList[i].ToString().Replace("//img.", "//s3.")), imgList[i], imgList1[i], }.Distinct().ToArray(); } else { imageInfo.ImageUri = new Uri[] { new Uri(imgList[i].ToString().Replace("//img.", "//s3.")), imgList[i], }.Distinct().ToArray(); } mangaInfo.Images.Add(imageInfo); } } #endregion this.m_decryptor = new ImageDecryptor(html, mangaInfo.NewUri); return(mangaInfo); }