diff --git a/src/base/search/searchdownloadhandler.cpp b/src/base/search/searchdownloadhandler.cpp index d4de1c10b..436637183 100644 --- a/src/base/search/searchdownloadhandler.cpp +++ b/src/base/search/searchdownloadhandler.cpp @@ -1,6 +1,6 @@ /* * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2018 Vladimir Golovnev + * Copyright (C) 2018-2024 Vladimir Golovnev * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -36,10 +36,10 @@ #include "base/utils/fs.h" #include "searchpluginmanager.h" -SearchDownloadHandler::SearchDownloadHandler(const QString &siteUrl, const QString &url, SearchPluginManager *manager) - : QObject {manager} +SearchDownloadHandler::SearchDownloadHandler(const QString &pluginName, const QString &url, SearchPluginManager *manager) + : QObject(manager) , m_manager {manager} - , m_downloadProcess {new QProcess {this}} + , m_downloadProcess {new QProcess(this)} { m_downloadProcess->setEnvironment(QProcess::systemEnvironment()); connect(m_downloadProcess, qOverload(&QProcess::finished) @@ -48,7 +48,7 @@ SearchDownloadHandler::SearchDownloadHandler(const QString &siteUrl, const QStri { Utils::ForeignApps::PYTHON_ISOLATE_MODE_FLAG, (SearchPluginManager::engineLocation() / Path(u"nova2dl.py"_s)).toString(), - siteUrl, + pluginName, url }; // Launch search diff --git a/src/base/search/searchdownloadhandler.h b/src/base/search/searchdownloadhandler.h index 4fa51a43c..426560e0a 100644 --- a/src/base/search/searchdownloadhandler.h +++ b/src/base/search/searchdownloadhandler.h @@ -1,6 +1,6 @@ /* * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2018 Vladimir Golovnev + * Copyright (C) 2018-2024 Vladimir Golovnev * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -41,7 +41,7 @@ class SearchDownloadHandler : public QObject friend class SearchPluginManager; - SearchDownloadHandler(const QString &siteUrl, const QString &url, SearchPluginManager *manager); + SearchDownloadHandler(const QString &pluginName, const QString &url, SearchPluginManager *manager); signals: void downloadFinished(const QString &path); diff --git a/src/base/search/searchhandler.cpp b/src/base/search/searchhandler.cpp index c5cace333..b08a62fd4 100644 --- a/src/base/search/searchhandler.cpp +++ b/src/base/search/searchhandler.cpp @@ -1,6 +1,6 @@ /* * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2015, 2018 Vladimir Golovnev + * Copyright (C) 2015-2024 Vladimir Golovnev * Copyright (C) 2006 Christophe Dumez * * This program is free software; you can redistribute it and/or @@ -61,13 +61,13 @@ namespace } SearchHandler::SearchHandler(const QString &pattern, const QString &category, const QStringList &usedPlugins, SearchPluginManager *manager) - : QObject {manager} + : QObject(manager) , m_pattern {pattern} , m_category {category} , m_usedPlugins {usedPlugins} , m_manager {manager} - , m_searchProcess {new QProcess {this}} - , m_searchTimeout {new QTimer {this}} + , m_searchProcess {new QProcess(this)} + , m_searchTimeout {new QTimer(this)} { // Load environment variables (proxy) m_searchProcess->setEnvironment(QProcess::systemEnvironment()); @@ -177,7 +177,8 @@ bool SearchHandler::parseSearchResult(const QStringView line, SearchResult &sear const QList parts = line.split(u'|'); const int nbFields = parts.size(); - if (nbFields <= PL_ENGINE_URL) return false; // Anything after ENGINE_URL is optional + if (nbFields <= PL_ENGINE_URL) + return false; // Anything after ENGINE_URL is optional searchResult = SearchResult(); searchResult.fileUrl = parts.at(PL_DL_LINK).trimmed().toString(); // download URL @@ -194,7 +195,8 @@ bool SearchHandler::parseSearchResult(const QStringView line, SearchResult &sear if (!ok || (searchResult.nbLeechers < 0)) searchResult.nbLeechers = -1; - searchResult.siteUrl = parts.at(PL_ENGINE_URL).trimmed().toString(); // Search site URL + searchResult.siteUrl = parts.at(PL_ENGINE_URL).trimmed().toString(); // Search engine site URL + searchResult.engineName = m_manager->pluginNameBySiteURL(searchResult.siteUrl); // Search engine name if (nbFields > PL_DESC_LINK) searchResult.descrLink = parts.at(PL_DESC_LINK).trimmed().toString(); // Description Link diff --git a/src/base/search/searchhandler.h b/src/base/search/searchhandler.h index 4085b20fa..c765a9bfe 100644 --- a/src/base/search/searchhandler.h +++ b/src/base/search/searchhandler.h @@ -1,6 +1,6 @@ /* * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2015, 2018 Vladimir Golovnev + * Copyright (C) 2015-2024 Vladimir Golovnev * Copyright (C) 2006 Christophe Dumez * * This program is free software; you can redistribute it and/or @@ -46,6 +46,7 @@ struct SearchResult qlonglong fileSize = 0; qlonglong nbSeeders = 0; qlonglong nbLeechers = 0; + QString engineName; QString siteUrl; QString descrLink; QDateTime pubDate; diff --git a/src/base/search/searchpluginmanager.cpp b/src/base/search/searchpluginmanager.cpp index dc7438748..095e3d57a 100644 --- a/src/base/search/searchpluginmanager.cpp +++ b/src/base/search/searchpluginmanager.cpp @@ -1,6 +1,6 @@ /* * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2015, 2018 Vladimir Golovnev + * Copyright (C) 2015-2024 Vladimir Golovnev * Copyright (C) 2006 Christophe Dumez * * This program is free software; you can redistribute it and/or @@ -181,6 +181,17 @@ PluginInfo *SearchPluginManager::pluginInfo(const QString &name) const return m_plugins.value(name); } +QString SearchPluginManager::pluginNameBySiteURL(const QString &siteURL) const +{ + for (const PluginInfo *plugin : asConst(m_plugins)) + { + if (plugin->url == siteURL) + return plugin->name; + } + + return {}; +} + void SearchPluginManager::enablePlugin(const QString &name, const bool enabled) { PluginInfo *plugin = m_plugins.value(name, nullptr); @@ -338,9 +349,9 @@ void SearchPluginManager::checkForUpdates() , this, &SearchPluginManager::versionInfoDownloadFinished); } -SearchDownloadHandler *SearchPluginManager::downloadTorrent(const QString &siteUrl, const QString &url) +SearchDownloadHandler *SearchPluginManager::downloadTorrent(const QString &pluginName, const QString &url) { - return new SearchDownloadHandler {siteUrl, url, this}; + return new SearchDownloadHandler(pluginName, url, this); } SearchHandler *SearchPluginManager::startSearch(const QString &pattern, const QString &category, const QStringList &usedPlugins) diff --git a/src/base/search/searchpluginmanager.h b/src/base/search/searchpluginmanager.h index 86038ad66..72cf0f146 100644 --- a/src/base/search/searchpluginmanager.h +++ b/src/base/search/searchpluginmanager.h @@ -1,6 +1,6 @@ /* * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2015, 2018 Vladimir Golovnev + * Copyright (C) 2015-2024 Vladimir Golovnev * Copyright (C) 2006 Christophe Dumez * * This program is free software; you can redistribute it and/or @@ -75,6 +75,7 @@ public: QStringList supportedCategories() const; QStringList getPluginCategories(const QString &pluginName) const; PluginInfo *pluginInfo(const QString &name) const; + QString pluginNameBySiteURL(const QString &siteURL) const; void enablePlugin(const QString &name, bool enabled = true); void updatePlugin(const QString &name); @@ -84,7 +85,7 @@ public: void checkForUpdates(); SearchHandler *startSearch(const QString &pattern, const QString &category, const QStringList &usedPlugins); - SearchDownloadHandler *downloadTorrent(const QString &siteUrl, const QString &url); + SearchDownloadHandler *downloadTorrent(const QString &pluginName, const QString &url); static PluginVersion getPluginVersion(const Path &filePath); static QString categoryFullName(const QString &categoryName); diff --git a/src/gui/search/searchjobwidget.cpp b/src/gui/search/searchjobwidget.cpp index 4c86ea4de..e8aa99ead 100644 --- a/src/gui/search/searchjobwidget.cpp +++ b/src/gui/search/searchjobwidget.cpp @@ -70,7 +70,8 @@ SearchJobWidget::SearchJobWidget(SearchHandler *searchHandler, IGUIApplication * m_searchListModel->setHeaderData(SearchSortModel::SIZE, Qt::Horizontal, tr("Size", "i.e: file size")); m_searchListModel->setHeaderData(SearchSortModel::SEEDS, Qt::Horizontal, tr("Seeders", "i.e: Number of full sources")); m_searchListModel->setHeaderData(SearchSortModel::LEECHES, Qt::Horizontal, tr("Leechers", "i.e: Number of partial sources")); - m_searchListModel->setHeaderData(SearchSortModel::ENGINE_URL, Qt::Horizontal, tr("Search engine")); + m_searchListModel->setHeaderData(SearchSortModel::ENGINE_NAME, Qt::Horizontal, tr("Engine")); + m_searchListModel->setHeaderData(SearchSortModel::ENGINE_URL, Qt::Horizontal, tr("Engine URL")); m_searchListModel->setHeaderData(SearchSortModel::PUB_DATE, Qt::Horizontal, tr("Published On")); // Set columns text alignment m_searchListModel->setHeaderData(SearchSortModel::SIZE, Qt::Horizontal, QVariant(Qt::AlignRight | Qt::AlignVCenter), Qt::TextAlignmentRole); @@ -269,8 +270,8 @@ void SearchJobWidget::downloadTorrent(const QModelIndex &rowIndex, const AddTorr { const QString torrentUrl = m_proxyModel->data( m_proxyModel->index(rowIndex.row(), SearchSortModel::DL_LINK)).toString(); - const QString siteUrl = m_proxyModel->data( - m_proxyModel->index(rowIndex.row(), SearchSortModel::ENGINE_URL)).toString(); + const QString engineName = m_proxyModel->data( + m_proxyModel->index(rowIndex.row(), SearchSortModel::ENGINE_NAME)).toString(); if (torrentUrl.startsWith(u"magnet:", Qt::CaseInsensitive)) { @@ -278,7 +279,7 @@ void SearchJobWidget::downloadTorrent(const QModelIndex &rowIndex, const AddTorr } else { - SearchDownloadHandler *downloadHandler = m_searchHandler->manager()->downloadTorrent(siteUrl, torrentUrl); + SearchDownloadHandler *downloadHandler = m_searchHandler->manager()->downloadTorrent(engineName, torrentUrl); connect(downloadHandler, &SearchDownloadHandler::downloadFinished , this, [this, option](const QString &source) { addTorrentToSession(source, option); }); connect(downloadHandler, &SearchDownloadHandler::downloadFinished, downloadHandler, &SearchDownloadHandler::deleteLater); @@ -516,7 +517,7 @@ void SearchJobWidget::appendSearchResults(const QVector &results) m_searchListModel->insertRow(row); const auto setModelData = [this, row] (const int column, const QString &displayData - , const QVariant &underlyingData, const Qt::Alignment textAlignmentData = {}) + , const QVariant &underlyingData, const Qt::Alignment textAlignmentData = {}) { const QMap data = { @@ -529,6 +530,7 @@ void SearchJobWidget::appendSearchResults(const QVector &results) setModelData(SearchSortModel::NAME, result.fileName, result.fileName); setModelData(SearchSortModel::DL_LINK, result.fileUrl, result.fileUrl); + setModelData(SearchSortModel::ENGINE_NAME, result.engineName, result.engineName); setModelData(SearchSortModel::ENGINE_URL, result.siteUrl, result.siteUrl); setModelData(SearchSortModel::DESC_LINK, result.descrLink, result.descrLink); setModelData(SearchSortModel::SIZE, Utils::Misc::friendlyUnit(result.fileSize), result.fileSize, (Qt::AlignRight | Qt::AlignVCenter)); diff --git a/src/gui/search/searchsortmodel.h b/src/gui/search/searchsortmodel.h index cbd3f8ff2..f250cded5 100644 --- a/src/gui/search/searchsortmodel.h +++ b/src/gui/search/searchsortmodel.h @@ -44,6 +44,7 @@ public: SIZE, SEEDS, LEECHES, + ENGINE_NAME, ENGINE_URL, PUB_DATE, DL_LINK, diff --git a/src/searchengine/nova3/nova2dl.py b/src/searchengine/nova3/nova2dl.py index 7146a9cb1..c35646654 100644 --- a/src/searchengine/nova3/nova2dl.py +++ b/src/searchengine/nova3/nova2dl.py @@ -1,7 +1,9 @@ -#VERSION: 1.23 +#VERSION: 1.24 # Author: # Christophe DUMEZ (chris@qbittorrent.org) +# Contributors: +# Vladimir Golovnev (glassez@yandex.ru) # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: @@ -27,9 +29,7 @@ # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. -import glob import importlib -import os import pathlib import sys @@ -40,34 +40,24 @@ if current_path not in sys.path: from helpers import download_file -supported_engines = dict() - -engines = glob.glob(os.path.join(os.path.dirname(__file__), 'engines', '*.py')) -for engine in engines: - e = engine.split(os.sep)[-1][:-3] - if len(e.strip()) == 0: - continue - if e.startswith('_'): - continue - try: - module = importlib.import_module("engines." + e) - engine_class = getattr(module, e) - globals()[e] = engine_class - engine_url = getattr(engine_class, 'url') - supported_engines[engine_url] = e - except Exception: - pass - if __name__ == '__main__': if len(sys.argv) < 3: - raise SystemExit('./nova2dl.py engine_url download_parameter') - engine_url = sys.argv[1].strip() + raise SystemExit('./nova2dl.py engine_name download_parameter') + + engine_name = sys.argv[1].strip() download_param = sys.argv[2].strip() - if engine_url not in supported_engines.keys(): - raise SystemExit('./nova2dl.py: this engine_url was not recognized') - engine = globals()[supported_engines[engine_url]]() + + try: + module = importlib.import_module("engines." + engine_name) + engine_class = getattr(module, engine_name) + engine = engine_class() + except Exception as e: + print(repr(e)) + raise SystemExit('./nova2dl.py: this engine_name was not recognized') + if hasattr(engine, 'download_torrent'): engine.download_torrent(download_param) else: print(download_file(download_param)) + sys.exit(0) diff --git a/src/webui/api/searchcontroller.cpp b/src/webui/api/searchcontroller.cpp index 44a88a7ac..b954da119 100644 --- a/src/webui/api/searchcontroller.cpp +++ b/src/webui/api/searchcontroller.cpp @@ -1,5 +1,6 @@ /* * Bittorrent Client using Qt and libtorrent. + * Copyright (C) 2024 Vladimir Golovnev * Copyright (C) 2018 Thomas Piccirello * * This program is free software; you can redistribute it and/or @@ -36,8 +37,11 @@ #include #include +#include "base/addtorrentmanager.h" #include "base/global.h" +#include "base/interfaces/iapplication.h" #include "base/logger.h" +#include "base/search/searchdownloadhandler.h" #include "base/search/searchhandler.h" #include "base/utils/datetime.h" #include "base/utils/foreignapps.h" @@ -213,6 +217,29 @@ void SearchController::deleteAction() m_searchHandlers.erase(iter); } +void SearchController::downloadTorrentAction() +{ + requireParams({u"torrentUrl"_s, u"pluginName"_s}); + + const QString torrentUrl = params()[u"torrentUrl"_s]; + const QString pluginName = params()[u"pluginName"_s]; + + if (torrentUrl.startsWith(u"magnet:", Qt::CaseInsensitive)) + { + app()->addTorrentManager()->addTorrent(torrentUrl); + } + else + { + SearchDownloadHandler *downloadHandler = SearchPluginManager::instance()->downloadTorrent(pluginName, torrentUrl); + connect(downloadHandler, &SearchDownloadHandler::downloadFinished + , this, [this, downloadHandler](const QString &source) + { + app()->addTorrentManager()->addTorrent(source); + downloadHandler->deleteLater(); + }); + } +} + void SearchController::pluginsAction() { const QStringList allPlugins = SearchPluginManager::instance()->allPlugins(); @@ -300,6 +327,7 @@ int SearchController::generateSearchId() const * - "fileSize" * - "nbSeeders" * - "nbLeechers" + * - "engineName" * - "siteUrl" * - "descrLink" * - "pubDate" @@ -316,6 +344,7 @@ QJsonObject SearchController::getResults(const QList &searchResult {u"fileSize"_s, searchResult.fileSize}, {u"nbSeeders"_s, searchResult.nbSeeders}, {u"nbLeechers"_s, searchResult.nbLeechers}, + {u"engineName"_s, searchResult.engineName}, {u"siteUrl"_s, searchResult.siteUrl}, {u"descrLink"_s, searchResult.descrLink}, {u"pubDate"_s, Utils::DateTime::toSecsSinceEpoch(searchResult.pubDate)} diff --git a/src/webui/api/searchcontroller.h b/src/webui/api/searchcontroller.h index 78e70e759..b5fd7928b 100644 --- a/src/webui/api/searchcontroller.h +++ b/src/webui/api/searchcontroller.h @@ -1,5 +1,6 @@ /* * Bittorrent Client using Qt and libtorrent. + * Copyright (C) 2024 Vladimir Golovnev * Copyright (C) 2018 Thomas Piccirello * * This program is free software; you can redistribute it and/or @@ -56,6 +57,7 @@ private slots: void statusAction(); void resultsAction(); void deleteAction(); + void downloadTorrentAction(); void pluginsAction(); void installPluginAction(); void uninstallPluginAction();