diff --git a/CMakeLists.txt b/CMakeLists.txt index 0c69c3e..f95cf38 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,16 +6,24 @@ project(xbot ) find_package(PkgConfig REQUIRED) -find_package(Boost 1.83.0 CONFIG COMPONENTS log) + pkg_check_modules(LIBHS libhs REQUIRED IMPORTED_TARGET) +set(BOOST_INCLUDE_LIBRARIES asio log signals2) +set(BOOST_ENABLE_CMAKE ON) include(FetchContent) FetchContent_Declare( - tomlplusplus - GIT_REPOSITORY https://github.com/marzer/tomlplusplus.git - GIT_TAG v3.4.0 +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( + tomlplusplus + GIT_REPOSITORY https://github.com/marzer/tomlplusplus.git + GIT_TAG v3.4.0 + ) FetchContent_MakeAvailable(tomlplusplus) +FetchContent_MakeAvailable(Boost) add_custom_command( OUTPUT irc_commands.inc @@ -39,4 +47,4 @@ add_executable(xbot ) 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) diff --git a/command_thread.cpp b/command_thread.cpp deleted file mode 100644 index 7752f07..0000000 --- a/command_thread.cpp +++ /dev/null @@ -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([&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); - }); -} diff --git a/command_thread.hpp b/command_thread.hpp deleted file mode 100644 index d1b7e66..0000000 --- a/command_thread.hpp +++ /dev/null @@ -1,30 +0,0 @@ -#pragma once - -#include "event.hpp" - -#include - -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; -}; diff --git a/event.hpp b/event.hpp deleted file mode 100644 index 9be648c..0000000 --- a/event.hpp +++ /dev/null @@ -1,6 +0,0 @@ -#pragma once - -struct Event { - virtual ~Event() = default; - bool handled_ = false; -}; diff --git a/ping_thread.cpp b/ping_thread.cpp deleted file mode 100644 index 43838fc..0000000 --- a/ping_thread.cpp +++ /dev/null @@ -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]); - } - }); -} diff --git a/ping_thread.hpp b/ping_thread.hpp deleted file mode 100644 index 989c12e..0000000 --- a/ping_thread.hpp +++ /dev/null @@ -1,8 +0,0 @@ -#pragma once - -struct Connection; - -struct PingThread -{ - static auto start(Connection& connection) -> void; -}; diff --git a/priv_thread.cpp b/priv_thread.cpp deleted file mode 100644 index b06a313..0000000 --- a/priv_thread.cpp +++ /dev/null @@ -1,224 +0,0 @@ -#include "priv_thread.hpp" - -#include "command_thread.hpp" -#include "connection.hpp" -#include "write_irc.hpp" - -#include - -#include - -#include -#include -#include - -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 -{ - auto thread = std::make_shared(connection, config_path); - - thread->load_config(); - - connection.add_listener([thread](CommandEvent& event) - { - thread->on_command(event); - }); - - return thread; -} diff --git a/priv_thread.hpp b/priv_thread.hpp deleted file mode 100644 index 5f7b48c..0000000 --- a/priv_thread.hpp +++ /dev/null @@ -1,33 +0,0 @@ -#pragma once - -#include -#include -#include -#include - -class Connection; -class CommandEvent; - -class PrivThread : std::enable_shared_from_this -{ - Connection& connection_; - std::string config_path_; - - std::unordered_map> oper_privs_; - std::unordered_map> 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; -}; diff --git a/settings.hpp b/settings.hpp index 6609414..e1c3a29 100644 --- a/settings.hpp +++ b/settings.hpp @@ -12,10 +12,10 @@ struct Settings std::string realname; std::string nickname; + std::string sasl_mechanism; std::string sasl_authcid; std::string sasl_authzid; std::string sasl_password; - std::string sasl_mechanism; static auto from_stream(std::istream & in) -> Settings; };