From bf343292971b51758d517e1ac295654e806d598c Mon Sep 17 00:00:00 2001 From: "Vladimir Golovnev (Glassez)" Date: Thu, 26 Dec 2024 15:33:06 +0300 Subject: [PATCH] Temp --- src/base/bittorrent/sessionimpl.cpp | 132 ++++++++++++++++------------ src/base/bittorrent/sessionimpl.h | 4 +- 2 files changed, 78 insertions(+), 58 deletions(-) diff --git a/src/base/bittorrent/sessionimpl.cpp b/src/base/bittorrent/sessionimpl.cpp index 60d769d6530..7d4a2a15a11 100644 --- a/src/base/bittorrent/sessionimpl.cpp +++ b/src/base/bittorrent/sessionimpl.cpp @@ -56,6 +56,7 @@ #include #include #include +#include #include #include @@ -326,6 +327,18 @@ namespace return torrentFilePath; } + + lt::entry LTWriteTorrentFile(lt::add_torrent_params ltAddTorrentParams, lt::error_code &ec) + try + { + ec.clear(); + return lt::write_torrent_file(ltAddTorrentParams); + } + catch (const lt::system_error &err) + { + ec = err.code(); + return {}; + } } struct BitTorrent::SessionImpl::ResumeSessionContext final : public QObject @@ -829,8 +842,12 @@ bool SessionImpl::isStoreTorrentFileEnabled() const void SessionImpl::setStoreTorrentFileEnabled(const bool enabled) { - if (enabled != m_isStoreTorrentFileEnabled) - m_isStoreTorrentFileEnabled = enabled; + if (enabled == m_isStoreTorrentFileEnabled) + return; + + m_isStoreTorrentFileEnabled = enabled; + if (!m_isStoreTorrentFileEnabled) + m_needStoreFileTorrents.clear(); } bool SessionImpl::isDeleteStoredTorrentFileOnRemoveEnabled() const @@ -846,7 +863,10 @@ void SessionImpl::setDeleteStoredTorrentFileOnRemoveEnabled(const bool enabled) Path SessionImpl::torrentFileStoreDirectory() const { - return m_torrentFileStoreDirectory; + const Path torrentFileStoreDirectory = m_torrentFileStoreDirectory; + return torrentFileStoreDirectory.isEmpty() + ? specialFolderLocation(SpecialFolder::Downloads) / Path(u"Torrent Files"_s) + : torrentFileStoreDirectory; } void SessionImpl::setTorrentFileStoreDirectory(const Path &path) @@ -2507,6 +2527,22 @@ bool SessionImpl::removeTorrent(const TorrentID &id, const TorrentRemoveOption d // Remove it from torrent resume directory m_resumeDataStorage->remove(torrentID); + m_needStoreFileTorrents.remove(torrent); + if (std::holds_alternative(torrent->storedTorrentInfo())) + { + const auto storedTorrentFilePath = std::get(torrent->storedTorrentInfo()); + if (const auto result = Utils::Fs::removeFile(storedTorrentFilePath)) + { + LogMsg(tr("Removed stored .torrent file. Torrent: \"%1\". File: \"%2\".") + .arg(torrent->name(), storedTorrentFilePath.toString())); + } + else + { + LogMsg(tr("Failed to remove stored .torrent file. Torrent: \"%1\". File: \"%2\". Reason: \"%3\".") + .arg(torrent->name(), storedTorrentFilePath.toString(), result.error())); + } + } + LogMsg(tr("Torrent removed. Torrent: \"%1\"").arg(torrentName)); delete torrent; return true; @@ -3121,31 +3157,6 @@ bool SessionImpl::downloadMetadata(const TorrentDescriptor &torrentDescr) return true; } -nonstd::expected SessionImpl::createTorrentFile(const Torrent *torrent, const Path &folderPath) -{ - if (!folderPath.exists() && !Utils::Fs::mkpath(folderPath)) - return nonstd::make_unexpected(tr("Unable to create folder. Path: \"%1\".").arg(folderPath.toString())); - - const Path torrentFilePath = generateTorrentFilePath(folderPath, torrent->name()); - if (const auto result = torrent->exportToFile(torrentFilePath); !result) - return nonstd::make_unexpected(result.error()); - - return torrentFilePath; -} - -nonstd::expected SessionImpl::createTorrentFile(const TorrentDescriptor &torrentDescr, const Path &folderPath) -{ - if (!folderPath.exists() && !Utils::Fs::mkpath(folderPath)) - return nonstd::make_unexpected(tr("Unable to create folder. Path: \"%1\".").arg(folderPath.toString())); - - const Path torrentFilePath = generateTorrentFilePath(folderPath, torrentDescr.name()); - const auto saveResult = torrentDescr.saveToFile(torrentFilePath); - if (saveResult) - return torrentFilePath; - - return nonstd::make_unexpected(saveResult.error()); -} - void SessionImpl::generateResumeData() { for (TorrentImpl *const torrent : asConst(m_torrents)) @@ -5065,14 +5076,9 @@ void SessionImpl::updateSeedingLimitTimer() } } -void SessionImpl::storeTorrentFile(TorrentImpl *torrent) +void SessionImpl::storeTorrentFile(TorrentImpl *torrent, [[maybe_unused]] const lt::add_torrent_params &resumeData) { - if (!isStoreTorrentFileEnabled()) - return; - - const Path storeDir = torrentFileStoreDirectory(); - if (storeDir.isEmpty()) - return; + const QString errorMessage = tr("Failed to store .torrent file. Torrent: \"%1\". Destination: \"%2\". Reason: \"%3\"."); const std::variant storedTorrentInfo = torrent->storedTorrentInfo(); if (!std::holds_alternative(storedTorrentInfo)) @@ -5082,28 +5088,49 @@ void SessionImpl::storeTorrentFile(TorrentImpl *torrent) if (originalMagnetURI.isEmpty()) return; - const auto parseResult = TorrentDescriptor::parse(originalMagnetURI); - if (!parseResult) + const Path storeDir = torrentFileStoreDirectory(); + + lt::error_code ec; + lt::add_torrent_params ltAddTorrentParams = lt::parse_magnet_uri(originalMagnetURI.toStdString(), ec); + if (ec) + { + LogMsg(errorMessage.arg(torrent->name(), storeDir.toString(), QString::fromStdString(ec.message())), Log::WARNING); + return; + } + + ltAddTorrentParams.ti = torrent->info().nativeInfo(); +#ifdef QBT_USES_LIBTORRENT2 + ltAddTorrentParams.merkle_trees = resumeData.merkle_trees; + ltAddTorrentParams.merkle_tree_mask = resumeData.merkle_tree_mask; +#endif + + const lt::entry torrentEntry = LTWriteTorrentFile(ltAddTorrentParams, ec); + if (ec) { - LogMsg(tr("Failed to store .torrent file. Torrent: \"%1\". Destination: \"%2\". Reason: \"%3\".") - .arg(torrent->name(), storeDir.toString(), parseResult.error()), Log::WARNING); +#ifdef QBT_USES_LIBTORRENT2 + if ((ec != lt::errors::torrent_missing_piece_layer) && (ec != lt::errors::torrent_invalid_piece_layer)) +#endif + LogMsg(errorMessage.arg(torrent->name(), storeDir.toString(), QString::fromStdString(ec.message())), Log::WARNING); return; } - TorrentDescriptor torrentDescr = parseResult.value(); - torrentDescr.setTorrentInfo(torrent->info()); + if (!storeDir.exists() && !Utils::Fs::mkpath(storeDir)) + { + LogMsg(errorMessage.arg(torrent->name(), storeDir.toString(), tr("Unable to create folder")), Log::WARNING); + return; + } - if (const auto result = createTorrentFile(torrentDescr, storeDir)) + const Path torrentFilePath = generateTorrentFilePath(storeDir, torrent->name()); + if (const auto result = Utils::IO::saveToFile(torrentFilePath, torrentEntry)) { - const Path torrentFilePath = result.value(); torrent->setStoredTorrentInfo(torrentFilePath); + m_needStoreFileTorrents.remove(torrent); LogMsg(tr("Stored .torrent file. Torrent: \"%1\". Destination: \"%2\".") .arg(torrent->name(), torrentFilePath.toString())); } else { - LogMsg(tr("Failed to store .torrent file. Torrent: \"%1\". Destination: \"%2\". Reason: \"%3\".") - .arg(torrent->name(), result.value().toString(), result.error()), Log::WARNING); + LogMsg(errorMessage.arg(torrent->name(), storeDir.toString(), result.error()), Log::WARNING); } } @@ -5219,6 +5246,9 @@ void SessionImpl::handleTorrentResumeDataReady(TorrentImpl *const torrent, const m_resumeDataStorage->remove(iter.value()); m_changedTorrentIDs.erase(iter); } + + if (m_needStoreFileTorrents.contains(torrent)) + storeTorrentFile(torrent, data.ltAddTorrentParams); } void SessionImpl::handleTorrentInfoHashChanged(TorrentImpl *torrent, const InfoHash &prevInfoHash) @@ -5823,14 +5853,7 @@ void SessionImpl::dispatchTorrentAlert(const lt::torrent_alert *alert) if (torrent) { - const bool needStoreTorentFile = (alert->type() == lt::save_resume_data_alert::alert_type) - && m_needStoreFileTorrents.contains(torrent); - torrent->handleAlert(alert); - - if (needStoreTorentFile) - storeTorrentFile(torrent); - return; } @@ -5857,12 +5880,11 @@ TorrentImpl *SessionImpl::createTorrent(const lt::torrent_handle &nativeHandle, torrent->requestResumeData(lt::torrent_handle::save_info_dict); const TorrentDescriptor torrentDescr = m_addingTorrents.take(torrent->id()); - if (const Path copyDir = torrentFileStoreDirectory(); - isStoreTorrentFileEnabled() && !copyDir.isEmpty()) + if (isStoreTorrentFileEnabled()) { if (torrentDescr.hasCompleteMetadata()) { - const auto storeTorrent = [&torrentDescr, ©Dir]() -> nonstd::expected + const auto storeTorrent = [&torrentDescr, copyDir = torrentFileStoreDirectory()]() -> nonstd::expected { if (!copyDir.exists() && !Utils::Fs::mkpath(copyDir)) return nonstd::make_unexpected(tr("Unable to create folder. Path: \"%1\".").arg(copyDir.toString())); diff --git a/src/base/bittorrent/sessionimpl.h b/src/base/bittorrent/sessionimpl.h index 9464273be12..fb48fad550d 100644 --- a/src/base/bittorrent/sessionimpl.h +++ b/src/base/bittorrent/sessionimpl.h @@ -562,9 +562,7 @@ namespace BitTorrent void updateSeedingLimitTimer(); - void storeTorrentFile(TorrentImpl *torrent); - nonstd::expected createTorrentFile(const Torrent *torrent, const Path &folderPath); - nonstd::expected createTorrentFile(const TorrentDescriptor &torrentDescr, const Path &folderPath); + void storeTorrentFile(TorrentImpl *torrent, const lt::add_torrent_params &resumeData); void handleAlert(const lt::alert *alert); void dispatchTorrentAlert(const lt::torrent_alert *alert);