implement a few commands
This commit is contained in:
parent
8c9678708b
commit
178d7dfcfe
@ -114,12 +114,11 @@ static auto start(
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
// Simple example of a command handler
|
// Dispatch commands to the webhook logic
|
||||||
bot->sig_command.connect([connection](const Bot::Command &cmd) {
|
bot->sig_command.connect([webhook, connection](const Bot::Command &cmd) {
|
||||||
if (cmd.oper == "glguy" && cmd.command == "ping") {
|
auto cursor = webhook_commands.find(std::string{cmd.command});
|
||||||
if (auto bang = cmd.source.find('!'); bang != cmd.source.npos) {
|
if (cursor != webhook_commands.end()) {
|
||||||
connection->send_notice(cmd.source.substr(0, bang), cmd.arguments);
|
cursor->second(webhook, cmd);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
143
driver/web.cpp
143
driver/web.cpp
@ -252,14 +252,21 @@ auto start_webhook(
|
|||||||
auto webhook_settings = toml::parse(webhook_settings_file);
|
auto webhook_settings = toml::parse(webhook_settings_file);
|
||||||
WebhookSettings settings = WebhookSettings::from_toml(webhook_settings);
|
WebhookSettings settings = WebhookSettings::from_toml(webhook_settings);
|
||||||
BOOST_LOG_TRIVIAL(info) << "Webhook settings: " << settings.to_toml();
|
BOOST_LOG_TRIVIAL(info) << "Webhook settings: " << settings.to_toml();
|
||||||
auto webhook = std::make_shared<GithubWebhook>(std::move(settings));
|
auto webhook = std::make_shared<GithubWebhook>(std::move(settings), webhook_settings_filename);
|
||||||
boost::asio::co_spawn(io, spawn_webhook(io, webhook), report_error);
|
boost::asio::co_spawn(io, spawn_webhook(io, webhook), report_error);
|
||||||
return webhook;
|
return webhook;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto GithubWebhook::write_event(WebhookEvent event) -> void
|
auto GithubWebhook::save_settings() const -> void
|
||||||
{
|
{
|
||||||
connection_->send_notice("glguy", event.channel + ": " + event.message);
|
std::ofstream webhook_settings_file{settings_file};
|
||||||
|
if (!webhook_settings_file)
|
||||||
|
{
|
||||||
|
BOOST_LOG_TRIVIAL(error) << "Unable to open webhook settings file";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
webhook_settings_file << settings_.to_toml();
|
||||||
}
|
}
|
||||||
|
|
||||||
auto ProjectSettings::from_toml(const toml::table &v) -> ProjectSettings
|
auto ProjectSettings::from_toml(const toml::table &v) -> ProjectSettings
|
||||||
@ -374,3 +381,133 @@ auto WebhookSettings::to_toml() const -> toml::table
|
|||||||
{"projects", std::move(project_tables)}
|
{"projects", std::move(project_tables)}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Either emit the event now or save it until a connection is set
|
||||||
|
auto GithubWebhook::add_event(Notice notice) -> void
|
||||||
|
{
|
||||||
|
if (connection_)
|
||||||
|
{
|
||||||
|
connection_->send_notice(notice.target, notice.message);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
events_.emplace_back(std::move(notice));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto GithubWebhook::set_connection(std::shared_ptr<myirc::Connection> connection) -> void
|
||||||
|
{
|
||||||
|
connection_ = std::move(connection);
|
||||||
|
for (auto &&event : events_)
|
||||||
|
{
|
||||||
|
connection_->send_notice(event.target, event.message);
|
||||||
|
}
|
||||||
|
events_.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
auto GithubWebhook::clear_connection() -> void
|
||||||
|
{
|
||||||
|
connection_.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
static auto reply_to(std::shared_ptr<GithubWebhook> webhooks, const myirc::Bot::Command &cmd, std::string message) -> void
|
||||||
|
{
|
||||||
|
if (cmd.target.starts_with("#"))
|
||||||
|
{
|
||||||
|
webhooks->add_event({std::string{cmd.target}, std::move(message)});
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
webhooks->add_event({std::string{cmd.nick()}, std::move(message)});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static auto authorized_for_project(const ProjectSettings &project, const std::string_view nick) -> bool
|
||||||
|
{
|
||||||
|
return project.authorized_accounts.find(std::string{nick}) != project.authorized_accounts.end();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::map<std::string, void (*)(std::shared_ptr<GithubWebhook>, const myirc::Bot::Command &)> webhook_commands{
|
||||||
|
{"add-credential", [](std::shared_ptr<GithubWebhook> webhooks, const myirc::Bot::Command &cmd) {
|
||||||
|
//if (cmd.oper.empty())
|
||||||
|
//{
|
||||||
|
// return;
|
||||||
|
//}
|
||||||
|
std::istringstream iss{std::string{cmd.arguments}};
|
||||||
|
std::string name, key;
|
||||||
|
if (iss >> name >> key)
|
||||||
|
{
|
||||||
|
webhooks->settings_.credentials.insert_or_assign(name, key);
|
||||||
|
webhooks->save_settings();
|
||||||
|
reply_to(webhooks, cmd, "Added credential " + name);
|
||||||
|
}
|
||||||
|
}},
|
||||||
|
{"drop-credential", [](std::shared_ptr<GithubWebhook> webhooks, const myirc::Bot::Command &cmd) {
|
||||||
|
//if (cmd.oper.empty())
|
||||||
|
//{
|
||||||
|
// return;
|
||||||
|
//}
|
||||||
|
std::istringstream iss{std::string{cmd.arguments}};
|
||||||
|
std::string name;
|
||||||
|
if (iss >> name)
|
||||||
|
{
|
||||||
|
webhooks->settings_.credentials.erase(name);
|
||||||
|
webhooks->save_settings();
|
||||||
|
reply_to(webhooks, cmd, "Dropped credential " + name);
|
||||||
|
}
|
||||||
|
}},
|
||||||
|
{"enable-project", [](std::shared_ptr<GithubWebhook> webhooks, const myirc::Bot::Command &cmd) {
|
||||||
|
std::istringstream iss{std::string{cmd.arguments}};
|
||||||
|
std::string name;
|
||||||
|
if (iss >> name)
|
||||||
|
{
|
||||||
|
auto cursor = webhooks->settings_.projects.find(name);
|
||||||
|
if (cursor == webhooks->settings_.projects.end())
|
||||||
|
{
|
||||||
|
reply_to(webhooks, cmd, "Unknown project " + name);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto &project = cursor->second;
|
||||||
|
|
||||||
|
if (not authorized_for_project(project, cmd.account))
|
||||||
|
{
|
||||||
|
reply_to(webhooks, cmd, "Unauthorized to enable project " + name);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
project.enabled = true;
|
||||||
|
webhooks->save_settings();
|
||||||
|
reply_to(webhooks, cmd, "Enabled project " + name);
|
||||||
|
}
|
||||||
|
}},
|
||||||
|
{"disable-project", [](std::shared_ptr<GithubWebhook> webhooks, const myirc::Bot::Command &cmd) {
|
||||||
|
//if (cmd.oper.empty())
|
||||||
|
//{
|
||||||
|
// return;
|
||||||
|
//}
|
||||||
|
std::istringstream iss{std::string{cmd.arguments}};
|
||||||
|
std::string name;
|
||||||
|
if (iss >> name)
|
||||||
|
{
|
||||||
|
auto cursor = webhooks->settings_.projects.find(name);
|
||||||
|
if (cursor == webhooks->settings_.projects.end())
|
||||||
|
{
|
||||||
|
webhooks->add_event({std::string{cmd.nick()}, "Unknown project " + name});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto &project = cursor->second;
|
||||||
|
|
||||||
|
if (not authorized_for_project(project, cmd.account))
|
||||||
|
{
|
||||||
|
reply_to(webhooks, cmd, "Unauthorized to disable project " + name);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
project.enabled = false;
|
||||||
|
webhooks->save_settings();
|
||||||
|
reply_to(webhooks, cmd, "Disabled project " + name);
|
||||||
|
}
|
||||||
|
}},
|
||||||
|
};
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <myirc/bot.hpp>
|
||||||
#include <myirc/connection.hpp>
|
#include <myirc/connection.hpp>
|
||||||
|
|
||||||
#include <toml++/toml.hpp>
|
#include <toml++/toml.hpp>
|
||||||
@ -46,55 +47,38 @@ struct WebhookSettings {
|
|||||||
static auto from_toml(const toml::table &v) -> WebhookSettings;
|
static auto from_toml(const toml::table &v) -> WebhookSettings;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct WebhookEvent {
|
class GithubWebhook {
|
||||||
std::string channel;
|
public:
|
||||||
|
struct Notice {
|
||||||
|
std::string target;
|
||||||
std::string message;
|
std::string message;
|
||||||
};
|
};
|
||||||
|
private:
|
||||||
|
|
||||||
class GithubWebhook {
|
|
||||||
// IRC connection to announce on; could be empty
|
// IRC connection to announce on; could be empty
|
||||||
std::shared_ptr<myirc::Connection> connection_;
|
std::shared_ptr<myirc::Connection> connection_;
|
||||||
|
|
||||||
// Buffered events in case connection was inactive when event was received
|
// Buffered events in case connection was inactive when event was received
|
||||||
std::vector<WebhookEvent> events_;
|
std::vector<Notice> events_;
|
||||||
|
|
||||||
|
const char * settings_file;
|
||||||
// Actually write the event to the connection.
|
|
||||||
// Only call when there is a connection.
|
|
||||||
auto write_event(WebhookEvent event) -> void;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
WebhookSettings settings_;
|
WebhookSettings settings_;
|
||||||
|
|
||||||
GithubWebhook(WebhookSettings settings)
|
GithubWebhook(WebhookSettings settings, const char * settings_file)
|
||||||
: settings_(std::move(settings))
|
: settings_(std::move(settings))
|
||||||
|
, settings_file(settings_file)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
// Either emit the event now or save it until a connection is set
|
// Either emit the event now or save it until a connection is set
|
||||||
auto add_event(WebhookEvent event) -> void
|
auto add_event(Notice event) -> void;
|
||||||
{
|
auto set_connection(std::shared_ptr<myirc::Connection> connection) -> void;
|
||||||
if (connection_) {
|
auto clear_connection() -> void;
|
||||||
write_event(std::move(event));
|
auto save_settings() const -> void;
|
||||||
} else {
|
|
||||||
events_.emplace_back(std::move(event));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
auto set_connection(std::shared_ptr<myirc::Connection> connection) -> void
|
|
||||||
{
|
|
||||||
connection_ = std::move(connection);
|
|
||||||
for (auto &&event : events_)
|
|
||||||
{
|
|
||||||
write_event(event);
|
|
||||||
}
|
|
||||||
events_.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
auto clear_connection() -> void
|
|
||||||
{
|
|
||||||
connection_.reset();
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
auto start_webhook(boost::asio::io_context &io, const char *) -> std::shared_ptr<GithubWebhook>;
|
auto start_webhook(boost::asio::io_context &io, const char *) -> std::shared_ptr<GithubWebhook>;
|
||||||
|
|
||||||
|
extern std::map<std::string, void(*)(std::shared_ptr<GithubWebhook>, const myirc::Bot::Command &)> webhook_commands;
|
||||||
|
@ -18,6 +18,15 @@ struct Bot : std::enable_shared_from_this<Bot>
|
|||||||
std::string_view account;
|
std::string_view account;
|
||||||
std::string_view command;
|
std::string_view command;
|
||||||
std::string_view arguments;
|
std::string_view arguments;
|
||||||
|
|
||||||
|
auto nick() const -> std::string_view {
|
||||||
|
auto bang = source.find('!');
|
||||||
|
if (bang == std::string::npos) {
|
||||||
|
return "";
|
||||||
|
} else {
|
||||||
|
return source.substr(0, bang);
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
std::shared_ptr<Client> self_;
|
std::shared_ptr<Client> self_;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user