From 2ee5c39854c7ef5741a7198062c759954a48a90e Mon Sep 17 00:00:00 2001 From: Bogdan Date: Tue, 31 Dec 2024 16:24:42 +0200 Subject: [PATCH] animebytes: parse response with STJson --- .../Indexers/Definitions/AnimeBytes.cs | 228 +++++++++++------- 1 file changed, 145 insertions(+), 83 deletions(-) diff --git a/src/Jackett.Common/Indexers/Definitions/AnimeBytes.cs b/src/Jackett.Common/Indexers/Definitions/AnimeBytes.cs index 49553b76e..895009896 100644 --- a/src/Jackett.Common/Indexers/Definitions/AnimeBytes.cs +++ b/src/Jackett.Common/Indexers/Definitions/AnimeBytes.cs @@ -6,11 +6,13 @@ using System.Globalization; using System.IO; using System.Linq; using System.Net; +using System.Text.Json.Serialization; using System.Text.RegularExpressions; using System.Threading.Tasks; using Jackett.Common.Extensions; using Jackett.Common.Models; using Jackett.Common.Models.IndexerConfig.Bespoke; +using Jackett.Common.Serializer; using Jackett.Common.Services.Interfaces; using Jackett.Common.Utils; using Newtonsoft.Json.Linq; @@ -262,28 +264,28 @@ namespace Jackett.Common.Indexers.Definitions try { - var json = JToken.Parse(response.ContentString); + var jsonResponse = STJson.Deserialize(response.ContentString); - if (json.Value("error") != null) + if (jsonResponse.Error.IsNotNullOrWhiteSpace()) { - throw new Exception(json.Value("error")); + throw new Exception($"Unexpected response from indexer request: {jsonResponse.Error}"); } - if (json.Value("Matches") == 0) + if (jsonResponse.Matches == 0) { return releases; } - foreach (var group in json.Value("Groups")) + foreach (var group in jsonResponse.Groups) { - var categoryName = group.Value("CategoryName"); - var description = group.Value("Description"); - var year = group.Value("Year"); - var posterStr = group.Value("Image"); + var categoryName = group.CategoryName; + var description = group.Description; + var year = group.Year; + var posterStr = group.Image; var poster = posterStr.IsNotNullOrWhiteSpace() ? new Uri(posterStr) : null; - var groupName = group.Value("GroupName"); - var seriesName = group.Value("SeriesName"); - var mainTitle = WebUtility.HtmlDecode(group.Value("FullName")); + var groupName = group.GroupName; + var seriesName = group.SeriesName; + var mainTitle = WebUtility.HtmlDecode(group.FullName); if (seriesName.IsNotNullOrWhiteSpace()) { @@ -295,95 +297,51 @@ namespace Jackett.Common.Indexers.Definitions mainTitle }; - if (group.Value("SynonymnsV2").HasValues && group.Value("SynonymnsV2") is JObject) + if (group.Synonymns != null && group.Synonymns.Any()) { - var allSynonyms = group.Value("SynonymnsV2").ToObject>(); - - if (AddJapaneseTitle && allSynonyms.TryGetValue("Japanese", out var japaneseTitle) && japaneseTitle.IsNotNullOrWhiteSpace()) + if (AddJapaneseTitle && group.Synonymns.TryGetValue("Japanese", out var japaneseTitle) && japaneseTitle.IsNotNullOrWhiteSpace()) { synonyms.Add(japaneseTitle.Trim()); } - if (AddRomajiTitle && allSynonyms.TryGetValue("Romaji", out var romajiTitle) && romajiTitle.IsNotNullOrWhiteSpace()) + if (AddRomajiTitle && group.Synonymns.TryGetValue("Romaji", out var romajiTitle) && romajiTitle.IsNotNullOrWhiteSpace()) { synonyms.Add(romajiTitle.Trim()); } - if (AddAlternativeTitles && allSynonyms.TryGetValue("Alternative", out var alternativeTitles) && alternativeTitles.IsNotNullOrWhiteSpace()) + if (AddAlternativeTitles && group.Synonymns.TryGetValue("Alternative", out var alternativeTitles) && alternativeTitles.IsNotNullOrWhiteSpace()) { synonyms.UnionWith(alternativeTitles.Split(',').Select(x => x.Trim()).Where(x => x.IsNotNullOrWhiteSpace())); } } - else if (group.Value("Synonymns").HasValues) - { - if (group.Value("Synonymns") is JArray) - { - var allSyonyms = group.Value("Synonymns").ToObject>(); - - if (AddJapaneseTitle && allSyonyms.Count >= 1 && allSyonyms[0].IsNotNullOrWhiteSpace()) - { - synonyms.Add(allSyonyms[0]); - } - - if (AddRomajiTitle && allSyonyms.Count >= 2 && allSyonyms[1].IsNotNullOrWhiteSpace()) - { - synonyms.Add(allSyonyms[1]); - } - - if (AddAlternativeTitles && allSyonyms.Count >= 3 && allSyonyms[2].IsNotNullOrWhiteSpace()) - { - synonyms.UnionWith(allSyonyms[2].Split(',').Select(x => x.Trim()).Where(x => x.IsNotNullOrWhiteSpace())); - } - } - else if (group.Value("Synonymns") is JObject) - { - var allSynonyms = group.Value("Synonymns").ToObject>(); - - if (AddJapaneseTitle && allSynonyms.TryGetValue(0, out var japaneseTitle) && japaneseTitle.IsNotNullOrWhiteSpace()) - { - synonyms.Add(japaneseTitle.Trim()); - } - - if (AddRomajiTitle && allSynonyms.TryGetValue(1, out var romajiTitle) && romajiTitle.IsNotNullOrWhiteSpace()) - { - synonyms.Add(romajiTitle.Trim()); - } - - if (AddAlternativeTitles && allSynonyms.TryGetValue(2, out var alternativeTitles) && alternativeTitles.IsNotNullOrWhiteSpace()) - { - synonyms.UnionWith(alternativeTitles.Split(',').Select(x => x.Trim()).Where(x => x.IsNotNullOrWhiteSpace())); - } - } - } List category = null; - foreach (var torrent in group.Value("Torrents")) + foreach (var torrent in group.Torrents) { // Skip non-freeleech results when freeleech only is set - if (ConfigData.FreeleechOnly.Value && torrent.Value("RawDownMultiplier") != 0) + if (ConfigData.FreeleechOnly.Value && torrent.RawDownMultiplier != 0) { continue; } - var torrentId = torrent.Value("ID"); - var link = torrent.Value("Link"); - var linkUri = new Uri(link); - var publishDate = DateTime.ParseExact(torrent.Value("UploadTime"), "yyyy-MM-dd HH:mm:ss", CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal); + var torrentId = torrent.Id; + var link = torrent.Link; + var publishDate = DateTime.ParseExact(torrent.UploadTime, "yyyy-MM-dd HH:mm:ss", CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal); var details = new Uri(SiteLink + "torrent/" + torrentId + "/group"); - var size = torrent.Value("Size"); - var snatched = torrent.Value("Snatched"); - var seeders = torrent.Value("Seeders"); - var leechers = torrent.Value("Leechers"); + var size = torrent.Size; + var snatched = torrent.Snatched; + var seeders = torrent.Seeders; + var leechers = torrent.Leechers; var peers = seeders + leechers; - var fileCount = torrent.Value("FileCount"); - var rawDownMultiplier = torrent.Value("RawDownMultiplier"); - var rawUpMultiplier = torrent.Value("RawUpMultiplier"); + var fileCount = torrent.FileCount; + var rawDownMultiplier = torrent.RawDownMultiplier; + var rawUpMultiplier = torrent.RawUpMultiplier; // MST with additional 5 hours per GB var minimumSeedTime = 259200 + (int)(size / (int)Math.Pow(1024, 3) * 18000); - var propertyList = WebUtility.HtmlDecode(torrent.Value("Property")) + var propertyList = WebUtility.HtmlDecode(torrent.Property) .Split('|') .Select(t => t.Trim()) .Where(p => p.IsNotNullOrWhiteSpace()) @@ -392,8 +350,7 @@ namespace Jackett.Common.Indexers.Definitions propertyList.RemoveAll(p => _ExcludedProperties.Any(p.ContainsIgnoreCase)); var properties = new HashSet(propertyList); - if (torrent.Value("FileList") != null && - torrent.Value("FileList").Any(f => f.Value("filename").ContainsIgnoreCase("Remux"))) + if (torrent.Files.Any(f => f.FileName.ContainsIgnoreCase("Remux"))) { var resolutionProperty = properties.FirstOrDefault(_RemuxResolutions.ContainsIgnoreCase); @@ -419,7 +376,7 @@ namespace Jackett.Common.Indexers.Definitions int? episode = null; var releaseInfo = categoryName == "Anime" ? "S01" : ""; - var editionTitle = torrent.Value("EditionData")?.Value("EditionTitle"); + var editionTitle = torrent.EditionData?.EditionTitle; if (editionTitle.IsNotNullOrWhiteSpace()) { @@ -573,7 +530,7 @@ namespace Jackett.Common.Indexers.Definitions var infoString = properties.Select(p => "[" + p + "]").Join(string.Empty); - var useYearInTitle = year is > 0 && torrent.Value("FileList").Any(f => f.Value("filename").Contains(year.Value.ToString())); + var useYearInTitle = year is > 0 && torrent.Files.Any(f => f.FileName.Contains(year.Value.ToString())); foreach (var title in synonyms) { @@ -591,7 +548,7 @@ namespace Jackett.Common.Indexers.Definitions Year = year, Details = details, Guid = guid, - Link = linkUri, + Link = link, Poster = poster, PublishDate = publishDate, Category = category, @@ -608,13 +565,13 @@ namespace Jackett.Common.Indexers.Definitions releases.Add(release); } - if (AddFileNameTitles && torrent.Value("FileList") != null) + if (AddFileNameTitles) { - var files = torrent.Value("FileList").ToList(); + var files = torrent.Files.ToList(); if (files.Count > 1) { - files = files.Where(f => !_ExcludedFileExtensions.Contains(Path.GetExtension(f.Value("filename")))).ToList(); + files = files.Where(f => !_ExcludedFileExtensions.Contains(Path.GetExtension(f.FileName))).ToList(); } if (files.Count != 1) @@ -622,7 +579,7 @@ namespace Jackett.Common.Indexers.Definitions continue; } - var releaseTitle = files.First().Value("filename"); + var releaseTitle = files.First().FileName; var guid = new Uri(details + "&nh=" + StringUtil.Hash(releaseTitle)); @@ -634,7 +591,7 @@ namespace Jackett.Common.Indexers.Definitions Year = year, Details = details, Guid = guid, - Link = linkUri, + Link = link, Poster = poster, PublishDate = publishDate, Category = category, @@ -705,4 +662,109 @@ namespace Jackett.Common.Indexers.Definitions return null; } } + + public class AnimeBytesResponse + { + [JsonPropertyName("Matches")] + public int Matches { get; set; } + + [JsonPropertyName("Groups")] + public IReadOnlyCollection Groups { get; set; } + + public string Error { get; set; } + } + + public class AnimeBytesGroup + { + [JsonPropertyName("ID")] + public long Id { get; set; } + + [JsonPropertyName("CategoryName")] + public string CategoryName { get; set; } + + [JsonPropertyName("FullName")] + public string FullName { get; set; } + + [JsonPropertyName("GroupName")] + public string GroupName { get; set; } + + [JsonPropertyName("SeriesName")] + public string SeriesName { get; set; } + + [JsonPropertyName("Year")] + [JsonNumberHandling(JsonNumberHandling.AllowReadingFromString)] + public int? Year { get; set; } + + [JsonPropertyName("Image")] + public string Image { get; set; } + + [JsonPropertyName("SynonymnsV2")] + public IReadOnlyDictionary Synonymns { get; set; } + + [JsonPropertyName("Description")] + public string Description { get; set; } + + [JsonPropertyName("Tags")] + public IReadOnlyCollection Tags { get; set; } + + [JsonPropertyName("Torrents")] + public IReadOnlyCollection Torrents { get; set; } + } + + public class AnimeBytesTorrent + { + [JsonPropertyName("ID")] + public long Id { get; set; } + + [JsonPropertyName("EditionData")] + public AnimeBytesEditionData EditionData { get; set; } + + [JsonPropertyName("RawDownMultiplier")] + public double RawDownMultiplier { get; set; } + + [JsonPropertyName("RawUpMultiplier")] + public double RawUpMultiplier { get; set; } + + [JsonPropertyName("Link")] + public Uri Link { get; set; } + + [JsonPropertyName("Property")] + public string Property { get; set; } + + [JsonPropertyName("Snatched")] + public int Snatched { get; set; } + + [JsonPropertyName("Seeders")] + public int Seeders { get; set; } + + [JsonPropertyName("Leechers")] + public int Leechers { get; set; } + + [JsonPropertyName("Size")] + public long Size { get; set; } + + [JsonPropertyName("FileCount")] + public int FileCount { get; set; } + + [JsonPropertyName("FileList")] + public IReadOnlyCollection Files { get; set; } + + [JsonPropertyName("UploadTime")] + public string UploadTime { get; set; } + } + + public class AnimeBytesFile + { + [JsonPropertyName("filename")] + public string FileName { get; set; } + + [JsonPropertyName("size")] + public long FileSize { get; set; } + } + + public class AnimeBytesEditionData + { + [JsonPropertyName("EditionTitle")] + public string EditionTitle { get; set; } + } }