refactor(moderation): remove the Akismet backend and its admin fields

The comment moderation pipeline no longer calls Akismet. Removed:
- check_akismet() and the Akismet step in Moderation::process().
- akismet_* config keys from Moderation defaults and ExtensionRuntime.
- akismet decision state, the jio_moderation_akismet / akismet_result
  comment meta writes, and the legacy-meta fallbacks in the comments column.
- The Akismet fieldset in both the PHP and Vue permissions schemas.

Rate limit, GeoIP, blocked keywords and AI moderation are unchanged.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
kate522andClaude Opus 5 committed 2026-11-05 11:27:24 +08:00
1 parent e6d9ff49a2
commit 3595935475
5 files changed
+4 -157

No files matched your search

@@ -130,10 +130,6 @@ export const permissionsSchemas = {
description: '管理评论审核、反垃圾、限流与拦截配置。',
defaults: {
enabled: false,
akismet_enabled: false,
akismet_site_url: '',
akismet_blog_lang: 'zh-CN',
akismet_api_key: '',
ai_enabled: false,
ai_moderate_comments: true,
ai_moderate_background: true,
@@ -157,17 +153,6 @@ export const permissionsSchemas = {
{ key: 'enabled', label: '启用审核系统', type: 'switch', help: '关闭后评论将不经过主题审核链路。' },
],
},
{
key: 'akismet',
title: 'Akismet',
icon: 'fa fas fa-filter',
fields: [
{ key: 'akismet_enabled', label: '启用 Akismet', type: 'switch', dependsOn: { key: 'enabled', value: true } },
{ key: 'akismet_site_url', label: 'Site URL', type: 'input', placeholder: 'https://your-site.com', dependsOn: { key: 'akismet_enabled', value: true } },
{ key: 'akismet_blog_lang', label: '博客语言', type: 'input', placeholder: 'zh-CN', dependsOn: { key: 'akismet_enabled', value: true } },
{ key: 'akismet_api_key', label: 'API Key', type: 'input', inputType: 'password', placeholder: 'Akismet API Key', dependsOn: { key: 'akismet_enabled', value: true } },
],
},
{
key: 'ai',
title: 'AI 审核',
-6
View File
@@ -144,12 +144,6 @@ class SchemaPermissions {
['key' => 'basic', 'title' => '审核总开关', 'fields' => [
['key' => 'enabled', 'label' => '启用审核系统', 'type' => 'switch', 'default' => false],
]],
['key' => 'akismet', 'title' => 'Akismet', 'fields' => [
['key' => 'akismet_enabled', 'label' => '启用 Akismet', 'type' => 'switch', 'default' => false, 'dependsOn' => ['key' => 'enabled', 'value' => true]],
['key' => 'akismet_site_url', 'label' => 'Site URL', 'type' => 'input', 'default' => '', 'dependsOn' => ['key' => 'akismet_enabled', 'value' => true]],
['key' => 'akismet_blog_lang', 'label' => '博客语言', 'type' => 'input', 'default' => 'zh-CN', 'dependsOn' => ['key' => 'akismet_enabled', 'value' => true]],
['key' => 'akismet_api_key', 'label' => 'API Key', 'type' => 'input', 'inputType' => 'password', 'default' => '', 'dependsOn' => ['key' => 'akismet_enabled', 'value' => true]],
]],
['key' => 'ai', 'title' => 'AI 审核', 'fields' => [
['key' => 'ai_enabled', 'label' => '启用 AI 审核', 'type' => 'switch', 'default' => false, 'dependsOn' => ['key' => 'enabled', 'value' => true]],
['key' => 'ai_api_hint', 'label' => '审核 API 配置', 'type' => 'notice', 'alertType' => 'info', 'alertContent' => 'API 接入在「扩展 → API 内容审核」中统一配置;此处仅控制审核范围和策略。', 'dependsOn' => ['key' => 'ai_enabled', 'value' => true]],
+1 -33
View File
@@ -68,10 +68,6 @@ class Moderation {
public function get_config(): array {
$defaults = [
'enabled' => false,
'akismet_enabled' => false,
'akismet_site_url' => '',
'akismet_blog_lang' => 'zh-CN',
'akismet_api_key' => '',
'ai_enabled' => false,
'ai_moderate_comments' => true,
'ai_moderate_background' => true,
@@ -199,27 +195,7 @@ class Moderation {
$decision['keyword_match_type'] = (string) ($keyword['match_type'] ?? 'plain');
}
// 4) Akismet.
$akismet = $this->check_akismet($commentdata, $config, $client_ip);
if ($akismet === 'spam') {
$commentdata['comment_approved'] = 'spam';
$decision['result'] = 'spam';
$decision['source'] = 'akismet';
$decision['reason'] = 'spam';
$decision['akismet'] = 'spam';
} elseif ($akismet === 'ham') {
$decision['akismet'] = 'ham';
if ($decision['source'] === 'wp_default') {
$decision['source'] = 'akismet';
$decision['reason'] = 'ham';
}
} elseif ($akismet === 'error') {
$decision['akismet'] = 'error';
} else {
$decision['akismet'] = 'unknown';
}
// 5) AI moderation provider (Baidu only).
// 4) AI moderation provider (Baidu only).
// If keyword already hit, keep keyword decision locked and skip AI override.
if (!$keyword_hit) {
$ai = $this->check_ai_moderation($commentdata, $config);
@@ -316,7 +292,6 @@ class Moderation {
update_comment_meta($comment_id, 'jio_moderation_result', (string) $decision['result']);
update_comment_meta($comment_id, 'jio_moderation_source', (string) $decision['source']);
update_comment_meta($comment_id, 'jio_moderation_reason', (string) $decision['reason']);
update_comment_meta($comment_id, 'jio_moderation_akismet', (string) $decision['akismet']);
update_comment_meta($comment_id, 'jio_moderation_ai_score', (string) $decision['ai_score']);
update_comment_meta($comment_id, 'jio_moderation_ai_flagged', (string) $decision['ai_flagged']);
update_comment_meta($comment_id, 'jio_moderation_ai_top_category', (string) $decision['ai_top_category']);
@@ -335,13 +310,6 @@ class Moderation {
update_comment_meta($comment_id, 'jio_moderation_user_id', (string) $moderation_user_id);
update_comment_meta($comment_id, 'jio_moderation_user_ip', $moderation_user_ip);
// Convenience marker for external tools expecting Akismet style keys.
if ($decision['source'] === 'akismet' && $decision['akismet'] === 'spam') {
update_comment_meta($comment_id, 'akismet_result', 'true');
} elseif ($decision['source'] === 'akismet' && $decision['akismet'] === 'ham') {
update_comment_meta($comment_id, 'akismet_result', 'false');
}
// Clean runtime maps.
$fp_comment = $this->comment_fingerprint((array) $comment);
$fp_data = $this->comment_fingerprint($commentdata);
+3 -99
View File
@@ -26,7 +26,6 @@ trait ModerationPart1 {
$source = (string) get_comment_meta($comment_id, 'jio_moderation_source', true);
$result_value = (string) get_comment_meta($comment_id, 'jio_moderation_result', true);
$reason = (string) get_comment_meta($comment_id, 'jio_moderation_reason', true);
$akismet = (string) get_comment_meta($comment_id, 'jio_moderation_akismet', true);
$ai_score = (string) get_comment_meta($comment_id, 'jio_moderation_ai_score', true);
$ai_flagged = (string) get_comment_meta($comment_id, 'jio_moderation_ai_flagged', true);
$ai_top = (string) get_comment_meta($comment_id, 'jio_moderation_ai_top_category', true);
@@ -44,38 +43,11 @@ trait ModerationPart1 {
if ($reason === '') {
$reason = 'wp_default_policy';
}
if ($akismet === '') {
$akismet_meta = get_comment_meta($comment_id, 'akismet_result', true);
if ((string) $akismet_meta === 'true') {
$akismet = 'spam';
} elseif ((string) $akismet_meta === 'false') {
$akismet = 'ham';
} else {
$akismet = 'unknown';
}
}
if ($source === 'wp_default' && $akismet === 'ham') {
$source = 'akismet';
if ($result_value === 'wp_default_policy') {
$result_value = 'approved';
}
if ($reason === 'wp_default_policy') {
$reason = 'ham';
}
} elseif ($source === 'wp_default' && $akismet === 'spam') {
$source = 'akismet';
$result_value = 'spam';
if ($reason === 'wp_default_policy') {
$reason = 'spam';
}
}
echo '<strong>' . esc_html($status_label) . '</strong><br>';
echo 'Source: ' . esc_html($source) . ' | ';
echo 'Result: ' . esc_html($result_value) . ' | ';
echo 'Reason: ' . esc_html($reason) . ' | ';
echo 'Akismet: ' . esc_html($akismet);
echo 'Reason: ' . esc_html($reason);
$extras = [];
if ($ai_score !== '') {
@@ -109,7 +81,6 @@ trait ModerationPart1 {
'result' => 'approved',
'source' => 'wp_default',
'reason' => 'wp_default_policy',
'akismet' => 'unknown',
'ai_score' => '',
'ai_flagged' => '',
'ai_top_category' => '',
@@ -145,18 +116,6 @@ trait ModerationPart1 {
$fallback['result'] = $this->result_by_approved((string) $comment->comment_approved);
$fallback['reason'] = 'wp_default_policy';
$akismet_meta = get_comment_meta($comment->comment_ID, 'akismet_result', true);
if ((string) $akismet_meta === 'true') {
$fallback['source'] = 'akismet';
$fallback['reason'] = 'spam';
$fallback['akismet'] = 'spam';
$fallback['result'] = 'spam';
} elseif ((string) $akismet_meta === 'false') {
$fallback['source'] = 'akismet';
$fallback['reason'] = 'ham';
$fallback['akismet'] = 'ham';
}
return $fallback;
}
@@ -171,9 +130,6 @@ trait ModerationPart1 {
if (!isset($result['reason']) || $result['reason'] === '') {
$result['reason'] = 'wp_default_policy';
}
if (!isset($result['akismet']) || $result['akismet'] === '') {
$result['akismet'] = 'unknown';
}
if (!isset($result['ai_score'])) {
$result['ai_score'] = '';
}
@@ -236,59 +192,7 @@ trait ModerationPart1 {
}
// ============================================================
// 1. Akismet
// ============================================================
private function check_akismet(array $data, array $config, string $ip) {
if (empty($config['akismet_enabled'])) {
return true;
}
$api_key = trim((string) ($config['akismet_api_key'] ?? ''));
if ($api_key === '') {
return 'error';
}
$site_url = !empty($config['akismet_site_url']) ? (string) $config['akismet_site_url'] : home_url('/');
$payload = [
'blog' => $site_url,
'blog_lang' => $config['akismet_blog_lang'] ?? 'zh-CN',
'blog_charset' => get_bloginfo('charset') ?: 'UTF-8',
'user_ip' => $ip,
'user_agent' => $_SERVER['HTTP_USER_AGENT'] ?? '',
'referrer' => $_SERVER['HTTP_REFERER'] ?? '',
'comment_type' => 'comment',
'comment_author' => $data['comment_author'] ?? '',
'comment_author_email' => $data['comment_author_email'] ?? '',
'comment_author_url' => $data['comment_author_URL'] ?? ($data['comment_author_url'] ?? ''),
'comment_content' => $data['comment_content'] ?? '',
'is_test' => defined('WP_DEBUG') && WP_DEBUG ? '1' : '0',
];
$endpoint = sprintf('https://%s.rest.akismet.com/1.1/comment-check', $api_key);
$response = wp_remote_post($endpoint, [
'body' => http_build_query($payload),
'timeout' => 10,
'headers' => ['Content-Type' => 'application/x-www-form-urlencoded'],
]);
if (is_wp_error($response)) {
return 'error';
}
$body = trim((string) wp_remote_retrieve_body($response));
if ($body === 'true') {
return 'spam';
}
if ($body === 'false') {
return 'ham';
}
return 'error';
}
// ============================================================
// 2. AI Moderation
// 1. AI Moderation
// ============================================================
private function check_ai_moderation(array $data, array $config) {
@@ -346,7 +250,7 @@ trait ModerationPart1 {
}
// ============================================================
// 3. Blocked keywords
// 2. Blocked keywords
// ============================================================
private function check_blocked_keywords(array $data, array $config): array {
-4
View File
@@ -13,10 +13,6 @@ class ExtensionRuntime {
public static function get_moderation(): array {
return get_option('jio_moderation_config', [
'enabled' => false,
'akismet_enabled' => false,
'akismet_site_url' => '',
'akismet_blog_lang' => 'zh-CN',
'akismet_api_key' => '',
'ai_enabled' => false,
'ai_provider' => 'baidu',
'baidu_api_key' => '',