Blocklist for moderating listings

No doubt it’s one of the best script but what I am looking for is word filter that can filter some ( abusive,http, https ) like words in url, description that can control spams on website with minimum human involvement. Many spammers just come to spam postings many times with links etc. If have better traffic 100 of ads need to check manually.
I tried many plugins but none works better as it’s mostly for posts &pages n not specific listings etc.

Thanks for your feedback, we’ll try to add more features for automatic moderation. The blocklist is already available for messages but not for listings yet.

2 Likes

Please add this feature as soon as possible. Filtering listings one by one to protect spam is too much time consuming.

3 Likes

Any development regarding block words for title & description

Hi,

Unfortunately, there is no exact timeframe, as we release new features depending on user votes and when the feature request was published. If you need this feature urgently, please consider hiring someone for custom work: https://fvrr.co/32e7LvY

Yeah this is a necessary feature.

1 Like

I hope that the blocklist feature can be ported from Messages plugin to a main plugin or all (since reviews should also be checked against illegal content).

There is a workaround (disadvantage is that the user is not informed about why their submission not saved their data)

A) (untested, AI suggested plugin “Wordfence Security” (needs to register free account license) Wordfence > All Options > Firewall > Advanced Firewall Options > Blocked Words

B) custom Wordpress plugin which seems to block any submissions containing blocked phrases, but it fails to inform user that the submission has been denied and it lasks significant features which are part of the solution “C)” below. Plugin code (please help improve it): Validate listing's description field for prohibited words

C) custom PHP code snippet for a WP plugin Code snippets (or similar). Generated using HivePress AI and tested to:

  • Block “Add listing” form submission and optionally user IP+UserAgent combination(for 24 hours) if submission contains words/phrases/regular expressions from blocklist files
  • That blocking is done by resetting user password, prefixinx their email with blocked and logout user.
  • When a temporary user IP+UA combination blocking is enabled, user will be unable to submit the Add listing form in next 24 hours(or other defined period) no matter which account they are using and no matter if they submission contains blocked phrases. Whole user blocking function and blocking period is optional.

Script setup:

  1. set to false “$ip_ua_blocklist_enabled = true;” if you do not want to block IP and UserAgent combinations of a users who have submit forbidden phrase, for a limited period of time (24 hours by default).
  2. create .txt files mentioned in the PHP code header
  3. replace /report-abuse-contact (2x) with your contact page address
define('HIVEPRESS_BLOCKLIST_ENABLED', true); // Enable temporary blocking of a UserAgent and IP of a user who submit blocked phrase
define('HIVEPRESS_BLOCKLIST_RETENTION_SECONDS', 86400); // For how many seconds that IP+UA will be blocked? 86400 = 1 day

 

add_filter(
    'hivepress/v1/forms/listing_update/errors',
    function( $errors, $form ) {
        $stylesheet_dir = get_stylesheet_directory();
        
        // Define paths once
        $forbidden_file = $stylesheet_dir . '/forbidden-strings.txt';
        $forbidden_regex_file = $stylesheet_dir . '/forbidden-strings-regex.txt';
        $forbidden_exact_file = $stylesheet_dir . '/forbidden-strings-exact-match.txt';
        $ip_ua_blocklist_file = $stylesheet_dir . '/forbidden-ips-ua-submissions.txt';
       
        $user_id = get_current_user_id();
        $user_ip = $_SERVER['REMOTE_ADDR'] ?? '';
        $user_agent = $_SERVER['HTTP_USER_AGENT'] ?? '';
        $ip_ua_combination = $user_ip . '|' . $user_agent;

        // Configuration (Using Constants)
        $ip_ua_blocklist_enabled = HIVEPRESS_BLOCKLIST_ENABLED;
        $ip_ua_blocklist_retention_seconds = HIVEPRESS_BLOCKLIST_RETENTION_SECONDS;
                
        // Check against IP+UA blocklist
        $ip_ua_blocked = false;
        if ( $ip_ua_blocklist_enabled && file_exists( $ip_ua_blocklist_file ) ) {
            $blocked_combinations = file( $ip_ua_blocklist_file, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES );
            if ( $blocked_combinations && in_array( $ip_ua_combination, $blocked_combinations, true ) ) {
                $ip_ua_blocked = true;
            }
        }

        // If already blocked, disable and exit immediately without checking content
        if ( $ip_ua_blocked ) {
            disable_and_logout_user( $user_id );
            $errors[] = 'Your account has just been disabled due to previous violations from the same or a similar visitor. <br />If you continue to see this repeatedly in the last few days or weeks, despite not submitting any forbidden phrases, do not navigate away from this page. Instead, copy this message and your submission content, and provide this data to the moderators via the <a href='' target="_blank">contact/report page</a>, so that we can check the forbidden* .txt file for your IP address ' . esc_html( $user_ip ) . ' and that the file is being emptied by our code snippet.';
            return $errors;
        }

        $values = $form->get_values();
        $content_to_check = '';
        $fields_to_check = [ 'title', 'description' ];
        
        foreach ( $fields_to_check as $field ) {
            if ( isset( $values[ $field ] ) ) {
                $content_to_check .= ' ' . $values[ $field ];
            }
        }
        
        $content_lower = strtolower( $content_to_check );
        $blocked_string = '';
        
        // Check against forbidden strings (literal partial matching)
        if ( file_exists( $forbidden_file ) ) {
            $forbidden_strings = file( $forbidden_file, FILE_IGNORE_NEW_LINES );
            
            if ( $forbidden_strings ) {
                foreach ( $forbidden_strings as $forbidden ) {
                    $forbidden_lower = strtolower( $forbidden );
                    
                    if ( ! empty( $forbidden_lower ) && strpos( $content_lower, $forbidden_lower ) !== false ) {
                        $blocked_string = $forbidden;
                        break;
                    }
                }
            }
        }
        
        // Check against exact match (word boundaries)
        if ( ! $blocked_string && file_exists( $forbidden_exact_file ) ) {
            $exact_strings = file( $forbidden_exact_file, FILE_IGNORE_NEW_LINES );
            
            if ( $exact_strings ) {
                foreach ( $exact_strings as $exact ) {
                    $exact_lower = strtolower( $exact );
                    
                    if ( ! empty( $exact_lower ) ) {
                        $pattern = '/(?<![a-z0-9])' . preg_quote( $exact_lower, '/' ) . '(?![a-z0-9])/i';
                        
                        if ( preg_match( $pattern, $content_lower ) ) {
                            $blocked_string = $exact;
                            break;
                        }
                    }
                }
            }
        }
        
        // Check against regex patterns
        if ( ! $blocked_string && file_exists( $forbidden_regex_file ) ) {
            $regex_patterns = file( $forbidden_regex_file, FILE_IGNORE_NEW_LINES );
            
            if ( $regex_patterns ) {
                foreach ( $regex_patterns as $pattern ) {
                    $pattern = trim( $pattern );
                    
                    if ( ! empty( $pattern ) ) {
                        $pattern = '/' . $pattern . '/i';
                        
                        if ( @preg_match( $pattern, $content_lower ) ) {
                            $blocked_string = $pattern;
                            break;
                        }
                    }
                }
            }
        }
        
        // Is IP+UA in a ip_ua_blocklist_file?
        $ip_ua_blocked = false;
        if ( $ip_ua_blocklist_enabled && file_exists( $ip_ua_blocklist_file ) ) {
            $blocked_combinations = file( $ip_ua_blocklist_file, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES );
            
            if ( $blocked_combinations && in_array( $ip_ua_combination, $blocked_combinations, true ) ) {
                $ip_ua_blocked = true;
            }
        }
        
        // Is forbidden content detected?
        if ( $blocked_string ) {
            // Add IP+UA to blocklist
            if ( $ip_ua_blocklist_enabled ) {
                file_put_contents( $ip_ua_blocklist_file, $ip_ua_combination . "\n", FILE_APPEND | LOCK_EX );
            }
            
            // Disable account and logout
            disable_and_logout_user( $user_id );
            
            $errors[] = 'You have submit forbidden content "' . esc_html( $blocked_string ) . '". Account ' . esc_html( $user_id ) . ' can no longer be used and you have been logged out and your IP ' . esc_html( $user_ip ) . ' temporarily logged.<br />If this is a false positive, do not navigate away from this page. Instead, copy this message and your submission content, and provide the data to the moderators using <a href='' target="_blank">contact/report page</a>.';
            return $errors;
        }
                
        return $errors;
    },
    1000,
    2
);

 

// Helper function to disable account and logout
function disable_and_logout_user( $user_id ) {
    // Reset password to random string
    $random_password = wp_generate_password( 32, true, true );
    wp_set_password( $random_password, $user_id );
    
    // Mark email as blocked (standard field modification)
    $user = get_user_by( 'id', $user_id );
    wp_update_user( [
        'ID' => $user_id,
        'user_email' => '_blocked_' . $user->user_email,
    ] );
    
    // Logout user
    wp_logout();
}

 

// Clear blocklist file every 24 hours
add_action( 'wp_loaded', function() { 
    $ip_ua_blocklist_file = get_stylesheet_directory() . '/forbidden-ips-ua-submissions.txt';
    $retention = HIVEPRESS_BLOCKLIST_RETENTION_SECONDS;
    $transient_key = 'hivepress_blocklist_cleared';
    
    if ( ! get_transient( $transient_key ) ) {
        if ( file_exists( $ip_ua_blocklist_file ) ) {
            file_put_contents( $ip_ua_blocklist_file, '' );
        }
        // Use the variable defined earlier if passed, otherwise default
        set_transient( $transient_key, 1, $ip_ua_blocklist_retention_seconds ?? 86400 );
    }
} );

Hi,

Thank you for your feedback. This feature is already on our roadmap and will be implemented in future updates.

We’ve also provided guidance in your other topic, which is related to this request.