shortener-bot/discord_client.cpp

107 lines
3.1 KiB
C++

#include "discord_client.h"
#include <spdlog/spdlog.h>
DiscordClient::DiscordClient(uv_loop_t *loop, std::string token) :
m_eventLoop(loop),
m_botToken(token)
{}
DiscordClient::~DiscordClient() {
stop();
}
// TODO make asynchronous
bool DiscordClient::start() {
if (m_running) return false;
m_running = true;
spdlog::debug("discord: start");
m_eventHandle = new uv_async_t;
m_eventHandle->data = this;
uv_async_init(m_eventLoop, m_eventHandle, DiscordClient::uv_callback);
m_bot = std::make_unique<dpp::cluster>(m_botToken);
try {
m_bot->start(true);
} catch (int e) {
spdlog::debug("discord: start failed");
return false;
}
m_bot->on_ready([this](const dpp::ready_t &event) {
spdlog::debug("discord: ready, registering commands");
dpp::slashcommand command("shorten", "Shorten a URL", m_bot->me.id);
command.add_option(dpp::command_option(dpp::co_string, std::string("url"), std::string("URL"), true));
std::vector<dpp::slashcommand> commands { command };
m_bot->global_bulk_command_create(commands, [](const dpp::confirmation_callback_t &e) {
if (!e.is_error()) {
spdlog::info("discord: register commands success");
} else {
spdlog::error("discord: register commands failure: {}", e.get_error().message);
}
});
});
m_bot->on_slashcommand([this](const dpp::slashcommand_t &event) {
auto cmdname = event.command.get_command_name();
if (cmdname == "shorten") {
dpp::slashcommand_t eventCopy = event;
eventCopy.thinking();
spdlog::debug("discord: received /shorten comand");
std::string url = std::get<std::string>(event.get_parameter("url"));
m_commandQueueMutex.lock();
m_commandQueue.push(std::move(BotCommand(ShortenCommand {url, std::move(event)})));
m_commandQueueMutex.unlock();
uv_async_send(m_eventHandle);
} else {
spdlog::warn("discord: received unknown command {}", cmdname);
}
});
return true;
}
void DiscordClient::uv_callback(uv_async_t *h) {
auto self = reinterpret_cast<DiscordClient*>(h->data);
self->m_commandQueueMutex.lock();
while (!self->m_commandQueue.empty()) {
BotCommand nextCmd = std::move(self->m_commandQueue.front());
self->m_commandQueue.pop();
switch (nextCmd.type) {
case BotCommandType::SHORTEN:
if (self->on_shorten_command)
self->on_shorten_command(nextCmd.shortenCmd.url, nextCmd.shortenCmd.event);
break;
}
}
self->m_commandQueueMutex.unlock();
}
bool DiscordClient::stop() {
if (!m_running) return false;
m_running = false;
m_bot->shutdown();
uv_close((uv_handle_t*)m_eventHandle, [](uv_handle_t *h){
delete h;
});
return true;
}
BotCommand::BotCommand(ShortenCommand &&cmd) : type(BotCommandType::SHORTEN), shortenCmd(cmd) {}
BotCommand::BotCommand(BotCommand &&other) {
type = other.type;
switch (other.type) {
case BotCommandType::SHORTEN:
new (&shortenCmd) ShortenCommand(other.shortenCmd);
break;
}
}
BotCommand::~BotCommand() {
switch (type) {
case BotCommandType::SHORTEN:
shortenCmd.~ShortenCommand();
break;
}
}