1
0
Fork 0
mirror of https://github.com/Jackett/Jackett synced 2025-02-24 15:21:06 +00:00

Implement recaptcha for torrentday (This will only work for localhost)

This commit is contained in:
KZ 2015-08-08 00:15:42 +01:00
parent 6ea759aeab
commit d1ff05ac13
7 changed files with 172 additions and 100 deletions

View file

@ -197,8 +197,8 @@ function reloadIndexers() {
}
function displayIndexers(items) {
var indexerTemplate = Handlebars.compile($("#templates > .configured-indexer")[0].outerHTML);
var unconfiguredIndexerTemplate = Handlebars.compile($("#templates > .unconfigured-indexer")[0].outerHTML);
var indexerTemplate = Handlebars.compile($("#configured-indexer").html());
var unconfiguredIndexerTemplate = Handlebars.compile($("#unconfigured-indexer").html());
for (var i = 0; i < items.length; i++) {
var item = items[i];
item.torznab_host = resolveUrl("/torznab/" + item.id);
@ -209,7 +209,7 @@ function displayIndexers(items) {
$('#unconfigured-indexers').append($(unconfiguredIndexerTemplate(item)));
}
var addIndexerButton = $("#templates > .add-indexer")[0].outerHTML;
var addIndexerButton = $('#add-indexer').html();
$('#indexers').append(addIndexerButton);
$('#indexers').fadeIn();
@ -293,12 +293,22 @@ function populateConfigItems(configForm, config) {
}
var $formItemContainer = configForm.find(".config-setup-form");
$formItemContainer.empty();
var setupItemTemplate = Handlebars.compile($("#templates > .setup-item")[0].outerHTML);
var setupItemTemplate = Handlebars.compile($("#setup-item").html());
for (var i = 0; i < config.length; i++) {
var item = config[i];
var setupValueTemplate = Handlebars.compile($("#templates > .setup-item-" + item.type)[0].outerHTML);
var setupValueTemplate = Handlebars.compile($("#setup-item-" + item.type).html());
item.value_element = setupValueTemplate(item);
$formItemContainer.append(setupItemTemplate(item));
var template = setupItemTemplate(item);
$formItemContainer.append(template);
if (item.type === 'recaptcha') {
grecaptcha.render($('.jackettrecaptcha')[0], {
'sitekey': item.sitekey
});
}
}
}
@ -327,6 +337,9 @@ function getConfigModalJson(configForm) {
case "inputbool":
itemEntry.value = $el.find(".setup-item-inputbool input").is(":checked");
break;
case "recaptcha":
itemEntry.value = $('.g-recaptcha-response').val();
break;
}
configJson.push(itemEntry)
});
@ -342,7 +355,7 @@ function populateSetupForm(indexerId, name, config, caps) {
var originalBtnText = $goButton.html();
$goButton.prop('disabled', true);
$goButton.html($('#templates > .spinner')[0].outerHTML);
$goButton.html($('#spinner').html());
var jqxhr = $.post("/admin/configure_indexer", JSON.stringify(data), function (data) {
if (data.result == "error") {

View file

@ -13,6 +13,7 @@
<script src="/libs/handlebarsmoment.js"></script>
<script src="/bootstrap/bootstrap.min.js"></script>
<script src="/libs/bootstrap-notify.js"></script>
<script src='https://www.google.com/recaptcha/api.js'></script>
<link href="/bootstrap/bootstrap.min.css" rel="stylesheet">
<link href="/animate.css" rel="stylesheet">
@ -20,6 +21,85 @@
<link href="/css/jquery.dataTables.css" rel="stylesheet">
<link rel="stylesheet" href="/css/font-awesome.min.css">
<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>
<div class="setup-item-value">{{{value_element}}}</div>
</div>
</script>
<script id="setup-item-inputstring" type="text/x-handlebars-template">
<div class="setup-item-inputstring">
{{#if ispassword}}
<input class="form-control" type="password" value="{{{value}}}" />
{{else}}
<input class="form-control" type="text" value="{{{value}}}" />
{{/if}}
</div>
</script>
<script id="setup-item-inputbool" type="text/x-handlebars-template">
<div class="setup-item-inputbool">
{{#if value}}
<input type="checkbox" data-id="{{id}}" class="form-control" checked />
{{else}}
<input type="checkbox" data-id="{{id}}" class="form-control" />
{{/if}}
</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}}}" />
</script>
<script id="setup-item-displayinfo" type="text/x-handlebars-template">
<div class="setup-item-displayinfo alert alert-info" role="alert">{{{value}}}</div>
</script>
<script id="setup-item-hiddendata" type="text/x-handlebars-template">
<div class="setup-item-hiddendata">
<input class="form-control" type="text" value="{{{value}}}" />
</div>
</script>
<script id="configured-indexer" type="text/x-handlebars-template">
<div class="configured-indexer indexer card">
<div class="indexer-logo"><img alt="{{name}}" title="{{name}}" src="/logos/{{id}}.png" /></div>
<div class="indexer-buttons">
<button class="btn btn-primary btn-sm indexer-setup" data-id="{{id}}">
<span class="glyphicon glyphicon-wrench" aria-hidden="true"></span>
</button>
<button class="btn btn-danger btn-sm indexer-button-delete" data-id="{{id}}">
<span class="glyphicon glyphicon-trash" aria-hidden="true"></span>
</button>
<a class="btn btn-info btn-sm" target="_blank" href="{{site_link}}">
<span class="glyphicon glyphicon-new-window" aria-hidden="true"></span>
</a>
<button class="btn btn-warning btn-sm indexer-button-test" data-id="{{id}}">
Test <span class="glyphicon glyphicon-screenshot" aria-hidden="true"></span>
</button>
</div>
<div class="indexer-host">
<b>Torznab Host:</b>
<input class="form-control" type="text" value="{{torznab_host}}" placeholder="Torznab Host" readonly="">
<b>CouchPotato Host:</b>
{{#if potatoenabled}}
<input class="form-control" type="text" value="{{potato_host}}" placeholder="Torznab Host" readonly="">
{{else}}
<input class="form-control" type="text" value="Not availible" placeholder="Torznab Host" readonly="">
{{/if}}
</div>
</div>
</script>
<script id="unconfigured-indexer" type="text/x-handlebars-template">
<div class="unconfigured-indexer card">
<div class="indexer-logo"><img alt="{{name}}" title="{{name}}" src="/logos/{{id}}.png" /></div>
<div class="indexer-buttons">
<a class="btn btn-info" target="_blank" href="{{site_link}}">Visit <span class="glyphicon glyphicon-new-window" aria-hidden="true"></span></a>
<button class="indexer-setup btn btn-success" data-id="{{id}}">Setup <span class="glyphicon glyphicon-ok" aria-hidden="true"></span></button>
</div>
</div>
</script>
<script id="jackett-releases" type="text/x-handlebars-template">
<div id="select-indexer-modal" class="modal fade" tabindex="-1" role="dialog" aria-hidden="true">
<div class="modal-dialog modal-lg modal-fillwidth">
@ -164,6 +244,17 @@
</div>
</div>
</script>
<script id="add-indexer" type="text/x-handlebars-template">
<button class="indexer card add-indexer" data-toggle="modal" data-target="#select-indexer-modal">
<div class="indexer-add-content">
<span class="glyphicon glyphicon glyphicon-plus" aria-hidden="true"></span>
<div class="light-text">Add</div>
</div>
</button>
</script>
<script id="spinner" type="text/x-handlebars-template">
<span class="spinner glyphicon glyphicon-refresh"></span>
</script>
<title>Jackett</title>
</head>
@ -248,85 +339,6 @@
</div>
<div id="modals"></div>
<div id="templates">
<button class="indexer card add-indexer" data-toggle="modal" data-target="#select-indexer-modal">
<div class="indexer-add-content">
<span class="glyphicon glyphicon glyphicon-plus" aria-hidden="true"></span>
<div class="light-text">Add</div>
</div>
</button>
<div class="configured-indexer indexer card">
<div class="indexer-logo"><img alt="{{name}}" title="{{name}}" src="/logos/{{id}}.png" /></div>
<div class="indexer-buttons">
<button class="btn btn-primary btn-sm indexer-setup" data-id="{{id}}">
<span class="glyphicon glyphicon-wrench" aria-hidden="true"></span>
</button>
<button class="btn btn-danger btn-sm indexer-button-delete" data-id="{{id}}">
<span class="glyphicon glyphicon-trash" aria-hidden="true"></span>
</button>
<a class="btn btn-info btn-sm" target="_blank" href="{{site_link}}">
<span class="glyphicon glyphicon-new-window" aria-hidden="true"></span>
</a>
<button class="btn btn-warning btn-sm indexer-button-test" data-id="{{id}}">
Test <span class="glyphicon glyphicon-screenshot" aria-hidden="true"></span>
</button>
</div>
<div class="indexer-host">
<b>Torznab Host:</b>
<input class="form-control" type="text" value="{{torznab_host}}" placeholder="Torznab Host" readonly="">
<b>CouchPotato Host:</b>
{{#if potatoenabled}}
<input class="form-control" type="text" value="{{potato_host}}" placeholder="Torznab Host" readonly="">
{{else}}
<input class="form-control" type="text" value="Not availible" placeholder="Torznab Host" readonly="">
{{/if}}
</div>
</div>
<div class="unconfigured-indexer card">
<div class="indexer-logo"><img alt="{{name}}" title="{{name}}" src="/logos/{{id}}.png" /></div>
<div class="indexer-buttons">
<a class="btn btn-info" target="_blank" href="{{site_link}}">Visit <span class="glyphicon glyphicon-new-window" aria-hidden="true"></span></a>
<button class="indexer-setup btn btn-success" data-id="{{id}}">Setup <span class="glyphicon glyphicon-ok" aria-hidden="true"></span></button>
</div>
</div>
<div class="setup-item form-group" data-id="{{id}}" data-value="{{value}}" data-type="{{type}}">
<div class="setup-item-label">{{name}}</div>
<div class="setup-item-value">{{{value_element}}}</div>
</div>
<div class="setup-item-inputstring">
{{#if ispassword}}
<input class="form-control" type="password" value="{{{value}}}" />
{{else}}
<input class="form-control" type="text" value="{{{value}}}" />
{{/if}}
</div>
<div class="setup-item-inputbool">
{{#if value}}
<input type="checkbox" data-id="{{id}}" class="form-control" checked />
{{else}}
<input type="checkbox" data-id="{{id}}" class="form-control" />
{{/if}}
</div>
<img class="setup-item-displayimage" src="{{{value}}}" />
<div class="setup-item-displayinfo alert alert-info" role="alert">{{{value}}}</div>
<div class="setup-item-hiddendata">
<input class="form-control" type="text" value="{{{value}}}" />
</div>
<span class="spinner glyphicon glyphicon-refresh"></span>
</div>
<script src="/custom.js"></script>
</body>
</html>

View file

@ -30,5 +30,4 @@ Handlebars.registerHelper('jacketTimespan', function (context, block) {
var years = timeSpan.asYears();
return Math.round(years) + 'y ago';
});
});

View file

@ -25,9 +25,9 @@ namespace Jackett.Indexers
private string LoginUrl { get { return SiteLink + "tak3login.php"; } }
private string SearchUrl { get { return SiteLink + "browse.php"; } }
new ConfigurationDataBasicLogin configData
new ConfigurationDataRecaptchaLogin configData
{
get { return (ConfigurationDataBasicLogin)base.configData; }
get { return (ConfigurationDataRecaptchaLogin)base.configData; }
set { base.configData = value; }
}
@ -40,7 +40,7 @@ namespace Jackett.Indexers
client: wc,
logger: l,
p: ps,
configData: new ConfigurationDataBasicLogin())
configData: new ConfigurationDataRecaptchaLogin())
{
AddCategoryMapping(29, TorznabCatType.Anime);
@ -84,19 +84,26 @@ namespace Jackett.Indexers
AddCategoryMapping(15, TorznabCatType.XXX);
}
public override async Task<ConfigurationData> GetConfigurationForSetup()
{
var loginPage = await RequestStringWithCookies(StartPageUrl, string.Empty);
CQ cq = loginPage.Content;
var result = new ConfigurationDataRecaptchaLogin();
result.CookieHeader.Value = loginPage.Cookies;
result.Captcha.SiteKey = cq.Find(".g-recaptcha").Attr("data-sitekey");
return result;
}
public async Task ApplyConfiguration(JToken configJson)
{
configData.LoadValuesFromJson(configJson);
var startMessage = await RequestStringWithCookies(StartPageUrl, string.Empty);
var pairs = new Dictionary<string, string> {
{ "username", configData.Username.Value },
{ "password", configData.Password.Value }
{ "password", configData.Password.Value },
{ "g-recaptcha-response", configData.Captcha.Value }
};
var result = await RequestLoginAndFollowRedirect(LoginUrl, pairs, null, true, SiteLink, LoginUrl);
var result = await RequestLoginAndFollowRedirect(LoginUrl, pairs, configData.CookieHeader.Value, true, SiteLink, LoginUrl);
await ConfigureIfOK(result.Cookies, result.Content != null && result.Content.Contains("logout.php"), () =>
{
CQ dom = result.Content;

View file

@ -213,6 +213,7 @@
<Compile Include="Models\CachedLog.cs" />
<Compile Include="Models\CachedResult.cs" />
<Compile Include="Models\CategoryMapping.cs" />
<Compile Include="Models\IndexerConfig\ConfigurationDataRecaptchaLogin.cs" />
<Compile Include="Models\IndexerConfig\ConfigurationDataLoginTokin.cs" />
<Compile Include="Models\IndexerConfig\ConfigurationDataNCore.cs" />
<Compile Include="Models\IndexerConfig\ConfigurationDataCaptchaLogin.cs" />

View file

@ -20,7 +20,8 @@ namespace Jackett.Models.IndexerConfig
InputBool,
DisplayImage,
DisplayInfo,
HiddenData
HiddenData,
Recaptcha
}
public HiddenItem CookieHeader { get; private set; } = new HiddenItem { Name = "CookieHeader" };
@ -69,6 +70,9 @@ namespace Jackett.Models.IndexerConfig
case ItemType.InputBool:
((BoolItem)item).Value = arrItem.Value<bool>("value");
break;
case ItemType.Recaptcha:
((RecaptchaItem)item).Value = arrItem.Value<string>("value");
break;
}
}
}
@ -85,6 +89,9 @@ namespace Jackett.Models.IndexerConfig
jObject["name"] = item.Name;
switch (item.ItemType)
{
case ItemType.Recaptcha:
jObject["sitekey"] = ((RecaptchaItem)item).SiteKey;
break;
case ItemType.InputString:
case ItemType.HiddenData:
case ItemType.DisplayInfo:
@ -98,7 +105,6 @@ namespace Jackett.Models.IndexerConfig
else if (ps != null)
value = ps.Protect(value);
}
jObject["value"] = value;
break;
case ItemType.InputBool:
@ -125,7 +131,7 @@ namespace Jackett.Models.IndexerConfig
if (!forDisplay)
{
properties = properties
.Where(p => p.ItemType == ItemType.HiddenData || p.ItemType == ItemType.InputBool || p.ItemType == ItemType.InputString)
.Where(p => p.ItemType == ItemType.HiddenData || p.ItemType == ItemType.InputBool || p.ItemType == ItemType.InputString || p.ItemType == ItemType.Recaptcha)
.ToArray();
}
@ -159,6 +165,7 @@ namespace Jackett.Models.IndexerConfig
public class StringItem : Item
{
public string SiteKey { get; set; }
public string Value { get; set; }
public StringItem()
{
@ -166,6 +173,14 @@ namespace Jackett.Models.IndexerConfig
}
}
public class RecaptchaItem : StringItem
{
public RecaptchaItem()
{
ItemType = ConfigurationData.ItemType.Recaptcha;
}
}
public class BoolItem : Item
{
public bool Value { get; set; }

View file

@ -0,0 +1,25 @@
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Jackett.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 ConfigurationDataRecaptchaLogin()
{
Username = new StringItem { Name = "Username" };
Password = new StringItem { Name = "Password" };
Captcha = new RecaptchaItem() { Name = "Recaptcha" };
}
}
}