- Автор темы
- Администратор
- Модер.
- Команда форума
- #1
Скрипт для поиска и удаления спам-тем, связанных с даркнет-маркетплейсами и кракен
Проверено на версии: 2.3.6
Вдохновился кодом от @West14 из данного поста: XF 2.2 - Борьба со спамом и решил переделать и доработать его полностью под свои нужды. Хочу поделиться с сообществом результатом своей работы! Этот скрипт предназначен для поиска и удаления спам-тем, связанных с даркнет-маркетплейсами, таких как «Кракен», на форумах XenForo. Он учитывает ключевые слова и регулярные выражения, позволяет исключать определенные темы и отображает подробную информацию о найденных темах.
Если вы найдете ошибки, баги или недоработки, пожалуйста, пишите в эту тему. Буду поддерживать скрипт новыми обновлениями и доработками. Также приветствуются любые предложения по улучшению функционала!
Ниже приведена подробная инструкция по использованию скрипта, а сам код прикреплен в спойлере. Надеюсь, он будет полезен для вашего форума!
Инструкция по использованию скрипта
1. Размещение скрипта
Создайте PHP-файл с уникальным и непредсказуемым именем (например, spam_cleaner_7x9z3.php), чтобы снизить вероятность его обнаружения посторонними.
Скопируйте код скрипта (приведен в спойлере ниже) в этот файл или скачайте уже готовый файл, но перед этим переименуйте его как указано в пункте "1."
Поместите файл в корневую папку вашего форума XenForo на хостинге (там, где находятся файлы вроде index.php и папка src).
2. Настройка скрипта Перед запуском необходимо настроить несколько параметров в коде скрипта:
Часовой пояс:
В коде установлен часовой пояс Asia/Tomsk (+7). Если ваш форум работает в другом часовом поясе, замените его на нужный, например, Europe/Moscow или America/New_York. Список поддерживаемых часовых поясов можно найти в документации PHP
[*]Измените строки:
в начале скрипта и внутри блока try.
ID Администратора:
Скрипт требует права администратора для удаления тем. Укажите ID администратора вашего форума в строке:
Замените 1 на ID вашего администратора. Найти ID можно в админ-панели XenForo в разделе «Пользователи» или в базе данных в таблице xf_user.
Исключение тем:
Чтобы исключить определенные темы из обработки (например, важные темы, которые не должны быть удалены), добавьте их ID в массив $excludeThreadIds:
Укажите ID тем через запятую. Например, для исключения тем с ID 250, 1353 и 7777:
Ключевые слова и регулярные выражения:
Скрипт ищет темы, содержащие определенные ключевые слова или соответствующие регулярным выражениям. Текущий список ключевых слов:
Вы можете добавить или удалить слова, связанные со спамом на вашем форуме. []Слово kraken обрабатывается особым образом: оно считается спамом только в сочетании с другими ключевыми словами. Список дополнительных слов:
Регулярные выражения для поиска спама:
Вы можете добавить свои регулярные выражения или изменить существующие для более точной фильтрации.
3. Запуск скрипта
Перейдите в браузере по адресу вашего скрипта, например:
Замените yourdomain.com на домен вашего форума и spam_cleaner_7x9z3.php на имя вашего файла.
4. Удаление тем ВНИМАНИЕ: Темы удаляются физически из базы данных без возможности восстановления и без записи в журналы XenForo. Будьте осторожны!
5. Дополнительная информация
Статистика:
Проверено на версии: 2.3.6
Вдохновился кодом от @West14 из данного поста: XF 2.2 - Борьба со спамом и решил переделать и доработать его полностью под свои нужды. Хочу поделиться с сообществом результатом своей работы! Этот скрипт предназначен для поиска и удаления спам-тем, связанных с даркнет-маркетплейсами, таких как «Кракен», на форумах XenForo. Он учитывает ключевые слова и регулярные выражения, позволяет исключать определенные темы и отображает подробную информацию о найденных темах.
Если вы найдете ошибки, баги или недоработки, пожалуйста, пишите в эту тему. Буду поддерживать скрипт новыми обновлениями и доработками. Также приветствуются любые предложения по улучшению функционала!
Ниже приведена подробная инструкция по использованию скрипта, а сам код прикреплен в спойлере. Надеюсь, он будет полезен для вашего форума!
Инструкция по использованию скрипта
1. Размещение скрипта
Создайте PHP-файл с уникальным и непредсказуемым именем (например, spam_cleaner_7x9z3.php), чтобы снизить вероятность его обнаружения посторонними.
Скопируйте код скрипта (приведен в спойлере ниже) в этот файл или скачайте уже готовый файл, но перед этим переименуйте его как указано в пункте "1."
Поместите файл в корневую папку вашего форума XenForo на хостинге (там, где находятся файлы вроде index.php и папка src).
2. Настройка скрипта Перед запуском необходимо настроить несколько параметров в коде скрипта:
Часовой пояс:
В коде установлен часовой пояс Asia/Tomsk (+7). Если ваш форум работает в другом часовом поясе, замените его на нужный, например, Europe/Moscow или America/New_York. Список поддерживаемых часовых поясов можно найти в документации PHP
[*]Измените строки:
PHP:
date_default_timezone_set('Asia/Tomsk');
ID Администратора:
Скрипт требует права администратора для удаления тем. Укажите ID администратора вашего форума в строке:
PHP:
$adminUser = \XF::finder('XF:User')->where('user_id', 1)->fetchOne();
Исключение тем:
Чтобы исключить определенные темы из обработки (например, важные темы, которые не должны быть удалены), добавьте их ID в массив $excludeThreadIds:
PHP:
$excludeThreadIds = [1, 2, 3, 10, 20];
PHP:
$excludeThreadIds = [250, 1353, 7777];
Ключевые слова и регулярные выражения:
Скрипт ищет темы, содержащие определенные ключевые слова или соответствующие регулярным выражениям. Текущий список ключевых слов:
PHP:
$spamKeywords = [ 'даркнет', 'darknet', 'kra34.cc', 'kra34.at', 'krn28.click', 'kra27.at', 'kraken', 'darkweb', 'KRaKeN?!' ];
PHP:
$secondarySpamKeywords = ['kraken', 'KRAKEN', 'Kraken'];
Регулярные выражения для поиска спама:
Код:
$spamPatterns = [ '/kra\d{1,2}.(cc|at)/i', // Домены типа kra34.cc, kra27.at '/.onion/i', // Ссылки на даркнет '/[!?@]{2,}/', // Многократные знаки препинания '/[\p{So}]/u' // Нестандартные символы ];
3. Запуск скрипта
Перейдите в браузере по адресу вашего скрипта, например:
Код:
https://yourdomain.com/spam_cleaner_7x9z3.php
- Скрипт выведет таблицу с найденными темами, которые соответствуют заданным критериям. В таблице отображаются:
- ID темы
- Название темы
- ID пользователя
- Имя пользователя
- Статус темы (активна, на модерации, удалена)
- Первые 50 символов первого сообщения
4. Удаление тем ВНИМАНИЕ: Темы удаляются физически из базы данных без возможности восстановления и без записи в журналы XenForo. Будьте осторожны!
- В таблице отметьте галочками темы, которые хотите удалить, или выберите «Выбрать все» для удаления всех найденных тем.
- Нажмите кнопку «Удалить выбранные темы».
- После удаления страница обновится, и удаленные темы исчезнут из списка.
- Если возникнут ошибки при удалении (например, недостаток прав), они будут отображены на странице.
5. Дополнительная информация
Статистика:
- Скрипт показывает общее количество тем и сообщений в базе, а также количество найденных спам-тем.
- Также отображается текущий часовой пояс и время запуска скрипта.
- Внизу страницы выводится список ID пользователей, создавших спам-темы. Это может быть полезно для дальнейшего анализа или блокировки ботов.
- Не разглашайте имя файла скрипта и не делитесь ссылкой на него с посторонними.
- После использования рекомендуется удалить файл с сервера или переместить его в защищенное место.
- Если вы хотите добавить возможность поиска по другим критериям (например, по датам создания тем или по конкретным форумам), напишите в этой теме, и я постараюсь доработать скрипт.
- Если у вас есть идеи по улучшению интерфейса или функционала, делитесь предложениями!
PHP:
<?php
// Устанавливаем часовой пояс Томск (+7) (Вы можете выбрать свой, если нужно)
date_default_timezone_set('Asia/Tomsk');
$dir = __DIR__;
require($dir . '/src/XF.php');
try {
XF::start($dir);
// Повторно устанавливаем часовой пояс (Здесь необходимо повторно установить ваш часовой пояс)
date_default_timezone_set('Asia/Tomsk');
// Установите права администратора (Укажите Ваш ID администратора на форуме где user_id', 1)
$adminUser = \XF::finder('XF:User')->where('user_id', 1)->fetchOne();
if ($adminUser) {
\XF::setVisitor($adminUser);
} else {
throw new \Exception("Не удалось установить пользователя ID=1");
}
$excludeThreadIds = [1, 2, 3, 10, 20]; // Исключайте темы здесь по ID через запятую.
// Ключевые слова для спама (Рекламные маркеры)
$spamKeywords = [
'даркнет', 'darknet', 'kra34.cc', 'kra34.at', 'krn28.click', 'kra27.at', 'kraken', 'darkweb', 'KRaKeN?!'
];
$spamPatterns = [
'/kra\d{1,2}\.(cc|at)/i',
'/\.onion/i',
'/[!?\@]{2,}/',
'/[\p{So}]/u'
];
// Ключевое слово "kraken" проверяем только с другими маркерами
$secondarySpamKeywords = ['kraken', 'KRAKEN', 'Kraken'];
$threadsFinder = \XF::finder('XF:Thread')
->with(['User', 'FirstPost'])
->where('discussion_state', ['visible', 'moderated'])
->where('thread_id', '!=', $excludeThreadIds[0])
->order('thread_id', 'DESC');
$keywordConditions = [];
foreach ($spamKeywords as $keyword) {
$keywordConditions[] = ['FirstPost.message', 'LIKE', "%$keyword%"];
$keywordConditions[] = ['title', 'LIKE', "%$keyword%"];
}
foreach ($secondarySpamKeywords as $keyword) {
foreach ($spamKeywords as $additionalKeyword) {
$keywordConditions[] = [
['FirstPost.message', 'LIKE', "%$keyword%"],
['FirstPost.message', 'LIKE', "%$additionalKeyword%"]
];
$keywordConditions[] = [
['title', 'LIKE', "%$keyword%"],
['title', 'LIKE', "%$additionalKeyword%"]
];
}
}
if (!empty($keywordConditions)) {
$threadsFinder = $threadsFinder->whereOr($keywordConditions);
}
$sqlQuery = $threadsFinder->getQuery();
$threads = $threadsFinder->fetch();
$filteredThreads = [];
foreach ($threads as $thread) {
$textToCheck = ($thread->title ?? '') . ' ' . ($thread->FirstPost->message ?? '');
$isSpam = false;
foreach ($spamPatterns as $pattern) {
if (preg_match($pattern, $textToCheck)) {
$isSpam = true;
break;
}
}
if ($isSpam) {
$filteredThreads[$thread->thread_id] = $thread;
}
}
// Подсчёт тем
$threadCount = count($filteredThreads);
// Общее количество тем и сообщений
$totalThreads = \XF::finder('XF:Thread')->total();
$totalPosts = \XF::finder('XF:Post')->total();
// Обработка удаления
$confirmDeletion = \XF::app()->request()->filter('delete_confirm', 'bool');
$deleteThreadIds = \XF::app()->request()->filter('delete_threads', 'array-uint');
$errorMessages = [];
if ($confirmDeletion && !empty($deleteThreadIds)) {
foreach ($filteredThreads as $thread) {
if (in_array($thread->thread_id, $deleteThreadIds)) {
try {
$error = '';
if ($thread->canDelete($error)) {
$thread->delete();
} else {
$errorMessages[] = "Невозможно удалить тему #{$thread->thread_id}: " . ($error ?: 'Отсутствуют права на удаление');
}
} catch (\Exception $e) {
$errorMessages[] = "Ошибка при удалении темы #{$thread->thread_id}: " . $e->getMessage();
}
}
}
if (empty($errorMessages)) {
header('Location: ' . $_SERVER['PHP_SELF']);
exit;
}
}
} catch (\Exception $e) {
$errorMessage = "Критическая ошибка: " . $e->getMessage() . "\nStack trace: " . $e->getTraceAsString();
$errorMessages[] = $errorMessage;
http_response_code(500);
}
?>
<!DOCTYPE html>
<html>
<head>
<title>Управление спам-темами</title>
<meta charset="UTF-8">
<style>
body { font-family: Georgia, serif; }
table { border-collapse: collapse; width: 100%; margin-bottom: 20px; }
th, td { border: 1px solid #ddd; padding: 8px; text-align: left; }
th { background-color: #f2f2f2; }
th:nth-child(1), th:nth-child(2), th:nth-child(4), th:nth-child(5) {
white-space: nowrap;
width: 100px;
}
th:nth-child(3) {
width: 800px;
white-space: nowrap;
}
.delete-btn { background-color: #ff4444; color: white; padding: 5px 10px; border: none; cursor: pointer; }
.delete-btn:hover { background-color: #cc0000; }
.error { color: red; margin-top: 10px; margin-bottom: 10px; }
.info {
color: #FF0000;
margin-top: 10px;
margin-bottom: 10px;
border: 2px solid #8B0000;
border-radius: 5px;
padding: 10px;
background-color: #FFF3F3;
text-align: center;
font-weight: bold;
}
.debug { margin-top: 10px; margin-bottom: 10px; }
.debug p { margin: 0; }
.label { color: #FF4500; }
.value { color: #008000; }
.warning {
border: 2px solid #FF0000;
background-color: #FFF3F3;
padding: 15px;
margin-bottom: 20px;
border-radius: 5px;
}
.warning h3 {
color: #FF0000;
margin-top: 0;
font-size: 1.2em;
}
.warning p {
margin: 5px 0;
}
.warning ul {
margin-left: 20px;
list-style-type: disc;
}
.description { margin-bottom: 15px; }
.description .label { font-weight: bold; }
h2 {
text-align: center;
color: #333333;
}
hr {
border: 0;
border-top: 1px solid #333333;
margin: 10px 0;
}
</style>
</head>
<body>
<h2>Управление спам-темами форума</h2>
<hr>
<div class="description">
<p><span class="label">Описание:</span><br>Этот инструмент позволяет находить и удалять спам-темы, связанные с даркнет-маркетплейсом «Кракен», содержащие ключевые слова (Например: «даркнет», «darknet», «kra34.cc», «kra34.at», «krn28.click», «kra27.at», «kraken», «darkweb», «KRaKeN?!») в заголовке или первом сообщении. Используйте с осторожностью и не разглашайте доступ к скрипту.</p><hr>
<p><span class="label">Дополнительная информация:</span><br><b>За идею благодарю:</b> <a href="https://xenforo.info/members/west14.22547/" style="color: #008000;">West14</a>.<br><b>Реализовал:</b> <a href="https://xenforo.info/members/shumasick.64948/" style="color: #8B0000;">Shumasick</a></p>
</div>
<hr>
<?php if (!empty($errorMessages)): ?>
<div class="error">
<?php foreach ($errorMessages as $error): ?>
<p><?= htmlspecialchars($error) ?></p>
<?php endforeach; ?>
</div>
<?php endif; ?>
<div class="warning">
<h3>ВНИМАНИЕ</h3>
<ul>
<li>Не разглашайте имя или существование этого файла. Доступ к нему должен быть строго ограничен, чтобы предотвратить несанкционированное использование и потенциальные проблемы с безопасностью форума.</li>
</ul>
</div>
<div class="debug">
<p><b><span class="label">Скрипт запущен: </span><span class="value"><?php
$date = new DateTime();
echo $date->format('d.m.Y H:i:s');
?></span></b></p>
<p><b><span class="label">Текущий часовой пояс: </span><span class="value"><?= date_default_timezone_get() ?></span></b></p>
<p><b><span class="label">Общее количество тем в базе: </span><span class="value"><?= isset($totalThreads) ? $totalThreads : 'Н/Д' ?></span></b></p>
<p><b><span class="label">Общее количество сообщений в базе: </span><span class="value"><?= isset($totalPosts) ? $totalPosts : 'Н/Д' ?></span></b></p>
<p><b><span class="label">Найдено тем по критериям: </span><span class="value"><?= $threadCount ?? 'Н/Д' ?></span></b></p>
</div>
<?php if (empty($filteredThreads)): ?>
<div class="info">
<p>Подходящие темы не найдены.</p>
</div>
<?php else: ?>
<form method="post">
<table>
<tr>
<th><input type="checkbox" id="selectAll"> Выбрать все</th>
<th>ID Темы:</th>
<th>Название Темы:</th>
<th>ID Пользователя:</th>
<th>Пользователь:</th>
<th>Статус Темы:</th>
<th>Первые 50 символов сообщения</th>
</tr>
<?php foreach ($filteredThreads as $thread): ?>
<tr>
<td><input type="checkbox" name="delete_threads[]" value="<?= $thread->thread_id ?>"></td>
<td><?= $thread->thread_id ?></td>
<td><?= htmlspecialchars($thread->title) ?></td>
<td><?= $thread->user_id ?? 'N/A' ?></td>
<td><?= htmlspecialchars($thread->User->username ?? 'Неизвестный пользователь') ?></td>
<td><?= $thread->discussion_state === 'moderated' ? 'На модерации' : ($thread->isDeleted() ? 'Удалена' : 'Активна') ?></td>
<td><?= htmlspecialchars(substr($thread->FirstPost->message ?? 'Нет сообщения', 0, 50)) . (strlen($thread->FirstPost->message ?? '') > 50 ? '...' : '') ?></td>
</tr>
<?php endforeach; ?>
</table>
<input type="hidden" name="delete_confirm" value="1">
<button type="submit" class="delete-btn">Удалить выбранные темы</button>
</form>
<p>Задействованные ID пользователей: <?= implode(', ', array_unique(array_filter(array_column($filteredThreads, 'user_id')))) ?></p>
<?php endif; ?>
<script>
document.getElementById('selectAll')?.addEventListener('change', function(e) {
document.querySelectorAll('input[name="delete_threads[]"]').forEach(checkbox => {
checkbox.checked = e.target.checked;
});
});
</script>
</body>
</html>