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
|
||||
bot->sig_command.connect([connection](const Bot::Command &cmd) {
|
||||
if (cmd.oper == "glguy" && cmd.command == "ping") {
|
||||
if (auto bang = cmd.source.find('!'); bang != cmd.source.npos) {
|
||||
connection->send_notice(cmd.source.substr(0, bang), cmd.arguments);
|
||||
}
|
||||
// Dispatch commands to the webhook logic
|
||||
bot->sig_command.connect([webhook, connection](const Bot::Command &cmd) {
|
||||
auto cursor = webhook_commands.find(std::string{cmd.command});
|
||||
if (cursor != webhook_commands.end()) {
|
||||
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);
|
||||
WebhookSettings settings = WebhookSettings::from_toml(webhook_settings);
|
||||
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);
|
||||
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
|
||||
@ -374,3 +381,133 @@ auto WebhookSettings::to_toml() const -> toml::table
|
||||
{"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
|
||||
|
||||
#include <myirc/bot.hpp>
|
||||
#include <myirc/connection.hpp>
|
||||
|
||||
#include <toml++/toml.hpp>
|
||||
@ -46,55 +47,38 @@ struct WebhookSettings {
|
||||
static auto from_toml(const toml::table &v) -> WebhookSettings;
|
||||
};
|
||||
|
||||
struct WebhookEvent {
|
||||
std::string channel;
|
||||
class GithubWebhook {
|
||||
public:
|
||||
struct Notice {
|
||||
std::string target;
|
||||
std::string message;
|
||||
};
|
||||
private:
|
||||
|
||||
class GithubWebhook {
|
||||
// IRC connection to announce on; could be empty
|
||||
std::shared_ptr<myirc::Connection> connection_;
|
||||
|
||||
// Buffered events in case connection was inactive when event was received
|
||||
std::vector<WebhookEvent> events_;
|
||||
std::vector<Notice> events_;
|
||||
|
||||
|
||||
// Actually write the event to the connection.
|
||||
// Only call when there is a connection.
|
||||
auto write_event(WebhookEvent event) -> void;
|
||||
const char * settings_file;
|
||||
|
||||
public:
|
||||
WebhookSettings settings_;
|
||||
|
||||
GithubWebhook(WebhookSettings settings)
|
||||
GithubWebhook(WebhookSettings settings, const char * settings_file)
|
||||
: settings_(std::move(settings))
|
||||
, settings_file(settings_file)
|
||||
{
|
||||
}
|
||||
|
||||
// Either emit the event now or save it until a connection is set
|
||||
auto add_event(WebhookEvent event) -> void
|
||||
{
|
||||
if (connection_) {
|
||||
write_event(std::move(event));
|
||||
} 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 add_event(Notice event) -> void;
|
||||
auto set_connection(std::shared_ptr<myirc::Connection> connection) -> void;
|
||||
auto clear_connection() -> void;
|
||||
auto save_settings() const -> void;
|
||||
};
|
||||
|
||||
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 command;
|
||||
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_;
|
||||
|
Loading…
x
Reference in New Issue
Block a user