From a33ecb5c7f41718396a3e32435e1174f7eff495d Mon Sep 17 00:00:00 2001 From: Miuna <809711+Mishura4@users.noreply.github.com> Date: Wed, 19 Jul 2023 03:28:53 -0400 Subject: [PATCH] feat: coroutines, still experimental but useable (#724) --- .../classes/Generator/CoroGenerator.php | 18 +- docpages/04_advanced_reference.md | 1 + docpages/advanced_reference/coroutines.md | 228 +++++ include/dpp/cluster.h | 10 + include/dpp/cluster_coro_calls.h | 740 +++++------------ include/dpp/coro.h | 699 ++++++++++++++-- include/dpp/dispatcher.h | 104 +++ include/dpp/event_router.h | 59 +- library/CMakeLists.txt | 13 +- src/dpp/cluster/timer.cpp | 11 + src/dpp/cluster_coro_calls.cpp | 782 ++++++++++++++++++ src/dpp/dispatcher.cpp | 51 ++ 12 files changed, 2054 insertions(+), 662 deletions(-) create mode 100644 docpages/advanced_reference/coroutines.md create mode 100644 src/dpp/cluster_coro_calls.cpp diff --git a/buildtools/classes/Generator/CoroGenerator.php b/buildtools/classes/Generator/CoroGenerator.php index e3ce67bb8a..faf0d41c72 100644 --- a/buildtools/classes/Generator/CoroGenerator.php +++ b/buildtools/classes/Generator/CoroGenerator.php @@ -54,6 +54,7 @@ public function generateHeaderStart(): string public function generateCppStart(): string { return $this->generateHeaderStart() . << #include @@ -80,6 +81,7 @@ public function checkForChanges(): bool } echo "-- Autogenerating include/dpp/cluster_coro_calls.h\n"; + echo "-- Autogenerating src/dpp/cluster_coro_calls.cpp\n"; return true; } @@ -88,11 +90,7 @@ public function checkForChanges(): bool */ public function generateHeaderDef(string $returnType, string $currentFunction, string $parameters, string $noDefaults, string $parameterTypes, string $parameterNames): string { - $parameterNames = preg_replace('/^, /', '', $parameterNames); - if (!empty($parameterNames)) { - $parameterNames .= ', '; - } - return "auto inline co_{$currentFunction}($noDefaults) {\n\treturn dpp::awaitable(this, [&] (auto cc) { this->$currentFunction({$parameterNames}cc); }); \n}\n\n"; + return "awaitable co_{$currentFunction}($parameters);\n\n"; } /** @@ -100,7 +98,7 @@ public function generateHeaderDef(string $returnType, string $currentFunction, s */ public function generateCppDef(string $returnType, string $currentFunction, string $parameters, string $noDefaults, string $parameterTypes, string $parameterNames): string { - return ''; + return "awaitable cluster::co_${currentFunction}($noDefaults) {\n\treturn {this, static_cast(&cluster::$currentFunction)$parameterNames};\n}\n\n"; } /** @@ -116,7 +114,7 @@ public function getCommentArray(): array */ public function saveHeader(string $content): void { - $content .= "auto inline co_request(const std::string &url, http_method method, const std::string &postdata = \"\", const std::string &mimetype = \"text/plain\", const std::multimap &headers = {}) {\n\treturn dpp::awaitable(this, [&] (auto cc) { this->request(url, method, cc, mimetype, headers); }); \n}\n\n"; + $content .= "awaitable co_request(const std::string &url, http_method method, const std::string &postdata = \"\", const std::string &mimetype = \"text/plain\", const std::multimap &headers = {});\n\n"; file_put_contents('include/dpp/cluster_coro_calls.h', $content); } @@ -125,7 +123,11 @@ public function saveHeader(string $content): void */ public function saveCpp(string $cppcontent): void { - /* No cpp file to save, code is all inline */ + $cppcontent .= "dpp::awaitable dpp::cluster::co_request(const std::string &url, http_method method, const std::string &postdata, const std::string &mimetype, const std::multimap &headers) {\n\treturn awaitable{[&](auto &&cc) { this->request(url, method, cc, postdata, mimetype, headers); }};\n} + +#endif +"; + file_put_contents('src/dpp/cluster_coro_calls.cpp', $cppcontent); } } diff --git a/docpages/04_advanced_reference.md b/docpages/04_advanced_reference.md index 1ad0dea434..dfb8f08383 100644 --- a/docpages/04_advanced_reference.md +++ b/docpages/04_advanced_reference.md @@ -5,3 +5,4 @@ * \subpage coding-standards "Coding Style Standards" * \subpage unit-tests "Unit Tests" * \subpage lambdas-and-locals "Ownership of local variables and safely transferring into a lambda" +* \subpage coroutines "Advanced commands with coroutines" diff --git a/docpages/advanced_reference/coroutines.md b/docpages/advanced_reference/coroutines.md new file mode 100644 index 0000000000..23b1950277 --- /dev/null +++ b/docpages/advanced_reference/coroutines.md @@ -0,0 +1,228 @@ +\page coroutines Advanced commands with coroutines + +\warning D++ Coroutines are a very new feature and are currently only supported by D++ on g++ 13.1 and MSVC 19.37, and the CMake option DPP_CORO must be enabled. They are experimental and may have bugs or even crashes, pease report any to [GitHub Issues](https://github.com/brainboxdotcc/DPP/issues) or to our [Discord Server](https://discord.gg/dpp). + +### What is a coroutine? + +Introduced in C++20, coroutines are the solution to the impracticality of callbacks. In short, a coroutine is a function that can be paused and resumed later : they are an extremely powerful alternative to callbacks for asynchronous APIs in particular, as the function can be paused when waiting for an API response, and resumed when it is received. + +Let's revisit [attaching a downloaded file](/attach-file.html), but this time with a coroutine : + + +~~~~~~~~~~~~~~~{.cpp} +#include + +int main() { + dpp::cluster bot("token", dpp::i_default_intents | dpp::i_message_content); + + bot.on_log(dpp::utility::cout_logger()); + + /* Message handler to look for a command called !file */ + /* Make note of passing the event by value, this is important (explained below) */ + bot.on_message_create.co_attach([](dpp::message_create_t event) -> dpp::task { + dpp::cluster *cluster = event.from->creator; + + if (event.msg.content == "!file") { + // request an image and co_await the response + dpp::http_request_completion_t result = co_await cluster->co_request("https://dpp.dev/DPP-Logo.png", dpp::m_get); + + // create a message + dpp::message msg(event.msg.channel_id, "This is my new attachment:"); + + // attach the image on success + if (result.status == 200) { + msg.add_file("logo.png", result.body); + } + + // send the message + cluster->message_create(msg); + } + }); + + bot.start(dpp::st_wait); + return 0; +} +~~~~~~~~~~~~~~~ + + +Coroutines can make commands simpler by eliminating callbacks, which can be very handy in the case of complex commands that rely on a lot of different data or steps. + +In order to be a coroutine, a function has to return a special type with special functions; D++ offers `dpp::task` which is designed to work seamlessly with asynchronous calls through `dpp::awaitable`, which all the functions starting with `co_` such as `dpp::cluster::co_message_create` return. To turn a function into a coroutine, simply make it return `dpp::task` as seen in the example at line 10. + +When an awaitable is `co_await`-ed, the coroutine suspends (pauses) and returns back to its caller : in other words, the program is free to go and do other things while the data is being retrieved, D++ will resume your coroutine when it has the data you need which will be returned from the `co_await` expression. + +Inside of a `dpp::task`, someone can use `co_return` in place of `return`. + +\attention As a rule of thumb when making dpp::task objects and in general coroutines, always prefer taking parameters by value and avoid capture : this may be confusing but a coroutine is *not* the lambda creating it, the captures are not bound to it and the code isn't ran inside the lambda. The lambda that returns a dpp::task simply returns a task object containing the code, which goes on to live on its own, separate from the lambda. +Similarly, with reference parameters, the object they reference to might be destroyed while the coroutine is suspended and resumed in another thread, which is why you want to pass by value. See also [lambdas and locals](/lambdas-and-locals.html) except this also applies to parameters in the case of coroutines. + +### Several steps in one + +\note The next example assumes you are already familiar with how to use [slash commands](/firstbot.html), [parameters](/slashcommands.html), and [sending files through a command](/discord-application-command-file-upload.html). + +Coroutines allow to write asynchronous functions almost as if they were executed synchronously, without the need for callbacks, which can save a lot of pain with keeping track of different data. Here is another example of what is made easier with coroutines : an "addemoji" command taking a file and a name as a parameter. This means downloading the emoji, submitting it to Discord, and finally replying, with some error handling along the way. + +~~~~~~~~~~{.cpp} +#include + +int main() { + dpp::cluster bot("token", dpp::i_default_intents | dpp::i_message_content); + + bot.on_log(dpp::utility::cout_logger()); + + bot.on_slashcommand.co_attach([](dpp::slashcommand_t event) -> dpp::task { + if (event.command.get_command_name() == "addemoji") { + dpp::cluster *cluster = event.from->creator; + // Retrieve parameter values + dpp::snowflake file_id = std::get(event.get_parameter("file")); + std::string emoji_name = std::get(event.get_parameter("name")); + + // Get the attachment from the resolved list + const dpp::attachment &attachment = event.command.get_resolved_attachment(file_id); + + // For simplicity for this example we only support PNG + if (attachment.content_type != "image/png") { + // While event.co_reply is available, we can just use event.reply, as we will exit the command anyway and don't need to wait on the result + event.reply("Error: type " + attachment.content_type + " not supported"); + co_return; + } + // Send a " is thinking..." message, to wait on later so we can edit + dpp::awaitable thinking = event.co_thinking(false); + + // Download and co_await the result + dpp::http_request_completion_t response = co_await cluster->co_request(attachment.url, dpp::m_get); + + if (response.status != 200) { // Page didn't send the image + co_await thinking; // Wait for the thinking response to arrive so we can edit + event.edit_response("Error: could not download the attachment"); + } + else { + // Load the image data in a dpp::emoji + dpp::emoji emoji(emoji_name); + emoji.load_image(response.body, dpp::image_type::i_png); + + // Create the emoji and co_await the response + dpp::confirmation_callback_t confirmation = co_await cluster->co_guild_emoji_create(event.command.guild_id, emoji); + + co_await thinking; // Wait for the thinking response to arrive so we can edit + if (confirmation.is_error()) + event.edit_response("Error: could not add emoji: " + confirmation.get_error().message); + else // Success + event.edit_response("Successfully added " + confirmation.get().get_mention()); // Show the new emoji + } + } + }); + + bot.on_ready([&bot](const dpp::ready_t & event) { + if (dpp::run_once()) { + dpp::slashcommand command("addemoji", "Add an emoji", bot.me.id); + + // Add file and name as required parameters + command.add_option(dpp::command_option(dpp::co_attachment, "file", "Select an image", true)); + command.add_option(dpp::command_option(dpp::co_string, "name", "Name of the emoji to add", true)); + + bot.global_command_create(command); + } + }); + + bot.start(dpp::st_wait); +} +~~~~~~~~~~ + +### I heard you liked tasks + +\note This next example is fairly advanced and makes uses of many of both C++ and D++'s advanced features. + +Lastly, `dpp::task` takes its return type as a template parameter, which allows you to use tasks inside tasks and return a result from them. + +Here is an example of a command making use of that to retrieve the avatar of a specified user, or if missing, the sender : + +~~~~~~~~~~{.cpp} +#include + +int main() { + dpp::cluster bot("token", dpp::i_default_intents | dpp::i_message_content); + + bot.on_log(dpp::utility::cout_logger()); + + bot.on_slashcommand.co_attach([](dpp::slashcommand_t event) -> dpp::task{ + if (event.command.get_command_name() == "avatar") { + // Make a nested coroutine to fetch the guild member requested, that returns it as an optional + constexpr auto resolve_member = [](const dpp::slashcommand_t &event) -> dpp::task> { + const dpp::command_value &user_param = event.get_parameter("user"); + dpp::snowflake user_id; + + if (std::holds_alternative(user_param)) + user_id = event.command.usr.id; // Parameter is empty so user is sender + else if (std::holds_alternative(user_param)) + user_id = std::get(user_param); // Parameter has a user + + // If we have the guild member in the command's resolved data, return it + const auto &member_map = event.command.resolved.members; + if (auto member = member_map.find(user_id); member != member_map.end()) + co_return member->second; + + // Try looking in guild cache + dpp::guild *guild = dpp::find_guild(event.command.guild_id); + if (guild) { + // Look in guild's member cache + if (auto member = guild->members.find(user_id); member != guild->members.end()) { + co_return member->second; + } + } + + // Finally if everything else failed, request API + dpp::confirmation_callback_t confirmation = co_await event.from->creator->co_guild_get_member(event.command.guild_id, user_id); + if (confirmation.is_error()) + co_return std::nullopt; // Member not found, return empty + else + co_return confirmation.get(); + }; + + // Send a " is thinking..." message, to wait on later so we can edit + dpp::awaitable thinking = event.co_thinking(false); + + // Call our coroutine defined above to retrieve the member requested + std::optional member = co_await resolve_member(event); + + if (!member.has_value()) { + // Wait for the thinking response to arrive to make sure we can edit + co_await thinking; + event.edit_original_response(dpp::message{"User not found in this server!"}); + co_return; + } + + std::string avatar_url = member->get_avatar_url(512); + if (avatar_url.empty()) { // Member does not have a custom avatar for this server, get their user avatar + dpp::confirmation_callback_t confirmation = co_await event.from->creator->co_user_get_cached(member->user_id); + + if (confirmation.is_error()) + { + // Wait for the thinking response to arrive to make sure we can edit + co_await thinking; + event.edit_original_response(dpp::message{"User not found!"}); + co_return; + } + avatar_url = confirmation.get().get_avatar_url(512); + } + + // Wait for the thinking response to arrive to make sure we can edit + co_await thinking; + event.edit_original_response(dpp::message{avatar_url}); + } + }); + + + bot.on_ready([&bot](const dpp::ready_t & event) { + if (dpp::run_once()) { + dpp::slashcommand command("avatar", "Get your or another user's avatar image", bot.me.id); + + command.add_option(dpp::command_option(dpp::co_user, "user", "User to fetch the avatar from")); + + bot.global_command_create(command); + } + }); + + bot.start(dpp::st_wait); +} +~~~~~~~~~~ \ No newline at end of file diff --git a/include/dpp/cluster.h b/include/dpp/cluster.h index ce5601aacc..b9c64bcd8c 100644 --- a/include/dpp/cluster.h +++ b/include/dpp/cluster.h @@ -348,6 +348,16 @@ class DPP_EXPORT cluster { */ bool stop_timer(timer t); +#ifdef DPP_CORO + /** + * @brief Start a one-time timer. Use the co_await keyword on its return value to suspend the coroutine until the timer ends + * + * @param seconds How long to run the timer for + * @return awaitable co_await-able object holding the timer_handle + */ + awaitable co_timer(uint64_t seconds); +#endif + /** * @brief Get the dm channel for a user id * diff --git a/include/dpp/cluster_coro_calls.h b/include/dpp/cluster_coro_calls.h index a49cb3cc66..0083de91f3 100644 --- a/include/dpp/cluster_coro_calls.h +++ b/include/dpp/cluster_coro_calls.h @@ -38,9 +38,7 @@ * @return slashcommand_map returned object on completion * \memberof dpp::cluster */ -auto inline co_global_bulk_command_create(const std::vector &commands) { - return dpp::awaitable(this, [&] (auto cc) { this->global_bulk_command_create(commands, cc); }); -} +awaitable co_global_bulk_command_create(const std::vector &commands); /** * @brief Create a global slash command (a bot can have a maximum of 100 of these). @@ -51,9 +49,7 @@ auto inline co_global_bulk_command_create(const std::vector &comma * @return slashcommand returned object on completion * \memberof dpp::cluster */ -auto inline co_global_command_create(const slashcommand &s) { - return dpp::awaitable(this, [&] (auto cc) { this->global_command_create(s, cc); }); -} +awaitable co_global_command_create(const slashcommand &s); /** * @brief Get a global slash command @@ -64,9 +60,7 @@ auto inline co_global_command_create(const slashcommand &s) { * @return slashcommand returned object on completion * \memberof dpp::cluster */ -auto inline co_global_command_get(snowflake id) { - return dpp::awaitable(this, [&] (auto cc) { this->global_command_get(id, cc); }); -} +awaitable co_global_command_get(snowflake id); /** * @brief Delete a global slash command (a bot can have a maximum of 100 of these) @@ -77,9 +71,7 @@ auto inline co_global_command_get(snowflake id) { * @return confirmation returned object on completion * \memberof dpp::cluster */ -auto inline co_global_command_delete(snowflake id) { - return dpp::awaitable(this, [&] (auto cc) { this->global_command_delete(id, cc); }); -} +awaitable co_global_command_delete(snowflake id); /** * @brief Edit a global slash command (a bot can have a maximum of 100 of these) @@ -90,9 +82,7 @@ auto inline co_global_command_delete(snowflake id) { * @return confirmation returned object on completion * \memberof dpp::cluster */ -auto inline co_global_command_edit(const slashcommand &s) { - return dpp::awaitable(this, [&] (auto cc) { this->global_command_edit(s, cc); }); -} +awaitable co_global_command_edit(const slashcommand &s); /** * @brief Get the application's global slash commands @@ -102,9 +92,7 @@ auto inline co_global_command_edit(const slashcommand &s) { * @return slashcommand_map returned object on completion * \memberof dpp::cluster */ -auto inline co_global_commands_get() { - return dpp::awaitable(this, [&] (auto cc) { this->global_commands_get(cc); }); -} +awaitable co_global_commands_get(); /** * @brief Create/overwrite guild slash commands. @@ -118,9 +106,7 @@ auto inline co_global_commands_get() { * @return slashcommand_map returned object on completion * \memberof dpp::cluster */ -auto inline co_guild_bulk_command_create(const std::vector &commands, snowflake guild_id) { - return dpp::awaitable(this, [&] (auto cc) { this->guild_bulk_command_create(commands, guild_id, cc); }); -} +awaitable co_guild_bulk_command_create(const std::vector &commands, snowflake guild_id); /** * @brief Get all slash command permissions of a guild @@ -131,9 +117,7 @@ auto inline co_guild_bulk_command_create(const std::vector &comman * @return guild_command_permissions_map returned object on completion * \memberof dpp::cluster */ -auto inline co_guild_commands_get_permissions(snowflake guild_id) { - return dpp::awaitable(this, [&] (auto cc) { this->guild_commands_get_permissions(guild_id, cc); }); -} +awaitable co_guild_commands_get_permissions(snowflake guild_id); /** * @brief Edit/Overwrite the permissions of all existing slash commands in a guild @@ -149,9 +133,7 @@ auto inline co_guild_commands_get_permissions(snowflake guild_id) { * @deprecated This has been disabled with updates to Permissions v2. You can use guild_command_edit_permissions instead * \memberof dpp::cluster */ -auto inline co_guild_bulk_command_edit_permissions(const std::vector &commands, snowflake guild_id) { - return dpp::awaitable(this, [&] (auto cc) { this->guild_bulk_command_edit_permissions(commands, guild_id, cc); }); -} +awaitable co_guild_bulk_command_edit_permissions(const std::vector &commands, snowflake guild_id); /** * @brief Create a slash command local to a guild @@ -164,9 +146,7 @@ auto inline co_guild_bulk_command_edit_permissions(const std::vectorguild_command_create(s, guild_id, cc); }); -} +awaitable co_guild_command_create(const slashcommand &s, snowflake guild_id); /** * @brief Delete a slash command local to a guild @@ -178,9 +158,7 @@ auto inline co_guild_command_create(const slashcommand &s, snowflake guild_id) { * @return confirmation returned object on completion * \memberof dpp::cluster */ -auto inline co_guild_command_delete(snowflake id, snowflake guild_id) { - return dpp::awaitable(this, [&] (auto cc) { this->guild_command_delete(id, guild_id, cc); }); -} +awaitable co_guild_command_delete(snowflake id, snowflake guild_id); /** * @brief Edit slash command permissions of a guild @@ -193,9 +171,7 @@ auto inline co_guild_command_delete(snowflake id, snowflake guild_id) { * @return confirmation returned object on completion * \memberof dpp::cluster */ -auto inline co_guild_command_edit_permissions(const slashcommand &s, snowflake guild_id) { - return dpp::awaitable(this, [&] (auto cc) { this->guild_command_edit_permissions(s, guild_id, cc); }); -} +awaitable co_guild_command_edit_permissions(const slashcommand &s, snowflake guild_id); /** * @brief Get a slash command of a guild @@ -208,9 +184,7 @@ auto inline co_guild_command_edit_permissions(const slashcommand &s, snowflake g * @return slashcommand returned object on completion * \memberof dpp::cluster */ -auto inline co_guild_command_get(snowflake id, snowflake guild_id) { - return dpp::awaitable(this, [&] (auto cc) { this->guild_command_get(id, guild_id, cc); }); -} +awaitable co_guild_command_get(snowflake id, snowflake guild_id); /** * @brief Get the permissions for a slash command of a guild @@ -222,9 +196,7 @@ auto inline co_guild_command_get(snowflake id, snowflake guild_id) { * @return guild_command_permissions returned object on completion * \memberof dpp::cluster */ -auto inline co_guild_command_get_permissions(snowflake id, snowflake guild_id) { - return dpp::awaitable(this, [&] (auto cc) { this->guild_command_get_permissions(id, guild_id, cc); }); -} +awaitable co_guild_command_get_permissions(snowflake id, snowflake guild_id); /** * @brief Edit a slash command local to a guild @@ -236,9 +208,7 @@ auto inline co_guild_command_get_permissions(snowflake id, snowflake guild_id) { * @return confirmation returned object on completion * \memberof dpp::cluster */ -auto inline co_guild_command_edit(const slashcommand &s, snowflake guild_id) { - return dpp::awaitable(this, [&] (auto cc) { this->guild_command_edit(s, guild_id, cc); }); -} +awaitable co_guild_command_edit(const slashcommand &s, snowflake guild_id); /** * @brief Get the application's slash commands for a guild @@ -250,9 +220,7 @@ auto inline co_guild_command_edit(const slashcommand &s, snowflake guild_id) { * @return slashcommand_map returned object on completion * \memberof dpp::cluster */ -auto inline co_guild_commands_get(snowflake guild_id) { - return dpp::awaitable(this, [&] (auto cc) { this->guild_commands_get(guild_id, cc); }); -} +awaitable co_guild_commands_get(snowflake guild_id); /** * @brief Respond to a slash command @@ -265,9 +233,7 @@ auto inline co_guild_commands_get(snowflake guild_id) { * @return confirmation returned object on completion * \memberof dpp::cluster */ -auto inline co_interaction_response_create(snowflake interaction_id, const std::string &token, const interaction_response &r) { - return dpp::awaitable(this, [&] (auto cc) { this->interaction_response_create(interaction_id, token, r, cc); }); -} +awaitable co_interaction_response_create(snowflake interaction_id, const std::string &token, const interaction_response &r); /** * @brief Edit response to a slash command @@ -279,9 +245,7 @@ auto inline co_interaction_response_create(snowflake interaction_id, const std:: * @return confirmation returned object on completion * \memberof dpp::cluster */ -auto inline co_interaction_response_edit(const std::string &token, const message &m) { - return dpp::awaitable(this, [&] (auto cc) { this->interaction_response_edit(token, m, cc); }); -} +awaitable co_interaction_response_edit(const std::string &token, const message &m); /** * @brief Get the original response to a slash command @@ -292,9 +256,7 @@ auto inline co_interaction_response_edit(const std::string &token, const message * @return message returned object on completion * \memberof dpp::cluster */ -auto inline co_interaction_response_get_original(const std::string &token) { - return dpp::awaitable(this, [&] (auto cc) { this->interaction_response_get_original(token, cc); }); -} +awaitable co_interaction_response_get_original(const std::string &token); /** * @brief Create a followup message to a slash command @@ -306,9 +268,7 @@ auto inline co_interaction_response_get_original(const std::string &token) { * @return confirmation returned object on completion * \memberof dpp::cluster */ -auto inline co_interaction_followup_create(const std::string &token, const message &m) { - return dpp::awaitable(this, [&] (auto cc) { this->interaction_followup_create(token, m, cc); }); -} +awaitable co_interaction_followup_create(const std::string &token, const message &m); /** * @brief Edit original followup message to a slash command @@ -321,9 +281,7 @@ auto inline co_interaction_followup_create(const std::string &token, const messa * @return confirmation returned object on completion * \memberof dpp::cluster */ -auto inline co_interaction_followup_edit_original(const std::string &token, const message &m) { - return dpp::awaitable(this, [&] (auto cc) { this->interaction_followup_edit_original(token, m, cc); }); -} +awaitable co_interaction_followup_edit_original(const std::string &token, const message &m); /** * @brief Delete the initial interaction response @@ -334,9 +292,7 @@ auto inline co_interaction_followup_edit_original(const std::string &token, cons * @return confirmation returned object on completion * \memberof dpp::cluster */ -auto inline co_interaction_followup_delete(const std::string &token) { - return dpp::awaitable(this, [&] (auto cc) { this->interaction_followup_delete(token, cc); }); -} +awaitable co_interaction_followup_delete(const std::string &token); /** * @brief Edit followup message to a slash command @@ -349,9 +305,7 @@ auto inline co_interaction_followup_delete(const std::string &token) { * @return confirmation returned object on completion * \memberof dpp::cluster */ -auto inline co_interaction_followup_edit(const std::string &token, const message &m) { - return dpp::awaitable(this, [&] (auto cc) { this->interaction_followup_edit(token, m, cc); }); -} +awaitable co_interaction_followup_edit(const std::string &token, const message &m); /** * @brief Get the followup message to a slash command @@ -363,9 +317,7 @@ auto inline co_interaction_followup_edit(const std::string &token, const message * @return message returned object on completion * \memberof dpp::cluster */ -auto inline co_interaction_followup_get(const std::string &token, snowflake message_id) { - return dpp::awaitable(this, [&] (auto cc) { this->interaction_followup_get(token, message_id, cc); }); -} +awaitable co_interaction_followup_get(const std::string &token, snowflake message_id); /** * @brief Get the original followup message to a slash command @@ -377,9 +329,7 @@ auto inline co_interaction_followup_get(const std::string &token, snowflake mess * @return message returned object on completion * \memberof dpp::cluster */ -auto inline co_interaction_followup_get_original(const std::string &token) { - return dpp::awaitable(this, [&] (auto cc) { this->interaction_followup_get_original(token, cc); }); -} +awaitable co_interaction_followup_get_original(const std::string &token); /** * @brief Get all auto moderation rules for a guild @@ -388,9 +338,7 @@ auto inline co_interaction_followup_get_original(const std::string &token) { * @return automod_rule_map returned object on completion * \memberof dpp::cluster */ -auto inline co_automod_rules_get(snowflake guild_id) { - return dpp::awaitable(this, [&] (auto cc) { this->automod_rules_get(guild_id, cc); }); -} +awaitable co_automod_rules_get(snowflake guild_id); /** * @brief Get a single auto moderation rule @@ -400,9 +348,7 @@ auto inline co_automod_rules_get(snowflake guild_id) { * @return automod_rule returned object on completion * \memberof dpp::cluster */ -auto inline co_automod_rule_get(snowflake guild_id, snowflake rule_id) { - return dpp::awaitable(this, [&] (auto cc) { this->automod_rule_get(guild_id, rule_id, cc); }); -} +awaitable co_automod_rule_get(snowflake guild_id, snowflake rule_id); /** * @brief Create an auto moderation rule @@ -412,9 +358,7 @@ auto inline co_automod_rule_get(snowflake guild_id, snowflake rule_id) { * @return automod_rule returned object on completion * \memberof dpp::cluster */ -auto inline co_automod_rule_create(snowflake guild_id, const automod_rule& r) { - return dpp::awaitable(this, [&] (auto cc) { this->automod_rule_create(guild_id, r, cc); }); -} +awaitable co_automod_rule_create(snowflake guild_id, const automod_rule& r); /** * @brief Edit an auto moderation rule @@ -424,9 +368,7 @@ auto inline co_automod_rule_create(snowflake guild_id, const automod_rule& r) { * @return automod_rule returned object on completion * \memberof dpp::cluster */ -auto inline co_automod_rule_edit(snowflake guild_id, const automod_rule& r) { - return dpp::awaitable(this, [&] (auto cc) { this->automod_rule_edit(guild_id, r, cc); }); -} +awaitable co_automod_rule_edit(snowflake guild_id, const automod_rule& r); /** * @brief Delete an auto moderation rule @@ -436,9 +378,7 @@ auto inline co_automod_rule_edit(snowflake guild_id, const automod_rule& r) { * @return confirmation returned object on completion * \memberof dpp::cluster */ -auto inline co_automod_rule_delete(snowflake guild_id, snowflake rule_id) { - return dpp::awaitable(this, [&] (auto cc) { this->automod_rule_delete(guild_id, rule_id, cc); }); -} +awaitable co_automod_rule_delete(snowflake guild_id, snowflake rule_id); /** * @brief Create a channel @@ -456,9 +396,7 @@ auto inline co_automod_rule_delete(snowflake guild_id, snowflake rule_id) { * @return channel returned object on completion * \memberof dpp::cluster */ -auto inline co_channel_create(const class channel &c) { - return dpp::awaitable(this, [&] (auto cc) { this->channel_create(c, cc); }); -} +awaitable co_channel_create(const class channel &c); /** * @brief Remove a permission from a channel @@ -470,9 +408,7 @@ auto inline co_channel_create(const class channel &c) { * @return confirmation returned object on completion * \memberof dpp::cluster */ -auto inline co_channel_delete_permission(const class channel &c, snowflake overwrite_id) { - return dpp::awaitable(this, [&] (auto cc) { this->channel_delete_permission(c, overwrite_id, cc); }); -} +awaitable co_channel_delete_permission(const class channel &c, snowflake overwrite_id); /** * @brief Delete a channel @@ -483,9 +419,7 @@ auto inline co_channel_delete_permission(const class channel &c, snowflake overw * @return confirmation returned object on completion * \memberof dpp::cluster */ -auto inline co_channel_delete(snowflake channel_id) { - return dpp::awaitable(this, [&] (auto cc) { this->channel_delete(channel_id, cc); }); -} +awaitable co_channel_delete(snowflake channel_id); /** * @brief Edit a channel's permissions @@ -501,9 +435,7 @@ auto inline co_channel_delete(snowflake channel_id) { * @return confirmation returned object on completion * \memberof dpp::cluster */ -auto inline co_channel_edit_permissions(const class channel &c, const snowflake overwrite_id, const uint64_t allow, const uint64_t deny, const bool member) { - return dpp::awaitable(this, [&] (auto cc) { this->channel_edit_permissions(c, overwrite_id, allow, deny, member, cc); }); -} +awaitable co_channel_edit_permissions(const class channel &c, const snowflake overwrite_id, const uint64_t allow, const uint64_t deny, const bool member); /** * @brief Edit a channel's permissions @@ -519,9 +451,7 @@ auto inline co_channel_edit_permissions(const class channel &c, const snowflake * @return confirmation returned object on completion * \memberof dpp::cluster */ -auto inline co_channel_edit_permissions(const snowflake channel_id, const snowflake overwrite_id, const uint64_t allow, const uint64_t deny, const bool member) { - return dpp::awaitable(this, [&] (auto cc) { this->channel_edit_permissions(channel_id, overwrite_id, allow, deny, member, cc); }); -} +awaitable co_channel_edit_permissions(const snowflake channel_id, const snowflake overwrite_id, const uint64_t allow, const uint64_t deny, const bool member); /** * @brief Edit multiple channels positions @@ -536,9 +466,7 @@ auto inline co_channel_edit_permissions(const snowflake channel_id, const snowfl * @return confirmation returned object on completion * \memberof dpp::cluster */ -auto inline co_channel_edit_positions(const std::vector &c) { - return dpp::awaitable(this, [&] (auto cc) { this->channel_edit_positions(c, cc); }); -} +awaitable co_channel_edit_positions(const std::vector &c); /** * @brief Edit a channel @@ -549,9 +477,7 @@ auto inline co_channel_edit_positions(const std::vector &c) { * @return channel returned object on completion * \memberof dpp::cluster */ -auto inline co_channel_edit(const class channel &c) { - return dpp::awaitable(this, [&] (auto cc) { this->channel_edit(c, cc); }); -} +awaitable co_channel_edit(const class channel &c); /** * @brief Follow an announcement (news) channel @@ -562,9 +488,7 @@ auto inline co_channel_edit(const class channel &c) { * @return confirmation returned object on completion * \memberof dpp::cluster */ -auto inline co_channel_follow_news(const class channel &c, snowflake target_channel_id) { - return dpp::awaitable(this, [&] (auto cc) { this->channel_follow_news(c, target_channel_id, cc); }); -} +awaitable co_channel_follow_news(const class channel &c, snowflake target_channel_id); /** * @brief Get a channel @@ -575,9 +499,7 @@ auto inline co_channel_follow_news(const class channel &c, snowflake target_chan * @return channel returned object on completion * \memberof dpp::cluster */ -auto inline co_channel_get(snowflake c) { - return dpp::awaitable(this, [&] (auto cc) { this->channel_get(c, cc); }); -} +awaitable co_channel_get(snowflake c); /** * @brief Create invite for a channel @@ -589,9 +511,7 @@ auto inline co_channel_get(snowflake c) { * @return invite returned object on completion * \memberof dpp::cluster */ -auto inline co_channel_invite_create(const class channel &c, const class invite &i) { - return dpp::awaitable(this, [&] (auto cc) { this->channel_invite_create(c, i, cc); }); -} +awaitable co_channel_invite_create(const class channel &c, const class invite &i); /** * @brief Get invites for a channel @@ -602,9 +522,7 @@ auto inline co_channel_invite_create(const class channel &c, const class invite * @return invite_map returned object on completion * \memberof dpp::cluster */ -auto inline co_channel_invites_get(const class channel &c) { - return dpp::awaitable(this, [&] (auto cc) { this->channel_invites_get(c, cc); }); -} +awaitable co_channel_invites_get(const class channel &c); /** * @brief Trigger channel typing indicator @@ -614,9 +532,7 @@ auto inline co_channel_invites_get(const class channel &c) { * @return confirmation returned object on completion * \memberof dpp::cluster */ -auto inline co_channel_typing(const class channel &c) { - return dpp::awaitable(this, [&] (auto cc) { this->channel_typing(c, cc); }); -} +awaitable co_channel_typing(const class channel &c); /** * @brief Trigger channel typing indicator @@ -626,9 +542,7 @@ auto inline co_channel_typing(const class channel &c) { * @return confirmation returned object on completion * \memberof dpp::cluster */ -auto inline co_channel_typing(snowflake cid) { - return dpp::awaitable(this, [&] (auto cc) { this->channel_typing(cid, cc); }); -} +awaitable co_channel_typing(snowflake cid); /** * @brief Get all channels for a guild @@ -639,9 +553,7 @@ auto inline co_channel_typing(snowflake cid) { * @return channel_map returned object on completion * \memberof dpp::cluster */ -auto inline co_channels_get(snowflake guild_id) { - return dpp::awaitable(this, [&] (auto cc) { this->channels_get(guild_id, cc); }); -} +awaitable co_channels_get(snowflake guild_id); /** * @brief Create a dm channel @@ -651,9 +563,7 @@ auto inline co_channels_get(snowflake guild_id) { * @return channel returned object on completion * \memberof dpp::cluster */ -auto inline co_create_dm_channel(snowflake user_id) { - return dpp::awaitable(this, [&] (auto cc) { this->create_dm_channel(user_id, cc); }); -} +awaitable co_create_dm_channel(snowflake user_id); /** * @brief Get current user DM channels @@ -661,9 +571,7 @@ auto inline co_create_dm_channel(snowflake user_id) { * @return channel_map returned object on completion * \memberof dpp::cluster */ -auto inline co_current_user_get_dms() { - return dpp::awaitable(this, [&] (auto cc) { this->current_user_get_dms(cc); }); -} +awaitable co_current_user_get_dms(); /** * @brief Create a direct message, also create the channel for the direct message if needed @@ -677,9 +585,7 @@ auto inline co_current_user_get_dms() { * @return message returned object on completion * \memberof dpp::cluster */ -auto inline co_direct_message_create(snowflake user_id, const message &m) { - return dpp::awaitable(this, [&] (auto cc) { this->direct_message_create(user_id, m, cc); }); -} +awaitable co_direct_message_create(snowflake user_id, const message &m); /** * @brief Adds a recipient to a Group DM using their access token @@ -692,9 +598,7 @@ auto inline co_direct_message_create(snowflake user_id, const message &m) { * @return confirmation returned object on completion * \memberof dpp::cluster */ -auto inline co_gdm_add(snowflake channel_id, snowflake user_id, const std::string &access_token, const std::string &nick) { - return dpp::awaitable(this, [&] (auto cc) { this->gdm_add(channel_id, user_id, access_token, nick, cc); }); -} +awaitable co_gdm_add(snowflake channel_id, snowflake user_id, const std::string &access_token, const std::string &nick); /** * @brief Removes a recipient from a Group DM @@ -705,9 +609,7 @@ auto inline co_gdm_add(snowflake channel_id, snowflake user_id, const std::strin * @return confirmation returned object on completion * \memberof dpp::cluster */ -auto inline co_gdm_remove(snowflake channel_id, snowflake user_id) { - return dpp::awaitable(this, [&] (auto cc) { this->gdm_remove(channel_id, user_id, cc); }); -} +awaitable co_gdm_remove(snowflake channel_id, snowflake user_id); /** * @brief Create single emoji. @@ -721,9 +623,7 @@ auto inline co_gdm_remove(snowflake channel_id, snowflake user_id) { * @return emoji returned object on completion * \memberof dpp::cluster */ -auto inline co_guild_emoji_create(snowflake guild_id, const class emoji& newemoji) { - return dpp::awaitable(this, [&] (auto cc) { this->guild_emoji_create(guild_id, newemoji, cc); }); -} +awaitable co_guild_emoji_create(snowflake guild_id, const class emoji& newemoji); /** * @brief Delete a guild emoji @@ -736,9 +636,7 @@ auto inline co_guild_emoji_create(snowflake guild_id, const class emoji& newemoj * @return confirmation returned object on completion * \memberof dpp::cluster */ -auto inline co_guild_emoji_delete(snowflake guild_id, snowflake emoji_id) { - return dpp::awaitable(this, [&] (auto cc) { this->guild_emoji_delete(guild_id, emoji_id, cc); }); -} +awaitable co_guild_emoji_delete(snowflake guild_id, snowflake emoji_id); /** * @brief Edit a single emoji. @@ -752,9 +650,7 @@ auto inline co_guild_emoji_delete(snowflake guild_id, snowflake emoji_id) { * @return emoji returned object on completion * \memberof dpp::cluster */ -auto inline co_guild_emoji_edit(snowflake guild_id, const class emoji& newemoji) { - return dpp::awaitable(this, [&] (auto cc) { this->guild_emoji_edit(guild_id, newemoji, cc); }); -} +awaitable co_guild_emoji_edit(snowflake guild_id, const class emoji& newemoji); /** * @brief Get a single emoji @@ -766,9 +662,7 @@ auto inline co_guild_emoji_edit(snowflake guild_id, const class emoji& newemoji) * @return emoji returned object on completion * \memberof dpp::cluster */ -auto inline co_guild_emoji_get(snowflake guild_id, snowflake emoji_id) { - return dpp::awaitable(this, [&] (auto cc) { this->guild_emoji_get(guild_id, emoji_id, cc); }); -} +awaitable co_guild_emoji_get(snowflake guild_id, snowflake emoji_id); /** * @brief Get all emojis for a guild @@ -779,9 +673,7 @@ auto inline co_guild_emoji_get(snowflake guild_id, snowflake emoji_id) { * @return emoji_map returned object on completion * \memberof dpp::cluster */ -auto inline co_guild_emojis_get(snowflake guild_id) { - return dpp::awaitable(this, [&] (auto cc) { this->guild_emojis_get(guild_id, cc); }); -} +awaitable co_guild_emojis_get(snowflake guild_id); /** * @brief Get the gateway information for the bot using the token @@ -790,9 +682,7 @@ auto inline co_guild_emojis_get(snowflake guild_id) { * @return gateway returned object on completion * \memberof dpp::cluster */ -auto inline co_get_gateway_bot() { - return dpp::awaitable(this, [&] (auto cc) { this->get_gateway_bot(cc); }); -} +awaitable co_get_gateway_bot(); /** * @brief Modify current member @@ -808,9 +698,7 @@ auto inline co_get_gateway_bot() { * @return confirmation returned object on completion * \memberof dpp::cluster */ -auto inline co_guild_current_member_edit(snowflake guild_id, const std::string &nickname) { - return dpp::awaitable(this, [&] (auto cc) { this->guild_current_member_edit(guild_id, nickname, cc); }); -} +awaitable co_guild_current_member_edit(snowflake guild_id, const std::string &nickname); /** * @brief Get the audit log for a guild @@ -826,9 +714,7 @@ auto inline co_guild_current_member_edit(snowflake guild_id, const std::string & * @return auditlog returned object on completion * \memberof dpp::cluster */ -auto inline co_guild_auditlog_get(snowflake guild_id, snowflake user_id, uint32_t action_type, snowflake before, snowflake after, uint32_t limit) { - return dpp::awaitable(this, [&] (auto cc) { this->guild_auditlog_get(guild_id, user_id, action_type, before, after, limit, cc); }); -} +awaitable co_guild_auditlog_get(snowflake guild_id, snowflake user_id, uint32_t action_type, snowflake before, snowflake after, uint32_t limit); /** * @brief Add guild ban @@ -844,9 +730,7 @@ auto inline co_guild_auditlog_get(snowflake guild_id, snowflake user_id, uint32_ * @return confirmation returned object on completion * \memberof dpp::cluster */ -auto inline co_guild_ban_add(snowflake guild_id, snowflake user_id, uint32_t delete_message_seconds) { - return dpp::awaitable(this, [&] (auto cc) { this->guild_ban_add(guild_id, user_id, delete_message_seconds, cc); }); -} +awaitable co_guild_ban_add(snowflake guild_id, snowflake user_id, uint32_t delete_message_seconds = 0); /** * @brief Delete guild ban @@ -861,9 +745,7 @@ auto inline co_guild_ban_add(snowflake guild_id, snowflake user_id, uint32_t del * @return confirmation returned object on completion * \memberof dpp::cluster */ -auto inline co_guild_ban_delete(snowflake guild_id, snowflake user_id) { - return dpp::awaitable(this, [&] (auto cc) { this->guild_ban_delete(guild_id, user_id, cc); }); -} +awaitable co_guild_ban_delete(snowflake guild_id, snowflake user_id); /** * @brief Create a guild @@ -886,9 +768,7 @@ auto inline co_guild_ban_delete(snowflake guild_id, snowflake user_id) { * @return guild returned object on completion * \memberof dpp::cluster */ -auto inline co_guild_create(const class guild &g) { - return dpp::awaitable(this, [&] (auto cc) { this->guild_create(g, cc); }); -} +awaitable co_guild_create(const class guild &g); /** * @brief Delete a guild @@ -901,9 +781,7 @@ auto inline co_guild_create(const class guild &g) { * @return confirmation returned object on completion * \memberof dpp::cluster */ -auto inline co_guild_delete(snowflake guild_id) { - return dpp::awaitable(this, [&] (auto cc) { this->guild_delete(guild_id, cc); }); -} +awaitable co_guild_delete(snowflake guild_id); /** * @brief Delete guild integration @@ -919,9 +797,7 @@ auto inline co_guild_delete(snowflake guild_id) { * @return confirmation returned object on completion * \memberof dpp::cluster */ -auto inline co_guild_delete_integration(snowflake guild_id, snowflake integration_id) { - return dpp::awaitable(this, [&] (auto cc) { this->guild_delete_integration(guild_id, integration_id, cc); }); -} +awaitable co_guild_delete_integration(snowflake guild_id, snowflake integration_id); /** * @brief Edit a guild @@ -936,9 +812,7 @@ auto inline co_guild_delete_integration(snowflake guild_id, snowflake integratio * @return guild returned object on completion * \memberof dpp::cluster */ -auto inline co_guild_edit(const class guild &g) { - return dpp::awaitable(this, [&] (auto cc) { this->guild_edit(g, cc); }); -} +awaitable co_guild_edit(const class guild &g); /** * @brief Edit guild widget @@ -953,9 +827,7 @@ auto inline co_guild_edit(const class guild &g) { * @return guild_widget returned object on completion * \memberof dpp::cluster */ -auto inline co_guild_edit_widget(snowflake guild_id, const class guild_widget &gw) { - return dpp::awaitable(this, [&] (auto cc) { this->guild_edit_widget(guild_id, gw, cc); }); -} +awaitable co_guild_edit_widget(snowflake guild_id, const class guild_widget &gw); /** * @brief Get single guild ban @@ -968,9 +840,7 @@ auto inline co_guild_edit_widget(snowflake guild_id, const class guild_widget &g * @return ban returned object on completion * \memberof dpp::cluster */ -auto inline co_guild_get_ban(snowflake guild_id, snowflake user_id) { - return dpp::awaitable(this, [&] (auto cc) { this->guild_get_ban(guild_id, user_id, cc); }); -} +awaitable co_guild_get_ban(snowflake guild_id, snowflake user_id); /** * @brief Get guild ban list @@ -986,14 +856,10 @@ auto inline co_guild_get_ban(snowflake guild_id, snowflake user_id) { * @return ban_map returned object on completion * \memberof dpp::cluster */ -auto inline co_guild_get_bans(snowflake guild_id, snowflake before, snowflake after, snowflake limit) { - return dpp::awaitable(this, [&] (auto cc) { this->guild_get_bans(guild_id, before, after, limit, cc); }); -} +awaitable co_guild_get_bans(snowflake guild_id, snowflake before, snowflake after, snowflake limit); -auto inline co_guild_get(snowflake guild_id) { - return dpp::awaitable(this, [&] (auto cc) { this->guild_get(guild_id, cc); }); -} +awaitable co_guild_get(snowflake guild_id); /** * @brief Get guild integrations @@ -1008,14 +874,10 @@ auto inline co_guild_get(snowflake guild_id) { * @note This endpoint returns a maximum of 50 integrations. If a guild has more integrations, they cannot be accessed. * \memberof dpp::cluster */ -auto inline co_guild_get_integrations(snowflake guild_id) { - return dpp::awaitable(this, [&] (auto cc) { this->guild_get_integrations(guild_id, cc); }); -} +awaitable co_guild_get_integrations(snowflake guild_id); -auto inline co_guild_get_preview(snowflake guild_id) { - return dpp::awaitable(this, [&] (auto cc) { this->guild_get_preview(guild_id, cc); }); -} +awaitable co_guild_get_preview(snowflake guild_id); /** * @brief Get guild vanity url, if enabled @@ -1027,9 +889,7 @@ auto inline co_guild_get_preview(snowflake guild_id) { * @return invite returned object on completion * \memberof dpp::cluster */ -auto inline co_guild_get_vanity(snowflake guild_id) { - return dpp::awaitable(this, [&] (auto cc) { this->guild_get_vanity(guild_id, cc); }); -} +awaitable co_guild_get_vanity(snowflake guild_id); /** * @brief Get guild widget @@ -1042,9 +902,7 @@ auto inline co_guild_get_vanity(snowflake guild_id) { * @return guild_widget returned object on completion * \memberof dpp::cluster */ -auto inline co_guild_get_widget(snowflake guild_id) { - return dpp::awaitable(this, [&] (auto cc) { this->guild_get_widget(guild_id, cc); }); -} +awaitable co_guild_get_widget(snowflake guild_id); /** * @brief Modify guild integration @@ -1057,9 +915,7 @@ auto inline co_guild_get_widget(snowflake guild_id) { * @return confirmation returned object on completion * \memberof dpp::cluster */ -auto inline co_guild_modify_integration(snowflake guild_id, const class integration &i) { - return dpp::awaitable(this, [&] (auto cc) { this->guild_modify_integration(guild_id, i, cc); }); -} +awaitable co_guild_modify_integration(snowflake guild_id, const class integration &i); /** * @brief Get prune counts @@ -1076,9 +932,7 @@ auto inline co_guild_modify_integration(snowflake guild_id, const class integrat * @return prune returned object on completion * \memberof dpp::cluster */ -auto inline co_guild_get_prune_counts(snowflake guild_id, const struct prune& pruneinfo) { - return dpp::awaitable(this, [&] (auto cc) { this->guild_get_prune_counts(guild_id, pruneinfo, cc); }); -} +awaitable co_guild_get_prune_counts(snowflake guild_id, const struct prune& pruneinfo); /** * @brief Begin guild prune @@ -1097,9 +951,7 @@ auto inline co_guild_get_prune_counts(snowflake guild_id, const struct prune& pr * @return prune returned object on completion * \memberof dpp::cluster */ -auto inline co_guild_begin_prune(snowflake guild_id, const struct prune& pruneinfo) { - return dpp::awaitable(this, [&] (auto cc) { this->guild_begin_prune(guild_id, pruneinfo, cc); }); -} +awaitable co_guild_begin_prune(snowflake guild_id, const struct prune& pruneinfo); /** * @brief Change current user nickname @@ -1116,9 +968,7 @@ auto inline co_guild_begin_prune(snowflake guild_id, const struct prune& prunein * @return confirmation returned object on completion * \memberof dpp::cluster */ -auto inline co_guild_set_nickname(snowflake guild_id, const std::string &nickname) { - return dpp::awaitable(this, [&] (auto cc) { this->guild_set_nickname(guild_id, nickname, cc); }); -} +awaitable co_guild_set_nickname(snowflake guild_id, const std::string &nickname); /** * @brief Sync guild integration @@ -1130,9 +980,7 @@ auto inline co_guild_set_nickname(snowflake guild_id, const std::string &nicknam * @return confirmation returned object on completion * \memberof dpp::cluster */ -auto inline co_guild_sync_integration(snowflake guild_id, snowflake integration_id) { - return dpp::awaitable(this, [&] (auto cc) { this->guild_sync_integration(guild_id, integration_id, cc); }); -} +awaitable co_guild_sync_integration(snowflake guild_id, snowflake integration_id); /** * @brief Add guild member. Needs a specific oauth2 scope, from which you get the access_token. @@ -1152,9 +1000,7 @@ auto inline co_guild_sync_integration(snowflake guild_id, snowflake integration_ * @return confirmation returned object on completion * \memberof dpp::cluster */ -auto inline co_guild_add_member(const guild_member& gm, const std::string &access_token) { - return dpp::awaitable(this, [&] (auto cc) { this->guild_add_member(gm, access_token, cc); }); -} +awaitable co_guild_add_member(const guild_member& gm, const std::string &access_token); /** * @brief Edit the properties of an existing guild member @@ -1170,9 +1016,7 @@ auto inline co_guild_add_member(const guild_member& gm, const std::string &acces * @return guild_member returned object on completion * \memberof dpp::cluster */ -auto inline co_guild_edit_member(const guild_member& gm) { - return dpp::awaitable(this, [&] (auto cc) { this->guild_edit_member(gm, cc); }); -} +awaitable co_guild_edit_member(const guild_member& gm); /** * @brief Get a guild member @@ -1183,9 +1027,7 @@ auto inline co_guild_edit_member(const guild_member& gm) { * @return guild_member returned object on completion * \memberof dpp::cluster */ -auto inline co_guild_get_member(snowflake guild_id, snowflake user_id) { - return dpp::awaitable(this, [&] (auto cc) { this->guild_get_member(guild_id, user_id, cc); }); -} +awaitable co_guild_get_member(snowflake guild_id, snowflake user_id); /** * @brief Get all guild members @@ -1199,9 +1041,7 @@ auto inline co_guild_get_member(snowflake guild_id, snowflake user_id) { * @return guild_member_map returned object on completion * \memberof dpp::cluster */ -auto inline co_guild_get_members(snowflake guild_id, uint16_t limit, snowflake after) { - return dpp::awaitable(this, [&] (auto cc) { this->guild_get_members(guild_id, limit, after, cc); }); -} +awaitable co_guild_get_members(snowflake guild_id, uint16_t limit, snowflake after); /** * @brief Add role to guild member @@ -1217,9 +1057,7 @@ auto inline co_guild_get_members(snowflake guild_id, uint16_t limit, snowflake a * @return confirmation returned object on completion * \memberof dpp::cluster */ -auto inline co_guild_member_add_role(snowflake guild_id, snowflake user_id, snowflake role_id) { - return dpp::awaitable(this, [&] (auto cc) { this->guild_member_add_role(guild_id, user_id, role_id, cc); }); -} +awaitable co_guild_member_add_role(snowflake guild_id, snowflake user_id, snowflake role_id); /** * @brief Remove (kick) a guild member @@ -1235,9 +1073,7 @@ auto inline co_guild_member_add_role(snowflake guild_id, snowflake user_id, snow * @return confirmation returned object on completion * \memberof dpp::cluster */ -auto inline co_guild_member_delete(snowflake guild_id, snowflake user_id) { - return dpp::awaitable(this, [&] (auto cc) { this->guild_member_delete(guild_id, user_id, cc); }); -} +awaitable co_guild_member_delete(snowflake guild_id, snowflake user_id); /** * @brief Remove (kick) a guild member @@ -1252,9 +1088,7 @@ auto inline co_guild_member_delete(snowflake guild_id, snowflake user_id) { * @return confirmation returned object on completion * \memberof dpp::cluster */ -auto inline co_guild_member_kick(snowflake guild_id, snowflake user_id) { - return dpp::awaitable(this, [&] (auto cc) { this->guild_member_kick(guild_id, user_id, cc); }); -} +awaitable co_guild_member_kick(snowflake guild_id, snowflake user_id); /** * @brief Set the timeout of a guild member @@ -1269,9 +1103,7 @@ auto inline co_guild_member_kick(snowflake guild_id, snowflake user_id) { * @return confirmation returned object on completion * \memberof dpp::cluster */ -auto inline co_guild_member_timeout(snowflake guild_id, snowflake user_id, time_t communication_disabled_until) { - return dpp::awaitable(this, [&] (auto cc) { this->guild_member_timeout(guild_id, user_id, communication_disabled_until, cc); }); -} +awaitable co_guild_member_timeout(snowflake guild_id, snowflake user_id, time_t communication_disabled_until); /** * @brief Remove role from guild member @@ -1288,9 +1120,7 @@ auto inline co_guild_member_timeout(snowflake guild_id, snowflake user_id, time_ * @deprecated Use dpp::cluster::guild_member_remove_role instead * \memberof dpp::cluster */ -auto inline co_guild_member_delete_role(snowflake guild_id, snowflake user_id, snowflake role_id) { - return dpp::awaitable(this, [&] (auto cc) { this->guild_member_delete_role(guild_id, user_id, role_id, cc); }); -} +awaitable co_guild_member_delete_role(snowflake guild_id, snowflake user_id, snowflake role_id); /** * @brief Remove role from guild member @@ -1306,9 +1136,7 @@ auto inline co_guild_member_delete_role(snowflake guild_id, snowflake user_id, s * @return confirmation returned object on completion * \memberof dpp::cluster */ -auto inline co_guild_member_remove_role(snowflake guild_id, snowflake user_id, snowflake role_id) { - return dpp::awaitable(this, [&] (auto cc) { this->guild_member_remove_role(guild_id, user_id, role_id, cc); }); -} +awaitable co_guild_member_remove_role(snowflake guild_id, snowflake user_id, snowflake role_id); /** * @brief Moves the guild member to a other voice channel, if member is connected to one. @@ -1325,9 +1153,7 @@ auto inline co_guild_member_remove_role(snowflake guild_id, snowflake user_id, s * @return guild_member returned object on completion * \memberof dpp::cluster */ -auto inline co_guild_member_move(const snowflake channel_id, const snowflake guild_id, const snowflake user_id) { - return dpp::awaitable(this, [&] (auto cc) { this->guild_member_move(channel_id, guild_id, user_id, cc); }); -} +awaitable co_guild_member_move(const snowflake channel_id, const snowflake guild_id, const snowflake user_id); /** * @brief Search for guild members based on whether their username or nickname starts with the given string. @@ -1341,9 +1167,7 @@ auto inline co_guild_member_move(const snowflake channel_id, const snowflake gui * @return guild_member_map returned object on completion * \memberof dpp::cluster */ -auto inline co_guild_search_members(snowflake guild_id, const std::string& query, uint16_t limit) { - return dpp::awaitable(this, [&] (auto cc) { this->guild_search_members(guild_id, query, limit, cc); }); -} +awaitable co_guild_search_members(snowflake guild_id, const std::string& query, uint16_t limit); /** * @brief Get guild invites @@ -1356,14 +1180,10 @@ auto inline co_guild_search_members(snowflake guild_id, const std::string& query * @return invite_map returned object on completion * \memberof dpp::cluster */ -auto inline co_guild_get_invites(snowflake guild_id) { - return dpp::awaitable(this, [&] (auto cc) { this->guild_get_invites(guild_id, cc); }); -} +awaitable co_guild_get_invites(snowflake guild_id); -auto inline co_invite_delete(const std::string &invitecode) { - return dpp::awaitable(this, [&] (auto cc) { this->invite_delete(invitecode, cc); }); -} +awaitable co_invite_delete(const std::string &invitecode); /** * @brief Get details about an invite @@ -1374,9 +1194,7 @@ auto inline co_invite_delete(const std::string &invitecode) { * @return invite returned object on completion * \memberof dpp::cluster */ -auto inline co_invite_get(const std::string &invite_code) { - return dpp::awaitable(this, [&] (auto cc) { this->invite_get(invite_code, cc); }); -} +awaitable co_invite_get(const std::string &invite_code); /** * @brief Add a reaction to a message. The reaction string must be either an `emojiname:id` or a unicode character. @@ -1388,9 +1206,7 @@ auto inline co_invite_get(const std::string &invite_code) { * @return confirmation returned object on completion * \memberof dpp::cluster */ -auto inline co_message_add_reaction(const struct message &m, const std::string &reaction) { - return dpp::awaitable(this, [&] (auto cc) { this->message_add_reaction(m, reaction, cc); }); -} +awaitable co_message_add_reaction(const struct message &m, const std::string &reaction); /** * @brief Add a reaction to a message by id. The reaction string must be either an `emojiname:id` or a unicode character. @@ -1403,9 +1219,7 @@ auto inline co_message_add_reaction(const struct message &m, const std::string & * @return confirmation returned object on completion * \memberof dpp::cluster */ -auto inline co_message_add_reaction(snowflake message_id, snowflake channel_id, const std::string &reaction) { - return dpp::awaitable(this, [&] (auto cc) { this->message_add_reaction(message_id, channel_id, reaction, cc); }); -} +awaitable co_message_add_reaction(snowflake message_id, snowflake channel_id, const std::string &reaction); /** * @brief Send a message to a channel. The callback function is called when the message has been sent @@ -1416,9 +1230,7 @@ auto inline co_message_add_reaction(snowflake message_id, snowflake channel_id, * @return message returned object on completion * \memberof dpp::cluster */ -auto inline co_message_create(const message &m) { - return dpp::awaitable(this, [&] (auto cc) { this->message_create(m, cc); }); -} +awaitable co_message_create(const struct message &m); /** * @brief Crosspost a message. The callback function is called when the message has been sent @@ -1430,9 +1242,7 @@ auto inline co_message_create(const message &m) { * @return message returned object on completion * \memberof dpp::cluster */ -auto inline co_message_crosspost(snowflake message_id, snowflake channel_id) { - return dpp::awaitable(this, [&] (auto cc) { this->message_crosspost(message_id, channel_id, cc); }); -} +awaitable co_message_crosspost(snowflake message_id, snowflake channel_id); /** * @brief Delete all reactions on a message @@ -1443,9 +1253,7 @@ auto inline co_message_crosspost(snowflake message_id, snowflake channel_id) { * @return confirmation returned object on completion * \memberof dpp::cluster */ -auto inline co_message_delete_all_reactions(const struct message &m) { - return dpp::awaitable(this, [&] (auto cc) { this->message_delete_all_reactions(m, cc); }); -} +awaitable co_message_delete_all_reactions(const struct message &m); /** * @brief Delete all reactions on a message by id @@ -1457,9 +1265,7 @@ auto inline co_message_delete_all_reactions(const struct message &m) { * @return confirmation returned object on completion * \memberof dpp::cluster */ -auto inline co_message_delete_all_reactions(snowflake message_id, snowflake channel_id) { - return dpp::awaitable(this, [&] (auto cc) { this->message_delete_all_reactions(message_id, channel_id, cc); }); -} +awaitable co_message_delete_all_reactions(snowflake message_id, snowflake channel_id); /** * @brief Bulk delete messages from a channel. The callback function is called when the message has been edited @@ -1474,9 +1280,7 @@ auto inline co_message_delete_all_reactions(snowflake message_id, snowflake chan * @return confirmation returned object on completion * \memberof dpp::cluster */ -auto inline co_message_delete_bulk(const std::vector& message_ids, snowflake channel_id) { - return dpp::awaitable(this, [&] (auto cc) { this->message_delete_bulk(message_ids, channel_id, cc); }); -} +awaitable co_message_delete_bulk(const std::vector &message_ids, snowflake channel_id); /** * @brief Delete a message from a channel. The callback function is called when the message has been edited @@ -1489,9 +1293,7 @@ auto inline co_message_delete_bulk(const std::vector& message_ids, sn * @return confirmation returned object on completion * \memberof dpp::cluster */ -auto inline co_message_delete(snowflake message_id, snowflake channel_id) { - return dpp::awaitable(this, [&] (auto cc) { this->message_delete(message_id, channel_id, cc); }); -} +awaitable co_message_delete(snowflake message_id, snowflake channel_id); /** * @brief Delete own reaction from a message. The reaction string must be either an `emojiname:id` or a unicode character. @@ -1503,9 +1305,7 @@ auto inline co_message_delete(snowflake message_id, snowflake channel_id) { * @return confirmation returned object on completion * \memberof dpp::cluster */ -auto inline co_message_delete_own_reaction(const struct message &m, const std::string &reaction) { - return dpp::awaitable(this, [&] (auto cc) { this->message_delete_own_reaction(m, reaction, cc); }); -} +awaitable co_message_delete_own_reaction(const struct message &m, const std::string &reaction); /** * @brief Delete own reaction from a message by id. The reaction string must be either an `emojiname:id` or a unicode character. @@ -1518,9 +1318,7 @@ auto inline co_message_delete_own_reaction(const struct message &m, const std::s * @return confirmation returned object on completion * \memberof dpp::cluster */ -auto inline co_message_delete_own_reaction(snowflake message_id, snowflake channel_id, const std::string &reaction) { - return dpp::awaitable(this, [&] (auto cc) { this->message_delete_own_reaction(message_id, channel_id, reaction, cc); }); -} +awaitable co_message_delete_own_reaction(snowflake message_id, snowflake channel_id, const std::string &reaction); /** * @brief Delete a user's reaction from a message. The reaction string must be either an `emojiname:id` or a unicode character @@ -1533,9 +1331,7 @@ auto inline co_message_delete_own_reaction(snowflake message_id, snowflake chann * @return confirmation returned object on completion * \memberof dpp::cluster */ -auto inline co_message_delete_reaction(const struct message &m, snowflake user_id, const std::string &reaction) { - return dpp::awaitable(this, [&] (auto cc) { this->message_delete_reaction(m, user_id, reaction, cc); }); -} +awaitable co_message_delete_reaction(const struct message &m, snowflake user_id, const std::string &reaction); /** * @brief Delete a user's reaction from a message by id. The reaction string must be either an `emojiname:id` or a unicode character @@ -1549,9 +1345,7 @@ auto inline co_message_delete_reaction(const struct message &m, snowflake user_i * @return confirmation returned object on completion * \memberof dpp::cluster */ -auto inline co_message_delete_reaction(snowflake message_id, snowflake channel_id, snowflake user_id, const std::string &reaction) { - return dpp::awaitable(this, [&] (auto cc) { this->message_delete_reaction(message_id, channel_id, user_id, reaction, cc); }); -} +awaitable co_message_delete_reaction(snowflake message_id, snowflake channel_id, snowflake user_id, const std::string &reaction); /** * @brief Delete all reactions on a message using a particular emoji. The reaction string must be either an `emojiname:id` or a unicode character @@ -1563,9 +1357,7 @@ auto inline co_message_delete_reaction(snowflake message_id, snowflake channel_i * @return confirmation returned object on completion * \memberof dpp::cluster */ -auto inline co_message_delete_reaction_emoji(const struct message &m, const std::string &reaction) { - return dpp::awaitable(this, [&] (auto cc) { this->message_delete_reaction_emoji(m, reaction, cc); }); -} +awaitable co_message_delete_reaction_emoji(const struct message &m, const std::string &reaction); /** * @brief Delete all reactions on a message using a particular emoji by id. The reaction string must be either an `emojiname:id` or a unicode character @@ -1578,9 +1370,7 @@ auto inline co_message_delete_reaction_emoji(const struct message &m, const std: * @return confirmation returned object on completion * \memberof dpp::cluster */ -auto inline co_message_delete_reaction_emoji(snowflake message_id, snowflake channel_id, const std::string &reaction) { - return dpp::awaitable(this, [&] (auto cc) { this->message_delete_reaction_emoji(message_id, channel_id, reaction, cc); }); -} +awaitable co_message_delete_reaction_emoji(snowflake message_id, snowflake channel_id, const std::string &reaction); /** * @brief Edit a message on a channel. The callback function is called when the message has been edited @@ -1591,9 +1381,7 @@ auto inline co_message_delete_reaction_emoji(snowflake message_id, snowflake cha * @return message returned object on completion * \memberof dpp::cluster */ -auto inline co_message_edit(const message &m) { - return dpp::awaitable(this, [&] (auto cc) { this->message_edit(m, cc); }); -} +awaitable co_message_edit(const struct message &m); /** * @brief Get a message @@ -1605,9 +1393,7 @@ auto inline co_message_edit(const message &m) { * @return message returned object on completion * \memberof dpp::cluster */ -auto inline co_message_get(snowflake message_id, snowflake channel_id) { - return dpp::awaitable(this, [&] (auto cc) { this->message_get(message_id, channel_id, cc); }); -} +awaitable co_message_get(snowflake message_id, snowflake channel_id); /** * @brief Get reactions on a message for a particular emoji. The reaction string must be either an `emojiname:id` or a unicode character @@ -1622,9 +1408,7 @@ auto inline co_message_get(snowflake message_id, snowflake channel_id) { * @return user_map returned object on completion * \memberof dpp::cluster */ -auto inline co_message_get_reactions(const struct message &m, const std::string &reaction, snowflake before, snowflake after, snowflake limit) { - return dpp::awaitable(this, [&] (auto cc) { this->message_get_reactions(m, reaction, before, after, limit, cc); }); -} +awaitable co_message_get_reactions(const struct message &m, const std::string &reaction, snowflake before, snowflake after, snowflake limit); /** * @brief Get reactions on a message for a particular emoji by id. The reaction string must be either an `emojiname:id` or a unicode character @@ -1640,9 +1424,7 @@ auto inline co_message_get_reactions(const struct message &m, const std::string * @return emoji_map returned object on completion * \memberof dpp::cluster */ -auto inline co_message_get_reactions(snowflake message_id, snowflake channel_id, const std::string &reaction, snowflake before, snowflake after, snowflake limit) { - return dpp::awaitable(this, [&] (auto cc) { this->message_get_reactions(message_id, channel_id, reaction, before, after, limit, cc); }); -} +awaitable co_message_get_reactions(snowflake message_id, snowflake channel_id, const std::string &reaction, snowflake before, snowflake after, snowflake limit); /** * @brief Pin a message @@ -1654,9 +1436,7 @@ auto inline co_message_get_reactions(snowflake message_id, snowflake channel_id, * @return confirmation returned object on completion * \memberof dpp::cluster */ -auto inline co_message_pin(snowflake channel_id, snowflake message_id) { - return dpp::awaitable(this, [&] (auto cc) { this->message_pin(channel_id, message_id, cc); }); -} +awaitable co_message_pin(snowflake channel_id, snowflake message_id); /** * @brief Get multiple messages. @@ -1673,9 +1453,7 @@ auto inline co_message_pin(snowflake channel_id, snowflake message_id) { * @return message_map returned object on completion * \memberof dpp::cluster */ -auto inline co_messages_get(snowflake channel_id, snowflake around, snowflake before, snowflake after, uint64_t limit) { - return dpp::awaitable(this, [&] (auto cc) { this->messages_get(channel_id, around, before, after, limit, cc); }); -} +awaitable co_messages_get(snowflake channel_id, snowflake around, snowflake before, snowflake after, uint64_t limit); /** * @brief Unpin a message @@ -1687,9 +1465,7 @@ auto inline co_messages_get(snowflake channel_id, snowflake around, snowflake be * @return confirmation returned object on completion * \memberof dpp::cluster */ -auto inline co_message_unpin(snowflake channel_id, snowflake message_id) { - return dpp::awaitable(this, [&] (auto cc) { this->message_unpin(channel_id, message_id, cc); }); -} +awaitable co_message_unpin(snowflake channel_id, snowflake message_id); /** * @brief Get a channel's pins @@ -1699,9 +1475,7 @@ auto inline co_message_unpin(snowflake channel_id, snowflake message_id) { * @return message_map returned object on completion * \memberof dpp::cluster */ -auto inline co_channel_pins_get(snowflake channel_id) { - return dpp::awaitable(this, [&] (auto cc) { this->channel_pins_get(channel_id, cc); }); -} +awaitable co_channel_pins_get(snowflake channel_id); /** * @brief Create a role on a guild @@ -1716,9 +1490,7 @@ auto inline co_channel_pins_get(snowflake channel_id) { * @return role returned object on completion * \memberof dpp::cluster */ -auto inline co_role_create(const class role &r) { - return dpp::awaitable(this, [&] (auto cc) { this->role_create(r, cc); }); -} +awaitable co_role_create(const class role &r); /** * @brief Delete a role @@ -1733,9 +1505,7 @@ auto inline co_role_create(const class role &r) { * @return confirmation returned object on completion * \memberof dpp::cluster */ -auto inline co_role_delete(snowflake guild_id, snowflake role_id) { - return dpp::awaitable(this, [&] (auto cc) { this->role_delete(guild_id, role_id, cc); }); -} +awaitable co_role_delete(snowflake guild_id, snowflake role_id); /** * @brief Edit a role on a guild @@ -1749,9 +1519,7 @@ auto inline co_role_delete(snowflake guild_id, snowflake role_id) { * @return role returned object on completion * \memberof dpp::cluster */ -auto inline co_role_edit(const class role &r) { - return dpp::awaitable(this, [&] (auto cc) { this->role_edit(r, cc); }); -} +awaitable co_role_edit(const class role &r); /** * @brief Edit multiple role's position in a guild. Returns a list of all roles of the guild on success. @@ -1767,9 +1535,7 @@ auto inline co_role_edit(const class role &r) { * @return role_map returned object on completion * \memberof dpp::cluster */ -auto inline co_roles_edit_position(snowflake guild_id, const std::vector &roles) { - return dpp::awaitable(this, [&] (auto cc) { this->roles_edit_position(guild_id, roles, cc); }); -} +awaitable co_roles_edit_position(snowflake guild_id, const std::vector &roles); /** * @brief Get a role for a guild @@ -1780,9 +1546,7 @@ auto inline co_roles_edit_position(snowflake guild_id, const std::vector & * @return role_map returned object on completion * \memberof dpp::cluster */ -auto inline co_roles_get(snowflake guild_id) { - return dpp::awaitable(this, [&] (auto cc) { this->roles_get(guild_id, cc); }); -} +awaitable co_roles_get(snowflake guild_id); /** * @brief Get the application's role connection metadata records @@ -1793,9 +1557,7 @@ auto inline co_roles_get(snowflake guild_id) { * @return application_role_connection returned object on completion * \memberof dpp::cluster */ -auto inline co_application_role_connection_get(snowflake application_id) { - return dpp::awaitable(this, [&] (auto cc) { this->application_role_connection_get(application_id, cc); }); -} +awaitable co_application_role_connection_get(snowflake application_id); /** * @brief Update the application's role connection metadata records @@ -1808,9 +1570,7 @@ auto inline co_application_role_connection_get(snowflake application_id) { * @note An application can have a maximum of 5 metadata records. * \memberof dpp::cluster */ -auto inline co_application_role_connection_update(snowflake application_id, const std::vector &connection_metadata) { - return dpp::awaitable(this, [&] (auto cc) { this->application_role_connection_update(application_id, connection_metadata, cc); }); -} +awaitable co_application_role_connection_update(snowflake application_id, const std::vector &connection_metadata); /** * @brief Get user application role connection @@ -1821,9 +1581,7 @@ auto inline co_application_role_connection_update(snowflake application_id, cons * @return application_role_connection returned object on completion * \memberof dpp::cluster */ -auto inline co_user_application_role_connection_get(snowflake application_id) { - return dpp::awaitable(this, [&] (auto cc) { this->user_application_role_connection_get(application_id, cc); }); -} +awaitable co_user_application_role_connection_get(snowflake application_id); /** * @brief Update user application role connection @@ -1835,9 +1593,7 @@ auto inline co_user_application_role_connection_get(snowflake application_id) { * @return application_role_connection returned object on completion * \memberof dpp::cluster */ -auto inline co_user_application_role_connection_update(snowflake application_id, const application_role_connection &connection) { - return dpp::awaitable(this, [&] (auto cc) { this->user_application_role_connection_update(application_id, connection, cc); }); -} +awaitable co_user_application_role_connection_update(snowflake application_id, const application_role_connection &connection); /** * @brief Get all scheduled events for a guild @@ -1847,9 +1603,7 @@ auto inline co_user_application_role_connection_update(snowflake application_id, * @return scheduled_event_map returned object on completion * \memberof dpp::cluster */ -auto inline co_guild_events_get(snowflake guild_id) { - return dpp::awaitable(this, [&] (auto cc) { this->guild_events_get(guild_id, cc); }); -} +awaitable co_guild_events_get(snowflake guild_id); /** * @brief Create a scheduled event on a guild @@ -1860,9 +1614,7 @@ auto inline co_guild_events_get(snowflake guild_id) { * @return scheduled_event returned object on completion * \memberof dpp::cluster */ -auto inline co_guild_event_create(const scheduled_event& event) { - return dpp::awaitable(this, [&] (auto cc) { this->guild_event_create(event, cc); }); -} +awaitable co_guild_event_create(const scheduled_event& event); /** * @brief Delete a scheduled event from a guild @@ -1874,9 +1626,7 @@ auto inline co_guild_event_create(const scheduled_event& event) { * @return confirmation returned object on completion * \memberof dpp::cluster */ -auto inline co_guild_event_delete(snowflake event_id, snowflake guild_id) { - return dpp::awaitable(this, [&] (auto cc) { this->guild_event_delete(event_id, guild_id, cc); }); -} +awaitable co_guild_event_delete(snowflake event_id, snowflake guild_id); /** * @brief Edit/modify a scheduled event on a guild @@ -1887,9 +1637,7 @@ auto inline co_guild_event_delete(snowflake event_id, snowflake guild_id) { * @return scheduled_event returned object on completion * \memberof dpp::cluster */ -auto inline co_guild_event_edit(const scheduled_event& event) { - return dpp::awaitable(this, [&] (auto cc) { this->guild_event_edit(event, cc); }); -} +awaitable co_guild_event_edit(const scheduled_event& event); /** * @brief Get a scheduled event for a guild @@ -1901,14 +1649,10 @@ auto inline co_guild_event_edit(const scheduled_event& event) { * @return scheduled_event returned object on completion * \memberof dpp::cluster */ -auto inline co_guild_event_get(snowflake guild_id, snowflake event_id) { - return dpp::awaitable(this, [&] (auto cc) { this->guild_event_get(guild_id, event_id, cc); }); -} +awaitable co_guild_event_get(snowflake guild_id, snowflake event_id); -auto inline co_stage_instance_create(const stage_instance& si) { - return dpp::awaitable(this, [&] (auto cc) { this->stage_instance_create(si, cc); }); -} +awaitable co_stage_instance_create(const stage_instance& si); /** * @brief Get the stage instance associated with the channel id, if it exists. @@ -1918,14 +1662,10 @@ auto inline co_stage_instance_create(const stage_instance& si) { * @return stage_instance returned object on completion * \memberof dpp::cluster */ -auto inline co_stage_instance_get(const snowflake channel_id) { - return dpp::awaitable(this, [&] (auto cc) { this->stage_instance_get(channel_id, cc); }); -} +awaitable co_stage_instance_get(const snowflake channel_id); -auto inline co_stage_instance_edit(const stage_instance& si) { - return dpp::awaitable(this, [&] (auto cc) { this->stage_instance_edit(si, cc); }); -} +awaitable co_stage_instance_edit(const stage_instance& si); /** * @brief Delete a stage instance. @@ -1936,9 +1676,7 @@ auto inline co_stage_instance_edit(const stage_instance& si) { * @note This method supports audit log reasons set by the cluster::set_audit_reason() method. * \memberof dpp::cluster */ -auto inline co_stage_instance_delete(const snowflake channel_id) { - return dpp::awaitable(this, [&] (auto cc) { this->stage_instance_delete(channel_id, cc); }); -} +awaitable co_stage_instance_delete(const snowflake channel_id); /** * @brief Create a sticker in a guild @@ -1949,9 +1687,7 @@ auto inline co_stage_instance_delete(const snowflake channel_id) { * @return sticker returned object on completion * \memberof dpp::cluster */ -auto inline co_guild_sticker_create(sticker &s) { - return dpp::awaitable(this, [&] (auto cc) { this->guild_sticker_create(s, cc); }); -} +awaitable co_guild_sticker_create(sticker &s); /** * @brief Delete a sticker from a guild @@ -1963,9 +1699,7 @@ auto inline co_guild_sticker_create(sticker &s) { * @return confirmation returned object on completion * \memberof dpp::cluster */ -auto inline co_guild_sticker_delete(snowflake sticker_id, snowflake guild_id) { - return dpp::awaitable(this, [&] (auto cc) { this->guild_sticker_delete(sticker_id, guild_id, cc); }); -} +awaitable co_guild_sticker_delete(snowflake sticker_id, snowflake guild_id); /** * @brief Get a guild sticker @@ -1976,9 +1710,7 @@ auto inline co_guild_sticker_delete(snowflake sticker_id, snowflake guild_id) { * @return sticker returned object on completion * \memberof dpp::cluster */ -auto inline co_guild_sticker_get(snowflake id, snowflake guild_id) { - return dpp::awaitable(this, [&] (auto cc) { this->guild_sticker_get(id, guild_id, cc); }); -} +awaitable co_guild_sticker_get(snowflake id, snowflake guild_id); /** * @brief Modify a sticker in a guild @@ -1989,9 +1721,7 @@ auto inline co_guild_sticker_get(snowflake id, snowflake guild_id) { * @return sticker returned object on completion * \memberof dpp::cluster */ -auto inline co_guild_sticker_modify(sticker &s) { - return dpp::awaitable(this, [&] (auto cc) { this->guild_sticker_modify(s, cc); }); -} +awaitable co_guild_sticker_modify(sticker &s); /** * @brief Get all guild stickers @@ -2001,9 +1731,7 @@ auto inline co_guild_sticker_modify(sticker &s) { * @return sticker_map returned object on completion * \memberof dpp::cluster */ -auto inline co_guild_stickers_get(snowflake guild_id) { - return dpp::awaitable(this, [&] (auto cc) { this->guild_stickers_get(guild_id, cc); }); -} +awaitable co_guild_stickers_get(snowflake guild_id); /** * @brief Get a nitro sticker @@ -2013,9 +1741,7 @@ auto inline co_guild_stickers_get(snowflake guild_id) { * @return sticker returned object on completion * \memberof dpp::cluster */ -auto inline co_nitro_sticker_get(snowflake id) { - return dpp::awaitable(this, [&] (auto cc) { this->nitro_sticker_get(id, cc); }); -} +awaitable co_nitro_sticker_get(snowflake id); /** * @brief Get sticker packs @@ -2024,9 +1750,7 @@ auto inline co_nitro_sticker_get(snowflake id) { * @return sticker_pack_map returned object on completion * \memberof dpp::cluster */ -auto inline co_sticker_packs_get() { - return dpp::awaitable(this, [&] (auto cc) { this->sticker_packs_get(cc); }); -} +awaitable co_sticker_packs_get(); /** * @brief Create a new guild based on a template. @@ -2038,9 +1762,7 @@ auto inline co_sticker_packs_get() { * @return guild returned object on completion * \memberof dpp::cluster */ -auto inline co_guild_create_from_template(const std::string &code, const std::string &name) { - return dpp::awaitable(this, [&] (auto cc) { this->guild_create_from_template(code, name, cc); }); -} +awaitable co_guild_create_from_template(const std::string &code, const std::string &name); /** * @brief Creates a template for the guild @@ -2053,9 +1775,7 @@ auto inline co_guild_create_from_template(const std::string &code, const std::st * @return dtemplate returned object on completion * \memberof dpp::cluster */ -auto inline co_guild_template_create(snowflake guild_id, const std::string &name, const std::string &description) { - return dpp::awaitable(this, [&] (auto cc) { this->guild_template_create(guild_id, name, description, cc); }); -} +awaitable co_guild_template_create(snowflake guild_id, const std::string &name, const std::string &description); /** * @brief Deletes the template @@ -2067,9 +1787,7 @@ auto inline co_guild_template_create(snowflake guild_id, const std::string &name * @return confirmation returned object on completion * \memberof dpp::cluster */ -auto inline co_guild_template_delete(snowflake guild_id, const std::string &code) { - return dpp::awaitable(this, [&] (auto cc) { this->guild_template_delete(guild_id, code, cc); }); -} +awaitable co_guild_template_delete(snowflake guild_id, const std::string &code); /** * @brief Modifies the template's metadata. @@ -2083,9 +1801,7 @@ auto inline co_guild_template_delete(snowflake guild_id, const std::string &code * @return dtemplate returned object on completion * \memberof dpp::cluster */ -auto inline co_guild_template_modify(snowflake guild_id, const std::string &code, const std::string &name, const std::string &description) { - return dpp::awaitable(this, [&] (auto cc) { this->guild_template_modify(guild_id, code, name, description, cc); }); -} +awaitable co_guild_template_modify(snowflake guild_id, const std::string &code, const std::string &name, const std::string &description); /** * @brief Get guild templates @@ -2096,9 +1812,7 @@ auto inline co_guild_template_modify(snowflake guild_id, const std::string &code * @return dtemplate_map returned object on completion * \memberof dpp::cluster */ -auto inline co_guild_templates_get(snowflake guild_id) { - return dpp::awaitable(this, [&] (auto cc) { this->guild_templates_get(guild_id, cc); }); -} +awaitable co_guild_templates_get(snowflake guild_id); /** * @brief Syncs the template to the guild's current state. @@ -2110,9 +1824,7 @@ auto inline co_guild_templates_get(snowflake guild_id) { * @return dtemplate returned object on completion * \memberof dpp::cluster */ -auto inline co_guild_template_sync(snowflake guild_id, const std::string &code) { - return dpp::awaitable(this, [&] (auto cc) { this->guild_template_sync(guild_id, code, cc); }); -} +awaitable co_guild_template_sync(snowflake guild_id, const std::string &code); /** * @brief Get a template @@ -2122,9 +1834,7 @@ auto inline co_guild_template_sync(snowflake guild_id, const std::string &code) * @return dtemplate returned object on completion * \memberof dpp::cluster */ -auto inline co_template_get(const std::string &code) { - return dpp::awaitable(this, [&] (auto cc) { this->template_get(code, cc); }); -} +awaitable co_template_get(const std::string &code); /** * @brief Join a thread @@ -2134,9 +1844,7 @@ auto inline co_template_get(const std::string &code) { * @return confirmation returned object on completion * \memberof dpp::cluster */ -auto inline co_current_user_join_thread(snowflake thread_id) { - return dpp::awaitable(this, [&] (auto cc) { this->current_user_join_thread(thread_id, cc); }); -} +awaitable co_current_user_join_thread(snowflake thread_id); /** * @brief Leave a thread @@ -2146,9 +1854,7 @@ auto inline co_current_user_join_thread(snowflake thread_id) { * @return confirmation returned object on completion * \memberof dpp::cluster */ -auto inline co_current_user_leave_thread(snowflake thread_id) { - return dpp::awaitable(this, [&] (auto cc) { this->current_user_leave_thread(thread_id, cc); }); -} +awaitable co_current_user_leave_thread(snowflake thread_id); /** * @brief Get all active threads in the guild, including public and private threads. Threads are ordered by their id, in descending order. @@ -2158,9 +1864,7 @@ auto inline co_current_user_leave_thread(snowflake thread_id) { * @return active_threads returned object on completion * \memberof dpp::cluster */ -auto inline co_threads_get_active(snowflake guild_id) { - return dpp::awaitable(this, [&] (auto cc) { this->threads_get_active(guild_id, cc); }); -} +awaitable co_threads_get_active(snowflake guild_id); /** * @brief Get private archived threads in a channel which current user has joined (Sorted by ID in descending order) @@ -2172,9 +1876,7 @@ auto inline co_threads_get_active(snowflake guild_id) { * @return thread_map returned object on completion * \memberof dpp::cluster */ -auto inline co_threads_get_joined_private_archived(snowflake channel_id, snowflake before_id, uint16_t limit) { - return dpp::awaitable(this, [&] (auto cc) { this->threads_get_joined_private_archived(channel_id, before_id, limit, cc); }); -} +awaitable co_threads_get_joined_private_archived(snowflake channel_id, snowflake before_id, uint16_t limit); /** * @brief Get private archived threads in a channel (Sorted by archive_timestamp in descending order) @@ -2186,9 +1888,7 @@ auto inline co_threads_get_joined_private_archived(snowflake channel_id, snowfla * @return thread_map returned object on completion * \memberof dpp::cluster */ -auto inline co_threads_get_private_archived(snowflake channel_id, time_t before_timestamp, uint16_t limit) { - return dpp::awaitable(this, [&] (auto cc) { this->threads_get_private_archived(channel_id, before_timestamp, limit, cc); }); -} +awaitable co_threads_get_private_archived(snowflake channel_id, time_t before_timestamp, uint16_t limit); /** * @brief Get public archived threads in a channel (Sorted by archive_timestamp in descending order) @@ -2200,9 +1900,7 @@ auto inline co_threads_get_private_archived(snowflake channel_id, time_t before_ * @return thread_map returned object on completion * \memberof dpp::cluster */ -auto inline co_threads_get_public_archived(snowflake channel_id, time_t before_timestamp, uint16_t limit) { - return dpp::awaitable(this, [&] (auto cc) { this->threads_get_public_archived(channel_id, before_timestamp, limit, cc); }); -} +awaitable co_threads_get_public_archived(snowflake channel_id, time_t before_timestamp, uint16_t limit); /** * @brief Get a thread member @@ -2213,9 +1911,7 @@ auto inline co_threads_get_public_archived(snowflake channel_id, time_t before_t * @return thread_member returned object on completion * \memberof dpp::cluster */ -auto inline co_thread_member_get(const snowflake thread_id, const snowflake user_id) { - return dpp::awaitable(this, [&] (auto cc) { this->thread_member_get(thread_id, user_id, cc); }); -} +awaitable co_thread_member_get(const snowflake thread_id, const snowflake user_id); /** * @brief Get members of a thread @@ -2225,9 +1921,7 @@ auto inline co_thread_member_get(const snowflake thread_id, const snowflake user * @return thread_member_map returned object on completion * \memberof dpp::cluster */ -auto inline co_thread_members_get(snowflake thread_id) { - return dpp::awaitable(this, [&] (auto cc) { this->thread_members_get(thread_id, cc); }); -} +awaitable co_thread_members_get(snowflake thread_id); /** * @brief Create a thread in forum channel @@ -2244,9 +1938,7 @@ auto inline co_thread_members_get(snowflake thread_id) { * @return thread returned object on completion * \memberof dpp::cluster */ -auto inline co_thread_create_in_forum(const std::string& thread_name, snowflake channel_id, const message& msg, auto_archive_duration_t auto_archive_duration, uint16_t rate_limit_per_user, std::vector applied_tags) { - return dpp::awaitable(this, [&] (auto cc) { this->thread_create_in_forum(thread_name, channel_id, msg, auto_archive_duration, rate_limit_per_user, applied_tags, cc); }); -} +awaitable co_thread_create_in_forum(const std::string& thread_name, snowflake channel_id, const message& msg, auto_archive_duration_t auto_archive_duration, uint16_t rate_limit_per_user, std::vector applied_tags = {}); /** * @brief Create a thread @@ -2263,9 +1955,7 @@ auto inline co_thread_create_in_forum(const std::string& thread_name, snowflake * @return thread returned object on completion * \memberof dpp::cluster */ -auto inline co_thread_create(const std::string& thread_name, snowflake channel_id, uint16_t auto_archive_duration, channel_type thread_type, bool invitable, uint16_t rate_limit_per_user) { - return dpp::awaitable(this, [&] (auto cc) { this->thread_create(thread_name, channel_id, auto_archive_duration, thread_type, invitable, rate_limit_per_user, cc); }); -} +awaitable co_thread_create(const std::string& thread_name, snowflake channel_id, uint16_t auto_archive_duration, channel_type thread_type, bool invitable, uint16_t rate_limit_per_user); /** * @brief Edit a thread @@ -2277,9 +1967,7 @@ auto inline co_thread_create(const std::string& thread_name, snowflake channel_i * @return thread returned object on completion * \memberof dpp::cluster */ -auto inline co_thread_edit(const thread &t) { - return dpp::awaitable(this, [&] (auto cc) { this->thread_edit(t, cc); }); -} +awaitable co_thread_edit(const thread &t); /** * @brief Create a thread with a message (Discord: ID of a thread is same as message ID) @@ -2294,9 +1982,7 @@ auto inline co_thread_edit(const thread &t) { * @return thread returned object on completion * \memberof dpp::cluster */ -auto inline co_thread_create_with_message(const std::string& thread_name, snowflake channel_id, snowflake message_id, uint16_t auto_archive_duration, uint16_t rate_limit_per_user) { - return dpp::awaitable(this, [&] (auto cc) { this->thread_create_with_message(thread_name, channel_id, message_id, auto_archive_duration, rate_limit_per_user, cc); }); -} +awaitable co_thread_create_with_message(const std::string& thread_name, snowflake channel_id, snowflake message_id, uint16_t auto_archive_duration, uint16_t rate_limit_per_user); /** * @brief Add a member to a thread @@ -2307,9 +1993,7 @@ auto inline co_thread_create_with_message(const std::string& thread_name, snowfl * @return confirmation returned object on completion * \memberof dpp::cluster */ -auto inline co_thread_member_add(snowflake thread_id, snowflake user_id) { - return dpp::awaitable(this, [&] (auto cc) { this->thread_member_add(thread_id, user_id, cc); }); -} +awaitable co_thread_member_add(snowflake thread_id, snowflake user_id); /** * @brief Remove a member from a thread @@ -2320,9 +2004,7 @@ auto inline co_thread_member_add(snowflake thread_id, snowflake user_id) { * @return confirmation returned object on completion * \memberof dpp::cluster */ -auto inline co_thread_member_remove(snowflake thread_id, snowflake user_id) { - return dpp::awaitable(this, [&] (auto cc) { this->thread_member_remove(thread_id, user_id, cc); }); -} +awaitable co_thread_member_remove(snowflake thread_id, snowflake user_id); /** * @brief Edit current (bot) user @@ -2338,9 +2020,7 @@ auto inline co_thread_member_remove(snowflake thread_id, snowflake user_id) { * @throw dpp::length_exception Image data is larger than the maximum size of 256 kilobytes * \memberof dpp::cluster */ -auto inline co_current_user_edit(const std::string &nickname, const std::string& image_blob, const image_type type) { - return dpp::awaitable(this, [&] (auto cc) { this->current_user_edit(nickname, image_blob, type, cc); }); -} +awaitable co_current_user_edit(const std::string &nickname, const std::string& image_blob = "", const image_type type = i_png); /** * @brief Get current (bot) application @@ -2350,9 +2030,7 @@ auto inline co_current_user_edit(const std::string &nickname, const std::string& * @return application returned object on completion * \memberof dpp::cluster */ -auto inline co_current_application_get() { - return dpp::awaitable(this, [&] (auto cc) { this->current_application_get(cc); }); -} +awaitable co_current_application_get(); /** * @brief Get current (bot) user @@ -2364,9 +2042,7 @@ auto inline co_current_application_get() { * If you do not have these scopes, these fields are empty. You can safely convert a user_identified to user with `dynamic_cast`. * \memberof dpp::cluster */ -auto inline co_current_user_get() { - return dpp::awaitable(this, [&] (auto cc) { this->current_user_get(cc); }); -} +awaitable co_current_user_get(); /** * @brief Set the bot's voice state on a stage channel @@ -2391,9 +2067,7 @@ auto inline co_current_user_get() { * @throw std::logic_exception You attempted to set a request_to_speak_timestamp in the past which is not the value of 0. * \memberof dpp::cluster */ -auto inline co_current_user_set_voice_state(snowflake guild_id, snowflake channel_id, bool suppress, time_t request_to_speak_timestamp) { - return dpp::awaitable(this, [&] (auto cc) { this->current_user_set_voice_state(guild_id, channel_id, suppress, request_to_speak_timestamp, cc); }); -} +awaitable co_current_user_set_voice_state(snowflake guild_id, snowflake channel_id, bool suppress = false, time_t request_to_speak_timestamp = 0); /** * @brief Set a user's voice state on a stage channel @@ -2417,9 +2091,7 @@ auto inline co_current_user_set_voice_state(snowflake guild_id, snowflake channe * @param suppress True if the user's audio should be suppressed, false if it should not * \memberof dpp::cluster */ -auto inline co_user_set_voice_state(snowflake user_id, snowflake guild_id, snowflake channel_id, bool suppress) { - return dpp::awaitable(this, [&] (auto cc) { this->user_set_voice_state(user_id, guild_id, channel_id, suppress, cc); }); -} +awaitable co_user_set_voice_state(snowflake user_id, snowflake guild_id, snowflake channel_id, bool suppress = false); /** * @brief Get current user's connections (linked accounts, e.g. steam, xbox). @@ -2430,9 +2102,7 @@ auto inline co_user_set_voice_state(snowflake user_id, snowflake guild_id, snowf * @return connection_map returned object on completion * \memberof dpp::cluster */ -auto inline co_current_user_connections_get() { - return dpp::awaitable(this, [&] (auto cc) { this->current_user_connections_get(cc); }); -} +awaitable co_current_user_connections_get(); /** * @brief Get current (bot) user guilds @@ -2441,9 +2111,7 @@ auto inline co_current_user_connections_get() { * @return guild_map returned object on completion * \memberof dpp::cluster */ -auto inline co_current_user_get_guilds() { - return dpp::awaitable(this, [&] (auto cc) { this->current_user_get_guilds(cc); }); -} +awaitable co_current_user_get_guilds(); /** * @brief Leave a guild @@ -2453,9 +2121,7 @@ auto inline co_current_user_get_guilds() { * @return confirmation returned object on completion * \memberof dpp::cluster */ -auto inline co_current_user_leave_guild(snowflake guild_id) { - return dpp::awaitable(this, [&] (auto cc) { this->current_user_leave_guild(guild_id, cc); }); -} +awaitable co_current_user_leave_guild(snowflake guild_id); /** * @brief Get a user by id, without using the cache @@ -2470,9 +2136,7 @@ auto inline co_current_user_leave_guild(snowflake guild_id) { * Call `dpp::find_user` instead that looks up the user in the cache rather than a REST call. * \memberof dpp::cluster */ -auto inline co_user_get(snowflake user_id) { - return dpp::awaitable(this, [&] (auto cc) { this->user_get(user_id, cc); }); -} +awaitable co_user_get(snowflake user_id); /** * @brief Get a user by id, checking in the cache first @@ -2487,9 +2151,7 @@ auto inline co_user_get(snowflake user_id) { * where you want to for example resolve a user who may no longer be in the bot's guilds, for something like a ban log message. * \memberof dpp::cluster */ -auto inline co_user_get_cached(snowflake user_id) { - return dpp::awaitable(this, [&] (auto cc) { this->user_get_cached(user_id, cc); }); -} +awaitable co_user_get_cached(snowflake user_id); /** * @brief Get all voice regions @@ -2498,9 +2160,7 @@ auto inline co_user_get_cached(snowflake user_id) { * @return voiceregion_map returned object on completion * \memberof dpp::cluster */ -auto inline co_get_voice_regions() { - return dpp::awaitable(this, [&] (auto cc) { this->get_voice_regions(cc); }); -} +awaitable co_get_voice_regions(); /** * @brief Get guild voice regions. @@ -2515,9 +2175,7 @@ auto inline co_get_voice_regions() { * @return voiceregion_map returned object on completion * \memberof dpp::cluster */ -auto inline co_guild_get_voice_regions(snowflake guild_id) { - return dpp::awaitable(this, [&] (auto cc) { this->guild_get_voice_regions(guild_id, cc); }); -} +awaitable co_guild_get_voice_regions(snowflake guild_id); /** * @brief Create a webhook @@ -2528,9 +2186,7 @@ auto inline co_guild_get_voice_regions(snowflake guild_id) { * @return webhook returned object on completion * \memberof dpp::cluster */ -auto inline co_create_webhook(const class webhook &w) { - return dpp::awaitable(this, [&] (auto cc) { this->create_webhook(w, cc); }); -} +awaitable co_create_webhook(const class webhook &w); /** * @brief Delete a webhook @@ -2541,9 +2197,7 @@ auto inline co_create_webhook(const class webhook &w) { * @return confirmation returned object on completion * \memberof dpp::cluster */ -auto inline co_delete_webhook(snowflake webhook_id) { - return dpp::awaitable(this, [&] (auto cc) { this->delete_webhook(webhook_id, cc); }); -} +awaitable co_delete_webhook(snowflake webhook_id); /** * @brief Delete webhook message @@ -2556,9 +2210,7 @@ auto inline co_delete_webhook(snowflake webhook_id) { * @return confirmation returned object on completion * \memberof dpp::cluster */ -auto inline co_delete_webhook_message(const class webhook &wh, snowflake message_id, snowflake thread_id) { - return dpp::awaitable(this, [&] (auto cc) { this->delete_webhook_message(wh, message_id, thread_id, cc); }); -} +awaitable co_delete_webhook_message(const class webhook &wh, snowflake message_id, snowflake thread_id = 0); /** * @brief Delete webhook with token @@ -2569,9 +2221,7 @@ auto inline co_delete_webhook_message(const class webhook &wh, snowflake message * @return confirmation returned object on completion * \memberof dpp::cluster */ -auto inline co_delete_webhook_with_token(snowflake webhook_id, const std::string &token) { - return dpp::awaitable(this, [&] (auto cc) { this->delete_webhook_with_token(webhook_id, token, cc); }); -} +awaitable co_delete_webhook_with_token(snowflake webhook_id, const std::string &token); /** * @brief Edit webhook @@ -2582,9 +2232,7 @@ auto inline co_delete_webhook_with_token(snowflake webhook_id, const std::string * @return webhook returned object on completion * \memberof dpp::cluster */ -auto inline co_edit_webhook(const class webhook& wh) { - return dpp::awaitable(this, [&] (auto cc) { this->edit_webhook(wh, cc); }); -} +awaitable co_edit_webhook(const class webhook& wh); /** * @brief Edit webhook message @@ -2603,9 +2251,7 @@ auto inline co_edit_webhook(const class webhook& wh) { * @return message returned object on completion * \memberof dpp::cluster */ -auto inline co_edit_webhook_message(const class webhook &wh, const struct message& m, snowflake thread_id) { - return dpp::awaitable(this, [&] (auto cc) { this->edit_webhook_message(wh, m, thread_id, cc); }); -} +awaitable co_edit_webhook_message(const class webhook &wh, const struct message &m, snowflake thread_id = 0); /** * @brief Edit webhook with token (token is encapsulated in the webhook object) @@ -2615,9 +2261,7 @@ auto inline co_edit_webhook_message(const class webhook &wh, const struct messag * @return webhook returned object on completion * \memberof dpp::cluster */ -auto inline co_edit_webhook_with_token(const class webhook& wh) { - return dpp::awaitable(this, [&] (auto cc) { this->edit_webhook_with_token(wh, cc); }); -} +awaitable co_edit_webhook_with_token(const class webhook& wh); /** * @brief Execute webhook @@ -2633,9 +2277,7 @@ auto inline co_edit_webhook_with_token(const class webhook& wh) { * @note If the webhook channel is a forum channel, you must provide either `thread_id` or `thread_name`. If `thread_id` is provided, the message will send in that thread. If `thread_name` is provided, a thread with that name will be created in the forum channel. * \memberof dpp::cluster */ -auto inline co_execute_webhook(const class webhook &wh, const struct message& m, bool wait, snowflake thread_id, const std::string& thread_name) { - return dpp::awaitable(this, [&] (auto cc) { this->execute_webhook(wh, m, wait, thread_id, thread_name, cc); }); -} +awaitable co_execute_webhook(const class webhook &wh, const struct message &m, bool wait = false, snowflake thread_id = 0, const std::string& thread_name = ""); /** * @brief Get channel webhooks @@ -2645,9 +2287,7 @@ auto inline co_execute_webhook(const class webhook &wh, const struct message& m, * @return webhook_map returned object on completion * \memberof dpp::cluster */ -auto inline co_get_channel_webhooks(snowflake channel_id) { - return dpp::awaitable(this, [&] (auto cc) { this->get_channel_webhooks(channel_id, cc); }); -} +awaitable co_get_channel_webhooks(snowflake channel_id); /** * @brief Get guild webhooks @@ -2657,9 +2297,7 @@ auto inline co_get_channel_webhooks(snowflake channel_id) { * @return webhook_map returned object on completion * \memberof dpp::cluster */ -auto inline co_get_guild_webhooks(snowflake guild_id) { - return dpp::awaitable(this, [&] (auto cc) { this->get_guild_webhooks(guild_id, cc); }); -} +awaitable co_get_guild_webhooks(snowflake guild_id); /** * @brief Get webhook @@ -2669,9 +2307,7 @@ auto inline co_get_guild_webhooks(snowflake guild_id) { * @return webhook returned object on completion * \memberof dpp::cluster */ -auto inline co_get_webhook(snowflake webhook_id) { - return dpp::awaitable(this, [&] (auto cc) { this->get_webhook(webhook_id, cc); }); -} +awaitable co_get_webhook(snowflake webhook_id); /** * @brief Get webhook message @@ -2684,9 +2320,7 @@ auto inline co_get_webhook(snowflake webhook_id) { * @return message returned object on completion * \memberof dpp::cluster */ -auto inline co_get_webhook_message(const class webhook &wh, snowflake message_id, snowflake thread_id) { - return dpp::awaitable(this, [&] (auto cc) { this->get_webhook_message(wh, message_id, thread_id, cc); }); -} +awaitable co_get_webhook_message(const class webhook &wh, snowflake message_id, snowflake thread_id = 0); /** * @brief Get webhook using token @@ -2697,13 +2331,9 @@ auto inline co_get_webhook_message(const class webhook &wh, snowflake message_id * @return webhook returned object on completion * \memberof dpp::cluster */ -auto inline co_get_webhook_with_token(snowflake webhook_id, const std::string &token) { - return dpp::awaitable(this, [&] (auto cc) { this->get_webhook_with_token(webhook_id, token, cc); }); -} +awaitable co_get_webhook_with_token(snowflake webhook_id, const std::string &token); /* End of auto-generated definitions */ -auto inline co_request(const std::string &url, http_method method, const std::string &postdata = "", const std::string &mimetype = "text/plain", const std::multimap &headers = {}) { - return dpp::awaitable(this, [&] (auto cc) { this->request(url, method, cc, mimetype, headers); }); -} +awaitable co_request(const std::string &url, http_method method, const std::string &postdata = "", const std::string &mimetype = "text/plain", const std::multimap &headers = {}); diff --git a/include/dpp/coro.h b/include/dpp/coro.h index 900a67e43b..53ea155b9f 100644 --- a/include/dpp/coro.h +++ b/include/dpp/coro.h @@ -1,158 +1,693 @@ #ifdef DPP_CORO #pragma once -#include -#include -namespace dpp { - - /** - * @brief Shorthand for the coroutine handle's type - */ - using handle_type = std::coroutine_handle; +#if !(defined( _MSC_VER ) || defined( _CONSOLE ) || defined( __GNUC__ )) // if libc++ +# define EXPERIMENTAL_COROUTINE +#endif +#ifdef EXPERIMENTAL_COROUTINE +# include +#else +# include +#endif + +#include +#include +#include + +namespace dpp { class cluster; + struct confirmation_callback_t; /** - * @brief Return type for coroutines + * @brief Implementation details for internal use only. + * + * @attention This is only meant to be used by D++ internally. Support will not be given regarding the facilities in this namespace. */ - struct task { + namespace detail { +#ifdef _DOXYGEN_ /** - * @brief Required nested promise_type for coroutines + * @brief Alias for either std or std::experimental depending on compiler and library. Used by coroutine implementation. + * + * @todo Remove and use std when all supported libraries have coroutines in it */ - using promise_type = dpp::promise; - }; + namespace std_coroutine {} +#else +# ifdef EXPERIMENTAL_COROUTINE + namespace std_coroutine = std::experimental; +# else + namespace std_coroutine = std; +# endif +#endif + + /** + * @brief A task's promise type, with special logic for handling nested tasks. + */ + template + struct task_promise; + + /** + * @brief The object automatically co_await-ed at the end of a task. Ensures nested task chains are resolved, and the promise cleans up if it needs to. + */ + template + struct task_chain_final_awaiter; + + /** + * @brief Alias for std::coroutine_handle for a task_promise. + */ + template + using task_handle = detail::std_coroutine::coroutine_handle>; + } /** - * @brief Implementation of promise_type for dpp's coroutines + * @brief A coroutine task. It can be co_awaited to make nested coroutines. + * + * Can be used in conjunction with coroutine events via dpp::event_router_t::co_attach, or on its own. + * + * @warning This feature is EXPERIMENTAL. The API may change at any time and there may be bugs. Please report any to GitHub issues or to the D++ Discord server. + * @tparam ReturnType Return type of the coroutine. Can be void, or a complete object that supports move construction and move assignment. */ - struct promise { + template +#ifndef _DOXYGEN_ + requires std::is_same_v || (!std::is_reference_v && std::is_move_constructible_v && std::is_move_assignable_v) +#endif + class task { /** - * @brief A pointer to the cluster making the requests in the coroutine + * @brief The coroutine handle of this task. */ - cluster* bot = nullptr; + detail::task_handle handle; /** - * @brief The result of the last co_await-ed function + * @brief Promise type of this coroutine. For internal use only, do not use. */ - confirmation_callback_t callback; + friend struct detail::task_promise; /** - * @brief Construct a new promise object + * @brief Construct from a coroutine handle. Internal use only */ - promise() = default; + explicit task(detail::task_handle handle_) : handle(handle_) {} + public: /** - * @brief Construct a new promise object - * - * @param ev Base type of all events, only used to get the dpp::cluster pointer + * @brief Default constructor, creates a task not bound to a coroutine. */ - promise(const dpp::event_dispatch_t& ev) : bot(ev.from->creator) { } + task() = default; /** - * @brief Get the return object - * - * @return task dpp::task type + * @brief Copy constructor is disabled */ - task get_return_object() { - return {}; + task(const task &) = delete; + + /** + * @brief Move constructor, grabs another task's coroutine handle + * + * @param other Task to move the handle from + */ + task(task &&other) noexcept : handle(std::exchange(other.handle, nullptr)) {} + + + /** + * @brief Destructor. + * + * Destroys the handle if coroutine is done, otherwise detaches it from this thread. + * In detached mode, the handle will destroy itself at the end of the coroutine. + */ + ~task() { + if (handle) { + auto &promise = handle.promise(); + + if (!promise.is_sync) { + std::unique_lock lock{promise.mutex}; + + if (promise.destroy) // promise in async thread checked first and skipped clean up, we do it + { + if (promise.exception && promise.exception_handler) + promise.exception_handler(promise.exception); + lock.unlock(); + handle.destroy(); + } + else + handle.promise().destroy = true; + } + else { + if (promise.exception && promise.exception_handler) + promise.exception_handler(promise.exception); + handle.destroy(); + } + } } /** - * @brief Function called when the coroutine is first suspended, never suspends - * - * @return std::suspend_never Never suspend this coroutine at the first suspend point + * @brief Copy assignment is disabled + */ + task &operator=(const task &) = delete; + + /** + * @brief Move assignment, grabs another task's coroutine handle + * + * @param other Task to move the handle from */ - std::suspend_never initial_suspend() noexcept { - return {}; + task &operator=(task &&other) noexcept { + handle = std::exchange(other.handle, nullptr); + return (*this); } /** - * @brief Function called when the coroutine reaches its last suspension point - * - * @return std::suspend_never Never suspend this coroutine at the final suspend point + * @brief First function called by the standard library when the task is co_await-ed. + * + * @remark Do not call this manually, use the co_await keyword instead. + * @return bool Whether not to suspend the caller or not + */ + bool await_ready() { + return handle.done(); + } + + /** + * @brief Second function called by the standard library when the task is co_await-ed, if await_ready returned false. + * + * Stores the calling coroutine in the promise to resume when this task suspends. + * + * @remark Do not call this manually, use the co_await keyword instead. + * @param caller The calling coroutine, now suspended + * @return bool Whether to suspend the caller or not */ - std::suspend_never final_suspend() noexcept { - return {}; + template + bool await_suspend(detail::task_handle caller) noexcept { + auto &my_promise = handle.promise(); + + if (my_promise.is_sync) + return false; + my_promise.parent = caller; + caller.promise().is_sync = false; + return true; } /** - * @brief Function called when the coroutine returns nothing + * @brief Function called by the standard library when the coroutine is resumed. + * + * @remark Do not call this manually, use the co_await keyword instead. + * @throw Throws any exception thrown or uncaught by the coroutine + * @return ReturnType The result of the coroutine. It is the value the whole co-await expression evaluates to */ - void return_void() noexcept {} + ReturnType await_resume(); /** - * @brief Function called when coroutine throws a un-catch-ed exception. Does nothing + * @brief Function to check if the coroutine has finished its execution entirely + * + * @return bool Whether the coroutine is done. + * @see https://en.cppreference.com/w/cpp/coroutine/coroutine_handle/done */ - void unhandled_exception() { - /* try { std::rethrow_exception(std::current_exception()); } */ - /* catch (const std::exception& e) { std::cout << e.what() << '\n'; } */ + bool done() const noexcept { + return handle.done(); + } + + /** + * @brief Set the exception handling function. Called when an exception is thrown but not caught + * + * @warning The exception handler must not throw. If an exception that is not caught is thrown in a detached task, the program will terminate. + */ + task &on_exception(std::function func) { + handle.promise().exception_handler = std::move(func); + if (handle.promise().exception) + func(handle.promise().exception); + return *this; } }; + namespace detail { + /** + * @brief Awaitable returned from task_promise's final_suspend. Resumes the parent and cleans up its handle if needed + */ + template + struct task_chain_final_awaiter { + /** + * @brief Always suspend at the end of the task. This allows us to clean up and resume the parent + */ + bool await_ready() noexcept { + return (false); + } + + /* + * @brief The suspension logic of the coroutine when it finishes. Always suspend the caller, meaning cleaning up the handle is on us + * + * @param handle The handle of this coroutine + */ + void await_suspend(detail::task_handle handle) noexcept; + + /* + * @brief Function called when this object is co_awaited by the standard library at the end of final_suspend. Do nothing, return nothing + */ + void await_resume() noexcept {} + }; + /** + * @brief Base implementation of task_promise, without the logic that would depend on the return type. Meant to be inherited from + */ + struct task_promise_base { + /** + * @brief Mutex for async task destruction. + */ + std::mutex mutex{}; + + /** + * @brief Parent coroutine to return to for nested coroutines. + */ + detail::std_coroutine::coroutine_handle<> parent = nullptr; + + /** + * @brief Exception ptr if any was thrown during the coroutine + * + * @see std::exception_ptr + */ + std::exception_ptr exception = nullptr; + + /** + * @brief Whether the coroutine has async calls or not + * + * Will only ever change on the calling thread while callback mutex guards the async thread + */ + bool is_sync = true; + + /** + * @brief Whether either the task object or the promise is gone and the next one to end will clean up + */ + bool destroy = false; + + /** + * @brief Function object called when an exception is thrown from a coroutine + */ + std::function exception_handler = nullptr; + + /** + * @brief Function called by the standard library when the coroutine is created. + * + * @return std::suspend_never Don't suspend, the coroutine starts immediately. + */ + std::suspend_never initial_suspend() noexcept { + return {}; + } + + /** + * @brief Function called by the standard library when an exception is thrown and not caught in the coroutine. + * + * Stores the exception pointer to rethrow later + */ + void unhandled_exception() { + exception = std::current_exception(); + } + }; + + /** + * @brief Implementation of task_promise for non-void return type + */ + template + struct task_promise : task_promise_base { + /** + * @brief Stored return value of the coroutine. + * + * @details The main reason we use std::optional here and not ReturnType is to avoid default construction of the value so we only require ReturnType to have a move constructor, instead of both a default constructor and move assignment operator + */ + std::optional value = std::nullopt; + + /** + * @brief Function called by the standard library when the coroutine co_returns a value. + * + * Stores the value internally to hand to the caller when it resumes. + * + * @param expr The value given to co_return + */ + void return_value(ReturnType expr) { + value = std::move(expr); + } + + /** + * @brief Function called by the standard library when the coroutine is created. + * + * @return task The coroutine object + */ + task get_return_object() { + return task{task_handle::from_promise(*this)}; + } + + /** + * @brief Function called by the standard library when the coroutine reaches its last suspension point + * + * @return task_chain_final_awaiter Special object containing the chain resolution and clean-up logic. + */ + task_chain_final_awaiter final_suspend() noexcept { + return {}; + } + }; + + /** + * @brief Implementation of task_promise for void return type + */ + template <> + struct task_promise : task_promise_base { + /** + * @brief Function called by the standard library when the coroutine co_returns + * + * Does nothing but is required by the standard library. + */ + void return_void() {} + + /** + * @brief Function called by the standard library when the coroutine is created. + * + * @return task The coroutine object + */ + task get_return_object() { + return task{task_handle::from_promise(*this)}; + } + + /** + * @brief Function called by the standard library when the coroutine reaches its last suspension point + * + * @return task_chain_final_awaiter Special object containing the chain resolution and clean-up logic. + */ + task_chain_final_awaiter final_suspend() noexcept { + return {}; + } + }; + + template + void detail::task_chain_final_awaiter::await_suspend(detail::task_handle handle) noexcept { + task_promise &promise = handle.promise(); + std_coroutine::coroutine_handle<> parent = promise.parent; + + if (!promise.is_sync) { + std::unique_lock lock{promise.mutex}; + + if (promise.destroy) { + if (promise.exception && promise.exception_handler) + promise.exception_handler(promise.exception); + lock.unlock(); + handle.destroy(); + } + else + promise.destroy = true; // Send the destruction back to the task + } + if (parent) + parent.resume(); + } + } + + template +#ifndef _DOXYGEN_ + requires std::is_same_v || (!std::is_reference_v && std::is_move_constructible_v && std::is_move_assignable_v) +#endif + ReturnType task::await_resume() { + if (handle.promise().exception) // If we have an exception, rethrow + std::rethrow_exception(handle.promise().exception); + if constexpr (!std::is_same_v) // If we have a return type, return it and clean up our stored value + return std::forward(*std::exchange(handle.promise().value, std::nullopt)); + } + /** - * @brief A co_await-able struct which returns the result of stored api call when co_await-ed. Meant to be opaque to the user - * - * @tparam T The type of the function (lambda if auto-generated by the php script) handling the making of api call + * @brief A co_await-able object handling an API call. + * + * This class is the return type of the dpp::cluster::co_* methods, but it can also be created manually to wrap any async call. + * + * @remark - This object's methods, other than constructors and operators, should not be called directly. It is designed to be used with coroutine keywords such as co_await. + * @remark - This object must not be co_await-ed more than once. + * @remark - The coroutine may be resumed in another thread, do not rely on thread_local variables. + * @warning This feature is EXPERIMENTAL. The API may change at any time and there may be bugs. Please report any to GitHub issues or to the D++ Discord server. + * @tparam ReturnType The return type of the API call. Defaults to confirmation_callback_t */ - template - struct awaitable { + template + class awaitable { /** - * @brief Pointer to the nested promise object of the coroutine, used for storing and retrieving the result of an api call + * @brief Ref-counted callback, contains the callback logic and manages the lifetime of the callback data over multiple threads. */ - promise* p; - + struct shared_callback { + /** + * @brief State of the awaitable and its callback. + */ + struct callback_state { + enum state_t { + waiting, + done, + dangling + }; + + /** + * @brief Mutex to ensure the API result isn't set at the same time the coroutine is awaited and its value is checked, or the awaitable is destroyed + */ + std::mutex mutex{}; + + /** + * @brief Number of references to this callback state. + */ + int ref_count; + + /** + * @brief State of the awaitable and the API callback + */ + state_t state = waiting; + + /** + * @brief The stored result of the API call + */ + std::optional result = std::nullopt; + + /** + * @brief Handle to the coroutine co_await-ing on this API call + * + * @see std::coroutine_handle + */ + std::coroutine_handle<> coro_handle = nullptr; + }; + + /** + * @brief Callback function. + * + * @param cback The result of the API call. + */ + void operator()(const ReturnType &cback) const { + std::unique_lock lock{get_mutex()}; + + if (state->state == callback_state::dangling) // Awaitable is gone - likely an exception killed it or it was never co_await-ed + return; + state->result = cback; + state->state = callback_state::done; + if (state->coro_handle) { + auto handle = state->coro_handle; + state->coro_handle = nullptr; + lock.unlock(); + handle.resume(); + } + } + + /** + * @brief Main constructor, allocates a new callback_state object. + */ + shared_callback() : state{new callback_state{.ref_count = 1}} {} + + /** + * @brief Copy constructor. Takes shared ownership of the callback state, increasing the reference count. + */ + shared_callback(const shared_callback &other) { + this->operator=(other); + } + + /** + * @brief Move constructor. Transfers ownership from another object, leaving intact the reference count. The other object releases the callback state. + */ + shared_callback(shared_callback &&other) noexcept { + this->operator=(std::move(other)); + } + + /** + * @brief Copy assignment. Takes shared ownership of the callback state, increasing the reference count. + */ + shared_callback &operator=(const shared_callback &other) noexcept { + std::lock_guard lock{other.get_mutex()}; + + state = other.state; + ++state->ref_count; + return *this; + } + + /** + * @brief Move assignment. Transfers ownership from another object, leaving intact the reference count. The other object releases the callback state. + */ + shared_callback &operator=(shared_callback &&other) noexcept { + std::lock_guard lock{other.get_mutex()}; + + state = std::exchange(other.state, nullptr); + return *this; + } + + /** + * @brief Function called by the awaitable when it is destroyed when it was never co_awaited, signals to the callback to abort. + */ + void set_dangling() { + if (!state) // moved-from object + return; + std::lock_guard lock{get_mutex()}; + + if (state->state == callback_state::waiting) + state->state = callback_state::dangling; + } + + /** + * @brief Convenience function to get the shared callback state's mutex. + */ + std::mutex &get_mutex() const { + return (state->mutex); + } + + /** + * @brief Convenience function to get the shared callback state's result. + */ + std::optional &get_result() const { + return (state->result); + } + + /** + * @brief Destructor. Releases the held reference and destroys if no other references exist. + */ + ~shared_callback() { + if (!state) // Moved-from object + return; + + std::unique_lock lock{state->mutex}; + + if (state->ref_count) { + --(state->ref_count); + if (state->ref_count <= 0) {; + lock.unlock(); + delete state; + } + } + } + + callback_state *state; + }; + /** - * @brief Pointer to the cluster making the api request + * @brief Shared state of the awaitable and its callback, to be used across threads. */ - cluster* bot; + shared_callback api_callback; + public: /** - * @brief The function handling the making of request, using the cluster pointer + * @brief Construct an awaitable wrapping an object method, the call is made immediately by forwarding to std::invoke and can be awaited later to retrieve the result. + * + * @param obj The object to call the method on + * @param fun The method of the object to call. Its last parameter must be a callback taking a parameter of type ReturnType + * @param args Parameters to pass to the method, excluding the callback */ - T api_req; + template +#ifndef _DOXYGEN_ + requires std::invocable> +#endif + awaitable(Obj &&obj, Fun &&fun, Args&&... args) : api_callback{} { + std::invoke(std::forward(fun), std::forward(obj), std::forward(args)..., api_callback); + } /** - * @brief Construct a new awaitable object - * - * @param cl pointer to the cluster making the api request - * @param api_call a function to invoke with the cluster pointer, handles the making of request + * @brief Construct an awaitable wrapping an invokeable object, the call is made immediately by forwarding to std::invoke and can be awaited later to retrieve the result. + * + * @param fun The object to call using std::invoke. Its last parameter must be a callable taking a parameter of type ReturnType + * @param args Parameters to pass to the object, excluding the callback + */ + template +#ifndef _DOXYGEN_ + requires std::invocable> +#endif + awaitable(Fun &&fun, Args&&... args) : api_callback{} { + std::invoke(std::forward(fun), std::forward(args)..., api_callback); + } + + /** + * @brief Destructor. If any callback is pending it will be aborted. + * + */ + ~awaitable() { + api_callback.set_dangling(); + } + + /** + * @brief Copy constructor is disabled + */ + awaitable(const awaitable &) = delete; + + /** + * @brief Move constructor + * + * NOTE: Despite being marked noexcept, this function uses std::lock_guard which may throw. The implementation assumes this can never happen, hence noexcept. Report it if it does, as that would be a bug. + * + * @remark Using the moved-from awaitable after this function is undefined behavior. + * @param other The awaitable object to move the data from. */ - awaitable(cluster* cl, T api_call) : bot{cl}, api_req{api_call} {} + awaitable(awaitable &&other) noexcept = default; /** - * @brief First function called when this object is co_await-ed, its return type tells if the coroutine should be immediately suspended + * @brief Copy assignment is disabled + */ + awaitable &operator=(const awaitable &) = delete; + + /** + * @brief Move assignment operator. + * + * NOTE: Despite being marked noexcept, this function uses std::lock_guard which may throw. The implementation assumes this can never happen, hence noexcept. Report it if it does, as that would be a bug. + * + * @remark Using the moved-from awaitable after this function is undefined behavior. + * @param other The awaitable object to move the data from + */ + awaitable &operator=(awaitable &&other) noexcept = default; + + /** + * @brief First function called by the standard library when the object is co-awaited. * - * @return bool false, signifying immediate suspension + * Returns whether we already have the result of the API call and don't need to suspend the caller. + * + * @remark Do not call this manually, use the co_await keyword instead. + * @return bool Whether we already have the result of the API call or not */ bool await_ready() noexcept { - return false; + std::lock_guard lock{api_callback.get_mutex()}; + + return api_callback.get_result().has_value(); } /** - * @brief Function called when the coroutine is suspended, makes the api request and queues the resumption of the suspended coroutine, storing the result in promise object - * - * @param handle the handle to the suspended coroutine + * @brief Second function called by the standard library when the object is co-awaited, if await_ready returned false. + * + * Checks again for the presence of the result, if absent, signals to suspend and keep track of the calling coroutine for the callback to resume. + * + * @remark Do not call this manually, use the co_await keyword instead. + * @param handle The handle to the coroutine co_await-ing and being suspended */ - void await_suspend(handle_type handle) { - /* p = &handle.promise(); */ - /* if (!p->bot) p->bot = bot; */ - api_req([handle](const confirmation_callback_t& cback) { handle.promise().callback = cback; handle.resume(); }); + template + bool await_suspend(detail::task_handle handle) { + std::lock_guard lock{api_callback.get_mutex()}; + + if (api_callback.get_result().has_value()) + return false; // immediately resume the coroutine as we already have the result of the api call + handle.promise().is_sync = false; + api_callback.state->coro_handle = handle; + return true; // suspend the caller, the callback will resume it } /** - * @brief Function called when the coroutine is resumed by its handle, handles the retrieval and return of result from promise object - * - * @return confirmation_callback_t the result of the api call + * @brief Function called by the standard library when the awaitable is resumed. Its return value is what the whole co_await expression evaluates to + * + * @remark Do not call this manually, use the co_await keyword instead. + * @return ReturnType The result of the API call. */ - confirmation_callback_t await_resume() { - return p->callback; + ReturnType await_resume() { + return std::move(*api_callback.get_result()); } }; +}; +/** + * @brief Specialization of std::coroutine_traits, helps the standard library figure out a promise type from a coroutine function. + */ +template +struct dpp::detail::std_coroutine::coroutine_traits, Args...> { + using promise_type = dpp::detail::task_promise; }; -/* template<> */ -/* struct std::coroutine_traits { */ -/* using promise_type = dpp::promise; */ -/* }; */ #endif diff --git a/include/dpp/dispatcher.h b/include/dpp/dispatcher.h index 330466a47d..58c0643393 100644 --- a/include/dpp/dispatcher.h +++ b/include/dpp/dispatcher.h @@ -47,6 +47,10 @@ #include #include +#ifdef DPP_CORO +#include +#endif /* DPP_CORO */ + namespace dpp { /* Forward declaration */ @@ -474,6 +478,106 @@ struct DPP_EXPORT interaction_create_t : public event_dispatch_t { */ void delete_original_response(command_completion_event_t callback = utility::log_error()) const; +#ifdef DPP_CORO + /** + * @brief Acknowledge interaction without displaying a message to the user, + * for use with button and select menu components. + * + * On success the result will contain a dpp::confirmation object in confirmation_callback_t::value. On failure, the value is undefined and confirmation_callback_t::is_error() method will return true. You can obtain full error details with confirmation_callback_t::get_error(). + */ + dpp::awaitable co_reply() const; + + /** + * @brief Send a reply for this interaction + * + * @param t Type of reply to send + * @param m Message object to send. Not all fields are supported by Discord. + * On success the result will contain a dpp::confirmation object in confirmation_callback_t::value. On failure, the value is undefined and confirmation_callback_t::is_error() method will return true. You can obtain full error details with confirmation_callback_t::get_error(). + */ + dpp::awaitable co_reply(interaction_response_type t, const message & m) const; + + /** + * @brief Send a reply for this interaction + * + * @param t Type of reply to send + * @param mt The string value to send, for simple text only messages + * On success the result will contain a dpp::confirmation object in confirmation_callback_t::value. On failure, the value is undefined and confirmation_callback_t::is_error() method will return true. You can obtain full error details with confirmation_callback_t::get_error(). + */ + dpp::awaitable co_reply(interaction_response_type t, const std::string & mt) const; + + /** + * @brief Send a reply for this interaction. + * Uses the default type of dpp::ir_channel_message_with_source, a simple message reply. + * + * @param m Message object to send. Not all fields are supported by Discord. + * On success the result will contain a dpp::confirmation object in confirmation_callback_t::value. On failure, the value is undefined and confirmation_callback_t::is_error() method will return true. You can obtain full error details with confirmation_callback_t::get_error(). + */ + dpp::awaitable co_reply(const message & m) const; + + /** + * @brief Send a reply for this interaction. + * Uses the default type of dpp::ir_channel_message_with_source, a simple message reply. + * + * @param mt The string value to send, for simple text only messages + * On success the result will contain a dpp::confirmation object in confirmation_callback_t::value. On failure, the value is undefined and confirmation_callback_t::is_error() method will return true. You can obtain full error details with confirmation_callback_t::get_error(). + */ + dpp::awaitable co_reply(const std::string & mt) const; + + /** + * @brief Reply to interaction with a dialog box + * + * @param mr Dialog box response to send + * On success the result will contain a dpp::confirmation object in confirmation_callback_t::value. On failure, the value is undefined and confirmation_callback_t::is_error() method will return true. You can obtain full error details with confirmation_callback_t::get_error(). + */ + dpp::awaitable co_dialog(const interaction_modal_response& mr) const; + + /** + * @brief Edit the response for this interaction + * + * @param m Message object to send. Not all fields are supported by Discord. + * On success the result will contain a dpp::confirmation object in confirmation_callback_t::value. On failure, the value is undefined and confirmation_callback_t::is_error() method will return true. You can obtain full error details with confirmation_callback_t::get_error(). + */ + dpp::awaitable co_edit_response(const message & m) const; + + /** + * @brief Edit the response for this interaction + * + * @param mt The string value to send, for simple text only messages + * On success the result will contain a dpp::confirmation object in confirmation_callback_t::value. On failure, the value is undefined and confirmation_callback_t::is_error() method will return true. You can obtain full error details with confirmation_callback_t::get_error(). + */ + dpp::awaitable co_edit_response(const std::string & mt) const; + + /** + * @brief Set the bot to 'thinking' state where you have up to 15 minutes to respond + * + * @param ephemeral True if the thinking state should be ephemeral + * On success the result will contain a dpp::confirmation object in confirmation_callback_t::value. On failure, the value is undefined and confirmation_callback_t::is_error() method will return true. You can obtain full error details with confirmation_callback_t::get_error(). + */ + dpp::awaitable co_thinking(bool ephemeral = false) const; + + /** + * @brief Get original response message for this interaction + * + * On success the result will contain a dpp::message object in confirmation_callback_t::value. On failure, the value is undefined and confirmation_callback_t::is_error() method will return true. You can obtain full error details with confirmation_callback_t::get_error(). + */ + dpp::awaitable co_get_original_response() const; + + /** + * @brief Edit original response message for this interaction + * + * @param m Message object to send. Not all fields are supported by Discord. + * On success the result will contain a dpp::message object in confirmation_callback_t::value. On failure, the value is undefined and confirmation_callback_t::is_error() method will return true. You can obtain full error details with confirmation_callback_t::get_error(). + */ + dpp::awaitable co_edit_original_response(const message & m) const; + + /** + * @brief Delete original response message for this interaction. This cannot be used on an ephemeral interaction response. + * + * On success the result will contain a dpp::confirmation object in confirmation_callback_t::value. On failure, the value is undefined and confirmation_callback_t::is_error() method will return true. You can obtain full error details with confirmation_callback_t::get_error(). + */ + dpp::awaitable co_delete_original_response() const; +#endif /* DPP_CORO */ + /** * @brief command interaction */ diff --git a/include/dpp/event_router.h b/include/dpp/event_router.h index 4f901fd394..6e2b2208b7 100644 --- a/include/dpp/event_router.h +++ b/include/dpp/event_router.h @@ -105,14 +105,18 @@ template class event_router_t { #ifdef DPP_CORO /** * @brief Container for event listeners (coroutines only) + * + * Note: keep a listener's parameter as a value type, the event passed can die while a coroutine is suspended */ - std::map> coroutine_container; + std::map(T)>> coroutine_container; #else - /** - * @brief Dummy container to keep the struct size same - */ - std::map> dummy_container; -#endif +#ifndef _DOXYGEN_ + /** + * @brief Dummy container to keep the struct size same + */ + std::map> dummy_container; +#endif /* _DOXYGEN_ */ +#endif /* DPP_CORO */ /** @@ -160,12 +164,23 @@ template class event_router_t { } }); #ifdef DPP_CORO + auto coro_exception_handler = [from = event.from](std::exception_ptr ptr) { + try { + std::rethrow_exception(ptr); + } + catch (const std::exception &exception) { + if (from && from->creator) + from->creator->log(dpp::loglevel::ll_error, std::string{"Uncaught exception in event coroutine: "} + exception.what()); + } + }; std::for_each(coroutine_container.begin(), coroutine_container.end(), [&](auto &ev) { if (!event.is_cancelled()) { - ev.second(event); + dpp::task task = ev.second(event); + + task.on_exception(coro_exception_handler); } }); -#endif +#endif /* DPP_CORO */ }; /** @@ -177,7 +192,11 @@ template class event_router_t { */ bool empty() const { std::shared_lock l(lock); +#ifdef DPP_CORO + return dispatch_container.empty() && coroutine_container.empty(); +#else return dispatch_container.empty(); +#endif /* DPP_CORO */ } /** @@ -210,7 +229,7 @@ template class event_router_t { * The lambda should follow the signature specified when declaring * the event object and should take exactly one parameter derived * from event_dispatch_t. - * + * * @param func Function lambda to attach to event * @return event_handle An event handle unique to this event, used to * detach the listener from the event later if necessary. @@ -219,17 +238,27 @@ template class event_router_t { std::unique_lock l(lock); event_handle h = next_handle++; dispatch_container.emplace(h, func); - return h; + return h; } #ifdef DPP_CORO - event_handle co_attach(std::function func) { + /** + * @brief Attach a coroutine task to the event, adding a listener. + * The coroutine should follow the signature specified when declaring + * the event object and should take exactly one parameter derived + * from event_dispatch_t. + * + * @param func Coroutine task to attack to the event + * @return event_handle An event handle unique to this event, used to + * detach the listener from the event later if necessary. + */ + event_handle co_attach(std::function(T)> func) { std::unique_lock l(lock); event_handle h = next_handle++; coroutine_container.emplace(h, func); - return h; + return h; } -#endif +#endif /* DPP_CORO */ /** * @brief Detach a listener from the event using a previously obtained ID. * @@ -239,7 +268,11 @@ template class event_router_t { */ bool detach(const event_handle& handle) { std::unique_lock l(lock); +#ifdef DPP_CORO + return this->dispatch_container.erase(handle) || this->coroutine_container.erase(handle); +#else return this->dispatch_container.erase(handle); +#endif /* DPP_CORO */ } }; diff --git a/library/CMakeLists.txt b/library/CMakeLists.txt index dc1f7f2955..c98c575786 100644 --- a/library/CMakeLists.txt +++ b/library/CMakeLists.txt @@ -176,9 +176,9 @@ endif() if(MSVC) if(CMAKE_BUILD_TYPE STREQUAL "Debug") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /std:c++17 /Od /DEBUG /Zi /sdl /DFD_SETSIZE=1024") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /Od /DEBUG /Zi /sdl /DFD_SETSIZE=1024") else() - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /std:c++17 /O2 /Oi /Oy /Gy /sdl /DFD_SETSIZE=1024") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /O2 /Oi /Oy /Gy /sdl /DFD_SETSIZE=1024") endif() if(NOT "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP /Zc:preprocessor") @@ -294,11 +294,16 @@ endif() if(DPP_CORO) message("-- ${Yellow}Enabled experimental coroutine support${ColourReset}") set(CMAKE_CXX_STANDARD 20) - target_compile_features(dpp PRIVATE cxx_std_20) + target_compile_features(dpp PUBLIC cxx_std_20) if(WIN32 AND NOT MINGW) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /await:strict") else() - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fcoroutines") + if(CMAKE_CXX_COMPILER_ID MATCHES "Clang") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++") + target_link_libraries(dpp PUBLIC "c++abi") + else() + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fcoroutines") + endif() endif() target_compile_definitions(dpp PUBLIC DPP_CORO) execute_process(WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/.." diff --git a/src/dpp/cluster/timer.cpp b/src/dpp/cluster/timer.cpp index 816af14923..c843c04ad0 100644 --- a/src/dpp/cluster/timer.cpp +++ b/src/dpp/cluster/timer.cpp @@ -104,6 +104,17 @@ void cluster::tick_timers() { } } +#ifdef DPP_CORO +awaitable cluster::co_timer(uint64_t seconds) { + return {[this, seconds] (auto &&cb) { + start_timer([this, cb](dpp::timer handle) { + cb(handle); + stop_timer(handle); + }, seconds); + }}; +} +#endif + oneshot_timer::oneshot_timer(class cluster* cl, uint64_t duration, timer_callback_t callback) : owner(cl) { /* Create timer */ th = cl->start_timer([callback, this](dpp::timer timer_handle) { diff --git a/src/dpp/cluster_coro_calls.cpp b/src/dpp/cluster_coro_calls.cpp new file mode 100644 index 0000000000..5eea1a0bc4 --- /dev/null +++ b/src/dpp/cluster_coro_calls.cpp @@ -0,0 +1,782 @@ +/************************************************************************************ + * + * D++, A Lightweight C++ library for Discord + * + * Copyright 2022 Craig Edwards and D++ contributors + * (https://github.com/brainboxdotcc/DPP/graphs/contributors) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ************************************************************************************/ + + +/* Auto @generated by buildtools/make_coro_struct.php. + * + * DO NOT EDIT BY HAND! + * + * To re-generate this header file re-run the script! + */ +#ifdef DPP_CORO + +#include +#include +#include +#include + +namespace dpp { + +awaitable cluster::co_global_bulk_command_create(const std::vector &commands) { + return {this, static_cast &, command_completion_event_t)>(&cluster::global_bulk_command_create), commands}; +} + +awaitable cluster::co_global_command_create(const slashcommand &s) { + return {this, static_cast(&cluster::global_command_create), s}; +} + +awaitable cluster::co_global_command_get(snowflake id) { + return {this, static_cast(&cluster::global_command_get), id}; +} + +awaitable cluster::co_global_command_delete(snowflake id) { + return {this, static_cast(&cluster::global_command_delete), id}; +} + +awaitable cluster::co_global_command_edit(const slashcommand &s) { + return {this, static_cast(&cluster::global_command_edit), s}; +} + +awaitable cluster::co_global_commands_get() { + return {this, static_cast(&cluster::global_commands_get)}; +} + +awaitable cluster::co_guild_bulk_command_create(const std::vector &commands, snowflake guild_id) { + return {this, static_cast &, snowflake, command_completion_event_t)>(&cluster::guild_bulk_command_create), commands, guild_id}; +} + +awaitable cluster::co_guild_commands_get_permissions(snowflake guild_id) { + return {this, static_cast(&cluster::guild_commands_get_permissions), guild_id}; +} + +awaitable cluster::co_guild_bulk_command_edit_permissions(const std::vector &commands, snowflake guild_id) { + return {this, static_cast &, snowflake, command_completion_event_t)>(&cluster::guild_bulk_command_edit_permissions), commands, guild_id}; +} + +awaitable cluster::co_guild_command_create(const slashcommand &s, snowflake guild_id) { + return {this, static_cast(&cluster::guild_command_create), s, guild_id}; +} + +awaitable cluster::co_guild_command_delete(snowflake id, snowflake guild_id) { + return {this, static_cast(&cluster::guild_command_delete), id, guild_id}; +} + +awaitable cluster::co_guild_command_edit_permissions(const slashcommand &s, snowflake guild_id) { + return {this, static_cast(&cluster::guild_command_edit_permissions), s, guild_id}; +} + +awaitable cluster::co_guild_command_get(snowflake id, snowflake guild_id) { + return {this, static_cast(&cluster::guild_command_get), id, guild_id}; +} + +awaitable cluster::co_guild_command_get_permissions(snowflake id, snowflake guild_id) { + return {this, static_cast(&cluster::guild_command_get_permissions), id, guild_id}; +} + +awaitable cluster::co_guild_command_edit(const slashcommand &s, snowflake guild_id) { + return {this, static_cast(&cluster::guild_command_edit), s, guild_id}; +} + +awaitable cluster::co_guild_commands_get(snowflake guild_id) { + return {this, static_cast(&cluster::guild_commands_get), guild_id}; +} + +awaitable cluster::co_interaction_response_create(snowflake interaction_id, const std::string &token, const interaction_response &r) { + return {this, static_cast(&cluster::interaction_response_create), interaction_id, token, r}; +} + +awaitable cluster::co_interaction_response_edit(const std::string &token, const message &m) { + return {this, static_cast(&cluster::interaction_response_edit), token, m}; +} + +awaitable cluster::co_interaction_response_get_original(const std::string &token) { + return {this, static_cast(&cluster::interaction_response_get_original), token}; +} + +awaitable cluster::co_interaction_followup_create(const std::string &token, const message &m) { + return {this, static_cast(&cluster::interaction_followup_create), token, m}; +} + +awaitable cluster::co_interaction_followup_edit_original(const std::string &token, const message &m) { + return {this, static_cast(&cluster::interaction_followup_edit_original), token, m}; +} + +awaitable cluster::co_interaction_followup_delete(const std::string &token) { + return {this, static_cast(&cluster::interaction_followup_delete), token}; +} + +awaitable cluster::co_interaction_followup_edit(const std::string &token, const message &m) { + return {this, static_cast(&cluster::interaction_followup_edit), token, m}; +} + +awaitable cluster::co_interaction_followup_get(const std::string &token, snowflake message_id) { + return {this, static_cast(&cluster::interaction_followup_get), token, message_id}; +} + +awaitable cluster::co_interaction_followup_get_original(const std::string &token) { + return {this, static_cast(&cluster::interaction_followup_get_original), token}; +} + +awaitable cluster::co_automod_rules_get(snowflake guild_id) { + return {this, static_cast(&cluster::automod_rules_get), guild_id}; +} + +awaitable cluster::co_automod_rule_get(snowflake guild_id, snowflake rule_id) { + return {this, static_cast(&cluster::automod_rule_get), guild_id, rule_id}; +} + +awaitable cluster::co_automod_rule_create(snowflake guild_id, const automod_rule& r) { + return {this, static_cast(&cluster::automod_rule_create), guild_id, r}; +} + +awaitable cluster::co_automod_rule_edit(snowflake guild_id, const automod_rule& r) { + return {this, static_cast(&cluster::automod_rule_edit), guild_id, r}; +} + +awaitable cluster::co_automod_rule_delete(snowflake guild_id, snowflake rule_id) { + return {this, static_cast(&cluster::automod_rule_delete), guild_id, rule_id}; +} + +awaitable cluster::co_channel_create(const class channel &c) { + return {this, static_cast(&cluster::channel_create), c}; +} + +awaitable cluster::co_channel_delete_permission(const class channel &c, snowflake overwrite_id) { + return {this, static_cast(&cluster::channel_delete_permission), c, overwrite_id}; +} + +awaitable cluster::co_channel_delete(snowflake channel_id) { + return {this, static_cast(&cluster::channel_delete), channel_id}; +} + +awaitable cluster::co_channel_edit_permissions(const class channel &c, const snowflake overwrite_id, const uint64_t allow, const uint64_t deny, const bool member) { + return {this, static_cast(&cluster::channel_edit_permissions), c, overwrite_id, allow, deny, member}; +} + +awaitable cluster::co_channel_edit_permissions(const snowflake channel_id, const snowflake overwrite_id, const uint64_t allow, const uint64_t deny, const bool member) { + return {this, static_cast(&cluster::channel_edit_permissions), channel_id, overwrite_id, allow, deny, member}; +} + +awaitable cluster::co_channel_edit_positions(const std::vector &c) { + return {this, static_cast &, command_completion_event_t)>(&cluster::channel_edit_positions), c}; +} + +awaitable cluster::co_channel_edit(const class channel &c) { + return {this, static_cast(&cluster::channel_edit), c}; +} + +awaitable cluster::co_channel_follow_news(const class channel &c, snowflake target_channel_id) { + return {this, static_cast(&cluster::channel_follow_news), c, target_channel_id}; +} + +awaitable cluster::co_channel_get(snowflake c) { + return {this, static_cast(&cluster::channel_get), c}; +} + +awaitable cluster::co_channel_invite_create(const class channel &c, const class invite &i) { + return {this, static_cast(&cluster::channel_invite_create), c, i}; +} + +awaitable cluster::co_channel_invites_get(const class channel &c) { + return {this, static_cast(&cluster::channel_invites_get), c}; +} + +awaitable cluster::co_channel_typing(const class channel &c) { + return {this, static_cast(&cluster::channel_typing), c}; +} + +awaitable cluster::co_channel_typing(snowflake cid) { + return {this, static_cast(&cluster::channel_typing), cid}; +} + +awaitable cluster::co_channels_get(snowflake guild_id) { + return {this, static_cast(&cluster::channels_get), guild_id}; +} + +awaitable cluster::co_create_dm_channel(snowflake user_id) { + return {this, static_cast(&cluster::create_dm_channel), user_id}; +} + +awaitable cluster::co_current_user_get_dms() { + return {this, static_cast(&cluster::current_user_get_dms)}; +} + +awaitable cluster::co_direct_message_create(snowflake user_id, const message &m) { + return {this, static_cast(&cluster::direct_message_create), user_id, m}; +} + +awaitable cluster::co_gdm_add(snowflake channel_id, snowflake user_id, const std::string &access_token, const std::string &nick) { + return {this, static_cast(&cluster::gdm_add), channel_id, user_id, access_token, nick}; +} + +awaitable cluster::co_gdm_remove(snowflake channel_id, snowflake user_id) { + return {this, static_cast(&cluster::gdm_remove), channel_id, user_id}; +} + +awaitable cluster::co_guild_emoji_create(snowflake guild_id, const class emoji& newemoji) { + return {this, static_cast(&cluster::guild_emoji_create), guild_id, newemoji}; +} + +awaitable cluster::co_guild_emoji_delete(snowflake guild_id, snowflake emoji_id) { + return {this, static_cast(&cluster::guild_emoji_delete), guild_id, emoji_id}; +} + +awaitable cluster::co_guild_emoji_edit(snowflake guild_id, const class emoji& newemoji) { + return {this, static_cast(&cluster::guild_emoji_edit), guild_id, newemoji}; +} + +awaitable cluster::co_guild_emoji_get(snowflake guild_id, snowflake emoji_id) { + return {this, static_cast(&cluster::guild_emoji_get), guild_id, emoji_id}; +} + +awaitable cluster::co_guild_emojis_get(snowflake guild_id) { + return {this, static_cast(&cluster::guild_emojis_get), guild_id}; +} + +awaitable cluster::co_get_gateway_bot() { + return {this, static_cast(&cluster::get_gateway_bot)}; +} + +awaitable cluster::co_guild_current_member_edit(snowflake guild_id, const std::string &nickname) { + return {this, static_cast(&cluster::guild_current_member_edit), guild_id, nickname}; +} + +awaitable cluster::co_guild_auditlog_get(snowflake guild_id, snowflake user_id, uint32_t action_type, snowflake before, snowflake after, uint32_t limit) { + return {this, static_cast(&cluster::guild_auditlog_get), guild_id, user_id, action_type, before, after, limit}; +} + +awaitable cluster::co_guild_ban_add(snowflake guild_id, snowflake user_id, uint32_t delete_message_seconds) { + return {this, static_cast(&cluster::guild_ban_add), guild_id, user_id, delete_message_seconds}; +} + +awaitable cluster::co_guild_ban_delete(snowflake guild_id, snowflake user_id) { + return {this, static_cast(&cluster::guild_ban_delete), guild_id, user_id}; +} + +awaitable cluster::co_guild_create(const class guild &g) { + return {this, static_cast(&cluster::guild_create), g}; +} + +awaitable cluster::co_guild_delete(snowflake guild_id) { + return {this, static_cast(&cluster::guild_delete), guild_id}; +} + +awaitable cluster::co_guild_delete_integration(snowflake guild_id, snowflake integration_id) { + return {this, static_cast(&cluster::guild_delete_integration), guild_id, integration_id}; +} + +awaitable cluster::co_guild_edit(const class guild &g) { + return {this, static_cast(&cluster::guild_edit), g}; +} + +awaitable cluster::co_guild_edit_widget(snowflake guild_id, const class guild_widget &gw) { + return {this, static_cast(&cluster::guild_edit_widget), guild_id, gw}; +} + +awaitable cluster::co_guild_get_ban(snowflake guild_id, snowflake user_id) { + return {this, static_cast(&cluster::guild_get_ban), guild_id, user_id}; +} + +awaitable cluster::co_guild_get_bans(snowflake guild_id, snowflake before, snowflake after, snowflake limit) { + return {this, static_cast(&cluster::guild_get_bans), guild_id, before, after, limit}; +} + +awaitable cluster::co_guild_get(snowflake guild_id) { + return {this, static_cast(&cluster::guild_get), guild_id}; +} + +awaitable cluster::co_guild_get_integrations(snowflake guild_id) { + return {this, static_cast(&cluster::guild_get_integrations), guild_id}; +} + +awaitable cluster::co_guild_get_preview(snowflake guild_id) { + return {this, static_cast(&cluster::guild_get_preview), guild_id}; +} + +awaitable cluster::co_guild_get_vanity(snowflake guild_id) { + return {this, static_cast(&cluster::guild_get_vanity), guild_id}; +} + +awaitable cluster::co_guild_get_widget(snowflake guild_id) { + return {this, static_cast(&cluster::guild_get_widget), guild_id}; +} + +awaitable cluster::co_guild_modify_integration(snowflake guild_id, const class integration &i) { + return {this, static_cast(&cluster::guild_modify_integration), guild_id, i}; +} + +awaitable cluster::co_guild_get_prune_counts(snowflake guild_id, const struct prune& pruneinfo) { + return {this, static_cast(&cluster::guild_get_prune_counts), guild_id, pruneinfo}; +} + +awaitable cluster::co_guild_begin_prune(snowflake guild_id, const struct prune& pruneinfo) { + return {this, static_cast(&cluster::guild_begin_prune), guild_id, pruneinfo}; +} + +awaitable cluster::co_guild_set_nickname(snowflake guild_id, const std::string &nickname) { + return {this, static_cast(&cluster::guild_set_nickname), guild_id, nickname}; +} + +awaitable cluster::co_guild_sync_integration(snowflake guild_id, snowflake integration_id) { + return {this, static_cast(&cluster::guild_sync_integration), guild_id, integration_id}; +} + +awaitable cluster::co_guild_add_member(const guild_member& gm, const std::string &access_token) { + return {this, static_cast(&cluster::guild_add_member), gm, access_token}; +} + +awaitable cluster::co_guild_edit_member(const guild_member& gm) { + return {this, static_cast(&cluster::guild_edit_member), gm}; +} + +awaitable cluster::co_guild_get_member(snowflake guild_id, snowflake user_id) { + return {this, static_cast(&cluster::guild_get_member), guild_id, user_id}; +} + +awaitable cluster::co_guild_get_members(snowflake guild_id, uint16_t limit, snowflake after) { + return {this, static_cast(&cluster::guild_get_members), guild_id, limit, after}; +} + +awaitable cluster::co_guild_member_add_role(snowflake guild_id, snowflake user_id, snowflake role_id) { + return {this, static_cast(&cluster::guild_member_add_role), guild_id, user_id, role_id}; +} + +awaitable cluster::co_guild_member_delete(snowflake guild_id, snowflake user_id) { + return {this, static_cast(&cluster::guild_member_delete), guild_id, user_id}; +} + +awaitable cluster::co_guild_member_kick(snowflake guild_id, snowflake user_id) { + return {this, static_cast(&cluster::guild_member_kick), guild_id, user_id}; +} + +awaitable cluster::co_guild_member_timeout(snowflake guild_id, snowflake user_id, time_t communication_disabled_until) { + return {this, static_cast(&cluster::guild_member_timeout), guild_id, user_id, communication_disabled_until}; +} + +awaitable cluster::co_guild_member_delete_role(snowflake guild_id, snowflake user_id, snowflake role_id) { + return {this, static_cast(&cluster::guild_member_delete_role), guild_id, user_id, role_id}; +} + +awaitable cluster::co_guild_member_remove_role(snowflake guild_id, snowflake user_id, snowflake role_id) { + return {this, static_cast(&cluster::guild_member_remove_role), guild_id, user_id, role_id}; +} + +awaitable cluster::co_guild_member_move(const snowflake channel_id, const snowflake guild_id, const snowflake user_id) { + return {this, static_cast(&cluster::guild_member_move), channel_id, guild_id, user_id}; +} + +awaitable cluster::co_guild_search_members(snowflake guild_id, const std::string& query, uint16_t limit) { + return {this, static_cast(&cluster::guild_search_members), guild_id, query, limit}; +} + +awaitable cluster::co_guild_get_invites(snowflake guild_id) { + return {this, static_cast(&cluster::guild_get_invites), guild_id}; +} + +awaitable cluster::co_invite_delete(const std::string &invitecode) { + return {this, static_cast(&cluster::invite_delete), invitecode}; +} + +awaitable cluster::co_invite_get(const std::string &invite_code) { + return {this, static_cast(&cluster::invite_get), invite_code}; +} + +awaitable cluster::co_message_add_reaction(const struct message &m, const std::string &reaction) { + return {this, static_cast(&cluster::message_add_reaction), m, reaction}; +} + +awaitable cluster::co_message_add_reaction(snowflake message_id, snowflake channel_id, const std::string &reaction) { + return {this, static_cast(&cluster::message_add_reaction), message_id, channel_id, reaction}; +} + +awaitable cluster::co_message_create(const message &m) { + return {this, static_cast(&cluster::message_create), m}; +} + +awaitable cluster::co_message_crosspost(snowflake message_id, snowflake channel_id) { + return {this, static_cast(&cluster::message_crosspost), message_id, channel_id}; +} + +awaitable cluster::co_message_delete_all_reactions(const struct message &m) { + return {this, static_cast(&cluster::message_delete_all_reactions), m}; +} + +awaitable cluster::co_message_delete_all_reactions(snowflake message_id, snowflake channel_id) { + return {this, static_cast(&cluster::message_delete_all_reactions), message_id, channel_id}; +} + +awaitable cluster::co_message_delete_bulk(const std::vector& message_ids, snowflake channel_id) { + return {this, static_cast&, snowflake, command_completion_event_t)>(&cluster::message_delete_bulk), message_ids, channel_id}; +} + +awaitable cluster::co_message_delete(snowflake message_id, snowflake channel_id) { + return {this, static_cast(&cluster::message_delete), message_id, channel_id}; +} + +awaitable cluster::co_message_delete_own_reaction(const struct message &m, const std::string &reaction) { + return {this, static_cast(&cluster::message_delete_own_reaction), m, reaction}; +} + +awaitable cluster::co_message_delete_own_reaction(snowflake message_id, snowflake channel_id, const std::string &reaction) { + return {this, static_cast(&cluster::message_delete_own_reaction), message_id, channel_id, reaction}; +} + +awaitable cluster::co_message_delete_reaction(const struct message &m, snowflake user_id, const std::string &reaction) { + return {this, static_cast(&cluster::message_delete_reaction), m, user_id, reaction}; +} + +awaitable cluster::co_message_delete_reaction(snowflake message_id, snowflake channel_id, snowflake user_id, const std::string &reaction) { + return {this, static_cast(&cluster::message_delete_reaction), message_id, channel_id, user_id, reaction}; +} + +awaitable cluster::co_message_delete_reaction_emoji(const struct message &m, const std::string &reaction) { + return {this, static_cast(&cluster::message_delete_reaction_emoji), m, reaction}; +} + +awaitable cluster::co_message_delete_reaction_emoji(snowflake message_id, snowflake channel_id, const std::string &reaction) { + return {this, static_cast(&cluster::message_delete_reaction_emoji), message_id, channel_id, reaction}; +} + +awaitable cluster::co_message_edit(const message &m) { + return {this, static_cast(&cluster::message_edit), m}; +} + +awaitable cluster::co_message_get(snowflake message_id, snowflake channel_id) { + return {this, static_cast(&cluster::message_get), message_id, channel_id}; +} + +awaitable cluster::co_message_get_reactions(const struct message &m, const std::string &reaction, snowflake before, snowflake after, snowflake limit) { + return {this, static_cast(&cluster::message_get_reactions), m, reaction, before, after, limit}; +} + +awaitable cluster::co_message_get_reactions(snowflake message_id, snowflake channel_id, const std::string &reaction, snowflake before, snowflake after, snowflake limit) { + return {this, static_cast(&cluster::message_get_reactions), message_id, channel_id, reaction, before, after, limit}; +} + +awaitable cluster::co_message_pin(snowflake channel_id, snowflake message_id) { + return {this, static_cast(&cluster::message_pin), channel_id, message_id}; +} + +awaitable cluster::co_messages_get(snowflake channel_id, snowflake around, snowflake before, snowflake after, uint64_t limit) { + return {this, static_cast(&cluster::messages_get), channel_id, around, before, after, limit}; +} + +awaitable cluster::co_message_unpin(snowflake channel_id, snowflake message_id) { + return {this, static_cast(&cluster::message_unpin), channel_id, message_id}; +} + +awaitable cluster::co_channel_pins_get(snowflake channel_id) { + return {this, static_cast(&cluster::channel_pins_get), channel_id}; +} + +awaitable cluster::co_role_create(const class role &r) { + return {this, static_cast(&cluster::role_create), r}; +} + +awaitable cluster::co_role_delete(snowflake guild_id, snowflake role_id) { + return {this, static_cast(&cluster::role_delete), guild_id, role_id}; +} + +awaitable cluster::co_role_edit(const class role &r) { + return {this, static_cast(&cluster::role_edit), r}; +} + +awaitable cluster::co_roles_edit_position(snowflake guild_id, const std::vector &roles) { + return {this, static_cast &, command_completion_event_t)>(&cluster::roles_edit_position), guild_id, roles}; +} + +awaitable cluster::co_roles_get(snowflake guild_id) { + return {this, static_cast(&cluster::roles_get), guild_id}; +} + +awaitable cluster::co_application_role_connection_get(snowflake application_id) { + return {this, static_cast(&cluster::application_role_connection_get), application_id}; +} + +awaitable cluster::co_application_role_connection_update(snowflake application_id, const std::vector &connection_metadata) { + return {this, static_cast &, command_completion_event_t)>(&cluster::application_role_connection_update), application_id, connection_metadata}; +} + +awaitable cluster::co_user_application_role_connection_get(snowflake application_id) { + return {this, static_cast(&cluster::user_application_role_connection_get), application_id}; +} + +awaitable cluster::co_user_application_role_connection_update(snowflake application_id, const application_role_connection &connection) { + return {this, static_cast(&cluster::user_application_role_connection_update), application_id, connection}; +} + +awaitable cluster::co_guild_events_get(snowflake guild_id) { + return {this, static_cast(&cluster::guild_events_get), guild_id}; +} + +awaitable cluster::co_guild_event_create(const scheduled_event& event) { + return {this, static_cast(&cluster::guild_event_create), event}; +} + +awaitable cluster::co_guild_event_delete(snowflake event_id, snowflake guild_id) { + return {this, static_cast(&cluster::guild_event_delete), event_id, guild_id}; +} + +awaitable cluster::co_guild_event_edit(const scheduled_event& event) { + return {this, static_cast(&cluster::guild_event_edit), event}; +} + +awaitable cluster::co_guild_event_get(snowflake guild_id, snowflake event_id) { + return {this, static_cast(&cluster::guild_event_get), guild_id, event_id}; +} + +awaitable cluster::co_stage_instance_create(const stage_instance& si) { + return {this, static_cast(&cluster::stage_instance_create), si}; +} + +awaitable cluster::co_stage_instance_get(const snowflake channel_id) { + return {this, static_cast(&cluster::stage_instance_get), channel_id}; +} + +awaitable cluster::co_stage_instance_edit(const stage_instance& si) { + return {this, static_cast(&cluster::stage_instance_edit), si}; +} + +awaitable cluster::co_stage_instance_delete(const snowflake channel_id) { + return {this, static_cast(&cluster::stage_instance_delete), channel_id}; +} + +awaitable cluster::co_guild_sticker_create(sticker &s) { + return {this, static_cast(&cluster::guild_sticker_create), s}; +} + +awaitable cluster::co_guild_sticker_delete(snowflake sticker_id, snowflake guild_id) { + return {this, static_cast(&cluster::guild_sticker_delete), sticker_id, guild_id}; +} + +awaitable cluster::co_guild_sticker_get(snowflake id, snowflake guild_id) { + return {this, static_cast(&cluster::guild_sticker_get), id, guild_id}; +} + +awaitable cluster::co_guild_sticker_modify(sticker &s) { + return {this, static_cast(&cluster::guild_sticker_modify), s}; +} + +awaitable cluster::co_guild_stickers_get(snowflake guild_id) { + return {this, static_cast(&cluster::guild_stickers_get), guild_id}; +} + +awaitable cluster::co_nitro_sticker_get(snowflake id) { + return {this, static_cast(&cluster::nitro_sticker_get), id}; +} + +awaitable cluster::co_sticker_packs_get() { + return {this, static_cast(&cluster::sticker_packs_get)}; +} + +awaitable cluster::co_guild_create_from_template(const std::string &code, const std::string &name) { + return {this, static_cast(&cluster::guild_create_from_template), code, name}; +} + +awaitable cluster::co_guild_template_create(snowflake guild_id, const std::string &name, const std::string &description) { + return {this, static_cast(&cluster::guild_template_create), guild_id, name, description}; +} + +awaitable cluster::co_guild_template_delete(snowflake guild_id, const std::string &code) { + return {this, static_cast(&cluster::guild_template_delete), guild_id, code}; +} + +awaitable cluster::co_guild_template_modify(snowflake guild_id, const std::string &code, const std::string &name, const std::string &description) { + return {this, static_cast(&cluster::guild_template_modify), guild_id, code, name, description}; +} + +awaitable cluster::co_guild_templates_get(snowflake guild_id) { + return {this, static_cast(&cluster::guild_templates_get), guild_id}; +} + +awaitable cluster::co_guild_template_sync(snowflake guild_id, const std::string &code) { + return {this, static_cast(&cluster::guild_template_sync), guild_id, code}; +} + +awaitable cluster::co_template_get(const std::string &code) { + return {this, static_cast(&cluster::template_get), code}; +} + +awaitable cluster::co_current_user_join_thread(snowflake thread_id) { + return {this, static_cast(&cluster::current_user_join_thread), thread_id}; +} + +awaitable cluster::co_current_user_leave_thread(snowflake thread_id) { + return {this, static_cast(&cluster::current_user_leave_thread), thread_id}; +} + +awaitable cluster::co_threads_get_active(snowflake guild_id) { + return {this, static_cast(&cluster::threads_get_active), guild_id}; +} + +awaitable cluster::co_threads_get_joined_private_archived(snowflake channel_id, snowflake before_id, uint16_t limit) { + return {this, static_cast(&cluster::threads_get_joined_private_archived), channel_id, before_id, limit}; +} + +awaitable cluster::co_threads_get_private_archived(snowflake channel_id, time_t before_timestamp, uint16_t limit) { + return {this, static_cast(&cluster::threads_get_private_archived), channel_id, before_timestamp, limit}; +} + +awaitable cluster::co_threads_get_public_archived(snowflake channel_id, time_t before_timestamp, uint16_t limit) { + return {this, static_cast(&cluster::threads_get_public_archived), channel_id, before_timestamp, limit}; +} + +awaitable cluster::co_thread_member_get(const snowflake thread_id, const snowflake user_id) { + return {this, static_cast(&cluster::thread_member_get), thread_id, user_id}; +} + +awaitable cluster::co_thread_members_get(snowflake thread_id) { + return {this, static_cast(&cluster::thread_members_get), thread_id}; +} + +awaitable cluster::co_thread_create_in_forum(const std::string& thread_name, snowflake channel_id, const message& msg, auto_archive_duration_t auto_archive_duration, uint16_t rate_limit_per_user, std::vector applied_tags) { + return {this, static_cast, command_completion_event_t)>(&cluster::thread_create_in_forum), thread_name, channel_id, msg, auto_archive_duration, rate_limit_per_user, applied_tags}; +} + +awaitable cluster::co_thread_create(const std::string& thread_name, snowflake channel_id, uint16_t auto_archive_duration, channel_type thread_type, bool invitable, uint16_t rate_limit_per_user) { + return {this, static_cast(&cluster::thread_create), thread_name, channel_id, auto_archive_duration, thread_type, invitable, rate_limit_per_user}; +} + +awaitable cluster::co_thread_edit(const thread &t) { + return {this, static_cast(&cluster::thread_edit), t}; +} + +awaitable cluster::co_thread_create_with_message(const std::string& thread_name, snowflake channel_id, snowflake message_id, uint16_t auto_archive_duration, uint16_t rate_limit_per_user) { + return {this, static_cast(&cluster::thread_create_with_message), thread_name, channel_id, message_id, auto_archive_duration, rate_limit_per_user}; +} + +awaitable cluster::co_thread_member_add(snowflake thread_id, snowflake user_id) { + return {this, static_cast(&cluster::thread_member_add), thread_id, user_id}; +} + +awaitable cluster::co_thread_member_remove(snowflake thread_id, snowflake user_id) { + return {this, static_cast(&cluster::thread_member_remove), thread_id, user_id}; +} + +awaitable cluster::co_current_user_edit(const std::string &nickname, const std::string& image_blob, const image_type type) { + return {this, static_cast(&cluster::current_user_edit), nickname, image_blob, type}; +} + +awaitable cluster::co_current_application_get() { + return {this, static_cast(&cluster::current_application_get)}; +} + +awaitable cluster::co_current_user_get() { + return {this, static_cast(&cluster::current_user_get)}; +} + +awaitable cluster::co_current_user_set_voice_state(snowflake guild_id, snowflake channel_id, bool suppress, time_t request_to_speak_timestamp) { + return {this, static_cast(&cluster::current_user_set_voice_state), guild_id, channel_id, suppress, request_to_speak_timestamp}; +} + +awaitable cluster::co_user_set_voice_state(snowflake user_id, snowflake guild_id, snowflake channel_id, bool suppress) { + return {this, static_cast(&cluster::user_set_voice_state), user_id, guild_id, channel_id, suppress}; +} + +awaitable cluster::co_current_user_connections_get() { + return {this, static_cast(&cluster::current_user_connections_get)}; +} + +awaitable cluster::co_current_user_get_guilds() { + return {this, static_cast(&cluster::current_user_get_guilds)}; +} + +awaitable cluster::co_current_user_leave_guild(snowflake guild_id) { + return {this, static_cast(&cluster::current_user_leave_guild), guild_id}; +} + +awaitable cluster::co_user_get(snowflake user_id) { + return {this, static_cast(&cluster::user_get), user_id}; +} + +awaitable cluster::co_user_get_cached(snowflake user_id) { + return {this, static_cast(&cluster::user_get_cached), user_id}; +} + +awaitable cluster::co_get_voice_regions() { + return {this, static_cast(&cluster::get_voice_regions)}; +} + +awaitable cluster::co_guild_get_voice_regions(snowflake guild_id) { + return {this, static_cast(&cluster::guild_get_voice_regions), guild_id}; +} + +awaitable cluster::co_create_webhook(const class webhook &w) { + return {this, static_cast(&cluster::create_webhook), w}; +} + +awaitable cluster::co_delete_webhook(snowflake webhook_id) { + return {this, static_cast(&cluster::delete_webhook), webhook_id}; +} + +awaitable cluster::co_delete_webhook_message(const class webhook &wh, snowflake message_id, snowflake thread_id) { + return {this, static_cast(&cluster::delete_webhook_message), wh, message_id, thread_id}; +} + +awaitable cluster::co_delete_webhook_with_token(snowflake webhook_id, const std::string &token) { + return {this, static_cast(&cluster::delete_webhook_with_token), webhook_id, token}; +} + +awaitable cluster::co_edit_webhook(const class webhook& wh) { + return {this, static_cast(&cluster::edit_webhook), wh}; +} + +awaitable cluster::co_edit_webhook_message(const class webhook &wh, const struct message& m, snowflake thread_id) { + return {this, static_cast(&cluster::edit_webhook_message), wh, m, thread_id}; +} + +awaitable cluster::co_edit_webhook_with_token(const class webhook& wh) { + return {this, static_cast(&cluster::edit_webhook_with_token), wh}; +} + +awaitable cluster::co_execute_webhook(const class webhook &wh, const struct message& m, bool wait, snowflake thread_id, const std::string& thread_name) { + return {this, static_cast(&cluster::execute_webhook), wh, m, wait, thread_id, thread_name}; +} + +awaitable cluster::co_get_channel_webhooks(snowflake channel_id) { + return {this, static_cast(&cluster::get_channel_webhooks), channel_id}; +} + +awaitable cluster::co_get_guild_webhooks(snowflake guild_id) { + return {this, static_cast(&cluster::get_guild_webhooks), guild_id}; +} + +awaitable cluster::co_get_webhook(snowflake webhook_id) { + return {this, static_cast(&cluster::get_webhook), webhook_id}; +} + +awaitable cluster::co_get_webhook_message(const class webhook &wh, snowflake message_id, snowflake thread_id) { + return {this, static_cast(&cluster::get_webhook_message), wh, message_id, thread_id}; +} + +awaitable cluster::co_get_webhook_with_token(snowflake webhook_id, const std::string &token) { + return {this, static_cast(&cluster::get_webhook_with_token), webhook_id, token}; +} + + +}; + +/* End of auto-generated definitions */ +dpp::awaitable dpp::cluster::co_request(const std::string &url, http_method method, const std::string &postdata, const std::string &mimetype, const std::multimap &headers) { + return awaitable{[&](auto &&cc) { this->request(url, method, cc, postdata, mimetype, headers); }}; +} + +#endif diff --git a/src/dpp/dispatcher.cpp b/src/dpp/dispatcher.cpp index 7ab6b68385..cecdce02fd 100644 --- a/src/dpp/dispatcher.cpp +++ b/src/dpp/dispatcher.cpp @@ -208,6 +208,57 @@ void interaction_create_t::delete_original_response(command_completion_event_t c }); } + +#ifdef DPP_CORO +awaitable interaction_create_t::co_reply() const { + return dpp::awaitable{[this](auto &&cb) { this->reply(cb); }}; +} + +awaitable interaction_create_t::co_reply(interaction_response_type t, const message & m) const { + return dpp::awaitable{[&, this](auto &&cb) { this->reply(t, m, cb); }}; +} + +awaitable interaction_create_t::co_reply(interaction_response_type t, const std::string & mt) const { + return dpp::awaitable{[&, this](auto &&cb) { this->reply(t, mt, cb); }}; +} + +awaitable interaction_create_t::co_reply(const message & m) const { + return dpp::awaitable{[&, this](auto &&cb) { this->reply(m, cb); }}; +} + +awaitable interaction_create_t::co_reply(const std::string & mt) const { + return dpp::awaitable{[&, this](auto &&cb) { this->reply(mt, cb); }}; +} + +awaitable interaction_create_t::co_dialog(const interaction_modal_response& mr) const { + return dpp::awaitable{[&, this](auto &&cb) { this->dialog(mr, cb); }}; +} + +awaitable interaction_create_t::co_edit_response(const message & m) const { + return dpp::awaitable{[&, this](auto &&cb) { this->edit_response(m, cb); }}; +} + +awaitable interaction_create_t::co_edit_response(const std::string & mt) const { + return dpp::awaitable{[&, this](auto &&cb) { this->edit_response(mt, cb); }}; +} + +awaitable interaction_create_t::co_thinking(bool ephemeral) const { + return dpp::awaitable{[&, this](auto &&cb) { this->thinking(ephemeral, cb); }}; +} + +awaitable interaction_create_t::co_get_original_response() const { + return dpp::awaitable{[&, this](auto &&cb) { this->get_original_response(cb); }}; +} + +awaitable interaction_create_t::co_edit_original_response(const message & m) const { + return dpp::awaitable{[&, this](auto &&cb) { this->edit_original_response(m, cb); }}; +} + +awaitable interaction_create_t::co_delete_original_response() const { + return dpp::awaitable{[&, this](auto &&cb) { this->delete_original_response(cb); }}; +} +#endif /* DPP_CORO */ + command_value interaction_create_t::get_parameter(const std::string& name) const { const command_interaction ci = command.get_command_interaction();