Compare commits

..

No commits in common. "f83abab0a031c765041b168667a3d6b75649ec31" and "8ff0f13109f551c9d73f9e482e3037d6bb912f99" have entirely different histories.

4 changed files with 23 additions and 229 deletions

View File

@ -47,11 +47,10 @@ jobs:
submodules: recursive submodules: recursive
- name: Install Dependencies - name: Install Dependencies
# TODO: is 2.6 new enough?
run: sudo apt update && sudo apt -y install nix run: sudo apt update && sudo apt -y install nix
- name: Nix build - name: Nix build
run: nix --extra-experimental-features nix-command build '.#static' run: nix build '.#static'
- uses: actions/upload-artifact@v3 - uses: actions/upload-artifact@v3
with: with:

View File

@ -15,11 +15,6 @@
#include "./message_cleanser.hpp" #include "./message_cleanser.hpp"
#include "./message_command_dispatcher.hpp" #include "./message_command_dispatcher.hpp"
#include <solanaceae/message3/components.hpp>
#include <solanaceae/contact/components.hpp>
#include <solanaceae/tox_contacts/components.hpp>
#include <solanaceae/toxcore/utils.hpp>
#include <nlohmann/json.hpp> #include <nlohmann/json.hpp>
#include <chrono> #include <chrono>
@ -170,13 +165,12 @@ int main(int argc, char** argv) {
mcd.registerCommand( mcd.registerCommand(
"host", "", "host", "",
"info", "info",
[](std::string_view, Message3Handle m) -> bool { [](std::string_view) -> bool {
std::cout << "INFO got called :)\n"; std::cout << "INFO got called :)\n";
return true; return true;
}, },
"Get basic information about this bot" "Get basic information about this bot"
); );
} }
PluginManager pm; PluginManager pm;
@ -203,134 +197,10 @@ int main(int argc, char** argv) {
ToxMessageManager tmm{rmm, cr, tcm, tc, tc}; ToxMessageManager tmm{rmm, cr, tcm, tc, tc};
ToxTransferManager ttm{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<Message::Components::ContactFrom>().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::Components::ToxFriendEphemeral>(contact_from)) {
const auto con_opt = tc.toxFriendGetConnectionStatus(cr.get<Contact::Components::ToxFriendEphemeral>(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::Components::ToxGroupPeerEphemeral>(contact_from)) {
const auto [group_number, peer_number] = cr.get<Contact::Components::ToxGroupPeerEphemeral>(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::Components::ToxFriendPersistent, Contact::Components::ToxGroupPeerPersistent>(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<Message::Components::ContactFrom>().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<Message::Components::ContactFrom>().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 { // setup plugin instances
g_provideInstance<ConfigModelI>("ConfigModelI", "host", &conf); g_provideInstance<ConfigModelI>("ConfigModelI", "host", &conf);
g_provideInstance<Contact3Registry>("Contact3Registry", "host", &cr); g_provideInstance<Contact3Registry>("Contact3Registry", "host", &cr);
g_provideInstance<RegistryMessageModel>("RegistryMessageModel", "host", &rmm); g_provideInstance<RegistryMessageModel>("RegistryMessageModel", "host", &rmm);
g_provideInstance<MessageCommandDispatcher>("MessageCommandDispatcher", "host", &mcd);
g_provideInstance<ToxI>("ToxI", "host", &tc); g_provideInstance<ToxI>("ToxI", "host", &tc);
g_provideInstance<ToxPrivateI>("ToxPrivateI", "host", &tpi); g_provideInstance<ToxPrivateI>("ToxPrivateI", "host", &tpi);
@ -379,8 +249,6 @@ int main(int argc, char** argv) {
mc.iterate(0.02f); mc.iterate(0.02f);
mcd.iterate(0.02f);
//std::this_thread::sleep_for( // time left to get to 60fps //std::this_thread::sleep_for( // time left to get to 60fps
//std::chrono::duration<float, std::chrono::seconds::period>(0.0166f) // 60fps frame duration //std::chrono::duration<float, std::chrono::seconds::period>(0.0166f) // 60fps frame duration
//- std::chrono::duration<float, std::chrono::seconds::period>(std::chrono::steady_clock::now() - new_time) // time used for rendering //- std::chrono::duration<float, std::chrono::seconds::period>(std::chrono::steady_clock::now() - new_time) // time used for rendering

View File

@ -3,11 +3,8 @@
#include <solanaceae/util/config_model.hpp> #include <solanaceae/util/config_model.hpp>
#include <solanaceae/message3/components.hpp> #include <solanaceae/message3/components.hpp>
#include <string_view>
#include <utility> #include <utility>
#include <iostream> #include <iostream>
#include <vector>
#include <map>
//MessageCommandDispatcher::Command::Command(Command&& other) : //MessageCommandDispatcher::Command::Command(Command&& other) :
//m(std::move(other.m)), //m(std::move(other.m)),
@ -32,8 +29,8 @@ MessageCommandDispatcher::MessageCommandDispatcher(
registerCommand( registerCommand(
"host", "", "host", "",
"help", "help",
[this](std::string_view params, Message3Handle m) -> bool { [this](std::string_view params) -> bool {
return helpCommand(params, m); return helpCommand(params);
}, },
"Get help" "Get help"
); );
@ -43,19 +40,11 @@ MessageCommandDispatcher::MessageCommandDispatcher(
MessageCommandDispatcher::~MessageCommandDispatcher(void) { MessageCommandDispatcher::~MessageCommandDispatcher(void) {
} }
void MessageCommandDispatcher::iterate(float) { void MessageCommandDispatcher::iterate(float time_delta) {
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) { static std::string_view get_first_word(std::string_view text) {
if (text.empty()) { if (text.empty()) {
out_next = std::string_view::npos;
return text; return text;
} }
@ -63,21 +52,17 @@ static std::string_view get_first_word(std::string_view text, std::string_view::
const auto pos_first_non_space = text.find_first_not_of(' '); const auto pos_first_non_space = text.find_first_not_of(' ');
if (pos_first_non_space == std::string_view::npos) { if (pos_first_non_space == std::string_view::npos) {
// only contains spaces o.o // only contains spaces o.o
out_next = std::string_view::npos; return ""; // should return text as is?
return "";
} }
text = text.substr(pos_first_non_space); text = text.substr(pos_first_non_space);
out_next += pos_first_non_space;
const auto pos_first_space = text.find_first_of(' '); const auto pos_first_space = text.find_first_of(' ');
if (pos_first_space == 0 || pos_first_space == std::string_view::npos) { if (pos_first_space == 0 || pos_first_space == std::string_view::npos) {
// does not contain spaces // does not contain spaces
// command is whole message // command is whole message
out_next = std::string_view::npos;
return text; return text;
} else { } else {
out_next += pos_first_space;
return text.substr(0, pos_first_space); return text.substr(0, pos_first_space);
} }
} }
@ -86,10 +71,10 @@ void MessageCommandDispatcher::registerCommand(
std::string_view m, // module std::string_view m, // module
std::string_view m_prefix, // module prefix (if any) std::string_view m_prefix, // module prefix (if any)
std::string_view command, // command std::string_view command, // command
std::function<bool(std::string_view params, Message3Handle m)>&& fn, std::function<bool(std::string_view params)>&& fn,
std::string_view help_text std::string_view help_text
) { ) {
std::string full_command_string = (m_prefix.empty() ? "" : std::string{m_prefix} + " ") + std::string{command}; std::string full_command_string = std::string{m_prefix} + std::string{command};
if (_command_map.count(full_command_string)) { if (_command_map.count(full_command_string)) {
std::cout << "MCD warning: overwriting existing '" << full_command_string << "'\n"; std::cout << "MCD warning: overwriting existing '" << full_command_string << "'\n";
@ -104,42 +89,8 @@ void MessageCommandDispatcher::registerCommand(
}; };
} }
bool MessageCommandDispatcher::helpCommand(std::string_view params, Message3Handle m) { bool MessageCommandDispatcher::helpCommand(std::string_view params) {
std::cout << "MCD: help got called '" << params << "'\n"; std::cout << "MCD: help got called '" << params << "'\n";
std::map<std::string, std::vector<decltype(_command_map.cbegin())>> 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<Message::Components::ContactFrom>().c;
for (const auto& [module_name, command_list] : module_command_list) {
_message_queue.push_back({
contact_from,
"=== " + module_name + " ==="
});
for (const auto& it : command_list) {
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
});
}
}
return true; return true;
} }
@ -207,35 +158,20 @@ bool MessageCommandDispatcher::onEvent(const Message::Events::MessageConstruct&
std::string_view first_word; std::string_view first_word;
std::string_view second_word; std::string_view second_word;
std::string_view::size_type pos_next = 0;
first_word = get_first_word(message_text, pos_next); first_word = get_first_word(message_text);
std::cout << "------- first_word:'" << first_word << "' pos_next:" << pos_next << "\n"; std::cout << "------- first_word:'" << first_word << "'\n";
if (first_word.size() != message_text.size()) { if (first_word.size() != message_text.size()) {
second_word = get_first_word( second_word = get_first_word(
message_text.substr(pos_next), message_text.substr(
pos_next // TODO: optimize this
message_text.find(first_word)
+ first_word.size()
)
); );
} }
std::cout << "------- second_word:'" << second_word << "' empty:" << second_word.empty() << " pos_next:" << pos_next << "\n"; std::cout << "------- second_word:'" << second_word << "' empty:" << second_word.empty() << "\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 // first search first + space + second word
if (!second_word.empty()) { if (!second_word.empty()) {
@ -245,7 +181,7 @@ bool MessageCommandDispatcher::onEvent(const Message::Events::MessageConstruct&
const auto command_it = _command_map.find(query); const auto command_it = _command_map.find(query);
if (command_it != _command_map.cend()) { if (command_it != _command_map.cend()) {
command_it->second.fn(params, e.e); command_it->second.fn(message_text);
return true; return true;
} }
} }
@ -253,8 +189,7 @@ bool MessageCommandDispatcher::onEvent(const Message::Events::MessageConstruct&
// then seach first word only // then seach first word only
const auto command_it = _command_map.find(std::string{first_word}); const auto command_it = _command_map.find(std::string{first_word});
if (command_it != _command_map.cend()) { if (command_it != _command_map.cend()) {
params = std::string{second_word} + " " + params; command_it->second.fn(message_text);
command_it->second.fn(params, e.e);
return true; return true;
} }

View File

@ -2,8 +2,6 @@
#include <solanaceae/message3/registry_message_model.hpp> #include <solanaceae/message3/registry_message_model.hpp>
#include <deque>
// fwd // fwd
struct ConfigModelI; struct ConfigModelI;
@ -16,19 +14,13 @@ class MessageCommandDispatcher : public RegistryMessageModelEventI {
std::string m; // module std::string m; // module
std::string m_prefix; // module prefix (if any) std::string m_prefix; // module prefix (if any)
std::string command; // command std::string command; // command
std::function<bool(std::string_view params, Message3Handle m)> fn; std::function<bool(std::string_view params)> fn;
std::string help_text; std::string help_text;
//Command(const Command&) = delete; //Command(const Command&) = delete;
}; };
std::unordered_map<std::string, Command> _command_map; std::unordered_map<std::string, Command> _command_map;
struct QueuedMessage {
Contact3 to;
std::string message;
};
std::deque<QueuedMessage> _message_queue;
public: public:
MessageCommandDispatcher(Contact3Registry& cr, RegistryMessageModel& rmm, ConfigModelI& conf); MessageCommandDispatcher(Contact3Registry& cr, RegistryMessageModel& rmm, ConfigModelI& conf);
~MessageCommandDispatcher(void); ~MessageCommandDispatcher(void);
@ -48,12 +40,12 @@ class MessageCommandDispatcher : public RegistryMessageModelEventI {
std::string_view m, // module std::string_view m, // module
std::string_view m_prefix, // module prefix (if any) std::string_view m_prefix, // module prefix (if any)
std::string_view command, // command std::string_view command, // command
std::function<bool(std::string_view params, Message3Handle m)>&& fn, std::function<bool(std::string_view params)>&& fn,
std::string_view help_text std::string_view help_text
); );
// generates a help // generates a help
bool helpCommand(std::string_view params, Message3Handle m); bool helpCommand(std::string_view params);
protected: // mm protected: // mm
bool onEvent(const Message::Events::MessageConstruct& e) override; bool onEvent(const Message::Events::MessageConstruct& e) override;