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 @@ +
    @@ -887,6 +904,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 = - '
    '. - '(%1$s) %2$s'. - '
    '; - - // выводим раздачи - 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 = + '
    ' . + '(%1$s) %2$s' . + '
    '; + + // выводим раздачи + 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) {