From bd30bc8fd5ae38034dc2c2e05ad37b6ead88ed30 Mon Sep 17 00:00:00 2001 From: Green Sky Date: Sun, 3 Dec 2023 20:01:47 +0100 Subject: [PATCH] params parsing + basic tox commands !! no permissions yet --- src/main.cpp | 132 ++++++++++++++++++++++++++++- src/message_command_dispatcher.cpp | 65 ++++++++++---- src/message_command_dispatcher.hpp | 6 +- 3 files changed, 182 insertions(+), 21 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index da80650..716510e 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -15,6 +15,11 @@ #include "./message_cleanser.hpp" #include "./message_command_dispatcher.hpp" +#include +#include +#include +#include + #include #include @@ -165,12 +170,13 @@ int main(int argc, char** argv) { mcd.registerCommand( "host", "", "info", - [](std::string_view) -> bool { + [](std::string_view, Message3Handle m) -> bool { std::cout << "INFO got called :)\n"; return true; }, "Get basic information about this bot" ); + } PluginManager pm; @@ -197,10 +203,134 @@ int main(int argc, char** argv) { ToxMessageManager tmm{rmm, cr, tcm, tc, tc}; ToxTransferManager ttm{rmm, cr, tcm, tc, tc}; + { // setup more advanced commands + mcd.registerCommand( + "tox", "tox", + "status", + [&](std::string_view, Message3Handle m) -> bool { + const auto tox_self_status = tc.toxSelfGetConnectionStatus(); + + const auto contact_from = m.get().c; + + std::string reply{"dht:"}; + + if (tox_self_status == Tox_Connection::TOX_CONNECTION_UDP) { + reply += "upd-direct"; + } else if (tox_self_status == Tox_Connection::TOX_CONNECTION_TCP) { + reply += "tcp-relayed"; + } + + if (cr.all_of(contact_from)) { + const auto con_opt = tc.toxFriendGetConnectionStatus(cr.get(contact_from).friend_number); + if (!con_opt.has_value() || con_opt.value() == Tox_Connection::TOX_CONNECTION_NONE) { + reply += "\nfriend:offline"; + } else if (con_opt.value() == Tox_Connection::TOX_CONNECTION_UDP) { + reply += "\nfriend:udp-direct"; + } else if (con_opt.value() == Tox_Connection::TOX_CONNECTION_TCP) { + reply += "\nfriend:tcp-relayed"; + } + } else if (cr.all_of(contact_from)) { + const auto [group_number, peer_number] = cr.get(contact_from); + + const auto [con_opt, _] = tc.toxGroupPeerGetConnectionStatus(group_number, peer_number); + if (!con_opt.has_value() || con_opt.value() == Tox_Connection::TOX_CONNECTION_NONE) { + reply += "\ngroup-peer:offline"; + } else if (con_opt.value() == Tox_Connection::TOX_CONNECTION_UDP) { + reply += "\ngroup-peer:udp-direct"; + } else if (con_opt.value() == Tox_Connection::TOX_CONNECTION_TCP) { + reply += "\ngroup-peer:tcp-relayed"; + } + } else if (cr.any_of(contact_from)) { + reply += "\noffline"; + } else { + reply += "\nunk"; + } + + rmm.sendText( + contact_from, + reply + ); + + return true; + }, + "Query the tox status of dht and to you." + ); + + mcd.registerCommand( + "tox", "tox", + "add", + [&](std::string_view params, Message3Handle m) -> bool { + const auto contact_from = m.get().c; + + if (params.size() != 38*2) { + rmm.sendText( + contact_from, + "error adding friend, id is not the correct size!" + ); + return true; + } + + // TODO: add tcm interface + const auto [_, err] = tc.toxFriendAdd(hex2bin(std::string{params}), "Add me, I am totato"); + + if (err == Tox_Err_Friend_Add::TOX_ERR_FRIEND_ADD_OK) { + rmm.sendText( + contact_from, + "freind request sent" + ); + } else { + rmm.sendText( + contact_from, + "error adding friend, error code " + std::to_string(err) + ); + } + + return true; + }, + "add a tox friend by id" + ); + + mcd.registerCommand( + "tox", "tox", + "join", + [&](std::string_view params, Message3Handle m) -> bool { + const auto contact_from = m.get().c; + + if (params.size() != 32*2) { + rmm.sendText( + contact_from, + "error joining group, id is not the correct size!" + ); + return true; + } + + auto name_opt = conf.get_string("tox", "name"); + + // TODO: add tcm interface + const auto [_, err] = tc.toxGroupJoin(hex2bin(std::string{params}), std::string{name_opt.value_or("no-name-found")}, ""); + if (err == Tox_Err_Group_Join::TOX_ERR_GROUP_JOIN_OK) { + rmm.sendText( + contact_from, + "joining group..." + ); + } else { + rmm.sendText( + contact_from, + "error joining group, error code " + std::to_string(err) + ); + } + + return true; + }, + "join a tox group by id" + ); + } + { // setup plugin instances g_provideInstance("ConfigModelI", "host", &conf); g_provideInstance("Contact3Registry", "host", &cr); g_provideInstance("RegistryMessageModel", "host", &rmm); + g_provideInstance("MessageCommandDispatcher", "host", &mcd); g_provideInstance("ToxI", "host", &tc); g_provideInstance("ToxPrivateI", "host", &tpi); diff --git a/src/message_command_dispatcher.cpp b/src/message_command_dispatcher.cpp index 89d4205..2eef90e 100644 --- a/src/message_command_dispatcher.cpp +++ b/src/message_command_dispatcher.cpp @@ -1,8 +1,12 @@ #include "./message_command_dispatcher.hpp" +#include "nlohmann/detail/input/position_t.hpp" +#include "solanaceae/message3/registry_message_model.hpp" +#include #include #include +#include #include #include @@ -29,8 +33,8 @@ MessageCommandDispatcher::MessageCommandDispatcher( registerCommand( "host", "", "help", - [this](std::string_view params) -> bool { - return helpCommand(params); + [this](std::string_view params, Message3Handle m) -> bool { + return helpCommand(params, m); }, "Get help" ); @@ -43,8 +47,9 @@ MessageCommandDispatcher::~MessageCommandDispatcher(void) { void MessageCommandDispatcher::iterate(float time_delta) { } -static std::string_view get_first_word(std::string_view text) { +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; } @@ -52,17 +57,21 @@ static std::string_view get_first_word(std::string_view text) { 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 - return ""; // should return text as is? + 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); } } @@ -71,10 +80,10 @@ 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::function&& fn, std::string_view help_text ) { - std::string full_command_string = std::string{m_prefix} + std::string{command}; + 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"; @@ -89,8 +98,14 @@ void MessageCommandDispatcher::registerCommand( }; } -bool MessageCommandDispatcher::helpCommand(std::string_view params) { +bool MessageCommandDispatcher::helpCommand(std::string_view params, Message3Handle m) { std::cout << "MCD: help got called '" << params << "'\n"; + + _rmm.sendText( + m.get().c, + "I am still missing :), ping green for how it actually works." + ); + return true; } @@ -158,20 +173,35 @@ bool MessageCommandDispatcher::onEvent(const Message::Events::MessageConstruct& 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); - std::cout << "------- first_word:'" << first_word << "'\n"; + 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( - // TODO: optimize this - message_text.find(first_word) - + first_word.size() - ) + message_text.substr(pos_next), + pos_next ); } - std::cout << "------- second_word:'" << second_word << "' empty:" << second_word.empty() << "\n"; + 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"; + } // first search first + space + second word if (!second_word.empty()) { @@ -181,7 +211,7 @@ bool MessageCommandDispatcher::onEvent(const Message::Events::MessageConstruct& const auto command_it = _command_map.find(query); if (command_it != _command_map.cend()) { - command_it->second.fn(message_text); + command_it->second.fn(params, e.e); return true; } } @@ -189,7 +219,8 @@ bool MessageCommandDispatcher::onEvent(const Message::Events::MessageConstruct& // then seach first word only const auto command_it = _command_map.find(std::string{first_word}); if (command_it != _command_map.cend()) { - command_it->second.fn(message_text); + params = std::string{second_word} + " " + params; + command_it->second.fn(params, e.e); return true; } diff --git a/src/message_command_dispatcher.hpp b/src/message_command_dispatcher.hpp index d38da01..502a4d1 100644 --- a/src/message_command_dispatcher.hpp +++ b/src/message_command_dispatcher.hpp @@ -14,7 +14,7 @@ class MessageCommandDispatcher : public RegistryMessageModelEventI { std::string m; // module std::string m_prefix; // module prefix (if any) std::string command; // command - std::function fn; + std::function fn; std::string help_text; //Command(const Command&) = delete; @@ -40,12 +40,12 @@ class MessageCommandDispatcher : public RegistryMessageModelEventI { std::string_view m, // module std::string_view m_prefix, // module prefix (if any) std::string_view command, // command - std::function&& fn, + std::function&& fn, std::string_view help_text ); // generates a help - bool helpCommand(std::string_view params); + bool helpCommand(std::string_view params, Message3Handle m); protected: // mm bool onEvent(const Message::Events::MessageConstruct& e) override;