Plugin Directory

Changeset 3466837


Ignore:
Timestamp:
02/22/2026 10:55:56 AM (5 weeks ago)
Author:
aamato
Message:

Release 1.2.3

Location:
spamanvil
Files:
12 edited
1 copied

Legend:

Unmodified
Added
Removed
  • spamanvil/tags/1.2.3/admin/class-spamanvil-admin.php

    r3461590 r3466837  
    397397        }
    398398
    399         // Get all comments with 'hold' status.
    400         $comments = get_comments( array( 'status' => 'hold', 'number' => 0 ) );
    401 
    402         if ( empty( $comments ) ) {
    403             wp_send_json_success( array(
    404                 'enqueued'       => 0,
    405                 'auto_spam'      => 0,
    406                 'already_queued' => 0,
    407             ) );
    408         }
    409 
    410         // Get comment IDs already in the queue.
    411         global $wpdb;
    412         $queue_table       = $wpdb->prefix . 'spamanvil_queue';
    413         $already_queued_ids = $wpdb->get_col( "SELECT comment_id FROM {$queue_table} WHERE status IN ('queued', 'processing', 'failed')" ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared, PluginCheck.Security.DirectDB.UnescapedDBParameter -- custom plugin table, table name from $wpdb->prefix.
    414 
    415         $enqueued       = 0;
    416         $auto_spam      = 0;
    417         $already_queued = 0;
    418 
    419         $heuristic_threshold = (int) get_option( 'spamanvil_heuristic_auto_spam', 95 );
    420 
    421         foreach ( $comments as $comment ) {
    422             if ( in_array( (string) $comment->comment_ID, $already_queued_ids, true ) ) {
    423                 $already_queued++;
    424                 continue;
    425             }
    426 
    427             // Run heuristics.
    428             $analysis = $this->heuristics->analyze( array(
    429                 'comment_content'      => $comment->comment_content,
    430                 'comment_author'       => $comment->comment_author,
    431                 'comment_author_email' => $comment->comment_author_email,
    432                 'comment_author_url'   => $comment->comment_author_url,
    433             ) );
    434 
    435             if ( $analysis['score'] >= $heuristic_threshold ) {
    436                 wp_spam_comment( $comment->comment_ID );
    437                 $this->stats->increment( 'heuristic_blocked' );
    438                 $this->stats->increment( 'comments_checked' );
    439                 $this->stats->log_evaluation( array(
    440                     'comment_id'        => $comment->comment_ID,
    441                     'score'             => $analysis['score'],
    442                     'provider'          => 'heuristics',
    443                     'model'             => 'regex',
    444                     'reason'            => 'Auto-blocked by heuristic analysis (scan pending)',
    445                     'heuristic_score'   => $analysis['score'],
    446                     'heuristic_details' => $this->heuristics->format_for_prompt( $analysis ),
    447                 ) );
    448 
    449                 $ip = get_comment_author_IP( $comment->comment_ID );
    450                 if ( ! empty( $ip ) ) {
    451                     $this->ip_manager->record_spam_attempt( $ip );
    452                 }
    453 
    454                 $auto_spam++;
    455             } else {
    456                 $this->queue->enqueue( $comment->comment_ID, $analysis['score'] );
    457                 $enqueued++;
    458             }
    459         }
     399        // Count pending comments before scanning for the already_queued stat.
     400        $pending_count = (int) wp_count_comments()->moderated;
     401
     402        // Capture stats before to compute auto_spam count.
     403        $heuristic_before = $this->stats->get_total( 'heuristic_blocked' );
     404
     405        $enqueued = $this->queue->auto_enqueue_pending( 0 ); // 0 = scan all (manual action).
     406
     407        $heuristic_after = $this->stats->get_total( 'heuristic_blocked' );
     408        $auto_spam       = $heuristic_after - $heuristic_before;
     409        $already_queued  = max( 0, $pending_count - $enqueued - $auto_spam );
    460410
    461411        // Trigger immediate cron run so the queue starts processing without waiting.
  • spamanvil/tags/1.2.3/includes/class-spamanvil-queue.php

    r3466819 r3466837  
    7878
    7979        try {
    80             $batch_size = (int) get_option( 'spamanvil_batch_size', 5 );
     80            $batch_size     = (int) get_option( 'spamanvil_batch_size', 5 );
     81            $auto_enqueued  = false;
    8182
    8283            // Loop through batches until queue is empty or time runs out.
     
    8586
    8687                if ( empty( $items ) ) {
     88                    // Queue is empty — try to auto-enqueue pending WordPress comments.
     89                    if ( ! $auto_enqueued && ! $force ) {
     90                        $auto_enqueued  = true;
     91                        $newly_enqueued = $this->auto_enqueue_pending();
     92                        if ( $newly_enqueued > 0 ) {
     93                            continue; // Re-enter loop to process newly enqueued items.
     94                        }
     95                    }
    8796                    break;
    8897                }
     
    645654    }
    646655
     656    /**
     657     * Auto-enqueue pending WordPress comments that are not already in the queue.
     658     *
     659     * Scans for comments with 'hold' status, runs heuristics on each, and either
     660     * auto-spams (high heuristic score) or enqueues for LLM analysis.
     661     *
     662     * @param int $limit Max comments to scan. 0 = unlimited. Default 100 (safe for cron).
     663     * @return int Number of comments enqueued for LLM analysis.
     664     */
     665    public function auto_enqueue_pending( $limit = 100 ) {
     666        global $wpdb;
     667
     668        // Skip if no provider is configured — nothing to process.
     669        if ( '' === get_option( 'spamanvil_primary_provider', '' ) ) {
     670            return 0;
     671        }
     672
     673        // Get comment IDs already in the queue (active statuses).
     674        $already_queued_ids = $wpdb->get_col(
     675            "SELECT comment_id FROM {$this->table} WHERE status IN ('queued', 'processing', 'failed', 'max_retries')"
     676        );
     677
     678        $comments = get_comments( array(
     679            'status' => 'hold',
     680            'number' => $limit,
     681        ) );
     682
     683        if ( empty( $comments ) ) {
     684            return 0;
     685        }
     686
     687        $enqueued             = 0;
     688        $heuristic_threshold  = (int) get_option( 'spamanvil_heuristic_auto_spam', 95 );
     689
     690        foreach ( $comments as $comment ) {
     691            if ( in_array( (string) $comment->comment_ID, $already_queued_ids, true ) ) {
     692                continue;
     693            }
     694
     695            // Run heuristics.
     696            $analysis = $this->heuristics->analyze( array(
     697                'comment_content'      => $comment->comment_content,
     698                'comment_author'       => $comment->comment_author,
     699                'comment_author_email' => $comment->comment_author_email,
     700                'comment_author_url'   => $comment->comment_author_url,
     701            ) );
     702
     703            if ( $analysis['score'] >= $heuristic_threshold ) {
     704                wp_spam_comment( $comment->comment_ID );
     705                $this->stats->increment( 'heuristic_blocked' );
     706                $this->stats->increment( 'comments_checked' );
     707                $this->stats->log_evaluation( array(
     708                    'comment_id'        => $comment->comment_ID,
     709                    'score'             => $analysis['score'],
     710                    'provider'          => 'heuristics',
     711                    'model'             => 'regex',
     712                    'reason'            => 'Auto-blocked by heuristic analysis (auto-enqueue)',
     713                    'heuristic_score'   => $analysis['score'],
     714                    'heuristic_details' => $this->heuristics->format_for_prompt( $analysis ),
     715                ) );
     716
     717                $ip = get_comment_author_IP( $comment->comment_ID );
     718                if ( ! empty( $ip ) ) {
     719                    $this->ip_manager->record_spam_attempt( $ip );
     720                }
     721            } else {
     722                $this->enqueue( $comment->comment_ID, $analysis['score'] );
     723                $enqueued++;
     724            }
     725        }
     726
     727        return $enqueued;
     728    }
     729
    647730    public function get_queue_status() {
    648731        global $wpdb;
  • spamanvil/tags/1.2.3/languages/spamanvil-pt_BR.po

    r3466819 r3466837  
    66msgid ""
    77msgstr ""
    8 "Project-Id-Version: SpamAnvil 1.2.2\n"
     8"Project-Id-Version: SpamAnvil 1.2.3\n"
    99"Report-Msgid-Bugs-To: https://software.amato.com.br/spamanvil-antispam-"
    1010"plugin-for-wordpress/\n"
  • spamanvil/tags/1.2.3/readme.txt

    r3466819 r3466837  
    66Tested up to: 6.9
    77Requires PHP: 7.4
    8 Stable tag: 1.2.2
     8Stable tag: 1.2.3
    99License: GPLv2 or later
    1010License URI: https://www.gnu.org/licenses/gpl-2.0.html
     
    215215== Changelog ==
    216216
     217= 1.2.3 =
     218* Feature: Cron now automatically scans pending WordPress comments when the queue is empty — no manual "Scan Pending" click needed
     219
    217220= 1.2.2 =
    218221* Feature: "Last automatic run" timestamp in Queue Status card shows when WP-Cron last processed the queue
  • spamanvil/tags/1.2.3/spamanvil.php

    r3466819 r3466837  
    44 * Plugin URI:        https://software.amato.com.br/spamanvil-antispam-plugin-for-wordpress/
    55 * Description:       Blocks comment spam using AI/LLM services with support for multiple providers, async processing, and intelligent heuristics.
    6  * Version:           1.2.2
     6 * Version:           1.2.3
    77 * Requires at least: 5.8
    88 * Requires PHP:      7.4
     
    1919}
    2020
    21 define( 'SPAMANVIL_VERSION', '1.2.2' );
     21define( 'SPAMANVIL_VERSION', '1.2.3' );
    2222define( 'SPAMANVIL_DB_VERSION', '1.0.0' );
    2323define( 'SPAMANVIL_PLUGIN_FILE', __FILE__ );
  • spamanvil/trunk/admin/class-spamanvil-admin.php

    r3461590 r3466837  
    397397        }
    398398
    399         // Get all comments with 'hold' status.
    400         $comments = get_comments( array( 'status' => 'hold', 'number' => 0 ) );
    401 
    402         if ( empty( $comments ) ) {
    403             wp_send_json_success( array(
    404                 'enqueued'       => 0,
    405                 'auto_spam'      => 0,
    406                 'already_queued' => 0,
    407             ) );
    408         }
    409 
    410         // Get comment IDs already in the queue.
    411         global $wpdb;
    412         $queue_table       = $wpdb->prefix . 'spamanvil_queue';
    413         $already_queued_ids = $wpdb->get_col( "SELECT comment_id FROM {$queue_table} WHERE status IN ('queued', 'processing', 'failed')" ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared, PluginCheck.Security.DirectDB.UnescapedDBParameter -- custom plugin table, table name from $wpdb->prefix.
    414 
    415         $enqueued       = 0;
    416         $auto_spam      = 0;
    417         $already_queued = 0;
    418 
    419         $heuristic_threshold = (int) get_option( 'spamanvil_heuristic_auto_spam', 95 );
    420 
    421         foreach ( $comments as $comment ) {
    422             if ( in_array( (string) $comment->comment_ID, $already_queued_ids, true ) ) {
    423                 $already_queued++;
    424                 continue;
    425             }
    426 
    427             // Run heuristics.
    428             $analysis = $this->heuristics->analyze( array(
    429                 'comment_content'      => $comment->comment_content,
    430                 'comment_author'       => $comment->comment_author,
    431                 'comment_author_email' => $comment->comment_author_email,
    432                 'comment_author_url'   => $comment->comment_author_url,
    433             ) );
    434 
    435             if ( $analysis['score'] >= $heuristic_threshold ) {
    436                 wp_spam_comment( $comment->comment_ID );
    437                 $this->stats->increment( 'heuristic_blocked' );
    438                 $this->stats->increment( 'comments_checked' );
    439                 $this->stats->log_evaluation( array(
    440                     'comment_id'        => $comment->comment_ID,
    441                     'score'             => $analysis['score'],
    442                     'provider'          => 'heuristics',
    443                     'model'             => 'regex',
    444                     'reason'            => 'Auto-blocked by heuristic analysis (scan pending)',
    445                     'heuristic_score'   => $analysis['score'],
    446                     'heuristic_details' => $this->heuristics->format_for_prompt( $analysis ),
    447                 ) );
    448 
    449                 $ip = get_comment_author_IP( $comment->comment_ID );
    450                 if ( ! empty( $ip ) ) {
    451                     $this->ip_manager->record_spam_attempt( $ip );
    452                 }
    453 
    454                 $auto_spam++;
    455             } else {
    456                 $this->queue->enqueue( $comment->comment_ID, $analysis['score'] );
    457                 $enqueued++;
    458             }
    459         }
     399        // Count pending comments before scanning for the already_queued stat.
     400        $pending_count = (int) wp_count_comments()->moderated;
     401
     402        // Capture stats before to compute auto_spam count.
     403        $heuristic_before = $this->stats->get_total( 'heuristic_blocked' );
     404
     405        $enqueued = $this->queue->auto_enqueue_pending( 0 ); // 0 = scan all (manual action).
     406
     407        $heuristic_after = $this->stats->get_total( 'heuristic_blocked' );
     408        $auto_spam       = $heuristic_after - $heuristic_before;
     409        $already_queued  = max( 0, $pending_count - $enqueued - $auto_spam );
    460410
    461411        // Trigger immediate cron run so the queue starts processing without waiting.
  • spamanvil/trunk/includes/class-spamanvil-queue.php

    r3466819 r3466837  
    7878
    7979        try {
    80             $batch_size = (int) get_option( 'spamanvil_batch_size', 5 );
     80            $batch_size     = (int) get_option( 'spamanvil_batch_size', 5 );
     81            $auto_enqueued  = false;
    8182
    8283            // Loop through batches until queue is empty or time runs out.
     
    8586
    8687                if ( empty( $items ) ) {
     88                    // Queue is empty — try to auto-enqueue pending WordPress comments.
     89                    if ( ! $auto_enqueued && ! $force ) {
     90                        $auto_enqueued  = true;
     91                        $newly_enqueued = $this->auto_enqueue_pending();
     92                        if ( $newly_enqueued > 0 ) {
     93                            continue; // Re-enter loop to process newly enqueued items.
     94                        }
     95                    }
    8796                    break;
    8897                }
     
    645654    }
    646655
     656    /**
     657     * Auto-enqueue pending WordPress comments that are not already in the queue.
     658     *
     659     * Scans for comments with 'hold' status, runs heuristics on each, and either
     660     * auto-spams (high heuristic score) or enqueues for LLM analysis.
     661     *
     662     * @param int $limit Max comments to scan. 0 = unlimited. Default 100 (safe for cron).
     663     * @return int Number of comments enqueued for LLM analysis.
     664     */
     665    public function auto_enqueue_pending( $limit = 100 ) {
     666        global $wpdb;
     667
     668        // Skip if no provider is configured — nothing to process.
     669        if ( '' === get_option( 'spamanvil_primary_provider', '' ) ) {
     670            return 0;
     671        }
     672
     673        // Get comment IDs already in the queue (active statuses).
     674        $already_queued_ids = $wpdb->get_col(
     675            "SELECT comment_id FROM {$this->table} WHERE status IN ('queued', 'processing', 'failed', 'max_retries')"
     676        );
     677
     678        $comments = get_comments( array(
     679            'status' => 'hold',
     680            'number' => $limit,
     681        ) );
     682
     683        if ( empty( $comments ) ) {
     684            return 0;
     685        }
     686
     687        $enqueued             = 0;
     688        $heuristic_threshold  = (int) get_option( 'spamanvil_heuristic_auto_spam', 95 );
     689
     690        foreach ( $comments as $comment ) {
     691            if ( in_array( (string) $comment->comment_ID, $already_queued_ids, true ) ) {
     692                continue;
     693            }
     694
     695            // Run heuristics.
     696            $analysis = $this->heuristics->analyze( array(
     697                'comment_content'      => $comment->comment_content,
     698                'comment_author'       => $comment->comment_author,
     699                'comment_author_email' => $comment->comment_author_email,
     700                'comment_author_url'   => $comment->comment_author_url,
     701            ) );
     702
     703            if ( $analysis['score'] >= $heuristic_threshold ) {
     704                wp_spam_comment( $comment->comment_ID );
     705                $this->stats->increment( 'heuristic_blocked' );
     706                $this->stats->increment( 'comments_checked' );
     707                $this->stats->log_evaluation( array(
     708                    'comment_id'        => $comment->comment_ID,
     709                    'score'             => $analysis['score'],
     710                    'provider'          => 'heuristics',
     711                    'model'             => 'regex',
     712                    'reason'            => 'Auto-blocked by heuristic analysis (auto-enqueue)',
     713                    'heuristic_score'   => $analysis['score'],
     714                    'heuristic_details' => $this->heuristics->format_for_prompt( $analysis ),
     715                ) );
     716
     717                $ip = get_comment_author_IP( $comment->comment_ID );
     718                if ( ! empty( $ip ) ) {
     719                    $this->ip_manager->record_spam_attempt( $ip );
     720                }
     721            } else {
     722                $this->enqueue( $comment->comment_ID, $analysis['score'] );
     723                $enqueued++;
     724            }
     725        }
     726
     727        return $enqueued;
     728    }
     729
    647730    public function get_queue_status() {
    648731        global $wpdb;
  • spamanvil/trunk/languages/spamanvil-pt_BR.po

    r3466819 r3466837  
    66msgid ""
    77msgstr ""
    8 "Project-Id-Version: SpamAnvil 1.2.2\n"
     8"Project-Id-Version: SpamAnvil 1.2.3\n"
    99"Report-Msgid-Bugs-To: https://software.amato.com.br/spamanvil-antispam-"
    1010"plugin-for-wordpress/\n"
  • spamanvil/trunk/readme.txt

    r3466819 r3466837  
    66Tested up to: 6.9
    77Requires PHP: 7.4
    8 Stable tag: 1.2.2
     8Stable tag: 1.2.3
    99License: GPLv2 or later
    1010License URI: https://www.gnu.org/licenses/gpl-2.0.html
     
    215215== Changelog ==
    216216
     217= 1.2.3 =
     218* Feature: Cron now automatically scans pending WordPress comments when the queue is empty — no manual "Scan Pending" click needed
     219
    217220= 1.2.2 =
    218221* Feature: "Last automatic run" timestamp in Queue Status card shows when WP-Cron last processed the queue
  • spamanvil/trunk/spamanvil.php

    r3466819 r3466837  
    44 * Plugin URI:        https://software.amato.com.br/spamanvil-antispam-plugin-for-wordpress/
    55 * Description:       Blocks comment spam using AI/LLM services with support for multiple providers, async processing, and intelligent heuristics.
    6  * Version:           1.2.2
     6 * Version:           1.2.3
    77 * Requires at least: 5.8
    88 * Requires PHP:      7.4
     
    1919}
    2020
    21 define( 'SPAMANVIL_VERSION', '1.2.2' );
     21define( 'SPAMANVIL_VERSION', '1.2.3' );
    2222define( 'SPAMANVIL_DB_VERSION', '1.0.0' );
    2323define( 'SPAMANVIL_PLUGIN_FILE', __FILE__ );
Note: See TracChangeset for help on using the changeset viewer.