diff --git a/README.md b/README.md index 41841ad55..b280c2b9c 100644 --- a/README.md +++ b/README.md @@ -32,7 +32,6 @@ A third-party Golang SDK for Jackett is available from [webtor-io/go-jackett](ht * Anidex * AniLibria * AnimeClipse - * Animedia * Anime Tosho * AniRena * AniSource diff --git a/src/Jackett.Common/Indexers/Animedia.cs b/src/Jackett.Common/Indexers/Animedia.cs deleted file mode 100644 index ff0975500..000000000 --- a/src/Jackett.Common/Indexers/Animedia.cs +++ /dev/null @@ -1,221 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Collections.Specialized; -using System.Diagnostics.CodeAnalysis; -using System.Linq; -using System.Text; -using System.Text.RegularExpressions; -using System.Threading.Tasks; -using AngleSharp.Dom; -using AngleSharp.Html.Dom; -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 -{ - [ExcludeFromCodeCoverage] - internal class Animedia : BaseWebIndexer - { - private static readonly Regex EpisodesInfoQueryRegex = new Regex(@"серии (\d+)-(\d+) из.*", RegexOptions.Compiled | RegexOptions.IgnoreCase); - private static readonly Regex ResolutionInfoQueryRegex = new Regex(@"Качество (\d+)", RegexOptions.Compiled | RegexOptions.IgnoreCase); - private static readonly Regex SizeInfoQueryRegex = new Regex(@"Размер:(.*)\n", RegexOptions.Compiled | RegexOptions.IgnoreCase); - private static readonly Regex ReleaseDateInfoQueryRegex = new Regex(@"Добавлен:(.*)\n", RegexOptions.Compiled | RegexOptions.IgnoreCase); - - public Animedia(IIndexerConfigurationService configService, WebClient wc, Logger l, IProtectionService ps, - ICacheService cs) - : base(id: "Animedia", - name: "Animedia", - description: "Animedia is a public russian tracker and release group for anime.", - link: "https://tt.animedia.tv/", - caps: new TorznabCapabilities - { - TvSearchParams = new List - { - TvSearchParam.Q, TvSearchParam.Season, TvSearchParam.Ep - } - }, - configService: configService, - client: wc, - logger: l, - p: ps, - cacheService: cs, - configData: new ConfigurationData()) - { - Encoding = Encoding.UTF8; - Language = "ru-RU"; - Type = "public"; - - // Configure the category mappings - AddCategoryMapping(1, TorznabCatType.TVAnime, "Anime"); - } - - /// - /// https://tt.animedia.tv/ajax/search_result/P0 - /// - private string SearchUrl => SiteLink + "ajax/search_result/P0"; - - public override async Task ApplyConfiguration(JToken configJson) - { - LoadValuesFromJson(configJson); - var releases = await PerformQuery(new TorznabQuery()); - - await ConfigureIfOK(string.Empty, releases.Any(), () => - throw new Exception("Could not find releases from this URL")); - - return IndexerConfigurationStatus.Completed; - } - - // If the search string is empty use the latest releases - protected override async Task> PerformQuery(TorznabQuery query) - { - WebResult result; - if (query.IsTest || string.IsNullOrWhiteSpace(query.SearchTerm)) - { - result = await RequestWithCookiesAndRetryAsync(SiteLink); - } - else - { - // Prepare the search query - var queryParameters = new NameValueCollection - { - { "keywords", query.SearchTerm }, - { "limit", "20"}, - { "orderby_sort", "entry_date|desc"} - }; - result = await RequestWithCookiesAndRetryAsync(SearchUrl + "?" + queryParameters.GetQueryString()); - } - - const string ReleaseLinksSelector = "a.ads-list__item__title"; - - var releases = new List(); - - try - { - var parser = new HtmlParser(); - var document = await parser.ParseDocumentAsync(result.ContentString); - - foreach (var linkNode in document.QuerySelectorAll(ReleaseLinksSelector)) - { - var url = linkNode.GetAttribute("href"); - releases.AddRange(await FetchShowReleases(url)); - } - } - catch (Exception ex) - { - OnParseError(result.ContentString, ex); - } - - return releases; - } - - private async Task> FetchShowReleases(string url) - { - var releases = new List(); - var uri = new Uri(url); - //Some URLs in search are broken - if (url.StartsWith("//")) - { - url = "https:" + url; - } - - var result = await RequestWithCookiesAndRetryAsync(url); - - try - { - var parser = new HtmlParser(); - var document = await parser.ParseDocumentAsync(result.ContentString); - - var baseRelease = new ReleaseInfo - { - Title = composeBaseTitle(document), - Poster = new Uri(document.QuerySelector("div.widget__post-info__poster > a").Attributes["href"].Value), - Details = uri, - DownloadVolumeFactor = 0, - UploadVolumeFactor = 1, - Category = new[] { TorznabCatType.TVAnime.ID } - }; - foreach (var t in document.QuerySelectorAll("ul.media__tabs__nav > li > a")) - { - var release = (ReleaseInfo)baseRelease.Clone(); - var tr_id = t.Attributes["href"].Value; - var tr = document.QuerySelector("div" + tr_id); - if (tr.Text().Contains("TORRENT READ ERROR")) - { - logger.Warn($"{DisplayName} The page at {uri.ToString()} has a TORRENT READ ERROR alert. Unable to retrieve this torrent's details."); - continue; - } - release.Title += " - " + composeTitleAdditionalInfo(t, tr); - release.Link = new Uri(tr.QuerySelector("div.download_tracker > a.btn__green").Attributes["href"].Value); - release.MagnetUri = new Uri(tr.QuerySelector("div.download_tracker > a.btn__d-gray").Attributes["href"].Value); - release.Seeders = long.Parse(tr.QuerySelector("div.circle_green_text_top").Text()); - release.Peers = release.Seeders + long.Parse(tr.QuerySelector("div.circle_red_text_top").Text()); - release.Grabs = long.Parse(tr.QuerySelector("div.circle_grey_text_top").Text()); - release.PublishDate = getReleaseDate(tr); - release.Size = getReleaseSize(tr); - release.Guid = new Uri(uri.ToString() + tr_id); - releases.Add(release); - } - } - catch (Exception ex) - { - OnParseError(result.ContentString, ex); - } - - return releases; - } - - private string composeBaseTitle(IHtmlDocument r) - { - var name_ru = r.QuerySelector("div.media__post__header > h1").Text().Trim(); - var name_en = r.QuerySelector("div.media__panel > div:nth-of-type(1) > div.col-l:nth-of-type(1) > div > span").Text().Trim(); - var name_orig = r.QuerySelector("div.media__panel > div:nth-of-type(1) > div.col-l:nth-of-type(2) > div > span").Text().Trim(); - - var title = name_ru + " / " + name_en; - if (name_en != name_orig) - { - title += " / " + name_orig; - } - return title; - } - - private string composeTitleAdditionalInfo(IElement t, IElement tr) - { - var tabName = t.Text(); - tabName = tabName.Replace("Сезон", "Season"); - if (tabName.Contains("Серии")) - { - tabName = ""; - } - - var heading = tr.QuerySelector("h3.tracker_info_bold").Text(); - // Transform episodes info if header contains that - heading = EpisodesInfoQueryRegex.Replace( - heading, - match => match.Success ? $"E{int.Parse(match.Groups[1].Value)}-{int.Parse(match.Groups[2].Value)}" : heading - ); - - var resolution = tr.QuerySelector("div.tracker_info_left").Text(); - resolution = ResolutionInfoQueryRegex.Match(resolution).Groups[1].Value; - - return tabName + " " + heading + " [" + resolution + "p]"; - } - - private static long getReleaseSize(IElement tr) - { - var sizeStr = tr.QuerySelector("div.tracker_info_left").Text(); - return ReleaseInfo.GetBytes(SizeInfoQueryRegex.Match(sizeStr).Groups[1].Value.Trim()); - } - - private static DateTime getReleaseDate(IElement tr) - { - var sizeStr = tr.QuerySelector("div.tracker_info_left").Text(); - return DateTime.Parse(ReleaseDateInfoQueryRegex.Match(sizeStr).Groups[1].Value.Trim()); - } - } -}