Je winkelwagen is leeg
Producten die je toevoegt, verschijnen hier.
Leer hoe je een AI-gestuurde comment moderator bouwt met Neuron v2 PHP en de WordPress Abilities API. Inclusief email verificatie tool. Stap voor stap met werkende code.
Samenvatting: AI Comment Moderator met Neuron + Abilities
In deze tutorial bouw je een WordPress plugin die comments automatisch analyseert op spam en kwaliteit met behulp van AI. Je combineert het Neuron v2 PHP framework met de WordPress Abilities API, inclusief een custom tool voor email verificatie.
Comments modereren is tijdrovend werk. Spam herkennen, toxische reacties filteren, en beslissen wat goedgekeurd mag worden - het kost uren per week. Maar wat als AI dit voor je kan doen?
In deze tutorial bouw je stap voor stap een comment moderator die gebruik maakt van Neuron AI (een PHP
KeurigOnline zegtPHP
KeurigOnline zegtWordPress
KeurigOnline zegtAPI
De complete code vind je op GitHub.
Onze plugin bestaat uit zeven classes die we stuk voor stuk opbouwen:
Vereisten
Maak een nieuwe plugin directory en initialiseer de structuur:
cd wp-content/plugins
mkdir ko-comment-moderator
cd ko-comment-moderator
mkdir -p src/Tools
Maak composer.json:
{
"name": "keurigonline/ko-comment-moderator",
"description": "AI-powered comment moderation",
"type": "wordpress-plugin",
"require": {
"php": ">=8.0",
"neuron-core/neuron-ai": "^2.0"
},
"autoload": {
"psr-4": {
"KO\\CommentModerator\\": "src/"
}
}
}
Installeer de dependencies:
composer install
Opmerking: Bij distributie via GitHub is de vendor/ directory meegeleverd. Eindgebruikers hoeven geen composer install uit te voeren.
Tip: Het package heette voorheen inspector-apm/neuron-ai. Gebruik altijd neuron-core/neuron-ai - dat is de actieve fork.
We beginnen met de eenvoudigste class: de definitie van wat we terug willen krijgen van de AI. Neuron AI ondersteunt structured output - je definieert een PHP class en krijgt een getypte response terug.
Maak src/CommentAnalysis.php:
<?php
namespace KO\CommentModerator;
use NeuronAI\StructuredOutput\SchemaProperty;
class CommentAnalysis
{
#[SchemaProperty(description: 'Spam probability from 0.0 (not spam) to 1.0 (definitely spam)')]
public float $spam_score;
#[SchemaProperty(description: 'Recommended action: approve, hold, reject, or spam')]
public string $action;
#[SchemaProperty(description: 'Brief explanation for the classification decision')]
public string $reason;
}
Elke property krijgt een #[SchemaProperty] attribute die de AI vertelt wat we verwachten:
Waarom structured output? Zonder structured output zou je JSON moeten parsen en hopen dat de AI het juiste formaat teruggeeft. Met SchemaProperty dwingt Neuron de AI om exact dit formaat te gebruiken, en krijg je een getypt PHP object terug.
Een slimme spamdetectie checkt niet alleen de comment tekst, maar ook of de auteur een legitiem email adres gebruikt. Dit is vooral nuttig wanneer de comment links bevat - spammers gebruiken vaak fake email adressen.
Neuron AI agents kunnen tools gebruiken - functies die de AI kan aanroepen wanneer nodig. We bouwen een tool die controleert of een email domein bestaat en mail kan ontvangen.
Maak src/Tools/VerifyEmailTool.php met de basis structuur:
<?php
namespace KO\CommentModerator\Tools;
use NeuronAI\Tools\Tool;
use NeuronAI\Tools\ToolProperty;
use NeuronAI\Tools\PropertyType;
class VerifyEmailTool
{
private const DISPOSABLE_DOMAINS = [
'tempmail.com',
'throwaway.email',
'guerrillamail.com',
'mailinator.com',
'temp-mail.org',
'10minutemail.com',
'yopmail.com',
];
}
We definiëren een lijst van bekende wegwerp-email diensten. Nu de make() method die de Neuron Tool aanmaakt:
<?php
namespace KO\CommentModerator\Tools;
use NeuronAI\Tools\Tool;
use NeuronAI\Tools\ToolProperty;
use NeuronAI\Tools\PropertyType;
class VerifyEmailTool
{
private const DISPOSABLE_DOMAINS = [
'tempmail.com',
'throwaway.email',
'guerrillamail.com',
'mailinator.com',
'temp-mail.org',
'10minutemail.com',
'yopmail.com',
];
public static function make(): Tool
{
return Tool::make(
'verify_email',
'Verify if an email address domain exists and can receive mail. Use when the comment contains URLs.'
)
->addProperty(
ToolProperty::make(
name: 'email',
type: PropertyType::STRING,
description: 'The email address to verify',
required: true
)
)
->setCallable([new self(), 'execute']);
}
}
Neuron v2 API: In Neuron v2 moet je ToolProperty::make() gebruiken met een PropertyType enum. De oude syntax addProperty('email', 'string', 'description') werkt niet meer.
Nu de execute() method die de daadwerkelijke verificatie uitvoert:
<?php
namespace KO\CommentModerator\Tools;
use NeuronAI\Tools\Tool;
use NeuronAI\Tools\ToolProperty;
use NeuronAI\Tools\PropertyType;
class VerifyEmailTool
{
private const DISPOSABLE_DOMAINS = [
'tempmail.com',
'throwaway.email',
'guerrillamail.com',
'mailinator.com',
'temp-mail.org',
'10minutemail.com',
'yopmail.com',
];
public static function make(): Tool
{
return Tool::make(
'verify_email',
'Verify if an email address domain exists and can receive mail. Use when the comment contains URLs.'
)
->addProperty(
ToolProperty::make(
name: 'email',
type: PropertyType::STRING,
description: 'The email address to verify',
required: true
)
)
->setCallable([new self(), 'execute']);
}
public function execute(string $email): string
{
// Valideer email formaat
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
return 'INVALID: Email format is invalid.';
}
// Extract domein
$domain = substr(strrchr($email, '@'), 1);
if (empty($domain)) {
return 'INVALID: Could not extract domain from email.';
}
// Check voor wegwerp-email diensten
if (in_array(strtolower($domain), self::DISPOSABLE_DOMAINS, true)) {
return 'SUSPICIOUS: "' . $domain . '" is a known disposable email service.';
}
// Check MX records (kan het domein mail ontvangen?)
$mxRecords = [];
$hasMx = @getmxrr($domain, $mxRecords);
if (!$hasMx || empty($mxRecords)) {
// Fallback: check A record
$hasA = @checkdnsrr($domain, 'A');
if (!$hasA) {
return 'SUSPICIOUS: Domain "' . $domain . '" does not exist. Likely a fake email.';
}
return 'WARNING: Domain "' . $domain . '" exists but has no mail server.';
}
return 'VALID: Email domain "' . $domain . '" exists and can receive mail.';
}
}
De tool controleert:
Waarom MX records? Elk domein dat email kan ontvangen heeft MX (Mail Exchange) records in DNS. Als die ontbreken kan het domein geen mail ontvangen - een sterke indicator voor een fake email.
Nu bouwen we de AI agent die de analyse uitvoert. Een Neuron agent is een class die Agent extend en drie methods implementeert: provider(), instructions(), en tools().
Maak src/CommentModeratorAgent.php:
<?php
namespace KO\CommentModerator;
use KO\CommentModerator\Tools\VerifyEmailTool;
use NeuronAI\Agent;
use NeuronAI\Providers\AIProviderInterface;
use NeuronAI\Providers\OpenAI\OpenAI;
use NeuronAI\SystemPrompt;
class CommentModeratorAgent extends Agent
{
public function provider(): AIProviderInterface
{
return new OpenAI(
key: Settings::get('api_key', ''),
model: 'gpt-5-nano'
);
}
}
De provider() method bepaalt welk AI model we gebruiken. GPT-5-nano is snel en goedkoop voor classificatietaken. De API key halen we uit de Settings class.
Nu de instructions() method met de systeem prompt:
<?php
namespace KO\CommentModerator;
use KO\CommentModerator\Tools\VerifyEmailTool;
use NeuronAI\Agent;
use NeuronAI\Providers\AIProviderInterface;
use NeuronAI\Providers\OpenAI\OpenAI;
use NeuronAI\SystemPrompt;
class CommentModeratorAgent extends Agent
{
public function provider(): AIProviderInterface
{
return new OpenAI(
key: Settings::get('api_key', ''),
model: 'gpt-5-nano'
);
}
public function instructions(): string
{
return (string) new SystemPrompt(
background: [
'You are a comment moderation assistant for a WordPress website.',
'Your job is to analyze comments and determine if they are spam, toxic, or legitimate.',
'You must be accurate but also fair - do not flag legitimate comments as spam.',
],
steps: [
'1. Check for common spam patterns: promotional links, casino/pharmacy keywords, excessive caps.',
'2. Assess the relevance: does the comment relate to typical blog discussions?',
'3. Check for toxicity: insults, hate speech, harassment.',
'4. Consider the author name: spammy names often contain URLs or random characters.',
'5. If the comment contains URLs, use the verify_email tool to check if the author email is real.',
'6. Make a final decision based on all factors.',
],
output: [
'Return a JSON object with exactly three fields:',
'- spam_score: float between 0.0 and 1.0',
'- action: one of "approve", "hold", "reject", "spam"',
'- reason: brief explanation (max 100 characters)',
]
);
}
}
Stap 5 in de instructions vertelt de AI om de verify_email tool te gebruiken wanneer de comment URLs bevat. Dit is de kracht van Neuron: je kunt de AI instrueren om tools conditieel te gebruiken.
Tot slot de tools() method die onze VerifyEmailTool registreert:
<?php
namespace KO\CommentModerator;
use KO\CommentModerator\Tools\VerifyEmailTool;
use NeuronAI\Agent;
use NeuronAI\Providers\AIProviderInterface;
use NeuronAI\Providers\OpenAI\OpenAI;
use NeuronAI\SystemPrompt;
class CommentModeratorAgent extends Agent
{
public function provider(): AIProviderInterface
{
return new OpenAI(
key: Settings::get('api_key', ''),
model: 'gpt-5-nano'
);
}
public function instructions(): string
{
return (string) new SystemPrompt(
background: [
'You are a comment moderation assistant for a WordPress website.',
'Your job is to analyze comments and determine if they are spam, toxic, or legitimate.',
'You must be accurate but also fair - do not flag legitimate comments as spam.',
],
steps: [
'1. Check for common spam patterns: promotional links, casino/pharmacy keywords, excessive caps.',
'2. Assess the relevance: does the comment relate to typical blog discussions?',
'3. Check for toxicity: insults, hate speech, harassment.',
'4. Consider the author name: spammy names often contain URLs or random characters.',
'5. If the comment contains URLs, use the verify_email tool to check if the author email is real.',
'6. Make a final decision based on all factors.',
],
output: [
'Return a JSON object with exactly three fields:',
'- spam_score: float between 0.0 and 1.0',
'- action: one of "approve", "hold", "reject", "spam"',
'- reason: brief explanation (max 100 characters)',
]
);
}
public function tools(): array
{
return [
VerifyEmailTool::make(),
];
}
}
De agent is nu compleet. Dankzij de gescheiden Tools/ directory is de code goed georganiseerd en kun je makkelijk meer tools toevoegen.
In plaats van API keys in wp-config.php te zetten, bouwen we een gebruiksvriendelijke settings pagina in WordPress admin.
Maak src/Settings.php met de basis structuur:
<?php
namespace KO\CommentModerator;
class Settings
{
private const OPTION_NAME = 'komod_settings';
private const DEFAULTS = [
'api_key' => '',
'demo_mode' => true,
'auto_moderate' => false,
'auto_approve_threshold' => 0.2,
'auto_spam_threshold' => 0.8,
'show_admin_columns' => true,
];
public static function init(): void
{
add_action('admin_menu', [self::class, 'add_menu_page']);
add_action('admin_init', [self::class, 'register_settings']);
}
public static function get(string $key, $default = null)
{
$settings = get_option(self::OPTION_NAME, []);
$settings = wp_parse_args($settings, self::DEFAULTS);
return $settings[$key] ?? $default ?? self::DEFAULTS[$key] ?? null;
}
public static function add_menu_page(): void
{
add_options_page(
'Comment Moderator',
'Comment Moderator',
'manage_options',
'ko-comment-moderator',
[self::class, 'render_page']
);
}
public static function register_settings(): void
{
register_setting('komod_settings_group', self::OPTION_NAME, [
'sanitize_callback' => [self::class, 'sanitize_settings'],
]);
add_settings_section(
'komod_api_section',
'API Configuratie',
[self::class, 'render_api_section'],
'ko-comment-moderator'
);
add_settings_field('api_key', 'OpenAI API Key', [self::class, 'render_api_key_field'], 'ko-comment-moderator', 'komod_api_section');
add_settings_field('demo_mode', 'Demo Modus', [self::class, 'render_demo_mode_field'], 'ko-comment-moderator', 'komod_api_section');
// Meer velden voor auto_moderate, thresholds...
}
}
De settings pagina bevat:
Complete Settings class
De volledige class met alle render methods, het test formulier, en sanitization vind je op GitHub.
Nu verbinden we alles met de WordPress Abilities API. Dit maakt onze moderator beschikbaar via REST API, WP-CLI
KeurigOnline zegtWP-CLI
Maak src/Ability.php:
<?php
namespace KO\CommentModerator;
use NeuronAI\Chat\Messages\UserMessage;
use WP_Error;
class Ability
{
public static function init(): void
{
add_action('wp_abilities_api_categories_init', [self::class, 'register_category']);
add_action('wp_abilities_api_init', [self::class, 'register_ability']);
}
public static function register_category(): void
{
wp_register_ability_category('moderation', [
'label' => 'Content Moderation',
'description' => 'Abilities for moderating user-generated content',
]);
}
}
Belangrijke valkuil: De hooks heten wp_abilities_api_init (met wp_ prefix), niet abilities_api_init. Zonder de prefix wordt je ability niet geregistreerd en krijg je geen foutmelding.
Nu de register_ability() method. Let op de comment_author_email parameter die we toevoegen voor de email verificatie:
public static function register_ability(): void
{
wp_register_ability('keurigonline/moderate-comment', [
'label' => 'Moderate Comment',
'description' => 'Analyzes a comment for spam and toxicity using AI',
'category' => 'moderation',
'input_schema' => [
'type' => 'object',
'properties' => [
'comment_text' => [
'type' => 'string',
'description' => 'The comment text to analyze',
],
'comment_author' => [
'type' => 'string',
'description' => 'The name of the comment author (optional)',
],
'comment_author_email' => [
'type' => 'string',
'description' => 'The email of the author (used for verification when URLs present)',
],
],
'required' => ['comment_text'],
],
'output_schema' => [
'type' => 'object',
'properties' => [
'spam_score' => ['type' => 'number'],
'action' => ['type' => 'string', 'enum' => ['approve', 'hold', 'reject', 'spam']],
'reason' => ['type' => 'string'],
],
],
'execute_callback' => [self::class, 'execute'],
'permission_callback' => [self::class, 'check_permission'],
'meta' => [
'show_in_rest' => true,
'annotations' => [
'readonly' => false, // POST request needed
'destructive' => false,
],
],
]);
}
De execute() method bevat de kernlogica. We geven het email adres mee aan de AI en hinten om de verify_email tool te gebruiken wanneer er URLs zijn:
public static function execute(array $input): array|WP_Error
{
$comment_text = $input['comment_text'] ?? '';
$comment_author = $input['comment_author'] ?? 'Anonymous';
$comment_email = $input['comment_author_email'] ?? '';
if (empty($comment_text)) {
return new WP_Error('missing_comment', 'Comment text is required.');
}
// Demo mode: pattern matching voor testen
if (Settings::get('demo_mode')) {
return self::get_demo_response($comment_text, $comment_email);
}
// API key check
if (empty(Settings::get('api_key'))) {
return new WP_Error('no_api_key', 'Configure your API key.');
}
try {
// Bouw prompt met context
$prompt = sprintf(
"Analyze this comment.\n\nAuthor: %s\nEmail: %s\nComment: %s",
$comment_author,
$comment_email ?: '(not provided)',
$comment_text
);
// Als comment URLs bevat, hint de AI om email te verifieren
if (preg_match('/https?:\/\//', $comment_text) && !empty($comment_email)) {
$prompt .= "\n\nNote: This comment contains URLs. Please use the verify_email tool to check if the author's email is legitimate.";
}
// AI analyse met structured output
$agent = CommentModeratorAgent::make();
$result = $agent->structured(new UserMessage($prompt), CommentAnalysis::class);
return [
'spam_score' => $result->spam_score,
'action' => $result->action,
'reason' => $result->reason,
];
} catch (\Exception $e) {
return new WP_Error('analysis_failed', $e->getMessage());
}
}
De demo mode heeft ook email verificatie, zodat je zonder API kosten kunt testen:
private static function get_demo_response(string $comment_text, string $comment_email = ''): array
{
$text_lower = strtolower($comment_text);
// Check voor spam keywords
$spam_keywords = ['casino', 'viagra', 'buy now', 'click here', 'free money'];
foreach ($spam_keywords as $keyword) {
if (str_contains($text_lower, $keyword)) {
return ['spam_score' => 0.95, 'action' => 'spam', 'reason' => '[DEMO] Contains spam keywords'];
}
}
// Check email bij URLs
$has_urls = preg_match('/https?:\/\//', $comment_text);
if ($has_urls && !empty($comment_email)) {
$domain = substr(strrchr($comment_email, '@'), 1);
if (!empty($domain)) {
$mxRecords = [];
if (!@getmxrr($domain, $mxRecords) || empty($mxRecords)) {
return ['spam_score' => 0.85, 'action' => 'spam', 'reason' => '[DEMO] URLs with invalid email domain'];
}
}
}
// Te veel links
if (substr_count($text_lower, 'http') > 2) {
return ['spam_score' => 0.95, 'action' => 'spam', 'reason' => '[DEMO] Too many links'];
}
// Korte comments naar review
if (strlen($comment_text) < 10) {
return ['spam_score' => 0.4, 'action' => 'hold', 'reason' => '[DEMO] Very short comment'];
}
return ['spam_score' => 0.1, 'action' => 'approve', 'reason' => '[DEMO] Comment appears legitimate'];
}
Complete Ability class
Bekijk de volledige class op GitHub.
Met de AutoModeration class kunnen we elke nieuwe comment automatisch laten analyseren.
Maak src/AutoModeration.php:
<?php
namespace KO\CommentModerator;
class AutoModeration
{
private static ?array $current_result = null;
public static function init(): void
{
if (!Settings::get('auto_moderate')) {
return;
}
add_filter('preprocess_comment', [self::class, 'analyze_comment']);
add_filter('pre_comment_approved', [self::class, 'set_comment_status'], 10, 2);
add_action('comment_post', [self::class, 'save_analysis_meta'], 10, 2);
}
public static function analyze_comment(array $commentdata): array
{
if (empty($commentdata['comment_content'])) {
return $commentdata;
}
self::$current_result = Ability::execute([
'comment_text' => $commentdata['comment_content'],
'comment_author' => $commentdata['comment_author'] ?? 'Anonymous',
'comment_author_email' => $commentdata['comment_author_email'] ?? '',
]);
if (is_wp_error(self::$current_result)) {
self::$current_result = null;
}
return $commentdata;
}
public static function set_comment_status($approved, array $commentdata)
{
if (self::$current_result === null) {
return $approved;
}
$action = self::$current_result['action'] ?? 'hold';
$spam_score = self::$current_result['spam_score'] ?? 0.5;
$auto_approve = Settings::get('auto_approve_threshold', 0.2);
$auto_spam = Settings::get('auto_spam_threshold', 0.8);
switch ($action) {
case 'approve':
return ($spam_score <= $auto_approve) ? 1 : 0;
case 'spam':
return ($spam_score >= $auto_spam) ? 'spam' : 0;
case 'reject':
return 'trash';
default:
return 0;
}
}
public static function save_analysis_meta(int $comment_id, $approved): void
{
if (self::$current_result === null) {
return;
}
update_comment_meta($comment_id, '_komod_spam_score', self::$current_result['spam_score']);
update_comment_meta($comment_id, '_komod_action', self::$current_result['action']);
update_comment_meta($comment_id, '_komod_reason', self::$current_result['reason']);
self::$current_result = null;
}
}
Let op dat comment_author_email nu wordt meegegeven, zodat de email verificatie ook werkt bij automatische moderatie.
Hoe werkt dit samen met WordPress?
Onze AI-moderatie draait vóór WordPress's ingebouwde checks. De flow is:
Dit geeft meerdere lagen bescherming. We raden aan om Akismet actief te houden naast onze plugin voor maximale spam bescherming.
Om de AI-analyse resultaten direct in het WordPress
KeurigOnline zegtWordPress
Maak src/AdminColumns.php:
<?php
namespace KO\CommentModerator;
class AdminColumns
{
public static function init(): void
{
// Alleen als de instelling aan staat
if (!Settings::get('show_admin_columns', true)) {
return;
}
add_filter('manage_edit-comments_columns', [self::class, 'add_columns']);
add_action('manage_comments_custom_column', [self::class, 'render_columns'], 10, 2);
add_action('admin_head-edit-comments.php', [self::class, 'add_inline_css']);
add_action('admin_footer-edit-comments.php', [self::class, 'enqueue_scripts']);
add_action('wp_ajax_komod_analyze_comment', [self::class, 'ajax_analyze_comment']);
}
public static function add_columns(array $columns): array
{
// Voeg kolommen toe na 'comment'
$new_columns = [];
foreach ($columns as $key => $label) {
$new_columns[$key] = $label;
if ($key === 'comment') {
$new_columns['komod_score'] = 'AI Score';
$new_columns['komod_action'] = 'AI Actie';
}
}
return $new_columns;
}
public static function render_columns(string $column_name, int $comment_id): void
{
if ($column_name === 'komod_score') {
$score = get_comment_meta($comment_id, '_komod_spam_score', true);
if ($score !== '') {
$color = $score < 0.3 ? '#28a745' : ($score < 0.7 ? '#ffc107' : '#dc3545');
echo '<span style="color:' . $color . ';font-weight:bold;">' . number_format((float)$score, 2) . '</span>';
} else {
echo '<button type="button" class="button button-small komod-analyze-btn" data-id="' . $comment_id . '">Analyseer</button>';
}
}
if ($column_name === 'komod_action') {
$action = get_comment_meta($comment_id, '_komod_action', true);
$reason = get_comment_meta($comment_id, '_komod_reason', true);
if ($action) {
echo '<span class="komod-action-badge komod-action-' . esc_attr($action) . '" title="' . esc_attr($reason) . '">' . esc_html($action) . '</span>';
} else {
echo '<span style="color:#999;">-</span>';
}
}
}
}
De class voegt twee kolommen toe:
Voor comments die nog niet geanalyseerd zijn, tonen we een "Analyseer" knop die via AJAX de analyse uitvoert.
Complete AdminColumns class
De volledige class met AJAX handlers, inline CSS, en JavaScript vind je op GitHub.
Instelling: Voeg 'show_admin_columns' => true toe aan de Settings DEFAULTS om deze kolommen optioneel te maken. Gebruikers kunnen dit uitschakelen in Instellingen → Comment Moderator.
Maak ko-comment-moderator.php in de plugin root:
<?php
/**
* Plugin Name: KO Comment Moderator
* Plugin URI: https://github.com/keurigonline/ko-comment-moderator
* Description: WordPress Ability van KeurigOnline die AI gebruikt om comments te analyseren op spam en toxiciteit.
* Version: 1.0.0
* Author: KeurigOnline
* Author URI: https://keurigonline.nl
* License: GPL v2 or later
* License URI: https://www.gnu.org/licenses/gpl-2.0.html
* Requires at least: 6.9
* Requires PHP: 8.0
* Text Domain: ko-comment-moderator
*/
if (!defined('ABSPATH')) {
exit;
}
define('KOMOD_VERSION', '1.0.0');
define('KOMOD_PLUGIN_DIR', plugin_dir_path(__FILE__));
function komod_init(): void
{
// Laad Composer autoloader
$autoloader = KOMOD_PLUGIN_DIR . 'vendor/autoload.php';
if (!file_exists($autoloader)) {
add_action('admin_notices', function() {
echo '<div class="notice notice-error"><p>KO Comment Moderator: Run "composer install" in the plugin directory.</p></div>';
});
return;
}
require_once $autoloader;
// Check voor Abilities API
if (!function_exists('wp_register_ability')) {
add_action('admin_notices', function() {
echo '<div class="notice notice-error"><p>KO Comment Moderator requires WordPress 6.9+ with the Abilities API.</p></div>';
});
return;
}
// Initialiseer alle classes
\KO\CommentModerator\Settings::init();
\KO\CommentModerator\Ability::init();
\KO\CommentModerator\AutoModeration::init();
\KO\CommentModerator\AdminColumns::init();
}
add_action('plugins_loaded', 'komod_init');
Activeer de plugin:
wp plugin activate ko-comment-moderator
Ga naar Instellingen → Comment Moderator en zorg dat Demo Mode aan staat.
Test via PHP
KeurigOnline zegtPHP
use KO\CommentModerator\Ability;
// Test 1: Normale comment
$result = Ability::execute([
'comment_text' => 'Great article about WordPress!',
'comment_author' => 'Jan'
]);
// Result: spam_score=0.1, action=approve
// Test 2: Spam keywords
$result = Ability::execute([
'comment_text' => 'Buy viagra at our casino!'
]);
// Result: spam_score=0.95, action=spam
// Test 3: URL met fake email domein
$result = Ability::execute([
'comment_text' => 'Check https://example.com now!',
'comment_author_email' => 'fake@nonexistent-domain-xyz.com'
]);
// Result: spam_score=0.85, action=spam
// Test 4: URL met valid email domein
$result = Ability::execute([
'comment_text' => 'Check https://example.com for more!',
'comment_author_email' => 'user@gmail.com'
]);
// Result: spam_score=0.1, action=approve
De email verificatie werkt: een comment met URL en fake email wordt als spam gemarkeerd, terwijl dezelfde comment met een valide email wordt goedgekeurd.
De complete plugin structuur:
ko-comment-moderator/
├── ko-comment-moderator.php # Main plugin file
├── composer.json
├── README.md
├── src/
│ ├── Ability.php # WordPress Ability registration
│ ├── AdminColumns.php # AI kolommen in Reacties tabel
│ ├── AutoModeration.php # Auto-moderate hook
│ ├── CommentAnalysis.php # Structured output schema
│ ├── CommentModeratorAgent.php # AI agent
│ ├── Settings.php # Admin UI
│ └── Tools/ # Agent tools
│ └── VerifyEmailTool.php # Email verification
└── vendor/ # Composer dependencies (included)
De Tools/ directory houdt de agent-tools gescheiden. Dit maakt het makkelijk om meer tools toe te voegen, zoals een URL scanner of duplicate checker.
Bij het ontwikkelen met Neuron en de Abilities API
KeurigOnline zegtAPI
Controleer of je wp_abilities_api_init gebruikt (met wp_ prefix). Zonder prefix wordt de ability stil genegeerd.
Neuron v2 vereist ToolProperty::make() met een PropertyType enum. De oude syntax addProperty('name', 'type', 'desc') werkt niet meer.
In CLI context is er geen ingelogde gebruiker. Roep wp_set_current_user(1) aan voordat je de ability uitvoert.
Controleer of de vendor/ directory aanwezig is. Bij download van GitHub
KeurigOnline zegtGithub