@arnaudw38/nodebb-plugin-spam-be-gone 1.0.2 → 1.0.3
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/CHANGELOG.md +34 -0
- package/library.js +68 -7
- package/package.json +5 -5
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
|
4
|
+
|
|
5
|
+
## [1.0.3] - 2026-02-25
|
|
6
|
+
|
|
7
|
+
### Fixed
|
|
8
|
+
- Fixed Cloudflare Turnstile failure on login retry without page reload.
|
|
9
|
+
- Reset Turnstile widget automatically after a failed login attempt (Turnstile tokens are single-use).
|
|
10
|
+
- Improved login flow reliability when users retry authentication on the same page.
|
|
11
|
+
|
|
12
|
+
### Improved
|
|
13
|
+
- Added safer Turnstile widget state handling on the login form.
|
|
14
|
+
- Added callbacks handling for expired/timeout token states.
|
|
15
|
+
- Better UX during repeated login attempts without manual refresh.
|
|
16
|
+
- Removed deprecated `stopforumspam` npm dependency and replaced it with direct StopForumSpam API requests using native `fetch` (eliminates `q` / `node-domexception` install warnings).
|
|
17
|
+
|
|
18
|
+
## [1.0.2] - 2026-02-25
|
|
19
|
+
|
|
20
|
+
### UI
|
|
21
|
+
- Replaced visible 'Turnstile' label with a more user-friendly label:
|
|
22
|
+
- French: `Vérification de sécurité`
|
|
23
|
+
|
|
24
|
+
## [1.0.1] - 2026-02-25
|
|
25
|
+
|
|
26
|
+
### Changed
|
|
27
|
+
- Refactored plugin for NodeBB 4.x compatibility.
|
|
28
|
+
- Removed legacy reCAPTCHA and hCaptcha integrations.
|
|
29
|
+
- Added Cloudflare Turnstile support (register + optional login protection).
|
|
30
|
+
- Simplified package/tooling for a minimal runtime-focused plugin setup.
|
|
31
|
+
|
|
32
|
+
### Docs
|
|
33
|
+
- Rewrote README in English (Turnstile-only, no images).
|
|
34
|
+
- Added npm-ready/publish-ready package metadata and documentation.
|
package/library.js
CHANGED
|
@@ -4,7 +4,6 @@ const util = require('util');
|
|
|
4
4
|
const https = require('https');
|
|
5
5
|
const querystring = require('querystring');
|
|
6
6
|
const Honeypot = require('project-honeypot');
|
|
7
|
-
const stopforumspam = require('stopforumspam');
|
|
8
7
|
|
|
9
8
|
const winston = require.main.require('winston');
|
|
10
9
|
const nconf = require.main.require('nconf');
|
|
@@ -100,9 +99,6 @@ Plugin.load = async function (params) {
|
|
|
100
99
|
if (!settings.akismetMinReputationHam) {
|
|
101
100
|
settings.akismetMinReputationHam = 10;
|
|
102
101
|
}
|
|
103
|
-
if (settings.stopforumspamApiKey) {
|
|
104
|
-
stopforumspam.Key(settings.stopforumspamApiKey);
|
|
105
|
-
}
|
|
106
102
|
|
|
107
103
|
pluginSettings = settings;
|
|
108
104
|
|
|
@@ -137,7 +133,7 @@ Plugin.report = async function (req, res, next) {
|
|
|
137
133
|
if (isAdmin) {
|
|
138
134
|
return res.status(403).send({ message: '[[spam-be-gone:cant-report-admin]]' });
|
|
139
135
|
}
|
|
140
|
-
await
|
|
136
|
+
await stopForumSpamSubmit({ ip: ips[0], email: fields.email, username: fields.username }, `Manual submission from user: ${req.uid} to user: ${fields.uid} via ${pluginData.id}`);
|
|
141
137
|
res.status(200).json({ message: '[[spam-be-gone:user-reported]]' });
|
|
142
138
|
} catch (err) {
|
|
143
139
|
winston.error(`[plugins/${pluginData.nbbId}][report-error] ${err.message}`);
|
|
@@ -152,7 +148,7 @@ Plugin.reportFromQueue = async (req, res) => {
|
|
|
152
148
|
}
|
|
153
149
|
const submitData = { ip: data.ip, email: data.email, username: data.username };
|
|
154
150
|
try {
|
|
155
|
-
await
|
|
151
|
+
await stopForumSpamSubmit(submitData, `Manual submission from user: ${req.uid} to user: ${data.username} via ${pluginData.id}`);
|
|
156
152
|
res.status(200).json({ message: '[[spam-be-gone:user-reported]]' });
|
|
157
153
|
} catch (err) {
|
|
158
154
|
winston.error(`[plugins/${pluginData.nbbId}][report-error] ${err.message}\n${JSON.stringify(submitData, null, 4)}`);
|
|
@@ -283,7 +279,7 @@ Plugin.getRegistrationQueue = async function (data) {
|
|
|
283
279
|
async function augmentWitSpamData(user) {
|
|
284
280
|
try {
|
|
285
281
|
user.ip = user.ip.replace('::ffff:', '');
|
|
286
|
-
let body = await
|
|
282
|
+
let body = await stopForumSpamLookup({ ip: user.ip, email: user.email, username: user.username });
|
|
287
283
|
if (!body) {
|
|
288
284
|
body = { success: 1, username: { frequency: 0, appears: 0 }, email: { frequency: 0, appears: 0 }, ip: { frequency: 0, appears: 0, asn: null } };
|
|
289
285
|
}
|
|
@@ -396,6 +392,71 @@ Plugin._turnstileCheck = async function (req) {
|
|
|
396
392
|
});
|
|
397
393
|
};
|
|
398
394
|
|
|
395
|
+
|
|
396
|
+
async function stopForumSpamLookup({ ip, email, username }) {
|
|
397
|
+
const params = new URLSearchParams();
|
|
398
|
+
params.set('f', 'json');
|
|
399
|
+
if (ip) params.set('ip', ip);
|
|
400
|
+
if (email) params.set('email', email);
|
|
401
|
+
if (username) params.set('username', username);
|
|
402
|
+
|
|
403
|
+
const res = await fetch(`https://api.stopforumspam.org/api?${params.toString()}`, {
|
|
404
|
+
headers: {
|
|
405
|
+
accept: 'application/json',
|
|
406
|
+
'user-agent': pluginData.id,
|
|
407
|
+
},
|
|
408
|
+
});
|
|
409
|
+
|
|
410
|
+
if (!res.ok) {
|
|
411
|
+
throw new Error(`StopForumSpam lookup failed (${res.status})`);
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
return await res.json();
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
async function stopForumSpamSubmit({ ip, email, username }, evidence) {
|
|
418
|
+
if (!pluginSettings.stopforumspamApiKey) {
|
|
419
|
+
throw new Error('[[spam-be-gone:sfs-api-key-not-set]]');
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
const body = new URLSearchParams();
|
|
423
|
+
body.set('api_key', pluginSettings.stopforumspamApiKey);
|
|
424
|
+
body.set('api', 'json');
|
|
425
|
+
if (ip) body.set('ip_addr', ip);
|
|
426
|
+
if (email) body.set('email', email);
|
|
427
|
+
if (username) body.set('username', username);
|
|
428
|
+
if (evidence) body.set('evidence', evidence);
|
|
429
|
+
|
|
430
|
+
const res = await fetch('https://www.stopforumspam.com/add.php', {
|
|
431
|
+
method: 'POST',
|
|
432
|
+
headers: {
|
|
433
|
+
'content-type': 'application/x-www-form-urlencoded',
|
|
434
|
+
accept: 'application/json, text/plain;q=0.9, */*;q=0.8',
|
|
435
|
+
'user-agent': pluginData.id,
|
|
436
|
+
},
|
|
437
|
+
body: body.toString(),
|
|
438
|
+
});
|
|
439
|
+
|
|
440
|
+
const text = await res.text();
|
|
441
|
+
if (!res.ok) {
|
|
442
|
+
throw new Error(`StopForumSpam submit failed (${res.status})`);
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
try {
|
|
446
|
+
const parsed = JSON.parse(text);
|
|
447
|
+
if (parsed.success === 0 || parsed.error) {
|
|
448
|
+
throw new Error(parsed.error || 'StopForumSpam submit failed');
|
|
449
|
+
}
|
|
450
|
+
return parsed;
|
|
451
|
+
} catch (err) {
|
|
452
|
+
// Some SFS responses can be plain text; consider HTTP 200 success as accepted.
|
|
453
|
+
if (/error/i.test(text)) {
|
|
454
|
+
throw err instanceof Error ? err : new Error('StopForumSpam submit failed');
|
|
455
|
+
}
|
|
456
|
+
return { success: 1, raw: text };
|
|
457
|
+
}
|
|
458
|
+
}
|
|
459
|
+
|
|
399
460
|
Plugin.admin = {
|
|
400
461
|
menu: function (custom_header, callback) {
|
|
401
462
|
custom_header.plugins.push({ route: `/plugins/${pluginData.nbbId}`, icon: pluginData.faIcon, name: pluginData.name });
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@arnaudw38/nodebb-plugin-spam-be-gone",
|
|
3
|
-
"version": "1.0.
|
|
4
|
-
"description": "Anti-spam plugin for NodeBB 4.x using Akismet, StopForumSpam, ProjectHoneyPot, and Cloudflare Turnstile (Turnstile-only fork)",
|
|
3
|
+
"version": "1.0.3",
|
|
4
|
+
"description": "Anti-spam plugin for NodeBB 4.x using Akismet, StopForumSpam API, ProjectHoneyPot, and Cloudflare Turnstile (Turnstile-only fork)",
|
|
5
5
|
"main": "library.js",
|
|
6
6
|
"scripts": {},
|
|
7
7
|
"repository": {
|
|
@@ -33,8 +33,7 @@
|
|
|
33
33
|
},
|
|
34
34
|
"dependencies": {
|
|
35
35
|
"async": "^3.2.0",
|
|
36
|
-
"project-honeypot": "~0.0.0"
|
|
37
|
-
"stopforumspam": "^1.3.8"
|
|
36
|
+
"project-honeypot": "~0.0.0"
|
|
38
37
|
},
|
|
39
38
|
"nbbpm": {
|
|
40
39
|
"compatibility": "^4.0.0"
|
|
@@ -50,7 +49,8 @@
|
|
|
50
49
|
"upgrades/",
|
|
51
50
|
"plugin.json",
|
|
52
51
|
"README.md",
|
|
53
|
-
"LICENSE"
|
|
52
|
+
"LICENSE",
|
|
53
|
+
"CHANGELOG.md"
|
|
54
54
|
],
|
|
55
55
|
"publishConfig": {
|
|
56
56
|
"access": "public"
|