From cacc2c82c3251e2660c6dffac4d4d6733e881c32 Mon Sep 17 00:00:00 2001
From: Max <1784545+max41479@users.noreply.github.com>
Date: Mon, 6 Feb 2023 04:52:13 +0300
Subject: [PATCH 1/2] Added cron for automatically adding torrents to clients
Signed-off-by: Max <1784545+max41479@users.noreply.github.com>
---
cron/auto_add.php | 13 +
index.php | 20 +-
php/actions/add_topics_to_client.php | 261 +-----
php/actions/add_topics_to_client_function.php | 276 ++++++
php/actions/get_filtered_list_topics.php | 843 +----------------
.../get_filtered_list_topics_function.php | 852 ++++++++++++++++++
php/actions/load_filter_for_cron.php | 28 +
php/actions/save_filter_for_cron.php | 27 +
php/actions/set_config.php | 3 +
php/classes/filter.php | 39 +
php/common.php | 1 +
php/common/auto_add.php | 50 +
scripts/jquery.subsections.js | 13 +
scripts/jquery.topics.js | 36 +
scripts/jquery.widgets.js | 1 +
15 files changed, 1362 insertions(+), 1101 deletions(-)
create mode 100644 cron/auto_add.php
create mode 100644 php/actions/add_topics_to_client_function.php
create mode 100644 php/actions/get_filtered_list_topics_function.php
create mode 100644 php/actions/load_filter_for_cron.php
create mode 100644 php/actions/save_filter_for_cron.php
create mode 100644 php/classes/filter.php
create mode 100644 php/common/auto_add.php
diff --git a/cron/auto_add.php b/cron/auto_add.php
new file mode 100644
index 000000000..93cbc34b5
--- /dev/null
+++ b/cron/auto_add.php
@@ -0,0 +1,13 @@
+getMessage());
+ Log::write($logFile);
+}
diff --git a/index.php b/index.php
index 3272cb320..4e228cf26 100644
--- a/index.php
+++ b/index.php
@@ -28,7 +28,7 @@
$optionFormat = '';
$itemFormat = '
%s';
$datasetFormatTorrentClient = 'data-comment="%s" data-type="%s" data-hostname="%s" data-port="%s" data-login="%s" data-password="%s" data-ssl="%s" data-peers="%s"';
- $datasetFormatForum = 'data-client="%s" data-label="%s" data-savepath="%s" data-subdirectory="%s" data-hide="%s" data-peers="%s"';
+ $datasetFormatForum = 'data-client="%s" data-label="%s" data-savepath="%s" data-subdirectory="%s" data-hide="%s" data-auto-add-topics="%s" data-peers="%s"';
// стандартные адреса
$forumAddressList = array(
@@ -117,6 +117,7 @@
$forumData['df'],
$forumData['sub_folder'],
$forumData['hide_topics'],
+ $forumData['auto_add_topics'],
$forumData['control_peers']
);
$optionForums .= sprintf(
@@ -235,6 +236,14 @@
+
+
+
+
@@ -698,6 +707,13 @@
Останавливать раздачи с количеством пиров более:
+
Настройки управления раздачами
@@ -879,6 +895,7 @@
+
diff --git a/php/actions/add_topics_to_client.php b/php/actions/add_topics_to_client.php
index 7ad4d70e9..09e9bc256 100644
--- a/php/actions/add_topics_to_client.php
+++ b/php/actions/add_topics_to_client.php
@@ -1,262 +1,5 @@
$forumTopicHashes) {
- if (isset($topicHashesByForums[$forumID])) {
- $topicHashesByForums[$forumID] = array_merge(
- $topicHashesByForums[$forumID],
- $forumTopicHashes
- );
- } else {
- $topicHashesByForums[$forumID] = $forumTopicHashes;
- }
- }
- unset($forumTopicHashes);
- unset($data);
- }
- unset($topicHashes);
- if (empty($topicHashesByForums)) {
- $result = 'Не получены идентификаторы раздач с привязкой к подразделу';
- throw new Exception();
- }
- // полный путь до каталога для сохранения торрент-файлов
- $localPath = getStorageDir() . DIRECTORY_SEPARATOR . 'tfiles';
- // очищаем каталог от старых торрент-файлов
- rmdir_recursive($localPath);
- // создаём каталог для торрент-файлов
- if (!mkdir_recursive($localPath)) {
- $result = 'Не удалось создать каталог "' . $localPath . '": неверно указан путь или недостаточно прав';
- throw new Exception();
- }
- $totalTorrentFilesAdded = 0;
- $usedTorrentClientsIDs = [];
- // скачивание торрент-файлов
- $download = new TorrentDownload($cfg['forum_address']);
- // применяем таймауты
- $download->setUserConnectionOptions($cfg['curl_setopt']['forum']);
- foreach ($topicHashesByForums as $forumID => $topicHashes) {
- if (empty($topicHashes)) {
- continue;
- }
- if (!isset($cfg['subsections'][$forumID])) {
- Log::append('В настройках нет данных о подразделе с идентификатором "' . $forumID . '"');
- continue;
- }
- // данные текущего подраздела
- $forumData = $cfg['subsections'][$forumID];
+include_once dirname(__FILE__) . '/add_topics_to_client_function.php';
- if (empty($forumData['cl'])) {
- Log::append('К подразделу "' . $forumID . '" не привязан торрент-клиент');
- continue;
- }
- // идентификатор торрент-клиента
- $torrentClientID = $forumData['cl'];
- if (empty($cfg['clients'][$torrentClientID])) {
- Log::append('В настройках нет данных о торрент-клиенте с идентификатором "' . $torrentClientID . '"');
- continue;
- }
- // данные текущего торрент-клиента
- $torrentClient = $cfg['clients'][$torrentClientID];
- // шаблон для сохранения
- $formatPathTorrentFile = $localPath . DIRECTORY_SEPARATOR . '[webtlo].h%s.torrent';
- if (PHP_OS == 'WINNT') {
- $formatPathTorrentFile = mb_convert_encoding($formatPathTorrentFile, 'Windows-1251', 'UTF-8');
- }
- foreach ($topicHashes as $topicHash) {
- $torrentFile = $download->getTorrentFile($cfg['api_key'], $cfg['user_id'], $topicHash, $cfg['retracker']);
- if ($torrentFile === false) {
- Log::append('Error: Не удалось скачать торрент-файл (' . $topicHash . ')');
- continue;
- }
- // сохранить в каталог
- $response = file_put_contents(
- sprintf($formatPathTorrentFile, $topicHash),
- $torrentFile
- );
- if ($response === false) {
- Log::append('Error: Произошла ошибка при сохранении торрент-файла (' . $topicHash . ')');
- continue;
- }
- $downloadedTorrentFiles[] = $topicHash;
- }
- if (empty($downloadedTorrentFiles)) {
- Log::append('Нет скачанных торрент-файлов для добавления их в торрент-клиент "' . $torrentClient['cm'] . '"');
- continue;
- }
- $numberDownloadedTorrentFiles = count($downloadedTorrentFiles);
- // подключаемся к торрент-клиенту
- /**
- * @var utorrent|transmission|vuze|deluge|ktorrent|rtorrent|qbittorrent|flood $client
- */
- $client = new $torrentClient['cl'](
- $torrentClient['ssl'],
- $torrentClient['ht'],
- $torrentClient['pt'],
- $torrentClient['lg'],
- $torrentClient['pw']
- );
- // проверяем доступность торрент-клиента
- if (!$client->isOnline()) {
- Log::append('Error: торрент-клиент "' . $torrentClient['cm'] . '" в данный момент недоступен');
- continue;
- }
- // применяем таймауты
- $client->setUserConnectionOptions($cfg['curl_setopt']['torrent_client']);
- // убираем последний слэш в пути каталога для данных
- if (preg_match('/(\/|\\\\)$/', $forumData['df'])) {
- $forumData['df'] = substr($forumData['df'], 0, -1);
- }
- // определяем направление слэша в пути каталога для данных
- $delimiter = strpos($forumData['df'], '/') === false ? '\\' : '/';
- // добавление раздач
- $downloadedTorrentFiles = array_chunk($downloadedTorrentFiles, 999);
- foreach ($downloadedTorrentFiles as $downloadedTorrentFiles) {
- // получаем идентификаторы раздач
- $placeholders = str_repeat('?,', count($downloadedTorrentFiles) - 1) . '?';
- $topicIDsByHash = Db::query_database(
- 'SELECT hs, id FROM Topics WHERE hs IN (' . $placeholders . ')',
- $downloadedTorrentFiles,
- true,
- PDO::FETCH_KEY_PAIR
- );
- unset($placeholders);
- foreach ($downloadedTorrentFiles as $topicHash) {
- $savePath = '';
- if (!empty($forumData['df'])) {
- $savePath = $forumData['df'];
- // подкаталог для данных
- if ($forumData['sub_folder']) {
- if ($forumData['sub_folder'] == 1) {
- $subdirectory = $topicIDsByHash[$topicHash];
- } elseif ($forumData['sub_folder'] == 2) {
- $subdirectory = $topicHash;
- } else {
- $subdirectory = '';
- }
- $savePath .= $delimiter . $subdirectory;
- }
- }
- // путь до торрент-файла на сервере
- $torrentFilePath = sprintf($formatPathTorrentFile, $topicHash);
- $response = $client->addTorrent($torrentFilePath, $savePath);
- if ($response !== false) {
- $addedTorrentFiles[] = $topicHash;
- }
- // ждём полсекунды
- usleep(500000);
- }
- unset($topicIDsByHash);
- }
- unset($downloadedTorrentFiles);
- if (empty($addedTorrentFiles)) {
- Log::append('Не удалось добавить раздачи в торрент-клиент "' . $torrentClient['cm'] . '"');
- continue;
- }
- $numberAddedTorrentFiles = count($addedTorrentFiles);
- // устанавливаем метку
- if (!empty($forumData['lb'])) {
- // ждём добавления раздач, чтобы проставить метку
- sleep(round(count($addedTorrentFiles) / 3) + 1); // < 3 дольше ожидание
- // устанавливаем метку
- $response = $client->setLabel($addedTorrentFiles, $forumData['lb']);
- if ($response === false) {
- Log::append('Error: Возникли проблемы при отправке запроса на установку метки');
- }
- }
- // помечаем в базе добавленные раздачи
- $addedTorrentFiles = array_chunk($addedTorrentFiles, 998);
- foreach ($addedTorrentFiles as $addedTorrentFiles) {
- $placeholders = str_repeat('?,', count($addedTorrentFiles) - 1) . '?';
- Db::query_database(
- 'INSERT INTO Torrents (
- info_hash,
- client_id,
- topic_id,
- name,
- total_size
- )
- SELECT
- Topics.hs,
- ?,
- Topics.id,
- Topics.na,
- Topics.si
- FROM Topics
- WHERE hs IN (' . $placeholders . ')',
- array_merge([$torrentClientID], $addedTorrentFiles)
- );
- unset($placeholders);
- }
- unset($addedTorrentFiles);
- Log::append('Добавлено раздач в торрент-клиент "' . $torrentClient['cm'] . '": ' . $numberAddedTorrentFiles . ' шт.');
- if (!in_array($torrentClientID, $usedTorrentClientsIDs)) {
- $usedTorrentClientsIDs[] = $torrentClientID;
- }
- $totalTorrentFilesAdded += $numberAddedTorrentFiles;
- unset($torrentClient);
- unset($forumData);
- unset($client);
- }
- $totalTorrentClients = count($usedTorrentClientsIDs);
- $result = 'Задействовано торрент-клиентов — ' . $totalTorrentClients . ', добавлено раздач всего — ' . $totalTorrentFilesAdded . ' шт.';
- $endtime = microtime(true);
- Log::append('Процесс добавления раздач в торрент-клиенты завершён за ' . convert_seconds($endtime - $starttime));
- // выводим на экран
- echo json_encode(
- [
- 'log' => Log::get(),
- 'result' => $result,
- ]
- );
-} catch (Exception $e) {
- Log::append($e->getMessage());
- echo json_encode(
- [
- 'log' => Log::get(),
- 'result' => $result,
- ]
- );
-}
+add_topics_to_client();
\ No newline at end of file
diff --git a/php/actions/add_topics_to_client_function.php b/php/actions/add_topics_to_client_function.php
new file mode 100644
index 000000000..30d1f5075
--- /dev/null
+++ b/php/actions/add_topics_to_client_function.php
@@ -0,0 +1,276 @@
+ $forumTopicHashes) {
+ if (isset($topicHashesByForums[$forumID])) {
+ $topicHashesByForums[$forumID] = array_merge(
+ $topicHashesByForums[$forumID],
+ $forumTopicHashes
+ );
+ } else {
+ $topicHashesByForums[$forumID] = $forumTopicHashes;
+ }
+ }
+ unset($forumTopicHashes);
+ unset($data);
+ }
+ unset($topicHashes);
+ if (empty($topicHashesByForums)) {
+ $result = 'Не получены идентификаторы раздач с привязкой к подразделу';
+ throw new Exception();
+ }
+ // полный путь до каталога для сохранения торрент-файлов
+ $localPath = getStorageDir() . DIRECTORY_SEPARATOR . 'tfiles';
+ // очищаем каталог от старых торрент-файлов
+ rmdir_recursive($localPath);
+ // создаём каталог для торрент-файлов
+ if (!mkdir_recursive($localPath)) {
+ $result = 'Не удалось создать каталог "' . $localPath . '": неверно указан путь или недостаточно прав';
+ throw new Exception();
+ }
+ $totalTorrentFilesAdded = 0;
+ $usedTorrentClientsIDs = [];
+ // скачивание торрент-файлов
+ $download = new TorrentDownload($cfg['forum_address']);
+ // применяем таймауты
+ $download->setUserConnectionOptions($cfg['curl_setopt']['forum']);
+ foreach ($topicHashesByForums as $forumID => $topicHashes) {
+ if (empty($topicHashes)) {
+ continue;
+ }
+ if (!isset($cfg['subsections'][$forumID])) {
+ Log::append('В настройках нет данных о подразделе с идентификатором "' . $forumID . '"');
+ continue;
+ }
+ // данные текущего подраздела
+ $forumData = $cfg['subsections'][$forumID];
+
+ if (empty($forumData['cl'])) {
+ Log::append('К подразделу "' . $forumID . '" не привязан торрент-клиент');
+ continue;
+ }
+ // идентификатор торрент-клиента
+ $torrentClientID = $forumData['cl'];
+ if (empty($cfg['clients'][$torrentClientID])) {
+ Log::append('В настройках нет данных о торрент-клиенте с идентификатором "' . $torrentClientID . '"');
+ continue;
+ }
+ // данные текущего торрент-клиента
+ $torrentClient = $cfg['clients'][$torrentClientID];
+ // шаблон для сохранения
+ $formatPathTorrentFile = $localPath . DIRECTORY_SEPARATOR . '[webtlo].h%s.torrent';
+ if (PHP_OS == 'WINNT') {
+ $formatPathTorrentFile = mb_convert_encoding($formatPathTorrentFile, 'Windows-1251', 'UTF-8');
+ }
+ foreach ($topicHashes as $topicHash) {
+ $torrentFile = $download->getTorrentFile(
+ $cfg['api_key'],
+ $cfg['user_id'],
+ $topicHash,
+ $cfg['retracker']
+ );
+ if ($torrentFile === false) {
+ Log::append('Error: Не удалось скачать торрент-файл (' . $topicHash . ')');
+ continue;
+ }
+ // сохранить в каталог
+ $response = file_put_contents(
+ sprintf($formatPathTorrentFile, $topicHash),
+ $torrentFile
+ );
+ if ($response === false) {
+ Log::append('Error: Произошла ошибка при сохранении торрент-файла (' . $topicHash . ')');
+ continue;
+ }
+ $downloadedTorrentFiles[] = $topicHash;
+ }
+ if (empty($downloadedTorrentFiles)) {
+ Log::append(
+ 'Нет скачанных торрент-файлов для добавления их в торрент-клиент "' . $torrentClient['cm'] . '"'
+ );
+ continue;
+ }
+ $numberDownloadedTorrentFiles = count($downloadedTorrentFiles);
+ // подключаемся к торрент-клиенту
+ /**
+ * @var utorrent|transmission|vuze|deluge|ktorrent|rtorrent|qbittorrent|flood $client
+ */
+ $client = new $torrentClient['cl'](
+ $torrentClient['ssl'],
+ $torrentClient['ht'],
+ $torrentClient['pt'],
+ $torrentClient['lg'],
+ $torrentClient['pw']
+ );
+ // проверяем доступность торрент-клиента
+ if (!$client->isOnline()) {
+ Log::append('Error: торрент-клиент "' . $torrentClient['cm'] . '" в данный момент недоступен');
+ continue;
+ }
+ // применяем таймауты
+ $client->setUserConnectionOptions($cfg['curl_setopt']['torrent_client']);
+ // убираем последний слэш в пути каталога для данных
+ if (preg_match('/(\/|\\\\)$/', $forumData['df'])) {
+ $forumData['df'] = substr($forumData['df'], 0, -1);
+ }
+ // определяем направление слэша в пути каталога для данных
+ $delimiter = strpos($forumData['df'], '/') === false ? '\\' : '/';
+ // добавление раздач
+ $downloadedTorrentFiles = array_chunk($downloadedTorrentFiles, 999);
+ foreach ($downloadedTorrentFiles as $downloadedTorrentFiles) {
+ // получаем идентификаторы раздач
+ $placeholders = str_repeat('?,', count($downloadedTorrentFiles) - 1) . '?';
+ $topicIDsByHash = Db::query_database(
+ 'SELECT hs, id FROM Topics WHERE hs IN (' . $placeholders . ')',
+ $downloadedTorrentFiles,
+ true,
+ PDO::FETCH_KEY_PAIR
+ );
+ unset($placeholders);
+ foreach ($downloadedTorrentFiles as $topicHash) {
+ $savePath = '';
+ if (!empty($forumData['df'])) {
+ $savePath = $forumData['df'];
+ // подкаталог для данных
+ if ($forumData['sub_folder']) {
+ if ($forumData['sub_folder'] == 1) {
+ $subdirectory = $topicIDsByHash[$topicHash];
+ } elseif ($forumData['sub_folder'] == 2) {
+ $subdirectory = $topicHash;
+ } else {
+ $subdirectory = '';
+ }
+ $savePath .= $delimiter . $subdirectory;
+ }
+ }
+ // путь до торрент-файла на сервере
+ $torrentFilePath = sprintf($formatPathTorrentFile, $topicHash);
+ $response = $client->addTorrent($torrentFilePath, $savePath);
+ if ($response !== false) {
+ $addedTorrentFiles[] = $topicHash;
+ }
+ // ждём полсекунды
+ usleep(500000);
+ }
+ unset($topicIDsByHash);
+ }
+ unset($downloadedTorrentFiles);
+ if (empty($addedTorrentFiles)) {
+ Log::append('Не удалось добавить раздачи в торрент-клиент "' . $torrentClient['cm'] . '"');
+ continue;
+ }
+ $numberAddedTorrentFiles = count($addedTorrentFiles);
+ // устанавливаем метку
+ if (!empty($forumData['lb'])) {
+ // ждём добавления раздач, чтобы проставить метку
+ sleep(round(count($addedTorrentFiles) / 3) + 1); // < 3 дольше ожидание
+ // устанавливаем метку
+ $response = $client->setLabel($addedTorrentFiles, $forumData['lb']);
+ if ($response === false) {
+ Log::append('Error: Возникли проблемы при отправке запроса на установку метки');
+ }
+ }
+ // помечаем в базе добавленные раздачи
+ $addedTorrentFiles = array_chunk($addedTorrentFiles, 998);
+ foreach ($addedTorrentFiles as $addedTorrentFiles) {
+ $placeholders = str_repeat('?,', count($addedTorrentFiles) - 1) . '?';
+ Db::query_database(
+ 'INSERT INTO Torrents (
+ info_hash,
+ client_id,
+ topic_id,
+ name,
+ total_size
+ )
+ SELECT
+ Topics.hs,
+ ?,
+ Topics.id,
+ Topics.na,
+ Topics.si
+ FROM Topics
+ WHERE hs IN (' . $placeholders . ')',
+ array_merge([$torrentClientID], $addedTorrentFiles)
+ );
+ unset($placeholders);
+ }
+ unset($addedTorrentFiles);
+ Log::append(
+ 'Добавлено раздач в торрент-клиент "' . $torrentClient['cm'] . '": ' . $numberAddedTorrentFiles . ' шт.'
+ );
+ if (!in_array($torrentClientID, $usedTorrentClientsIDs)) {
+ $usedTorrentClientsIDs[] = $torrentClientID;
+ }
+ $totalTorrentFilesAdded += $numberAddedTorrentFiles;
+ unset($torrentClient);
+ unset($forumData);
+ unset($client);
+ }
+ $totalTorrentClients = count($usedTorrentClientsIDs);
+ $result = 'Задействовано торрент-клиентов — ' . $totalTorrentClients . ', добавлено раздач всего — ' . $totalTorrentFilesAdded . ' шт.';
+ $endtime = microtime(true);
+ Log::append(
+ 'Процесс добавления раздач в торрент-клиенты завершён за ' . convert_seconds($endtime - $starttime)
+ );
+ // выводим на экран
+ echo json_encode(
+ [
+ 'log' => Log::get(),
+ 'result' => $result,
+ ]
+ );
+ } catch (Exception $e) {
+ Log::append($e->getMessage());
+ echo json_encode(
+ [
+ 'log' => Log::get(),
+ 'result' => $result,
+ ]
+ );
+ }
+}
diff --git a/php/actions/get_filtered_list_topics.php b/php/actions/get_filtered_list_topics.php
index 891251738..d0e70495e 100644
--- a/php/actions/get_filtered_list_topics.php
+++ b/php/actions/get_filtered_list_topics.php
@@ -1,844 +1,5 @@
id,na,si,convert(si)rg,se,ds,cl
- $pattern_topic_block = ' %s
';
- $pattern_topic_data = [
- 'id' => '',
- 'ds' => ' ',
- 'rg' => ' | %6$s | ',
- 'cl' => ' %10$s | ',
- 'na' => '%3$s',
- 'si' => ' (%5$s)',
- 'se' => ' - %7$s',
- ];
-
- $output = '';
- $preparedOutput = [];
- $filtered_topics_count = 0;
- $filtered_topics_size = 0;
-
- if ($forum_id == 0) {
- // сторонние раздачи
- $topics = Db::query_database(
- 'SELECT
- TopicsUntracked.id,
- TopicsUntracked.hs,
- TopicsUntracked.na,
- TopicsUntracked.si,
- TopicsUntracked.rg,
- TopicsUntracked.ss,
- TopicsUntracked.se,
- Torrents.client_id as cl
- FROM TopicsUntracked
- LEFT JOIN Torrents ON Torrents.info_hash = TopicsUntracked.hs
- WHERE TopicsUntracked.hs IS NOT NULL',
- [],
- true
- );
- $forumsTitles = Db::query_database(
- "SELECT
- id,
- na
- FROM Forums
- WHERE id IN (SELECT DISTINCT ss FROM TopicsUntracked)",
- [],
- true,
- PDO::FETCH_KEY_PAIR
- );
- // сортировка раздач
- $topics = natsort_field(
- $topics,
- $filter['filter_sort'],
- $filter['filter_sort_direction']
- );
-
- $pattern_topic_head =
- '';
-
- // выводим раздачи
- foreach ($topics as $topic_id => $topic_data) {
- $data = '';
- $forumID = $topic_data['ss'];
- $filtered_topics_count++;
- $filtered_topics_size += $topic_data['si'];
- foreach ($pattern_topic_data as $field => $pattern) {
- if (isset($topic_data[$field])) {
- $data .= $pattern;
- }
- }
- if (!isset($preparedOutput[$forumID])) {
- $preparedOutput[$forumID] = sprintf(
- $pattern_topic_head,
- $forumID,
- $forumsTitles[$forumID]
- );
- }
- $preparedOutput[$forumID] .= sprintf(
- $pattern_topic_block,
- sprintf(
- $data,
- $topic_data['hs'],
- $topic_data['id'],
- $topic_data['na'],
- $topic_data['si'],
- convert_bytes($topic_data['si']),
- date('d.m.Y', $topic_data['rg']),
- $topic_data['se'],
- '',
- '',
- get_client_name($topic_data['cl'], $cfg)
- ),
- ''
- );
- }
- unset($topics);
- natcasesort($preparedOutput);
- $output = implode('', $preparedOutput);
- } elseif ($forum_id == -1) {
- // незарегистрированные раздачи
- $topics = Db::query_database(
- 'SELECT
- Torrents.topic_id,
- CASE WHEN TopicsUnregistered.name IS "" OR TopicsUnregistered.name IS NULL THEN Torrents.name ELSE TopicsUnregistered.name END as name,
- TopicsUnregistered.status,
- Torrents.info_hash,
- Torrents.client_id,
- Torrents.total_size,
- Torrents.time_added,
- Torrents.paused,
- Torrents.done
- FROM TopicsUnregistered
- LEFT JOIN Torrents ON TopicsUnregistered.info_hash = Torrents.info_hash
- WHERE TopicsUnregistered.info_hash IS NOT NULL
- ORDER BY TopicsUnregistered.name',
- [],
- true
- );
- // формирование строки вывода
- foreach ($topics as $topic) {
- $filtered_topics_count++;
- $filtered_topics_size += $topic['total_size'];
- $topicStatus = $topic['status'];
-
- $topicBlock = '';
- foreach ($pattern_topic_data as $field => $pattern) {
- if (in_array($field, ['id', 'rg', 'ds', 'cl', 'na', 'si'])) {
- $topicBlock .= $pattern;
- }
- }
- // тип пульки: раздаю, качаю, на паузе, ошибка
- $stateTorrentClient = '';
- if ($topic['done'] == 1) {
- $stateTorrentClient = 'fa-arrow-up';
- } elseif ($topic['done'] === null) {
- $stateTorrentClient = 'fa-circle';
- } else {
- $stateTorrentClient = 'fa-arrow-down';
- }
- if ($topic['paused'] == 1) {
- $stateTorrentClient = 'fa-pause';
- }
- if (!isset($preparedOutput[$topicStatus])) {
- $preparedOutput[$topicStatus] = '' . $topicStatus . '
';
- }
- $preparedOutput[$topicStatus] .= sprintf(
- $pattern_topic_block,
- sprintf(
- $topicBlock,
- $topic['info_hash'],
- $topic['topic_id'],
- $topic['name'],
- $topic['total_size'],
- convert_bytes($topic['total_size']),
- date('d.m.Y', $topic['time_added']),
- '',
- 'text-success',
- $stateTorrentClient,
- get_client_name($topic['client_id'], $cfg)
- ),
- ''
- );
- }
- unset($topics);
- natcasesort($preparedOutput);
- $output = implode('', $preparedOutput);
- } elseif ($forum_id == -2) {
- // находим значение за последний день
- $se = $cfg['avg_seeders'] ? '(se * 1.) / qt as se' : 'se';
- // чёрный список
- $topics = Db::query_database(
- 'SELECT
- Topics.id,
- Topics.hs,
- Topics.ss,
- Topics.na,
- Topics.si,
- Topics.rg,'
- . $se . ',
- TopicsExcluded.comment
- FROM Topics
- LEFT JOIN TopicsExcluded ON Topics.hs = TopicsExcluded.info_hash
- WHERE TopicsExcluded.info_hash IS NOT NULL',
- [],
- true
- );
- // сортировка раздач
- $topics = natsort_field(
- $topics,
- $filter['filter_sort'],
- $filter['filter_sort_direction']
- );
- // выводим раздачи
- foreach ($topics as $topic_id => $topic_data) {
- $data = '';
- $forumID = $topic_data['ss'];
- $filtered_topics_count++;
- $filtered_topics_size += $topic_data['si'];
- foreach ($pattern_topic_data as $field => $pattern) {
- if (isset($topic_data[$field])) {
- $data .= $pattern;
- }
- }
- if (!isset($preparedOutput[$forumID])) {
- $preparedOutput[$forumID] = '' . $cfg['subsections'][$forumID]['na'] . '
';
- }
- $preparedOutput[$forumID] .= sprintf(
- $pattern_topic_block,
- sprintf(
- $data,
- $topic_data['hs'],
- $topic_data['id'],
- $topic_data['na'],
- $topic_data['si'],
- convert_bytes($topic_data['si']),
- date('d.m.Y', $topic_data['rg']),
- round($topic_data['se'])
- ),
- '' . $topic_data['comment'] . ''
- );
- }
- unset($topics);
- natcasesort($preparedOutput);
- $output = implode('', $preparedOutput);
- } elseif ($forum_id == -4) {
- // дублирующиеся раздачи
- $statementFields = [];
- $statementLeftJoin = [];
- if ($cfg['avg_seeders']) {
- if (!is_numeric($filter['avg_seeders_period'])) {
- throw new Exception('В фильтре введено некорректное значение для периода средних сидов');
- }
- $filter['avg_seeders_period'] = $filter['avg_seeders_period'] > 0 ? $filter['avg_seeders_period'] : 1;
- $filter['avg_seeders_period'] = $filter['avg_seeders_period'] <= 30 ? $filter['avg_seeders_period'] : 30;
- for ($dayNumber = 0; $dayNumber < $filter['avg_seeders_period']; $dayNumber++) {
- $statementTotal['seeders'][] = 'CASE WHEN d' . $dayNumber . ' IS "" OR d' . $dayNumber . ' IS NULL THEN 0 ELSE d' . $dayNumber . ' END';
- $statementTotal['updates'][] = 'CASE WHEN q' . $dayNumber . ' IS "" OR q' . $dayNumber . ' IS NULL THEN 0 ELSE q' . $dayNumber . ' END';
- $statementTotal['values'][] = 'CASE WHEN q' . $dayNumber . ' IS "" OR q' . $dayNumber . ' IS NULL THEN 0 ELSE 1 END';
- }
- $statementTotalValues = implode('+', $statementTotal['values']);
- $statementTotalUpdates = implode('+', $statementTotal['updates']);
- $statementTotalSeeders = implode('+', $statementTotal['seeders']);
- $statementAverageSeeders = 'CASE WHEN ' . $statementTotalValues . ' IS 0 THEN (se * 1.) / qt ELSE ( se * 1. + ' . $statementTotalSeeders . ') / ( qt + ' . $statementTotalUpdates . ') END';
- $statementFields = [
- $statementTotalValues . ' as ds',
- $statementAverageSeeders . ' as se'
- ];
- $statementLeftJoin[] = 'LEFT JOIN Seeders ON Topics.id = Seeders.id';
- } else {
- $statementFields[] = 'se';
- }
- $statementSQL =
- 'SELECT
- Topics.id,
- Topics.hs,
- Topics.na,
- Topics.si,
- Topics.rg
- %s
- FROM Topics %s
- WHERE Topics.hs IN (SELECT info_hash FROM Torrents GROUP BY info_hash HAVING count(*) > 1)';
- $statement = sprintf(
- $statementSQL,
- ',' . implode(',', $statementFields),
- ' ' . implode(' ', $statementLeftJoin)
- );
- $topicsData = Db::query_database($statement, [], true);
- $topicsData = natsort_field(
- $topicsData,
- $filter['filter_sort'],
- $filter['filter_sort_direction']
- );
- foreach ($topicsData as $topicID => $topicData) {
- $outputLine = '';
- $filtered_topics_count++;
- $filtered_topics_size += $topicData['si'];
- foreach ($pattern_topic_data as $field => $pattern) {
- if (isset($topicData[$field])) {
- $outputLine .= $pattern;
- }
- }
- $stateAverageSeeders = '';
- if (isset($topicData['ds'])) {
- if ($topicData['ds'] < $filter['avg_seeders_period']) {
- $stateAverageSeeders = $topicData['ds'] >= $filter['avg_seeders_period'] / 2 ? 'text-warning' : 'text-danger';
- } else {
- $stateAverageSeeders = 'text-success';
- }
- }
- $statement =
- 'SELECT
- client_id,
- done,
- paused,
- error
- FROM Torrents
- WHERE info_hash = ?
- ORDER BY client_id';
- $listTorrentClientsIDs = Db::query_database(
- $statement,
- [$topicData['hs']],
- true
- );
- // сортировка торрент-клиентов
- $sortOrderTorrentClients = array_flip(array_keys($cfg['clients']));
- usort($listTorrentClientsIDs, function ($a, $b) use ($sortOrderTorrentClients) {
- return $sortOrderTorrentClients[$a['client_id']] - $sortOrderTorrentClients[$b['client_id']];
- });
- $formatTorrentClientList = ' %3$s';
- $listTorrentClientsNames = array_map(function ($e) use ($cfg, $formatTorrentClientList) {
- if (isset($cfg['clients'][$e['client_id']])) {
- if ($e['done'] == 1) {
- $stateTorrentClientStatus = 'arrow-up';
- $stateTorrentClientColor = 'success';
- } else {
- $stateTorrentClientStatus = 'arrow-down';
- $stateTorrentClientColor = 'danger';
- }
- if ($e['paused'] == 1) {
- $stateTorrentClientStatus = 'pause';
- }
- if ($e['error'] == 1) {
- $stateTorrentClientStatus = 'times';
- $stateTorrentClientColor = 'danger';
- }
- return sprintf(
- $formatTorrentClientList,
- $stateTorrentClientStatus,
- $stateTorrentClientColor,
- $cfg['clients'][$e['client_id']]['cm']
- );
- }
- }, $listTorrentClientsIDs);
- $listTorrentClientsNames = '| ' . implode(', ', $listTorrentClientsNames);
- $output .= sprintf(
- $pattern_topic_block,
- sprintf(
- $outputLine,
- $topicData['hs'],
- $topicData['id'],
- $topicData['na'],
- $topicData['si'],
- convert_bytes($topicData['si']),
- date('d.m.Y', $topicData['rg']),
- round($topicData['se']),
- $stateAverageSeeders,
- 'fa-circle'
- ),
- $listTorrentClientsNames
- );
- }
- } elseif (
- $forum_id > 0 // заданный раздел
- || $forum_id == -3 // все хранимые подразделы
- || $forum_id == -5 // высокий приоритет
- || $forum_id == -6 // все хранимые подразделы по спискам
- ) {
- // все хранимые раздачи
- // не выбраны статусы раздач
- if (empty($filter['filter_tracker_status'])) {
- throw new Exception('Не выбраны статусы раздач для трекера');
- }
-
- if (empty($filter['keeping_priority'])) {
- if ($forum_id == -5) {
- $filter['keeping_priority'] = [2];
- } else {
- throw new Exception('Не выбраны приоритеты раздач для трекера');
- }
- }
-
- if (empty($filter['filter_client_status'])) {
- throw new Exception('Не выбраны статусы раздач для торрент-клиента');
- }
-
- // некорретный ввод значения сидов или количества хранителей
- $filters_hints = [
- "filter_rule_interval" => "сидов",
- "keepers_filter_rule_interval" => "количества хранителей",
- ];
- foreach ($filters_hints as $filter_name => $hint) {
- if (isset($filter['filter_interval']) || $filter_name == "keepers_filter_rule_interval") {
- if (
- !is_numeric($filter[$filter_name]['from'])
- || !is_numeric($filter[$filter_name]['to'])
- ) {
- throw new Exception('В фильтре введено некорректное значение ' . $hint);
- }
- if ($filter[$filter_name]['from'] < 0 || $filter[$filter_name]['to'] < 0) {
- throw new Exception('Значение ' . $hint . ' в фильтре должно быть больше 0');
- }
- if ($filter[$filter_name]['from'] > $filter[$filter_name]['to']) {
- throw new Exception('Начальное значение ' . $hint . ' в фильтре должно быть меньше или равно конечному значению');
- }
- } else {
- if (!is_numeric($filter['filter_rule'])) {
- throw new Exception('В фильтре введено некорректное значение ' . $hint);
- }
-
- if ($filter['filter_rule'] < 0) {
- throw new Exception('Значение ' . $hint . ' в фильтре должно быть больше 0');
- }
- }
- }
-
- // некорректная дата
- $date_release = DateTime::createFromFormat('d.m.Y', $filter['filter_date_release']);
- if (!$date_release) {
- throw new Exception('В фильтре введена некорректная дата создания релиза');
- }
-
- // Исключить себя из списка хранителей.
- $exclude_self_keep = $cfg['exclude_self_keep'];
-
- // хранимые подразделы
- if ($forum_id > 0) {
- $forumsIDs = [$forum_id];
- } elseif ($forum_id == -5) {
- $forumsIDs = Db::query_database(
- 'SELECT DISTINCT ss FROM Topics WHERE pt = 2',
- [],
- true,
- PDO::FETCH_COLUMN
- );
- if (empty($forumsIDs)) {
- $forumsIDs = [0];
- }
- } else {
- // -3 || -6
- if (isset($cfg['subsections'])) {
- foreach ($cfg['subsections'] as $sub_forum_id => $subsection) {
- if (!$subsection['hide_topics']) {
- $forumsIDs[] = $sub_forum_id;
- }
- }
- } else {
- $forumsIDs = [0];
- }
- }
-
- $ss = str_repeat('?,', count($forumsIDs) - 1) . '?';
- $st = str_repeat('?,', count($filter['filter_tracker_status']) - 1) . '?';
- $torrentDone = 'CAST(done as INT) IS ' . implode(' OR CAST(done AS INT) IS ', $filter['filter_client_status']);
-
- // 1 - fields, 2 - left join, 3 - where
- $pattern_statement =
- 'SELECT
- Topics.id,
- Topics.hs,
- Topics.na,
- Topics.si,
- Topics.rg,
- Topics.pt,
- Torrents.done,
- Torrents.paused,
- Torrents.error,
- Torrents.client_id as cl
- %s
- FROM Topics
- LEFT JOIN Torrents ON Topics.hs = Torrents.info_hash
- %s
- LEFT JOIN (
- SELECT
- id,
- nick,
- MAX(posted) as posted,
- complete,
- MAX(seeding) as seeding
- FROM (
- SELECT
- Topics.id,
- Keepers.nick,
- complete,posted,
- NULL as seeding
- FROM Topics
- LEFT JOIN Keepers ON Topics.id = Keepers.id
- WHERE Keepers.id IS NOT NULL
- UNION ALL
- SELECT
- topic_id,
- nick,
- 1,
- NULL,
- 1
- FROM Topics
- LEFT JOIN KeepersSeeders ON Topics.id = KeepersSeeders.topic_id
- WHERE KeepersSeeders.topic_id IS NOT NULL
- ) GROUP BY id
- ) Keepers ON Topics.id = Keepers.id
- LEFT JOIN (SELECT info_hash FROM TopicsExcluded GROUP BY info_hash) TopicsExcluded ON Topics.hs = TopicsExcluded.info_hash
- WHERE
- ss IN (' . $ss . ')
- AND st IN (' . $st . ')
- AND (' . $torrentDone . ')
- AND TopicsExcluded.info_hash IS NULL
- %s';
-
- $fields = [];
- $where = [];
- $left_join = [];
-
- if ($cfg['avg_seeders']) {
- // некорректный период средних сидов
- if (!is_numeric($filter['avg_seeders_period'])) {
- throw new Exception('В фильтре введено некорректное значение для периода средних сидов');
- }
- // жёсткое ограничение на 30 дней для средних сидов
- $filter['avg_seeders_period'] = $filter['avg_seeders_period'] > 0 ? $filter['avg_seeders_period'] : 1;
- $filter['avg_seeders_period'] = $filter['avg_seeders_period'] <= 30 ? $filter['avg_seeders_period'] : 30;
- for ($i = 0; $i < $filter['avg_seeders_period']; $i++) {
- $avg['sum_se'][] = 'CASE WHEN d' . $i . ' IS "" OR d' . $i . ' IS NULL THEN 0 ELSE d' . $i . ' END';
- $avg['sum_qt'][] = 'CASE WHEN q' . $i . ' IS "" OR q' . $i . ' IS NULL THEN 0 ELSE q' . $i . ' END';
- $avg['qt'][] = 'CASE WHEN q' . $i . ' IS "" OR q' . $i . ' IS NULL THEN 0 ELSE 1 END';
- }
- $qt = implode('+', $avg['qt']);
- $sum_qt = implode('+', $avg['sum_qt']);
- $sum_se = implode('+', $avg['sum_se']);
- $avg = 'CASE WHEN ' . $qt . ' IS 0 THEN (se * 1.) / qt ELSE ( se * 1. + ' . $sum_se . ') / ( qt + ' . $sum_qt . ') END';
-
- $fields[] = $qt . ' as ds';
- $fields[] = $avg . ' as se';
- $left_join[] = 'LEFT JOIN Seeders ON Topics.id = Seeders.id';
- } else {
- $fields[] = 'se';
- }
-
- // есть/нет хранители
- if (isset($filter['not_keepers'])) {
- $where[] = 'AND Keepers.posted IS NULL AND (posted IS NULL OR rg > posted)';
- } elseif (isset($filter['is_keepers'])) {
- $where[] = 'AND Keepers.posted IS NOT NULL AND (posted IS NULL OR rg < posted)';
- }
-
- // есть/нет сиды-хранители
- if (isset($filter['not_keepers_seeders'])) {
- $where[] = 'AND seeding IS NULL';
- } elseif (isset($filter['is_keepers_seeders'])) {
- $where[] = 'AND seeding = 1';
- }
-
- // данные о других хранителях
- $forumsIDsChunks = array_chunk($forumsIDs, 499);
- $keepers = [];
- foreach ($forumsIDsChunks as $forumsIDsChunk) {
- $keepers += Db::query_database(
- 'SELECT k.id,k.nick,MAX(k.complete) as complete,MAX(k.posted) as posted,MAX(k.seeding) as seeding FROM (
- SELECT Topics.id,Keepers.nick,complete,posted,NULL as seeding FROM Topics
- LEFT JOIN Keepers ON Topics.id = Keepers.id
- WHERE ss IN (' . $ss . ') AND rg < posted AND Keepers.id IS NOT NULL
- UNION ALL
- SELECT topic_id,nick,1 as complete,NULL as posted,1 as seeding FROM Topics
- LEFT JOIN KeepersSeeders ON Topics.id = KeepersSeeders.topic_id
- WHERE ss IN (' . $ss . ') AND KeepersSeeders.topic_id IS NOT NULL
- ) as k
- GROUP BY id, nick
- ORDER BY (CASE WHEN k.nick == ? THEN 1 ELSE 0 END) DESC',
- array_merge($forumsIDsChunk, $forumsIDsChunk, [$cfg['tracker_login']]),
- true,
- PDO::FETCH_ASSOC | PDO::FETCH_GROUP
- );
- }
- $statement = sprintf(
- $pattern_statement,
- ',' . implode(',', $fields),
- ' ' . implode(' ', $left_join),
- ' ' . implode(' ', $where)
- );
-
- // из базы
- $topics = Db::query_database(
- $statement,
- array_merge(
- $forumsIDs,
- $filter['filter_tracker_status']
- ),
- true
- );
-
- // сортировка раздач
- $topics = natsort_field(
- $topics,
- $filter['filter_sort'],
- $filter['filter_sort_direction']
- );
-
- // фильтрация по фразе е=ё
- if (!empty($filter['filter_phrase'])) {
- $filterByTopicName = preg_replace(
- '/[её]/ui',
- '(е|ё)',
- quotemeta($filter['filter_phrase'])
- );
- $filterValues = explode(',', $filter['filter_phrase']);
- $filterValues = array_filter($filterValues);
- }
-
- // выводим раздачи
- foreach ($topics as $topic_id => $topic_data) {
- // фильтрация по клиенту
- if ($filter['filter_client_id'] > 0 && $filter['filter_client_id'] != $topic_data['cl']) {
- continue;
- }
- // фильтрация по приоритету
- if (!in_array($topic_data['pt'], $filter['keeping_priority'])) {
- continue;
- }
- // фильтрация по дате релиза
- if ($topic_data['rg'] > $date_release->format('U')) {
- continue;
- }
- // фильтрация по количеству сидов
- if (isset($filter['filter_interval'])) {
- if (
- $filter['filter_rule_interval']['from'] > $topic_data['se']
- || $filter['filter_rule_interval']['to'] < $topic_data['se']
- ) {
- continue;
- }
- } else {
- if ($filter['filter_rule_direction']) {
- if ($filter['filter_rule'] < $topic_data['se']) {
- continue;
- }
- } else {
- if ($filter['filter_rule'] > $topic_data['se']) {
- continue;
- }
- }
- }
- // фильтрация по статусу "зелёные"
- if (
- isset($topic_data['ds'])
- && isset($filter['avg_seeders_complete'])
- && $filter['avg_seeders_period'] > $topic_data['ds']
- ) {
- continue;
- }
- // список хранителей на раздаче
- $topic_keepers = [];
- if (isset($keepers[$topic_data['id']])) {
- $topic_keepers = $keepers[$topic_data['id']];
- }
- // фильтрация раздач по своим спискам
- if ($forum_id == -6) {
- $exclude_self_keep = 0;
- $topicKeepers = array_column($topic_keepers, 'nick');
- if (!count($topicKeepers) || !in_array($cfg['tracker_login'], $topicKeepers)) {
- continue;
- }
- }
- // исключим себя из списка хранителей раздачи
- if ($exclude_self_keep) {
- $topic_keepers = array_filter($topic_keepers, function($e) use ($cfg) {
- return strcasecmp($cfg['tracker_login'], $e['nick']) !== 0;
- });
- }
- $keepers_list = '';
- if (count($topic_keepers)) {
- $formatKeeperList = ' %3$s';
- $keepers_list = array_map(function ($e) use ($formatKeeperList, $cfg) {
- if ($e['complete'] == 1) {
- if ($e['posted'] === null) {
- $stateKeeperIcon = 'arrow-circle-up';
- } else {
- $stateKeeperIcon = $e['seeding'] == 1 ? 'upload' : 'arrow-up';
- }
- $stateKeeperColor = 'success';
- } else {
- $stateKeeperIcon = 'arrow-down';
- $stateKeeperColor = 'danger';
- }
- if (strcasecmp($cfg['tracker_login'], $e['nick']) === 0) {
- $stateKeeperColor = 'self';
- }
- return sprintf(
- $formatKeeperList,
- $stateKeeperIcon,
- $stateKeeperColor,
- $e['nick']
- );
- }, $topic_keepers);
- $keepers_list = '| ' . implode(', ', $keepers_list);
- }
- // фильтрация по фразе
- if (!empty($filter['filter_phrase'])) {
- if ($filter['filter_by_phrase'] == 0) { // в имени хранителя
- $topicKeepers = array_column($topic_keepers, 'nick');
- unset($matchKeepers);
- foreach ($filterValues as $filterKeeper) {
- if (empty($filterKeeper)) {
- continue;
- }
- if (mb_substr($filterKeeper, 0, 1) === '!') {
- $matchKeepers[] = !in_array(mb_substr($filterKeeper, 1), $topicKeepers);
- } else {
- $matchKeepers[] = in_array($filterKeeper, $topicKeepers);
- }
- }
- if (in_array(0, $matchKeepers)) {
- continue;
- }
- } elseif ($filter['filter_by_phrase'] == 1) { // в названии раздачи
- if (!mb_eregi($filterByTopicName, $topic_data['na'])) {
- continue;
- }
- } elseif ($filter['filter_by_phrase'] == 2) { // в номере/ид раздачи
- $matchId = false;
- foreach ($filterValues as $filterId) {
- $filterId = sprintf("^%s$", str_replace('*', '.*', $filterId));
- if (mb_eregi($filterId, $topic_data['id'])) {
- $matchId = true;
- }
- }
- if (!$matchId) {
- continue;
- }
- }
- }
-
- if (
- isset($filter['is_keepers'])
- && (
- $filter['keepers_filter_rule_interval']['from'] > count($topic_keepers)
- || $filter['keepers_filter_rule_interval']['to'] < count($topic_keepers)
- )
- ) {
- continue;
- }
- $data = '';
- $filtered_topics_count++;
- $filtered_topics_size += $topic_data['si'];
- foreach ($pattern_topic_data as $field => $pattern) {
- if (isset($topic_data[$field])) {
- $data .= $pattern;
- }
- }
- // тип пульки: раздаю, качаю, на паузе, ошибка
- $stateTorrentClient = '';
- if ($topic_data['done'] == 1) {
- $stateTorrentClient = 'fa-arrow-up';
- } elseif ($topic_data['done'] === null) {
- $stateTorrentClient = 'fa-circle';
- } else {
- $stateTorrentClient = 'fa-arrow-down';
- }
- if ($topic_data['paused'] == 1) {
- $stateTorrentClient = 'fa-pause';
- }
- if ($topic_data['error'] == 1) {
- $stateTorrentClient = 'fa-times';
- }
- // цвет пульки
- $bullet = '';
- if (isset($topic_data['ds'])) {
- if ($topic_data['ds'] < $filter['avg_seeders_period']) {
- $bullet = $topic_data['ds'] >= $filter['avg_seeders_period'] / 2 ? 'text-warning' : 'text-danger';
- } else {
- $bullet = 'text-success';
- }
- }
- // выводим строку
- $output .= sprintf(
- $pattern_topic_block,
- sprintf(
- $data,
- $topic_data['hs'],
- $topic_data['id'],
- $topic_data['na'],
- $topic_data['si'],
- convert_bytes($topic_data['si']),
- date('d.m.Y', $topic_data['rg']),
- round($topic_data['se'], 2),
- $bullet,
- $stateTorrentClient,
- get_client_name($topic_data['cl'], $cfg)
- ),
- $keepers_list
- );
- }
- }
-
- echo json_encode([
- 'log' => '',
- 'topics' => $output,
- 'size' => $filtered_topics_size,
- 'count' => $filtered_topics_count,
- ]);
-} catch (Exception $e) {
- echo json_encode([
- 'log' => $e->getMessage(),
- 'topics' => null,
- 'size' => 0,
- 'count' => 0,
- ]);
-}
-
-function get_client_name( int|null $clientID, array $cfg): string
-{
- if (!$clientID || !isset($cfg['clients'][$clientID])) return '';
- return sprintf(
- '%s',
- $cfg['clients'][$clientID]['cm']
- );
-}
+get_filtered_list_topics();
\ No newline at end of file
diff --git a/php/actions/get_filtered_list_topics_function.php b/php/actions/get_filtered_list_topics_function.php
new file mode 100644
index 000000000..f08e2b944
--- /dev/null
+++ b/php/actions/get_filtered_list_topics_function.php
@@ -0,0 +1,852 @@
+ id,na,si,convert(si)rg,se,ds,cl
+ $pattern_topic_block = ' %s
';
+ $pattern_topic_data = [
+ 'id' => '',
+ 'ds' => ' ',
+ 'rg' => ' | %6$s | ',
+ 'cl' => ' %10$s | ',
+ 'na' => '%3$s',
+ 'si' => ' (%5$s)',
+ 'se' => ' - %7$s',
+ ];
+
+ $output = '';
+ $preparedOutput = [];
+ $filtered_topics_count = 0;
+ $filtered_topics_size = 0;
+
+ if ($forum_id == 0) {
+ // сторонние раздачи
+ $topics = Db::query_database(
+ 'SELECT
+ TopicsUntracked.id,
+ TopicsUntracked.hs,
+ TopicsUntracked.na,
+ TopicsUntracked.si,
+ TopicsUntracked.rg,
+ TopicsUntracked.ss,
+ TopicsUntracked.se,
+ Torrents.client_id as cl
+ FROM TopicsUntracked
+ LEFT JOIN Torrents ON Torrents.info_hash = TopicsUntracked.hs
+ WHERE TopicsUntracked.hs IS NOT NULL',
+ [],
+ true
+ );
+ $forumsTitles = Db::query_database(
+ "SELECT
+ id,
+ na
+ FROM Forums
+ WHERE id IN (SELECT DISTINCT ss FROM TopicsUntracked)",
+ [],
+ true,
+ PDO::FETCH_KEY_PAIR
+ );
+ // сортировка раздач
+ $topics = natsort_field(
+ $topics,
+ $filter['filter_sort'],
+ $filter['filter_sort_direction']
+ );
+
+ $pattern_topic_head =
+ '';
+
+ // выводим раздачи
+ foreach ($topics as $topic_id => $topic_data) {
+ $data = '';
+ $forumID = $topic_data['ss'];
+ $filtered_topics_count++;
+ $filtered_topics_size += $topic_data['si'];
+ foreach ($pattern_topic_data as $field => $pattern) {
+ if (isset($topic_data[$field])) {
+ $data .= $pattern;
+ }
+ }
+ if (!isset($preparedOutput[$forumID])) {
+ $preparedOutput[$forumID] = sprintf(
+ $pattern_topic_head,
+ $forumID,
+ $forumsTitles[$forumID]
+ );
+ }
+ $preparedOutput[$forumID] .= sprintf(
+ $pattern_topic_block,
+ sprintf(
+ $data,
+ $topic_data['hs'],
+ $topic_data['id'],
+ $topic_data['na'],
+ $topic_data['si'],
+ convert_bytes($topic_data['si']),
+ date('d.m.Y', $topic_data['rg']),
+ $topic_data['se'],
+ '',
+ '',
+ get_client_name($topic_data['cl'], $cfg)
+ ),
+ ''
+ );
+ }
+ unset($topics);
+ natcasesort($preparedOutput);
+ $output = implode('', $preparedOutput);
+ } elseif ($forum_id == -1) {
+ // незарегистрированные раздачи
+ $topics = Db::query_database(
+ 'SELECT
+ Torrents.topic_id,
+ CASE WHEN TopicsUnregistered.name IS "" OR TopicsUnregistered.name IS NULL THEN Torrents.name ELSE TopicsUnregistered.name END as name,
+ TopicsUnregistered.status,
+ Torrents.info_hash,
+ Torrents.client_id,
+ Torrents.total_size,
+ Torrents.time_added,
+ Torrents.paused,
+ Torrents.done
+ FROM TopicsUnregistered
+ LEFT JOIN Torrents ON TopicsUnregistered.info_hash = Torrents.info_hash
+ WHERE TopicsUnregistered.info_hash IS NOT NULL
+ ORDER BY TopicsUnregistered.name',
+ [],
+ true
+ );
+ // формирование строки вывода
+ foreach ($topics as $topic) {
+ $filtered_topics_count++;
+ $filtered_topics_size += $topic['total_size'];
+ $topicStatus = $topic['status'];
+
+ $topicBlock = '';
+ foreach ($pattern_topic_data as $field => $pattern) {
+ if (in_array($field, ['id', 'rg', 'ds', 'cl', 'na', 'si'])) {
+ $topicBlock .= $pattern;
+ }
+ }
+ // тип пульки: раздаю, качаю, на паузе, ошибка
+ $stateTorrentClient = '';
+ if ($topic['done'] == 1) {
+ $stateTorrentClient = 'fa-arrow-up';
+ } elseif ($topic['done'] === null) {
+ $stateTorrentClient = 'fa-circle';
+ } else {
+ $stateTorrentClient = 'fa-arrow-down';
+ }
+ if ($topic['paused'] == 1) {
+ $stateTorrentClient = 'fa-pause';
+ }
+ if (!isset($preparedOutput[$topicStatus])) {
+ $preparedOutput[$topicStatus] = '' . $topicStatus . '
';
+ }
+ $preparedOutput[$topicStatus] .= sprintf(
+ $pattern_topic_block,
+ sprintf(
+ $topicBlock,
+ $topic['info_hash'],
+ $topic['topic_id'],
+ $topic['name'],
+ $topic['total_size'],
+ convert_bytes($topic['total_size']),
+ date('d.m.Y', $topic['time_added']),
+ '',
+ 'text-success',
+ $stateTorrentClient,
+ get_client_name($topic['client_id'], $cfg)
+ ),
+ ''
+ );
+ }
+ unset($topics);
+ natcasesort($preparedOutput);
+ $output = implode('', $preparedOutput);
+ } elseif ($forum_id == -2) {
+ // находим значение за последний день
+ $se = $cfg['avg_seeders'] ? '(se * 1.) / qt as se' : 'se';
+ // чёрный список
+ $topics = Db::query_database(
+ 'SELECT
+ Topics.id,
+ Topics.hs,
+ Topics.ss,
+ Topics.na,
+ Topics.si,
+ Topics.rg,'
+ . $se . ',
+ TopicsExcluded.comment
+ FROM Topics
+ LEFT JOIN TopicsExcluded ON Topics.hs = TopicsExcluded.info_hash
+ WHERE TopicsExcluded.info_hash IS NOT NULL',
+ [],
+ true
+ );
+ // сортировка раздач
+ $topics = natsort_field(
+ $topics,
+ $filter['filter_sort'],
+ $filter['filter_sort_direction']
+ );
+ // выводим раздачи
+ foreach ($topics as $topic_id => $topic_data) {
+ $data = '';
+ $forumID = $topic_data['ss'];
+ $filtered_topics_count++;
+ $filtered_topics_size += $topic_data['si'];
+ foreach ($pattern_topic_data as $field => $pattern) {
+ if (isset($topic_data[$field])) {
+ $data .= $pattern;
+ }
+ }
+ if (!isset($preparedOutput[$forumID])) {
+ $preparedOutput[$forumID] = '' . $cfg['subsections'][$forumID]['na'] . '
';
+ }
+ $preparedOutput[$forumID] .= sprintf(
+ $pattern_topic_block,
+ sprintf(
+ $data,
+ $topic_data['hs'],
+ $topic_data['id'],
+ $topic_data['na'],
+ $topic_data['si'],
+ convert_bytes($topic_data['si']),
+ date('d.m.Y', $topic_data['rg']),
+ round($topic_data['se'])
+ ),
+ '' . $topic_data['comment'] . ''
+ );
+ }
+ unset($topics);
+ natcasesort($preparedOutput);
+ $output = implode('', $preparedOutput);
+ } elseif ($forum_id == -4) {
+ // дублирующиеся раздачи
+ $statementFields = [];
+ $statementLeftJoin = [];
+ if ($cfg['avg_seeders']) {
+ if (!is_numeric($filter['avg_seeders_period'])) {
+ throw new Exception('В фильтре введено некорректное значение для периода средних сидов');
+ }
+ $filter['avg_seeders_period'] = $filter['avg_seeders_period'] > 0 ? $filter['avg_seeders_period'] : 1;
+ $filter['avg_seeders_period'] = $filter['avg_seeders_period'] <= 30 ? $filter['avg_seeders_period'] : 30;
+ for ($dayNumber = 0; $dayNumber < $filter['avg_seeders_period']; $dayNumber++) {
+ $statementTotal['seeders'][] = 'CASE WHEN d' . $dayNumber . ' IS "" OR d' . $dayNumber . ' IS NULL THEN 0 ELSE d' . $dayNumber . ' END';
+ $statementTotal['updates'][] = 'CASE WHEN q' . $dayNumber . ' IS "" OR q' . $dayNumber . ' IS NULL THEN 0 ELSE q' . $dayNumber . ' END';
+ $statementTotal['values'][] = 'CASE WHEN q' . $dayNumber . ' IS "" OR q' . $dayNumber . ' IS NULL THEN 0 ELSE 1 END';
+ }
+ $statementTotalValues = implode('+', $statementTotal['values']);
+ $statementTotalUpdates = implode('+', $statementTotal['updates']);
+ $statementTotalSeeders = implode('+', $statementTotal['seeders']);
+ $statementAverageSeeders = 'CASE WHEN ' . $statementTotalValues . ' IS 0 THEN (se * 1.) / qt ELSE ( se * 1. + ' . $statementTotalSeeders . ') / ( qt + ' . $statementTotalUpdates . ') END';
+ $statementFields = [
+ $statementTotalValues . ' as ds',
+ $statementAverageSeeders . ' as se'
+ ];
+ $statementLeftJoin[] = 'LEFT JOIN Seeders ON Topics.id = Seeders.id';
+ } else {
+ $statementFields[] = 'se';
+ }
+ $statementSQL =
+ 'SELECT
+ Topics.id,
+ Topics.hs,
+ Topics.na,
+ Topics.si,
+ Topics.rg
+ %s
+ FROM Topics %s
+ WHERE Topics.hs IN (SELECT info_hash FROM Torrents GROUP BY info_hash HAVING count(*) > 1)';
+ $statement = sprintf(
+ $statementSQL,
+ ',' . implode(',', $statementFields),
+ ' ' . implode(' ', $statementLeftJoin)
+ );
+ $topicsData = Db::query_database($statement, [], true);
+ $topicsData = natsort_field(
+ $topicsData,
+ $filter['filter_sort'],
+ $filter['filter_sort_direction']
+ );
+ foreach ($topicsData as $topicID => $topicData) {
+ $outputLine = '';
+ $filtered_topics_count++;
+ $filtered_topics_size += $topicData['si'];
+ foreach ($pattern_topic_data as $field => $pattern) {
+ if (isset($topicData[$field])) {
+ $outputLine .= $pattern;
+ }
+ }
+ $stateAverageSeeders = '';
+ if (isset($topicData['ds'])) {
+ if ($topicData['ds'] < $filter['avg_seeders_period']) {
+ $stateAverageSeeders = $topicData['ds'] >= $filter['avg_seeders_period'] / 2 ? 'text-warning' : 'text-danger';
+ } else {
+ $stateAverageSeeders = 'text-success';
+ }
+ }
+ $statement =
+ 'SELECT
+ client_id,
+ done,
+ paused,
+ error
+ FROM Torrents
+ WHERE info_hash = ?
+ ORDER BY client_id';
+ $listTorrentClientsIDs = Db::query_database(
+ $statement,
+ [$topicData['hs']],
+ true
+ );
+ // сортировка торрент-клиентов
+ $sortOrderTorrentClients = array_flip(array_keys($cfg['clients']));
+ usort($listTorrentClientsIDs, function ($a, $b) use ($sortOrderTorrentClients) {
+ return $sortOrderTorrentClients[$a['client_id']] - $sortOrderTorrentClients[$b['client_id']];
+ });
+ $formatTorrentClientList = ' %3$s';
+ $listTorrentClientsNames = array_map(function ($e) use ($cfg, $formatTorrentClientList) {
+ if (isset($cfg['clients'][$e['client_id']])) {
+ if ($e['done'] == 1) {
+ $stateTorrentClientStatus = 'arrow-up';
+ $stateTorrentClientColor = 'success';
+ } else {
+ $stateTorrentClientStatus = 'arrow-down';
+ $stateTorrentClientColor = 'danger';
+ }
+ if ($e['paused'] == 1) {
+ $stateTorrentClientStatus = 'pause';
+ }
+ if ($e['error'] == 1) {
+ $stateTorrentClientStatus = 'times';
+ $stateTorrentClientColor = 'danger';
+ }
+ return sprintf(
+ $formatTorrentClientList,
+ $stateTorrentClientStatus,
+ $stateTorrentClientColor,
+ $cfg['clients'][$e['client_id']]['cm']
+ );
+ }
+ }, $listTorrentClientsIDs);
+ $listTorrentClientsNames = '| ' . implode(', ', $listTorrentClientsNames);
+ $output .= sprintf(
+ $pattern_topic_block,
+ sprintf(
+ $outputLine,
+ $topicData['hs'],
+ $topicData['id'],
+ $topicData['na'],
+ $topicData['si'],
+ convert_bytes($topicData['si']),
+ date('d.m.Y', $topicData['rg']),
+ round($topicData['se']),
+ $stateAverageSeeders,
+ 'fa-circle'
+ ),
+ $listTorrentClientsNames
+ );
+ }
+ } elseif (
+ $forum_id > 0 // заданный раздел
+ || $forum_id == -3 // все хранимые подразделы
+ || $forum_id == -5 // высокий приоритет
+ || $forum_id == -6 // все хранимые подразделы по спискам
+ ) {
+ // все хранимые раздачи
+ // не выбраны статусы раздач
+ if (empty($filter['filter_tracker_status'])) {
+ throw new Exception('Не выбраны статусы раздач для трекера');
+ }
+
+ if (empty($filter['keeping_priority'])) {
+ if ($forum_id == -5) {
+ $filter['keeping_priority'] = [2];
+ } else {
+ throw new Exception('Не выбраны приоритеты раздач для трекера');
+ }
+ }
+
+ if (empty($filter['filter_client_status'])) {
+ throw new Exception('Не выбраны статусы раздач для торрент-клиента');
+ }
+
+ // некорретный ввод значения сидов или количества хранителей
+ $filters_hints = [
+ "filter_rule_interval" => "сидов",
+ "keepers_filter_rule_interval" => "количества хранителей",
+ ];
+ foreach ($filters_hints as $filter_name => $hint) {
+ if (isset($filter['filter_interval']) || $filter_name == "keepers_filter_rule_interval") {
+ if (
+ !is_numeric($filter[$filter_name]['from'])
+ || !is_numeric($filter[$filter_name]['to'])
+ ) {
+ throw new Exception('В фильтре введено некорректное значение ' . $hint);
+ }
+ if ($filter[$filter_name]['from'] < 0 || $filter[$filter_name]['to'] < 0) {
+ throw new Exception('Значение ' . $hint . ' в фильтре должно быть больше 0');
+ }
+ if ($filter[$filter_name]['from'] > $filter[$filter_name]['to']) {
+ throw new Exception(
+ 'Начальное значение ' . $hint . ' в фильтре должно быть меньше или равно конечному значению'
+ );
+ }
+ } else {
+ if (!is_numeric($filter['filter_rule'])) {
+ throw new Exception('В фильтре введено некорректное значение ' . $hint);
+ }
+
+ if ($filter['filter_rule'] < 0) {
+ throw new Exception('Значение ' . $hint . ' в фильтре должно быть больше 0');
+ }
+ }
+ }
+
+ // некорректная дата
+ $date_release = DateTime::createFromFormat('d.m.Y', $filter['filter_date_release']);
+ if (!$date_release) {
+ throw new Exception('В фильтре введена некорректная дата создания релиза');
+ }
+
+ // Исключить себя из списка хранителей.
+ $exclude_self_keep = $cfg['exclude_self_keep'];
+
+ // хранимые подразделы
+ if ($forum_id > 0) {
+ $forumsIDs = [$forum_id];
+ } elseif ($forum_id == -5) {
+ $forumsIDs = Db::query_database(
+ 'SELECT DISTINCT ss FROM Topics WHERE pt = 2',
+ [],
+ true,
+ PDO::FETCH_COLUMN
+ );
+ if (empty($forumsIDs)) {
+ $forumsIDs = [0];
+ }
+ } else {
+ // -3 || -6
+ if (isset($cfg['subsections'])) {
+ foreach ($cfg['subsections'] as $sub_forum_id => $subsection) {
+ if (!$subsection['hide_topics']) {
+ $forumsIDs[] = $sub_forum_id;
+ }
+ }
+ } else {
+ $forumsIDs = [0];
+ }
+ }
+
+ $ss = str_repeat('?,', count($forumsIDs) - 1) . '?';
+ $st = str_repeat('?,', count($filter['filter_tracker_status']) - 1) . '?';
+ $torrentDone = 'CAST(done as INT) IS ' . implode(
+ ' OR CAST(done AS INT) IS ',
+ $filter['filter_client_status']
+ );
+
+ // 1 - fields, 2 - left join, 3 - where
+ $pattern_statement =
+ 'SELECT
+ Topics.id,
+ Topics.hs,
+ Topics.na,
+ Topics.si,
+ Topics.rg,
+ Topics.pt,
+ Torrents.done,
+ Torrents.paused,
+ Torrents.error,
+ Torrents.client_id as cl
+ %s
+ FROM Topics
+ LEFT JOIN Torrents ON Topics.hs = Torrents.info_hash
+ %s
+ LEFT JOIN (
+ SELECT
+ id,
+ nick,
+ MAX(posted) as posted,
+ complete,
+ MAX(seeding) as seeding
+ FROM (
+ SELECT
+ Topics.id,
+ Keepers.nick,
+ complete,posted,
+ NULL as seeding
+ FROM Topics
+ LEFT JOIN Keepers ON Topics.id = Keepers.id
+ WHERE Keepers.id IS NOT NULL
+ UNION ALL
+ SELECT
+ topic_id,
+ nick,
+ 1,
+ NULL,
+ 1
+ FROM Topics
+ LEFT JOIN KeepersSeeders ON Topics.id = KeepersSeeders.topic_id
+ WHERE KeepersSeeders.topic_id IS NOT NULL
+ ) GROUP BY id
+ ) Keepers ON Topics.id = Keepers.id
+ LEFT JOIN (SELECT info_hash FROM TopicsExcluded GROUP BY info_hash) TopicsExcluded ON Topics.hs = TopicsExcluded.info_hash
+ WHERE
+ ss IN (' . $ss . ')
+ AND st IN (' . $st . ')
+ AND (' . $torrentDone . ')
+ AND TopicsExcluded.info_hash IS NULL
+ %s';
+
+ $fields = [];
+ $where = [];
+ $left_join = [];
+
+ if ($cfg['avg_seeders']) {
+ // некорректный период средних сидов
+ if (!is_numeric($filter['avg_seeders_period'])) {
+ throw new Exception('В фильтре введено некорректное значение для периода средних сидов');
+ }
+ // жёсткое ограничение на 30 дней для средних сидов
+ $filter['avg_seeders_period'] = $filter['avg_seeders_period'] > 0 ? $filter['avg_seeders_period'] : 1;
+ $filter['avg_seeders_period'] = $filter['avg_seeders_period'] <= 30 ? $filter['avg_seeders_period'] : 30;
+ for ($i = 0; $i < $filter['avg_seeders_period']; $i++) {
+ $avg['sum_se'][] = 'CASE WHEN d' . $i . ' IS "" OR d' . $i . ' IS NULL THEN 0 ELSE d' . $i . ' END';
+ $avg['sum_qt'][] = 'CASE WHEN q' . $i . ' IS "" OR q' . $i . ' IS NULL THEN 0 ELSE q' . $i . ' END';
+ $avg['qt'][] = 'CASE WHEN q' . $i . ' IS "" OR q' . $i . ' IS NULL THEN 0 ELSE 1 END';
+ }
+ $qt = implode('+', $avg['qt']);
+ $sum_qt = implode('+', $avg['sum_qt']);
+ $sum_se = implode('+', $avg['sum_se']);
+ $avg = 'CASE WHEN ' . $qt . ' IS 0 THEN (se * 1.) / qt ELSE ( se * 1. + ' . $sum_se . ') / ( qt + ' . $sum_qt . ') END';
+
+ $fields[] = $qt . ' as ds';
+ $fields[] = $avg . ' as se';
+ $left_join[] = 'LEFT JOIN Seeders ON Topics.id = Seeders.id';
+ } else {
+ $fields[] = 'se';
+ }
+
+ // есть/нет хранители
+ if (isset($filter['not_keepers'])) {
+ $where[] = 'AND Keepers.posted IS NULL AND (posted IS NULL OR rg > posted)';
+ } elseif (isset($filter['is_keepers'])) {
+ $where[] = 'AND Keepers.posted IS NOT NULL AND (posted IS NULL OR rg < posted)';
+ }
+
+ // есть/нет сиды-хранители
+ if (isset($filter['not_keepers_seeders'])) {
+ $where[] = 'AND seeding IS NULL';
+ } elseif (isset($filter['is_keepers_seeders'])) {
+ $where[] = 'AND seeding = 1';
+ }
+
+ // данные о других хранителях
+ $forumsIDsChunks = array_chunk($forumsIDs, 499);
+ $keepers = [];
+ foreach ($forumsIDsChunks as $forumsIDsChunk) {
+ $keepers += Db::query_database(
+ 'SELECT k.id,k.nick,MAX(k.complete) as complete,MAX(k.posted) as posted,MAX(k.seeding) as seeding FROM (
+ SELECT Topics.id,Keepers.nick,complete,posted,NULL as seeding FROM Topics
+ LEFT JOIN Keepers ON Topics.id = Keepers.id
+ WHERE ss IN (' . $ss . ') AND rg < posted AND Keepers.id IS NOT NULL
+ UNION ALL
+ SELECT topic_id,nick,1 as complete,NULL as posted,1 as seeding FROM Topics
+ LEFT JOIN KeepersSeeders ON Topics.id = KeepersSeeders.topic_id
+ WHERE ss IN (' . $ss . ') AND KeepersSeeders.topic_id IS NOT NULL
+ ) as k
+ GROUP BY id, nick
+ ORDER BY (CASE WHEN k.nick == ? THEN 1 ELSE 0 END) DESC',
+ array_merge($forumsIDsChunk, $forumsIDsChunk, [$cfg['tracker_login']]),
+ true,
+ PDO::FETCH_ASSOC | PDO::FETCH_GROUP
+ );
+ }
+ $statement = sprintf(
+ $pattern_statement,
+ ',' . implode(',', $fields),
+ ' ' . implode(' ', $left_join),
+ ' ' . implode(' ', $where)
+ );
+
+ // из базы
+ $topics = Db::query_database(
+ $statement,
+ array_merge(
+ $forumsIDs,
+ $filter['filter_tracker_status']
+ ),
+ true
+ );
+
+ // сортировка раздач
+ $topics = natsort_field(
+ $topics,
+ $filter['filter_sort'],
+ $filter['filter_sort_direction']
+ );
+
+ // фильтрация по фразе е=ё
+ if (!empty($filter['filter_phrase'])) {
+ $filterByTopicName = preg_replace(
+ '/[её]/ui',
+ '(е|ё)',
+ quotemeta($filter['filter_phrase'])
+ );
+ $filterValues = explode(',', $filter['filter_phrase']);
+ $filterValues = array_filter($filterValues);
+ }
+
+ // выводим раздачи
+ foreach ($topics as $topic_id => $topic_data) {
+ // фильтрация по клиенту
+ if ($filter['filter_client_id'] > 0 && $filter['filter_client_id'] != $topic_data['cl']) {
+ continue;
+ }
+ // фильтрация по приоритету
+ if (!in_array($topic_data['pt'], $filter['keeping_priority'])) {
+ continue;
+ }
+ // фильтрация по дате релиза
+ if ($topic_data['rg'] > $date_release->format('U')) {
+ continue;
+ }
+ // фильтрация по количеству сидов
+ if (isset($filter['filter_interval'])) {
+ if (
+ $filter['filter_rule_interval']['from'] > $topic_data['se']
+ || $filter['filter_rule_interval']['to'] < $topic_data['se']
+ ) {
+ continue;
+ }
+ } else {
+ if ($filter['filter_rule_direction']) {
+ if ($filter['filter_rule'] < $topic_data['se']) {
+ continue;
+ }
+ } else {
+ if ($filter['filter_rule'] > $topic_data['se']) {
+ continue;
+ }
+ }
+ }
+ // фильтрация по статусу "зелёные"
+ if (
+ isset($topic_data['ds'])
+ && isset($filter['avg_seeders_complete'])
+ && $filter['avg_seeders_period'] > $topic_data['ds']
+ ) {
+ continue;
+ }
+ // список хранителей на раздаче
+ $topic_keepers = [];
+ if (isset($keepers[$topic_data['id']])) {
+ $topic_keepers = $keepers[$topic_data['id']];
+ }
+ // фильтрация раздач по своим спискам
+ if ($forum_id == -6) {
+ $exclude_self_keep = 0;
+ $topicKeepers = array_column($topic_keepers, 'nick');
+ if (!count($topicKeepers) || !in_array($cfg['tracker_login'], $topicKeepers)) {
+ continue;
+ }
+ }
+ // исключим себя из списка хранителей раздачи
+ if ($exclude_self_keep) {
+ $topic_keepers = array_filter($topic_keepers, function ($e) use ($cfg) {
+ return strcasecmp($cfg['tracker_login'], $e['nick']) !== 0;
+ });
+ }
+ $keepers_list = '';
+ if (count($topic_keepers)) {
+ $formatKeeperList = ' %3$s';
+ $keepers_list = array_map(function ($e) use ($formatKeeperList, $cfg) {
+ if ($e['complete'] == 1) {
+ if ($e['posted'] === null) {
+ $stateKeeperIcon = 'arrow-circle-up';
+ } else {
+ $stateKeeperIcon = $e['seeding'] == 1 ? 'upload' : 'arrow-up';
+ }
+ $stateKeeperColor = 'success';
+ } else {
+ $stateKeeperIcon = 'arrow-down';
+ $stateKeeperColor = 'danger';
+ }
+ if (strcasecmp($cfg['tracker_login'], $e['nick']) === 0) {
+ $stateKeeperColor = 'self';
+ }
+ return sprintf(
+ $formatKeeperList,
+ $stateKeeperIcon,
+ $stateKeeperColor,
+ $e['nick']
+ );
+ }, $topic_keepers);
+ $keepers_list = '| ' . implode(', ', $keepers_list);
+ }
+ // фильтрация по фразе
+ if (!empty($filter['filter_phrase'])) {
+ if ($filter['filter_by_phrase'] == 0) { // в имени хранителя
+ $topicKeepers = array_column($topic_keepers, 'nick');
+ unset($matchKeepers);
+ foreach ($filterValues as $filterKeeper) {
+ if (empty($filterKeeper)) {
+ continue;
+ }
+ if (mb_substr($filterKeeper, 0, 1) === '!') {
+ $matchKeepers[] = !in_array(mb_substr($filterKeeper, 1), $topicKeepers);
+ } else {
+ $matchKeepers[] = in_array($filterKeeper, $topicKeepers);
+ }
+ }
+ if (in_array(0, $matchKeepers)) {
+ continue;
+ }
+ } elseif ($filter['filter_by_phrase'] == 1) { // в названии раздачи
+ if (!mb_eregi($filterByTopicName, $topic_data['na'])) {
+ continue;
+ }
+ } elseif ($filter['filter_by_phrase'] == 2) { // в номере/ид раздачи
+ $matchId = false;
+ foreach ($filterValues as $filterId) {
+ $filterId = sprintf("^%s$", str_replace('*', '.*', $filterId));
+ if (mb_eregi($filterId, $topic_data['id'])) {
+ $matchId = true;
+ }
+ }
+ if (!$matchId) {
+ continue;
+ }
+ }
+ }
+
+ if (
+ isset($filter['is_keepers'])
+ && (
+ $filter['keepers_filter_rule_interval']['from'] > count($topic_keepers)
+ || $filter['keepers_filter_rule_interval']['to'] < count($topic_keepers)
+ )
+ ) {
+ continue;
+ }
+ $data = '';
+ $filtered_topics_count++;
+ $filtered_topics_size += $topic_data['si'];
+ foreach ($pattern_topic_data as $field => $pattern) {
+ if (isset($topic_data[$field])) {
+ $data .= $pattern;
+ }
+ }
+ // тип пульки: раздаю, качаю, на паузе, ошибка
+ $stateTorrentClient = '';
+ if ($topic_data['done'] == 1) {
+ $stateTorrentClient = 'fa-arrow-up';
+ } elseif ($topic_data['done'] === null) {
+ $stateTorrentClient = 'fa-circle';
+ } else {
+ $stateTorrentClient = 'fa-arrow-down';
+ }
+ if ($topic_data['paused'] == 1) {
+ $stateTorrentClient = 'fa-pause';
+ }
+ if ($topic_data['error'] == 1) {
+ $stateTorrentClient = 'fa-times';
+ }
+ // цвет пульки
+ $bullet = '';
+ if (isset($topic_data['ds'])) {
+ if ($topic_data['ds'] < $filter['avg_seeders_period']) {
+ $bullet = $topic_data['ds'] >= $filter['avg_seeders_period'] / 2 ? 'text-warning' : 'text-danger';
+ } else {
+ $bullet = 'text-success';
+ }
+ }
+ // выводим строку
+ $output .= sprintf(
+ $pattern_topic_block,
+ sprintf(
+ $data,
+ $topic_data['hs'],
+ $topic_data['id'],
+ $topic_data['na'],
+ $topic_data['si'],
+ convert_bytes($topic_data['si']),
+ date('d.m.Y', $topic_data['rg']),
+ round($topic_data['se'], 2),
+ $bullet,
+ $stateTorrentClient,
+ get_client_name($topic_data['cl'], $cfg)
+ ),
+ $keepers_list
+ );
+ }
+ }
+
+ echo json_encode([
+ 'log' => '',
+ 'topics' => $output,
+ 'size' => $filtered_topics_size,
+ 'count' => $filtered_topics_count,
+ ]);
+ } catch (Exception $e) {
+ echo json_encode([
+ 'log' => $e->getMessage(),
+ 'topics' => null,
+ 'size' => 0,
+ 'count' => 0,
+ ]);
+ }
+}
+
+function get_client_name( int|null $clientID, array $cfg): string
+{
+ if (!$clientID || !isset($cfg['clients'][$clientID])) return '';
+ return sprintf(
+ '%s',
+ $cfg['clients'][$clientID]['cm']
+ );
+}
\ No newline at end of file
diff --git a/php/actions/load_filter_for_cron.php b/php/actions/load_filter_for_cron.php
new file mode 100644
index 000000000..357a429df
--- /dev/null
+++ b/php/actions/load_filter_for_cron.php
@@ -0,0 +1,28 @@
+readFilterFromFile();
+ if (empty($result[$_POST['forum-id']])) {
+ Log::append('Не удалось прочитать параметры фильтра из файла для подраздела:' . $_POST['forum-id']);
+ } else {
+ Log::append('Параметры фильтра успешно прочитаны из файла для подраздела:' . $_POST['forum-id']);
+ }
+ echo json_encode(
+ [
+ 'log' => Log::get(),
+ 'result' => $result[$_POST['forum-id']],
+ ]
+ );
+} catch (Exception $e) {
+ Log::append($e->getMessage());
+ echo json_encode(
+ [
+ 'log' => Log::get(),
+ 'result' => $result[$_POST['forum-id']],
+ ]
+ );
+}
\ No newline at end of file
diff --git a/php/actions/save_filter_for_cron.php b/php/actions/save_filter_for_cron.php
new file mode 100644
index 000000000..f4959d4bb
--- /dev/null
+++ b/php/actions/save_filter_for_cron.php
@@ -0,0 +1,27 @@
+writeFilterToFile($_POST['forum-id'], $_POST['filter-options']);
+ if ($result === false) {
+ Log::append('Не удалось сохранить параметры фильтра в файл');
+ } else {
+ Log::append('Параметры фильтра успешно сохранены в файл');
+ }
+ echo json_encode(
+ [
+ 'log' => Log::get()
+ ]
+ );
+} catch (Exception $e) {
+ Log::append($e->getMessage());
+ echo json_encode(
+ [
+ 'log' => Log::get()
+ ]
+ );
+}
\ No newline at end of file
diff --git a/php/actions/set_config.php b/php/actions/set_config.php
index 4b0f6ea28..d4940eb62 100644
--- a/php/actions/set_config.php
+++ b/php/actions/set_config.php
@@ -110,6 +110,9 @@
if (isset($forumData['hide'])) {
$ini->write($forumID, 'hide-topics', $forumData['hide']);
}
+ if (isset($forumData['autoAdd'])) {
+ $ini->write($forumID, 'auto-add-topics', $forumData['autoAdd']);
+ }
if (isset($forumData['control_peers'])) {
$ini->write($forumID, 'control-peers', $forumData['control_peers']);
}
diff --git a/php/classes/filter.php b/php/classes/filter.php
new file mode 100644
index 000000000..c7c5ff55b
--- /dev/null
+++ b/php/classes/filter.php
@@ -0,0 +1,39 @@
+filterOptions = $this->readFilterFromFile();
+ }
+
+ public mixed $filterOptions;
+
+ public function writeFilterToFile($forumID, $newFilterOptions): bool|int
+ {
+ $this->filterOptions[$forumID] = $newFilterOptions;
+ return file_put_contents(
+ getStorageDir() . DIRECTORY_SEPARATOR . 'filter.json',
+ json_encode(
+ $this->filterOptions
+ )
+ );
+ }
+
+ public function readFilterFromFile(): array
+ {
+ return (array) json_decode(file_get_contents(getStorageDir() . DIRECTORY_SEPARATOR . 'filter.json'));
+ }
+
+ public function getFilterPresetsList(): array
+ {
+ return array_keys($this->readFilterFromFile());
+ }
+
+}
\ No newline at end of file
diff --git a/php/common.php b/php/common.php
index 8048ee83e..65deaf78c 100644
--- a/php/common.php
+++ b/php/common.php
@@ -95,6 +95,7 @@ function get_settings($filename = "")
$config['subsections'][$id]['df'] = $ini->read("$id", "data-folder", "");
$config['subsections'][$id]['sub_folder'] = $ini->read($id, "data-sub-folder", 0);
$config['subsections'][$id]['hide_topics'] = $ini->read($id, "hide-topics", 0);
+ $config['subsections'][$id]['auto_add_topics'] = $ini->read($id, "auto-add-topics", 0);
$config['subsections'][$id]['id'] = $id;
$config['subsections'][$id]['na'] = isset($titles[$id]) ? $titles[$id] : $ini->read("$id", "title", "$id");
$config['subsections'][$id]['control_peers'] = $ini->read($id, 'control-peers', '');
diff --git a/php/common/auto_add.php b/php/common/auto_add.php
new file mode 100644
index 000000000..fc69dcbae
--- /dev/null
+++ b/php/common/auto_add.php
@@ -0,0 +1,50 @@
+ $forumData) {
+ if ($forumData['auto_add_topics'] == 1) {
+ Log::append('Начат процесс добавления новых раздач в торрент-клиент для подраздела ' . $forumID);
+ if (!empty($filter->filterOptions[$forumID])) {
+ $_POST['forum_id'] = $forumID;
+ $_POST['filter'] = json_decode($filter->filterOptions[$forumID], true);
+ $tessst = array_map(function ($key, $value) {
+ return [$value['name'] => $value['value']];
+ }, array_keys($_POST['filter']), array_values($_POST['filter']));
+ $a = 1;
+
+ $_POST['filter'] = http_build_query(
+ array_merge_recursive(
+ ...array_map(function ($key, $value) {
+ return [str_replace("[]", "", $value['name']) => $value['value']];
+ }, array_keys($_POST['filter']), array_values($_POST['filter']))
+ )
+ );
+ ob_start();
+ get_filtered_list_topics();
+ $topics_list = json_decode(ob_get_clean(), true);
+ if (!empty($topics_list['topics'])) {
+ preg_match_all('/(?<=value=").{40}/i', $topics_list['topics'], $_POST['topic_hashes']);
+ $_POST['topic_hashes'] = http_build_query(array_combine(["topic_hashes"], $_POST['topic_hashes']));
+ add_topics_to_client();
+ } else {
+ Log::append("Отсутствуют раздачи для добавления");
+ }
+ Log::append('Процесс добавления торрентов для подраздела ' . $forumID . " завершен");
+ } else {
+ Log::append('Не удалось прочитать параметры фильтра из файла для подраздела:' . $forumID);
+ Log::append('Процесс добавления торрентов для подраздела ' . $forumID . " завершен");
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/scripts/jquery.subsections.js b/scripts/jquery.subsections.js
index d97e81670..d810ed480 100644
--- a/scripts/jquery.subsections.js
+++ b/scripts/jquery.subsections.js
@@ -82,6 +82,9 @@ $(document).ready(function () {
if (forumData.hide == '') {
forumData.hide = 0;
}
+ if (forumData.autoAddTopics == '') {
+ forumData.autoAddTopics = 0;
+ }
var torrentClientID = $("#forum-client option[value=" + forumData.client + "]").val();
if (typeof torrentClientID === "undefined") {
$("#forum-client :first").prop("selected", "selected");
@@ -100,6 +103,12 @@ $(document).ready(function () {
} else {
$("#forum-hide-topics [value=" + hideTopics + "]").prop("selected", "selected");
}
+ var autoAddTopics = $("#forum-auto-add-topics [value=" + forumData.autoAddTopics + "]").val();
+ if (typeof autoAddTopics === "undefined") {
+ $("#forum-auto-add-topics :first").prop("selected", "selected");
+ } else {
+ $("#forum-auto-add-topics [value=" + autoAddTopics + "]").prop("selected", "selected");
+ }
$("#forum-label").val(forumData.label);
$("#forum-savepath").val(forumData.savepath);
$("#forum-control-peers").val(forumData.peers);
@@ -108,6 +117,7 @@ $(document).ready(function () {
$("#forum-client").selectmenu().selectmenu("refresh");
$("#forum-subdirectory").selectmenu().selectmenu("refresh");
$("#forum-hide-topics").selectmenu().selectmenu("refresh");
+ $("#forum-auto-add-topics").selectmenu().selectmenu("refresh");
});
// изменение свойств подраздела
@@ -117,6 +127,7 @@ $(document).ready(function () {
var forumSavePath = $("#forum-savepath").val();
var forumSubdirectory = $("#forum-subdirectory").val();
var forumHideTopics = $("#forum-hide-topics :selected").val();
+ var forumAutoAddTopics = $("#forum-auto-add-topics :selected").val();
var forumControlPeers = $("#forum-control-peers").val();
var optionForum = $("#list-forums option[value=" + editableForumID + "]");
optionForum.attr("data-client", forumClient).data("client", forumClient);
@@ -124,6 +135,7 @@ $(document).ready(function () {
optionForum.attr("data-savepath", forumSavePath).data("savepath", forumSavePath);
optionForum.attr("data-subdirectory", forumSubdirectory).data("subdirectory", forumSubdirectory);
optionForum.attr("data-hide", forumHideTopics).data("hide", forumHideTopics);
+ optionForum.attr("data-auto", forumAutoAddTopics).data("autoAdd", forumAutoAddTopics);
optionForum.attr("data-peers", forumControlPeers).data("peers", forumControlPeers);
});
@@ -269,6 +281,7 @@ function getForums() {
"savepath": forumData.savepath,
"subdirectory": forumData.subdirectory,
"hide": forumData.hide,
+ "autoAdd": forumData.autoAdd,
"control_peers": forumData.peers
};
}
diff --git a/scripts/jquery.topics.js b/scripts/jquery.topics.js
index b86f840fd..5caf9497b 100644
--- a/scripts/jquery.topics.js
+++ b/scripts/jquery.topics.js
@@ -261,6 +261,42 @@ $(document).ready(function () {
);
});
+ // сохранение параметров фильтра в файл
+ $("#save_filter_for_cron").on("click", function () {
+ $.ajax({
+ type: "POST",
+ url: "php/actions/save_filter_for_cron.php",
+ data: {
+ "forum-id": $("#main-subsections").val(),
+ "filter-options": JSON.stringify($("#topics_filter").serializeAllArray())
+ },
+ success: function (response) {
+ response = $.parseJSON(response);
+ $("#log").append(response.log);
+
+ }
+ });
+ });
+
+ // чтение параметров фильтра из файла
+ $("#load_filter_for_cron").on("click", function () {
+ $.ajax({
+ type: "POST",
+ url: "php/actions/load_filter_for_cron.php",
+ data: {
+ "forum-id": $("#main-subsections").val(),
+ },
+ success: function (response) {
+ response = $.parseJSON(response);
+ $("#log").append(response.log);
+ if (response.result != null) {
+ loadSavedFilterOptions(response.result);
+ $("#topics_filter").change();
+ }
+ }
+ });
+ });
+
// кнопка выделить все / отменить выделение
$(".tor_select").on("click", function () {
var value = $(this).val();
diff --git a/scripts/jquery.widgets.js b/scripts/jquery.widgets.js
index 0ac7fd900..581bbb213 100644
--- a/scripts/jquery.widgets.js
+++ b/scripts/jquery.widgets.js
@@ -59,6 +59,7 @@ $(document).ready(function () {
$("input[type=button]").button();
$("#toolbar-select-topics").buttonset();
$("#toolbar-control-topics").buttonset();
+ $("#toolbar-cron-topics").buttonset();
$("#toolbar-filter-topics").buttonset();
$("#log_tabs").tabs();
$("#tor_download_options").selectmenu({
From 5038e7d9e36cd73d300ff4abec84656caacca0e4 Mon Sep 17 00:00:00 2001
From: Max <1784545+max41479@users.noreply.github.com>
Date: Mon, 6 Feb 2023 05:04:29 +0300
Subject: [PATCH 2/2] Fixed typo
Signed-off-by: Max <1784545+max41479@users.noreply.github.com>
---
php/common/auto_add.php | 2 --
1 file changed, 2 deletions(-)
diff --git a/php/common/auto_add.php b/php/common/auto_add.php
index fc69dcbae..8005cfeb9 100644
--- a/php/common/auto_add.php
+++ b/php/common/auto_add.php
@@ -21,8 +21,6 @@
$tessst = array_map(function ($key, $value) {
return [$value['name'] => $value['value']];
}, array_keys($_POST['filter']), array_values($_POST['filter']));
- $a = 1;
-
$_POST['filter'] = http_build_query(
array_merge_recursive(
...array_map(function ($key, $value) {