public override (List <NetTask>, ExtractedInfo) Extract(string url, IExtractorOption option = null) { var match = ValidUrl.Match(url).Groups; if (option == null) { option = RecommendOption(url); } if (option.Type == ExtractorType.Images) { var id = match["id"].Value; // Handle Redirect var string3 = NetTools.DownloadString(url); RETRY_DOWNLOAD1: if (string.IsNullOrEmpty(string3)) { return(null, null); } if (string3.ToHtmlNode().SelectSingleNode("//title").InnerText == "Redirect") { id = string3.ToHtmlNode().SelectSingleNode("//a").GetAttributeValue("href", "").Split('/', '-').Last().Split('.')[0]; string3 = NetTools.DownloadString(string3.ToHtmlNode().SelectSingleNode("//a").GetAttributeValue("href", "")); goto RETRY_DOWNLOAD1; } var sinfo = new ExtractedInfo.WorksComic(); var imgs_url = $"https://ltn.hitomi.la/galleries/{id}.js"; option.PageReadCallback?.Invoke($"https://ltn.hitomi.la/galleryblock/{id}.html"); option.PageReadCallback?.Invoke(url); option.PageReadCallback?.Invoke(imgs_url); var urls = new List <string> { $"https://ltn.hitomi.la/galleryblock/{id}.html", imgs_url }; var strings = NetTools.DownloadStrings(urls); if (string.IsNullOrEmpty(strings[0]) || string.IsNullOrEmpty(strings[1])) { return(null, null); } var data1 = ParseGalleryBlock(strings[0]); var imgs = strings[1]; var string2 = NetTools.DownloadString($"https://hitomi.la{data1.Magic}"); if (string.IsNullOrEmpty(string2)) { return(null, null); } var data2 = ParseGallery(string2); option.SimpleInfoCallback?.Invoke($"[{id}] {data1.Title}"); // download.js var number_of_frontends = 3; var subdomain = Convert.ToChar(97 + (Convert.ToInt32(id.Last()) % number_of_frontends)); if (id.Last() == '0') { subdomain = 'a'; } var arr = JToken.Parse(imgs.Substring(imgs.IndexOf('=') + 1))["files"]; var img_urls = new List <string>(); foreach (var obj in (JArray)arr) { var hash = obj.Value <string>("hash"); if (obj.Value <int>("haswebp") == 0 || hash == null) { //img_urls.Add($"https://{subdomain}a.hitomi.la/galleries/{id}/{obj.Value<string>("name")}"); var postfix = hash.Substring(hash.Length - 3); img_urls.Add($"https://{subdomain}a.hitomi.la/images/{postfix[2]}/{postfix[0]}{postfix[1]}/{hash}.{obj.Value<string>("name").Split('.').Last()}"); } else if (hash == "") { img_urls.Add($"https://{subdomain}a.hitomi.la/webp/{obj.Value<string>("name")}.webp"); } else if (hash.Length < 3) { img_urls.Add($"https://{subdomain}a.hitomi.la/webp/{hash}.webp"); } else { var postfix = hash.Substring(hash.Length - 3); img_urls.Add($"https://{subdomain}a.hitomi.la/webp/{postfix[2]}/{postfix[0]}{postfix[1]}/{hash}.webp"); } } var result = new List <NetTask>(); var ordering = 1; foreach (var img in img_urls) { var filename = Path.GetFileNameWithoutExtension(img.Split('/').Last()); if (!(option as HitomiExtractorOption).RealFilename) { filename = ordering++.ToString("000"); } var task = NetTask.MakeDefault(img); task.SaveFile = true; task.Filename = img.Split('/').Last(); task.Format = new ExtractorFileNameFormat { Title = data1.Title, Id = id, Language = data1.Language, UploadDate = data1.Posted, FilenameWithoutExtension = filename, Extension = Path.GetExtension(img.Split('/').Last()).Replace(".", "") }; if (data1.artist != null) { task.Format.Artist = data1.artist[0]; } else { task.Format.Artist = "NA"; } if (data1.parody != null) { task.Format.Series = data1.parody[0]; } else { task.Format.Series = "NA"; } if (data2.group != null) { task.Format.Group = data2.group[0]; } else { task.Format.Group = "NA"; } if (data2.character != null) { task.Format.Character = data2.character[0]; } else { task.Format.Character = "NA"; } if (task.Format.Artist == "NA" && task.Format.Group != "NA") { task.Format.Artist = task.Format.Group; } result.Add(task); } option.ThumbnailCallback?.Invoke(result[0]); sinfo.Thumbnail = result[0]; sinfo.URL = url; sinfo.Title = data1.Title; sinfo.Author = data1.artist?.ToArray(); sinfo.AuthorGroup = data2.group?.ToArray(); sinfo.ShortInfo = $"[{id}] {data1.Title}"; sinfo.Tags = data1.Tags?.ToArray(); sinfo.Characters = data2.character?.ToArray(); sinfo.Language = data1.Language; sinfo.Parodies = data1.parody?.ToArray(); result.ForEach(task => task.Format.Extractor = GetType().Name.Replace("Extractor", "")); return(result, new ExtractedInfo { Info = sinfo, Type = ExtractedInfo.ExtractedType.WorksComic }); } return(null, null); }
public override (List <NetTask>, ExtractedInfo) Extract(string url, IExtractorOption option = null) { var match = ValidUrl.Match(url).Groups; if (option == null) { option = RecommendOption(url); } if (option.Type == ExtractorType.Images) { var sinfo = new ExtractedInfo.WorksComic(); var imgs_url = $"https://ltn.hitomi.la/galleries/{match["id"].Value}.js"; option.PageReadCallback?.Invoke($"https://ltn.hitomi.la/galleryblock/{match["id"]}.html"); option.PageReadCallback?.Invoke(url); option.PageReadCallback?.Invoke(imgs_url); var urls = new List <string> { $"https://ltn.hitomi.la/galleryblock/{match["id"]}.html", url, imgs_url }; var strings = NetTools.DownloadStrings(urls); if (string.IsNullOrEmpty(strings[0]) || string.IsNullOrEmpty(strings[1]) || string.IsNullOrEmpty(strings[2])) { return(null, null); } var data1 = ParseGalleryBlock(strings[0]); var data2 = ParseGallery(strings[1]); var imgs = strings[2]; option.SimpleInfoCallback?.Invoke($"[{data1.Magic}] {data1.Title}"); // download.js var number_of_frontends = 3; var subdomain = Convert.ToChar(97 + (Convert.ToInt32(match["id"].Value.Last()) % number_of_frontends)); if (match["id"].Value.Last() == '0') { subdomain = 'a'; } var arr = JArray.Parse(imgs.Substring(imgs.IndexOf('['))); var img_urls = new List <string>(); foreach (var obj in arr) { if (obj.Value <int>("haswebp") == 0) { img_urls.Add($"https://{subdomain}a.hitomi.la/galleries/{match["id"].Value}/{obj.Value<string>("name")}"); } else { img_urls.Add($"https://{subdomain}a.hitomi.la/webp/{match["id"].Value}/{obj.Value<string>("name")}.webp"); } } var result = new List <NetTask>(); foreach (var img in img_urls) { var task = NetTask.MakeDefault(img); task.SaveFile = true; task.Filename = img.Split('/').Last(); task.Format = new ExtractorFileNameFormat { Title = data1.Title, Id = data1.Magic, Language = data1.Language, UploadDate = data1.Posted, FilenameWithoutExtension = Path.GetFileNameWithoutExtension(img.Split('/').Last()), Extension = Path.GetExtension(img.Split('/').Last()).Replace(".", "") }; if (data1.artist != null) { task.Format.Artist = data1.artist[0]; } else { task.Format.Artist = "N/A"; } if (data1.parody != null) { task.Format.Series = data1.parody[0]; } else { task.Format.Series = "N/A"; } if (data2.group != null) { task.Format.Group = data2.group[0]; } else { task.Format.Group = "N/A"; } if (data2.character != null) { task.Format.Character = data2.character[0]; } else { task.Format.Character = "N/A"; } if (task.Format.Artist == "N/A" && task.Format.Group != "N/A") { task.Format.Artist = task.Format.Group; } result.Add(task); } option.ThumbnailCallback?.Invoke(result[0]); sinfo.Thumbnail = result[0]; sinfo.URL = url; sinfo.Title = data1.Title; sinfo.Author = data1.artist?.ToArray(); sinfo.AuthorGroup = data2.group?.ToArray(); sinfo.ShortInfo = $"[{data1.Magic}] {data1.Title}"; sinfo.Tags = data1.Tags?.ToArray(); sinfo.Characters = data2.character?.ToArray(); sinfo.Language = data1.Language; sinfo.Parodies = data1.parody?.ToArray(); result.ForEach(task => task.Format.Extractor = GetType().Name.Replace("Extractor", "")); return(result, new ExtractedInfo { Info = sinfo, Type = ExtractedInfo.ExtractedType.WorksComic }); } return(null, null); }