'fitme-antispam|', 'log_table' => 'blocked_submissions', 'keywords' => ['seo', 'backlink', 'backlinks', 'crypto', 'bitcoin', 'casino', 'viagra', 'loan', 'guest post', 'web design', 'website traffic', 'ranking', 'forex', 'investment opportunity'], // Marcas do português: quem as usa não é pontuado como «texto estrangeiro». 'native' => '/\b(ol[aá]|bom dia|boa (tarde|noite)|gostaria|queria|aulas?|gin[aá]sio|treino|obrigad[oa]|marcar|experimental|hor[aá]rio)\b/u', ]); // Devolve o motivo da recusa (já registado) ou null para seguir. function public_form_screen(PDO $pdo, string $form, string $table, string $name, string $text): ?string { try { platform_ip_guard($pdo); // sai com 403 se o IP estiver banido return platform_antispam_check($pdo, $form, $table, ['name' => $name, 'text' => $text]); } catch (Throwable $e) { error_log('[antispam] ' . $form . ': ' . $e->getMessage()); return null; } } // Os campos escondidos que o formulário tem de levar (honeypot + carimbo + // prova de JS). Sem eles o carimbo falha e a submissão é recusada. function public_form_trap(string $form): string { try { return platform_antispam_trap_field($form, $GLOBALS['pdo'] ?? null); } catch (Throwable $e) { error_log('[antispam] trap ' . $form . ': ' . $e->getMessage()); return ''; } }