Skip to content

Commit

Permalink
Feat: Implementing named commands handlers for the cluster (#1262)
Browse files Browse the repository at this point in the history
  • Loading branch information
braindigitalis authored Oct 9, 2024
2 parents 14caa73 + 95270f5 commit 190adf2
Show file tree
Hide file tree
Showing 2 changed files with 120 additions and 0 deletions.
75 changes: 75 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,49 @@ 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);
auto [_, inserted] = named_commands.try_emplace(name, std::forward<F>(handler));
return inserted;
};
#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
45 changes: 45 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;
}
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;
}
copy = it->second;
}
copy(event);
});
#endif
}

cluster::~cluster()
Expand Down Expand Up @@ -466,4 +500,15 @@ 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);
auto [_, inserted] = named_commands.try_emplace(name, handler);
return inserted;
}

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

};

0 comments on commit 190adf2

Please sign in to comment.