diff --git a/templates/captcha_script.html b/templates/captcha_script.html index 79b0b230..c2f5d87f 100644 --- a/templates/captcha_script.html +++ b/templates/captcha_script.html @@ -1,6 +1,6 @@ -{% if config.hcaptcha %} +{% if config.captcha.mode == 'hcaptcha' %} {% endif %} -{% if config.turnstile %} +{% if config.captcha.mode == 'turnstile' %} {% endif %} diff --git a/templates/header.html b/templates/header.html index 7e3f9c54..27b1a31f 100644 --- a/templates/header.html +++ b/templates/header.html @@ -28,6 +28,6 @@ {% endif %} {% endif %} - {% if config.recaptcha %} + {% if config.captcha.mode == 'recaptcha' %} {% endif %} diff --git a/templates/main.js b/templates/main.js index c48a6ed3..574a3611 100755 --- a/templates/main.js +++ b/templates/main.js @@ -243,27 +243,46 @@ function getCookie(cookie_name) { {% endraw %} /* BEGIN CAPTCHA REGION */ -{% if config.hcaptcha or config.turnstile %} // If any captcha +{% if config.captcha.mode == 'hcaptcha' or config.captcha.mode == 'turnstile' %} // If any captcha // Global captcha object. Assigned by `onCaptchaLoad()`. var captcha_renderer = null; +// Captcha widget id of the post form. +var postCaptchaId = null; -{% if config.hcaptcha %} // If hcaptcha +{% if config.captcha.mode == 'hcaptcha' %} // If hcaptcha function onCaptchaLoadHcaptcha() { if (captcha_renderer === null && (active_page === 'index' || active_page === 'catalog' || active_page === 'thread')) { let renderer = { + /** + * @returns {object} Opaque widget id. + */ applyOn: (container, params) => hcaptcha.render(container, { - sitekey: "{{ config.hcaptcha_public }}", + sitekey: "{{ config.captcha.hcaptcha.public }}", callback: params['on-success'], }), + /** + * @returns {void} + */ remove: (widgetId) => { /* Not supported */ }, - reset: (widgetId) => hcaptcha.reset(widgetId) + /** + * @returns {void} + */ + reset: (widgetId) => hcaptcha.reset(widgetId), + /** + * @returns {bool} + */ + hasResponse: (widgetId) => !!hcaptcha.getResponse(widgetId), + /** + * @returns {void} + */ + execute: (widgetId) => hcaptcha.execute(widgetId) }; onCaptchaLoad(renderer); } } {% endif %} // End if hcaptcha -{% if config.turnstile %} // If turnstile +{% if config.captcha.mode == 'turnstile' %} // If turnstile // Wrapper function to be called from thread.html window.onCaptchaLoadTurnstile_post_reply = function() { @@ -279,9 +298,12 @@ window.onCaptchaLoadTurnstile_post_thread = function() { function onCaptchaLoadTurnstile(action) { if (captcha_renderer === null && (active_page === 'index' || active_page === 'catalog' || active_page === 'thread')) { let renderer = { + /** + * @returns {object} Opaque widget id. + */ applyOn: function(container, params) { let widgetId = turnstile.render('#' + container, { - sitekey: "{{ config.turnstile_public }}", + sitekey: "{{ config.captcha.turnstile.public }}", action: action, callback: params['on-success'], }); @@ -290,8 +312,22 @@ function onCaptchaLoadTurnstile(action) { } return widgetId; }, + /** + * @returns {void} + */ remove: (widgetId) => turnstile.remove(widgetId), - reset: (widgetId) => turnstile.reset(widgetId) + /** + * @returns {void} + */ + reset: (widgetId) => turnstile.reset(widgetId), + /** + * @returns {bool} + */ + hasResponse: (widgetId) => !!turnstile.getResponse(widgetId), + /** + * @returns {void} + */ + execute: (widgetId) => turnstile.execute(widgetId) }; onCaptchaLoad(renderer); @@ -313,6 +349,7 @@ function onCaptchaLoad(renderer) { if (widgetId === null) { console.error('Could not render captcha!'); } + postCaptchaId = widgetId; document.addEventListener('afterdopost', function(e) { // User posted! Reset the captcha. renderer.reset(widgetId); @@ -390,6 +427,11 @@ function doPost(form) { saved[document.location] = form.elements['body'].value; sessionStorage.body = JSON.stringify(saved); + if (captcha_renderer && postCaptchaId && !captcha_renderer.hasResponse(postCaptchaId)) { + captcha_renderer.execute(postCaptchaId); + return false; + } + // Needs to be delayed by at least 1 frame, otherwise it may reset the form (read captcha) fields before they're sent. setTimeout(() => document.dispatchEvent(new Event('afterdopost'))); return form.elements['body'].value != "" || (form.elements['file'] && form.elements['file'].value != "") || (form.elements.file_url && form.elements['file_url'].value != ""); diff --git a/templates/post_form.html b/templates/post_form.html index adca9ef6..6cb0ea7a 100644 --- a/templates/post_form.html +++ b/templates/post_form.html @@ -90,8 +90,8 @@ {% endif %} {% endif %} - {% if config.recaptcha %} - {% if config.dynamic_captcha %} + {% if config.captcha.mode == 'recaptcha' %} + {% if config.captcha.dynamic %}