mirror of https://github.com/Jackett/Jackett
parent
938315cebd
commit
ed9d0a8328
|
@ -24,8 +24,6 @@ $.fn.focusWithoutScrolling = function () {
|
|||
|
||||
$(document).ready(function () {
|
||||
$.ajaxSetup({ cache: false });
|
||||
//window.jackettIsLocal = window.location.hostname === '127.0.0.1';
|
||||
window.jackettIsLocal = false; // reCaptcha can't be solved via 127.0.0.1 anymore. This loophold was fixed by google around 2.10.2017
|
||||
|
||||
Handlebars.registerHelper('if_eq', function(a, b, opts) {
|
||||
if (a == b)
|
||||
|
@ -511,79 +509,13 @@ function populateConfigItems(configForm, config) {
|
|||
var $formItemContainer = configForm.find(".config-setup-form");
|
||||
$formItemContainer.empty();
|
||||
|
||||
$('.jackettrecaptcha').remove();
|
||||
|
||||
var hasReacaptcha = false;
|
||||
var captchaItem = null;
|
||||
for (var i = 0; i < config.length; i++) {
|
||||
if (config[i].type === 'recaptcha') {
|
||||
hasReacaptcha = true;
|
||||
captchaItem = config[i];
|
||||
}
|
||||
else if (config[i].id === 'cookieheader' && hasReacaptcha) { // inject cookie into captcha item
|
||||
captchaItem.cookieheader = config[i].value;
|
||||
console.log(captchaItem);
|
||||
}
|
||||
}
|
||||
|
||||
var setupItemTemplate = Handlebars.compile($("#setup-item").html());
|
||||
if (hasReacaptcha && !window.jackettIsLocal && false) { // disable this for now, use inline cookie (below)
|
||||
var setupValueTemplate = Handlebars.compile($("#setup-item-nonlocalrecaptcha").html());
|
||||
captchaItem.value_element = setupValueTemplate(captchaItem);
|
||||
var template = setupItemTemplate(captchaItem);
|
||||
for (var i = 0; i < config.length; i++) {
|
||||
var item = config[i];
|
||||
var setupValueTemplate = Handlebars.compile($("#setup-item-" + item.type).html());
|
||||
item.value_element = setupValueTemplate(item);
|
||||
var template = setupItemTemplate(item);
|
||||
$formItemContainer.append(template);
|
||||
} else {
|
||||
|
||||
for (var i = 0; i < config.length; i++) {
|
||||
var item = config[i];
|
||||
if ((item.id === 'username' || item.id === 'password') && hasReacaptcha) {
|
||||
continue; // skip username/password if there's a recaptcha
|
||||
}
|
||||
if (item.type != 'recaptcha') {
|
||||
var setupValueTemplate = Handlebars.compile($("#setup-item-" + item.type).html());
|
||||
item.value_element = setupValueTemplate(item);
|
||||
var template = setupItemTemplate(item);
|
||||
$formItemContainer.append(template);
|
||||
}
|
||||
if (item.type === 'recaptcha') {
|
||||
// inject cookie dialog until recaptcha can be solved again
|
||||
var setupValueTemplate = Handlebars.compile($("#setup-item-nonlocalrecaptcha").html());
|
||||
captchaItem.value_element = setupValueTemplate(captchaItem);
|
||||
var template = setupItemTemplate(captchaItem);
|
||||
$formItemContainer.append(template);
|
||||
/*
|
||||
var jackettrecaptcha = $('.jackettrecaptcha');
|
||||
jackettrecaptcha.data("version", item.version);
|
||||
switch (item.version) {
|
||||
case "1":
|
||||
// The v1 reCAPTCHA code uses document.write() calls to write the CAPTCHA to the location where the script was loaded.
|
||||
// As it's loaded async this doesn't work.
|
||||
// We use an iframe to work around this problem.
|
||||
var html = '<script type="text/javascript" src="https://www.google.com/recaptcha/api/challenge?k='+encodeURIComponent(item.sitekey)+'"></script>';
|
||||
var frame = document.createElement('iframe');
|
||||
frame.id = "jackettrecaptchaiframe";
|
||||
frame.style.height = "145px";
|
||||
frame.style.weight = "326px";
|
||||
frame.style.border = "none";
|
||||
frame.onload = function () {
|
||||
// auto resize iframe to content
|
||||
frame.style.height = frame.contentWindow.document.body.scrollHeight + 'px';
|
||||
frame.style.width = frame.contentWindow.document.body.scrollWidth + 'px';
|
||||
}
|
||||
jackettrecaptcha.append(frame);
|
||||
frame.contentDocument.open();
|
||||
frame.contentDocument.write(html);
|
||||
frame.contentDocument.close();
|
||||
break;
|
||||
case "2":
|
||||
grecaptcha.render(jackettrecaptcha[0], {
|
||||
'sitekey': item.sitekey
|
||||
});
|
||||
break;
|
||||
}
|
||||
*/
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -631,24 +563,6 @@ function getConfigModalJson(configForm) {
|
|||
case "inputselect":
|
||||
itemEntry.value = $el.find(".setup-item-inputselect select").val();
|
||||
break;
|
||||
case "recaptcha":
|
||||
if (window.jackettIsLocal) {
|
||||
var version = $el.find('.jackettrecaptcha').data("version");
|
||||
switch (version) {
|
||||
case "1":
|
||||
var frameDoc = $("#jackettrecaptchaiframe")[0].contentDocument;
|
||||
itemEntry.version = version;
|
||||
itemEntry.challenge = $("#recaptcha_challenge_field", frameDoc).val()
|
||||
itemEntry.value = $("#recaptcha_response_field", frameDoc).val()
|
||||
break;
|
||||
case "2":
|
||||
itemEntry.value = $('.g-recaptcha-response').val();
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
itemEntry.cookie = $el.find(".setup-item-recaptcha input").val();
|
||||
}
|
||||
break;
|
||||
}
|
||||
configJson.push(itemEntry)
|
||||
});
|
||||
|
|
|
@ -30,7 +30,6 @@
|
|||
<script type="text/javascript" src="../bootstrap/bootstrap.min.js?changed=2017083001"></script>
|
||||
<script type="text/javascript" src="../libs/bootstrap-notify.js?changed=2017083001"></script>
|
||||
<script type="text/javascript" src="../libs/bootstrap-multiselect.js?changed=2017083001"></script>
|
||||
<!--<script type="text/javascript" src="https://www.google.com/recaptcha/api.js?render=explicit" async defer></script>-->
|
||||
|
||||
<link rel="stylesheet" type="text/css" href="../bootstrap/bootstrap.min.css?changed=2017083001">
|
||||
<link rel="stylesheet" type="text/css" href="../animate.css?changed=2017083001">
|
||||
|
@ -205,13 +204,6 @@
|
|||
|
||||
<div id="modals"></div>
|
||||
|
||||
<script id="setup-item-nonlocalrecaptcha" type="text/x-handlebars-template">
|
||||
<div class="setup-item-recaptcha">
|
||||
<p>This site requires you to solve a ReCaptcha. It's no longer possible to solve the captcha in Jackett. Please enter the cookie for the site manually. <a href="https://github.com/Jackett/Jackett/wiki/Finding-cookies" target="_blank">See here</a> on how get the cookies.</p>
|
||||
<div class="setup-item-label">Full cookie header</div>
|
||||
<input class="form-control" type="text" value="{{cookieheader}}" />
|
||||
</div>
|
||||
</script>
|
||||
<script id="setup-item" type="text/x-handlebars-template">
|
||||
<div class="setup-item form-group" data-id="{{id}}" data-value="{{value}}" data-type="{{type}}">
|
||||
<div class="setup-item-label">{{name}}</div>
|
||||
|
@ -262,10 +254,6 @@
|
|||
</select>
|
||||
</div>
|
||||
</script>
|
||||
<script id="setup-item-recaptcha" type="text/x-handlebars-template">
|
||||
<div class="jackettrecaptcha">
|
||||
</div>
|
||||
</script>
|
||||
<script id="setup-item-displayimage" type="text/x-handlebars-template">
|
||||
<img class="setup-item-displayimage" src="{{{value}}}" alt="No image available" />
|
||||
</script>
|
||||
|
@ -692,6 +680,6 @@
|
|||
</script>
|
||||
|
||||
<script type="text/javascript" src="../libs/api.js?changed=2017083001"></script>
|
||||
<script type="text/javascript" src="../custom.js?changed=20200926"></script>
|
||||
<script type="text/javascript" src="../custom.js?changed=20201104"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -524,11 +524,6 @@ namespace Jackett.Common.Indexers
|
|||
{
|
||||
throw new Exception("Request to " + response.Request.Url + " failed (Error " + response.Status + ") - The tracker seems to be down.");
|
||||
}
|
||||
|
||||
if (response.Status == System.Net.HttpStatusCode.Forbidden && response.ContentString.Contains("<span data-translate=\"complete_sec_check\">Please complete the security check to access</span>"))
|
||||
{
|
||||
throw new Exception("Request to " + response.Request.Url + " failed (Error " + response.Status + ") - The page is protected by an Cloudflare reCaptcha. The page is in aggressive DDoS mitigation mode or your IP might be blacklisted (e.g. in case of shared VPN IPs). There's no easy way of making it usable with Jackett.");
|
||||
}
|
||||
}
|
||||
|
||||
protected async Task FollowIfRedirect(WebResult response, string referrer = null, string overrideRedirectUrl = null, string overrideCookies = null, bool accumulateCookies = false)
|
||||
|
|
|
@ -21,11 +21,9 @@ namespace Jackett.Common.Indexers
|
|||
[ExcludeFromCodeCoverage]
|
||||
public class BitHDTV : BaseWebIndexer
|
||||
{
|
||||
private string LoginUrl => SiteLink + "login.php";
|
||||
private string TakeLoginUrl => SiteLink + "takelogin.php";
|
||||
private string SearchUrl => SiteLink + "torrents.php";
|
||||
|
||||
private new ConfigurationDataRecaptchaLogin configData => (ConfigurationDataRecaptchaLogin)base.configData;
|
||||
private new ConfigurationDataCookie configData => (ConfigurationDataCookie)base.configData;
|
||||
|
||||
public BitHDTV(IIndexerConfigurationService configService, WebClient w, Logger l, IProtectionService ps)
|
||||
: base(id: "bithdtv",
|
||||
|
@ -47,7 +45,7 @@ namespace Jackett.Common.Indexers
|
|||
client: w,
|
||||
logger: l,
|
||||
p: ps,
|
||||
configData: new ConfigurationDataRecaptchaLogin("For best results, change the 'Torrents per page' setting to 100 in your profile."))
|
||||
configData: new ConfigurationDataCookie("For best results, change the 'Torrents per page' setting to 100 in your profile."))
|
||||
{
|
||||
Encoding = Encoding.GetEncoding("iso-8859-1");
|
||||
Language = "en-us";
|
||||
|
@ -66,59 +64,26 @@ namespace Jackett.Common.Indexers
|
|||
AddCategoryMapping(11, TorznabCatType.XXX); // XXX
|
||||
}
|
||||
|
||||
public override async Task<ConfigurationData> GetConfigurationForSetup()
|
||||
{
|
||||
var result = configData;
|
||||
var loginPage = await RequestWithCookiesAsync(LoginUrl, configData.CookieHeader.Value);
|
||||
if (loginPage.IsRedirect)
|
||||
return result; // already logged in
|
||||
var parser = new HtmlParser();
|
||||
var cq = parser.ParseDocument(loginPage.ContentString);
|
||||
var recaptchaSiteKey = cq.QuerySelector(".g-recaptcha")?.GetAttribute("data-sitekey");
|
||||
result.CookieHeader.Value = loginPage.Cookies;
|
||||
result.Captcha.SiteKey = recaptchaSiteKey;
|
||||
result.Captcha.Version = "2";
|
||||
return result;
|
||||
}
|
||||
|
||||
public override async Task<IndexerConfigurationStatus> ApplyConfiguration(JToken configJson)
|
||||
{
|
||||
LoadValuesFromJson(configJson);
|
||||
var pairs = new Dictionary<string, string>
|
||||
{
|
||||
{"username", configData.Username.Value},
|
||||
{"password", configData.Password.Value},
|
||||
{"g-recaptcha-response", configData.Captcha.Value}
|
||||
};
|
||||
if (!string.IsNullOrWhiteSpace(configData.Captcha.Cookie))
|
||||
{
|
||||
// Cookie was manually supplied
|
||||
CookieHeader = configData.Captcha.Cookie;
|
||||
try
|
||||
{
|
||||
var results = await PerformQuery(new TorznabQuery());
|
||||
if (!results.Any())
|
||||
throw new Exception("Found 0 results in the tracker");
|
||||
IsConfigured = true;
|
||||
SaveConfig();
|
||||
return IndexerConfigurationStatus.Completed;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
IsConfigured = false;
|
||||
throw new Exception("Your cookie did not work: " + e.Message);
|
||||
}
|
||||
}
|
||||
|
||||
var response = await RequestLoginAndFollowRedirect(TakeLoginUrl, pairs, null, true, referer: SiteLink);
|
||||
await ConfigureIfOK(response.Cookies, response.ContentString?.Contains("logout.php") == true, () =>
|
||||
CookieHeader = configData.Cookie.Value;
|
||||
try
|
||||
{
|
||||
var parser = new HtmlParser();
|
||||
var dom = parser.ParseDocument(response.ContentString);
|
||||
var errorMessage = dom.QuerySelector("table.detail td.text").FirstChild.TextContent.Trim();
|
||||
throw new ExceptionWithConfigData(errorMessage, configData);
|
||||
});
|
||||
return IndexerConfigurationStatus.RequiresTesting;
|
||||
var results = await PerformQuery(new TorznabQuery());
|
||||
if (!results.Any())
|
||||
throw new Exception("Found 0 results in the tracker");
|
||||
|
||||
IsConfigured = true;
|
||||
SaveConfig();
|
||||
return IndexerConfigurationStatus.Completed;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
IsConfigured = false;
|
||||
throw new Exception("Your cookie did not work: " + e.Message);
|
||||
}
|
||||
}
|
||||
|
||||
protected override async Task<IEnumerable<ReleaseInfo>> PerformQuery(TorznabQuery query)
|
||||
|
|
|
@ -502,47 +502,6 @@ namespace Jackett.Common.Indexers
|
|||
var queryCollection = new NameValueCollection();
|
||||
var pairs = new Dictionary<string, string>();
|
||||
|
||||
var CaptchaConfigItem = (RecaptchaItem)configData.GetDynamic("Captcha");
|
||||
|
||||
if (CaptchaConfigItem != null)
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(CaptchaConfigItem.Cookie))
|
||||
{
|
||||
// for remote users just set the cookie and return
|
||||
CookieHeader = CaptchaConfigItem.Cookie;
|
||||
return true;
|
||||
}
|
||||
|
||||
var CloudFlareCaptchaChallenge = landingResultDocument.QuerySelector("script[src=\"/cdn-cgi/scripts/cf.challenge.js\"]");
|
||||
if (CloudFlareCaptchaChallenge != null)
|
||||
{
|
||||
var CloudFlareQueryCollection = new NameValueCollection
|
||||
{
|
||||
["id"] = CloudFlareCaptchaChallenge.GetAttribute("data-ray"),
|
||||
|
||||
["g-recaptcha-response"] = CaptchaConfigItem.Value
|
||||
};
|
||||
var ClearanceUrl = resolvePath("/cdn-cgi/l/chk_captcha?" + CloudFlareQueryCollection.GetQueryString());
|
||||
var ClearanceResult = await RequestWithCookiesAsync(ClearanceUrl.ToString(), referer: SiteLink);
|
||||
|
||||
if (ClearanceResult.IsRedirect) // clearance successfull
|
||||
{
|
||||
// request real login page again
|
||||
landingResult = await RequestWithCookiesAsync(LoginUrl, referer: SiteLink);
|
||||
var htmlParser = new HtmlParser();
|
||||
landingResultDocument = htmlParser.ParseDocument(landingResult.ContentString);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new ExceptionWithConfigData(string.Format("Login failed: Cloudflare clearance failed using cookies {0}: {1}", CookieHeader, ClearanceResult.ContentString), configData);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
pairs.Add("g-recaptcha-response", CaptchaConfigItem.Value);
|
||||
}
|
||||
}
|
||||
|
||||
var FormSelector = Login.Form;
|
||||
if (FormSelector == null)
|
||||
FormSelector = "form";
|
||||
|
@ -886,36 +845,10 @@ namespace Jackett.Common.Indexers
|
|||
await FollowIfRedirect(landingResult, LoginUrl.AbsoluteUri, overrideCookies: landingResult.Cookies, accumulateCookies: true);
|
||||
}
|
||||
|
||||
var hasCaptcha = false;
|
||||
var htmlParser = new HtmlParser();
|
||||
landingResultDocument = htmlParser.ParseDocument(landingResult.ContentString);
|
||||
|
||||
var hasCaptcha = false;
|
||||
|
||||
var cloudFlareCaptchaScript = landingResultDocument.QuerySelector("script[src*=\"/recaptcha/api.js\"]");
|
||||
var cloudFlareCaptchaGroup = landingResultDocument.QuerySelector("#recaptca_group");
|
||||
var cloudFlareCaptchaDisplay = true;
|
||||
if (cloudFlareCaptchaGroup != null)
|
||||
{
|
||||
var cloudFlareCaptchaGroupStyle = cloudFlareCaptchaGroup.GetAttribute("style");
|
||||
if (cloudFlareCaptchaGroupStyle != null)
|
||||
cloudFlareCaptchaDisplay = !cloudFlareCaptchaGroupStyle.Contains("display:none;");
|
||||
}
|
||||
var grecaptcha = landingResultDocument.QuerySelector(".g-recaptcha");
|
||||
if (cloudFlareCaptchaScript != null && grecaptcha != null && cloudFlareCaptchaDisplay)
|
||||
{
|
||||
hasCaptcha = true;
|
||||
var CaptchaItem = new RecaptchaItem
|
||||
{
|
||||
Name = "Captcha",
|
||||
Version = "2",
|
||||
// some sites don't store the sitekey in the .g-recaptcha div (e.g. cloudflare captcha challenge page)
|
||||
SiteKey = grecaptcha.GetAttribute("data-sitekey") ??
|
||||
landingResultDocument.QuerySelector("[data-sitekey]").GetAttribute("data-sitekey")
|
||||
};
|
||||
|
||||
configData.AddDynamic("Captcha", CaptchaItem);
|
||||
}
|
||||
|
||||
if (Login.Captcha != null)
|
||||
{
|
||||
var Captcha = Login.Captcha;
|
||||
|
|
|
@ -5,7 +5,6 @@ using System.Diagnostics.CodeAnalysis;
|
|||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using AngleSharp.Html.Parser;
|
||||
using Jackett.Common.Helpers;
|
||||
|
@ -28,13 +27,8 @@ namespace Jackett.Common.Indexers
|
|||
};
|
||||
|
||||
private string SearchUrl => SiteLink + "browse.php";
|
||||
private string LoginUrl => SiteLink + "login.php";
|
||||
|
||||
private new ConfigurationDataRecaptchaLogin configData
|
||||
{
|
||||
get => (ConfigurationDataRecaptchaLogin)base.configData;
|
||||
set => base.configData = value;
|
||||
}
|
||||
private new ConfigurationDataCookie configData => (ConfigurationDataCookie)base.configData;
|
||||
|
||||
public Fuzer(IIndexerConfigurationService configService, WebClient w, Logger l, IProtectionService ps)
|
||||
: base(id: "fuzer",
|
||||
|
@ -64,7 +58,7 @@ namespace Jackett.Common.Indexers
|
|||
client: w,
|
||||
logger: l,
|
||||
p: ps,
|
||||
configData: new ConfigurationDataRecaptchaLogin())
|
||||
configData: new ConfigurationDataCookie())
|
||||
{
|
||||
Encoding = Encoding.GetEncoding("windows-1255");
|
||||
Language = "he-il";
|
||||
|
@ -121,70 +115,26 @@ namespace Jackett.Common.Indexers
|
|||
AddCategoryMapping(76, TorznabCatType.TV, "סדרות");
|
||||
}
|
||||
|
||||
public override async Task<ConfigurationData> GetConfigurationForSetup()
|
||||
{
|
||||
var loginPage = await RequestWithCookiesAsync(LoginUrl, string.Empty);
|
||||
var parser = new HtmlParser();
|
||||
var cq = parser.ParseDocument(loginPage.ContentString);
|
||||
var captcha = cq.QuerySelector(".g-recaptcha"); // invisible recaptcha
|
||||
if (captcha != null)
|
||||
{
|
||||
var result = configData;
|
||||
result.CookieHeader.Value = loginPage.Cookies;
|
||||
result.Captcha.SiteKey = captcha.GetAttribute("data-sitekey");
|
||||
result.Captcha.Version = "2";
|
||||
return result;
|
||||
}
|
||||
else
|
||||
{
|
||||
var result = new ConfigurationDataBasicLogin();
|
||||
result.SiteLink.Value = configData.SiteLink.Value;
|
||||
result.Instructions.Value = configData.Instructions.Value;
|
||||
result.Username.Value = configData.Username.Value;
|
||||
result.Password.Value = configData.Password.Value;
|
||||
result.CookieHeader.Value = loginPage.Cookies;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
public override async Task<IndexerConfigurationStatus> ApplyConfiguration(JToken configJson)
|
||||
{
|
||||
LoadValuesFromJson(configJson);
|
||||
if (!string.IsNullOrWhiteSpace(configData.Captcha.Cookie))
|
||||
{
|
||||
CookieHeader = configData.Captcha.Cookie;
|
||||
try
|
||||
{
|
||||
var results = await PerformQuery(new TorznabQuery());
|
||||
if (!results.Any())
|
||||
throw new Exception("Found 0 results in the tracker");
|
||||
IsConfigured = true;
|
||||
SaveConfig();
|
||||
return IndexerConfigurationStatus.Completed;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
IsConfigured = false;
|
||||
throw new Exception("Your cookie did not work: " + e.Message);
|
||||
}
|
||||
}
|
||||
|
||||
var loginPage = await RequestWithCookiesAsync(LoginUrl, string.Empty);
|
||||
var pairs = new Dictionary<string, string>
|
||||
CookieHeader = configData.Cookie.Value;
|
||||
try
|
||||
{
|
||||
{"vb_login_username", configData.Username.Value},
|
||||
{"vb_login_password", ""},
|
||||
{"securitytoken", "guest"},
|
||||
{"do", "login"},
|
||||
{"vb_login_md5password", StringUtil.Hash(configData.Password.Value).ToLower()},
|
||||
{"vb_login_md5password_utf", StringUtil.Hash(configData.Password.Value).ToLower()},
|
||||
{"cookieuser", "1"}
|
||||
};
|
||||
var result = await RequestLoginAndFollowRedirect(LoginUrl, pairs, loginPage.Cookies, true, null, LoginUrl);
|
||||
await ConfigureIfOK(result.Cookies, result.ContentString?.Contains("images/loading.gif") == true,
|
||||
() => throw new ExceptionWithConfigData("Couldn't login", configData));
|
||||
Thread.Sleep(2);
|
||||
return IndexerConfigurationStatus.RequiresTesting;
|
||||
var results = await PerformQuery(new TorznabQuery());
|
||||
if (!results.Any())
|
||||
throw new Exception("Found 0 results in the tracker");
|
||||
|
||||
IsConfigured = true;
|
||||
SaveConfig();
|
||||
return IndexerConfigurationStatus.Completed;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
IsConfigured = false;
|
||||
throw new Exception("Your cookie did not work: " + e.Message);
|
||||
}
|
||||
}
|
||||
|
||||
protected override async Task<IEnumerable<ReleaseInfo>> PerformQuery(TorznabQuery query)
|
||||
|
|
|
@ -8,7 +8,6 @@ using System.Text.RegularExpressions;
|
|||
using System.Threading.Tasks;
|
||||
using AngleSharp.Html.Parser;
|
||||
using Jackett.Common.Models;
|
||||
using Jackett.Common.Models.IndexerConfig;
|
||||
using Jackett.Common.Models.IndexerConfig.Bespoke;
|
||||
using Jackett.Common.Services.Interfaces;
|
||||
using Jackett.Common.Utils;
|
||||
|
@ -21,8 +20,6 @@ namespace Jackett.Common.Indexers
|
|||
[ExcludeFromCodeCoverage]
|
||||
public class SceneTime : BaseWebIndexer
|
||||
{
|
||||
private string StartPageUrl => SiteLink + "login.php";
|
||||
private string LoginUrl => SiteLink + "takelogin1.php";
|
||||
private string SearchUrl => SiteLink + "browse.php";
|
||||
private string DownloadUrl => SiteLink + "download.php/{0}/download.torrent";
|
||||
|
||||
|
@ -88,80 +85,26 @@ namespace Jackett.Common.Indexers
|
|||
AddCategoryMapping(116, TorznabCatType.Audio, "Music Pack");
|
||||
}
|
||||
|
||||
public override async Task<ConfigurationData> GetConfigurationForSetup()
|
||||
{
|
||||
WebResult loginPage;
|
||||
try
|
||||
{
|
||||
loginPage = await RequestWithCookiesAsync(StartPageUrl, string.Empty);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
// The login page is protected by Cloudflare
|
||||
return configData;
|
||||
}
|
||||
|
||||
var parser = new HtmlParser();
|
||||
var dom = parser.ParseDocument(loginPage.ContentString);
|
||||
var recaptcha = dom.QuerySelector(".g-recaptcha");
|
||||
if (recaptcha != null)
|
||||
{
|
||||
var result = configData;
|
||||
result.Captcha.Version = "2";
|
||||
result.CookieHeader.Value = loginPage.Cookies;
|
||||
result.Captcha.SiteKey = recaptcha.GetAttribute("data-sitekey");
|
||||
return result;
|
||||
}
|
||||
|
||||
var stdResult = new ConfigurationDataBasicLogin
|
||||
{
|
||||
SiteLink = { Value = configData.SiteLink.Value },
|
||||
Username = { Value = configData.Username.Value },
|
||||
Password = { Value = configData.Password.Value },
|
||||
CookieHeader = { Value = loginPage.Cookies }
|
||||
};
|
||||
return stdResult;
|
||||
}
|
||||
|
||||
public override async Task<IndexerConfigurationStatus> ApplyConfiguration(JToken configJson)
|
||||
{
|
||||
LoadValuesFromJson(configJson);
|
||||
var pairs = new Dictionary<string, string> {
|
||||
{ "username", configData.Username.Value },
|
||||
{ "password", configData.Password.Value },
|
||||
{ "g-recaptcha-response", configData.Captcha.Value }
|
||||
};
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(configData.Captcha.Cookie))
|
||||
CookieHeader = configData.Cookie.Value;
|
||||
try
|
||||
{
|
||||
CookieHeader = configData.Captcha.Cookie;
|
||||
try
|
||||
{
|
||||
var results = await PerformQuery(new TorznabQuery());
|
||||
if (!results.Any())
|
||||
throw new Exception("Found 0 results in the tracker");
|
||||
var results = await PerformQuery(new TorznabQuery());
|
||||
if (!results.Any())
|
||||
throw new Exception("Found 0 results in the tracker");
|
||||
|
||||
IsConfigured = true;
|
||||
SaveConfig();
|
||||
return IndexerConfigurationStatus.Completed;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
IsConfigured = false;
|
||||
throw new Exception("Your cookie did not work: " + e.Message);
|
||||
}
|
||||
IsConfigured = true;
|
||||
SaveConfig();
|
||||
return IndexerConfigurationStatus.Completed;
|
||||
}
|
||||
|
||||
var result = await RequestLoginAndFollowRedirect(LoginUrl, pairs, null, true, null, LoginUrl);
|
||||
await ConfigureIfOK(result.Cookies, result.ContentString != null && result.ContentString.Contains("logout.php"), () =>
|
||||
catch (Exception e)
|
||||
{
|
||||
var parser = new HtmlParser();
|
||||
var dom = parser.ParseDocument(result.ContentString);
|
||||
var errorMessage = dom.QuerySelector("td.text").TextContent.Trim();
|
||||
throw new ExceptionWithConfigData(errorMessage, configData);
|
||||
});
|
||||
|
||||
return IndexerConfigurationStatus.RequiresTesting;
|
||||
IsConfigured = false;
|
||||
throw new Exception("Your cookie did not work: " + e.Message);
|
||||
}
|
||||
}
|
||||
|
||||
protected override async Task<IEnumerable<ReleaseInfo>> PerformQuery(TorznabQuery query)
|
||||
|
|
|
@ -2,7 +2,6 @@ using System;
|
|||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
|
@ -23,7 +22,7 @@ namespace Jackett.Common.Indexers
|
|||
{
|
||||
private string LoginUrl => SiteLink + "user/account/login/";
|
||||
private string SearchUrl => SiteLink + "torrents/browse/list/";
|
||||
private new ConfigurationDataRecaptchaLogin configData => (ConfigurationDataRecaptchaLogin)base.configData;
|
||||
private new ConfigurationDataBasicLogin configData => (ConfigurationDataBasicLogin)base.configData;
|
||||
|
||||
public override string[] LegacySiteLinks { get; protected set; } =
|
||||
{
|
||||
|
@ -58,7 +57,7 @@ namespace Jackett.Common.Indexers
|
|||
client: wc,
|
||||
logger: l,
|
||||
p: ps,
|
||||
configData: new ConfigurationDataRecaptchaLogin(
|
||||
configData: new ConfigurationDataBasicLogin(
|
||||
"For best results, change the 'Default Number of Torrents per Page' setting to 100 in your Profile."))
|
||||
{
|
||||
Encoding = Encoding.UTF8;
|
||||
|
@ -119,58 +118,9 @@ namespace Jackett.Common.Indexers
|
|||
AddCategoryMapping(38, TorznabCatType.Other, "Education");
|
||||
}
|
||||
|
||||
public override async Task<ConfigurationData> GetConfigurationForSetup()
|
||||
{
|
||||
var loginPage = await RequestWithCookiesAsync(LoginUrl, string.Empty);
|
||||
var parser = new HtmlParser();
|
||||
var dom = parser.ParseDocument(loginPage.ContentString);
|
||||
var captcha = dom.QuerySelector(".g-recaptcha");
|
||||
if (captcha != null)
|
||||
{
|
||||
var result = configData;
|
||||
result.CookieHeader.Value = loginPage.Cookies;
|
||||
result.Captcha.SiteKey = captcha.GetAttribute("data-sitekey");
|
||||
result.Captcha.Version = "2";
|
||||
return result;
|
||||
}
|
||||
else
|
||||
{
|
||||
var result = new ConfigurationDataBasicLogin
|
||||
{
|
||||
SiteLink = { Value = configData.SiteLink.Value },
|
||||
Instructions = { Value = configData.Instructions.Value },
|
||||
Username = { Value = configData.Username.Value },
|
||||
Password = { Value = configData.Password.Value },
|
||||
CookieHeader = { Value = loginPage.Cookies }
|
||||
};
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
public override async Task<IndexerConfigurationStatus> ApplyConfiguration(JToken configJson)
|
||||
{
|
||||
LoadValuesFromJson(configJson);
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(configData.Captcha.Cookie))
|
||||
{
|
||||
CookieHeader = configData.Captcha.Cookie;
|
||||
try
|
||||
{
|
||||
var results = await PerformQuery(new TorznabQuery());
|
||||
if (!results.Any())
|
||||
throw new Exception("Found 0 results in the tracker");
|
||||
|
||||
IsConfigured = true;
|
||||
SaveConfig();
|
||||
return IndexerConfigurationStatus.Completed;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
IsConfigured = false;
|
||||
throw new Exception("Your cookie did not work: " + e.Message);
|
||||
}
|
||||
}
|
||||
|
||||
await DoLogin();
|
||||
return IndexerConfigurationStatus.RequiresTesting;
|
||||
}
|
||||
|
|
|
@ -6,7 +6,5 @@ namespace Jackett.Common.Models.DTO
|
|||
public string value { get; set; }
|
||||
public string[] values { get; set; } // for array data (e.g. checkboxes)
|
||||
public string cookie { get; set; } // for cookie alternative login (captcha needed + remote host)
|
||||
public string challenge { get; set; } // for reCaptcha V1 compatibility
|
||||
public string version { get; set; } // for reCaptcha V1 compatibility
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,22 +3,14 @@ using System.Diagnostics.CodeAnalysis;
|
|||
namespace Jackett.Common.Models.IndexerConfig.Bespoke
|
||||
{
|
||||
[ExcludeFromCodeCoverage]
|
||||
internal class ConfigurationDataSceneTime : ConfigurationData
|
||||
internal class ConfigurationDataSceneTime : ConfigurationDataCookie
|
||||
{
|
||||
public StringItem Username { get; private set; }
|
||||
public StringItem Password { get; private set; }
|
||||
public RecaptchaItem Captcha { get; private set; }
|
||||
public BoolItem Freeleech { get; private set; }
|
||||
public DisplayItem Instructions { get; private set; }
|
||||
|
||||
public ConfigurationDataSceneTime()
|
||||
: base()
|
||||
: base("For best results, change the 'Torrents per page' setting to the maximum in your profile on the SceneTime webpage.")
|
||||
{
|
||||
Username = new StringItem { Name = "Username" };
|
||||
Password = new StringItem { Name = "Password" };
|
||||
Captcha = new RecaptchaItem() { Name = "Recaptcha" };
|
||||
Freeleech = new BoolItem() { Name = "Freeleech Only (Optional)", Value = false };
|
||||
Instructions = new DisplayItem("For best results, change the 'Torrents per page' setting to the maximum in your profile on the SceneTime webpage.") { Name = "" };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,8 +20,7 @@ namespace Jackett.Common.Models.IndexerConfig
|
|||
InputSelect,
|
||||
DisplayImage,
|
||||
DisplayInfo,
|
||||
HiddenData,
|
||||
Recaptcha
|
||||
HiddenData
|
||||
}
|
||||
|
||||
public HiddenItem CookieHeader { get; private set; } = new HiddenItem { Name = "CookieHeader" };
|
||||
|
@ -89,12 +88,6 @@ namespace Jackett.Common.Models.IndexerConfig
|
|||
case ItemType.InputSelect:
|
||||
((SelectItem)item).Value = arrItem.Value<string>("value");
|
||||
break;
|
||||
case ItemType.Recaptcha:
|
||||
((RecaptchaItem)item).Value = arrItem.Value<string>("value");
|
||||
((RecaptchaItem)item).Cookie = arrItem.Value<string>("cookie");
|
||||
((RecaptchaItem)item).Version = arrItem.Value<string>("version");
|
||||
((RecaptchaItem)item).Challenge = arrItem.Value<string>("challenge");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -113,10 +106,6 @@ namespace Jackett.Common.Models.IndexerConfig
|
|||
};
|
||||
switch (item.ItemType)
|
||||
{
|
||||
case ItemType.Recaptcha:
|
||||
jObject["sitekey"] = ((RecaptchaItem)item).SiteKey;
|
||||
jObject["version"] = ((RecaptchaItem)item).Version;
|
||||
break;
|
||||
case ItemType.InputString:
|
||||
case ItemType.HiddenData:
|
||||
case ItemType.DisplayInfo:
|
||||
|
@ -181,7 +170,7 @@ namespace Jackett.Common.Models.IndexerConfig
|
|||
if (!forDisplay)
|
||||
{
|
||||
properties = properties
|
||||
.Where(p => p.ItemType == ItemType.HiddenData || p.ItemType == ItemType.InputBool || p.ItemType == ItemType.InputString || p.ItemType == ItemType.InputCheckbox || p.ItemType == ItemType.InputSelect || p.ItemType == ItemType.Recaptcha || p.ItemType == ItemType.DisplayInfo)
|
||||
.Where(p => p.ItemType == ItemType.HiddenData || p.ItemType == ItemType.InputBool || p.ItemType == ItemType.InputString || p.ItemType == ItemType.InputCheckbox || p.ItemType == ItemType.InputSelect || p.ItemType == ItemType.DisplayInfo)
|
||||
.ToList();
|
||||
}
|
||||
|
||||
|
@ -239,17 +228,6 @@ namespace Jackett.Common.Models.IndexerConfig
|
|||
public StringItem() => ItemType = ItemType.InputString;
|
||||
}
|
||||
|
||||
public class RecaptchaItem : StringItem
|
||||
{
|
||||
public string Version { get; set; }
|
||||
public string Challenge { get; set; }
|
||||
public RecaptchaItem()
|
||||
{
|
||||
Version = "2";
|
||||
ItemType = ItemType.Recaptcha;
|
||||
}
|
||||
}
|
||||
|
||||
public class BoolItem : Item
|
||||
{
|
||||
public bool Value { get; set; }
|
||||
|
|
|
@ -1,20 +0,0 @@
|
|||
namespace Jackett.Common.Models.IndexerConfig
|
||||
{
|
||||
public class ConfigurationDataRecaptchaLogin : ConfigurationData
|
||||
{
|
||||
public StringItem Username { get; private set; }
|
||||
public StringItem Password { get; private set; }
|
||||
public RecaptchaItem Captcha { get; private set; }
|
||||
public DisplayItem Instructions { get; private set; }
|
||||
|
||||
public ConfigurationDataRecaptchaLogin(string instructionMessageOptional = null)
|
||||
{
|
||||
Username = new StringItem { Name = "Username" };
|
||||
Password = new StringItem { Name = "Password" };
|
||||
Captcha = new RecaptchaItem() { Name = "Recaptcha" };
|
||||
Instructions = new DisplayItem(instructionMessageOptional) { Name = "" };
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
|
@ -76,7 +76,6 @@ namespace Jackett.Common.Models
|
|||
{
|
||||
public string Type { get; set; }
|
||||
public string Selector { get; set; }
|
||||
public string Image { get => throw new Exception("Deprecated, please use Login.Captcha.Selector instead"); set => throw new Exception("Deprecated, please use login/captcha/selector instead of image"); }
|
||||
public string Input { get; set; }
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue