diff --git a/gtk/Application.cc b/gtk/Application.cc index 87ab9633c..e67ebadd5 100644 --- a/gtk/Application.cc +++ b/gtk/Application.cc @@ -1481,7 +1481,7 @@ void Application::Impl::start_all_torrents() tr_variant request; tr_variantInitDict(&request, 1); - tr_variantDictAddStrView(&request, TR_KEY_method, "torrent-start"sv); + tr_variantDictAddStrView(&request, TR_KEY_method, tr_quark_get_string_view(TR_KEY_torrent_start_kebab)); tr_rpc_request_exec(session, request, {}); } @@ -1491,7 +1491,7 @@ void Application::Impl::pause_all_torrents() tr_variant request; tr_variantInitDict(&request, 1); - tr_variantDictAddStrView(&request, TR_KEY_method, "torrent-stop"sv); + tr_variantDictAddStrView(&request, TR_KEY_method, tr_quark_get_string_view(TR_KEY_torrent_stop_kebab)); tr_rpc_request_exec(session, request, {}); } @@ -1564,6 +1564,7 @@ void Application::Impl::actions_handler(Glib::ustring const& action_name) } } else if ( + // TODO: migrate from _kebab action_name == "torrent-start" || action_name == "torrent-start-now" || action_name == "torrent-stop" || action_name == "torrent-reannounce" || action_name == "torrent-verify" || action_name == "queue-move-top" || action_name == "queue-move-up" || action_name == "queue-move-down" || action_name == "queue-move-bottom") diff --git a/libtransmission/quark.cc b/libtransmission/quark.cc index a5ce1e5ac..804f9dc84 100644 --- a/libtransmission/quark.cc +++ b/libtransmission/quark.cc @@ -73,11 +73,13 @@ auto constexpr MyStatic = std::array{ "blocklist-date"sv, "blocklist-enabled"sv, "blocklist-size"sv, + "blocklist-update"sv, "blocklist-updates-enabled"sv, "blocklist-url"sv, "blocklist_date"sv, "blocklist_enabled"sv, "blocklist_size"sv, + "blocklist_update"sv, "blocklist_updates_enabled"sv, "blocklist_url"sv, "blocks"sv, @@ -195,6 +197,8 @@ auto constexpr MyStatic = std::array{ "flag_str"sv, "flags"sv, "format"sv, + "free-space"sv, + "free_space"sv, "fromCache"sv, "fromDht"sv, "fromIncoming"sv, @@ -210,6 +214,10 @@ auto constexpr MyStatic = std::array{ "from_pex"sv, "from_tracker"sv, "group"sv, + "group-get"sv, + "group-set"sv, + "group_get"sv, + "group_set"sv, "hasAnnounced"sv, "hasScraped"sv, "has_announced"sv, @@ -398,8 +406,10 @@ auto constexpr MyStatic = std::array{ "port"sv, "port-forwarding-enabled"sv, "port-is-open"sv, + "port-test"sv, "port_forwarding_enabled"sv, "port_is_open"sv, + "port_test"sv, "preallocation"sv, "preferred_transports"sv, "primary-mime-type"sv, @@ -417,9 +427,17 @@ auto constexpr MyStatic = std::array{ "prompt-before-exit"sv, "prompt_before_exit"sv, "proxy_url"sv, + "queue-move-bottom"sv, + "queue-move-down"sv, + "queue-move-top"sv, + "queue-move-up"sv, "queue-stalled-enabled"sv, "queue-stalled-minutes"sv, "queuePosition"sv, + "queue_move_bottom"sv, + "queue_move_down"sv, + "queue_move_top"sv, + "queue_move_up"sv, "queue_position"sv, "queue_stalled_enabled"sv, "queue_stalled_minutes"sv, @@ -535,11 +553,19 @@ auto constexpr MyStatic = std::array{ "seeding_time_seconds"sv, "sequential_download"sv, "sequential_download_from_piece"sv, + "session-close"sv, "session-count"sv, + "session-get"sv, "session-id"sv, + "session-set"sv, + "session-stats"sv, "sessionCount"sv, + "session_close"sv, "session_count"sv, + "session_get"sv, "session_id"sv, + "session_set"sv, + "session_stats"sv, "show-backup-trackers"sv, "show-extra-peer-details"sv, "show-filterbar"sv, @@ -600,6 +626,7 @@ auto constexpr MyStatic = std::array{ "tcp_enabled"sv, "tier"sv, "time-checked"sv, + "torrent-add"sv, "torrent-added"sv, "torrent-added-notification-enabled"sv, "torrent-added-verify-mode"sv, @@ -608,10 +635,18 @@ auto constexpr MyStatic = std::array{ "torrent-complete-sound-enabled"sv, "torrent-duplicate"sv, "torrent-get"sv, + "torrent-reannounce"sv, + "torrent-remove"sv, + "torrent-rename-path"sv, "torrent-set"sv, "torrent-set-location"sv, + "torrent-start"sv, + "torrent-start-now"sv, + "torrent-stop"sv, + "torrent-verify"sv, "torrentCount"sv, "torrentFile"sv, + "torrent_add"sv, "torrent_added"sv, "torrent_added_notification_enabled"sv, "torrent_added_verify_mode"sv, @@ -623,8 +658,15 @@ auto constexpr MyStatic = std::array{ "torrent_duplicate"sv, "torrent_file"sv, "torrent_get"sv, + "torrent_reannounce"sv, + "torrent_remove"sv, + "torrent_rename_path"sv, "torrent_set"sv, "torrent_set_location"sv, + "torrent_start"sv, + "torrent_start_now"sv, + "torrent_stop"sv, + "torrent_verify"sv, "torrents"sv, "totalSize"sv, "total_size"sv, @@ -784,6 +826,7 @@ tr_quark tr_quark_convert(tr_quark q) case TR_KEY_blocklist_date_kebab: return TR_KEY_blocklist_date; case TR_KEY_blocklist_enabled_kebab: return TR_KEY_blocklist_enabled; case TR_KEY_blocklist_size_kebab: return TR_KEY_blocklist_size; + case TR_KEY_blocklist_update_kebab: return TR_KEY_blocklist_update; case TR_KEY_blocklist_updates_enabled_kebab: return TR_KEY_blocklist_updates_enabled; case TR_KEY_blocklist_url_kebab: return TR_KEY_blocklist_url; case TR_KEY_bytes_completed_camel: return TR_KEY_bytes_completed; @@ -835,6 +878,7 @@ tr_quark tr_quark_convert(tr_quark q) case TR_KEY_filter_text_kebab: return TR_KEY_filter_text; case TR_KEY_filter_trackers_kebab: return TR_KEY_filter_trackers; case TR_KEY_flag_str_camel: return TR_KEY_flag_str; + case TR_KEY_free_space_kebab: return TR_KEY_free_space; case TR_KEY_from_cache_camel: return TR_KEY_from_cache; case TR_KEY_from_dht_camel: return TR_KEY_from_dht; case TR_KEY_from_incoming_camel: return TR_KEY_from_incoming; @@ -842,6 +886,8 @@ tr_quark tr_quark_convert(tr_quark q) case TR_KEY_from_ltep_camel: return TR_KEY_from_ltep; case TR_KEY_from_pex_camel: return TR_KEY_from_pex; case TR_KEY_from_tracker_camel: return TR_KEY_from_tracker; + case TR_KEY_group_get_kebab: return TR_KEY_group_get; + case TR_KEY_group_set_kebab: return TR_KEY_group_set; case TR_KEY_hash_string_camel: return TR_KEY_hash_string; case TR_KEY_has_announced_camel: return TR_KEY_has_announced; case TR_KEY_has_scraped_camel: return TR_KEY_has_scraped; @@ -919,12 +965,17 @@ tr_quark tr_quark_convert(tr_quark q) case TR_KEY_piece_size_camel: return TR_KEY_piece_size; case TR_KEY_port_forwarding_enabled_kebab: return TR_KEY_port_forwarding_enabled; case TR_KEY_port_is_open_kebab: return TR_KEY_port_is_open; + case TR_KEY_port_test_kebab: return TR_KEY_port_test; case TR_KEY_primary_mime_type_kebab: return TR_KEY_primary_mime_type; case TR_KEY_priority_high_kebab: return TR_KEY_priority_high; case TR_KEY_priority_low_kebab: return TR_KEY_priority_low; case TR_KEY_priority_normal_kebab: return TR_KEY_priority_normal; case TR_KEY_prompt_before_exit_kebab: return TR_KEY_prompt_before_exit; case TR_KEY_queue_position_camel: return TR_KEY_queue_position; + case TR_KEY_queue_move_bottom_kebab: return TR_KEY_queue_move_bottom; + case TR_KEY_queue_move_down_kebab: return TR_KEY_queue_move_down; + case TR_KEY_queue_move_top_kebab: return TR_KEY_queue_move_top; + case TR_KEY_queue_move_up_kebab: return TR_KEY_queue_move_up; case TR_KEY_queue_stalled_enabled_kebab: return TR_KEY_queue_stalled_enabled; case TR_KEY_queue_stalled_minutes_kebab: return TR_KEY_queue_stalled_minutes; case TR_KEY_rate_download_camel: return TR_KEY_rate_download; @@ -981,10 +1032,14 @@ tr_quark tr_quark_convert(tr_quark q) case TR_KEY_seed_ratio_mode_camel: return TR_KEY_seed_ratio_mode; case TR_KEY_seeding_time_seconds_kebab: return TR_KEY_seeding_time_seconds; case TR_KEY_seeder_count_camel: return TR_KEY_seeder_count; + case TR_KEY_session_close_kebab: return TR_KEY_session_close; case TR_KEY_session_count_camel: case TR_KEY_session_count_kebab: return TR_KEY_session_count; + case TR_KEY_session_get_kebab: return TR_KEY_session_get; case TR_KEY_session_id_kebab: return TR_KEY_session_id; + case TR_KEY_session_set_kebab: return TR_KEY_session_set; + case TR_KEY_session_stats_kebab: return TR_KEY_session_stats; case TR_KEY_show_backup_trackers_kebab: return TR_KEY_show_backup_trackers; case TR_KEY_show_extra_peer_details_kebab: return TR_KEY_show_extra_peer_details; case TR_KEY_show_filterbar_kebab: return TR_KEY_show_filterbar; @@ -1010,6 +1065,7 @@ tr_quark tr_quark_convert(tr_quark q) case TR_KEY_start_minimized_kebab: return TR_KEY_start_minimized; case TR_KEY_statusbar_stats_kebab: return TR_KEY_statusbar_stats; case TR_KEY_tcp_enabled_kebab: return TR_KEY_tcp_enabled; + case TR_KEY_torrent_add_kebab: return TR_KEY_torrent_add; case TR_KEY_torrent_added_kebab: return TR_KEY_torrent_added; case TR_KEY_torrent_added_notification_enabled_kebab: return TR_KEY_torrent_added_notification_enabled; case TR_KEY_torrent_added_verify_mode_kebab: return TR_KEY_torrent_added_verify_mode; @@ -1020,8 +1076,15 @@ tr_quark tr_quark_convert(tr_quark q) case TR_KEY_torrent_duplicate_kebab: return TR_KEY_torrent_duplicate; case TR_KEY_torrent_file_camel: return TR_KEY_torrent_file; case TR_KEY_torrent_get_kebab: return TR_KEY_torrent_get; + case TR_KEY_torrent_reannounce_kebab: return TR_KEY_torrent_reannounce; + case TR_KEY_torrent_remove_kebab: return TR_KEY_torrent_remove; + case TR_KEY_torrent_rename_path_kebab: return TR_KEY_torrent_rename_path; case TR_KEY_torrent_set_kebab: return TR_KEY_torrent_set; case TR_KEY_torrent_set_location_kebab: return TR_KEY_torrent_set_location; + case TR_KEY_torrent_start_kebab: return TR_KEY_torrent_start; + case TR_KEY_torrent_start_now_kebab: return TR_KEY_torrent_start_now; + case TR_KEY_torrent_stop_kebab: return TR_KEY_torrent_stop; + case TR_KEY_torrent_verify_kebab: return TR_KEY_torrent_verify; case TR_KEY_total_size_camel: return TR_KEY_total_size; case TR_KEY_tracker_add_camel: return TR_KEY_tracker_add; case TR_KEY_tracker_list_camel: return TR_KEY_tracker_list; diff --git a/libtransmission/quark.h b/libtransmission/quark.h index 5188a457e..7072afe36 100644 --- a/libtransmission/quark.h +++ b/libtransmission/quark.h @@ -71,11 +71,13 @@ enum // NOLINT(performance-enum-size) TR_KEY_blocklist_date_kebab, TR_KEY_blocklist_enabled_kebab, TR_KEY_blocklist_size_kebab, + TR_KEY_blocklist_update_kebab, TR_KEY_blocklist_updates_enabled_kebab, TR_KEY_blocklist_url_kebab, TR_KEY_blocklist_date, TR_KEY_blocklist_enabled, TR_KEY_blocklist_size, + TR_KEY_blocklist_update, TR_KEY_blocklist_updates_enabled, TR_KEY_blocklist_url, TR_KEY_blocks, @@ -193,6 +195,8 @@ enum // NOLINT(performance-enum-size) TR_KEY_flag_str, TR_KEY_flags, TR_KEY_format, + TR_KEY_free_space_kebab, + TR_KEY_free_space, TR_KEY_from_cache_camel, TR_KEY_from_dht_camel, TR_KEY_from_incoming_camel, @@ -208,6 +212,10 @@ enum // NOLINT(performance-enum-size) TR_KEY_from_pex, TR_KEY_from_tracker, TR_KEY_group, + TR_KEY_group_get_kebab, + TR_KEY_group_set_kebab, + TR_KEY_group_get, + TR_KEY_group_set, TR_KEY_has_announced_camel, TR_KEY_has_scraped_camel, TR_KEY_has_announced, @@ -396,8 +404,10 @@ enum // NOLINT(performance-enum-size) TR_KEY_port, TR_KEY_port_forwarding_enabled_kebab, TR_KEY_port_is_open_kebab, + TR_KEY_port_test_kebab, TR_KEY_port_forwarding_enabled, TR_KEY_port_is_open, + TR_KEY_port_test, TR_KEY_preallocation, TR_KEY_preferred_transports, TR_KEY_primary_mime_type_kebab, @@ -415,9 +425,17 @@ enum // NOLINT(performance-enum-size) TR_KEY_prompt_before_exit_kebab, TR_KEY_prompt_before_exit, TR_KEY_proxy_url, + TR_KEY_queue_move_bottom_kebab, + TR_KEY_queue_move_down_kebab, + TR_KEY_queue_move_top_kebab, + TR_KEY_queue_move_up_kebab, TR_KEY_queue_stalled_enabled_kebab, TR_KEY_queue_stalled_minutes_kebab, TR_KEY_queue_position_camel, + TR_KEY_queue_move_bottom, + TR_KEY_queue_move_down, + TR_KEY_queue_move_top, + TR_KEY_queue_move_up, TR_KEY_queue_position, TR_KEY_queue_stalled_enabled, TR_KEY_queue_stalled_minutes, @@ -533,11 +551,19 @@ enum // NOLINT(performance-enum-size) TR_KEY_seeding_time_seconds, TR_KEY_sequential_download, TR_KEY_sequential_download_from_piece, + TR_KEY_session_close_kebab, TR_KEY_session_count_kebab, + TR_KEY_session_get_kebab, TR_KEY_session_id_kebab, + TR_KEY_session_set_kebab, + TR_KEY_session_stats_kebab, TR_KEY_session_count_camel, + TR_KEY_session_close, TR_KEY_session_count, + TR_KEY_session_get, TR_KEY_session_id, + TR_KEY_session_set, + TR_KEY_session_stats, TR_KEY_show_backup_trackers_kebab, TR_KEY_show_extra_peer_details_kebab, TR_KEY_show_filterbar_kebab, @@ -598,6 +624,7 @@ enum // NOLINT(performance-enum-size) TR_KEY_tcp_enabled, TR_KEY_tier, TR_KEY_time_checked, + TR_KEY_torrent_add_kebab, TR_KEY_torrent_added_kebab, TR_KEY_torrent_added_notification_enabled_kebab, TR_KEY_torrent_added_verify_mode_kebab, @@ -606,10 +633,18 @@ enum // NOLINT(performance-enum-size) TR_KEY_torrent_complete_sound_enabled_kebab, TR_KEY_torrent_duplicate_kebab, TR_KEY_torrent_get_kebab, + TR_KEY_torrent_reannounce_kebab, + TR_KEY_torrent_remove_kebab, + TR_KEY_torrent_rename_path_kebab, TR_KEY_torrent_set_kebab, TR_KEY_torrent_set_location_kebab, + TR_KEY_torrent_start_kebab, + TR_KEY_torrent_start_now_kebab, + TR_KEY_torrent_stop_kebab, + TR_KEY_torrent_verify_kebab, TR_KEY_torrent_count_camel, TR_KEY_torrent_file_camel, + TR_KEY_torrent_add, TR_KEY_torrent_added, TR_KEY_torrent_added_notification_enabled, TR_KEY_torrent_added_verify_mode, @@ -621,8 +656,15 @@ enum // NOLINT(performance-enum-size) TR_KEY_torrent_duplicate, TR_KEY_torrent_file, TR_KEY_torrent_get, + TR_KEY_torrent_reannounce, + TR_KEY_torrent_remove, + TR_KEY_torrent_rename_path, TR_KEY_torrent_set, TR_KEY_torrent_set_location, + TR_KEY_torrent_start, + TR_KEY_torrent_start_now, + TR_KEY_torrent_stop, + TR_KEY_torrent_verify, TR_KEY_torrents, TR_KEY_total_size_camel, TR_KEY_total_size, diff --git a/libtransmission/rpcimpl.cc b/libtransmission/rpcimpl.cc index 9c56b9762..4deddd352 100644 --- a/libtransmission/rpcimpl.cc +++ b/libtransmission/rpcimpl.cc @@ -19,6 +19,8 @@ #include +#include + #include #include "libtransmission/transmission.h" @@ -2809,36 +2811,36 @@ namespace session_get_helpers using SyncHandler = std::pair (*)(tr_session*, tr_variant::Map const&, tr_variant::Map&); -auto constexpr SyncHandlers = std::array, 20U>{ { - { "free_space"sv, freeSpace, false }, - { "group_get"sv, groupGet, false }, - { "group_set"sv, groupSet, true }, - { "queue_move_bottom"sv, queueMoveBottom, true }, - { "queue_move_down"sv, queueMoveDown, true }, - { "queue_move_top"sv, queueMoveTop, true }, - { "queue_move_up"sv, queueMoveUp, true }, - { "session_close"sv, sessionClose, true }, - { "session_get"sv, sessionGet, false }, - { "session_set"sv, sessionSet, true }, - { "session_stats"sv, sessionStats, false }, - { "torrent_get"sv, torrentGet, false }, - { "torrent_reannounce"sv, torrentReannounce, true }, - { "torrent_remove"sv, torrentRemove, true }, - { "torrent_set"sv, torrentSet, true }, - { "torrent_set_location"sv, torrentSetLocation, true }, - { "torrent_start"sv, torrentStart, true }, - { "torrent_start_now"sv, torrentStartNow, true }, - { "torrent_stop"sv, torrentStop, true }, - { "torrent_verify"sv, torrentVerify, true }, +auto const sync_handlers = small::max_size_map, 20U>{ { + { TR_KEY_free_space, { freeSpace, false } }, + { TR_KEY_group_get, { groupGet, false } }, + { TR_KEY_group_set, { groupSet, true } }, + { TR_KEY_queue_move_bottom, { queueMoveBottom, true } }, + { TR_KEY_queue_move_down, { queueMoveDown, true } }, + { TR_KEY_queue_move_top, { queueMoveTop, true } }, + { TR_KEY_queue_move_up, { queueMoveUp, true } }, + { TR_KEY_session_close, { sessionClose, true } }, + { TR_KEY_session_get, { sessionGet, false } }, + { TR_KEY_session_set, { sessionSet, true } }, + { TR_KEY_session_stats, { sessionStats, false } }, + { TR_KEY_torrent_get, { torrentGet, false } }, + { TR_KEY_torrent_reannounce, { torrentReannounce, true } }, + { TR_KEY_torrent_remove, { torrentRemove, true } }, + { TR_KEY_torrent_set, { torrentSet, true } }, + { TR_KEY_torrent_set_location, { torrentSetLocation, true } }, + { TR_KEY_torrent_start, { torrentStart, true } }, + { TR_KEY_torrent_start_now, { torrentStartNow, true } }, + { TR_KEY_torrent_stop, { torrentStop, true } }, + { TR_KEY_torrent_verify, { torrentVerify, true } }, } }; using AsyncHandler = void (*)(tr_session*, tr_variant::Map const&, DoneCb&&, tr_rpc_idle_data*); -auto constexpr AsyncHandlers = std::array, 4U>{ { - { "blocklist_update"sv, blocklistUpdate, true }, - { "port_test"sv, portTest, false }, - { "torrent_add"sv, torrentAdd, true }, - { "torrent_rename_path"sv, torrentRenamePath, true }, +auto const async_handlers = small::max_size_map, 4U>{ { + { TR_KEY_blocklist_update, { blocklistUpdate, true } }, + { TR_KEY_port_test, { portTest, false } }, + { TR_KEY_torrent_add, { torrentAdd, true } }, + { TR_KEY_torrent_rename_path, { torrentRenamePath, true } }, } }; void noop_response_callback(tr_session* /*session*/, tr_variant&& /*response*/) @@ -2887,6 +2889,7 @@ void tr_rpc_request_exec_impl(tr_session* session, tr_variant const& request, tr } auto const method_name = map->value_if(TR_KEY_method).value_or(""sv); + auto const method_key = tr_quark_convert(tr_quark_new(method_name)); auto data = tr_rpc_idle_data{}; data.session = session; @@ -2924,22 +2927,9 @@ void tr_rpc_request_exec_impl(tr_session* session, tr_variant const& request, tr auto done_cb = is_jsonrpc ? tr_rpc_idle_done : tr_rpc_idle_done_legacy; - auto const test = [method_name](auto const& handler) + if (auto const handler = async_handlers.find(method_key); handler != std::end(async_handlers)) { - auto const& name = std::get<0>(handler); - if (name == method_name) - { - return true; - } - - auto kebab_case = std::string{ name }; - std::replace(std::begin(kebab_case), std::end(kebab_case), '_', '-'); - return kebab_case == method_name; - }; - - if (auto const end = std::end(AsyncHandlers), handler = std::find_if(std::begin(AsyncHandlers), end, test); handler != end) - { - auto const& [name, func, has_side_effects] = *handler; + auto const& [func, has_side_effects] = handler->second; if (is_notification && !has_side_effects) { done_cb(&data, Error::SUCCESS, {}); @@ -2958,9 +2948,9 @@ void tr_rpc_request_exec_impl(tr_session* session, tr_variant const& request, tr return; } - if (auto const end = std::end(SyncHandlers), handler = std::find_if(std::begin(SyncHandlers), end, test); handler != end) + if (auto const handler = sync_handlers.find(method_key); handler != std::end(sync_handlers)) { - auto const& [name, func, has_side_effects] = *handler; + auto const& [func, has_side_effects] = handler->second; if (is_notification && !has_side_effects) { done_cb(&data, Error::SUCCESS, {}); diff --git a/qt/FreeSpaceLabel.cc b/qt/FreeSpaceLabel.cc index 7daaa6841..370b9c793 100644 --- a/qt/FreeSpaceLabel.cc +++ b/qt/FreeSpaceLabel.cc @@ -76,7 +76,7 @@ void FreeSpaceLabel::onTimer() auto* q = new RpcQueue{ this }; - q->add([this, &args]() { return session_->exec("free-space", &args); }); + q->add([this, &args]() { return session_->exec(TR_KEY_free_space_kebab, &args); }); q->add( [this](RpcResponse const& r) diff --git a/qt/RpcClient.cc b/qt/RpcClient.cc index 4a3db302e..422ab5ec3 100644 --- a/qt/RpcClient.cc +++ b/qt/RpcClient.cc @@ -71,13 +71,10 @@ void RpcClient::start(QUrl const& url) request_.reset(); } -RpcResponseFuture RpcClient::exec(tr_quark method, tr_variant* args) +RpcResponseFuture RpcClient::exec(tr_quark const method_key, tr_variant* args) { - return exec(tr_quark_get_string_view(method), args); -} + auto const method = tr_quark_get_string_view(method_key); -RpcResponseFuture RpcClient::exec(std::string_view method, tr_variant* args) -{ TrVariantPtr const json = createVariant(); tr_variantInitDict(json.get(), 3); dictAdd(json.get(), TR_KEY_method, method); diff --git a/qt/RpcClient.h b/qt/RpcClient.h index 419f9f644..9c57be677 100644 --- a/qt/RpcClient.h +++ b/qt/RpcClient.h @@ -73,7 +73,6 @@ public: void start(QUrl const& url); RpcResponseFuture exec(tr_quark method, tr_variant* args); - RpcResponseFuture exec(std::string_view method, tr_variant* args); signals: void httpAuthenticationRequired(); diff --git a/qt/Session.cc b/qt/Session.cc index f00c24410..68ee18e89 100644 --- a/qt/Session.cc +++ b/qt/Session.cc @@ -80,7 +80,7 @@ void Session::sessionSet(tr_quark const key, QVariant const& value) assert(false); } - exec("session-set", &args); + exec(TR_KEY_session_set_kebab, &args); } void Session::portTest(Session::PortTestIpProtocol const ip_protocol) @@ -108,7 +108,7 @@ void Session::portTest(Session::PortTestIpProtocol const ip_protocol) auto* q = new RpcQueue{}; - q->add([this, &args]() { return exec("port-test", &args); }, response_func); + q->add([this, &args]() { return exec(TR_KEY_port_test_kebab, &args); }, response_func); q->add(response_func); @@ -489,7 +489,7 @@ void Session::torrentRenamePath(torrent_ids_t const& torrent_ids, QString const& auto* q = new RpcQueue{}; q->add( - [this, &args]() { return exec("torrent-rename-path", &args); }, + [this, &args]() { return exec(TR_KEY_torrent_rename_path_kebab, &args); }, [](RpcResponse const& r) { auto const path = dictFind(r.args.get(), TR_KEY_path).value_or(QStringLiteral("(unknown)")); @@ -690,7 +690,7 @@ void Session::refreshExtraStats(torrent_ids_t const& ids) refreshTorrents(ids, TorrentProperties::DetailStat); } -void Session::sendTorrentRequest(std::string_view request, torrent_ids_t const& torrent_ids) +void Session::sendTorrentRequest(tr_quark const method, torrent_ids_t const& torrent_ids) { tr_variant args; tr_variantInitDict(&args, 1); @@ -698,7 +698,7 @@ void Session::sendTorrentRequest(std::string_view request, torrent_ids_t const& auto* q = new RpcQueue{}; - q->add([this, request, &args]() { return exec(request, &args); }); + q->add([this, method, &args]() { return exec(method, &args); }); q->add([this, torrent_ids]() { refreshTorrents(torrent_ids, TorrentProperties::MainStats); }); @@ -707,37 +707,37 @@ void Session::sendTorrentRequest(std::string_view request, torrent_ids_t const& void Session::pauseTorrents(torrent_ids_t const& ids) { - sendTorrentRequest("torrent-stop", ids); + sendTorrentRequest(TR_KEY_torrent_stop_kebab, ids); } void Session::startTorrents(torrent_ids_t const& ids) { - sendTorrentRequest("torrent-start", ids); + sendTorrentRequest(TR_KEY_torrent_start_kebab, ids); } void Session::startTorrentsNow(torrent_ids_t const& ids) { - sendTorrentRequest("torrent-start-now", ids); + sendTorrentRequest(TR_KEY_torrent_start_now_kebab, ids); } void Session::queueMoveTop(torrent_ids_t const& ids) { - sendTorrentRequest("queue-move-top", ids); + sendTorrentRequest(TR_KEY_queue_move_top_kebab, ids); } void Session::queueMoveUp(torrent_ids_t const& ids) { - sendTorrentRequest("queue-move-up", ids); + sendTorrentRequest(TR_KEY_queue_move_up_kebab, ids); } void Session::queueMoveDown(torrent_ids_t const& ids) { - sendTorrentRequest("queue-move-down", ids); + sendTorrentRequest(TR_KEY_queue_move_down_kebab, ids); } void Session::queueMoveBottom(torrent_ids_t const& ids) { - sendTorrentRequest("queue-move-bottom", ids); + sendTorrentRequest(TR_KEY_queue_move_bottom_kebab, ids); } void Session::refreshActiveTorrents() @@ -762,7 +762,7 @@ void Session::refreshSessionStats() { auto* q = new RpcQueue{}; - q->add([this]() { return exec("session-stats", nullptr); }); + q->add([this]() { return exec(TR_KEY_session_stats_kebab, nullptr); }); q->add([this](RpcResponse const& r) { updateStats(r.args.get()); }); @@ -773,7 +773,7 @@ void Session::refreshSessionInfo() { auto* q = new RpcQueue{}; - q->add([this]() { return exec("session-get", nullptr); }); + q->add([this]() { return exec(TR_KEY_session_get_kebab, nullptr); }); q->add([this](RpcResponse const& r) { updateInfo(r.args.get()); }); @@ -784,7 +784,7 @@ void Session::updateBlocklist() { auto* q = new RpcQueue{}; - q->add([this]() { return exec("blocklist-update", nullptr); }); + q->add([this]() { return exec(TR_KEY_blocklist_update_kebab, nullptr); }); q->add( [this](RpcResponse const& r) @@ -807,11 +807,6 @@ RpcResponseFuture Session::exec(tr_quark method, tr_variant* args) return rpc_.exec(method, args); } -RpcResponseFuture Session::exec(std::string_view method, tr_variant* args) -{ - return rpc_.exec(method, args); -} - void Session::updateStats(tr_variant* args_dict, tr_session_stats* stats) { if (auto const value = dictFind(args_dict, TR_KEY_uploaded_bytes_camel); value) @@ -1020,7 +1015,7 @@ void Session::addTorrent(AddData add_me, tr_variant* args_dict) auto* q = new RpcQueue{}; q->add( - [this, args_dict]() { return exec("torrent-add", args_dict); }, + [this, args_dict]() { return exec(TR_KEY_torrent_add_kebab, args_dict); }, [add_me](RpcResponse const& r) { auto* d = new QMessageBox{ QMessageBox::Warning, @@ -1102,7 +1097,7 @@ void Session::addNewlyCreatedTorrent(QString const& filename, QString const& loc dictAdd(&args, TR_KEY_paused, !prefs_.getBool(Prefs::START)); dictAdd(&args, TR_KEY_metainfo, b64); - exec("torrent-add", &args); + exec(TR_KEY_torrent_add_kebab, &args); } void Session::removeTorrents(torrent_ids_t const& ids, bool delete_files) @@ -1114,7 +1109,7 @@ void Session::removeTorrents(torrent_ids_t const& ids, bool delete_files) addOptionalIds(&args, ids); dictAdd(&args, TR_KEY_delete_local_data_kebab, delete_files); - exec("torrent-remove", &args); + exec(TR_KEY_torrent_remove_kebab, &args); } } @@ -1126,7 +1121,7 @@ void Session::verifyTorrents(torrent_ids_t const& ids) tr_variantInitDict(&args, 1); addOptionalIds(&args, ids); - exec("torrent-verify", &args); + exec(TR_KEY_torrent_verify_kebab, &args); } } @@ -1138,7 +1133,7 @@ void Session::reannounceTorrents(torrent_ids_t const& ids) tr_variantInitDict(&args, 1); addOptionalIds(&args, ids); - exec("torrent-reannounce", &args); + exec(TR_KEY_torrent_reannounce_kebab, &args); } } diff --git a/qt/Session.h b/qt/Session.h index 27328a45c..7753741bf 100644 --- a/qt/Session.h +++ b/qt/Session.h @@ -101,7 +101,6 @@ public: } RpcResponseFuture exec(tr_quark method, tr_variant* args); - RpcResponseFuture exec(std::string_view method, tr_variant* args); using Tag = RpcQueue::Tag; Tag torrentSet(torrent_ids_t const& torrent_ids, tr_quark const key, bool val); @@ -194,7 +193,7 @@ private: Tag torrentSetImpl(tr_variant* args); void sessionSet(tr_quark const key, QVariant const& value); void pumpRequests(); - void sendTorrentRequest(std::string_view request, torrent_ids_t const& torrent_ids); + void sendTorrentRequest(tr_quark method, torrent_ids_t const& torrent_ids); void refreshTorrents(torrent_ids_t const& ids, TorrentProperties props); std::set const& getKeyNames(TorrentProperties props); diff --git a/tests/libtransmission/rpc-test.cc b/tests/libtransmission/rpc-test.cc index 8159a1b60..3e333a134 100644 --- a/tests/libtransmission/rpc-test.cc +++ b/tests/libtransmission/rpc-test.cc @@ -99,7 +99,7 @@ TEST_F(RpcTest, JsonRpcWrongVersion) { auto request_map = tr_variant::Map{ 3U }; request_map.try_emplace(TR_KEY_jsonrpc, "1.0"); - request_map.try_emplace(TR_KEY_method, "session_stats"); + request_map.try_emplace(TR_KEY_method, tr_variant::unmanaged_string(tr_quark_get_string_view(TR_KEY_session_stats))); request_map.try_emplace(TR_KEY_id, 12345); auto response = tr_variant{}; @@ -141,7 +141,9 @@ TEST_F(RpcTest, idSync) { auto request_map = tr_variant::Map{ 3U }; request_map.try_emplace(TR_KEY_jsonrpc, JsonRpc::Version); - request_map.try_emplace(TR_KEY_method, "session-stats"); + request_map.try_emplace( + TR_KEY_method, + tr_variant::unmanaged_string(tr_quark_get_string_view(TR_KEY_session_stats_kebab))); request_map[TR_KEY_id].merge(request_id); // copy auto response = tr_variant{}; @@ -187,7 +189,7 @@ TEST_F(RpcTest, idWrongType) { auto request_map = tr_variant::Map{ 3U }; request_map.try_emplace(TR_KEY_jsonrpc, JsonRpc::Version); - request_map.try_emplace(TR_KEY_method, "session_stats"); + request_map.try_emplace(TR_KEY_method, tr_variant::unmanaged_string(tr_quark_get_string_view(TR_KEY_session_stats))); request_map[TR_KEY_id].merge(request_id); // copy auto response = tr_variant{}; @@ -221,7 +223,7 @@ TEST_F(RpcTest, idWrongType) TEST_F(RpcTest, tagSyncLegacy) { auto request_map = tr_variant::Map{ 2U }; - request_map.try_emplace(TR_KEY_method, "session_stats"); + request_map.try_emplace(TR_KEY_method, tr_variant::unmanaged_string(tr_quark_get_string_view(TR_KEY_session_stats))); request_map.try_emplace(TR_KEY_tag, 12345); auto response = tr_variant{}; @@ -255,7 +257,9 @@ TEST_F(RpcTest, idAsync) auto request_map = tr_variant::Map{ 3U }; request_map.try_emplace(TR_KEY_jsonrpc, JsonRpc::Version); - request_map.try_emplace(TR_KEY_method, "torrent-rename-path"); + request_map.try_emplace( + TR_KEY_method, + tr_variant::unmanaged_string(tr_quark_get_string_view(TR_KEY_torrent_rename_path_kebab))); request_map[TR_KEY_id].merge(request_id); // copy auto params_map = tr_variant::Map{ 2U }; @@ -306,7 +310,7 @@ TEST_F(RpcTest, tagAsyncLegacy) EXPECT_NE(nullptr, tor); auto request_map = tr_variant::Map{ 3U }; - request_map.try_emplace(TR_KEY_method, "torrent_rename_path"); + request_map.try_emplace(TR_KEY_method, tr_variant::unmanaged_string(tr_quark_get_string_view(TR_KEY_torrent_rename_path))); request_map.try_emplace(TR_KEY_tag, 12345); auto arguments_map = tr_variant::Map{ 2U }; @@ -339,7 +343,7 @@ TEST_F(RpcTest, NotificationSync) { auto request_map = tr_variant::Map{ 2U }; request_map.try_emplace(TR_KEY_jsonrpc, JsonRpc::Version); - request_map.try_emplace(TR_KEY_method, "session_stats"); + request_map.try_emplace(TR_KEY_method, tr_variant::unmanaged_string(tr_quark_get_string_view(TR_KEY_session_stats))); auto response = tr_variant{}; tr_rpc_request_exec( @@ -357,7 +361,7 @@ TEST_F(RpcTest, NotificationAsync) auto request_map = tr_variant::Map{ 2U }; request_map.try_emplace(TR_KEY_jsonrpc, JsonRpc::Version); - request_map.try_emplace(TR_KEY_method, "torrent_rename_path"); + request_map.try_emplace(TR_KEY_method, tr_variant::unmanaged_string(tr_quark_get_string_view(TR_KEY_torrent_rename_path))); auto params_map = tr_variant::Map{ 2U }; params_map.try_emplace(TR_KEY_path, "files-filled-with-zeroes/512"); @@ -440,18 +444,18 @@ TEST_F(RpcTest, batch) auto request = tr_variant::Map{ 3U }; request.try_emplace(TR_KEY_jsonrpc, JsonRpc::Version); - request.try_emplace(TR_KEY_method, "session-stats"); + request.try_emplace(TR_KEY_method, tr_variant::unmanaged_string(tr_quark_get_string_view(TR_KEY_session_stats_kebab))); request.try_emplace(TR_KEY_id, 12345); request_vec.emplace_back(std::move(request)); request = tr_variant::Map{ 2U }; request.try_emplace(TR_KEY_jsonrpc, JsonRpc::Version); - request.try_emplace(TR_KEY_method, "session-set"); + request.try_emplace(TR_KEY_method, tr_variant::unmanaged_string(tr_quark_get_string_view(TR_KEY_session_set_kebab))); request_vec.emplace_back(std::move(request)); request = tr_variant::Map{ 3U }; request.try_emplace(TR_KEY_jsonrpc, JsonRpc::Version); - request.try_emplace(TR_KEY_method, "session-stats"); + request.try_emplace(TR_KEY_method, tr_variant::unmanaged_string(tr_quark_get_string_view(TR_KEY_session_stats_kebab))); request.try_emplace(TR_KEY_id, "12345"sv); request_vec.emplace_back(std::move(request)); @@ -473,7 +477,7 @@ TEST_F(RpcTest, batch) request_vec.emplace_back(std::move(request)); request = tr_variant::Map{ 2U }; - request.try_emplace(TR_KEY_method, "session-stats"); + request.try_emplace(TR_KEY_method, tr_variant::unmanaged_string(tr_quark_get_string_view(TR_KEY_session_stats_kebab))); request.try_emplace(TR_KEY_tag, 12345); request_vec.emplace_back(std::move(request)); @@ -592,7 +596,7 @@ TEST_F(RpcTest, sessionGet) auto request_map = tr_variant::Map{ 3U }; request_map.try_emplace(TR_KEY_jsonrpc, JsonRpc::Version); - request_map.try_emplace(TR_KEY_method, "session_get"sv); + request_map.try_emplace(TR_KEY_method, tr_variant::unmanaged_string(tr_quark_get_string_view(TR_KEY_session_get))); request_map.try_emplace(TR_KEY_id, 12345); auto response = tr_variant{}; tr_rpc_request_exec( @@ -764,7 +768,7 @@ TEST_F(RpcTest, torrentGet) auto request = tr_variant::Map{ 3U }; request.try_emplace(TR_KEY_jsonrpc, JsonRpc::Version); - request.try_emplace(TR_KEY_method, "torrent_get"sv); + request.try_emplace(TR_KEY_method, tr_variant::unmanaged_string(tr_quark_get_string_view(TR_KEY_torrent_get))); request.try_emplace(TR_KEY_id, 12345); auto params = tr_variant::Map{ 1U }; @@ -798,4 +802,44 @@ TEST_F(RpcTest, torrentGet) tr_torrentRemove(tor, false, nullptr, nullptr, nullptr, nullptr); } +TEST_F(RpcTest, torrentGetLegacy) +{ + auto* tor = zeroTorrentInit(ZeroTorrentState::NoFiles); + EXPECT_NE(nullptr, tor); + + auto request = tr_variant::Map{ 1U }; + + request.try_emplace(TR_KEY_method, tr_quark_get_string_view(TR_KEY_torrent_get_kebab)); + + auto args_in = tr_variant::Map{ 1U }; + auto fields = tr_variant::Vector{}; + fields.emplace_back(tr_quark_get_string_view(TR_KEY_id)); + args_in.try_emplace(TR_KEY_fields, std::move(fields)); + request.try_emplace(TR_KEY_arguments, std::move(args_in)); + + auto response = tr_variant{}; + tr_rpc_request_exec( + session_, + std::move(request), + [&response](tr_session* /*session*/, tr_variant&& resp) { response = std::move(resp); }); + + auto* response_map = response.get_if(); + ASSERT_NE(response_map, nullptr); + auto* args_out = response_map->find_if(TR_KEY_arguments); + ASSERT_NE(args_out, nullptr); + + auto* torrents = args_out->find_if(TR_KEY_torrents); + ASSERT_NE(torrents, nullptr); + EXPECT_EQ(1UL, std::size(*torrents)); + + auto* first_torrent = (*torrents)[0].get_if(); + ASSERT_NE(first_torrent, nullptr); + auto first_torrent_id = first_torrent->value_if(TR_KEY_id); + ASSERT_TRUE(first_torrent_id); + EXPECT_EQ(1, *first_torrent_id); + + // cleanup + tr_torrentRemove(tor, false, nullptr, nullptr, nullptr, nullptr); +} + } // namespace libtransmission::test diff --git a/utils/remote.cc b/utils/remote.cc index 1ae2e45d2..4b76565a1 100644 --- a/utils/remote.cc +++ b/utils/remote.cc @@ -2525,7 +2525,7 @@ tr_variant::Map& ensure_sset(tr_variant& sset) { sset = tr_variant::Map{ 3 }; map = sset.get_if(); - map->try_emplace(TR_KEY_method, tr_variant::unmanaged_string("session-set"sv)); + map->try_emplace(TR_KEY_method, tr_variant::unmanaged_string(tr_quark_get_string_view(TR_KEY_session_set_kebab))); } auto* args = map->find_if(TR_KEY_arguments); @@ -2561,7 +2561,7 @@ tr_variant::Map& ensure_tadd(tr_variant& tadd) { tadd = tr_variant::Map{ 3 }; map = tadd.get_if(); - map->try_emplace(TR_KEY_method, tr_variant::unmanaged_string("torrent-add"sv)); + map->try_emplace(TR_KEY_method, tr_variant::unmanaged_string(tr_quark_get_string_view(TR_KEY_torrent_add_kebab))); map->try_emplace(TR_KEY_tag, TAG_TORRENT_ADD); } @@ -2808,7 +2808,7 @@ int process_args(char const* rpcurl, int argc, char const* const* argv, RemoteCo } args.insert_or_assign(TR_KEY_fields, std::move(fields)); - map.insert_or_assign(TR_KEY_method, tr_variant::unmanaged_string("torrent-get"sv)); + fields.emplace_back(tr_variant::unmanaged_string(tr_quark_get_string_view(TR_KEY_torrent_get_kebab))); map.insert_or_assign(TR_KEY_arguments, std::move(args)); auto top = tr_variant{ std::move(map) }; status |= flush(rpcurl, &top, config); @@ -3240,7 +3240,7 @@ int process_args(char const* rpcurl, int argc, char const* const* argv, RemoteCo args.try_emplace(TR_KEY_delete_local_data_kebab, c == 840); add_id_arg(args, config); - map.try_emplace(TR_KEY_method, tr_variant::unmanaged_string("torrent-remove"sv)); + map.try_emplace(TR_KEY_method, tr_variant::unmanaged_string(tr_quark_get_string_view(TR_KEY_torrent_remove_kebab))); map.try_emplace(TR_KEY_arguments, std::move(args)); auto top = tr_variant{ std::move(map) }; @@ -3263,7 +3263,8 @@ int process_args(char const* rpcurl, int argc, char const* const* argv, RemoteCo auto map = tr_variant::Map{ 2 }; auto args = tr_variant::Map{ 1 }; add_id_arg(args, config); - map.try_emplace(TR_KEY_method, tr_variant::unmanaged_string(is_stop ? "torrent-stop"sv : "torrent-start"sv)); + auto const key = is_stop ? TR_KEY_torrent_stop_kebab : TR_KEY_torrent_start_kebab; + map.try_emplace(TR_KEY_method, tr_variant::unmanaged_string(tr_quark_get_string_view(key))); map.try_emplace(TR_KEY_arguments, std::move(args)); auto top = tr_variant{ std::move(map) }; @@ -3277,12 +3278,12 @@ int process_args(char const* rpcurl, int argc, char const* const* argv, RemoteCo switch (option) { case 'v': - return "torrent-verify"sv; + return TR_KEY_torrent_verify_kebab; case 600: - return "torrent-reannounce"sv; + return TR_KEY_torrent_reannounce_kebab; default: TR_ASSERT_MSG(false, "unhandled value"); - return ""sv; + return TR_KEY_NONE; } }; @@ -3300,7 +3301,8 @@ int process_args(char const* rpcurl, int argc, char const* const* argv, RemoteCo auto map = tr_variant::Map{ 2 }; auto args = tr_variant::Map{ 1 }; add_id_arg(args, config); - map.try_emplace(TR_KEY_method, tr_variant::unmanaged_string(Method(c))); + auto const key = Method(c); + map.try_emplace(TR_KEY_method, tr_variant::unmanaged_string(tr_quark_get_string_view(key))); map.try_emplace(TR_KEY_arguments, std::move(args)); auto top = tr_variant{ std::move(map) }; status |= flush(rpcurl, &top, config); @@ -3312,7 +3314,9 @@ int process_args(char const* rpcurl, int argc, char const* const* argv, RemoteCo case 920: /* session-info */ { auto map = tr_variant::Map{ 2 }; - map.try_emplace(TR_KEY_method, tr_variant::unmanaged_string("session-get"sv)); + map.try_emplace( + TR_KEY_method, + tr_variant::unmanaged_string(tr_quark_get_string_view(TR_KEY_session_get_kebab))); map.try_emplace(TR_KEY_tag, TAG_SESSION); auto top = tr_variant{ std::move(map) }; @@ -3330,7 +3334,9 @@ int process_args(char const* rpcurl, int argc, char const* const* argv, RemoteCo case 850: { auto map = tr_variant::Map{ 1 }; - map.try_emplace(TR_KEY_method, tr_variant::unmanaged_string("session-close"sv)); + map.try_emplace( + TR_KEY_method, + tr_variant::unmanaged_string(tr_quark_get_string_view(TR_KEY_session_close_kebab))); auto top = tr_variant{ std::move(map) }; status |= flush(rpcurl, &top, config); } @@ -3339,7 +3345,9 @@ int process_args(char const* rpcurl, int argc, char const* const* argv, RemoteCo case 963: { auto map = tr_variant::Map{ 1 }; - map.try_emplace(TR_KEY_method, tr_variant::unmanaged_string("blocklist-update"sv)); + map.try_emplace( + TR_KEY_method, + tr_variant::unmanaged_string(tr_quark_get_string_view(TR_KEY_blocklist_update_kebab))); auto top = tr_variant{ std::move(map) }; status |= flush(rpcurl, &top, config); } @@ -3348,7 +3356,9 @@ int process_args(char const* rpcurl, int argc, char const* const* argv, RemoteCo case 921: { auto map = tr_variant::Map{ 2 }; - map.try_emplace(TR_KEY_method, tr_variant::unmanaged_string("session-stats"sv)); + map.try_emplace( + TR_KEY_method, + tr_variant::unmanaged_string(tr_quark_get_string_view(TR_KEY_session_stats_kebab))); map.try_emplace(TR_KEY_tag, TAG_STATS); auto top = tr_variant{ std::move(map) }; status |= flush(rpcurl, &top, config); @@ -3358,7 +3368,9 @@ int process_args(char const* rpcurl, int argc, char const* const* argv, RemoteCo case 962: { auto map = tr_variant::Map{ 2 }; - map.try_emplace(TR_KEY_method, tr_variant::unmanaged_string("port-test"sv)); + map.try_emplace( + TR_KEY_method, + tr_variant::unmanaged_string(tr_quark_get_string_view(TR_KEY_port_test_kebab))); map.try_emplace(TR_KEY_tag, TAG_PORTTEST); auto top = tr_variant{ std::move(map) }; status |= flush(rpcurl, &top, config); @@ -3417,7 +3429,9 @@ int process_args(char const* rpcurl, int argc, char const* const* argv, RemoteCo args.try_emplace(TR_KEY_path, rename_from); args.try_emplace(TR_KEY_name, optarg_sv); add_id_arg(args, config); - map.try_emplace(TR_KEY_method, tr_variant::unmanaged_string("torrent-rename-path"sv)); + map.try_emplace( + TR_KEY_method, + tr_variant::unmanaged_string(tr_quark_get_string_view(TR_KEY_torrent_rename_path_kebab))); map.try_emplace(TR_KEY_arguments, std::move(args)); auto top = tr_variant{ std::move(map) }; status |= flush(rpcurl, &top, config); @@ -3432,7 +3446,9 @@ int process_args(char const* rpcurl, int argc, char const* const* argv, RemoteCo case 732: { auto map = tr_variant::Map{ 2 }; - map.try_emplace(TR_KEY_method, tr_variant::unmanaged_string("group-get"sv)); + map.try_emplace( + TR_KEY_method, + tr_variant::unmanaged_string(tr_quark_get_string_view(TR_KEY_group_get_kebab))); map.try_emplace(TR_KEY_tag, TAG_GROUPS); auto top = tr_variant{ std::move(map) }; status |= flush(rpcurl, &top, config);