1
0
Fork 0
mirror of https://gitlab.com/niansa/SomeBot.git synced 2025-03-06 20:48:26 +01:00
SomeBot/bot.hpp
2022-11-01 15:11:17 +01:00

127 lines
5.1 KiB
C++

#ifndef _BOT_HPP
#define _BOT_HPP
#include <string>
#include <string_view>
#include <functional>
#include <mutex>
#include <memory>
#include <dpp/dpp.h>
#include <dpp/cluster.h>
#include "sqlite_modern_cpp/sqlite_modern_cpp.h"
#define BOT_ADD_MODULE(name) class StaticModuleRegistration##name { \
std::unordered_map<Bot*, name*> instances; \
\
public: \
StaticModuleRegistration##name() { \
Bot::add_on_init([this](Bot *bot) { \
if (bot->is_module_enabled(#name)) bot->add_loaded_module(#name, instances[bot] = new name(bot)); \
}); \
Bot::add_on_deinit([this](Bot *bot) { \
if (bot->is_module_enabled(#name)) delete instances[bot]; \
}); \
} \
} static static_module_registration
class Bot {
static std::vector<std::function<void (Bot *)>> on_init,
on_deinit;
public:
template<class interactionCallbackDataT>
struct Interaction {
std::vector<std::string> names;
std::string description;
dpp::slashcommand misc;
using Callback = std::function<void (const interactionCallbackDataT& i)>;
Callback callback;
Interaction(const std::vector<std::string>& names, const std::string& description)
: names(names), description(description) {}
Interaction(const std::vector<std::string>& names, const std::string& description, const dpp::slashcommand& misc)
: names(names), description(description), misc(misc) {}
void operator()(const interactionCallbackDataT& i) const {
callback(i);
}
bool operator==(const dpp::interaction& i) const {
for (const auto& name : names) {
if (name == i.get_command_name()) {
return true;
}
}
return false;
}
};
using ChatCommand = Interaction<dpp::slashcommand_t>;
using UserCommand = Interaction<dpp::user_context_menu_t>;
using MessageCommand = Interaction<dpp::message_context_menu_t>;
private:
bool inited = false;
std::unordered_map<std::string_view, void*> loaded_modules;
struct Commands {
std::vector<ChatCommand> chat_commands;
std::vector<UserCommand> user_commands;
std::vector<MessageCommand> message_commands;
std::vector<std::pair<ChatCommand, dpp::snowflake>> guild_chat_commands;
std::vector<std::pair<UserCommand, dpp::snowflake>> guild_user_commands;
std::vector<std::pair<MessageCommand, dpp::snowflake>> guild_message_commands;
} commands;
public:
dpp::cluster cluster;
sqlite::database db;
struct Config {
std::string id;
dpp::snowflake owner_id = 123,
management_guild_id = 123;
bool _private = false;
bool reregister_commands = false;
std::vector<std::string> modules;
enum class ModulesMode {
whitelist,
blacklist
} modules_mode = ModulesMode::blacklist;
enum class CommandAliasMode {
all,
first,
last
} command_alias_mode = CommandAliasMode::all;
} config;
std::unordered_map<std::string_view, std::pair<void*, std::mutex*>> properties;
Bot(const std::string& token, const std::string& database = "db.sqlite3");
~Bot();
void start();
static inline void add_on_init(const std::function<void (Bot*)>& cb) {on_init.push_back(cb);}
static inline void add_on_deinit(const std::function<void (Bot*)>& cb) {on_deinit.push_back(cb);}
void add_module(const std::string& name) {config.modules.push_back(name);}
template<class T>
void add_loaded_module(std::string_view name, T *instance) {loaded_modules[name] = reinterpret_cast<void*>(instance);}
template<class T>
T *get_loaded_module(std::string_view name) const {return reinterpret_cast<T*>(loaded_modules.at(name));}
bool is_module_enabled(std::string_view name);
void add_chatcommand(ChatCommand command, const ChatCommand::Callback& cb, dpp::snowflake guild_id = 0);
void add_usercommand(UserCommand command, const UserCommand::Callback& cb, dpp::snowflake guild_id = 0);
void add_messagecommand(MessageCommand command, const MessageCommand::Callback& cb, dpp::snowflake guild_id = 0);
const Commands& get_commands() const {return commands;}
template<class T>
void add_property(std::string_view name, T *value, std::mutex& mutex) {properties[name] = std::pair<void*, std::mutex*>{value, &mutex};}
template<class T>
std::pair<T*, std::unique_ptr<std::scoped_lock<std::mutex>>> get_locked_property(std::string_view name) {auto prop = properties.at(name); return {reinterpret_cast<T*>(prop.first), std::make_unique<std::scoped_lock<std::mutex>>(*prop.second)};}
};
#endif // _BOT_HPP