Published on

Xử lý comment spam WordPress theo cách của bạn

Authors

Comment spam trên blog WordPress vẫn là một vấn nạn khá nhức nhối kể từ xa xưa đến bây giờ. Không hiểu sao dạo gần đây plugin Akismet 🔗 thần thánh không thể lọc được spam nữa nên comment spam cứ thế mà liên tục được bắn vào, rất là khó chịu trong khi mình không muốn lọc comment. Ngoài ra, đây cũng là cơ hội hay để thử nghiệm cách lọc spam mà không phụ thuộc vào plugin và Javascript để xem có hiệu quả hay không.

Cách xử lý khác nhau dựa trên cách hoạt động của từng website. Mong rằng bài viết này có thể giúp bạn xử lý tốt hơn mà không phải dựa vào plugin nếu không thể, không cần thiết.

Không dùng captcha, không dùng Akismet để đỡ phải xử lý thêm ở phía client, vậy thì mình phải làm sao?............ Chính xác, mình xem đặc điểm các comment spam và comment thật của người dùng trên website của mình để từ đó lọc cho hợp lý.

true

Dù đã kích hoạt plugin Akismet nhưng những comment spam vẫn được chấp nhận và hiển thị ra bên ngoài, ảnh hưởng rất nhiều đến website.

Sau khi xem qua vài chục comment của khách hàng bình thường sẽ bao gồm nội dung bình thường hoặc đôi khi sẽ có kèm số điện thoại, trong khi comment spam luôn luôn có 2 đặc điểm sau:

  • Trong comment lúc nào cũng có liên kết đến website khác.
  • Spam đôi khi có liên kết đến website khác (Author URL). Vì website mình đã ẩn đi khung URL này, nên những comment nào có thể gửi được URL của tác giả đều phải gửi bằng phương thức POST qua /wp-comment-posts.php. Quá lộ :D

Việc đơn giản của mình là lọc hoặc cho vào spam tùy theo mức độ, vì đôi khi khách hàng có thể chia sẻ liên kết Facebook, ảnh chụp màn hình nên không thể lúc nào cũng cho vào spam.

Chuẩn bị

Trước tiên, chúng ta phải tìm ra một hook hay filter để có thể can thiệp vào sự kiện người dùng bình luận. Tất nhiên phải tìm sự kiện chạy trước khi comment được thêm vào bài viết. Vì nếu chọn sự kiện sau khi thêm comment, WordPress có thể đã kích hoạt rất nhiều sự kiện khác, bao gồm clear cache. Lúc này comment spam đã xuất hiện trên website, và rất có thể đã bị Google nhìn thấy.

Rất may mắn WordPress đã chuẩn bị sẵn filter 🔗 [pre_comment_approved](https://codex.wordpress.org/Plugin_API/Filter_Reference/pre_comment_approved), sẽ xảy ra sau khi người dùng bình luận rồi sẽ quyết định là có chấp nhận (approve) hay chờ (pending) hoặc cho thẳng vào spam hay thùng rác luôn.

Trong tài liệu đã ghi rất rõ và dễ hiểu, trả về 1 nếu bạn muốn chấp nhận, 0 nếu muốn cho chờ và spam hoặc trash theo nghĩa tương đương.

Vậy đoạn code ta sắp viết sẽ được gói gọn như sau (đã có trong tài liệu):

function filter_handler( $approved , $commentdata ){
    // Xử lý và return
}

add_filter( 'pre_comment_approved' , 'filter_handler' , '99', 2 );

Chuẩn bị phần 2

Tiếp theo, chúng ta phải viết code để biết thế nào là một comment spam, hoặc nghi ngờ, hoặc chấp nhận ngay. Vậy chúng ta cùng lật lại 2 đặc điểm của comment spam của mình và xử lý:

  • Trong comment lúc nào cũng có liên kết đến website khác.
    • Cách xử lý: Cho vào Pending để duyệt sau.
  • Spam đôi khi có liên kết đến website khác (Author URL).
    • Cách xử lý: Cho ngay vào spam vì người dùng bình thường chẳng thể thêm được URL này.

Dựa vào mảng $commentdata mà WordPress chuẩn bị sẵn, ta có thể xử lý hai trường hợp này như sau:

Nếu tác giả có URL đến website khác

Nếu trong mảng con comment_author_url có chứa bất kì nội dung nào, cho ngay vào spam nhe :D Mình đặt đoạn này ở trên vì nếu có chứa author's URL, chúng ta không cần xử lý gì nữa.

if(!empty($commentdata['comment_author_url'])){
    return 'spam';
}

Nếu trong nội dung comment có chứa URL nào đó

Đoạn này lại phải sử dụng Regular Expression, nếu bạn nào có đoạn đẹp hơn, nhẹ nhàng hơn thì góp ý với mình nhé. Đoạn code bên dưới có tác dụng phát hiện ra trong nội dung bình luận có chứa liên kết nào không, nếu có sẽ đưa vào dạng Chờ (pending) để mình chấp nhận sau.

Kết quả khi kiểm tra ở regex101.com 🔗 như sau:

true

$reg_exUrl = "/(?i)\\b((?:https?:\\/\\/|www\\d{0,3}\[.\]|\[a-z0-9.\\-\]+\[.\]\[a-z\]{2,4}\\/)(?:\[^\\s()<>\]+|\\((\[^\\s()<>\]+|(\\(\[^\\s()<>\]+\\)))\*\\))+(?:\\((\[^\\s()<>\]+|(\\(\[^\\s()<>\]+\\)))\*\\)|\[^\\s\`!()\\\[\\\]{};:'\\".,<>?«»“”‘’\]))/";
if(preg_match_all($reg_exUrl, $commentdata\['comment_content'\], $url)) {
    return 0;
}

Gom lại

Sau khi đã chuẩn bị tất cả, chúng ta gom vào làm một để triển khai thôi. Đoạn code cuối cùng sẽ là như vầy:

<?php

function filter_handler( $approved , $commentdata ){
    if(!empty($commentdata['comment_author_url'])){
        return 'spam';
    }

    $reg_exUrl = "/(?i)\b((?:https?:\/\/|www\d{0,3}[.]|[a-z0-9.\-]+[.][a-z]{2,4}\/)(?:[^\s()<>]+|\(([^\s()<>]+|(\([^\s()<>]+\)))*\))+(?:\(([^\s()<>]+|(\([^\s()<>]+\)))*\)|[^\s`!()\[\]{};:'\".,<>?«»“”‘’]))/";
    if(preg_match_all($reg_exUrl, $commentdata['comment_content'], $url)) {
        return 0;
    }

    return 1;
}

add_filter( 'pre_comment_approved' , 'filter_handler' , '99', 2 );

Uki, vậy là xong rồi đó, bạn có thể chèn đoạn code này vào tập tin functions.php của theme hoặc tạo một plugin tùy chỉnh tùy ý bạn. Sau đó bạn có thể đi comment thử xem còn được duyệt không nhé. Hihi.

Mở rộng

Ngoài ra, nếu bạn không có vấn đề với các liên kết ngoài, vẫn chấp nhận tự động nhưng lại không muốn WordPress tự động tạo thành liên kết thì có thể thêm đoạn này vào tập tin functions.php nhé. Đoạn code này không liên quan đến code ở trên, bạn muốn để đâu cũng được.

remove_filter( 'comment_text', 'make_clickable', 9 );