From 077e4727f20d33a49798bca279c65207fa42c8de Mon Sep 17 00:00:00 2001 From: Bogdan Date: Fri, 27 Jan 2023 00:40:02 +0200 Subject: [PATCH] New: Add aro.lol --- .../Indexers/Definitions/AlphaRatio.cs | 4 +- .../Indexers/Definitions/AroLol.cs | 81 +++++++++++++++++++ .../Definitions/Gazelle/GazelleBase.cs | 45 +++++++---- .../Definitions/Gazelle/GazelleSettings.cs | 2 +- .../Indexers/Definitions/GreatPosterWall.cs | 2 +- 5 files changed, 113 insertions(+), 21 deletions(-) create mode 100644 src/NzbDrone.Core/Indexers/Definitions/AroLol.cs diff --git a/src/NzbDrone.Core/Indexers/Definitions/AlphaRatio.cs b/src/NzbDrone.Core/Indexers/Definitions/AlphaRatio.cs index 30ce66ad2..ef9d70139 100644 --- a/src/NzbDrone.Core/Indexers/Definitions/AlphaRatio.cs +++ b/src/NzbDrone.Core/Indexers/Definitions/AlphaRatio.cs @@ -112,9 +112,9 @@ public class AlphaRatioRequestGenerator : GazelleRequestGenerator public class AlphaRatioSettings : GazelleSettings { - [FieldDefinition(5, Label = "Freeleech Only", Type = FieldType.Checkbox, HelpText = "Search freeleech torrents only")] + [FieldDefinition(6, Label = "Freeleech Only", Type = FieldType.Checkbox, HelpText = "Search freeleech torrents only")] public bool FreeleechOnly { get; set; } - [FieldDefinition(6, Label = "Exclude Scene", Type = FieldType.Checkbox, HelpText = "Exclude Scene torrents from results")] + [FieldDefinition(7, Label = "Exclude Scene", Type = FieldType.Checkbox, HelpText = "Exclude Scene torrents from results")] public bool ExcludeScene { get; set; } } diff --git a/src/NzbDrone.Core/Indexers/Definitions/AroLol.cs b/src/NzbDrone.Core/Indexers/Definitions/AroLol.cs new file mode 100644 index 000000000..9adc88f49 --- /dev/null +++ b/src/NzbDrone.Core/Indexers/Definitions/AroLol.cs @@ -0,0 +1,81 @@ +using System.Collections.Generic; +using AngleSharp.Html.Parser; +using NLog; +using NzbDrone.Common.Http; +using NzbDrone.Core.Annotations; +using NzbDrone.Core.Configuration; +using NzbDrone.Core.Indexers.Definitions.Gazelle; +using NzbDrone.Core.Indexers.Exceptions; +using NzbDrone.Core.Messaging.Events; + +namespace NzbDrone.Core.Indexers.Definitions; + +public class AroLol : GazelleBase +{ + public override string Name => "aro.lol"; + public override string[] IndexerUrls => new[] { "https://aro.lol/" }; + public override string Description => "aro.lol is a SERBIAN/ENGLISH Private Torrent Tracker for ANIME"; + public override IndexerPrivacy Privacy => IndexerPrivacy.Private; + + public AroLol(IIndexerHttpClient httpClient, + IEventAggregator eventAggregator, + IIndexerStatusService indexerStatusService, + IConfigService configService, + Logger logger) + : base(httpClient, eventAggregator, indexerStatusService, configService, logger) + { + } + + protected override HttpRequestBuilder AuthLoginRequestBuilder() + { + return base.AuthLoginRequestBuilder() + .AddFormParameter("twofa", Settings.TwoFactorAuthCode.Trim()); + } + + protected override bool CheckForLoginError(HttpResponse response) + { + if (response.Content.Contains("loginform")) + { + var parser = new HtmlParser(); + var dom = parser.ParseDocument(response.Content); + var errorMessage = dom.QuerySelector("#loginform > .warning")?.TextContent.Trim(); + + throw new IndexerAuthException(errorMessage ?? "Unknown error message, please report."); + } + + return true; + } + + protected override IndexerCapabilities SetCapabilities() + { + var caps = new IndexerCapabilities + { + TvSearchParams = new List + { + TvSearchParam.Q + }, + MovieSearchParams = new List + { + MovieSearchParam.Q + }, + BookSearchParams = new List + { + BookSearchParam.Q + } + }; + + caps.Categories.AddCategoryMapping("1", NewznabStandardCategory.Movies, "Movies"); + caps.Categories.AddCategoryMapping("2", NewznabStandardCategory.TVAnime, "Anime"); + caps.Categories.AddCategoryMapping("3", NewznabStandardCategory.Books, "Manga"); + caps.Categories.AddCategoryMapping("4", NewznabStandardCategory.Console, "Games"); + caps.Categories.AddCategoryMapping("5", NewznabStandardCategory.Other, "Other"); + + return caps; + } +} + +public class AroLolSettings : GazelleSettings +{ + [FieldDefinition(4, Label = "2FA code", Type = FieldType.Textbox, HelpText = "Only fill in the 2FA code box if you have enabled 2FA on the aro.lol Web Site. Otherwise just leave it empty.")] + public string TwoFactorAuthCode { get; set; } +} diff --git a/src/NzbDrone.Core/Indexers/Definitions/Gazelle/GazelleBase.cs b/src/NzbDrone.Core/Indexers/Definitions/Gazelle/GazelleBase.cs index bddb5ed22..2bfb713d1 100644 --- a/src/NzbDrone.Core/Indexers/Definitions/Gazelle/GazelleBase.cs +++ b/src/NzbDrone.Core/Indexers/Definitions/Gazelle/GazelleBase.cs @@ -1,4 +1,5 @@ using System; +using System.Linq; using System.Net.Http; using System.Threading.Tasks; using NLog; @@ -40,12 +41,27 @@ public abstract class GazelleBase : TorrentIndexerBase protected virtual IndexerCapabilities SetCapabilities() { - var caps = new IndexerCapabilities(); - - return caps; + return new IndexerCapabilities(); } protected override async Task DoLogin() + { + var cookies = Cookies; + Cookies = null; + + var authLoginRequestBuilder = AuthLoginRequestBuilder(); + + var response = await ExecuteAuth(authLoginRequestBuilder.Build()); + + CheckForLoginError(response); + + cookies = response.GetCookies(); + UpdateCookies(cookies, DateTime.Now + TimeSpan.FromDays(30)); + + _logger.Debug("Gazelle authentication succeeded."); + } + + protected virtual HttpRequestBuilder AuthLoginRequestBuilder() { var requestBuilder = new HttpRequestBuilder(LoginUrl) { @@ -54,26 +70,19 @@ public abstract class GazelleBase : TorrentIndexerBase }; requestBuilder.PostProcess += r => r.RequestTimeout = TimeSpan.FromSeconds(15); - var cookies = Cookies; - - Cookies = null; - var authLoginRequest = requestBuilder + var authLoginRequestBuilder = requestBuilder .AddFormParameter("username", Settings.Username) .AddFormParameter("password", Settings.Password) .AddFormParameter("keeplogged", "1") .SetHeader("Content-Type", "application/x-www-form-urlencoded") - .Accept(HttpAccept.Json) - .Build(); - - var response = await ExecuteAuth(authLoginRequest); - - cookies = response.GetCookies(); - - UpdateCookies(cookies, DateTime.Now + TimeSpan.FromDays(30)); + .SetHeader("Referer", LoginUrl) + .Accept(HttpAccept.Json); - _logger.Debug("Gazelle authentication succeeded."); + return authLoginRequestBuilder; } + protected virtual bool CheckForLoginError(HttpResponse response) => true; + public override async Task Download(Uri link) { var response = await base.Download(link); @@ -100,6 +109,8 @@ public abstract class GazelleBase : TorrentIndexerBase protected override bool CheckIfLoginNeeded(HttpResponse response) { - return response.HasHttpRedirect || (response.Content != null && response.Content.Contains("\"bad credentials\"")); + var invalidResponses = new[] { "\"bad credentials\"", "\"groupName\":\"wrong-creds\"" }; + + return response.HasHttpRedirect || (response.Content != null && invalidResponses.Any(response.Content.Contains)); } } diff --git a/src/NzbDrone.Core/Indexers/Definitions/Gazelle/GazelleSettings.cs b/src/NzbDrone.Core/Indexers/Definitions/Gazelle/GazelleSettings.cs index f91089b33..b5d652f1c 100644 --- a/src/NzbDrone.Core/Indexers/Definitions/Gazelle/GazelleSettings.cs +++ b/src/NzbDrone.Core/Indexers/Definitions/Gazelle/GazelleSettings.cs @@ -15,7 +15,7 @@ public class GazelleSettings : UserPassTorrentBaseSettings public string AuthKey { get; set; } public string PassKey { get; set; } - [FieldDefinition(4, Type = FieldType.Checkbox, Label = "Use Freeleech Token", HelpText = "Use freeleech tokens when available")] + [FieldDefinition(5, Type = FieldType.Checkbox, Label = "Use Freeleech Token", HelpText = "Use freeleech tokens when available")] public bool UseFreeleechToken { get; set; } public override NzbDroneValidationResult Validate() diff --git a/src/NzbDrone.Core/Indexers/Definitions/GreatPosterWall.cs b/src/NzbDrone.Core/Indexers/Definitions/GreatPosterWall.cs index 35fbe3c4f..8b7021f5f 100644 --- a/src/NzbDrone.Core/Indexers/Definitions/GreatPosterWall.cs +++ b/src/NzbDrone.Core/Indexers/Definitions/GreatPosterWall.cs @@ -217,7 +217,7 @@ public class GreatPosterWallParser : GazelleParser public class GreatPosterWallSettings : GazelleSettings { - [FieldDefinition(5, Label = "Freeleech Only", Type = FieldType.Checkbox, HelpText = "Search freeleech torrents only")] + [FieldDefinition(6, Label = "Freeleech Only", Type = FieldType.Checkbox, HelpText = "Search freeleech torrents only")] public bool FreeleechOnly { get; set; } }