|
|
|
@@ -298,125 +298,220 @@ char const* torrentVerify(tr_session* session, tr_variant* args_in, tr_variant*
|
|
|
|
|
|
|
|
|
|
|
|
// ---
|
|
|
|
// ---
|
|
|
|
|
|
|
|
|
|
|
|
void addLabels(tr_torrent const* tor, tr_variant* list)
|
|
|
|
namespace make_torrent_field_helpers
|
|
|
|
{
|
|
|
|
{
|
|
|
|
tr_variantInitList(list, std::size(tor->labels));
|
|
|
|
[[nodiscard]] auto make_file_wanted_vec(tr_torrent const& tor)
|
|
|
|
for (auto const& label : tor->labels)
|
|
|
|
{
|
|
|
|
|
|
|
|
auto const n_files = tor.file_count();
|
|
|
|
|
|
|
|
auto vec = tr_variant::Vector{};
|
|
|
|
|
|
|
|
vec.reserve(n_files);
|
|
|
|
|
|
|
|
for (tr_file_index_t idx = 0U; idx != n_files; ++idx)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
tr_variantListAddQuark(list, label);
|
|
|
|
vec.emplace_back(tr_torrentFile(&tor, idx).wanted ? 1 : 0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return tr_variant{ std::move(vec) };
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void addFileStats(tr_torrent const* tor, tr_variant* list)
|
|
|
|
[[nodiscard]] auto make_labels_vec(tr_torrent const& tor)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
for (tr_file_index_t i = 0, n = tor->file_count(); i < n; ++i)
|
|
|
|
auto const n_labels = std::size(tor.labels);
|
|
|
|
|
|
|
|
auto labels = tr_variant::Vector{};
|
|
|
|
|
|
|
|
labels.reserve(n_labels);
|
|
|
|
|
|
|
|
for (auto const& label : tor.labels)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
auto const file = tr_torrentFile(tor, i);
|
|
|
|
labels.emplace_back(tr_variant::unmanaged_string(tr_quark_get_string_view(label)));
|
|
|
|
tr_variant* d = tr_variantListAddDict(list, 3);
|
|
|
|
|
|
|
|
tr_variantDictAddInt(d, TR_KEY_bytesCompleted, file.have);
|
|
|
|
|
|
|
|
tr_variantDictAddInt(d, TR_KEY_priority, file.priority);
|
|
|
|
|
|
|
|
tr_variantDictAddBool(d, TR_KEY_wanted, file.wanted);
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return tr_variant{ std::move(labels) };
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void addFiles(tr_torrent const* tor, tr_variant* list)
|
|
|
|
[[nodiscard]] auto make_file_priorities_vec(tr_torrent const& tor)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
for (tr_file_index_t i = 0, n = tor->file_count(); i < n; ++i)
|
|
|
|
auto const n_files = tor.file_count();
|
|
|
|
|
|
|
|
auto vec = tr_variant::Vector{};
|
|
|
|
|
|
|
|
vec.reserve(n_files);
|
|
|
|
|
|
|
|
for (tr_file_index_t idx = 0U; idx != n_files; ++idx)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
auto const file = tr_torrentFile(tor, i);
|
|
|
|
vec.emplace_back(tr_torrentFile(&tor, idx).priority);
|
|
|
|
tr_variant* d = tr_variantListAddDict(list, 5);
|
|
|
|
|
|
|
|
tr_variantDictAddInt(d, TR_KEY_beginPiece, file.beginPiece);
|
|
|
|
|
|
|
|
tr_variantDictAddInt(d, TR_KEY_bytesCompleted, file.have);
|
|
|
|
|
|
|
|
tr_variantDictAddInt(d, TR_KEY_endPiece, file.endPiece);
|
|
|
|
|
|
|
|
tr_variantDictAddInt(d, TR_KEY_length, file.length);
|
|
|
|
|
|
|
|
tr_variantDictAddStr(d, TR_KEY_name, file.name);
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return tr_variant{ std::move(vec) };
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void addWebseeds(tr_torrent const* tor, tr_variant* webseeds)
|
|
|
|
[[nodiscard]] auto make_file_stats_vec(tr_torrent const& tor)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
for (size_t i = 0, n = tor->webseed_count(); i < n; ++i)
|
|
|
|
auto const n_files = tor.file_count();
|
|
|
|
|
|
|
|
auto vec = tr_variant::Vector{};
|
|
|
|
|
|
|
|
vec.reserve(n_files);
|
|
|
|
|
|
|
|
for (tr_file_index_t idx = 0U; idx != n_files; ++idx)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
tr_variantListAddStr(webseeds, tor->webseed(i));
|
|
|
|
auto const file = tr_torrentFile(&tor, idx);
|
|
|
|
|
|
|
|
auto stats_map = tr_variant::Map{ 3U };
|
|
|
|
|
|
|
|
stats_map.try_emplace(TR_KEY_bytesCompleted, file.have);
|
|
|
|
|
|
|
|
stats_map.try_emplace(TR_KEY_priority, file.priority);
|
|
|
|
|
|
|
|
stats_map.try_emplace(TR_KEY_wanted, file.wanted);
|
|
|
|
|
|
|
|
vec.emplace_back(std::move(stats_map));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return tr_variant{ std::move(vec) };
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void addTrackers(tr_torrent const* tor, tr_variant* trackers)
|
|
|
|
[[nodiscard]] auto make_file_vec(tr_torrent const& tor)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
for (auto const& tracker : tor->announce_list())
|
|
|
|
auto const n_files = tor.file_count();
|
|
|
|
|
|
|
|
auto vec = tr_variant::Vector{};
|
|
|
|
|
|
|
|
vec.reserve(n_files);
|
|
|
|
|
|
|
|
for (tr_file_index_t idx = 0U; idx != n_files; ++idx)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
auto* const d = tr_variantListAddDict(trackers, 5);
|
|
|
|
auto const file = tr_torrentFile(&tor, idx);
|
|
|
|
tr_variantDictAddQuark(d, TR_KEY_announce, tracker.announce.quark());
|
|
|
|
auto file_map = tr_variant::Map{ 5U };
|
|
|
|
tr_variantDictAddInt(d, TR_KEY_id, tracker.id);
|
|
|
|
file_map.try_emplace(TR_KEY_beginPiece, file.beginPiece);
|
|
|
|
tr_variantDictAddQuark(d, TR_KEY_scrape, tracker.scrape.quark());
|
|
|
|
file_map.try_emplace(TR_KEY_bytesCompleted, file.have);
|
|
|
|
tr_variantDictAddStrView(d, TR_KEY_sitename, tracker.sitename);
|
|
|
|
file_map.try_emplace(TR_KEY_endPiece, file.endPiece);
|
|
|
|
tr_variantDictAddInt(d, TR_KEY_tier, tracker.tier);
|
|
|
|
file_map.try_emplace(TR_KEY_length, file.length);
|
|
|
|
|
|
|
|
file_map.try_emplace(TR_KEY_name, file.name);
|
|
|
|
|
|
|
|
vec.emplace_back(std::move(file_map));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return tr_variant{ std::move(vec) };
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void addTrackerStats(tr_tracker_view const& tracker, tr_variant* list)
|
|
|
|
[[nodiscard]] auto make_webseed_vec(tr_torrent const& tor)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
auto* const d = tr_variantListAddDict(list, 27);
|
|
|
|
auto const n_webseeds = tor.webseed_count();
|
|
|
|
tr_variantDictAddStr(d, TR_KEY_announce, tracker.announce);
|
|
|
|
auto vec = tr_variant::Vector{};
|
|
|
|
tr_variantDictAddInt(d, TR_KEY_announceState, tracker.announceState);
|
|
|
|
for (size_t idx = 0U; idx != n_webseeds; ++idx)
|
|
|
|
tr_variantDictAddInt(d, TR_KEY_downloadCount, tracker.downloadCount);
|
|
|
|
|
|
|
|
tr_variantDictAddBool(d, TR_KEY_hasAnnounced, tracker.hasAnnounced);
|
|
|
|
|
|
|
|
tr_variantDictAddBool(d, TR_KEY_hasScraped, tracker.hasScraped);
|
|
|
|
|
|
|
|
tr_variantDictAddStr(d, TR_KEY_host, tracker.host_and_port);
|
|
|
|
|
|
|
|
tr_variantDictAddStr(d, TR_KEY_sitename, tracker.sitename);
|
|
|
|
|
|
|
|
tr_variantDictAddInt(d, TR_KEY_id, tracker.id);
|
|
|
|
|
|
|
|
tr_variantDictAddBool(d, TR_KEY_isBackup, tracker.isBackup);
|
|
|
|
|
|
|
|
tr_variantDictAddInt(d, TR_KEY_lastAnnouncePeerCount, tracker.lastAnnouncePeerCount);
|
|
|
|
|
|
|
|
tr_variantDictAddStr(d, TR_KEY_lastAnnounceResult, tracker.lastAnnounceResult);
|
|
|
|
|
|
|
|
tr_variantDictAddInt(d, TR_KEY_lastAnnounceStartTime, tracker.lastAnnounceStartTime);
|
|
|
|
|
|
|
|
tr_variantDictAddBool(d, TR_KEY_lastAnnounceSucceeded, tracker.lastAnnounceSucceeded);
|
|
|
|
|
|
|
|
tr_variantDictAddInt(d, TR_KEY_lastAnnounceTime, tracker.lastAnnounceTime);
|
|
|
|
|
|
|
|
tr_variantDictAddBool(d, TR_KEY_lastAnnounceTimedOut, tracker.lastAnnounceTimedOut);
|
|
|
|
|
|
|
|
tr_variantDictAddStr(d, TR_KEY_lastScrapeResult, tracker.lastScrapeResult);
|
|
|
|
|
|
|
|
tr_variantDictAddInt(d, TR_KEY_lastScrapeStartTime, tracker.lastScrapeStartTime);
|
|
|
|
|
|
|
|
tr_variantDictAddBool(d, TR_KEY_lastScrapeSucceeded, tracker.lastScrapeSucceeded);
|
|
|
|
|
|
|
|
tr_variantDictAddInt(d, TR_KEY_lastScrapeTime, tracker.lastScrapeTime);
|
|
|
|
|
|
|
|
tr_variantDictAddBool(d, TR_KEY_lastScrapeTimedOut, tracker.lastScrapeTimedOut);
|
|
|
|
|
|
|
|
tr_variantDictAddInt(d, TR_KEY_leecherCount, tracker.leecherCount);
|
|
|
|
|
|
|
|
tr_variantDictAddInt(d, TR_KEY_nextAnnounceTime, tracker.nextAnnounceTime);
|
|
|
|
|
|
|
|
tr_variantDictAddInt(d, TR_KEY_nextScrapeTime, tracker.nextScrapeTime);
|
|
|
|
|
|
|
|
tr_variantDictAddStr(d, TR_KEY_scrape, tracker.scrape);
|
|
|
|
|
|
|
|
tr_variantDictAddInt(d, TR_KEY_scrapeState, tracker.scrapeState);
|
|
|
|
|
|
|
|
tr_variantDictAddInt(d, TR_KEY_seederCount, tracker.seederCount);
|
|
|
|
|
|
|
|
tr_variantDictAddInt(d, TR_KEY_tier, tracker.tier);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void addPeers(tr_torrent const* tor, tr_variant* list)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
auto peer_count = size_t{};
|
|
|
|
|
|
|
|
tr_peer_stat* peers = tr_torrentPeers(tor, &peer_count);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
tr_variantInitList(list, peer_count);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for (size_t i = 0; i < peer_count; ++i)
|
|
|
|
|
|
|
|
{
|
|
|
|
{
|
|
|
|
tr_variant* d = tr_variantListAddDict(list, 16);
|
|
|
|
vec.emplace_back(tor.webseed(idx));
|
|
|
|
tr_peer_stat const* peer = peers + i;
|
|
|
|
}
|
|
|
|
tr_variantDictAddStr(d, TR_KEY_address, peer->addr);
|
|
|
|
return tr_variant{ std::move(vec) };
|
|
|
|
tr_variantDictAddStr(d, TR_KEY_clientName, peer->client);
|
|
|
|
}
|
|
|
|
tr_variantDictAddBool(d, TR_KEY_clientIsChoked, peer->clientIsChoked);
|
|
|
|
|
|
|
|
tr_variantDictAddBool(d, TR_KEY_clientIsInterested, peer->clientIsInterested);
|
|
|
|
[[nodiscard]] auto make_tracker_vec(tr_torrent const& tor)
|
|
|
|
tr_variantDictAddStr(d, TR_KEY_flagStr, peer->flagStr);
|
|
|
|
{
|
|
|
|
tr_variantDictAddBool(d, TR_KEY_isDownloadingFrom, peer->isDownloadingFrom);
|
|
|
|
auto const& trackers = tor.announce_list();
|
|
|
|
tr_variantDictAddBool(d, TR_KEY_isEncrypted, peer->isEncrypted);
|
|
|
|
auto const n_trackers = std::size(trackers);
|
|
|
|
tr_variantDictAddBool(d, TR_KEY_isIncoming, peer->isIncoming);
|
|
|
|
auto vec = tr_variant::Vector{};
|
|
|
|
tr_variantDictAddBool(d, TR_KEY_isUploadingTo, peer->isUploadingTo);
|
|
|
|
vec.reserve(n_trackers);
|
|
|
|
tr_variantDictAddBool(d, TR_KEY_isUTP, peer->isUTP);
|
|
|
|
for (auto const& tracker : trackers)
|
|
|
|
tr_variantDictAddBool(d, TR_KEY_peerIsChoked, peer->peerIsChoked);
|
|
|
|
{
|
|
|
|
tr_variantDictAddBool(d, TR_KEY_peerIsInterested, peer->peerIsInterested);
|
|
|
|
auto tracker_map = tr_variant::Map{ 5U };
|
|
|
|
tr_variantDictAddInt(d, TR_KEY_port, peer->port);
|
|
|
|
tracker_map.try_emplace(TR_KEY_announce, tracker.announce.sv());
|
|
|
|
tr_variantDictAddReal(d, TR_KEY_progress, peer->progress);
|
|
|
|
tracker_map.try_emplace(TR_KEY_id, tracker.id);
|
|
|
|
tr_variantDictAddInt(d, TR_KEY_rateToClient, tr_toSpeedBytes(peer->rateToClient_KBps));
|
|
|
|
tracker_map.try_emplace(TR_KEY_scrape, tracker.scrape.sv());
|
|
|
|
tr_variantDictAddInt(d, TR_KEY_rateToPeer, tr_toSpeedBytes(peer->rateToPeer_KBps));
|
|
|
|
tracker_map.try_emplace(TR_KEY_sitename, tracker.sitename.sv());
|
|
|
|
|
|
|
|
tracker_map.try_emplace(TR_KEY_tier, tracker.tier);
|
|
|
|
|
|
|
|
vec.emplace_back(std::move(tracker_map));
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return tr_variant{ std::move(vec) };
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
[[nodiscard]] auto make_tracker_stats_vec(tr_torrent const& tor)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
auto const n_trackers = tr_torrentTrackerCount(&tor);
|
|
|
|
|
|
|
|
auto vec = tr_variant::Vector{};
|
|
|
|
|
|
|
|
vec.reserve(n_trackers);
|
|
|
|
|
|
|
|
for (size_t idx = 0U; idx != n_trackers; ++idx)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
auto const tracker = tr_torrentTracker(&tor, idx);
|
|
|
|
|
|
|
|
auto stats_map = tr_variant::Map{ 27U };
|
|
|
|
|
|
|
|
stats_map.try_emplace(TR_KEY_announce, tracker.announce);
|
|
|
|
|
|
|
|
stats_map.try_emplace(TR_KEY_announceState, tracker.announceState);
|
|
|
|
|
|
|
|
stats_map.try_emplace(TR_KEY_downloadCount, tracker.downloadCount);
|
|
|
|
|
|
|
|
stats_map.try_emplace(TR_KEY_hasAnnounced, tracker.hasAnnounced);
|
|
|
|
|
|
|
|
stats_map.try_emplace(TR_KEY_hasScraped, tracker.hasScraped);
|
|
|
|
|
|
|
|
stats_map.try_emplace(TR_KEY_host, tracker.host_and_port);
|
|
|
|
|
|
|
|
stats_map.try_emplace(TR_KEY_id, tracker.id);
|
|
|
|
|
|
|
|
stats_map.try_emplace(TR_KEY_isBackup, tracker.isBackup);
|
|
|
|
|
|
|
|
stats_map.try_emplace(TR_KEY_lastAnnouncePeerCount, tracker.lastAnnouncePeerCount);
|
|
|
|
|
|
|
|
stats_map.try_emplace(TR_KEY_lastAnnounceResult, tracker.lastAnnounceResult);
|
|
|
|
|
|
|
|
stats_map.try_emplace(TR_KEY_lastAnnounceStartTime, tracker.lastAnnounceStartTime);
|
|
|
|
|
|
|
|
stats_map.try_emplace(TR_KEY_lastAnnounceSucceeded, tracker.lastAnnounceSucceeded);
|
|
|
|
|
|
|
|
stats_map.try_emplace(TR_KEY_lastAnnounceTime, tracker.lastAnnounceTime);
|
|
|
|
|
|
|
|
stats_map.try_emplace(TR_KEY_lastAnnounceTimedOut, tracker.lastAnnounceTimedOut);
|
|
|
|
|
|
|
|
stats_map.try_emplace(TR_KEY_lastScrapeResult, tracker.lastScrapeResult);
|
|
|
|
|
|
|
|
stats_map.try_emplace(TR_KEY_lastScrapeStartTime, tracker.lastScrapeStartTime);
|
|
|
|
|
|
|
|
stats_map.try_emplace(TR_KEY_lastScrapeSucceeded, tracker.lastScrapeSucceeded);
|
|
|
|
|
|
|
|
stats_map.try_emplace(TR_KEY_lastScrapeTime, tracker.lastScrapeTime);
|
|
|
|
|
|
|
|
stats_map.try_emplace(TR_KEY_lastScrapeTimedOut, tracker.lastScrapeTimedOut);
|
|
|
|
|
|
|
|
stats_map.try_emplace(TR_KEY_leecherCount, tracker.leecherCount);
|
|
|
|
|
|
|
|
stats_map.try_emplace(TR_KEY_nextAnnounceTime, tracker.nextAnnounceTime);
|
|
|
|
|
|
|
|
stats_map.try_emplace(TR_KEY_nextScrapeTime, tracker.nextScrapeTime);
|
|
|
|
|
|
|
|
stats_map.try_emplace(TR_KEY_scrape, tracker.scrape);
|
|
|
|
|
|
|
|
stats_map.try_emplace(TR_KEY_scrapeState, tracker.scrapeState);
|
|
|
|
|
|
|
|
stats_map.try_emplace(TR_KEY_seederCount, tracker.seederCount);
|
|
|
|
|
|
|
|
stats_map.try_emplace(TR_KEY_sitename, tracker.sitename);
|
|
|
|
|
|
|
|
stats_map.try_emplace(TR_KEY_tier, tracker.tier);
|
|
|
|
|
|
|
|
vec.emplace_back(std::move(stats_map));
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return tr_variant{ std::move(vec) };
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
[[nodiscard]] auto make_peer_vec(tr_torrent const& tor)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
auto n_peers = size_t{};
|
|
|
|
|
|
|
|
auto* const peers = tr_torrentPeers(&tor, &n_peers);
|
|
|
|
|
|
|
|
auto peers_vec = tr_variant::Vector{};
|
|
|
|
|
|
|
|
peers_vec.reserve(n_peers);
|
|
|
|
|
|
|
|
for (size_t idx = 0U; idx != n_peers; ++idx)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
auto const& peer = peers[idx];
|
|
|
|
|
|
|
|
auto peer_map = tr_variant::Map{ 16U };
|
|
|
|
|
|
|
|
peer_map.try_emplace(TR_KEY_address, peer.addr);
|
|
|
|
|
|
|
|
peer_map.try_emplace(TR_KEY_clientIsChoked, peer.clientIsChoked);
|
|
|
|
|
|
|
|
peer_map.try_emplace(TR_KEY_clientIsInterested, peer.clientIsInterested);
|
|
|
|
|
|
|
|
peer_map.try_emplace(TR_KEY_clientName, peer.client);
|
|
|
|
|
|
|
|
peer_map.try_emplace(TR_KEY_flagStr, peer.flagStr);
|
|
|
|
|
|
|
|
peer_map.try_emplace(TR_KEY_isDownloadingFrom, peer.isDownloadingFrom);
|
|
|
|
|
|
|
|
peer_map.try_emplace(TR_KEY_isEncrypted, peer.isEncrypted);
|
|
|
|
|
|
|
|
peer_map.try_emplace(TR_KEY_isIncoming, peer.isIncoming);
|
|
|
|
|
|
|
|
peer_map.try_emplace(TR_KEY_isUTP, peer.isUTP);
|
|
|
|
|
|
|
|
peer_map.try_emplace(TR_KEY_isUploadingTo, peer.isUploadingTo);
|
|
|
|
|
|
|
|
peer_map.try_emplace(TR_KEY_peerIsChoked, peer.peerIsChoked);
|
|
|
|
|
|
|
|
peer_map.try_emplace(TR_KEY_peerIsInterested, peer.peerIsInterested);
|
|
|
|
|
|
|
|
peer_map.try_emplace(TR_KEY_port, peer.port);
|
|
|
|
|
|
|
|
peer_map.try_emplace(TR_KEY_progress, peer.progress);
|
|
|
|
|
|
|
|
peer_map.try_emplace(TR_KEY_rateToClient, tr_toSpeedBytes(peer.rateToClient_KBps));
|
|
|
|
|
|
|
|
peer_map.try_emplace(TR_KEY_rateToPeer, tr_toSpeedBytes(peer.rateToPeer_KBps));
|
|
|
|
|
|
|
|
peers_vec.emplace_back(std::move(peer_map));
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
tr_torrentPeersFree(peers, n_peers);
|
|
|
|
|
|
|
|
return tr_variant{ std::move(peers_vec) };
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
[[nodiscard]] auto make_peer_counts_map(tr_stat const& st)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
auto const& from = st.peersFrom;
|
|
|
|
|
|
|
|
auto from_map = tr_variant::Map{ 7U };
|
|
|
|
|
|
|
|
from_map.try_emplace(TR_KEY_fromCache, from[TR_PEER_FROM_RESUME]);
|
|
|
|
|
|
|
|
from_map.try_emplace(TR_KEY_fromDht, from[TR_PEER_FROM_DHT]);
|
|
|
|
|
|
|
|
from_map.try_emplace(TR_KEY_fromIncoming, from[TR_PEER_FROM_INCOMING]);
|
|
|
|
|
|
|
|
from_map.try_emplace(TR_KEY_fromLpd, from[TR_PEER_FROM_LPD]);
|
|
|
|
|
|
|
|
from_map.try_emplace(TR_KEY_fromLtep, from[TR_PEER_FROM_LTEP]);
|
|
|
|
|
|
|
|
from_map.try_emplace(TR_KEY_fromPex, from[TR_PEER_FROM_PEX]);
|
|
|
|
|
|
|
|
from_map.try_emplace(TR_KEY_fromTracker, from[TR_PEER_FROM_TRACKER]);
|
|
|
|
|
|
|
|
return tr_variant{ std::move(from_map) };
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
[[nodiscard]] auto make_piece_availability_vec(tr_torrent const& tor)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
auto const n_pieces = tor.piece_count();
|
|
|
|
|
|
|
|
auto vec = tr_variant::Vector{};
|
|
|
|
|
|
|
|
vec.reserve(n_pieces);
|
|
|
|
|
|
|
|
for (tr_piece_index_t idx = 0U; idx != n_pieces; ++idx)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
vec.emplace_back(tr_peerMgrPieceAvailability(&tor, idx));
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return tr_variant{ std::move(vec) };
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
[[nodiscard]] auto make_piece_bitfield(tr_torrent const& tor)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
if (tor.has_metainfo())
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
auto const bytes = tor.create_piece_bitfield();
|
|
|
|
|
|
|
|
return tr_variant{ tr_base64_encode({ reinterpret_cast<char const*>(std::data(bytes)), std::size(bytes) }) };
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
tr_torrentPeersFree(peers, peer_count);
|
|
|
|
return tr_variant::unmanaged_string(""sv);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
} // namespace make_torrent_field_helpers
|
|
|
|
|
|
|
|
|
|
|
|
[[nodiscard]] auto constexpr isSupportedTorrentGetField(tr_quark key)
|
|
|
|
[[nodiscard]] auto constexpr isSupportedTorrentGetField(tr_quark key)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
@@ -506,374 +601,96 @@ void addPeers(tr_torrent const* tor, tr_variant* list)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void initField(tr_torrent const* const tor, tr_stat const* const st, tr_variant* const initme, tr_quark key)
|
|
|
|
[[nodiscard]] tr_variant make_torrent_field(tr_torrent const& tor, tr_stat const& st, tr_quark key)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
|
|
|
|
using namespace make_torrent_field_helpers;
|
|
|
|
|
|
|
|
|
|
|
|
TR_ASSERT(isSupportedTorrentGetField(key));
|
|
|
|
TR_ASSERT(isSupportedTorrentGetField(key));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// clang-format off
|
|
|
|
switch (key)
|
|
|
|
switch (key)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
case TR_KEY_activityDate:
|
|
|
|
case TR_KEY_activityDate: return st.activityDate;
|
|
|
|
tr_variantInitInt(initme, st->activityDate);
|
|
|
|
case TR_KEY_addedDate: return st.addedDate;
|
|
|
|
break;
|
|
|
|
case TR_KEY_availability: return make_piece_availability_vec(tor);
|
|
|
|
|
|
|
|
case TR_KEY_bandwidthPriority: return tor.get_priority();
|
|
|
|
case TR_KEY_addedDate:
|
|
|
|
case TR_KEY_comment: return tor.comment();
|
|
|
|
tr_variantInitInt(initme, st->addedDate);
|
|
|
|
case TR_KEY_corruptEver: return st.corruptEver;
|
|
|
|
break;
|
|
|
|
case TR_KEY_creator: return tor.creator();
|
|
|
|
|
|
|
|
case TR_KEY_dateCreated: return tor.date_created();
|
|
|
|
case TR_KEY_availability:
|
|
|
|
case TR_KEY_desiredAvailable: return st.desiredAvailable;
|
|
|
|
tr_variantInitList(initme, tor->piece_count());
|
|
|
|
case TR_KEY_doneDate: return st.doneDate;
|
|
|
|
for (tr_piece_index_t piece = 0, n = tor->piece_count(); piece < n; ++piece)
|
|
|
|
case TR_KEY_downloadDir: return tor.download_dir().sv();
|
|
|
|
{
|
|
|
|
case TR_KEY_downloadLimit: return tr_torrentGetSpeedLimit_KBps(&tor, TR_DOWN);
|
|
|
|
tr_variantListAddInt(initme, tr_peerMgrPieceAvailability(tor, piece));
|
|
|
|
case TR_KEY_downloadLimited: return tor.uses_speed_limit(TR_DOWN);
|
|
|
|
}
|
|
|
|
case TR_KEY_downloadedEver: return st.downloadedEver;
|
|
|
|
break;
|
|
|
|
case TR_KEY_editDate: return st.editDate;
|
|
|
|
|
|
|
|
case TR_KEY_error: return st.error;
|
|
|
|
case TR_KEY_bandwidthPriority:
|
|
|
|
case TR_KEY_errorString: return st.errorString;
|
|
|
|
tr_variantInitInt(initme, tor->get_priority());
|
|
|
|
case TR_KEY_eta: return st.eta;
|
|
|
|
break;
|
|
|
|
case TR_KEY_etaIdle: return st.etaIdle;
|
|
|
|
|
|
|
|
case TR_KEY_fileStats: return make_file_stats_vec(tor);
|
|
|
|
case TR_KEY_comment:
|
|
|
|
case TR_KEY_file_count: return tor.file_count();
|
|
|
|
tr_variantInitStr(initme, tor->comment());
|
|
|
|
case TR_KEY_files: return make_file_vec(tor);
|
|
|
|
break;
|
|
|
|
case TR_KEY_group: return tor.bandwidth_group().sv();
|
|
|
|
|
|
|
|
case TR_KEY_hashString: return tor.info_hash_string().sv();
|
|
|
|
case TR_KEY_corruptEver:
|
|
|
|
case TR_KEY_haveUnchecked: return st.haveUnchecked;
|
|
|
|
tr_variantInitInt(initme, st->corruptEver);
|
|
|
|
case TR_KEY_haveValid: return st.haveValid;
|
|
|
|
break;
|
|
|
|
case TR_KEY_honorsSessionLimits: return tor.uses_session_limits();
|
|
|
|
|
|
|
|
case TR_KEY_id: return st.id;
|
|
|
|
case TR_KEY_creator:
|
|
|
|
case TR_KEY_isFinished: return st.finished;
|
|
|
|
tr_variantInitStrView(initme, tor->creator());
|
|
|
|
case TR_KEY_isPrivate: return tor.is_private();
|
|
|
|
break;
|
|
|
|
case TR_KEY_isStalled: return st.isStalled;
|
|
|
|
|
|
|
|
case TR_KEY_labels: return make_labels_vec(tor);
|
|
|
|
case TR_KEY_dateCreated:
|
|
|
|
case TR_KEY_leftUntilDone: return st.leftUntilDone;
|
|
|
|
tr_variantInitInt(initme, tor->date_created());
|
|
|
|
case TR_KEY_magnetLink: return tor.metainfo_.magnet();
|
|
|
|
break;
|
|
|
|
case TR_KEY_manualAnnounceTime: return tr_announcerNextManualAnnounce(&tor);
|
|
|
|
|
|
|
|
case TR_KEY_maxConnectedPeers: return tor.peer_limit();
|
|
|
|
case TR_KEY_desiredAvailable:
|
|
|
|
case TR_KEY_metadataPercentComplete: return st.metadataPercentComplete;
|
|
|
|
tr_variantInitInt(initme, st->desiredAvailable);
|
|
|
|
case TR_KEY_name: return tor.name();
|
|
|
|
break;
|
|
|
|
case TR_KEY_peer_limit: return tor.peer_limit();
|
|
|
|
|
|
|
|
case TR_KEY_peers: return make_peer_vec(tor);
|
|
|
|
case TR_KEY_doneDate:
|
|
|
|
case TR_KEY_peersConnected: return st.peersConnected;
|
|
|
|
tr_variantInitInt(initme, st->doneDate);
|
|
|
|
case TR_KEY_peersFrom: return make_peer_counts_map(st);
|
|
|
|
break;
|
|
|
|
case TR_KEY_peersGettingFromUs: return st.peersGettingFromUs;
|
|
|
|
|
|
|
|
case TR_KEY_peersSendingToUs: return st.peersSendingToUs;
|
|
|
|
case TR_KEY_downloadDir:
|
|
|
|
case TR_KEY_percentComplete: return st.percentComplete;
|
|
|
|
tr_variantInitStrView(initme, tr_torrentGetDownloadDir(tor));
|
|
|
|
case TR_KEY_percentDone: return st.percentDone;
|
|
|
|
break;
|
|
|
|
case TR_KEY_pieceCount: return tor.piece_count();
|
|
|
|
|
|
|
|
case TR_KEY_pieceSize: return tor.piece_size();
|
|
|
|
case TR_KEY_downloadedEver:
|
|
|
|
case TR_KEY_pieces: return make_piece_bitfield(tor);
|
|
|
|
tr_variantInitInt(initme, st->downloadedEver);
|
|
|
|
case TR_KEY_primary_mime_type: return tor.primary_mime_type();
|
|
|
|
break;
|
|
|
|
case TR_KEY_priorities: return make_file_priorities_vec(tor);
|
|
|
|
|
|
|
|
case TR_KEY_queuePosition: return st.queuePosition;
|
|
|
|
case TR_KEY_downloadLimit:
|
|
|
|
case TR_KEY_rateDownload: return tr_toSpeedBytes(st.pieceDownloadSpeed_KBps);
|
|
|
|
tr_variantInitInt(initme, tr_torrentGetSpeedLimit_KBps(tor, TR_DOWN));
|
|
|
|
case TR_KEY_rateUpload: return tr_toSpeedBytes(st.pieceUploadSpeed_KBps);
|
|
|
|
break;
|
|
|
|
case TR_KEY_recheckProgress: return st.recheckProgress;
|
|
|
|
|
|
|
|
case TR_KEY_secondsDownloading: return st.secondsDownloading;
|
|
|
|
case TR_KEY_downloadLimited:
|
|
|
|
case TR_KEY_secondsSeeding: return st.secondsSeeding;
|
|
|
|
tr_variantInitBool(initme, tor->uses_speed_limit(TR_DOWN));
|
|
|
|
case TR_KEY_seedIdleLimit: return tor.idle_limit_minutes();
|
|
|
|
break;
|
|
|
|
case TR_KEY_seedIdleMode: return tor.idle_limit_mode();
|
|
|
|
|
|
|
|
case TR_KEY_seedRatioLimit: return tr_torrentGetRatioLimit(&tor);
|
|
|
|
case TR_KEY_error:
|
|
|
|
case TR_KEY_seedRatioMode: return tr_torrentGetRatioMode(&tor);
|
|
|
|
tr_variantInitInt(initme, st->error);
|
|
|
|
case TR_KEY_sequentialDownload: return tor.is_sequential_download();
|
|
|
|
break;
|
|
|
|
case TR_KEY_sizeWhenDone: return st.sizeWhenDone;
|
|
|
|
|
|
|
|
case TR_KEY_source: return tor.source();
|
|
|
|
case TR_KEY_errorString:
|
|
|
|
case TR_KEY_startDate: return st.startDate;
|
|
|
|
tr_variantInitStrView(initme, st->errorString);
|
|
|
|
case TR_KEY_status: return st.activity;
|
|
|
|
break;
|
|
|
|
case TR_KEY_torrentFile: return tor.torrent_file();
|
|
|
|
|
|
|
|
case TR_KEY_totalSize: return tor.total_size();
|
|
|
|
case TR_KEY_eta:
|
|
|
|
case TR_KEY_trackerList: return tor.tracker_list();
|
|
|
|
tr_variantInitInt(initme, st->eta);
|
|
|
|
case TR_KEY_trackerStats: return make_tracker_stats_vec(tor);
|
|
|
|
break;
|
|
|
|
case TR_KEY_trackers: return make_tracker_vec(tor);
|
|
|
|
|
|
|
|
case TR_KEY_uploadLimit: return tr_torrentGetSpeedLimit_KBps(&tor, TR_UP);
|
|
|
|
case TR_KEY_file_count:
|
|
|
|
case TR_KEY_uploadLimited: return tor.uses_speed_limit(TR_UP);
|
|
|
|
tr_variantInitInt(initme, tor->file_count());
|
|
|
|
case TR_KEY_uploadRatio: return st.ratio;
|
|
|
|
break;
|
|
|
|
case TR_KEY_uploadedEver: return st.uploadedEver;
|
|
|
|
|
|
|
|
case TR_KEY_wanted: return make_file_wanted_vec(tor);
|
|
|
|
case TR_KEY_files:
|
|
|
|
case TR_KEY_webseeds: return make_webseed_vec(tor);
|
|
|
|
tr_variantInitList(initme, tor->file_count());
|
|
|
|
case TR_KEY_webseedsSendingToUs: return st.webseedsSendingToUs;
|
|
|
|
addFiles(tor, initme);
|
|
|
|
default: return tr_variant{};
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
case TR_KEY_fileStats:
|
|
|
|
|
|
|
|
tr_variantInitList(initme, tor->file_count());
|
|
|
|
|
|
|
|
addFileStats(tor, initme);
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
case TR_KEY_group:
|
|
|
|
|
|
|
|
tr_variantInitStrView(initme, tor->bandwidth_group().sv());
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
case TR_KEY_hashString:
|
|
|
|
|
|
|
|
tr_variantInitStrView(initme, tor->info_hash_string());
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
case TR_KEY_haveUnchecked:
|
|
|
|
|
|
|
|
tr_variantInitInt(initme, st->haveUnchecked);
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
case TR_KEY_sequentialDownload:
|
|
|
|
|
|
|
|
tr_variantDictAddBool(initme, TR_KEY_sequentialDownload, tor->is_sequential_download());
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
case TR_KEY_haveValid:
|
|
|
|
|
|
|
|
tr_variantInitInt(initme, st->haveValid);
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
case TR_KEY_honorsSessionLimits:
|
|
|
|
|
|
|
|
tr_variantInitBool(initme, tor->uses_session_limits());
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
case TR_KEY_id:
|
|
|
|
|
|
|
|
tr_variantInitInt(initme, st->id);
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
case TR_KEY_editDate:
|
|
|
|
|
|
|
|
tr_variantInitInt(initme, st->editDate);
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
case TR_KEY_isFinished:
|
|
|
|
|
|
|
|
tr_variantInitBool(initme, st->finished);
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
case TR_KEY_isPrivate:
|
|
|
|
|
|
|
|
tr_variantInitBool(initme, tor->is_private());
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
case TR_KEY_isStalled:
|
|
|
|
|
|
|
|
tr_variantInitBool(initme, st->isStalled);
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
case TR_KEY_labels:
|
|
|
|
|
|
|
|
addLabels(tor, initme);
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
case TR_KEY_leftUntilDone:
|
|
|
|
|
|
|
|
tr_variantInitInt(initme, st->leftUntilDone);
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
case TR_KEY_manualAnnounceTime:
|
|
|
|
|
|
|
|
tr_variantInitInt(initme, tr_announcerNextManualAnnounce(tor));
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
case TR_KEY_maxConnectedPeers:
|
|
|
|
|
|
|
|
case TR_KEY_peer_limit:
|
|
|
|
|
|
|
|
tr_variantInitInt(initme, tor->peer_limit());
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
case TR_KEY_magnetLink:
|
|
|
|
|
|
|
|
tr_variantInitStr(initme, tor->metainfo_.magnet());
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
case TR_KEY_metadataPercentComplete:
|
|
|
|
|
|
|
|
tr_variantInitReal(initme, st->metadataPercentComplete);
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
case TR_KEY_name:
|
|
|
|
|
|
|
|
tr_variantInitStrView(initme, tr_torrentName(tor));
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
case TR_KEY_percentComplete:
|
|
|
|
|
|
|
|
tr_variantInitReal(initme, st->percentComplete);
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
case TR_KEY_percentDone:
|
|
|
|
|
|
|
|
tr_variantInitReal(initme, st->percentDone);
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
case TR_KEY_peers:
|
|
|
|
|
|
|
|
addPeers(tor, initme);
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
case TR_KEY_peersConnected:
|
|
|
|
|
|
|
|
tr_variantInitInt(initme, st->peersConnected);
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
case TR_KEY_peersFrom:
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
tr_variantInitDict(initme, 7);
|
|
|
|
|
|
|
|
auto const* f = st->peersFrom;
|
|
|
|
|
|
|
|
tr_variantDictAddInt(initme, TR_KEY_fromCache, f[TR_PEER_FROM_RESUME]);
|
|
|
|
|
|
|
|
tr_variantDictAddInt(initme, TR_KEY_fromDht, f[TR_PEER_FROM_DHT]);
|
|
|
|
|
|
|
|
tr_variantDictAddInt(initme, TR_KEY_fromIncoming, f[TR_PEER_FROM_INCOMING]);
|
|
|
|
|
|
|
|
tr_variantDictAddInt(initme, TR_KEY_fromLpd, f[TR_PEER_FROM_LPD]);
|
|
|
|
|
|
|
|
tr_variantDictAddInt(initme, TR_KEY_fromLtep, f[TR_PEER_FROM_LTEP]);
|
|
|
|
|
|
|
|
tr_variantDictAddInt(initme, TR_KEY_fromPex, f[TR_PEER_FROM_PEX]);
|
|
|
|
|
|
|
|
tr_variantDictAddInt(initme, TR_KEY_fromTracker, f[TR_PEER_FROM_TRACKER]);
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
case TR_KEY_peersGettingFromUs:
|
|
|
|
|
|
|
|
tr_variantInitInt(initme, st->peersGettingFromUs);
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
case TR_KEY_peersSendingToUs:
|
|
|
|
|
|
|
|
tr_variantInitInt(initme, st->peersSendingToUs);
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
case TR_KEY_pieces:
|
|
|
|
|
|
|
|
if (tor->has_metainfo())
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
auto const bytes = tor->create_piece_bitfield();
|
|
|
|
|
|
|
|
auto const enc = tr_base64_encode({ reinterpret_cast<char const*>(std::data(bytes)), std::size(bytes) });
|
|
|
|
|
|
|
|
tr_variantInitStr(initme, enc);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
else
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
tr_variantInitStrView(initme, ""sv);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
case TR_KEY_pieceCount:
|
|
|
|
|
|
|
|
tr_variantInitInt(initme, tor->piece_count());
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
case TR_KEY_pieceSize:
|
|
|
|
|
|
|
|
tr_variantInitInt(initme, tor->piece_size());
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
case TR_KEY_primary_mime_type:
|
|
|
|
|
|
|
|
tr_variantInitStrView(initme, tor->primary_mime_type());
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
case TR_KEY_priorities:
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
auto const n = tor->file_count();
|
|
|
|
|
|
|
|
tr_variantInitList(initme, n);
|
|
|
|
|
|
|
|
for (tr_file_index_t i = 0; i < n; ++i)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
tr_variantListAddInt(initme, tr_torrentFile(tor, i).priority);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
case TR_KEY_queuePosition:
|
|
|
|
|
|
|
|
tr_variantInitInt(initme, st->queuePosition);
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
case TR_KEY_etaIdle:
|
|
|
|
|
|
|
|
tr_variantInitInt(initme, st->etaIdle);
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
case TR_KEY_rateDownload:
|
|
|
|
|
|
|
|
tr_variantInitInt(initme, tr_toSpeedBytes(st->pieceDownloadSpeed_KBps));
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
case TR_KEY_rateUpload:
|
|
|
|
|
|
|
|
tr_variantInitInt(initme, tr_toSpeedBytes(st->pieceUploadSpeed_KBps));
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
case TR_KEY_recheckProgress:
|
|
|
|
|
|
|
|
tr_variantInitReal(initme, st->recheckProgress);
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
case TR_KEY_seedIdleLimit:
|
|
|
|
|
|
|
|
tr_variantInitInt(initme, tor->idle_limit_minutes());
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
case TR_KEY_seedIdleMode:
|
|
|
|
|
|
|
|
tr_variantInitInt(initme, tor->idle_limit_mode());
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
case TR_KEY_seedRatioLimit:
|
|
|
|
|
|
|
|
tr_variantInitReal(initme, tr_torrentGetRatioLimit(tor));
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
case TR_KEY_seedRatioMode:
|
|
|
|
|
|
|
|
tr_variantInitInt(initme, tr_torrentGetRatioMode(tor));
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
case TR_KEY_sizeWhenDone:
|
|
|
|
|
|
|
|
tr_variantInitInt(initme, st->sizeWhenDone);
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
case TR_KEY_source:
|
|
|
|
|
|
|
|
tr_variantInitStrView(initme, tor->source());
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
case TR_KEY_startDate:
|
|
|
|
|
|
|
|
tr_variantInitInt(initme, st->startDate);
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
case TR_KEY_status:
|
|
|
|
|
|
|
|
tr_variantInitInt(initme, st->activity);
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
case TR_KEY_secondsDownloading:
|
|
|
|
|
|
|
|
tr_variantInitInt(initme, st->secondsDownloading);
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
case TR_KEY_secondsSeeding:
|
|
|
|
|
|
|
|
tr_variantInitInt(initme, st->secondsSeeding);
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
case TR_KEY_trackers:
|
|
|
|
|
|
|
|
tr_variantInitList(initme, tor->tracker_count());
|
|
|
|
|
|
|
|
addTrackers(tor, initme);
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
case TR_KEY_trackerList:
|
|
|
|
|
|
|
|
tr_variantInitStr(initme, tor->tracker_list());
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
case TR_KEY_trackerStats:
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
auto const n = tr_torrentTrackerCount(tor);
|
|
|
|
|
|
|
|
tr_variantInitList(initme, n);
|
|
|
|
|
|
|
|
for (size_t i = 0; i < n; ++i)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
auto const& tracker = tr_torrentTracker(tor, i);
|
|
|
|
|
|
|
|
addTrackerStats(tracker, initme);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
case TR_KEY_torrentFile:
|
|
|
|
|
|
|
|
tr_variantInitStr(initme, tor->torrent_file());
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
case TR_KEY_totalSize:
|
|
|
|
|
|
|
|
tr_variantInitInt(initme, tor->total_size());
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
case TR_KEY_uploadedEver:
|
|
|
|
|
|
|
|
tr_variantInitInt(initme, st->uploadedEver);
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
case TR_KEY_uploadLimit:
|
|
|
|
|
|
|
|
tr_variantInitInt(initme, tr_torrentGetSpeedLimit_KBps(tor, TR_UP));
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
case TR_KEY_uploadLimited:
|
|
|
|
|
|
|
|
tr_variantInitBool(initme, tor->uses_speed_limit(TR_UP));
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
case TR_KEY_uploadRatio:
|
|
|
|
|
|
|
|
tr_variantInitReal(initme, st->ratio);
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
case TR_KEY_wanted:
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
auto const n = tor->file_count();
|
|
|
|
|
|
|
|
tr_variantInitList(initme, n);
|
|
|
|
|
|
|
|
for (tr_file_index_t i = 0; i < n; ++i)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
tr_variantListAddInt(initme, tr_torrentFile(tor, i).wanted ? 1 : 0);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
case TR_KEY_webseeds:
|
|
|
|
|
|
|
|
tr_variantInitList(initme, tor->webseed_count());
|
|
|
|
|
|
|
|
addWebseeds(tor, initme);
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
case TR_KEY_webseedsSendingToUs:
|
|
|
|
|
|
|
|
tr_variantInitInt(initme, st->webseedsSendingToUs);
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// clang-format on
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void addTorrentInfo(tr_torrent* tor, TrFormat format, tr_variant* entry, tr_quark const* fields, size_t field_count)
|
|
|
|
void addTorrentInfo(tr_torrent* tor, TrFormat format, tr_variant* entry, tr_quark const* fields, size_t field_count)
|
|
|
|
@@ -895,7 +712,7 @@ void addTorrentInfo(tr_torrent* tor, TrFormat format, tr_variant* entry, tr_quar
|
|
|
|
{
|
|
|
|
{
|
|
|
|
tr_variant* child = format == TrFormat::Table ? tr_variantListAdd(entry) : tr_variantDictAdd(entry, fields[i]);
|
|
|
|
tr_variant* child = format == TrFormat::Table ? tr_variantListAdd(entry) : tr_variantDictAdd(entry, fields[i]);
|
|
|
|
|
|
|
|
|
|
|
|
initField(tor, st, child, fields[i]);
|
|
|
|
*child = make_torrent_field(*tor, *st, fields[i]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
@@ -2590,26 +2407,23 @@ void tr_rpc_request_exec_json(
|
|
|
|
* - values that are all-digits or commas are number lists
|
|
|
|
* - values that are all-digits or commas are number lists
|
|
|
|
* - all other values are strings
|
|
|
|
* - all other values are strings
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
void tr_rpc_parse_list_str(tr_variant* setme, std::string_view str)
|
|
|
|
tr_variant tr_rpc_parse_list_str(std::string_view str)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
auto const values = tr_num_parse_range(str);
|
|
|
|
auto const values = tr_num_parse_range(str);
|
|
|
|
auto const value_count = std::size(values);
|
|
|
|
auto const n_values = std::size(values);
|
|
|
|
|
|
|
|
|
|
|
|
if (value_count == 0)
|
|
|
|
if (n_values == 0)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
tr_variantInitStr(setme, str);
|
|
|
|
return { str };
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (value_count == 1)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
tr_variantInitInt(setme, values[0]);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
else
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
tr_variantInitList(setme, value_count);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for (auto const& value : values)
|
|
|
|
if (n_values == 1)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
tr_variantListAddInt(setme, value);
|
|
|
|
return { values[0] };
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
auto num_vec = tr_variant::Vector{};
|
|
|
|
|
|
|
|
num_vec.reserve(n_values);
|
|
|
|
|
|
|
|
std::copy_n(std::cbegin(values), n_values, std::back_inserter(num_vec));
|
|
|
|
|
|
|
|
return { std::move(num_vec) };
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|