Bestellen
Hosting
Domeinnaam
Ondersteuning
Ontdek

Op deze pagina

Blog / WordPress · · ~20 min lezen

AI Comment Moderator bouwen met Neuron v2 en WordPress Abilities

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.

Geschreven door: Pablo Cleij Pablo Cleij
Deel dit artikel

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 PHPKeurigOnline zegtPHPPHP (Hypertext Preprocessor) is een populaire open-source scripttaal die speciaal is ontworpen voor webontwikkeling en server-side programmering. AI agent framework) en de nieuwe WordPressKeurigOnline zegtWordPressWordPress is een open-source contentmanagementsysteem (CMS) geschreven in PHP, waarmee je eenvoudig websites en blogs kunt bouwen en beheren. Abilities APIKeurigOnline zegtAPIEen API (Application Programming Interface) is een set regels en protocollen waarmee softwareapplicaties met elkaar kunnen communiceren en gegevens uitwisselen.. Het resultaat: een plugin die comments analyseert en automatisch classificeert.

De complete code vind je op GitHub.


Wat gaan we bouwen?

Onze plugin bestaat uit zeven classes die we stuk voor stuk opbouwen:

  1. CommentAnalysis - Definieert de structuur van het AI-antwoord
  2. VerifyEmailTool - Tool om email domeinen te verifiëren
  3. CommentModeratorAgent - De AI agent die comments analyseert
  4. Settings - Beheert plugin instellingen via WordPress admin
  5. Ability - Registreert de moderatie als WordPress Ability
  6. AutoModeration - Optionele automatische moderatie van nieuwe comments
  7. AdminColumns - Toont AI-analyse in de WordPress Reacties tabel

Vereisten

  • WordPress 6.9+ met Abilities API
  • PHP 8.0+
  • Composer
  • OpenAI API key (of gebruik demo mode)

Project setup

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

Composer configuratie

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.


CommentAnalysis: de output structuur

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:

  • spam_score - Getal tussen 0 en 1 dat aangeeft hoe waarschijnlijk spam is
  • action - Aanbevolen actie: approve, hold, reject, of spam
  • reason - Korte uitleg voor de beslissing

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.


VerifyEmailTool: email verificatie

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',
    ];
}

De tool registreren

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.

De execute method

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:

  1. Email formaat - Is het een geldig email adres?
  2. Wegwerp-domeinen - Bekende tijdelijke email diensten
  3. MX records - Heeft het domein een mail server?
  4. A records - Bestaat het domein überhaupt?

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.


CommentModeratorAgent: de AI agent

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.

De system prompt

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.

Tools registreren

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.


Settings: de instellingen pagina

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:

  • API Key - OpenAI API key (password field)
  • Demo Mode - Test zonder APIKeurigOnline zegtAPIEen API (Application Programming Interface) is een set regels en protocollen waarmee softwareapplicaties met elkaar kunnen communiceren en gegevens uitwisselen. kosten
  • Auto-Moderation - Analyseer automatisch alle nieuwe comments
  • Thresholds - Wanneer auto-approve/spam?
  • Admin Columns - Toon AI-info in de Reacties tabel
  • Test form - Probeer de moderator direct uit

Complete Settings class

De volledige class met alle render methods, het test formulier, en sanitization vind je op GitHub.


Ability: WordPress Abilities API integratie

Nu verbinden we alles met de WordPress Abilities API. Dit maakt onze moderator beschikbaar via REST API, WP-CLIKeurigOnline zegtWP-CLIWP-CLI is de command line interface voor WordPress waarmee ontwikkelaars WordPress beheren via de terminal., en MCP.

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.

De ability registreren

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 callback

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());
    }
}

Demo mode

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.


AutoModeration: automatisch modereren

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:

  1. Onze plugin analyseert de comment en stelt een status voor
  2. WordPress built-in checks (block lists, moderation keywords)
  3. Akismet (indien actief) - extra spam filtering

Dit geeft meerdere lagen bescherming. We raden aan om Akismet actief te houden naast onze plugin voor maximale spam bescherming.


AdminColumns: AI-info in de Reacties tabel

Om de AI-analyse resultaten direct in het WordPressKeurigOnline zegtWordPressWordPress is een open-source contentmanagementsysteem (CMS) geschreven in PHP, waarmee je eenvoudig websites en blogs kunt bouwen en beheren. admin te zien, voegen we custom kolommen toe aan de Reacties tabel. Dit maakt het makkelijk om snel te zien waarom een comment is goedgekeurd of als spam gemarkeerd.

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>';
            }
        }
    }
}

Wat de kolommen tonen

De class voegt twee kolommen toe:

  • AI Score - De spam_score met kleurcodering (groen < 0.3, geel 0.3-0.7, rood > 0.7)
  • AI Actie - De aanbevolen actie met tooltip voor de reden

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.


De main plugin file

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');

Testen

Activeer de plugin:

wp plugin activate ko-comment-moderator

Ga naar Instellingen → Comment Moderator en zorg dat Demo Mode aan staat.

Test scenarios

Test via PHPKeurigOnline zegtPHPPHP (Hypertext Preprocessor) is een populaire open-source scripttaal die speciaal is ontworpen voor webontwikkeling en server-side programmering. met verschillende scenarios:

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.


Project structuur

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.


Veel voorkomende problemen

Bij het ontwikkelen met Neuron en de Abilities APIKeurigOnline zegtAPIEen API (Application Programming Interface) is een set regels en protocollen waarmee softwareapplicaties met elkaar kunnen communiceren en gegevens uitwisselen. kun je tegen deze issues aanlopen:

Ability wordt niet geregistreerd

Controleer of je wp_abilities_api_init gebruikt (met wp_ prefix). Zonder prefix wordt de ability stil genegeerd.

TypeError: addProperty() expects ToolPropertyInterface

Neuron v2 vereist ToolProperty::make() met een PropertyType enum. De oude syntax addProperty('name', 'type', 'desc') werkt niet meer.

"Permission denied" in WP-CLI

In CLI context is er geen ingelogde gebruiker. Roep wp_set_current_user(1) aan voordat je de ability uitvoert.

"Class not found" errors

Controleer of de vendor/ directory aanwezig is. Bij download van GitHubKeurigOnline zegtGithubGitHub is een cloudplatform voor versiebeheer en samenwerking aan softwareprojecten met Git. is deze meegeleverd.


Bronnen