@arnaudw38/nodebb-plugin-spam-be-gone 1.0.0 → 1.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/library.js +1 -1
- package/package.json +1 -1
- package/public/js/scripts.js +85 -2
package/README.md
CHANGED
|
@@ -26,7 +26,7 @@ Anti-spam plugin for **NodeBB 4.x** with **Cloudflare Turnstile** (Turnstile-onl
|
|
|
26
26
|
From your NodeBB root directory:
|
|
27
27
|
|
|
28
28
|
```bash
|
|
29
|
-
npm install nodebb-plugin-spam-be-gone
|
|
29
|
+
npm install @arnaudw38/nodebb-plugin-spam-be-gone
|
|
30
30
|
./nodebb build
|
|
31
31
|
./nodebb restart
|
|
32
32
|
```
|
package/library.js
CHANGED
|
@@ -199,7 +199,7 @@ Plugin.addCaptcha = async (data) => {
|
|
|
199
199
|
if (turnstile) {
|
|
200
200
|
data.templateData.turnstileArgs = turnstile;
|
|
201
201
|
addChallenge(data.templateData, turnstile.addLoginTurnstile, {
|
|
202
|
-
label: '
|
|
202
|
+
label: 'Vérification de sécurité',
|
|
203
203
|
html: `<div id="${turnstile.targetId}"></div>`,
|
|
204
204
|
styleName: pluginData.nbbId,
|
|
205
205
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@arnaudw38/nodebb-plugin-spam-be-gone",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.2",
|
|
4
4
|
"description": "Anti-spam plugin for NodeBB 4.x using Akismet, StopForumSpam, ProjectHoneyPot, and Cloudflare Turnstile (Turnstile-only fork)",
|
|
5
5
|
"main": "library.js",
|
|
6
6
|
"scripts": {},
|
package/public/js/scripts.js
CHANGED
|
@@ -5,6 +5,10 @@
|
|
|
5
5
|
$(function () {
|
|
6
6
|
var pluginName = 'spam-be-gone';
|
|
7
7
|
var turnstileScriptUrl = 'https://challenges.cloudflare.com/turnstile/v0/api.js?render=explicit';
|
|
8
|
+
var turnstileState = {
|
|
9
|
+
widgets: {},
|
|
10
|
+
loginBindingsAttached: false,
|
|
11
|
+
};
|
|
8
12
|
|
|
9
13
|
function getTurnstileArgs() {
|
|
10
14
|
return ajaxify.data && ajaxify.data.turnstileArgs;
|
|
@@ -25,6 +29,67 @@ $(function () {
|
|
|
25
29
|
});
|
|
26
30
|
}
|
|
27
31
|
|
|
32
|
+
function getCurrentTurnstileResponse() {
|
|
33
|
+
var input = document.querySelector('input[name="cf-turnstile-response"]');
|
|
34
|
+
return input && input.value;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function resetTurnstileWidget(targetId) {
|
|
38
|
+
if (typeof turnstile === 'undefined') {
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
var widgetId = turnstileState.widgets[targetId];
|
|
42
|
+
if (widgetId === undefined || widgetId === null) {
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
try {
|
|
46
|
+
turnstile.reset(widgetId);
|
|
47
|
+
} catch (err) {
|
|
48
|
+
// Ignore reset errors when the widget is already destroyed by navigation.
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function scheduleLoginTurnstileReset(targetId) {
|
|
53
|
+
// Turnstile tokens are single-use. On failed login, NodeBB keeps the user on the
|
|
54
|
+
// same page, so we refresh the widget shortly after submit to allow a retry.
|
|
55
|
+
[1200, 3000].forEach(function (delay) {
|
|
56
|
+
window.setTimeout(function () {
|
|
57
|
+
if (ajaxify.data && ajaxify.data.template && ajaxify.data.template.name && ajaxify.data.template.name !== 'login') {
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
if (!document.getElementById(targetId)) {
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
if (getCurrentTurnstileResponse()) {
|
|
64
|
+
resetTurnstileWidget(targetId);
|
|
65
|
+
}
|
|
66
|
+
}, delay);
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
function bindLoginRetryReset(targetId) {
|
|
71
|
+
if (turnstileState.loginBindingsAttached) {
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
turnstileState.loginBindingsAttached = true;
|
|
75
|
+
|
|
76
|
+
$(document)
|
|
77
|
+
.off('submit.spamBeGoneTurnstileLogin')
|
|
78
|
+
.on('submit.spamBeGoneTurnstileLogin', 'form[action="/login"], form[data-action="login"], #login', function () {
|
|
79
|
+
scheduleLoginTurnstileReset(targetId);
|
|
80
|
+
})
|
|
81
|
+
.off('click.spamBeGoneTurnstileLogin')
|
|
82
|
+
.on('click.spamBeGoneTurnstileLogin', '[component="login/submit"]', function () {
|
|
83
|
+
scheduleLoginTurnstileReset(targetId);
|
|
84
|
+
})
|
|
85
|
+
.off('input.spamBeGoneTurnstileLogin change.spamBeGoneTurnstileLogin')
|
|
86
|
+
.on('input.spamBeGoneTurnstileLogin change.spamBeGoneTurnstileLogin', 'input[name="username"], input[name="password"]', function () {
|
|
87
|
+
if (document.getElementById(targetId) && getCurrentTurnstileResponse()) {
|
|
88
|
+
resetTurnstileWidget(targetId);
|
|
89
|
+
}
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
|
|
28
93
|
function renderTurnstileIfNeeded(isLoginPage) {
|
|
29
94
|
var args = getTurnstileArgs();
|
|
30
95
|
if (!args || (isLoginPage && !args.addLoginTurnstile)) {
|
|
@@ -37,10 +102,18 @@ $(function () {
|
|
|
37
102
|
return;
|
|
38
103
|
}
|
|
39
104
|
var target = document.getElementById(args.targetId);
|
|
40
|
-
if (!target
|
|
105
|
+
if (!target) {
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
if (target.dataset.turnstileRendered === '1') {
|
|
110
|
+
if (isLoginPage) {
|
|
111
|
+
bindLoginRetryReset(args.targetId);
|
|
112
|
+
}
|
|
41
113
|
return;
|
|
42
114
|
}
|
|
43
|
-
|
|
115
|
+
|
|
116
|
+
var widgetId = turnstile.render('#' + args.targetId, {
|
|
44
117
|
sitekey: args.siteKey,
|
|
45
118
|
theme: args.theme || 'auto',
|
|
46
119
|
size: args.size || 'normal',
|
|
@@ -55,8 +128,18 @@ $(function () {
|
|
|
55
128
|
'error-callback': function () {
|
|
56
129
|
require(['alerts'], function (alerts) { alerts.error('[[spam-be-gone:captcha-not-verified]]'); });
|
|
57
130
|
},
|
|
131
|
+
'expired-callback': function () {
|
|
132
|
+
resetTurnstileWidget(args.targetId);
|
|
133
|
+
},
|
|
134
|
+
'timeout-callback': function () {
|
|
135
|
+
resetTurnstileWidget(args.targetId);
|
|
136
|
+
},
|
|
58
137
|
});
|
|
59
138
|
target.dataset.turnstileRendered = '1';
|
|
139
|
+
turnstileState.widgets[args.targetId] = widgetId;
|
|
140
|
+
if (isLoginPage) {
|
|
141
|
+
bindLoginRetryReset(args.targetId);
|
|
142
|
+
}
|
|
60
143
|
})
|
|
61
144
|
.catch(function () {
|
|
62
145
|
require(['alerts'], function (alerts) { alerts.error('Failed to load Cloudflare Turnstile'); });
|