cleanup
This commit is contained in:
parent
4d298b7eec
commit
fd4612d385
@ -6,16 +6,24 @@ project(xbot
|
|||||||
)
|
)
|
||||||
|
|
||||||
find_package(PkgConfig REQUIRED)
|
find_package(PkgConfig REQUIRED)
|
||||||
find_package(Boost 1.83.0 CONFIG COMPONENTS log)
|
|
||||||
pkg_check_modules(LIBHS libhs REQUIRED IMPORTED_TARGET)
|
pkg_check_modules(LIBHS libhs REQUIRED IMPORTED_TARGET)
|
||||||
|
|
||||||
|
set(BOOST_INCLUDE_LIBRARIES asio log signals2)
|
||||||
|
set(BOOST_ENABLE_CMAKE ON)
|
||||||
include(FetchContent)
|
include(FetchContent)
|
||||||
|
FetchContent_Declare(
|
||||||
|
Boost
|
||||||
|
URL https://github.com/boostorg/boost/releases/download/boost-1.87.0/boost-1.87.0-cmake.tar.xz
|
||||||
|
URL_HASH SHA1=4ec86f884ffb57ce7f6a6c6eb05b1af247aba0ac
|
||||||
|
)
|
||||||
FetchContent_Declare(
|
FetchContent_Declare(
|
||||||
tomlplusplus
|
tomlplusplus
|
||||||
GIT_REPOSITORY https://github.com/marzer/tomlplusplus.git
|
GIT_REPOSITORY https://github.com/marzer/tomlplusplus.git
|
||||||
GIT_TAG v3.4.0
|
GIT_TAG v3.4.0
|
||||||
)
|
)
|
||||||
FetchContent_MakeAvailable(tomlplusplus)
|
FetchContent_MakeAvailable(tomlplusplus)
|
||||||
|
FetchContent_MakeAvailable(Boost)
|
||||||
|
|
||||||
add_custom_command(
|
add_custom_command(
|
||||||
OUTPUT irc_commands.inc
|
OUTPUT irc_commands.inc
|
||||||
@ -39,4 +47,4 @@ add_executable(xbot
|
|||||||
)
|
)
|
||||||
|
|
||||||
target_include_directories(xbot PRIVATE ${CMAKE_CURRENT_BINARY_DIR})
|
target_include_directories(xbot PRIVATE ${CMAKE_CURRENT_BINARY_DIR})
|
||||||
target_link_libraries(xbot PRIVATE Boost::log Boost::boost tomlplusplus_tomlplusplus PkgConfig::LIBHS mybase64)
|
target_link_libraries(xbot PRIVATE Boost::signals2 Boost::log Boost::asio tomlplusplus_tomlplusplus PkgConfig::LIBHS mybase64)
|
||||||
|
@ -1,53 +0,0 @@
|
|||||||
#include "command_thread.hpp"
|
|
||||||
|
|
||||||
#include "connection.hpp"
|
|
||||||
#include "irc_parse_thread.hpp"
|
|
||||||
#include "ircmsg.hpp"
|
|
||||||
|
|
||||||
auto CommandThread::start(Connection& connection) -> void
|
|
||||||
{
|
|
||||||
connection.add_listener<IrcMsgEvent>([&connection](IrcMsgEvent& event)
|
|
||||||
{
|
|
||||||
if (IrcCommand::PRIVMSG != event.command) return;
|
|
||||||
auto const message = event.irc.args[1];
|
|
||||||
if (message.empty()) return;
|
|
||||||
if ('!' != message.front()) return;
|
|
||||||
|
|
||||||
CommandEvent command_event;
|
|
||||||
|
|
||||||
{
|
|
||||||
auto const cmdend = message.find(' ');
|
|
||||||
if (std::string_view::npos == cmdend)
|
|
||||||
{
|
|
||||||
command_event.command = message.substr(1);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
command_event.command = message.substr(1, cmdend - 1);
|
|
||||||
command_event.arg = message.substr(cmdend + 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
auto const nickend = event.irc.source.find('!');
|
|
||||||
if (std::string_view::npos != nickend)
|
|
||||||
{
|
|
||||||
command_event.nick = event.irc.source.substr(0, nickend);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (auto const& [k,v] : event.irc.tags)
|
|
||||||
{
|
|
||||||
if ("solanum.chat/oper" == k)
|
|
||||||
{
|
|
||||||
command_event.oper = v;
|
|
||||||
}
|
|
||||||
else if ("account" == k)
|
|
||||||
{
|
|
||||||
command_event.account = v;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
connection.dispatch(command_event);
|
|
||||||
});
|
|
||||||
}
|
|
@ -1,30 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "event.hpp"
|
|
||||||
|
|
||||||
#include <string_view>
|
|
||||||
|
|
||||||
class Connection;
|
|
||||||
|
|
||||||
struct CommandEvent : Event
|
|
||||||
{
|
|
||||||
/// @brief oper account of sender
|
|
||||||
std::string_view oper;
|
|
||||||
|
|
||||||
/// @brief nickserv acccount of sender
|
|
||||||
std::string_view account;
|
|
||||||
|
|
||||||
/// @brief nickname of sender
|
|
||||||
std::string_view nick;
|
|
||||||
|
|
||||||
/// @brief command name excluding sigil
|
|
||||||
std::string_view command;
|
|
||||||
|
|
||||||
/// @brief complete argument excluding space after command
|
|
||||||
std::string_view arg;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct CommandThread
|
|
||||||
{
|
|
||||||
static auto start(Connection&) -> void;
|
|
||||||
};
|
|
@ -1,6 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
struct Event {
|
|
||||||
virtual ~Event() = default;
|
|
||||||
bool handled_ = false;
|
|
||||||
};
|
|
@ -1,15 +0,0 @@
|
|||||||
#include "ping_thread.hpp"
|
|
||||||
|
|
||||||
#include "connection.hpp"
|
|
||||||
#include "write_irc.hpp"
|
|
||||||
|
|
||||||
auto PingThread::start(Connection& connection) -> void
|
|
||||||
{
|
|
||||||
connection.sig_ircmsg.connect([&connection](auto cmd, auto& msg)
|
|
||||||
{
|
|
||||||
if (IrcCommand::PING == cmd)
|
|
||||||
{
|
|
||||||
send_pong(connection, msg.args[0]);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
@ -1,8 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
struct Connection;
|
|
||||||
|
|
||||||
struct PingThread
|
|
||||||
{
|
|
||||||
static auto start(Connection& connection) -> void;
|
|
||||||
};
|
|
224
priv_thread.cpp
224
priv_thread.cpp
@ -1,224 +0,0 @@
|
|||||||
#include "priv_thread.hpp"
|
|
||||||
|
|
||||||
#include "command_thread.hpp"
|
|
||||||
#include "connection.hpp"
|
|
||||||
#include "write_irc.hpp"
|
|
||||||
|
|
||||||
#include <toml++/toml.hpp>
|
|
||||||
|
|
||||||
#include <boost/log/trivial.hpp>
|
|
||||||
|
|
||||||
#include <fstream>
|
|
||||||
#include <sstream>
|
|
||||||
#include <filesystem>
|
|
||||||
|
|
||||||
PrivThread::PrivThread(Connection& connection, std::string config_path)
|
|
||||||
: connection_{connection}
|
|
||||||
, config_path_{std::move(config_path)}
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
auto PrivThread::check_command(CommandEvent& event, std::string priv) -> bool
|
|
||||||
{
|
|
||||||
auto check_priv = [&priv](auto& map, std::string const& name) {
|
|
||||||
auto const cursor = map.find(name);
|
|
||||||
return cursor != map.end() && cursor->second.contains(priv);
|
|
||||||
};
|
|
||||||
auto check = [&check_priv](auto& map, auto& name) {
|
|
||||||
return
|
|
||||||
(not name.empty() &&
|
|
||||||
(check_priv(map, wildcard) ||
|
|
||||||
check_priv(map, std::string{name})));
|
|
||||||
};
|
|
||||||
return check(oper_privs_, event.oper) || check(account_privs_, event.account);
|
|
||||||
}
|
|
||||||
|
|
||||||
auto PrivThread::list_privs(std::string_view nick) -> void
|
|
||||||
{
|
|
||||||
for (auto const& [oper, privset] : oper_privs_)
|
|
||||||
{
|
|
||||||
std::string message = "Oper ";
|
|
||||||
message += oper;
|
|
||||||
message += ":";
|
|
||||||
|
|
||||||
for (auto const& priv : privset)
|
|
||||||
{
|
|
||||||
message += " ";
|
|
||||||
message += priv;
|
|
||||||
}
|
|
||||||
|
|
||||||
send_notice(connection_, nick, message);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (auto const& [account, privset] : account_privs_)
|
|
||||||
{
|
|
||||||
std::string message = "Account ";
|
|
||||||
message += account;
|
|
||||||
message += ":";
|
|
||||||
|
|
||||||
for (auto const& priv : privset)
|
|
||||||
{
|
|
||||||
message += " ";
|
|
||||||
message += priv;
|
|
||||||
}
|
|
||||||
|
|
||||||
send_notice(connection_, nick, message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
auto PrivThread::on_command(CommandEvent& event) -> void
|
|
||||||
{
|
|
||||||
if ("list_privs" == event.command)
|
|
||||||
{
|
|
||||||
if (check_command(event, PrivThread::owner_priv))
|
|
||||||
{
|
|
||||||
list_privs(event.nick);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if ("add_priv" == event.command)
|
|
||||||
{
|
|
||||||
if (check_command(event, PrivThread::owner_priv))
|
|
||||||
{
|
|
||||||
auto in = std::istringstream{std::string{event.arg}};
|
|
||||||
std::string kind, name, priv;
|
|
||||||
if (in >> kind >> name >> priv)
|
|
||||||
{
|
|
||||||
if ("oper" == kind)
|
|
||||||
{
|
|
||||||
oper_privs_[name].insert(priv);
|
|
||||||
save_config();
|
|
||||||
send_notice(connection_, event.nick, "ack");
|
|
||||||
BOOST_LOG_TRIVIAL(info) << "Priv added. by:" << event.nick << " oper:" << name << " priv:" << priv;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
else if ("account" == kind)
|
|
||||||
{
|
|
||||||
account_privs_[name].insert(priv);
|
|
||||||
save_config();
|
|
||||||
send_notice(connection_, event.nick, "ack");
|
|
||||||
BOOST_LOG_TRIVIAL(info) << "Priv added. by:" << event.nick << " account:" << name << " priv:" << priv;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
send_notice(connection_, event.nick, "nak");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if ("remove_priv" == event.command)
|
|
||||||
{
|
|
||||||
if (check_command(event, PrivThread::owner_priv))
|
|
||||||
{
|
|
||||||
auto in = std::istringstream{std::string{event.arg}};
|
|
||||||
std::string kind, name, priv;
|
|
||||||
if (in >> kind >> name >> priv)
|
|
||||||
{
|
|
||||||
if ("oper" == kind)
|
|
||||||
{
|
|
||||||
if (wildcard == priv)
|
|
||||||
{
|
|
||||||
oper_privs_.erase(name);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
oper_privs_[name].erase(priv);
|
|
||||||
if (oper_privs_[name].empty()) oper_privs_.erase(name);
|
|
||||||
}
|
|
||||||
save_config();
|
|
||||||
send_notice(connection_, event.nick, "ack");
|
|
||||||
BOOST_LOG_TRIVIAL(info) << "Priv removed. by:" << event.nick << " oper:" << name << " priv:" << priv;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
else if ("account" == kind)
|
|
||||||
{
|
|
||||||
if (wildcard == priv)
|
|
||||||
{
|
|
||||||
account_privs_.erase(name);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
account_privs_[name].erase(priv);
|
|
||||||
if (account_privs_[name].empty()) account_privs_.erase(name);
|
|
||||||
}
|
|
||||||
save_config();
|
|
||||||
send_notice(connection_, event.nick, "ack");
|
|
||||||
BOOST_LOG_TRIVIAL(info) << "Priv removed. by:" << event.nick << " account:" << name << " priv:" << priv;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
send_notice(connection_, event.nick, "nak");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
auto PrivThread::save_config() -> void
|
|
||||||
{
|
|
||||||
auto config = toml::table{};
|
|
||||||
|
|
||||||
auto serialize_table = [&config](auto name, auto& map) {
|
|
||||||
if (not map.empty()) {
|
|
||||||
auto tab = toml::table{};
|
|
||||||
for (auto const& [oper, privs] : map)
|
|
||||||
{
|
|
||||||
auto privset = toml::array{};
|
|
||||||
for (auto const& priv : privs)
|
|
||||||
{
|
|
||||||
privset.push_back(priv);
|
|
||||||
}
|
|
||||||
tab.insert(oper, privset);
|
|
||||||
}
|
|
||||||
config.insert(name, tab);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
serialize_table("oper", oper_privs_);
|
|
||||||
serialize_table("account", account_privs_);
|
|
||||||
|
|
||||||
std::string tmp = config_path_ + ".tmp";
|
|
||||||
std::ofstream{tmp} << config;
|
|
||||||
std::filesystem::rename(tmp, config_path_);
|
|
||||||
}
|
|
||||||
|
|
||||||
auto PrivThread::load_config() -> void
|
|
||||||
{
|
|
||||||
if (auto in = std::ifstream{config_path_})
|
|
||||||
{
|
|
||||||
auto const config = toml::parse(in);
|
|
||||||
|
|
||||||
if (config.contains("oper"))
|
|
||||||
{
|
|
||||||
for (auto const [oper, privs] : *config["oper"].as_table())
|
|
||||||
{
|
|
||||||
auto& privset = oper_privs_[std::string{oper.str()}];
|
|
||||||
for (auto const& priv : *privs.as_array())
|
|
||||||
{
|
|
||||||
privset.insert(priv.as_string()->get());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (config.contains("account"))
|
|
||||||
{
|
|
||||||
for (auto const [account, privs] : *config["account"].as_table())
|
|
||||||
{
|
|
||||||
auto& privset = account_privs_[std::string{account.str()}];
|
|
||||||
for (auto const& priv : *privs.as_array())
|
|
||||||
{
|
|
||||||
privset.insert(priv.as_string()->get());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
auto PrivThread::start(Connection& connection, std::string config_path) -> std::shared_ptr<PrivThread>
|
|
||||||
{
|
|
||||||
auto thread = std::make_shared<PrivThread>(connection, config_path);
|
|
||||||
|
|
||||||
thread->load_config();
|
|
||||||
|
|
||||||
connection.add_listener<CommandEvent>([thread](CommandEvent& event)
|
|
||||||
{
|
|
||||||
thread->on_command(event);
|
|
||||||
});
|
|
||||||
|
|
||||||
return thread;
|
|
||||||
}
|
|
@ -1,33 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <memory>
|
|
||||||
#include <string>
|
|
||||||
#include <unordered_map>
|
|
||||||
#include <unordered_set>
|
|
||||||
|
|
||||||
class Connection;
|
|
||||||
class CommandEvent;
|
|
||||||
|
|
||||||
class PrivThread : std::enable_shared_from_this<PrivThread>
|
|
||||||
{
|
|
||||||
Connection& connection_;
|
|
||||||
std::string config_path_;
|
|
||||||
|
|
||||||
std::unordered_map<std::string, std::unordered_set<std::string>> oper_privs_;
|
|
||||||
std::unordered_map<std::string, std::unordered_set<std::string>> account_privs_;
|
|
||||||
|
|
||||||
auto on_command(CommandEvent&) -> void;
|
|
||||||
|
|
||||||
auto load_config() -> void;
|
|
||||||
auto save_config() -> void;
|
|
||||||
auto list_privs(std::string_view nick) -> void;
|
|
||||||
|
|
||||||
public:
|
|
||||||
PrivThread(Connection&, std::string config_path);
|
|
||||||
auto check_command(CommandEvent& event, std::string priv) -> bool;
|
|
||||||
|
|
||||||
static constexpr char const* owner_priv = "owner";
|
|
||||||
static constexpr char const* wildcard = "*";
|
|
||||||
|
|
||||||
static auto start(Connection&, std::string config_path) -> std::shared_ptr<PrivThread>;
|
|
||||||
};
|
|
@ -12,10 +12,10 @@ struct Settings
|
|||||||
std::string realname;
|
std::string realname;
|
||||||
std::string nickname;
|
std::string nickname;
|
||||||
|
|
||||||
|
std::string sasl_mechanism;
|
||||||
std::string sasl_authcid;
|
std::string sasl_authcid;
|
||||||
std::string sasl_authzid;
|
std::string sasl_authzid;
|
||||||
std::string sasl_password;
|
std::string sasl_password;
|
||||||
std::string sasl_mechanism;
|
|
||||||
|
|
||||||
static auto from_stream(std::istream & in) -> Settings;
|
static auto from_stream(std::istream & in) -> Settings;
|
||||||
};
|
};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user