349 lines
9.8 KiB
PHP
349 lines
9.8 KiB
PHP
<?php
|
|
|
|
require_once 'vendor/autoload.php';
|
|
require_once 'inc/anti-bot.php';
|
|
require_once 'inc/functions.php';
|
|
|
|
function _createClient($config) {
|
|
return new GuzzleHttp\Client([
|
|
'base_uri' => $config['spam_noticer']['base_url'],
|
|
'http_errors' => false
|
|
]);
|
|
}
|
|
|
|
$REASONS = [
|
|
(1 << 0) => [
|
|
'reason' => 'RECENTLY_POSTED_ATTACHMENT_ABOVE_RATE',
|
|
'explanation' => 'your file was posted too fast',
|
|
],
|
|
(1 << 1) => [
|
|
'reason' => 'LEXICAL_ANALYSIS_SHOWS_NONSENSE',
|
|
'explanation' => 'your post is nonsense',
|
|
],
|
|
(1 << 2) => [
|
|
'reason' => 'SEGMENTED_AVG_ENTROPY_TOO_HIGH',
|
|
'explanation' => 'this seems to be garbage input',
|
|
],
|
|
(1 << 3) => [
|
|
'reason' => 'TEXT_MATCHES_KNOWN_SPAM',
|
|
'explanation' => 'your text is considered spam',
|
|
],
|
|
(1 << 4) => [
|
|
'reason' => 'RECENTLY_POSTED_TEXT_ABOVE_RATE',
|
|
'explanation' => 'your text is being spammed',
|
|
],
|
|
(1 << 5) => [
|
|
'reason' => 'TEXT_IS_URL',
|
|
'explanation' => 'this is just a url',
|
|
],
|
|
(1 << 6) => [
|
|
'reason' => 'TEXT_IS_ONE_LONG_WORD',
|
|
'explanation' => "your post is illegible",
|
|
],
|
|
(1 << 7) => [
|
|
'reason' => 'TEXT_IS_RANDOM_WORDS',
|
|
'explanation' => "what you're saying is nonsense",
|
|
],
|
|
(1 << 8) => [
|
|
'reason' => 'ATTACHMENT_MATCHES_KNOWN_SPAM',
|
|
'explanation' => 'that file is considered spam',
|
|
],
|
|
(1 << 9) => [
|
|
'reason' => 'TEXT_MANUALLY_MARKED_AS_SPAM',
|
|
'explanation' => "we said you can't post that",
|
|
],
|
|
(1 << 10) => [
|
|
'reason' => 'ATTACHMENT_MANUALLY_MARKED_AS_SPAM',
|
|
'explanation' => 'that file is spam',
|
|
],
|
|
(1 << 11) => [
|
|
'reason' => 'ILLEGAL_ATTACHMENT',
|
|
'explanation' => 'of illegal content',
|
|
],
|
|
];
|
|
|
|
function reasonsFromBitmap($n) {
|
|
$reasons = [];
|
|
|
|
foreach ($GLOBALS['REASONS'] as $bit => $reason) {
|
|
if ($n & $bit) {
|
|
$reasons[] = $reason['explanation'];
|
|
}
|
|
}
|
|
|
|
return $reasons;
|
|
}
|
|
|
|
function renderReasons($reason) {
|
|
$reasons = reasonsFromBitmap($reason);
|
|
$result = '';
|
|
|
|
if (!empty($reasons)) {
|
|
$result = implode(' and ', $reasons);
|
|
}
|
|
|
|
return $result;
|
|
}
|
|
|
|
class SpamNoticerResult {
|
|
public $result_json = NULL;
|
|
public $noticed = false;
|
|
public $succeeded = false;
|
|
public $reason = NULL;
|
|
public $client = NULL;
|
|
}
|
|
|
|
class SpamNoticerBanFileInfo {
|
|
public $filename;
|
|
public $is_illegal;
|
|
public $is_spam;
|
|
|
|
public function __construct($filename, $isIllegal, $isSpam) {
|
|
$this->filename = $filename;
|
|
$this->is_illegal = $isIllegal;
|
|
$this->is_spam = $isSpam;
|
|
}
|
|
}
|
|
|
|
class BanFormFieldsForSpamnoticer {
|
|
public bool $ban;
|
|
public bool $delete;
|
|
public bool $ban_content;
|
|
public bool $text_is_spam;
|
|
public array $files_info;
|
|
|
|
public function __construct(
|
|
bool $ban,
|
|
bool $delete,
|
|
bool $ban_content,
|
|
bool $text_is_spam,
|
|
array $files_info, // Array of SpamNoticerBanFileInfo
|
|
) {
|
|
$this->ban = $ban;
|
|
$this->delete = $delete;
|
|
$this->ban_content = $ban_content;
|
|
$this->text_is_spam = $text_is_spam;
|
|
$this->files_info = array();
|
|
|
|
foreach ($files_info as $info) {
|
|
$this->files_info[$info->filename] = $info;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
function getUsername() {
|
|
global $config;
|
|
|
|
if (isset($_COOKIE[$config['cookies']['mod']])) {
|
|
// Should be username:hash:salt
|
|
$cookie = explode(':', $_COOKIE[$config['cookies']['mod']]);
|
|
return $cookie[0];
|
|
} else {
|
|
return '__BOARD_MOD_USERNAME__';
|
|
}
|
|
}
|
|
|
|
function addToSpamNoticer($config, $post, $boardname, BanFormFieldsForSpamnoticer $form_info) {
|
|
global $board;
|
|
|
|
$client = _createClient($config);
|
|
|
|
$attachments = array();
|
|
|
|
if (isset($post->files) && is_array($post->files)) {
|
|
foreach ($post->files as $file) {
|
|
$key = $file->file_id . '.' . $file->extension;
|
|
|
|
if (!isset($form_info->files_info[$key])) {
|
|
continue;
|
|
}
|
|
|
|
$file_info = $form_info->files_info[$key];
|
|
$thumb_uri
|
|
= $config['spam_noticer']['imageboard_root']
|
|
. $board['uri']
|
|
. '/' . $config['dir']['thumb']
|
|
. $file->file_id
|
|
. '.png';
|
|
|
|
$a = array(
|
|
'filename' => $file->filename,
|
|
'mimetype' => $file->type ? $file->type : mime_content_type($file->tmp_name),
|
|
'md5_hash' => $file->hash,
|
|
'thumbnail_url' => $thumb_uri,
|
|
'is_spam' => $file_info->is_spam
|
|
);
|
|
|
|
if ($file_info->is_illegal) {
|
|
$a['is_illegal'] = true;
|
|
}
|
|
|
|
$attachments[] = $a;
|
|
}
|
|
}
|
|
|
|
$json_payload = [
|
|
'attachments' => $attachments,
|
|
'body' => remove_modifiers($post->body_nomarkup),
|
|
'body_is_spam' => $form_info->text_is_spam,
|
|
'time_stamp' => $post->time,
|
|
'website_name' => $config['spam_noticer']['website_name'],
|
|
'board_name' => $boardname,
|
|
'reporter_name' => getUsername()
|
|
];
|
|
|
|
if (isset($post->thread)) {
|
|
$json_payload['thread_id'] = $post->thread;
|
|
}
|
|
|
|
try {
|
|
$multipart = array();
|
|
$multipart[] =
|
|
array(
|
|
'name' => 'json',
|
|
'contents' => json_encode($json_payload)
|
|
);
|
|
|
|
if (isset($post->files) && is_array($post->files)) {
|
|
foreach ($post->files as $file) {
|
|
$key = $file->file_id . '.' . $file->extension;
|
|
if (!isset($form_info->files_info[$key])) {
|
|
continue;
|
|
}
|
|
|
|
$filename = $board['dir'] . $config['dir']['img'] . $file->file;
|
|
|
|
$multipart[] = array(
|
|
'name' => 'attachments',
|
|
'contents' => GuzzleHttp\Psr7\Utils::tryFopen($filename, 'r')
|
|
);
|
|
}
|
|
}
|
|
|
|
|
|
$response = $client->request('POST', '/add_post_to_known_spam', [
|
|
'multipart' => $multipart
|
|
]);
|
|
|
|
$status_code = $response->getStatusCode();
|
|
$result_body = (string) $response->getBody();
|
|
print_err($result_body);
|
|
return "$status_code $result_body";
|
|
|
|
} catch (GuzzleHttp\Exception\ConnectException $e) {
|
|
return 'Spamnoticer Connection ERROR: ' . $e->getMessage();
|
|
}
|
|
}
|
|
|
|
function checkWithSpamNoticer($config, $post, $boardname) {
|
|
$client = _createClient($config);
|
|
|
|
$attachments = [];
|
|
|
|
foreach ($post['files'] as $key => $file) {
|
|
$attachments[] = array(
|
|
'filename' => $file['filename'],
|
|
'mimetype' => $file['type'] ? $file['type'] : mime_content_type($file['tmp_name']),
|
|
'md5_hash' => $file['hash'],
|
|
);
|
|
}
|
|
|
|
$json_payload = [
|
|
'attachments' => $attachments,
|
|
'body' => $post['raw_body'],
|
|
'time_stamp' => time(),
|
|
'website_name' => $config['spam_noticer']['website_name'],
|
|
'board_name' => $boardname,
|
|
'delete_token' => $post['delete_token'],
|
|
];
|
|
|
|
if (array_key_exists('thread', $post)) {
|
|
$json_payload['thread_id'] = $post['thread'];
|
|
}
|
|
|
|
$result = new SpamNoticerResult();
|
|
|
|
try {
|
|
$multipart = array();
|
|
$multipart[] =
|
|
[
|
|
'name' => 'json',
|
|
'contents' => json_encode($json_payload)
|
|
];
|
|
|
|
foreach ($post['files'] as $key => $file) {
|
|
$multipart[] = array(
|
|
'name' => 'attachments',
|
|
'contents' => GuzzleHttp\Psr7\Utils::tryFopen($file['tmp_name'], 'r')
|
|
);
|
|
}
|
|
|
|
|
|
$response = $client->request('POST', '', [
|
|
'multipart' => $multipart
|
|
]);
|
|
|
|
$status_code = $response->getStatusCode();
|
|
|
|
if ($status_code >= 200 && $status_code < 300) {
|
|
$result->succeeded = true;
|
|
$result->result_json = json_decode($response->getBody(), true);
|
|
$result->noticed = $result->result_json['noticed'] == true;
|
|
|
|
if ($result->noticed) {
|
|
$body = (string) $response->getBody();
|
|
print_err($body);
|
|
$reasons_bitmap = json_decode($body)->reason;
|
|
$result->reason = renderReasons($reasons_bitmap);
|
|
}
|
|
} else {
|
|
print_err("spamnoticer status code: " . $status_code);
|
|
print_err("spamnoticer response body: " . $response->getBody());
|
|
|
|
$result->reason = (string) $response->getBody();
|
|
}
|
|
|
|
$result->client = $client;
|
|
|
|
return $result;
|
|
} catch (GuzzleHttp\Exception\ConnectException $e) {
|
|
$result->reason = $e->getMessage();
|
|
}
|
|
|
|
return $result;
|
|
}
|
|
|
|
function removeRecentPostFromSpamnoticer($config, $delete_tokens, $files_only = false) {
|
|
if (!$delete_tokens) {
|
|
return;
|
|
}
|
|
|
|
$client = _createClient($config);
|
|
|
|
$promise = $client->postAsync('/undo_recent_post', [
|
|
'headers' => [
|
|
'Content-Type' => 'application/json',
|
|
],
|
|
'json' => [
|
|
'delete_tokens' => $delete_tokens,
|
|
'files_only' => $files_only,
|
|
]
|
|
]);
|
|
|
|
$promise->then(
|
|
function ($response) use ($config) {
|
|
// This callback is executed when the request is successful
|
|
if ($config['debug']) {
|
|
print_err("POST to SpamNoticer /undo_recent_post sent successfully!");
|
|
}
|
|
},
|
|
function (RequestException $exception) {
|
|
print_err("ERROR sending POST to SpamNoticer /undo_recent_post:\n$exception");
|
|
}
|
|
);
|
|
|
|
// This will initiate the asynchronous request, but we won't wait for the response.
|
|
$promise->wait(false); // Set to false for asynchronous behavior
|
|
}
|