consolidate command interface
This commit is contained in:
parent
5aec8397bb
commit
5f2439e5af
@ -67,15 +67,15 @@ static auto start_irc(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
client->sig_registered.connect([connection, webhook]() {
|
client->sig_registered.connect([client, webhook]() {
|
||||||
webhook->set_connection(connection);
|
webhook->set_client(client);
|
||||||
});
|
});
|
||||||
|
|
||||||
// On disconnect reconnect in 5 seconds
|
// On disconnect reconnect in 5 seconds
|
||||||
// connection is captured in the disconnect handler so it can keep itself alive
|
// connection is captured in the disconnect handler so it can keep itself alive
|
||||||
connection->sig_disconnect.connect(
|
connection->sig_disconnect.connect(
|
||||||
[&io, &settings, connection, webhook]() {
|
[&io, &settings, connection, webhook]() {
|
||||||
webhook->clear_connection();
|
webhook->clear_client();
|
||||||
auto timer = std::make_shared<boost::asio::steady_timer>(io);
|
auto timer = std::make_shared<boost::asio::steady_timer>(io);
|
||||||
timer->expires_after(5s);
|
timer->expires_after(5s);
|
||||||
timer->async_wait([&io, &settings, timer, webhook](auto) { start_irc(io, settings, webhook); });
|
timer->async_wait([&io, &settings, timer, webhook](auto) { start_irc(io, settings, webhook); });
|
||||||
|
222
driver/web.cpp
222
driver/web.cpp
@ -269,31 +269,32 @@ auto start_webhook(
|
|||||||
const char *webhook_settings_filename
|
const char *webhook_settings_filename
|
||||||
) -> std::shared_ptr<Webhooks>
|
) -> std::shared_ptr<Webhooks>
|
||||||
{
|
{
|
||||||
std::ifstream webhook_settings_file{webhook_settings_filename};
|
auto webhook = std::make_shared<Webhooks>(webhook_settings_filename);
|
||||||
if (!webhook_settings_file)
|
webhook->load_settings();
|
||||||
{
|
|
||||||
BOOST_LOG_TRIVIAL(error) << "Unable to open webhook settings file";
|
|
||||||
std::exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
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<Webhooks>(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 Webhooks::load_settings() -> void
|
||||||
|
{
|
||||||
|
std::ifstream webhook_settings_file{settings_filename_};
|
||||||
|
if (!webhook_settings_file)
|
||||||
|
{
|
||||||
|
BOOST_LOG_TRIVIAL(error) << "Unable to open webhook settings file";
|
||||||
|
}
|
||||||
|
auto webhook_settings = toml::parse(webhook_settings_file);
|
||||||
|
settings_ = WebhookSettings::from_toml(webhook_settings);
|
||||||
|
}
|
||||||
|
|
||||||
auto Webhooks::save_settings() const -> void
|
auto Webhooks::save_settings() const -> void
|
||||||
{
|
{
|
||||||
std::ofstream webhook_settings_file{settings_file};
|
std::ofstream webhook_settings_file{settings_filename_};
|
||||||
if (!webhook_settings_file)
|
if (!webhook_settings_file)
|
||||||
{
|
{
|
||||||
BOOST_LOG_TRIVIAL(error) << "Unable to open webhook settings file";
|
BOOST_LOG_TRIVIAL(error) << "Unable to open webhook settings file";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
webhook_settings_file << settings_.to_toml() << "\n";
|
||||||
webhook_settings_file << settings_.to_toml();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
auto ProjectSettings::from_toml(const toml::table &v) -> ProjectSettings
|
auto ProjectSettings::from_toml(const toml::table &v) -> ProjectSettings
|
||||||
@ -412,9 +413,9 @@ auto WebhookSettings::to_toml() const -> toml::table
|
|||||||
// 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 Webhooks::send_notice(std::string_view target, std::string message) -> void
|
auto Webhooks::send_notice(std::string_view target, std::string message) -> void
|
||||||
{
|
{
|
||||||
if (connection_)
|
if (client_)
|
||||||
{
|
{
|
||||||
connection_->send_notice(target, message);
|
client_->get_connection().send_notice(target, message);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -422,19 +423,19 @@ auto Webhooks::send_notice(std::string_view target, std::string message) -> void
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Webhooks::set_connection(std::shared_ptr<myirc::Connection> connection) -> void
|
auto Webhooks::set_client(std::shared_ptr<myirc::Client> client) -> void
|
||||||
{
|
{
|
||||||
connection_ = std::move(connection);
|
client_ = std::move(client);
|
||||||
for (auto &&[target, message] : std::move(events_))
|
for (auto &&[target, message] : std::move(events_))
|
||||||
{
|
{
|
||||||
connection_->send_notice(target, message);
|
client_->get_connection().send_notice(target, message);
|
||||||
}
|
}
|
||||||
events_.clear();
|
events_.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Webhooks::clear_connection() -> void
|
auto Webhooks::clear_client() -> void
|
||||||
{
|
{
|
||||||
connection_.reset();
|
client_.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
static auto reply_to(std::shared_ptr<Webhooks> webhooks, const myirc::Bot::Command &cmd, std::string message) -> void
|
static auto reply_to(std::shared_ptr<Webhooks> webhooks, const myirc::Bot::Command &cmd, std::string message) -> void
|
||||||
@ -460,68 +461,32 @@ static auto authorized_for_project(
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::map<std::string, void (*)(std::shared_ptr<Webhooks>, const myirc::Bot::Command &)> webhook_commands{
|
std::map<std::string, void (*)(std::shared_ptr<Webhooks>, const myirc::Bot::Command &)> webhook_commands{
|
||||||
{"add-credential", [](std::shared_ptr<Webhooks> webhooks, const myirc::Bot::Command &cmd) {
|
{"announce", [](std::shared_ptr<Webhooks> webhooks, const myirc::Bot::Command &cmd) {
|
||||||
if (cmd.oper.empty())
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
std::istringstream iss{std::string{cmd.arguments}};
|
std::istringstream iss{std::string{cmd.arguments}};
|
||||||
std::string name, key;
|
std::string name, mode;
|
||||||
if (iss >> name >> key)
|
if (iss >> name >> mode)
|
||||||
{
|
|
||||||
webhooks->settings_.credentials.insert_or_assign(name, key);
|
|
||||||
webhooks->save_settings();
|
|
||||||
reply_to(webhooks, cmd, "Added credential " + name);
|
|
||||||
}
|
|
||||||
}},
|
|
||||||
{"drop-credential", [](std::shared_ptr<Webhooks> 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<Webhooks> webhooks, const myirc::Bot::Command &cmd) {
|
|
||||||
std::istringstream iss{std::string{cmd.arguments}};
|
|
||||||
std::string name;
|
|
||||||
if (iss >> name)
|
|
||||||
{
|
{
|
||||||
auto &project = webhooks->settings_.projects.at(name);
|
auto &project = webhooks->settings_.projects.at(name);
|
||||||
if (not authorized_for_project(cmd, project, cmd.account))
|
if (not authorized_for_project(cmd, project, cmd.account))
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (mode == "on") {
|
||||||
project.enabled = true;
|
project.enabled = true;
|
||||||
webhooks->save_settings();
|
|
||||||
reply_to(webhooks, cmd, "Enabled project " + name);
|
reply_to(webhooks, cmd, "Enabled project " + name);
|
||||||
}
|
} else if (mode == "off") {
|
||||||
}},
|
project.enabled = false;
|
||||||
{"disable-project", [](std::shared_ptr<Webhooks> webhooks, const myirc::Bot::Command &cmd) {
|
reply_to(webhooks, cmd, "Disabled project " + name);
|
||||||
std::istringstream iss{std::string{cmd.arguments}};
|
} else {
|
||||||
std::string name;
|
|
||||||
if (iss >> name)
|
|
||||||
{
|
|
||||||
auto &project = webhooks->settings_.projects.at(name);
|
|
||||||
if (not authorized_for_project(cmd, project, cmd.account))
|
|
||||||
{
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
project.enabled = false;
|
|
||||||
webhooks->save_settings();
|
webhooks->save_settings();
|
||||||
reply_to(webhooks, cmd, "Disabled project " + name);
|
|
||||||
}
|
}
|
||||||
}},
|
}},
|
||||||
{"add-events", [](std::shared_ptr<Webhooks> webhooks, const myirc::Bot::Command &cmd) {
|
{"event", [](std::shared_ptr<Webhooks> webhooks, const myirc::Bot::Command &cmd) {
|
||||||
std::istringstream iss{std::string{cmd.arguments}};
|
std::istringstream iss{std::string{cmd.arguments}};
|
||||||
std::string name;
|
std::string name, mode;
|
||||||
if (iss >> name)
|
if (iss >> name >> mode)
|
||||||
{
|
{
|
||||||
auto &project = webhooks->settings_.projects.at(name);
|
auto &project = webhooks->settings_.projects.at(name);
|
||||||
if (not authorized_for_project(cmd, project, cmd.account))
|
if (not authorized_for_project(cmd, project, cmd.account))
|
||||||
@ -529,7 +494,18 @@ std::map<std::string, void (*)(std::shared_ptr<Webhooks>, const myirc::Bot::Comm
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned n_added = 0, n_skipped = 0, n_unknown = 0;
|
if (mode == "list") {
|
||||||
|
std::stringstream ss;
|
||||||
|
ss << "Events for " << name << ":";
|
||||||
|
for (auto &&event : project.events) {
|
||||||
|
ss << " " << event;
|
||||||
|
}
|
||||||
|
reply_to(webhooks, cmd, ss.str());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned n_added = 0, n_removed = 0, n_skipped = 0, n_unknown = 0;
|
||||||
|
if (mode == "add") {
|
||||||
while (iss >> name) {
|
while (iss >> name) {
|
||||||
if (formatters.contains(name)) {
|
if (formatters.contains(name)) {
|
||||||
const auto [_, added] = project.events.insert(name);
|
const auto [_, added] = project.events.insert(name);
|
||||||
@ -538,29 +514,7 @@ std::map<std::string, void (*)(std::shared_ptr<Webhooks>, const myirc::Bot::Comm
|
|||||||
n_unknown++;
|
n_unknown++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else if (mode == "del") {
|
||||||
webhooks->save_settings();
|
|
||||||
|
|
||||||
std::stringstream ss;
|
|
||||||
ss << "Events updated.";
|
|
||||||
if (n_added) { ss << " added: " << n_added; }
|
|
||||||
if (n_skipped) { ss << " skipped: " << n_skipped; }
|
|
||||||
if (n_unknown) { ss << " unknown: " << n_unknown; }
|
|
||||||
reply_to(webhooks, cmd, ss.str());
|
|
||||||
}
|
|
||||||
}},
|
|
||||||
{"drop-events", [](std::shared_ptr<Webhooks> webhooks, const myirc::Bot::Command &cmd) {
|
|
||||||
std::istringstream iss{std::string{cmd.arguments}};
|
|
||||||
std::string name;
|
|
||||||
if (iss >> name)
|
|
||||||
{
|
|
||||||
auto &project = webhooks->settings_.projects.at(name);
|
|
||||||
if (not authorized_for_project(cmd, project, cmd.account))
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned n_removed = 0, n_skipped = 0, n_unknown = 0;
|
|
||||||
while (iss >> name) {
|
while (iss >> name) {
|
||||||
if (formatters.contains(name)) {
|
if (formatters.contains(name)) {
|
||||||
const auto removed = project.events.erase(name);
|
const auto removed = project.events.erase(name);
|
||||||
@ -569,62 +523,62 @@ std::map<std::string, void (*)(std::shared_ptr<Webhooks>, const myirc::Bot::Comm
|
|||||||
n_unknown++;
|
n_unknown++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
webhooks->save_settings();
|
webhooks->save_settings();
|
||||||
|
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
ss << "Events updated.";
|
ss << "Events updated:";
|
||||||
if (n_removed) { ss << " removed: " << n_removed; }
|
if (n_added) { ss << " added " << n_added; }
|
||||||
if (n_skipped) { ss << " skipped: " << n_skipped; }
|
if (n_removed) { ss << " removed " << n_removed; }
|
||||||
if (n_unknown) { ss << " unknown: " << n_unknown; }
|
if (n_skipped) { ss << " skipped " << n_skipped; }
|
||||||
|
if (n_unknown) { ss << " unknown " << n_unknown; }
|
||||||
reply_to(webhooks, cmd, ss.str());
|
reply_to(webhooks, cmd, ss.str());
|
||||||
}
|
}
|
||||||
}},
|
}},
|
||||||
{"add-access", [](std::shared_ptr<Webhooks> webhooks, const myirc::Bot::Command &cmd) {
|
{"auth", [](std::shared_ptr<Webhooks> webhooks, const myirc::Bot::Command &cmd) {
|
||||||
if (cmd.oper.empty())
|
if (cmd.oper.empty())
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
std::istringstream iss{std::string{cmd.arguments}};
|
std::istringstream iss{std::string{cmd.arguments}};
|
||||||
std::string name, account;
|
std::string name, mode;
|
||||||
if (iss >> name >> account)
|
if (iss >> name >> mode)
|
||||||
{
|
{
|
||||||
auto &project = webhooks->settings_.projects.at(name);
|
auto &project = webhooks->settings_.projects.at(name);
|
||||||
if (not authorized_for_project(cmd, project, cmd.account))
|
|
||||||
{
|
if (mode == "list") {
|
||||||
|
std::stringstream ss;
|
||||||
|
ss << "Authorized accounts:";
|
||||||
|
for (auto &&event : project.authorized_accounts) {
|
||||||
|
ss << " " << event;
|
||||||
|
}
|
||||||
|
reply_to(webhooks, cmd, ss.str());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
auto [_, inserted] = project.authorized_accounts.insert(account);
|
|
||||||
if (inserted) {
|
unsigned n_added = 0, n_removed = 0, n_skipped = 0;
|
||||||
|
if (mode == "add") {
|
||||||
|
while (iss >> name) {
|
||||||
|
const auto [_, added] = project.authorized_accounts.insert(name);
|
||||||
|
if (added) { n_added++; } else { n_skipped++; }
|
||||||
|
}
|
||||||
|
} else if (mode == "del") {
|
||||||
|
while (iss >> name) {
|
||||||
|
const auto removed = project.authorized_accounts.erase(name);
|
||||||
|
if (removed) { n_removed++; } else { n_skipped++; }
|
||||||
|
}
|
||||||
|
}
|
||||||
webhooks->save_settings();
|
webhooks->save_settings();
|
||||||
reply_to(webhooks, cmd, "Access added");
|
|
||||||
}
|
std::stringstream ss;
|
||||||
else
|
ss << "Authorized accounts updated:";
|
||||||
{
|
if (n_added) { ss << " added " << n_added; }
|
||||||
reply_to(webhooks, cmd, "Access already set");
|
if (n_removed) { ss << " removed " << n_removed; }
|
||||||
}
|
if (n_skipped) { ss << " skipped " << n_skipped; }
|
||||||
|
reply_to(webhooks, cmd, ss.str());
|
||||||
}
|
}
|
||||||
}},
|
}},
|
||||||
{"drop-access", [](std::shared_ptr<Webhooks> webhooks, const myirc::Bot::Command &cmd) {
|
{"setchannel", [](std::shared_ptr<Webhooks> webhooks, const myirc::Bot::Command &cmd) {
|
||||||
if (cmd.oper.empty())
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
std::istringstream iss{std::string{cmd.arguments}};
|
|
||||||
std::string name, account;
|
|
||||||
if (iss >> name >> account)
|
|
||||||
{
|
|
||||||
auto &project = webhooks->settings_.projects.at(name);
|
|
||||||
auto removed = project.authorized_accounts.erase(account);
|
|
||||||
if (removed) {
|
|
||||||
webhooks->save_settings();
|
|
||||||
reply_to(webhooks, cmd, "Access dropped");
|
|
||||||
} else {
|
|
||||||
reply_to(webhooks, cmd, "Access not found");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}},
|
|
||||||
{"set-channel", [](std::shared_ptr<Webhooks> webhooks, const myirc::Bot::Command &cmd) {
|
|
||||||
if (cmd.oper.empty())
|
if (cmd.oper.empty())
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
@ -639,4 +593,12 @@ std::map<std::string, void (*)(std::shared_ptr<Webhooks>, const myirc::Bot::Comm
|
|||||||
reply_to(webhooks, cmd, "Channel assigned");
|
reply_to(webhooks, cmd, "Channel assigned");
|
||||||
}
|
}
|
||||||
}},
|
}},
|
||||||
|
{"rehash", [](std::shared_ptr<Webhooks> webhooks, const myirc::Bot::Command &cmd) {
|
||||||
|
if (cmd.oper.empty())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
webhooks->load_settings();
|
||||||
|
reply_to(webhooks, cmd, "Rehashed");
|
||||||
|
}},
|
||||||
};
|
};
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <myirc/bot.hpp>
|
#include <myirc/bot.hpp>
|
||||||
#include <myirc/connection.hpp>
|
#include <myirc/client.hpp>
|
||||||
|
|
||||||
#include <toml++/toml.hpp>
|
#include <toml++/toml.hpp>
|
||||||
|
|
||||||
@ -49,27 +49,27 @@ struct WebhookSettings {
|
|||||||
|
|
||||||
class Webhooks {
|
class Webhooks {
|
||||||
// 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::Client> client_;
|
||||||
|
|
||||||
// Buffered events in case connection was inactive when event was received
|
// Buffered events in case connection was inactive when event was received
|
||||||
std::vector<std::pair<std::string, std::string>> events_;
|
std::vector<std::pair<std::string, std::string>> events_;
|
||||||
|
|
||||||
const char * settings_file;
|
const char * settings_filename_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
WebhookSettings settings_;
|
WebhookSettings settings_;
|
||||||
|
|
||||||
Webhooks(WebhookSettings settings, const char * settings_file)
|
Webhooks(const char * settings_filename)
|
||||||
: settings_(std::move(settings))
|
: settings_filename_{settings_filename}
|
||||||
, 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 send_notice(std::string_view, std::string) -> void;
|
auto send_notice(std::string_view, std::string) -> void;
|
||||||
auto set_connection(std::shared_ptr<myirc::Connection> connection) -> void;
|
auto set_client(std::shared_ptr<myirc::Client> client) -> void;
|
||||||
auto clear_connection() -> void;
|
auto clear_client() -> void;
|
||||||
auto save_settings() const -> void;
|
auto save_settings() const -> void;
|
||||||
|
auto load_settings() -> void;
|
||||||
};
|
};
|
||||||
|
|
||||||
auto start_webhook(boost::asio::io_context &io, const char *) -> std::shared_ptr<Webhooks>;
|
auto start_webhook(boost::asio::io_context &io, const char *) -> std::shared_ptr<Webhooks>;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user