diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index ed17f7b..11b41e3 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -12,9 +12,6 @@ add_executable(totato ./message_cleanser.hpp ./message_cleanser.cpp - ./message_command_dispatcher.hpp - ./message_command_dispatcher.cpp - ./managment_commands.hpp ./managment_commands.cpp diff --git a/src/config_commands.cpp b/src/config_commands.cpp index 2e8dc48..1b70789 100644 --- a/src/config_commands.cpp +++ b/src/config_commands.cpp @@ -3,7 +3,7 @@ #include #include -#include "./message_command_dispatcher.hpp" +#include #include #include diff --git a/src/fun_commands.cpp b/src/fun_commands.cpp index 5ce3626..8917052 100644 --- a/src/fun_commands.cpp +++ b/src/fun_commands.cpp @@ -4,7 +4,7 @@ #include //#include -#include "./message_command_dispatcher.hpp" +#include #include //#include diff --git a/src/main.cpp b/src/main.cpp index 8807380..072e681 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -13,7 +13,7 @@ #include "./tox_client.hpp" #include "./auto_dirty.hpp" #include "./message_cleanser.hpp" -#include "./message_command_dispatcher.hpp" +#include #include "./managment_commands.hpp" #include "./config_commands.hpp" diff --git a/src/managment_commands.cpp b/src/managment_commands.cpp index 6dc5a0c..1b8fed4 100644 --- a/src/managment_commands.cpp +++ b/src/managment_commands.cpp @@ -3,11 +3,11 @@ #include #include -#include "./message_command_dispatcher.hpp" +#include #include #include -#include +#include #include #include diff --git a/src/message_command_dispatcher.cpp b/src/message_command_dispatcher.cpp deleted file mode 100644 index ec64a7a..0000000 --- a/src/message_command_dispatcher.cpp +++ /dev/null @@ -1,373 +0,0 @@ -#include "./message_command_dispatcher.hpp" - -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -MessageCommandDispatcher::MessageCommandDispatcher( - Contact3Registry& cr, - RegistryMessageModel& rmm, - ConfigModelI& conf -) : - _cr(cr), _rmm(rmm), _conf(conf), _program_started_at(Message::getTimeMS()) -{ - // overwrite default admin and moderator to false - _conf.set("MessageCommandDispatcher", "admin", false); - _conf.set("MessageCommandDispatcher", "moderator", false); - - _rmm.subscribe(this, RegistryMessageModel_Event::message_construct); - - { // setup basic commands for bot - registerCommand( - "host", "", - "help", - [this](std::string_view params, Message3Handle m) -> bool { - return helpCommand(params, m); - }, - "Get help", - Perms::EVERYONE - ); - } -} - -MessageCommandDispatcher::~MessageCommandDispatcher(void) { -} - -void MessageCommandDispatcher::iterate(float) { - if (!_message_queue.empty()) { - _rmm.sendText( - _message_queue.front().to, - _message_queue.front().message - ); - _message_queue.pop_front(); - } -} - -static std::string_view get_first_word(std::string_view text, std::string_view::size_type& out_next) { - if (text.empty()) { - out_next = std::string_view::npos; - return text; - } - - // trim - const auto pos_first_non_space = text.find_first_not_of(' '); - if (pos_first_non_space == std::string_view::npos) { - // only contains spaces o.o - out_next = std::string_view::npos; - return ""; - } - - text = text.substr(pos_first_non_space); - out_next += pos_first_non_space; - - const auto pos_first_space = text.find_first_of(' '); - if (pos_first_space == 0 || pos_first_space == std::string_view::npos) { - // does not contain spaces - // command is whole message - out_next = std::string_view::npos; - return text; - } else { - out_next += pos_first_space; - return text.substr(0, pos_first_space); - } -} - -void MessageCommandDispatcher::registerCommand( - std::string_view m, // module - std::string_view m_prefix, // module prefix (if any) - std::string_view command, // command - std::function&& fn, - std::string_view help_text, - Perms perms -) { - std::string full_command_string = (m_prefix.empty() ? "" : std::string{m_prefix} + " ") + std::string{command}; - - if (_command_map.count(full_command_string)) { - std::cout << "MCD warning: overwriting existing '" << full_command_string << "'\n"; - } - - assert( - // needs atleast one "group" - (perms & ( - Perms::EVERYONE | - Perms::ADMIN | - Perms::MODERATOR - )) != 0u - ); - - assert( - // at most one "group" - (((perms & Perms::EVERYONE) != 0) + - ((perms & Perms::ADMIN) != 0) + - ((perms & Perms::MODERATOR) != 0)) - == 1 - ); - - _command_map[full_command_string] = Command{ - std::string{m}, - std::string{m_prefix}, - std::string{command}, - std::move(fn), - std::string{help_text}, - perms - }; -} - -bool MessageCommandDispatcher::helpCommand(std::string_view params, Message3Handle m) { - std::cout << "MCD: help got called '" << params << "'\n"; - - std::map> module_command_list; - for (auto it = _command_map.cbegin(); it != _command_map.cend(); it++) { - if (true) { // have permission - module_command_list[it->second.m].push_back(it); - } - } - - const auto contact_from = m.get().c; - - for (const auto& [module_name, command_list] : module_command_list) { - _message_queue.push_back({ - contact_from, - "=== " + module_name + " ===" - }); - - bool module_empty = true; - for (const auto& it : command_list) { - if (!hasPermission(it->second, contact_from)) { - continue; - } - - module_empty = false; - - std::string help_line {" !"}; - if (!it->second.m_prefix.empty()) { - help_line += it->second.m_prefix + " "; - } - - help_line += it->second.command; - - help_line += " - "; - help_line += it->second.help_text; - - _message_queue.push_back({ - contact_from, - help_line - }); - } - - if (module_empty) { - // unsend module cat title - _message_queue.pop_back(); - } - } - - return true; -} - -bool MessageCommandDispatcher::hasPermission(const Command& cmd, const Contact3 contact) { - if (!_cr.all_of(contact)) { - std::cerr << "MCD error: contact without ID\n"; - return false; // default to false - } - - const auto id_str = bin2hex(_cr.get(contact).data); - std::cout << "MCD: perm check for id '" << id_str << "'\n"; - - // TODO: blacklist here - // TODO: whitelist here - - if ((cmd.perms & Perms::EVERYONE) != 0) { - return true; - } - - if ((cmd.perms & Perms::ADMIN) != 0) { - auto is_admin_opt = _conf.get_bool("MessageCommandDispatcher", "admin", id_str); - assert(is_admin_opt.has_value); - - return is_admin_opt.value(); - } - - if ((cmd.perms & Perms::MODERATOR) != 0) { - auto is_mod_opt = _conf.get_bool("MessageCommandDispatcher", "moderator", id_str); - assert(is_mod_opt.has_value); - - return is_mod_opt.value(); - } - - return false; -} - -bool MessageCommandDispatcher::onEvent(const Message::Events::MessageConstruct& e) { - if (!e.e.all_of()) { - std::cout << "MCD: got message that is not"; - - if (!e.e.all_of()) { - std::cout << " contact_from"; - } - if (!e.e.all_of()) { - std::cout << " text"; - } - if (!e.e.all_of()) { - std::cout << " unread"; - } - - std::cout << "\n"; - return false; - } - - if (e.e.any_of()) { - std::cout << "MCD: got message that is"; - if (e.e.all_of()) { - std::cout << " action"; - } - std::cout << "\n"; - return false; - } - - if (e.e.any_of()) { - // test if message was written before program was started (-1s) - if (e.e.get().ts + 1'000 < _program_started_at) { - // message too old - return false; - } - } - - std::string_view message_text = e.e.get().text; - - if (message_text.empty()) { - std::cout << "MCD warning: empty message\n"; - // empty message? - return false; - } - - // skip unrelyable synced - if (e.e.all_of()) { - const auto& list = e.e.get().ts; - if ( - std::find_if( - list.cbegin(), list.cend(), - [this](const auto&& it) { - return _cr.any_of< - Contact::Components::TagSelfStrong, - Contact::Components::TagSelfWeak // trust weak self - >(it.first); - } - ) == list.cend() - ) { - // self not found - // TODO: config for self only - return false; - } - } - - const bool is_private = _cr.any_of(e.e.get().c); - - if (is_private) { - // check for command prefix - if ( - message_text.at(0) == '!' || - message_text.at(0) == '/' - ) { - // starts with command prefix - // remove c prefix - message_text = message_text.substr(1); - } - } else { - // check for command prefix - if ( - message_text.at(0) != '!' && - message_text.at(0) != '/' - ) { - // does not start with command prefix, not for us - return false; - } - - // remove c prefix - message_text = message_text.substr(1); - } - - if (message_text.empty()) { - // empty message? - std::cout << "MCD: got empty command\n"; - return false; - } - - std::cout << "MCD: got command '" << message_text << "'\n"; - - std::string_view first_word; - std::string_view second_word; - std::string_view::size_type pos_next = 0; - - first_word = get_first_word(message_text, pos_next); - std::cout << "------- first_word:'" << first_word << "' pos_next:" << pos_next << "\n"; - if (first_word.size() != message_text.size()) { - second_word = get_first_word( - message_text.substr(pos_next), - pos_next - ); - } - - std::cout << "------- second_word:'" << second_word << "' empty:" << second_word.empty() << " pos_next:" << pos_next << "\n"; - - std::string params; - if (pos_next != std::string_view::npos && message_text.size() > pos_next+1) { - auto tmp_params = message_text.substr(pos_next); - - const auto params_pos_first_non_space = tmp_params.find_first_not_of(' '); - if (params_pos_first_non_space == std::string_view::npos) { - tmp_params = {}; - } else if (params_pos_first_non_space != 0) { - // trim leading whitespace - tmp_params = tmp_params.substr(params_pos_first_non_space); - } - - params = tmp_params; - - std::cout << "------- params:'" << params << "'\n"; - } - - const auto contact_from = e.e.get().c; - - // first search first + space + second word - if (!second_word.empty()) { - std::string query {first_word}; - query += " "; - query += second_word; - - const auto command_it = _command_map.find(query); - if (command_it != _command_map.cend()) { - if (!hasPermission(command_it->second, contact_from)) { - return false; - } - - return command_it->second.fn(params, e.e); - } - } - - // then seach first word only - const auto command_it = _command_map.find(std::string{first_word}); - if (command_it != _command_map.cend()) { - if (!hasPermission(command_it->second, contact_from)) { - return false; - } - - params = std::string{second_word} + " " + params; - return command_it->second.fn(params, e.e); - } - - return false; -} - -bool MessageCommandDispatcher::onEvent(const Message::Events::MessageUpdated&) { - // do i need this? - return false; -} - diff --git a/src/message_command_dispatcher.hpp b/src/message_command_dispatcher.hpp deleted file mode 100644 index b8daf26..0000000 --- a/src/message_command_dispatcher.hpp +++ /dev/null @@ -1,89 +0,0 @@ -#pragma once - -#include -#include - -#include -#include -#include -#include -#include - -// fwd -struct ConfigModelI; - -class MessageCommandDispatcher : public RegistryMessageModelEventI { - Contact3Registry& _cr; - RegistryMessageModel& _rmm; - ConfigModelI& _conf; - - public: - enum Perms { - BLACKLIST = 1 << 0, - WHITELIST = 1 << 1, - - // can only be trumped by blacklist - EVERYONE = 1 << 2, - - // can only be trumped by blacklist - // TODO: replace with groups? - ADMIN = 1 << 3, - MODERATOR = 1 << 4, - }; - - private: - struct Command { - std::string m; // module - std::string m_prefix; // module prefix (if any) - std::string command; // command - std::function fn; - std::string help_text; - - Perms perms = Perms::ADMIN; // default to highest - - //Command(const Command&) = delete; - }; - std::unordered_map _command_map; - - struct QueuedMessage { - Contact3 to; - std::string message; - }; - std::deque _message_queue; - - uint64_t _program_started_at {0}; - - public: - MessageCommandDispatcher(Contact3Registry& cr, RegistryMessageModel& rmm, ConfigModelI& conf); - ~MessageCommandDispatcher(void); - - void iterate(float time_delta); // do we? - - // module command/command - // permissions? - // - user(s) - // - group(s) - // - everyone else? - // callable - // help text? - - - void registerCommand( - std::string_view m, // module - std::string_view m_prefix, // module prefix (if any) - std::string_view command, // command - std::function&& fn, - std::string_view help_text, - Perms perms = Perms::ADMIN - ); - - // generates a help - bool helpCommand(std::string_view params, Message3Handle m); - - bool hasPermission(const Command& cmd, const Contact3 contact); - - protected: // mm - bool onEvent(const Message::Events::MessageConstruct& e) override; - bool onEvent(const Message::Events::MessageUpdated& e) override; -}; - diff --git a/src/tox_commands.cpp b/src/tox_commands.cpp index 7f02272..7346e83 100644 --- a/src/tox_commands.cpp +++ b/src/tox_commands.cpp @@ -2,15 +2,15 @@ #include #include +#include #include #include -#include "./message_command_dispatcher.hpp" +#include #include #include #include -#include #include