initial formatter framework

This commit is contained in:
Eric Mertens 2025-02-02 19:46:11 -08:00
parent 39a4d84a54
commit 5aec8397bb

View File

@ -21,6 +21,12 @@ using namespace std::literals;
namespace { namespace {
std::map<std::string, void(*)(std::shared_ptr<Webhooks>, const ProjectSettings &, std::string_view, const boost::json::object &)> formatters {
{"push", [](std::shared_ptr<Webhooks> webhooks, const ProjectSettings &project, std::string_view full_name, const boost::json::object &body) {
webhooks->send_notice(project.channel, "push");
}},
};
// Used as the completion handler for coroutines in this module to print // Used as the completion handler for coroutines in this module to print
// failure reasons to the log. // failure reasons to the log.
auto report_error(std::exception_ptr eptr) -> void auto report_error(std::exception_ptr eptr) -> void
@ -86,7 +92,7 @@ auto announce_event(
auto process_event( auto process_event(
std::shared_ptr<Webhooks> self, std::shared_ptr<Webhooks> self,
const std::string_view notify_user, const std::string_view notify_user,
const std::string_view event_name, const std::string event_name,
const boost::json::value &json const boost::json::value &json
) -> void ) -> void
{ {
@ -117,13 +123,16 @@ auto process_event(
return; return;
} }
if (not settings.enabled || not settings.events.contains(std::string{event_name})) if (not settings.enabled || not settings.events.contains(event_name))
{ {
// quietly ignore events we don't care about // quietly ignore events we don't care about
return; return;
} }
announce_event(self, settings, std::move(full_name), event_name, std::move(event)); auto formatter_cursor = formatters.find(event_name);
if (formatter_cursor != formatters.end()) {
formatter_cursor->second(self, settings, full_name, event);
}
} }
// Process the HTTP request validating its structure and signature. // Process the HTTP request validating its structure and signature.
@ -509,6 +518,68 @@ std::map<std::string, void (*)(std::shared_ptr<Webhooks>, const myirc::Bot::Comm
reply_to(webhooks, cmd, "Disabled project " + name); reply_to(webhooks, cmd, "Disabled project " + name);
} }
}}, }},
{"add-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_added = 0, n_skipped = 0, n_unknown = 0;
while (iss >> name) {
if (formatters.contains(name)) {
const auto [_, added] = project.events.insert(name);
if (added) { n_added++; } else { n_skipped++; }
} else {
n_unknown++;
}
}
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) {
if (formatters.contains(name)) {
const auto removed = project.events.erase(name);
if (removed) { n_removed++; } else { n_skipped++; }
} else {
n_unknown++;
}
}
webhooks->save_settings();
std::stringstream ss;
ss << "Events updated.";
if (n_removed) { ss << " removed: " << n_removed; }
if (n_skipped) { ss << " skipped: " << n_skipped; }
if (n_unknown) { ss << " unknown: " << n_unknown; }
reply_to(webhooks, cmd, ss.str());
}
}},
{"add-access", [](std::shared_ptr<Webhooks> webhooks, const myirc::Bot::Command &cmd) { {"add-access", [](std::shared_ptr<Webhooks> webhooks, const myirc::Bot::Command &cmd) {
if (cmd.oper.empty()) if (cmd.oper.empty())
{ {
@ -544,10 +615,6 @@ std::map<std::string, void (*)(std::shared_ptr<Webhooks>, const myirc::Bot::Comm
if (iss >> name >> account) if (iss >> name >> account)
{ {
auto &project = webhooks->settings_.projects.at(name); auto &project = webhooks->settings_.projects.at(name);
if (not authorized_for_project(cmd, project, cmd.account))
{
return;
}
auto removed = project.authorized_accounts.erase(account); auto removed = project.authorized_accounts.erase(account);
if (removed) { if (removed) {
webhooks->save_settings(); webhooks->save_settings();
@ -557,4 +624,19 @@ std::map<std::string, void (*)(std::shared_ptr<Webhooks>, const myirc::Bot::Comm
} }
} }
}}, }},
{"set-channel", [](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, channel;
if (iss >> name >> channel)
{
auto &project = webhooks->settings_.projects.at(name);
project.channel = channel;
webhooks->save_settings();
reply_to(webhooks, cmd, "Channel assigned");
}
}},
}; };