Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat: Implementing named commands handlers for the cluster #1262

Merged
merged 10 commits into from
Oct 9, 2024
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
79 changes: 79 additions & 0 deletions include/dpp/cluster.h
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,38 @@ class DPP_EXPORT cluster {
*/
timer_next_t next_timer;

/**
* @brief Mutex to work with named_commands and synchronize read write access
*/
std::shared_mutex named_commands_mutex;

/**
* @brief Typedef for slashcommand handler type
*/
using slashcommand_handler_t = std::function<void(const slashcommand_t &)>;

#ifdef DPP_CORO
/**
* @brief Typedef for coroutines based slashcommand handler type
*/
using co_slashcommand_handler_t = std::function<dpp::task<void>(const slashcommand_t&)>;

/**
* @brief Typedef for variant of coroutines based slashcommand handler type and regular version of it
*/
using slashcommand_handler_variant = std::variant<slashcommand_handler_t,co_slashcommand_handler_t>;

/**
* @brief Container to store relation between command name and it's handler
*/
std::map<std::string,slashcommand_handler_variant> named_commands;
#else
/**
* @brief Container to store relation between command name and it's handler
*/
std::map<std::string,slashcommand_handler_t> named_commands;
#endif

/**
* @brief Tick active timers
*/
Expand Down Expand Up @@ -436,6 +468,53 @@ class DPP_EXPORT cluster {

/* Functions for attaching to event handlers */

/**
* @brief Register a slash command handler.
*
* @param name The name of the slash command to register
* @param handler A handler function of type `slashcommand_handler_t`
*
* @return bool Returns `true` if the command was registered successfully, or `false` if
* the command with the same name already exists
*/
bool register_command(const std::string& name, const slashcommand_handler_t handler);

#ifdef DPP_CORO
/**
* @brief Register a coroutine-based slash command handler.
*
* @param name The name of the slash command to register.
* @param handler A coroutine handler function of type `co_slashcommand_handler_t`.
*
* @return bool Returns `true` if the command was registered successfully, or `false` if
* the command with the same name already exists.
*/
template <typename F>
std::enable_if_t<std::is_same_v<std::invoke_result_t<F, const slashcommand_handler_t&>, dpp::task<void>>, bool>
register_command(const std::string& name, F&& handler){
std::unique_lock lk(named_commands_mutex);
if (named_commands.count(name) != 0) {
return false;
}
named_commands.emplace(name, handler);
return true;
};
#endif

/**
* @brief Unregister a slash command.
*
* This function unregisters (removes) a previously registered slash command by name.
* If the command is successfully removed, it returns `true`.
*
* @param name The name of the slash command to unregister.
*
* @return bool Returns `true` if the command was successfully unregistered, or `false`
* if the command was not found.
*/
bool unregister_command(const std::string& name);


/**
* @brief on voice state update event
*
Expand Down
49 changes: 49 additions & 0 deletions src/dpp/cluster.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,40 @@ cluster::cluster(const std::string &_token, uint32_t _intents, uint32_t _shards,
i_message_content,
"You have attached an event to cluster::on_message_update() but have not specified the privileged intent dpp::i_message_content. Message content, embeds, attachments, and components on received guild messages will be empty.")
);

/* Add slashcommand callback for named commands. */
#ifdef DPP_CORO
on_slashcommand([this](const slashcommand_t& event) -> task<void> {
slashcommand_handler_variant copy;
{
std::shared_lock lk(named_commands_mutex);
auto it = named_commands.find(event.command.get_command_name());
if (it == named_commands.end()) {
co_return; // Command not found
ruslan-ilesik marked this conversation as resolved.
Show resolved Hide resolved
}
copy = it->second;
}
if (std::holds_alternative<co_slashcommand_handler_t>(copy)) {
co_await std::get<co_slashcommand_handler_t>(copy)(event);
} else if (std::holds_alternative<slashcommand_handler_t>(copy)) {
std::get<slashcommand_handler_t>(copy)(event);
}
co_return;
});
#else
on_slashcommand([this](const slashcommand_t& event) {
slashcommand_handler_t copy;
{
std::shared_lock lk(named_commands_mutex);
auto it = named_commands.find(event.command.get_command_name());
if (it == named_commands.end()) {
return; // Command not found
ruslan-ilesik marked this conversation as resolved.
Show resolved Hide resolved
}
copy = it->second;
}
copy(event);
});
#endif
}

cluster::~cluster()
Expand Down Expand Up @@ -466,4 +500,19 @@ cluster& cluster::set_request_timeout(uint16_t timeout) {
return *this;
}

bool cluster::register_command(const std::string &name, const slashcommand_handler_t handler) {
std::unique_lock lk(named_commands_mutex);
if (named_commands.count(name) != 0) {
return false;
}
named_commands.emplace(name, handler);
braindigitalis marked this conversation as resolved.
Show resolved Hide resolved
return true;
}

bool cluster::unregister_command(const std::string &name) {
std::unique_lock lk(named_commands_mutex);
return named_commands.erase(name) == 1;
}


};
Loading