107 lines
3.1 KiB
C++
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;
|
|
}
|
|
}
|