diff --git a/EhTagClient/Client.cs b/EhTagClient/Client.cs index 2fd5576d..394c4f22 100644 --- a/EhTagClient/Client.cs +++ b/EhTagClient/Client.cs @@ -23,9 +23,9 @@ static Client() private const string LAST_UPDATE = "EhTagClient.LastUpdate"; - private static readonly Regex reg = new Regex(@"([^<]+)", RegexOptions.Singleline | RegexOptions.Compiled); + private static readonly Regex _Reg = new Regex(@"([^<]+)", RegexOptions.Singleline | RegexOptions.Compiled); - private static readonly string DbUri = "https://repo.e-hentai.org/tools.php?act=taggroup&show={0}"; + private static readonly string DbUri = "https://repo.e-hentai.org/tools/taggroup?show={0}"; public static DateTimeOffset LastUpdate { @@ -86,7 +86,7 @@ await Task.Run(async () => private static async Task updateDbAsync(TagDb db, string html, CancellationToken token) { - var matches = reg.Matches(html); + var matches = _Reg.Matches(html); var toAdd = new List(matches.Count); foreach (var item in matches.Cast()) { diff --git a/ExClient/Api/ImageData.cs b/ExClient/Api/ImageData.cs index ae2eaa3c..b9ba83c8 100644 --- a/ExClient/Api/ImageData.cs +++ b/ExClient/Api/ImageData.cs @@ -34,7 +34,6 @@ protected override void CheckResponseOverride(ApiRequest request) throw new ArgumentException("Key mismatch"); } -#pragma warning disable IDE0051 // 删除未使用的私有成员 #pragma warning disable IDE1006 // 命名样式 [JsonProperty] internal int p { get; set; } [JsonProperty] internal string s { get; set; } @@ -44,11 +43,9 @@ protected override void CheckResponseOverride(ApiRequest request) [JsonProperty] internal string i3 { get; set; } [JsonProperty] internal string i5 { get; set; } [JsonProperty] internal string i6 { get; set; } - [JsonProperty] internal string i7 { get; set; } [JsonProperty] internal int si { get; set; } [JsonProperty] internal string x { get; set; } [JsonProperty] internal string y { get; set; } -#pragma warning restore IDE0051 // 删除未使用的私有成员 #pragma warning restore IDE1006 // 命名样式 } } diff --git a/ExClient/Galleries/Commenting/Comment.cs b/ExClient/Galleries/Commenting/Comment.cs index 045029c4..fc7668bc 100644 --- a/ExClient/Galleries/Commenting/Comment.cs +++ b/ExClient/Galleries/Commenting/Comment.cs @@ -105,22 +105,36 @@ private Comment(CommentCollection owner, int id, HtmlNode commentNode) private static readonly HttpClient _TransClient = new HttpClient(); + private static async Task _TranslateAsync(string source, string targetLangCode, CancellationToken token) + { + if (Uri.TryCreate(source, UriKind.Absolute, out var urlContent) && (urlContent.Scheme == "http" || urlContent.Scheme == "https")) + { + // Do not translate url + return source; + } + var uri = $"https://clients5.google.com/translate_a/t?client=dict-chrome-ex" + + $"&sl=auto&tl={Uri.EscapeDataString(targetLangCode)}&q={Uri.EscapeDataString(source)}"; + var transTask = _TransClient.GetStringAsync(new(uri)); + var transRetHtml = await transTask.AsTask(token); + var obj = JsonConvert.DeserializeObject[]>(transRetHtml); + var first = obj[0]; + first.RemoveAt(first.Count - 1); + return string.Concat(first); + } + public IAsyncOperation TranslateAsync(string targetLangCode) { return AsyncInfo.Run(async token => { var node = HtmlNode.CreateNode(Content.OuterHtml); - foreach (var item in node.Descendants("#text")) + var textNodes = node.Descendants("#text").ToList(); + var tasks = textNodes.Select(async node => { - var data = item.GetInnerText(); - var uri = $"https://translate.google.cn/translate_a/single?client=gtx&dt=t&ie=UTF-8&oe=UTF-8" - + $"&sl=auto&tl={targetLangCode}&q={Uri.EscapeDataString(data)}"; - var transRetHtml = await _TransClient.GetStringAsync(new Uri(uri)); - var obj = JsonConvert.DeserializeObject(transRetHtml); - var objarr = (JArray)obj[0]; - var translated = string.Concat(objarr.Select(a => a[0].ToString())); - item.InnerHtml = HtmlEntity.Entitize(translated); - } + var data = node.GetInnerText(); + var translated = await _TranslateAsync(data, targetLangCode, token); + node.InnerHtml = HtmlEntity.Entitize(translated); + }); + await Task.WhenAll(tasks); TranslatedContent = node; return node; }); diff --git a/ExClient/Galleries/Gallery.cs b/ExClient/Galleries/Gallery.cs index da28d66e..d6a5c476 100644 --- a/ExClient/Galleries/Gallery.cs +++ b/ExClient/Galleries/Gallery.cs @@ -456,19 +456,18 @@ async Task getDoc(int imageIndex, CancellationToken cancellationTo return doc; } - var rows = doc.GetElementbyId("gdo2").Elements("div", "ths").Last().GetInnerText(); - rows = rows.Substring(0, rows.IndexOf(' ')); - var rowCount = int.Parse(rows); - PageSize = rowCount * 5; - if (doc.GetElementbyId("gdo4").Elements("div", "ths").Last().InnerText != "Large") + var content = doc.GetElementbyId("gdt"); + if(content.Element("div", "gdts") is not null) { // 切换到大图模式 await Client.Current.HttpClient.GetAsync(new Uri("/?inline_set=ts_l", UriKind.Relative)); - doc = await getDoc(imageIndex, cancellationToken, true); + return await getDoc(imageIndex, cancellationToken, true); } - else if (pageIndex != imageIndex / _PageSize) + var items = content.Elements("div", "gdtl").ToList(); + PageSize = items.Count; + if (pageIndex != imageIndex / _PageSize) { - doc = await getDoc(imageIndex, cancellationToken, true); + return await getDoc(imageIndex, cancellationToken, true); } return doc; } diff --git a/ExClient/Galleries/GalleryImage.cs b/ExClient/Galleries/GalleryImage.cs index d1565e53..5e698792 100644 --- a/ExClient/Galleries/GalleryImage.cs +++ b/ExClient/Galleries/GalleryImage.cs @@ -80,9 +80,7 @@ async Task loadFromApi() doc.LoadHtml(res.i3); analyzeI3Node(doc.DocumentNode); doc.LoadHtml(res.i6); - analyzeI6Node(doc.DocumentNode); - doc.LoadHtml(res.i7); - analyzeI7Node(doc.DocumentNode); + analyzeI6Node(doc.DocumentNode); } catch (ArgumentException) { @@ -98,8 +96,7 @@ async Task loadFromHtml() var doc = await Client.Current.HttpClient.GetDocumentAsync(loadPageUri).AsTask(token); analyzeI3Node(doc.GetElementbyId("i3")); - analyzeI6Node(doc.GetElementbyId("i6")); - analyzeI7Node(doc.GetElementbyId("i7")); + analyzeI6Node(doc.GetElementbyId("i6")); Owner.ShowKey = doc.DocumentNode.Descendants("script").Select(n => { var match = _ShowKeyMatcher.Match(n.GetInnerText()); @@ -124,13 +121,13 @@ void analyzeI3Node(HtmlNode i3) } void analyzeI6Node(HtmlNode i6) { - var hashNode = i6.Element("a"); - ImageHash = SHA1Value.Parse(_HashMatcher.Match(hashNode.GetAttribute("href", "")).Groups[1].Value); - } - void analyzeI7Node(HtmlNode i7) - { - var origNode = i7.Element("a"); - originalImageUri = origNode?.GetAttribute("href", default(Uri)); + var links = i6.Descendants("a").Select(a => a.GetAttribute("href", "")).ToList(); + + var hashLink = links.First(l => l.Contains("f_shash=")); + ImageHash = SHA1Value.Parse(_HashMatcher.Match(hashLink).Groups[1].Value); + + var originalLink = links.FirstOrDefault(l => l.Contains("fullimg")); + originalImageUri = originalLink.IsNullOrEmpty() ? null : new Uri(originalLink); } } diff --git a/ExClient/Services/TorrentInfo.cs b/ExClient/Services/TorrentInfo.cs index 8e66dd2f..70938051 100644 --- a/ExClient/Services/TorrentInfo.cs +++ b/ExClient/Services/TorrentInfo.cs @@ -27,7 +27,7 @@ public static IAsyncOperation> FetchTorrnetsAsyn public readonly struct TorrentInfo : IEquatable { - private static readonly Regex _InfoMatcher = new Regex(@"\s+Posted:\s([-\d:\s]+)\s+Size:\s([\d\.]+\s+[KMG]?B)\s+Seeds:\s(\d+)\s+Peers:\s(\d+)\s+Downloads:\s(\d+)\s+Uploader:\s+(.+)\s+", RegexOptions.Compiled); + private static readonly Regex _InfoMatcher = new Regex(@"\s+Posted:\s([-\d:\s]+)\s+Size:\s([\d\.]+\s+[KMG]?i?B)\s+Seeds:\s(\d+)\s+Peers:\s(\d+)\s+Downloads:\s(\d+)\s+Uploader:\s+(.+)\s+", RegexOptions.Compiled); private static readonly Regex _UrlMatcher = new Regex(@"document\.location='([^']+?)'", RegexOptions.Compiled); internal static IAsyncOperation> FetchAsync(GalleryInfo galleryInfo) @@ -73,19 +73,14 @@ long parseSize(string sizeStr) { var s = sizeStr.Split(' '); var value = double.Parse(s[0]); - switch (s[1]) + return s[1] switch { - case "B": - return (long)value; - case "KB": - return (long)(value * (1 << 10)); - case "MB": - return (long)(value * (1 << 20)); - case "GB": - return (long)(value * (1 << 30)); - default: - return 0; - } + "B" => (long)value, + "KB" or "KiB" => (long)(value * (1 << 10)), + "MB" or "MiB" => (long)(value * (1 << 20)), + "GB" or "GiB" => (long)(value * (1 << 30)), + _ => 0, + }; } }).AsAsyncOperation(); } diff --git a/ExClient/Status/TaggingRecord.cs b/ExClient/Status/TaggingRecord.cs index a97260ef..40633073 100644 --- a/ExClient/Status/TaggingRecord.cs +++ b/ExClient/Status/TaggingRecord.cs @@ -4,21 +4,20 @@ using HtmlAgilityPack; using System; +using System.Collections.Generic; using System.Linq; namespace ExClient.Status { public readonly struct TaggingRecord : IEquatable { - internal TaggingRecord(HtmlNode trNode) + internal TaggingRecord(GalleryInfo gallery, List tdNodes) { - var td = trNode.Elements("td").ToList(); - Tag = Tag.Parse(td[1].GetInnerText()); - Score = int.Parse(td[2].GetInnerText()); - var uri = td[3].Element("a").GetAttribute("href", default(Uri)); - GalleryInfo = GalleryInfo.Parse(uri); - Timestamp = DateTimeOffset.Parse(td[4].GetInnerText(), null, System.Globalization.DateTimeStyles.AssumeUniversal); - } + GalleryInfo = gallery; + Timestamp = DateTimeOffset.Parse(tdNodes[0].GetInnerText(), null, System.Globalization.DateTimeStyles.AssumeUniversal); + Score = int.Parse(tdNodes[1].GetInnerText()); + Tag = Tag.Parse(tdNodes[2].GetInnerText()); + } public Tag Tag { get; } diff --git a/ExClient/Status/TaggingStatistics.cs b/ExClient/Status/TaggingStatistics.cs index 74588fc6..7ba1e78e 100644 --- a/ExClient/Status/TaggingStatistics.cs +++ b/ExClient/Status/TaggingStatistics.cs @@ -1,9 +1,12 @@ -using HtmlAgilityPack; +using ExClient.Api; + +using HtmlAgilityPack; using Opportunity.MvvmUniverse; using Opportunity.MvvmUniverse.Collections; using System; +using System.Collections.Generic; using System.Linq; using System.Runtime.InteropServices.WindowsRuntime; using System.Text.RegularExpressions; @@ -34,10 +37,9 @@ public IAsyncAction RefreshAsync() var uid = Client.Current.UserId; if (uid < 0) throw new InvalidOperationException("Hasn't log in"); - var getPage = Client.Current.HttpClient.GetDocumentAsync(new Uri($"https://e-hentai.org/tools.php?act=taglist&uid={uid}")); + var getPage = Client.Current.HttpClient.GetDocumentAsync(new Uri($"https://repo.e-hentai.org/tools.php?act=taglist&uid={uid}")); token.Register(getPage.Cancel); var page = await getPage; - var body = page.DocumentNode.Element("html").Element("body"); var tagstats = page.GetElementbyId("tagstats")?.Elements("tr")?.ToArray(); if (tagstats != null && tagstats.Length == 3) @@ -56,9 +58,25 @@ public IAsyncAction RefreshAsync() } } - var table = body.Element("table"); - if (table != null) - records.Update(table.Elements("tr").Skip(1).Select(item => new TaggingRecord(item)).ToList()); + var usertaglist = page.GetElementbyId("usertaglist"); + if (usertaglist != null) + { + var list = new List(); + var gallary = default(GalleryInfo); + foreach (var row in usertaglist.Elements("tr")) + { + var cells = row.Elements("td").ToList(); + if (cells.Count == 1) + { + gallary = GalleryInfo.Parse(cells[0].Descendants("a").Last().GetAttribute("href", default(Uri))); + } + else + { + list.Add(new TaggingRecord(gallary, cells)); + } + } + records.Update(list); + } else if (tagstats != null) records.Clear(); OnPropertyChanged(default(string)); diff --git a/ExClient/Status/UserStatus.cs b/ExClient/Status/UserStatus.cs index 2a98050b..1ab75bd1 100644 --- a/ExClient/Status/UserStatus.cs +++ b/ExClient/Status/UserStatus.cs @@ -132,7 +132,7 @@ public IAsyncAction ResetImageUsageAsync() { return AsyncInfo.Run(async token => { - var p = Client.Current.HttpClient.PostAsync(infoUri, new KeyValuePair("act", "limits")); + var p = Client.Current.HttpClient.PostAsync(infoUri, new KeyValuePair("reset_imagelimit", "reset_imagelimit")); token.Register(p.Cancel); var r = await p; var html = await r.Content.ReadAsStringAsync(); diff --git a/ExClient/Tagging/Namespace.cs b/ExClient/Tagging/Namespace.cs index c84fdb40..f77df579 100644 --- a/ExClient/Tagging/Namespace.cs +++ b/ExClient/Tagging/Namespace.cs @@ -70,6 +70,10 @@ private static readonly Dictionary parsingDic ["X"] = Namespace.Mixed, ["Mixed"] = Namespace.Mixed, + + ["T"] = Namespace.Temp, + ["Temp"] = Namespace.Temp, + ["Temporary"] = Namespace.Temp, }; private static readonly Dictionary _SearchDic diff --git a/ExClient/Tagging/TagCollection.cs b/ExClient/Tagging/TagCollection.cs index ea014c3a..9ee3b81a 100644 --- a/ExClient/Tagging/TagCollection.cs +++ b/ExClient/Tagging/TagCollection.cs @@ -56,8 +56,7 @@ private void _InitOrReset(IEnumerable<(Tag tag, TagState ts)> items) { var rawData = items.OrderBy(t => t.tag.Namespace) // put low-power tags to the end - .ThenByDescending(t => t.ts & TagState.NormalPower) - .ThenBy(t => t.tag.Content) + .ThenByDescending(t => t.ts.GetPowerState()) .ToList(); var data = new Tag[rawData.Count]; var state = new TagState[rawData.Count]; diff --git a/ExClient/Tagging/TagState.cs b/ExClient/Tagging/TagState.cs index 25b56316..9f5b13d7 100644 --- a/ExClient/Tagging/TagState.cs +++ b/ExClient/Tagging/TagState.cs @@ -29,7 +29,7 @@ public enum TagState /// /// Mod-power >= 100. /// - HighPower = 0b0111_0000_0000 + HighPower = 0b0111_0000_0000, } public static class TagStateExtension