[Архив] Shadow Ban для ChatX

  Архив

Актуальная версия 2.5.0

Данный код содержит нереализованную функцию для ChatX и не поддерживается разработчиком!

Данный код писался с целью реализации системы «тихого» бана (shadow ban) для чата, предполагающий возможность для «тихо» заблокированного пользователя читать и оставлять сообщения в чате. Отправленные таким пользователем сообщения будут доступны только ему самому. Таким образом, идея разработки заключалась в создании возможности полного игнорирования пользователей без их уведомления об этом, а также нарочного симулирования нормального поведения чата.

К сожалению, процесс разработки натолкнулся на ряд препятствий, поэтому данная функция осталась нереализованной. В частности, поскольку чат загружает 20 последних сообщений (если другое число не задано в настройках), сообщения от игнорируемого пользователя также будут входить в данный массив, что, в свою очередь, приведет к сокращению числа отображаемых сообщений чата для обычных пользователей. Также, поскольку ID сообщений пишется в статичный файл last_items.php, для обычных пользователей ID сообщений в чате не будут совпадать с данными в статичного файла, что вызовет дополнительные обновления сообщений (load.php) и нагрузку на сервер.

В текущей архитектуре чата реализация данного функционала является крайне проблематичной и неоправданной.

Ниже мы приводим сниппет кода, который позволяет повторить функцию shadow ban.

load.php

<?php


declare(strict_types=1);

use Firebase\JWT\JWT;
include_once 'settings.php';

function createShoutArray($shout) {
$config = ['language' => '\RelativeTime\Languages\L' . $l_g, 'truncate' => 1];
$relativeTime = new \RelativeTime\RelativeTime($config);
$timeAgo = $relativeTime->timeAgo($shout->createdAt);
$timeAgoValue = empty($timeAgo) ? date('H:i', $shout->createdAt) : $timeAgo;

return [
'id' => mb_substr($shout->getId(), 0, 4),
'loggedIn' => $shout->loggedIn,
'text' => $shout->text,
'name' => $shout->name,
'timeAgo' => $timeAgoValue,
'timeStamp' => date('d.m.Y H:i', $shout->createdAt),
];
}

$shouts = $repoShouts->query()
->orderBy('createdAt DESC')
->limit(isset($_GET['history']) ? $m_h : $m_s, isset($_GET['history']) ? $m_s : 0)
->execute();

$results = [];

header('Content-type: application/json; charset=utf-8');

try {
$token = JWT::decode($authHeader, $secretKey, ['HS512']);
/* $is_valid_moderator = $token->data->moderator;
$is_valid_logged_in = $token->data->loggedIn;*/
$bannedProfile = $repoProfiles->query()
->where('username', '==', strtolower($token->data->userName))
->execute();

$is_not_valid_user = false;
$u = '';

foreach ($bannedProfile as $profile) {
$b = $profile->banned;
$u = $profile->username;
if ($b) {
$is_not_valid_user = true;
include 'data/languages/' . $l_g . '/app_lang.extra.' . $l_g . '.php';
echo '[{"id":"denied","text":"' . $lang['APP_ACCESS_DENIED_BANNED'] . '","name":"ChatX","timeAgo":""}]';
die;
}
}

foreach ($shouts as $shout) {
$isValidShadow = isset($shout->shadow) && $shout->shadow === "true";
$isValidUser = isset($u) && strtolower($u) === strtolower($shout->name);

if ($isValidShadow && $isValidUser) {
$results[] = createShoutArray($shout);
} elseif (!$isValidShadow) {
$results[] = createShoutArray($shout);
}
}

echo json_encode($results, JSON_UNESCAPED_UNICODE);

} catch (Exception $e) {
if ($r_a === '1') {
include 'data/languages/' . $l_g . '/app_lang.extra.' . $l_g . '.php';
echo '[{"id":"denied","text":"' . $lang['APP_ACCESS_DENIED'] . '","name":"ChatX","timeAgo":""}]';
} else {
foreach ($shouts as $shout) {
if (!isset($shout->shadow) && $shout->shadow !== "true") {
$results[] = createShoutArray($shout);
}
}
echo json_encode($results, JSON_UNESCAPED_UNICODE);
}
}
?>

publish.php

<?php

declare(strict_types=1);
use Firebase\JWT\JWT;

include_once 'settings.php';
include_once 'bbcode.php';

try {
$token = JWT::decode($authHeader, $secretKey, ['HS512']);
$bannedProfile = $repoProfiles->query()
->where('username', '==', strtolower($token->data->userName))
->execute();
foreach($bannedProfile as $profile) {
$b = $profile->banned;
$sb= $profile->shadowBanned;
$u = $profile->username;
}
if ($token->iss !== $serverName ||
$token->nbf > $now->getTimestamp() ||
$token->exp < $now->getTimestamp() ||
$b || !$u) {
exit;
}
} catch (Exception $e) {
$userIsGuest = true;
}

if (isset($_POST["name"], $_POST["comment"]) && mb_strlen($_POST['name'], 'utf-8') <= 25 && !empty($_POST['comment']) && mb_strlen($_POST['comment'], 'utf-8') <= $m_c) {
$name = str_replace(["\n", "\r"], '', htmlspecialchars($_POST["name"]));
$comment = htmlspecialchars($_POST["comment"]);
$comment = preg_replace('/(\r?\n){3,}/', "\n\n", $comment);
if($userIsGuest) {
$comment = preg_replace('~https://i\.imgur\.com(*SKIP)(*FAIL)|https?://' . $_SERVER['SERVER_NAME'] . '(*SKIP)(*FAIL)|\[url=https?://(*SKIP)(*FAIL)|https?://~s', '', $comment);
}
$comment = showBBcodes($comment);

if ($r_a === '1' && $userIsGuest) {
echo 'Access Denied';
die();
}

$shoutData = [
'text' => $comment,
'name' => $userIsGuest ? $name : $token->data->userName,
'createdAt' => time()
];

if (!$userIsGuest) {
$shoutData['loggedIn'] = 'true';
if($sb) {
$shoutData['shadow'] = 'true';
}
}

$shout = new \JamesMoss\Flywheel\Document($shoutData);
$repoShouts->store($shout);
include 'update_ids.php';
}

Для того, чтобы отправить пользователя в «тихий» бан, в его профиле надо добавить «shadowBanned»: «true». Далее ко всем его новым сообщениям будет автоматически добавляться флаг «shadow»: «true», что исключит их из выдачи для остальных пользователей чата.