From 7ad667e8d2fe62f3def92db3849fc58c849698d8 Mon Sep 17 00:00:00 2001 From: Vladimir Golovnev Date: Thu, 12 May 2022 08:12:19 +0300 Subject: [PATCH] Add trackers in exported .torrent files Co-authored-by: Chocobo1 PR #17018. --- src/base/bittorrent/session.cpp | 38 ++++++----------------------- src/base/bittorrent/session.h | 2 +- src/base/bittorrent/torrent.h | 4 ++- src/base/bittorrent/torrentimpl.cpp | 33 +++++++++++++++++++++++++ src/base/bittorrent/torrentimpl.h | 1 + src/base/bittorrent/torrentinfo.cpp | 1 - src/base/bittorrent/torrentinfo.h | 1 + 7 files changed, 47 insertions(+), 33 deletions(-) diff --git a/src/base/bittorrent/session.cpp b/src/base/bittorrent/session.cpp index f32004801..6aa665fcc 100644 --- a/src/base/bittorrent/session.cpp +++ b/src/base/bittorrent/session.cpp @@ -2351,9 +2351,9 @@ bool Session::downloadMetadata(const MagnetUri &magnetUri) return true; } -void Session::exportTorrentFile(const TorrentInfo &torrentInfo, const QString &folderPath, const QString &baseName) +void Session::exportTorrentFile(const Torrent *torrent, const QString &folderPath) { - const QString validName = Utils::Fs::toValidFileSystemName(baseName); + const QString validName = Utils::Fs::toValidFileSystemName(torrent->name()); QString torrentExportFilename = QString::fromLatin1("%1.torrent").arg(validName); const QDir exportDir {folderPath}; if (exportDir.exists() || exportDir.mkpath(exportDir.absolutePath())) @@ -2367,11 +2367,11 @@ void Session::exportTorrentFile(const TorrentInfo &torrentInfo, const QString &f newTorrentPath = exportDir.absoluteFilePath(torrentExportFilename); } - const nonstd::expected result = torrentInfo.saveToFile(newTorrentPath); + const nonstd::expected result = torrent->exportToFile(newTorrentPath); if (!result) { - LogMsg(tr("Couldn't export torrent metadata file '%1'. Reason: %2.") - .arg(newTorrentPath, result.error()), Log::WARNING); + LogMsg(tr("Failed to export torrent. Torrent: \"%1\". Destination: \"%2\". Reason: \"%3\"") + .arg(torrent->name(), newTorrentPath, result.error()), Log::WARNING); } } } @@ -3978,17 +3978,8 @@ void Session::handleTorrentUrlSeedsRemoved(TorrentImpl *const torrent, const QVe void Session::handleTorrentMetadataReceived(TorrentImpl *const torrent) { - // Copy the torrent file to the export folder if (!torrentExportDirectory().isEmpty()) - { -#ifdef QBT_USES_LIBTORRENT2 - const std::shared_ptr completeTorrentInfo = torrent->nativeHandle().torrent_file_with_hashes(); - const TorrentInfo torrentInfo {*(completeTorrentInfo ? completeTorrentInfo : torrent->nativeHandle().torrent_file())}; -#else - const TorrentInfo torrentInfo {*torrent->nativeHandle().torrent_file()}; -#endif - exportTorrentFile(torrentInfo, torrentExportDirectory(), torrent->name()); - } + exportTorrentFile(torrent, torrentExportDirectory()); emit torrentMetadataReceived(torrent); } @@ -4035,17 +4026,8 @@ void Session::handleTorrentFinished(TorrentImpl *const torrent) } } - // Move .torrent file to another folder if (!finishedTorrentExportDirectory().isEmpty()) - { -#ifdef QBT_USES_LIBTORRENT2 - const std::shared_ptr completeTorrentInfo = torrent->nativeHandle().torrent_file_with_hashes(); - const TorrentInfo torrentInfo {*(completeTorrentInfo ? completeTorrentInfo : torrent->nativeHandle().torrent_file())}; -#else - const TorrentInfo torrentInfo {*torrent->nativeHandle().torrent_file()}; -#endif - exportTorrentFile(torrentInfo, finishedTorrentExportDirectory(), torrent->name()); - } + exportTorrentFile(torrent, finishedTorrentExportDirectory()); if (!hasUnfinishedTorrents()) emit allTorrentsFinished(); @@ -4777,12 +4759,8 @@ void Session::createTorrent(const lt::torrent_handle &nativeHandle) // The following is useless for newly added magnet if (hasMetadata) { - // Copy the torrent file to the export folder if (!torrentExportDirectory().isEmpty()) - { - const TorrentInfo torrentInfo {*params.ltAddTorrentParams.ti}; - exportTorrentFile(torrentInfo, torrentExportDirectory(), torrent->name()); - } + exportTorrentFile(torrent, torrentExportDirectory()); } if (isAddTrackersEnabled() && !torrent->isPrivate()) diff --git a/src/base/bittorrent/session.h b/src/base/bittorrent/session.h index 9c6eae3d1..d0f0f5f8a 100644 --- a/src/base/bittorrent/session.h +++ b/src/base/bittorrent/session.h @@ -609,7 +609,7 @@ namespace BitTorrent bool addTorrent_impl(const std::variant &source, const AddTorrentParams &addTorrentParams); void updateSeedingLimitTimer(); - void exportTorrentFile(const TorrentInfo &torrentInfo, const QString &folderPath, const QString &baseName); + void exportTorrentFile(const Torrent *torrent, const QString &folderPath); void handleAlert(const lt::alert *a); void dispatchTorrentAlert(const lt::alert *a); diff --git a/src/base/bittorrent/torrent.h b/src/base/bittorrent/torrent.h index cd3c9345a..2ff5a5330 100644 --- a/src/base/bittorrent/torrent.h +++ b/src/base/bittorrent/torrent.h @@ -29,10 +29,11 @@ #pragma once +#include #include #include -#include +#include "base/3rdparty/expected.hpp" #include "base/tagset.h" #include "abstractfilestorage.h" @@ -294,6 +295,7 @@ namespace BitTorrent virtual void clearPeers() = 0; virtual QString createMagnetURI() const = 0; + virtual nonstd::expected exportToFile(const QString &path) const = 0; TorrentID id() const; bool isResumed() const; diff --git a/src/base/bittorrent/torrentimpl.cpp b/src/base/bittorrent/torrentimpl.cpp index 897621fd3..ca3b650cc 100644 --- a/src/base/bittorrent/torrentimpl.cpp +++ b/src/base/bittorrent/torrentimpl.cpp @@ -35,6 +35,7 @@ #include #include +#include #include #include #include @@ -55,6 +56,7 @@ #include "base/logger.h" #include "base/preferences.h" #include "base/utils/fs.h" +#include "base/utils/io.h" #include "base/utils/string.h" #include "common.h" #include "downloadpriority.h" @@ -2248,6 +2250,37 @@ QString TorrentImpl::createMagnetURI() const return QString::fromStdString(lt::make_magnet_uri(m_nativeHandle)); } +nonstd::expected TorrentImpl::exportToFile(const QString &path) const +{ + if (!hasMetadata()) + return nonstd::make_unexpected(tr("Missing metadata")); + + try + { +#ifdef QBT_USES_LIBTORRENT2 + const std::shared_ptr completeTorrentInfo = m_nativeHandle.torrent_file_with_hashes(); + const std::shared_ptr torrentInfo = (completeTorrentInfo ? completeTorrentInfo : info().nativeInfo()); +#else + const std::shared_ptr torrentInfo = info().nativeInfo(); +#endif + auto creator = lt::create_torrent(*torrentInfo); + + for (const TrackerEntry &entry : asConst(trackers())) + creator.add_tracker(entry.url.toStdString(), entry.tier); + + const lt::entry torrentEntry = creator.generate(); + const nonstd::expected result = Utils::IO::saveToFile(path, torrentEntry); + if (!result) + return result.get_unexpected(); + } + catch (const lt::system_error &err) + { + return nonstd::make_unexpected(QString::fromLocal8Bit(err.what())); + } + + return {}; +} + void TorrentImpl::prioritizeFiles(const QVector &priorities) { if (!hasMetadata()) return; diff --git a/src/base/bittorrent/torrentimpl.h b/src/base/bittorrent/torrentimpl.h index 764251511..f66c23776 100644 --- a/src/base/bittorrent/torrentimpl.h +++ b/src/base/bittorrent/torrentimpl.h @@ -224,6 +224,7 @@ namespace BitTorrent void clearPeers() override; QString createMagnetURI() const override; + nonstd::expected exportToFile(const QString &path) const; bool needSaveResumeData() const; diff --git a/src/base/bittorrent/torrentinfo.cpp b/src/base/bittorrent/torrentinfo.cpp index e46e60b07..58701d0e1 100644 --- a/src/base/bittorrent/torrentinfo.cpp +++ b/src/base/bittorrent/torrentinfo.cpp @@ -38,7 +38,6 @@ #include #include #include -#include #include "base/global.h" #include "base/utils/fs.h" diff --git a/src/base/bittorrent/torrentinfo.h b/src/base/bittorrent/torrentinfo.h index 62d073ef5..d55fa7c1e 100644 --- a/src/base/bittorrent/torrentinfo.h +++ b/src/base/bittorrent/torrentinfo.h @@ -32,6 +32,7 @@ #include #include +#include #include "base/3rdparty/expected.hpp" #include "base/indexrange.h"