1
0
Fork 0
mirror of https://gitlab.com/niansa/asbots.git synced 2025-03-06 20:48:25 +01:00

Code that makes gcc crash... commited for bug reporting

This commit is contained in:
Nils 2021-06-27 23:10:14 +02:00
parent 14163753e5
commit 8773d0b886
6 changed files with 171 additions and 7 deletions

View file

@ -11,6 +11,7 @@ add_executable(asbots
utility.cpp
serviceBase.cpp
services/nickserv.cpp
services/chanserv.cpp
configParser.cpp
)

View file

@ -31,6 +31,7 @@
#include <fmt/format.h>
#include <string>
#include <string_view>
#include <sstream>
#include <optional>
#include <unordered_map>
#include <vector>
@ -66,6 +67,14 @@ struct ModeSet {
std::string str;
std::vector<std::tuple<char, std::string>> params;
std::string fullStr() const {
std::ostringstream o;
o << str;
for (const auto& [mode, param] : params) {
o << ' ' << param;
}
return o.str();
}
template<bool channelModes>
void parse(std::string_view str, NetworkInfo& netInfo);
};
@ -96,6 +105,13 @@ struct Channel {
.text = std::string(topic)
};
}
Event get_tmode(const ModeSet& modes, const UUID& user) const {
return {
.sender = user,
.name = "TMODE",
.raw_args = fmt::format("{} {} {}", time(nullptr), name, modes.fullStr())
};
}
};
struct User {

101
services/chanserv.cpp Normal file
View file

@ -0,0 +1,101 @@
/*
* 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 <https://www.gnu.org/licenses/>.
*/
#include "chanserv.hpp"
#include "../instance.hpp"
#include <async/result.hpp>
#include <fmt/format.h>
#include <string>
#include <string_view>
#include <vector>
#include <memory>
using fmt::operator""_format;
async::result<void> ChanServ::intitialize() {
co_await i->netInfo.wait_ready();
user = {
.server = i->config.server.uid,
.nick = std::string(getConfig("ChanServ", "nickname").value_or("ChanServ")),
.realhost = i->config.server.name,
.uid = uuid,
.realname = i->netInfo.name
};
co_await mark_ready(user);
using namespace sqlite_orm;
storage = std::make_unique<Storage>(make_storage(
std::string(getConfig("ChanServ", "database").value_or("chanserv.sqlite")),
make_table("users",
make_column("id", &ChannelReg::id, autoincrement(), primary_key()),
make_column("name", &ChannelReg::name),
make_column("owner", &ChannelReg::owner))
));
storage->sync_schema();
commands = {
{"register", {[this] (u_User& sender, std::vector<std::string_view> args) -> async::result<void> {
// Get channel
u_Channel *channel;
{
auto res = i->cache.find_channel_by_name(args[0]);
if (res == i->cache.channels.end()) {
co_await i->send_event(user.get_notice("Error: {} does not exist!"_format(args[0]), sender->uid));
co_return;
}
channel = &*res;
}
// Check if user is operator in the channel
// TODO
// Check that account does not exist already
{
auto channelregs_found = storage->get_all<ChannelReg>(where(c(&ChannelReg::name) == std::string(args[0])));
if (!channelregs_found.empty()) {
co_await i->send_event(user.get_notice("Error: {} has already been registered!"_format(sender->nick), sender->uid));
co_return;
}
}
// Append it to database
ChannelReg reg = {
.name = std::string(args[0]),
.owner = sender->nick
};
storage->insert(reg);
// Report success
co_await i->send_event(user.get_notice("{} has been registered!"_format(args[0]), sender->uid));
// Initialize channel
co_await initializeChannel(channel, reg);
}, "<channel>", 1, true}
},
};
}
async::result<void> ChanServ::initializeChannel(u_Channel *channel, const ChannelReg& channelReg) {
// We need to loop twice because co_await'ing inside a loop through a non-local dynamically-sized container is DANGEROUS
std::vector<u_User*> to_mark_as_admin;
for (const auto member : channel->get()->members) {
if (member->get()->loginName.value_or("") == channelReg.owner) {
to_mark_as_admin.push_back(member);
}
}
for (const auto member : to_mark_as_admin) {
co_await i->send_event(channel->get()->get_tmode({"o", {std::tuple<char, std::string>{'o', member->get()->uid.str()}}}, member->get()->uid));
}
}

45
services/chanserv.hpp Normal file
View file

@ -0,0 +1,45 @@
/*
* 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 <https://www.gnu.org/licenses/>.
*/
#ifndef _TEST_HPP
#define _TEST_HPP
#include "../instance.hpp"
#include "../serviceBase.hpp"
#include <async/result.hpp>
#include <string>
#include <memory>
#include "sqlite_orm.h"
struct ChannelReg {
int id = -1;
std::string name, owner;
};
using Storage = sqlite_orm::internal::storage_t<sqlite_orm::internal::table_t<ChannelReg, sqlite_orm::internal::column_t<ChannelReg, int, const int& (ChannelReg::*)() const, void (ChannelReg::*)(int), sqlite_orm::constraints::autoincrement_t, sqlite_orm::constraints::primary_key_t<> >, sqlite_orm::internal::column_t<ChannelReg, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, const std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >& (ChannelReg::*)() const, void (ChannelReg::*)(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >)>, sqlite_orm::internal::column_t<ChannelReg, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, const std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >& (ChannelReg::*)() const, void (ChannelReg::*)(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >)> > >;
class ChanServ : public ServiceBase {
std::unique_ptr<Storage> storage;
User user;
virtual async::result<void> intitialize() override;
async::result<void> initializeChannel(u_Channel *channel, const ChannelReg& channelReg);
};
#endif

View file

@ -19,6 +19,7 @@
#include "../instance.hpp"
#include <async/result.hpp>
#include <fmt/format.h>
#include <cryptopp/hex.h>
#include <cryptopp/sha.h>
#include <cryptopp/pwdbased.h>
@ -27,6 +28,8 @@
#include <vector>
#include <memory>
using fmt::operator""_format;
async::result<void> NickServ::intitialize() {
@ -70,7 +73,7 @@ async::result<void> NickServ::intitialize() {
// Get account from storage
auto accounts_found = storage->get_all<Account>(where(c(&Account::name) == std::string(accountName)));
if (accounts_found.empty()) {
co_await i->send_event(user.get_notice("Error: '"+std::string(accountName)+"' is not registered!", sender->uid));
co_await i->send_event(user.get_notice("Error: {} is not registered!"_format(accountName), sender->uid));
co_return;
}
auto& account = accounts_found[0];
@ -96,11 +99,11 @@ async::result<void> NickServ::intitialize() {
co_await i->send_event(user.get_notice("Error: Passwords may not contain spaces!", sender->uid));
co_return;
}
// Check that user does not exist already
// Check that account does not exist already
{
auto accounts_found = storage->get_all<Account>(where(c(&Account::name) == sender->nick));
if (!accounts_found.empty()) {
co_await i->send_event(user.get_notice("Error: This nick has already been registered!", sender->uid));
co_await i->send_event(user.get_notice("Error: {} has already been registered!"_format(sender->nick), sender->uid));
co_return;
}
}
@ -111,7 +114,7 @@ async::result<void> NickServ::intitialize() {
.password_hash = pwdHash(args[0])
});
// Report success
co_await i->send_event(user.get_notice("Your nickname has been registered!", sender->uid));
co_await i->send_event(user.get_notice("{} has been registered!"_format(sender->nick), sender->uid));
}, "<password> <email>", 2, false}
},
};

View file

@ -20,11 +20,10 @@
#include "../instance.hpp"
#include "../serviceBase.hpp"
#include "sqlite_orm.h"
#include <async/result.hpp>
#include <string>
#include <memory>
#include "sqlite_orm.h"
@ -37,7 +36,6 @@ using Storage = sqlite_orm::internal::storage_t<sqlite_orm::internal::table_t<Ac
class NickServ : public ServiceBase {
std::unique_ptr<Storage> storage;
User user;
virtual async::result<void> intitialize() override;