Add unified class to represent parsed torrent metadata

* Add unified class to represent parsed torrent metadata
* Unify startup logic of "Add new torrent dialog"

PR #19301.
This commit is contained in:
Vladimir Golovnev 2023-07-21 08:40:16 +03:00 committed by GitHub
parent d554f4d44a
commit f27f2c20e0
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
18 changed files with 498 additions and 439 deletions

View file

@ -101,10 +101,10 @@
#include "filterparserthread.h"
#include "loadtorrentparams.h"
#include "lttypecast.h"
#include "magneturi.h"
#include "nativesessionextension.h"
#include "portforwarderimpl.h"
#include "resumedatastorage.h"
#include "torrentdescriptor.h"
#include "torrentimpl.h"
#include "tracker.h"
@ -2250,14 +2250,22 @@ void SessionImpl::handleDownloadFinished(const Net::DownloadResult &result)
{
case Net::DownloadStatus::Success:
emit downloadFromUrlFinished(result.url);
if (const nonstd::expected<TorrentInfo, QString> loadResult = TorrentInfo::load(result.data); loadResult)
if (const auto loadResult = TorrentDescriptor::load(result.data))
addTorrent(loadResult.value(), m_downloadedTorrents.take(result.url));
else
LogMsg(tr("Failed to load torrent. Reason: \"%1\"").arg(loadResult.error()), Log::WARNING);
break;
case Net::DownloadStatus::RedirectedToMagnet:
emit downloadFromUrlFinished(result.url);
addTorrent(MagnetUri(result.magnet), m_downloadedTorrents.take(result.url));
if (const auto parseResult = TorrentDescriptor::parse(result.magnetURI))
{
addTorrent(parseResult.value(), m_downloadedTorrents.take(result.url));
}
else
{
LogMsg(tr("Failed to load torrent. The request was redirected to invalid Magnet URI. Reason: \"%1\"")
.arg(parseResult.error()), Log::WARNING);
}
break;
default:
emit downloadFromUrlFailed(result.url, result.errorString);
@ -2592,13 +2600,12 @@ bool SessionImpl::addTorrent(const QString &source, const AddTorrentParams &para
return true;
}
const MagnetUri magnetUri {source};
if (magnetUri.isValid())
return addTorrent(magnetUri, params);
if (const auto parseResult = TorrentDescriptor::parse(source))
return addTorrent(parseResult.value(), params);
const Path path {source};
TorrentFileGuard guard {path};
const nonstd::expected<TorrentInfo, QString> loadResult = TorrentInfo::loadFromFile(path);
const auto loadResult = TorrentDescriptor::loadFromFile(path);
if (!loadResult)
{
LogMsg(tr("Failed to load torrent. Source: \"%1\". Reason: \"%2\"").arg(source, loadResult.error()), Log::WARNING);
@ -2609,23 +2616,12 @@ bool SessionImpl::addTorrent(const QString &source, const AddTorrentParams &para
return addTorrent(loadResult.value(), params);
}
bool SessionImpl::addTorrent(const MagnetUri &magnetUri, const AddTorrentParams &params)
bool SessionImpl::addTorrent(const TorrentDescriptor &torrentDescr, const AddTorrentParams &params)
{
if (!isRestored())
return false;
if (!magnetUri.isValid())
return false;
return addTorrent_impl(magnetUri, params);
}
bool SessionImpl::addTorrent(const TorrentInfo &torrentInfo, const AddTorrentParams &params)
{
if (!isRestored())
return false;
return addTorrent_impl(torrentInfo, params);
return addTorrent_impl(torrentDescr, params);
}
LoadTorrentParams SessionImpl::initLoadTorrentParams(const AddTorrentParams &addTorrentParams)
@ -2690,12 +2686,12 @@ LoadTorrentParams SessionImpl::initLoadTorrentParams(const AddTorrentParams &add
}
// Add a torrent to the BitTorrent session
bool SessionImpl::addTorrent_impl(const std::variant<MagnetUri, TorrentInfo> &source, const AddTorrentParams &addTorrentParams)
bool SessionImpl::addTorrent_impl(const TorrentDescriptor &source, const AddTorrentParams &addTorrentParams)
{
Q_ASSERT(isRestored());
const bool hasMetadata = std::holds_alternative<TorrentInfo>(source);
const auto infoHash = (hasMetadata ? std::get<TorrentInfo>(source).infoHash() : std::get<MagnetUri>(source).infoHash());
const bool hasMetadata = (source.info().has_value());
const auto infoHash = source.infoHash();
const auto id = TorrentID::fromInfoHash(infoHash);
// alternative ID can be useful to find existing torrent in case if hybrid torrent was added by v1 info hash
@ -2712,7 +2708,7 @@ bool SessionImpl::addTorrent_impl(const std::variant<MagnetUri, TorrentInfo> &so
if (hasMetadata)
{
// Trying to set metadata to existing torrent in case if it has none
torrent->setMetadata(std::get<TorrentInfo>(source));
torrent->setMetadata(*source.info());
}
if (!isMergeTrackersEnabled())
@ -2721,29 +2717,16 @@ bool SessionImpl::addTorrent_impl(const std::variant<MagnetUri, TorrentInfo> &so
return false;
}
const bool isPrivate = torrent->isPrivate() || (hasMetadata && std::get<TorrentInfo>(source).isPrivate());
const bool isPrivate = torrent->isPrivate() || (hasMetadata && source.info()->isPrivate());
if (isPrivate)
{
LogMsg(tr("Detected an attempt to add a duplicate torrent. Trackers cannot be merged because it is a private torrent. Torrent: %1").arg(torrent->name()));
return false;
}
if (hasMetadata)
{
const TorrentInfo &torrentInfo = std::get<TorrentInfo>(source);
// merge trackers and web seeds
torrent->addTrackers(torrentInfo.trackers());
torrent->addUrlSeeds(torrentInfo.urlSeeds());
}
else
{
const MagnetUri &magnetUri = std::get<MagnetUri>(source);
// merge trackers and web seeds
torrent->addTrackers(magnetUri.trackers());
torrent->addUrlSeeds(magnetUri.urlSeeds());
}
// merge trackers and web seeds
torrent->addTrackers(source.trackers());
torrent->addUrlSeeds(source.urlSeeds());
LogMsg(tr("Detected an attempt to add a duplicate torrent. Trackers are merged from new source. Torrent: %1").arg(torrent->name()));
return false;
@ -2759,6 +2742,7 @@ bool SessionImpl::addTorrent_impl(const std::variant<MagnetUri, TorrentInfo> &so
LoadTorrentParams loadTorrentParams = initLoadTorrentParams(addTorrentParams);
lt::add_torrent_params &p = loadTorrentParams.ltAddTorrentParams;
p = source.ltAddTorrentParams();
bool isFindingIncompleteFiles = false;
@ -2767,7 +2751,7 @@ bool SessionImpl::addTorrent_impl(const std::variant<MagnetUri, TorrentInfo> &so
if (hasMetadata)
{
const TorrentInfo &torrentInfo = std::get<TorrentInfo>(source);
const TorrentInfo &torrentInfo = *source.info();
Q_ASSERT(addTorrentParams.filePaths.isEmpty() || (addTorrentParams.filePaths.size() == torrentInfo.filesCount()));
@ -2779,8 +2763,7 @@ bool SessionImpl::addTorrent_impl(const std::variant<MagnetUri, TorrentInfo> &so
{
const Path originalRootFolder = Path::findRootFolder(filePaths);
const auto originalContentLayout = (originalRootFolder.isEmpty()
? TorrentContentLayout::NoSubfolder
: TorrentContentLayout::Subfolder);
? TorrentContentLayout::NoSubfolder : TorrentContentLayout::Subfolder);
if (loadTorrentParams.contentLayout != originalContentLayout)
{
if (loadTorrentParams.contentLayout == TorrentContentLayout::NoSubfolder)
@ -2843,13 +2826,10 @@ bool SessionImpl::addTorrent_impl(const std::variant<MagnetUri, TorrentInfo> &so
p.file_priorities[LT::toUnderlyingType(nativeIndexes[i])] = LT::toNative(addTorrentParams.filePriorities[i]);
}
p.ti = torrentInfo.nativeInfo();
Q_ASSERT(p.ti);
}
else
{
const MagnetUri &magnetUri = std::get<MagnetUri>(source);
p = magnetUri.addTorrentParams();
if (loadTorrentParams.name.isEmpty() && !p.name.empty())
loadTorrentParams.name = QString::fromStdString(p.name);
}
@ -3009,19 +2989,20 @@ void SessionImpl::invokeAsync(std::function<void ()> func)
// Add a torrent to libtorrent session in hidden mode
// and force it to download its metadata
bool SessionImpl::downloadMetadata(const MagnetUri &magnetUri)
bool SessionImpl::downloadMetadata(const TorrentDescriptor &torrentDescr)
{
if (!magnetUri.isValid())
Q_ASSERT(!torrentDescr.info().has_value());
if (Q_UNLIKELY(torrentDescr.info().has_value()))
return false;
const InfoHash infoHash = magnetUri.infoHash();
const InfoHash infoHash = torrentDescr.infoHash();
// We should not add torrent if it's already
// processed or adding to session
if (isKnownTorrent(infoHash))
return false;
lt::add_torrent_params p = magnetUri.addTorrentParams();
lt::add_torrent_params p = torrentDescr.ltAddTorrentParams();
if (isAddTrackersEnabled())
{
@ -5281,8 +5262,7 @@ void SessionImpl::recursiveTorrentDownload(const TorrentID &id)
AddTorrentParams params;
// Passing the save path along to the sub torrent file
params.savePath = torrent->savePath();
const nonstd::expected<TorrentInfo, QString> loadResult = TorrentInfo::loadFromFile(torrentFullpath);
if (loadResult)
if (const auto loadResult = TorrentDescriptor::loadFromFile(torrentFullpath))
{
addTorrent(loadResult.value(), params);
}