From 85c736f44f885f09af9e4dd92015632a8e9e5432 Mon Sep 17 00:00:00 2001 From: Diego Heras Date: Sun, 21 Jun 2020 11:22:49 +0200 Subject: [PATCH] anthelion: fix categories and remux. show imdb id. #7923 (#9023) --- src/Jackett.Common/Indexers/Anthelion.cs | 149 +++++++++++++++++++++-- 1 file changed, 142 insertions(+), 7 deletions(-) diff --git a/src/Jackett.Common/Indexers/Anthelion.cs b/src/Jackett.Common/Indexers/Anthelion.cs index 6140ea1a6..010d8a668 100644 --- a/src/Jackett.Common/Indexers/Anthelion.cs +++ b/src/Jackett.Common/Indexers/Anthelion.cs @@ -1,15 +1,31 @@ +using System; +using System.Collections.Generic; +using System.Collections.Specialized; using System.Diagnostics.CodeAnalysis; -using Jackett.Common.Indexers.Abstract; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using AngleSharp.Html.Parser; using Jackett.Common.Models; +using Jackett.Common.Models.IndexerConfig; using Jackett.Common.Services.Interfaces; +using Jackett.Common.Utils; using Jackett.Common.Utils.Clients; +using Newtonsoft.Json.Linq; using NLog; namespace Jackett.Common.Indexers { + // This tracker is based on GazelleTracker but we can't use the API/abstract because there are some + // missing features. https://github.com/Jackett/Jackett/issues/7923 [ExcludeFromCodeCoverage] - public class Anthelion : GazelleTracker + public class Anthelion : BaseWebIndexer { + private string LoginUrl => SiteLink + "login.php"; + private string BrowseUrl => SiteLink + "torrents.php"; + + private new ConfigurationDataBasicLogin configData => (ConfigurationDataBasicLogin)base.configData; + public override string[] LegacySiteLinks { get; protected set; } = { "https://tehconnection.me/", }; @@ -24,15 +40,134 @@ namespace Jackett.Common.Indexers client: wc, logger: l, p: ps, - supportsFreeleechTokens: true) + configData: new ConfigurationDataBasicLogin()) { + Encoding = Encoding.UTF8; Language = "en-us"; Type = "private"; - AddCategoryMapping(1, TorznabCatType.Movies, "Feature Film"); - AddCategoryMapping(2, TorznabCatType.Movies, "Short Film"); - AddCategoryMapping(3, TorznabCatType.Movies, "Miniseries"); - AddCategoryMapping(4, TorznabCatType.Movies, "Other"); + AddCategoryMapping("1", TorznabCatType.Movies, "Feature Film"); + AddCategoryMapping("2", TorznabCatType.Movies, "Short Film"); + AddCategoryMapping("3", TorznabCatType.TV, "Miniseries"); + AddCategoryMapping("4", TorznabCatType.Other, "Other"); + } + + public override async Task ApplyConfiguration(JToken configJson) + { + LoadValuesFromJson(configJson); + + var pairs = new Dictionary + { + { "username", configData.Username.Value }, + { "password", configData.Password.Value }, + { "keeplogged", "1" }, + { "login", "Log+In!" } + }; + + var result = await RequestLoginAndFollowRedirect(LoginUrl, pairs, null, true, null, LoginUrl, true); + await ConfigureIfOK(result.Cookies, result.Content?.Contains("logout.php") == true, () => + { + var parser = new HtmlParser(); + var dom = parser.ParseDocument(result.Content); + var errorMessage = dom.QuerySelector("form#loginform").TextContent.Trim(); + throw new ExceptionWithConfigData(errorMessage, configData); + }); + return IndexerConfigurationStatus.RequiresTesting; + } + + protected override async Task> PerformQuery(TorznabQuery query) + { + var releases = new List(); + + // TODO: IMDB search is available but it requires to parse the details page + var qc = new NameValueCollection + { + { "order_by", "time" }, + { "order_way", "desc" }, + { "action", "basic" }, + { "searchsubmit", "1" }, + { "searchstr", query.IsImdbQuery ? query.ImdbID : query.GetQueryString() } + }; + + var catList = MapTorznabCapsToTrackers(query); + foreach (var cat in catList) + qc.Add($"filter_cat[{cat}]", "1"); + + var searchUrl = BrowseUrl + "?" + qc.GetQueryString(); + var results = await RequestStringWithCookies(searchUrl); + try + { + var parser = new HtmlParser(); + var doc = parser.ParseDocument(results.Content); + var rows = doc.QuerySelectorAll("table.torrent_table > tbody > tr.torrent"); + foreach (var row in rows) + { + var qDetailsLink = row.QuerySelector("a.torrent_name"); + var year = qDetailsLink.NextSibling.TextContent.Replace("[", "").Replace("]", "").Trim(); + var tags = row.QuerySelector("div.torrent_info").FirstChild.TextContent.Replace(" / ", " ").Trim(); + var title = $"{qDetailsLink.TextContent} {year} {tags}"; + var description = row.QuerySelector("div.tags").TextContent.Trim(); + var comments = new Uri(SiteLink + qDetailsLink.GetAttribute("href")); + var torrentId = qDetailsLink.GetAttribute("href").Split('=').Last(); + var link = new Uri(SiteLink + "torrents.php?action=download&id=" + torrentId); + var bannerStr = qDetailsLink.GetAttribute("data-cover"); + var banner = !string.IsNullOrWhiteSpace(bannerStr) ? new Uri(qDetailsLink.GetAttribute("data-cover")) : null; + + var files = ParseUtil.CoerceLong(row.QuerySelector("td:nth-child(3)").TextContent); + var publishDate = DateTimeUtil.FromTimeAgo(row.QuerySelector("td:nth-child(4)").TextContent); + var size = ReleaseInfo.GetBytes(row.QuerySelector("td:nth-child(5)").FirstChild.TextContent); + var grabs = ParseUtil.CoerceLong(row.QuerySelector("td:nth-child(6)").TextContent); + var seeders = ParseUtil.CoerceInt(row.QuerySelector("td:nth-child(7)").TextContent); + var leechers = ParseUtil.CoerceInt(row.QuerySelector("td:nth-child(8)").TextContent); + + var dlVolumeFactor = row.QuerySelector("strong.tl_free") != null ? 0 : 1; + + var cat = row.QuerySelector("td.cats_col > div").GetAttribute("class").Replace("tooltip cats_", ""); + var category = new List { + cat switch + { + "featurefilm" => TorznabCatType.Movies.ID, + "shortfilm" => TorznabCatType.Movies.ID, + "miniseries" => TorznabCatType.TV.ID, + "other" => TorznabCatType.Other.ID, + _ => throw new Exception($"Unknown category: {cat}") + } + }; + + // TODO: TMDb is also available + var qImdb = row.QuerySelector("a[href^=\"https://www.imdb.com\"]"); + var imdb = qImdb != null ? ParseUtil.GetImdbID(qImdb.GetAttribute("href").Split('/').Last()) : null; + + var release = new ReleaseInfo + { + MinimumRatio = 1, + MinimumSeedTime = 0, + Description = description, + Title = title, + PublishDate = publishDate, + Category = category, + Link = link, + Comments = comments, + Guid = link, + Imdb = imdb, + BannerUrl = banner, + Seeders = seeders, + Peers = leechers + seeders, + Size = size, + Grabs = grabs, + Files = files, + DownloadVolumeFactor = dlVolumeFactor, + UploadVolumeFactor = 1 + }; + releases.Add(release); + } + } + catch (Exception ex) + { + OnParseError(results.Content, ex); + } + + return releases; } } }