From def0dc67158bba258d7321be20d8bb81a6f91e17 Mon Sep 17 00:00:00 2001 From: Nils Date: Wed, 23 Jun 2021 14:02:41 +0200 Subject: [PATCH] First signs of NickServ arriving soon! lol --- .gitmodules | 3 ++ CMakeLists.txt | 7 ++-- instance.hpp | 2 +- main.cpp | 4 +-- serviceBase.cpp | 21 +++++++++++ serviceBase.hpp | 5 ++- services/nickserv.cpp | 60 ++++++++++++++++++++++++++++++++ services/nickserv.hpp | 46 ++++++++++++++++++++++++ services/template.cpp | 28 --------------- services/template.hpp | 34 ------------------ services/test.cpp | 81 ------------------------------------------- services/test.hpp | 34 ------------------ sqlite_orm | 1 + 13 files changed, 143 insertions(+), 183 deletions(-) create mode 100644 .gitmodules create mode 100644 services/nickserv.cpp create mode 100644 services/nickserv.hpp delete mode 100644 services/template.cpp delete mode 100644 services/template.hpp delete mode 100644 services/test.cpp delete mode 100644 services/test.hpp create mode 160000 sqlite_orm diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..4172eb6 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "sqlite_orm"] + path = sqlite_orm + url = https://github.com/fnc12/sqlite_orm diff --git a/CMakeLists.txt b/CMakeLists.txt index 5c0d142..5cb6ceb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -10,14 +10,17 @@ add_executable(asbots instance.cpp utility.cpp serviceBase.cpp - services/test.cpp + services/nickserv.cpp configParser.cpp ) +target_include_directories(asbots PRIVATE sqlite_orm/include/sqlite_orm) + find_package(PkgConfig REQUIRED) pkg_check_modules(libasync-uv REQUIRED IMPORTED_TARGET libasync-uv) pkg_check_modules(fmt REQUIRED IMPORTED_TARGET fmt) +pkg_check_modules(sqlite3 REQUIRED IMPORTED_TARGET sqlite3) -target_link_libraries(asbots PRIVATE PkgConfig::libasync-uv PkgConfig::fmt) +target_link_libraries(asbots PRIVATE PkgConfig::libasync-uv PkgConfig::fmt PkgConfig::sqlite3) configure_file(config.inil config.inil COPYONLY) diff --git a/instance.hpp b/instance.hpp index a06cb29..31061b3 100644 --- a/instance.hpp +++ b/instance.hpp @@ -103,7 +103,7 @@ struct User { std::string nick; size_t hops = 1; ModeSet umode; - std::string ident; + std::string ident = "~"; std::optional vhost; std::optional ip; std::string realhost; diff --git a/main.cpp b/main.cpp index 6d7b7d9..831f2aa 100644 --- a/main.cpp +++ b/main.cpp @@ -18,7 +18,7 @@ #include "config.hpp" #include "instance.hpp" -#include "services/test.hpp" +#include "services/nickserv.hpp" #include #include @@ -33,7 +33,7 @@ int main() { loop_service service; Instance instance(service, parseConfig("config.inil")); - instance.services.push_back(std::make_unique()); + instance.services.push_back(std::make_unique()); async::detach(instance.run()); async::run_forever(rq.run_token(), loop_service_wrapper{service}); diff --git a/serviceBase.cpp b/serviceBase.cpp index 87f4bc2..3aceeaf 100644 --- a/serviceBase.cpp +++ b/serviceBase.cpp @@ -19,10 +19,13 @@ #include "instance.hpp" #include +#include #include #include #include +using fmt::operator""_format; + async::result ServiceBase::mark_ready(const User& user) { @@ -46,3 +49,21 @@ std::optional ServiceBase::getConfig(const std::string& sectio // Return final result return {k_res->second}; } + +async::result ServiceBase::on_direct_privmsg(std::string_view msg, u_User& author) { + auto split = Utility::strSplit(msg, ' '); + User user = {.server = i->config.server.uid, .uid = uuid}; + + auto res = commands.find(Utility::lowers(split[0])); + if (res == commands.end()) { + co_await i->send_event(user.get_notice("Error: Command not found", author->uid)); + } else { + split.erase(split.begin()); + auto& [fnc, usage, minArgs] = res->second; + if (split.size() < minArgs) { + co_await i->send_event(user.get_notice("Error: Usage: {}"_format(usage), author->uid)); + } else { + co_await fnc(author, split); + } + } +} diff --git a/serviceBase.hpp b/serviceBase.hpp index 4718b89..0ebd7bc 100644 --- a/serviceBase.hpp +++ b/serviceBase.hpp @@ -27,6 +27,8 @@ class Instance; #include #include #include +#include +#include #include @@ -36,10 +38,11 @@ public: UUID uuid; Instance *i; bool ready = false; + std::unordered_map (u_User& sender, const std::vector& args)>, std::string_view, size_t>> commands; virtual async::result intitialize() = 0; virtual async::result on_event(const Event& event) = 0; - virtual async::result on_direct_privmsg(std::string_view msg, u_User& author) = 0; + virtual async::result on_direct_privmsg(std::string_view msg, u_User& author); async::result mark_ready(const User& user); std::optional getConfig(const std::string& section, const std::string& key); diff --git a/services/nickserv.cpp b/services/nickserv.cpp new file mode 100644 index 0000000..2ebb10d --- /dev/null +++ b/services/nickserv.cpp @@ -0,0 +1,60 @@ +#include "nickserv.hpp" +#include "../instance.hpp" + +#include +#include +#include +#include +#include + + + +async::result NickServ::intitialize() { + co_await i->netInfo.wait_ready(); + user = { + .server = i->config.server.uid, + .nick = std::string(getConfig("NickServ", "nickname").value_or("NickServ")), + .realhost = i->config.server.name, + .uid = uuid, + .realname = i->netInfo.name + }; + co_await mark_ready(user); + + using namespace sqlite_orm; + storage = std::make_unique(make_storage( + std::string(getConfig("NickServ", "database").value_or("nickserv.sqlite")), + make_table("users", + make_column("id", &Account::id, autoincrement(), primary_key()), + make_column("name", &Account::name), + make_column("password_hash", &Account::password_hash)) + )); + storage->sync_schema(); + + commands = { + {"test", {[this] (u_User& sender, std::vector args) -> async::result { + co_await i->send_event(user.get_notice("Hello world! Works", sender->uid)); + }, "", 0} + }, + {"identify", {[this] (u_User& sender, const std::vector& args) -> async::result { + // Get user from storage + auto accounts_found = storage->get_all(where(c(&Account::name) == sender->nick)); + if (accounts_found.empty()) { + co_await i->send_event(user.get_notice("Error: Your nick is not registered!", sender->uid)); + co_return; + } + auto& account = accounts_found[0]; + // Check password + if (account.password_hash != args[0]) { + co_await i->send_event(user.get_notice("Error: Invalid password!", sender->uid)); + co_return; + } + // Login + co_await i->send_event(sender->get_encap_su(account.name)); + }, "", 1} + } + }; +} + +async::result NickServ::on_event(const Event& event) { + co_return; +} diff --git a/services/nickserv.hpp b/services/nickserv.hpp new file mode 100644 index 0000000..c5625a9 --- /dev/null +++ b/services/nickserv.hpp @@ -0,0 +1,46 @@ +/* + * asbots + * Copyright (C) 2021 niansa + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#ifndef _TEST_HPP +#define _TEST_HPP +#include "../instance.hpp" +#include "../serviceBase.hpp" + +#include "sqlite_orm.h" + +#include +#include +#include + + + +struct Account { + size_t id; + std::string name, password_hash; +}; + +using Storage = sqlite_orm::internal::storage_t >, sqlite_orm::internal::column_t, std::allocator >, const std::__cxx11::basic_string, std::allocator >& (Account::*)() const, void (Account::*)(std::__cxx11::basic_string, std::allocator >)>, sqlite_orm::internal::column_t, std::allocator >, const std::__cxx11::basic_string, std::allocator >& (Account::*)() const, void (Account::*)(std::__cxx11::basic_string, std::allocator >)> > >; + +class NickServ : public ServiceBase { + std::unique_ptr storage; + + User user; + + virtual async::result intitialize() override; + virtual async::result on_event(const Event& event) override; +}; +#endif diff --git a/services/template.cpp b/services/template.cpp deleted file mode 100644 index 82859f2..0000000 --- a/services/template.cpp +++ /dev/null @@ -1,28 +0,0 @@ -#include "test.hpp" - -#include - - - -async::result TestService::intitialize() { - user = { - .server = i->config.get().server.uid, - .nick = "services", - .ident = "services", - .host = "services.", - .realhost = "127.0.0.1", - .uid = uuid, - .realname = "LOL" - }; - co_await mark_ready(user); - co_await i->send_event(user.get_join("#lol")); - co_await i->send_event(user.get_privmsg("Test... Hello world!", "#lol")); -} - -async::result TestService::on_event(const Event& event) { - co_return; -} - -async::result TestService::on_direct_privmsg(std::string_view msg, u_User& author) { - co_await i->send_event(user.get_privmsg("I received a message: "+std::string(msg), "#lol")); -} diff --git a/services/template.hpp b/services/template.hpp deleted file mode 100644 index 18da3a6..0000000 --- a/services/template.hpp +++ /dev/null @@ -1,34 +0,0 @@ -/* - * asbots - * Copyright (C) 2021 niansa - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -#ifndef _TEST_HPP -#define _TEST_HPP -#include "../instance.hpp" -#include "../serviceBase.hpp" - -#include - - - -class TestService : public ServiceBase { - User user; - - virtual async::result intitialize() override; - virtual async::result on_event(const Event& event) override; - virtual async::result on_direct_privmsg(std::string_view msg, u_User& author) override; -}; -#endif diff --git a/services/test.cpp b/services/test.cpp deleted file mode 100644 index 256a6cd..0000000 --- a/services/test.cpp +++ /dev/null @@ -1,81 +0,0 @@ -/* - * asbots - * Copyright (C) 2021 niansa - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -#include "test.hpp" -#include "../utility.hpp" - -#include -#include - -using fmt::operator""_format; - - - -async::result TestService::intitialize() { - co_await i->netInfo.wait_ready(); - user = { - .server = i->config.server.uid, - .nick = "services", - .ident = "services", - .realhost = "services.", - .uid = uuid, - .realname = i->netInfo.name, - .loginName = "serviceD" - }; - Channel serviceChannel = { - .server = i->config.server.uid, - .name = std::string(getConfig("testservice", "channel").value_or("#services")) - }; - co_await mark_ready(user); - co_await i->send_event(serviceChannel.get_sjoin(user.uid)); - //co_await i->send_event(serviceChannel.get_topic("IRC Service channel", user.uid)); - co_await i->send_event(user.get_notice("Test... Hello world!", serviceChannel.name)); -} - -async::result TestService::on_event(const Event& event) { - co_return; -} - -async::result TestService::on_direct_privmsg(std::string_view msg, u_User &author) { - auto cmd = Utility::strSplit(msg, ' ', 1); - - auto command = Utility::lowers(cmd[0]); - - Event response = user.get_notice("You need to log in as NetOP first", author->uid); - if (cmd.size() == 2 && !cmd[1].empty()) { - if (command == "login") { - co_await i->send_event(author->get_encap_su(cmd[1])); - response = user.get_notice("Logged in!", author->uid); - } else if (command == "send") { - if (author->loginName.value_or("") == "NetOP") { - Event event; - try { - event.parse(cmd[1]); - co_await i->send_event(event); - response = user.get_notice("Sent.", author->uid); - } catch (std::exception&e) { - response = user.get_notice(e.what(), author->uid); - } - } - } else { - response = user.get_notice("Unknown command", author->uid); - } - } else { - response = user.get_notice("Insufficient arguments?", author->uid); - } - co_await i->send_event(response); -} diff --git a/services/test.hpp b/services/test.hpp deleted file mode 100644 index 18da3a6..0000000 --- a/services/test.hpp +++ /dev/null @@ -1,34 +0,0 @@ -/* - * asbots - * Copyright (C) 2021 niansa - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -#ifndef _TEST_HPP -#define _TEST_HPP -#include "../instance.hpp" -#include "../serviceBase.hpp" - -#include - - - -class TestService : public ServiceBase { - User user; - - virtual async::result intitialize() override; - virtual async::result on_event(const Event& event) override; - virtual async::result on_direct_privmsg(std::string_view msg, u_User& author) override; -}; -#endif diff --git a/sqlite_orm b/sqlite_orm new file mode 160000 index 0000000..1ee0a86 --- /dev/null +++ b/sqlite_orm @@ -0,0 +1 @@ +Subproject commit 1ee0a8653fe57ed4d4f69b5a65839b1861c41d32