Excluir automaticamente usuários sinalizados pelo sistema?

Olá!

Todos os dias, tenho uma dúzia de contas de spam sinalizadas como “Este novo usuário inseriu informações de perfil sem ler nenhum tópico ou postagem”.

Em dois anos, tivemos 0 falsos positivos.

Portanto, estou pensando que poderíamos excluir automaticamente essas contas se elas forem sinalizadas por esse motivo específico.

Opcionalmente, um e-mail automático poderia ser enviado ao destinatário antes da exclusão, mencionando que a conta foi excluída automaticamente, mas que o administrador pode ser contatado por e-mail através do fórum.

Dei uma olhada em Discourse Automation, mas ele não permite isso de imediato.

Seria possível codificar um plugin usando os métodos de automação do Discourse, ou ele deve ser codificado do zero?

Ou existe uma maneira mais fácil de evitar que esse spam interminável chegue à nossa lista de revisão?

4 curtidas

Então, estou tentando isso, vou usar os webhooks que nunca usei antes.
Comecei a usar Use Discourse webhooks with PHP como modelo e ele retorna dados corretamente para o Discourse.

Mas preciso criar itens de revisão de spam manualmente (como “usuário digitou muito rápido” ou “preencheu o perfil sem ler nenhuma postagem”). Alguma ideia de como fazer isso?

Consegui fazer funcionar.

Criando um usuário com o Insomnia, preenchendo seu perfil com um gatilho do Akismet, que aciona uma Revisão.
Algumas verificações são feitas e o usuário é automaticamente excluído.

As propriedades de Revisão para o script acionar a exclusão de um usuário são:

  • Type: ReviewableAkismetUser, ReviewableUser ou ReviewableQueuedPost
  • Score > 0

Não quero excluir automaticamente usuários sinalizados por outros que não o @system.

Aqui está o script PHP que uso:

<?php

// Verifica imediatamente a autenticidade da solicitação.
if (array_key_exists('HTTP_X_DISCOURSE_EVENT_SIGNATURE', $_SERVER)) {
    $discourse_payload_raw = file_get_contents('php://input');
    $discourse_payload_sha256 = substr($_SERVER['HTTP_X_DISCOURSE_EVENT_SIGNATURE'], 7);
    
    // Para segurança, configure o webhook com um segredo no Discourse e defina-o abaixo.
    $discourse_payload_secret = '2J3tM5X4WYGkGp0tTkmu';
    
    // Verifica se a solicitação foi enviada por um webhook autorizado.
    if (hash_hmac('sha256', $discourse_payload_raw, $discourse_payload_secret) == $discourse_payload_sha256) {
        echo 'received';
    }
    else {
        die('authentication failed');
    }
}
else {
    die('access denied');
}

// Prepara o payload para uso no script PHP.
$discourse_json = json_decode($discourse_payload_raw);

$reviewable = $discourse_json->reviewable;

// Configura a URL da API
$api_url = "https://discourse.canapin.com/review/$reviewable->id/perform/delete_user?version=0";
//$api_url = "https://discourse.canapin.com/review/$reviewable->id/perform/delete_user?version=$reviewable->version";


// Verifica se as propriedades "type" e "score" são válidas
if (($reviewable->type == "ReviewableUser" || $reviewable->type == "ReviewableAkismetUser" || $reviewable->type == "ReviewableQueuedPost") && $reviewable->score > 0) {
  // Configura as opções do curl
    $options = array(
        CURLOPT_URL => $api_url,
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_CUSTOMREQUEST => "PUT", // Define o método da solicitação como PUT
        CURLOPT_HTTPHEADER => array(
            "Api-Key: 6666666666666666666666666666666666666666666",
            "Api-Username: system"
        )
    );
    // Inicializa a sessão curl
    $curl = curl_init();
    curl_setopt_array($curl, $options);
    // Faz a chamada da API
    $response = curl_exec($curl);
    curl_close($curl);
    // Decodifica a resposta
    $response_data = json_decode($response);
    print_r($response_data);
}   else {
    exit;
}

?>

Em uma escala de 0 a 10… Quão feio confiável ele é, considerando o contexto em que funcionará (0 falsos positivos em 2 anos para detecções do Discourse e akismet)?


Tenho algumas perguntas sobre o payload da solicitação de revisão iniciada pelo Discourse quando um usuário é detectado como uma conta de spam potencial.

  1. Por que existem 2 solicitações para 1 ReviewableUser com diferenças mínimas entre seus respectivos payloads (a primeira solicitação está à esquerda)?

  2. O que link_admin significa?

  3. Quando excluo manualmente um usuário (detectado pelo Akismet) do painel de revisão, ele aciona o webhook de revisão com um novo payload contendo, entre outras coisas: "user_deleted": false. Isso não deveria ser true? :thinking:

  4. Na URL https://discourse.canapin.com/review/355/perform/delete_user?version=0", a “version” aqui se refere à “version” encontrada no payload? Devo me preocupar com este parâmetro? Ele deve ser igual ao parâmetro version do payload?

No estado atual, estou bastante confiante de que funcionará (bem, principalmente por intuição…) e podemos rastrear problemas potenciais olhando os resultados dos webhooks…
Ou listar os itens revisados.

Mas há um problema aqui que não consigo resolver.

Às vezes, a lista de itens revisados fica assim, sem nenhuma informação:

E às vezes fica assim:

Gostaria de manter todas as informações para poder rastrear mais facilmente se houve um falso positivo excluído.

Alguma ideia de onde vem esse comportamento?

Parece acontecer após uma exclusão automática em algum momento, mas não sei como e por quê.

Adiciono que a versão JSON da página de itens revisados contém todas as informações que faltam na interface do Discourse.


Editar: Descobri. É isso que acontece quando você desabilita o plugin Akismet.

Só para constar, já vi isso acontecer algumas vezes, e uma vez foi um falso positivo: um novo membro sensato e atencioso preenchendo seu perfil primeiro. Portanto, pode acontecer.

1 curtida

Sim. Para ser honesto, tive 1 falso positivo (pelo que sei) nesse período de mais de dois anos.
O usuário então entrou em contato comigo por e-mail, que pode ser facilmente encontrado no site caso os usuários encontrem algum problema.

No meu caso, e após revisar manualmente milhares de usuários, o benefício dessa autoexclusão seria, na minha opinião, bastante óbvio, especialmente por se tratar de um fórum de nicho – usuários realmente interessados no tópico irão entrar em contato conosco se enfrentarem qualquer inconveniente. :slight_smile:

2 curtidas

Este tópico foi fechado automaticamente 30 dias após a última resposta. Novas respostas não são mais permitidas.