1
0
Fork 0
mirror of https://github.com/transmission/transmission synced 2024-12-30 19:46:56 +00:00

fix: correctly handle batch-adding trackers to multiple torrents (#5122)

This commit is contained in:
Charles Kerr 2023-03-02 00:33:49 -06:00 committed by GitHub
parent d3273504bd
commit 8fc904617b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 47 additions and 23 deletions

View file

@ -6,6 +6,8 @@
#include <algorithm> #include <algorithm>
#include <cassert> #include <cassert>
#include <ctime> #include <ctime>
#include <map>
#include <set>
#include <utility> #include <utility>
#include <QDateTime> #include <QDateTime>
@ -28,6 +30,7 @@
#include <QTreeWidgetItem> #include <QTreeWidgetItem>
#include <libtransmission/transmission.h> #include <libtransmission/transmission.h>
#include <libtransmission/announce-list.h>
#include <libtransmission/utils.h> // tr_getRatio() #include <libtransmission/utils.h> // tr_getRatio()
#include "BaseDialog.h" #include "BaseDialog.h"
@ -1340,42 +1343,56 @@ void DetailsDialog::onTrackerSelectionChanged()
void DetailsDialog::onAddTrackerClicked() void DetailsDialog::onAddTrackerClicked()
{ {
bool ok = false; bool ok = false;
auto const text_qstr = QInputDialog::getMultiLineText(
QString const text = QInputDialog::getMultiLineText(
this, this,
tr("Add URL(s)"), tr("Add URL(s)"),
tr("Add tracker announce URLs, one per line:"), tr("Add tracker announce URLs, one per line:"),
{}, {},
&ok); &ok);
if (!ok)
if (ok)
{ {
QSet<QString> urls; return;
torrent_ids_t ids; }
for (auto const& line : text.split(QRegularExpression(QStringLiteral("[\r\n]+")))) // for each URL entered by the user...
auto announce_list = tr_announce_list{};
announce_list.parse(text_qstr.toStdString());
auto url_to_ids = std::map<QString, std::set<tr_torrent_id_t>>{};
for (auto const& info : announce_list)
{
// for each selected torrent...
auto sv = info.announce.sv();
auto const announce_url = QString::fromUtf8(std::data(sv), std::size(sv));
for (auto const& id : ids_)
{ {
QString const url = line.trimmed(); // make a note if the torrent doesn't already have the URL
if (!line.isEmpty() && QUrl(url).isValid()) if (tracker_model_->find(id, announce_url) == -1)
{ {
for (auto const& id : ids_) url_to_ids[announce_url].insert(id);
{
if (tracker_model_->find(id, url) == -1 && !urls.contains(url))
{
ids.insert(id);
urls.insert(url);
}
}
} }
} }
}
if (urls.isEmpty()) // now reverse the map so that if we're adding identical trackers
// to more than one torrent, that can be batched into a single call
auto ids_to_urls = std::map<std::set<tr_torrent_id_t>, std::set<QString>>{};
for (auto& [announce_url, ids] : url_to_ids)
{
ids_to_urls[ids].insert(announce_url);
}
if (std::empty(ids_to_urls))
{
QMessageBox::warning(this, tr("Error"), tr("No new URLs found."));
}
else
{
for (auto const& [ids, urls] : ids_to_urls)
{ {
QMessageBox::warning(this, tr("Error"), tr("No new URLs found.")); torrentSet(
} torrent_ids_t{ std::begin(ids), std::end(ids) },
else TR_KEY_trackerAdd,
{ QList<QString>{ std::begin(urls), std::end(urls) });
torrentSet(ids, TR_KEY_trackerAdd, urls.values());
} }
} }
} }

View file

@ -5,6 +5,8 @@
#include <string_view> #include <string_view>
#include <fmt/format.h>
#include "RpcClient.h" #include "RpcClient.h"
#include <QApplication> #include <QApplication>
@ -160,6 +162,11 @@ void RpcClient::sendNetworkRequest(TrVariantPtr json, QFutureInterface<RpcRespon
void RpcClient::sendLocalRequest(TrVariantPtr json, QFutureInterface<RpcResponse> const& promise, int64_t tag) void RpcClient::sendLocalRequest(TrVariantPtr json, QFutureInterface<RpcResponse> const& promise, int64_t tag)
{ {
if (verbose_)
{
fmt::print("{:s}:{:d} sending req:\n{:s}\n", __FILE__, __LINE__, tr_variantToStr(json.get(), TR_VARIANT_FMT_JSON));
}
local_requests_.insert(tag, promise); local_requests_.insert(tag, promise);
tr_rpc_request_exec_json(session_, json.get(), localSessionCallback, this); tr_rpc_request_exec_json(session_, json.get(), localSessionCallback, this);
} }