Version Description
Release Date - 26 July 2022
- Added a new feature to catch spammers by observing how they interact with the page.
Download this release
Release Info
Developer | cfinke |
Plugin | Akismet Anti-Spam |
Version | 5.0 |
Comparing to | |
See all releases |
Code changes from version 4.2.5 to 5.0
- .htaccess +1 -1
- _inc/akismet-frontend.js +332 -0
- akismet.php +2 -2
- class.akismet.php +36 -6
- readme.txt +6 -1
.htaccess
CHANGED
@@ -12,7 +12,7 @@
|
|
12 |
</IfModule>
|
13 |
|
14 |
# Akismet CSS and JS
|
15 |
-
<FilesMatch "^(form\.js|akismet\.js|akismet\.css)$">
|
16 |
<IfModule !mod_authz_core.c>
|
17 |
Allow from all
|
18 |
</IfModule>
|
12 |
</IfModule>
|
13 |
|
14 |
# Akismet CSS and JS
|
15 |
+
<FilesMatch "^(form\.js|akismet\.js|akismet-frontend\.js|akismet\.css)$">
|
16 |
<IfModule !mod_authz_core.c>
|
17 |
Allow from all
|
18 |
</IfModule>
|
_inc/akismet-frontend.js
ADDED
@@ -0,0 +1,332 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
/**
|
2 |
+
* Observe how the user enters content into the comment form in order to determine whether it's a bot or not.
|
3 |
+
*
|
4 |
+
* Note that no actual input is being saved here, only counts and timings between events.
|
5 |
+
*/
|
6 |
+
|
7 |
+
( function() {
|
8 |
+
function init() {
|
9 |
+
var input_begin = '';
|
10 |
+
|
11 |
+
var keydowns = {};
|
12 |
+
var lastKeyup = null;
|
13 |
+
var lastKeydown = null;
|
14 |
+
var keypresses = [];
|
15 |
+
|
16 |
+
var modifierKeys = [];
|
17 |
+
var correctionKeys = [];
|
18 |
+
|
19 |
+
var lastMouseup = null;
|
20 |
+
var lastMousedown = null;
|
21 |
+
var mouseclicks = [];
|
22 |
+
|
23 |
+
var mousemoveTimer = null;
|
24 |
+
var lastMousemoveX = null;
|
25 |
+
var lastMousemoveY = null;
|
26 |
+
var mousemoveStart = null;
|
27 |
+
var mousemoves = [];
|
28 |
+
|
29 |
+
var touchmoveCountTimer = null;
|
30 |
+
var touchmoveCount = 0;
|
31 |
+
|
32 |
+
var lastTouchEnd = null;
|
33 |
+
var lastTouchStart = null;
|
34 |
+
var touchEvents = [];
|
35 |
+
|
36 |
+
var scrollCountTimer = null;
|
37 |
+
var scrollCount = 0;
|
38 |
+
|
39 |
+
var correctionKeyCodes = [ 'Backspace', 'Delete', 'ArrowUp', 'ArrowDown', 'ArrowLeft', 'ArrowRight', 'Home', 'End', 'PageUp', 'PageDown' ];
|
40 |
+
var modifierKeyCodes = [ 'Shift', 'CapsLock' ];
|
41 |
+
|
42 |
+
var forms = document.querySelectorAll( 'form[method=post]' );
|
43 |
+
|
44 |
+
for ( var i = 0; i < forms.length; i++ ) {
|
45 |
+
var form = forms[i];
|
46 |
+
|
47 |
+
form.addEventListener( 'submit', function () {
|
48 |
+
var ak_bkp = prepare_timestamp_array_for_request( keypresses );
|
49 |
+
var ak_bmc = prepare_timestamp_array_for_request( mouseclicks );
|
50 |
+
var ak_bte = prepare_timestamp_array_for_request( touchEvents );
|
51 |
+
var ak_bmm = prepare_timestamp_array_for_request( mousemoves );
|
52 |
+
|
53 |
+
var input_fields = {
|
54 |
+
// When did the user begin entering any input?
|
55 |
+
'ak_bib': input_begin,
|
56 |
+
|
57 |
+
// When was the form submitted?
|
58 |
+
'ak_bfs': Date.now(),
|
59 |
+
|
60 |
+
// How many keypresses did they make?
|
61 |
+
'ak_bkpc': keypresses.length,
|
62 |
+
|
63 |
+
// How quickly did they press a sample of keys, and how long between them?
|
64 |
+
'ak_bkp': ak_bkp,
|
65 |
+
|
66 |
+
// How quickly did they click the mouse, and how long between clicks?
|
67 |
+
'ak_bmc': ak_bmc,
|
68 |
+
|
69 |
+
// How many mouseclicks did they make?
|
70 |
+
'ak_bmcc': mouseclicks.length,
|
71 |
+
|
72 |
+
// When did they press modifier keys (like Shift or Capslock)?
|
73 |
+
'ak_bmk': modifierKeys.join( ';' ),
|
74 |
+
|
75 |
+
// When did they correct themselves? e.g., press Backspace, or use the arrow keys to move the cursor back
|
76 |
+
'ak_bck': correctionKeys.join( ';' ),
|
77 |
+
|
78 |
+
// How many times did they move the mouse?
|
79 |
+
'ak_bmmc': mousemoves.length,
|
80 |
+
|
81 |
+
// How many times did they move around using a touchscreen?
|
82 |
+
'ak_btmc': touchmoveCount,
|
83 |
+
|
84 |
+
// How many times did they scroll?
|
85 |
+
'ak_bsc': scrollCount,
|
86 |
+
|
87 |
+
// How quickly did they perform touch events, and how long between them?
|
88 |
+
'ak_bte': ak_bte,
|
89 |
+
|
90 |
+
// How many touch events were there?
|
91 |
+
'ak_btec' : touchEvents.length,
|
92 |
+
|
93 |
+
// How quickly did they move the mouse, and how long between moves?
|
94 |
+
'ak_bmm' : ak_bmm
|
95 |
+
};
|
96 |
+
|
97 |
+
for ( var field_name in input_fields ) {
|
98 |
+
var field = document.createElement( 'input' );
|
99 |
+
field.setAttribute( 'type', 'hidden' );
|
100 |
+
field.setAttribute( 'name', field_name );
|
101 |
+
field.setAttribute( 'value', input_fields[ field_name ] );
|
102 |
+
this.appendChild( field );
|
103 |
+
}
|
104 |
+
} );
|
105 |
+
|
106 |
+
form.addEventListener( 'keydown', function ( e ) {
|
107 |
+
// If you hold a key down, some browsers send multiple keydown events in a row.
|
108 |
+
// Ignore any keydown events for a key that hasn't come back up yet.
|
109 |
+
if ( e.key in keydowns ) {
|
110 |
+
return;
|
111 |
+
}
|
112 |
+
|
113 |
+
var keydownTime = ( new Date() ).getTime();
|
114 |
+
keydowns[ e.key ] = [ keydownTime ];
|
115 |
+
|
116 |
+
if ( ! input_begin ) {
|
117 |
+
input_begin = keydownTime;
|
118 |
+
}
|
119 |
+
|
120 |
+
// In some situations, we don't want to record an interval since the last keypress -- for example,
|
121 |
+
// on the first keypress, or on a keypress after focus has changed to another element. Normally,
|
122 |
+
// we want to record the time between the last keyup and this keydown. But if they press a
|
123 |
+
// key while already pressing a key, we want to record the time between the two keydowns.
|
124 |
+
|
125 |
+
var lastKeyEvent = Math.max( lastKeydown, lastKeyup );
|
126 |
+
|
127 |
+
if ( lastKeyEvent ) {
|
128 |
+
keydowns[ e.key ].push( keydownTime - lastKeyEvent );
|
129 |
+
}
|
130 |
+
|
131 |
+
lastKeydown = keydownTime;
|
132 |
+
} );
|
133 |
+
|
134 |
+
form.addEventListener( 'keyup', function ( e ) {
|
135 |
+
if ( ! ( e.key in keydowns ) ) {
|
136 |
+
// This key was pressed before this script was loaded, or a mouseclick happened during the keypress, or...
|
137 |
+
return;
|
138 |
+
}
|
139 |
+
|
140 |
+
var keyupTime = ( new Date() ).getTime();
|
141 |
+
|
142 |
+
if ( 'TEXTAREA' === e.target.nodeName || 'INPUT' === e.target.nodeName ) {
|
143 |
+
if ( -1 !== modifierKeyCodes.indexOf( e.key ) ) {
|
144 |
+
modifierKeys.push( keypresses.length - 1 );
|
145 |
+
} else if ( -1 !== correctionKeyCodes.indexOf( e.key ) ) {
|
146 |
+
correctionKeys.push( keypresses.length - 1 );
|
147 |
+
} else {
|
148 |
+
// ^ Don't record timings for keys like Shift or backspace, since they
|
149 |
+
// typically get held down for longer than regular typing.
|
150 |
+
|
151 |
+
var keydownTime = keydowns[ e.key ][0];
|
152 |
+
|
153 |
+
var keypress = [];
|
154 |
+
|
155 |
+
// Keypress duration.
|
156 |
+
keypress.push( keyupTime - keydownTime );
|
157 |
+
|
158 |
+
// Amount of time between this keypress and the previous keypress.
|
159 |
+
if ( keydowns[ e.key ].length > 1 ) {
|
160 |
+
keypress.push( keydowns[ e.key ][1] );
|
161 |
+
}
|
162 |
+
|
163 |
+
keypresses.push( keypress );
|
164 |
+
}
|
165 |
+
}
|
166 |
+
|
167 |
+
delete keydowns[ e.key ];
|
168 |
+
|
169 |
+
lastKeyup = keyupTime;
|
170 |
+
} );
|
171 |
+
|
172 |
+
form.addEventListener( "focusin", function ( e ) {
|
173 |
+
lastKeydown = null;
|
174 |
+
lastKeyup = null;
|
175 |
+
keydowns = {};
|
176 |
+
} );
|
177 |
+
|
178 |
+
form.addEventListener( "focusout", function ( e ) {
|
179 |
+
lastKeydown = null;
|
180 |
+
lastKeyup = null;
|
181 |
+
keydowns = {};
|
182 |
+
} );
|
183 |
+
}
|
184 |
+
|
185 |
+
document.addEventListener( 'mousedown', function ( e ) {
|
186 |
+
lastMousedown = ( new Date() ).getTime();
|
187 |
+
} );
|
188 |
+
|
189 |
+
document.addEventListener( 'mouseup', function ( e ) {
|
190 |
+
if ( ! lastMousedown ) {
|
191 |
+
// If the mousedown happened before this script was loaded, but the mouseup happened after...
|
192 |
+
return;
|
193 |
+
}
|
194 |
+
|
195 |
+
var now = ( new Date() ).getTime();
|
196 |
+
|
197 |
+
var mouseclick = [];
|
198 |
+
mouseclick.push( now - lastMousedown );
|
199 |
+
|
200 |
+
if ( lastMouseup ) {
|
201 |
+
mouseclick.push( lastMousedown - lastMouseup );
|
202 |
+
}
|
203 |
+
|
204 |
+
mouseclicks.push( mouseclick );
|
205 |
+
|
206 |
+
lastMouseup = now;
|
207 |
+
|
208 |
+
// If the mouse has been clicked, don't record this time as an interval between keypresses.
|
209 |
+
lastKeydown = null;
|
210 |
+
lastKeyup = null;
|
211 |
+
keydowns = {};
|
212 |
+
} );
|
213 |
+
|
214 |
+
document.addEventListener( 'mousemove', function ( e ) {
|
215 |
+
if ( mousemoveTimer ) {
|
216 |
+
clearTimeout( mousemoveTimer );
|
217 |
+
mousemoveTimer = null;
|
218 |
+
}
|
219 |
+
else {
|
220 |
+
mousemoveStart = ( new Date() ).getTime();
|
221 |
+
lastMousemoveX = e.offsetX;
|
222 |
+
lastMousemoveY = e.offsetY;
|
223 |
+
}
|
224 |
+
|
225 |
+
mousemoveTimer = setTimeout( function ( theEvent, originalMousemoveStart ) {
|
226 |
+
var now = ( new Date() ).getTime() - 250; // To account for the timer delay.
|
227 |
+
|
228 |
+
var mousemove = [];
|
229 |
+
mousemove.push( now - originalMousemoveStart );
|
230 |
+
mousemove.push(
|
231 |
+
Math.round(
|
232 |
+
Math.sqrt(
|
233 |
+
Math.pow( theEvent.offsetX - lastMousemoveX, 2 ) +
|
234 |
+
Math.pow( theEvent.offsetY - lastMousemoveY, 2 )
|
235 |
+
)
|
236 |
+
)
|
237 |
+
);
|
238 |
+
|
239 |
+
if ( mousemove[1] > 0 ) {
|
240 |
+
// If there was no measurable distance, then it wasn't really a move.
|
241 |
+
mousemoves.push( mousemove );
|
242 |
+
}
|
243 |
+
|
244 |
+
mousemoveStart = null;
|
245 |
+
mousemoveTimer = null;
|
246 |
+
}, 250, e, mousemoveStart );
|
247 |
+
} );
|
248 |
+
|
249 |
+
document.addEventListener( 'touchmove', function ( e ) {
|
250 |
+
if ( touchmoveCountTimer ) {
|
251 |
+
clearTimeout( touchmoveCountTimer );
|
252 |
+
}
|
253 |
+
|
254 |
+
touchmoveCountTimer = setTimeout( function () {
|
255 |
+
touchmoveCount++;
|
256 |
+
}, 250 );
|
257 |
+
} );
|
258 |
+
|
259 |
+
document.addEventListener( 'touchstart', function ( e ) {
|
260 |
+
lastTouchStart = ( new Date() ).getTime();
|
261 |
+
} );
|
262 |
+
|
263 |
+
document.addEventListener( 'touchend', function ( e ) {
|
264 |
+
if ( ! lastTouchStart ) {
|
265 |
+
// If the touchstart happened before this script was loaded, but the touchend happened after...
|
266 |
+
return;
|
267 |
+
}
|
268 |
+
|
269 |
+
var now = ( new Date() ).getTime();
|
270 |
+
|
271 |
+
var touchEvent = [];
|
272 |
+
touchEvent.push( now - lastTouchStart );
|
273 |
+
|
274 |
+
if ( lastTouchEnd ) {
|
275 |
+
touchEvent.push( lastTouchStart - lastTouchEnd );
|
276 |
+
}
|
277 |
+
|
278 |
+
touchEvents.push( touchEvent );
|
279 |
+
|
280 |
+
lastTouchEnd = now;
|
281 |
+
|
282 |
+
// Don't record this time as an interval between keypresses.
|
283 |
+
lastKeydown = null;
|
284 |
+
lastKeyup = null;
|
285 |
+
keydowns = {};
|
286 |
+
} );
|
287 |
+
|
288 |
+
document.addEventListener( 'scroll', function ( e ) {
|
289 |
+
if ( scrollCountTimer ) {
|
290 |
+
clearTimeout( scrollCountTimer );
|
291 |
+
}
|
292 |
+
|
293 |
+
scrollCountTimer = setTimeout( function () {
|
294 |
+
scrollCount++;
|
295 |
+
}, 250 );
|
296 |
+
} );
|
297 |
+
}
|
298 |
+
|
299 |
+
/**
|
300 |
+
* For the timestamp data that is collected, don't send more than `limit` data points in the request.
|
301 |
+
* Choose a random slice and send those.
|
302 |
+
*/
|
303 |
+
function prepare_timestamp_array_for_request( a, limit ) {
|
304 |
+
if ( ! limit ) {
|
305 |
+
limit = 100;
|
306 |
+
}
|
307 |
+
|
308 |
+
var rv = '';
|
309 |
+
|
310 |
+
if ( a.length > 0 ) {
|
311 |
+
var random_starting_point = Math.max( 0, Math.floor( Math.random() * a.length - limit ) );
|
312 |
+
|
313 |
+
for ( var i = 0; i < limit && i < a.length; i++ ) {
|
314 |
+
rv += a[ random_starting_point + i ][0];
|
315 |
+
|
316 |
+
if ( a[ random_starting_point + i ].length >= 2 ) {
|
317 |
+
rv += "," + a[ random_starting_point + i ][1];
|
318 |
+
}
|
319 |
+
|
320 |
+
rv += ";";
|
321 |
+
}
|
322 |
+
}
|
323 |
+
|
324 |
+
return rv;
|
325 |
+
}
|
326 |
+
|
327 |
+
if ( document.readyState !== 'loading' ) {
|
328 |
+
init();
|
329 |
+
} else {
|
330 |
+
document.addEventListener( 'DOMContentLoaded', init );
|
331 |
+
}
|
332 |
+
})();
|
akismet.php
CHANGED
@@ -6,7 +6,7 @@
|
|
6 |
Plugin Name: Akismet Anti-Spam
|
7 |
Plugin URI: https://akismet.com/
|
8 |
Description: Used by millions, Akismet is quite possibly the best way in the world to <strong>protect your blog from spam</strong>. It keeps your site protected even while you sleep. To get started: activate the Akismet plugin and then go to your Akismet Settings page to set up your API key.
|
9 |
-
Version:
|
10 |
Author: Automattic
|
11 |
Author URI: https://automattic.com/wordpress-plugins/
|
12 |
License: GPLv2 or later
|
@@ -37,7 +37,7 @@ if ( !function_exists( 'add_action' ) ) {
|
|
37 |
exit;
|
38 |
}
|
39 |
|
40 |
-
define( 'AKISMET_VERSION', '
|
41 |
define( 'AKISMET__MINIMUM_WP_VERSION', '5.0' );
|
42 |
define( 'AKISMET__PLUGIN_DIR', plugin_dir_path( __FILE__ ) );
|
43 |
define( 'AKISMET_DELETE_LIMIT', 10000 );
|
6 |
Plugin Name: Akismet Anti-Spam
|
7 |
Plugin URI: https://akismet.com/
|
8 |
Description: Used by millions, Akismet is quite possibly the best way in the world to <strong>protect your blog from spam</strong>. It keeps your site protected even while you sleep. To get started: activate the Akismet plugin and then go to your Akismet Settings page to set up your API key.
|
9 |
+
Version: 5.0
|
10 |
Author: Automattic
|
11 |
Author URI: https://automattic.com/wordpress-plugins/
|
12 |
License: GPLv2 or later
|
37 |
exit;
|
38 |
}
|
39 |
|
40 |
+
define( 'AKISMET_VERSION', '5.0' );
|
41 |
define( 'AKISMET__MINIMUM_WP_VERSION', '5.0' );
|
42 |
define( 'AKISMET__PLUGIN_DIR', plugin_dir_path( __FILE__ ) );
|
43 |
define( 'AKISMET_DELETE_LIMIT', 10000 );
|
class.akismet.php
CHANGED
@@ -35,6 +35,9 @@ class Akismet {
|
|
35 |
add_filter( 'preprocess_comment', array( 'Akismet', 'auto_check_comment' ), 1 );
|
36 |
add_filter( 'rest_pre_insert_comment', array( 'Akismet', 'rest_auto_check_comment' ), 1 );
|
37 |
|
|
|
|
|
|
|
38 |
add_action( 'akismet_scheduled_delete', array( 'Akismet', 'delete_old_comments' ) );
|
39 |
add_action( 'akismet_scheduled_delete', array( 'Akismet', 'delete_old_comments_meta' ) );
|
40 |
add_action( 'akismet_scheduled_delete', array( 'Akismet', 'delete_orphaned_commentmeta' ) );
|
@@ -42,6 +45,7 @@ class Akismet {
|
|
42 |
|
43 |
add_action( 'comment_form', array( 'Akismet', 'add_comment_nonce' ), 1 );
|
44 |
add_action( 'comment_form', array( 'Akismet', 'output_custom_form_fields' ) );
|
|
|
45 |
|
46 |
add_filter( 'comment_moderation_recipients', array( 'Akismet', 'disable_moderation_emails_if_unreachable' ), 1000, 2 );
|
47 |
add_filter( 'pre_comment_approved', array( 'Akismet', 'last_comment_status' ), 10, 2 );
|
@@ -1344,13 +1348,17 @@ class Akismet {
|
|
1344 |
}
|
1345 |
}
|
1346 |
|
1347 |
-
|
1348 |
-
|
1349 |
-
|
1350 |
-
|
|
|
1351 |
public static function set_form_js_async( $tag, $handle, $src ) {
|
1352 |
-
|
1353 |
-
|
|
|
|
|
|
|
1354 |
}
|
1355 |
|
1356 |
public static function get_akismet_form_fields() {
|
@@ -1739,4 +1747,26 @@ p {
|
|
1739 |
) . '</p>'
|
1740 |
);
|
1741 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1742 |
}
|
35 |
add_filter( 'preprocess_comment', array( 'Akismet', 'auto_check_comment' ), 1 );
|
36 |
add_filter( 'rest_pre_insert_comment', array( 'Akismet', 'rest_auto_check_comment' ), 1 );
|
37 |
|
38 |
+
add_action( 'comment_form', array( 'Akismet', 'load_form_js' ) );
|
39 |
+
add_action( 'do_shortcode_tag', array( 'Akismet', 'load_form_js_via_filter' ), 10, 4 );
|
40 |
+
|
41 |
add_action( 'akismet_scheduled_delete', array( 'Akismet', 'delete_old_comments' ) );
|
42 |
add_action( 'akismet_scheduled_delete', array( 'Akismet', 'delete_old_comments_meta' ) );
|
43 |
add_action( 'akismet_scheduled_delete', array( 'Akismet', 'delete_orphaned_commentmeta' ) );
|
45 |
|
46 |
add_action( 'comment_form', array( 'Akismet', 'add_comment_nonce' ), 1 );
|
47 |
add_action( 'comment_form', array( 'Akismet', 'output_custom_form_fields' ) );
|
48 |
+
add_filter( 'script_loader_tag', array( 'Akismet', 'set_form_js_async' ), 10, 3 );
|
49 |
|
50 |
add_filter( 'comment_moderation_recipients', array( 'Akismet', 'disable_moderation_emails_if_unreachable' ), 1000, 2 );
|
51 |
add_filter( 'pre_comment_approved', array( 'Akismet', 'last_comment_status' ), 10, 2 );
|
1348 |
}
|
1349 |
}
|
1350 |
|
1351 |
+
/**
|
1352 |
+
* Mark akismet-frontend.js as deferred. Because nothing depends on it, it can run at any time
|
1353 |
+
* after it's loaded, and the browser won't have to wait for it to load to continue
|
1354 |
+
* parsing the rest of the page.
|
1355 |
+
*/
|
1356 |
public static function set_form_js_async( $tag, $handle, $src ) {
|
1357 |
+
if ( 'akismet-frontend' !== $handle ) {
|
1358 |
+
return $tag;
|
1359 |
+
}
|
1360 |
+
|
1361 |
+
return preg_replace( '/^<script /i', '<script defer ', $tag );
|
1362 |
}
|
1363 |
|
1364 |
public static function get_akismet_form_fields() {
|
1747 |
) . '</p>'
|
1748 |
);
|
1749 |
}
|
1750 |
+
|
1751 |
+
public static function load_form_js() {
|
1752 |
+
if (
|
1753 |
+
! is_admin()
|
1754 |
+
&& ( ! function_exists( 'amp_is_request' ) || ! amp_is_request() )
|
1755 |
+
&& self::get_api_key()
|
1756 |
+
) {
|
1757 |
+
wp_register_script( 'akismet-frontend', plugin_dir_url( __FILE__ ) . '_inc/akismet-frontend.js', array(), filemtime( plugin_dir_path( __FILE__ ) . '_inc/akismet-frontend.js' ), true );
|
1758 |
+
wp_enqueue_script( 'akismet-frontend' );
|
1759 |
+
}
|
1760 |
+
}
|
1761 |
+
|
1762 |
+
/**
|
1763 |
+
* Add the form JavaScript when we detect that a supported form shortcode is being parsed.
|
1764 |
+
*/
|
1765 |
+
public static function load_form_js_via_filter( $return_value, $tag, $attr, $m ) {
|
1766 |
+
if ( in_array( $tag, array( 'contact-form', 'gravityform', 'contact-form-7', 'formidable', 'fluentform' ) ) ) {
|
1767 |
+
self::load_form_js();
|
1768 |
+
}
|
1769 |
+
|
1770 |
+
return $return_value;
|
1771 |
+
}
|
1772 |
}
|
readme.txt
CHANGED
@@ -3,7 +3,7 @@ Contributors: matt, ryan, andy, mdawaffe, tellyworth, josephscott, lessbloat, eo
|
|
3 |
Tags: comments, spam, antispam, anti-spam, contact form, anti spam, comment moderation, comment spam, contact form spam, spam comments
|
4 |
Requires at least: 5.0
|
5 |
Tested up to: 6.0.1
|
6 |
-
Stable tag:
|
7 |
License: GPLv2 or later
|
8 |
|
9 |
The best anti-spam protection to block spam comments and spam in a contact form. The most trusted antispam solution for WordPress and WooCommerce.
|
@@ -30,6 +30,11 @@ Upload the Akismet plugin to your blog, activate it, and then enter your Akismet
|
|
30 |
|
31 |
== Changelog ==
|
32 |
|
|
|
|
|
|
|
|
|
|
|
33 |
= 4.2.5 =
|
34 |
*Release Date - 11 July 2022*
|
35 |
|
3 |
Tags: comments, spam, antispam, anti-spam, contact form, anti spam, comment moderation, comment spam, contact form spam, spam comments
|
4 |
Requires at least: 5.0
|
5 |
Tested up to: 6.0.1
|
6 |
+
Stable tag: 5.0
|
7 |
License: GPLv2 or later
|
8 |
|
9 |
The best anti-spam protection to block spam comments and spam in a contact form. The most trusted antispam solution for WordPress and WooCommerce.
|
30 |
|
31 |
== Changelog ==
|
32 |
|
33 |
+
= 5.0 =
|
34 |
+
*Release Date - 26 July 2022*
|
35 |
+
|
36 |
+
* Added a new feature to catch spammers by observing how they interact with the page.
|
37 |
+
|
38 |
= 4.2.5 =
|
39 |
*Release Date - 11 July 2022*
|
40 |
|