#ifndef _BOT_HPP #define _BOT_HPP #include #include #include #include #include #include #include #include "sqlite_modern_cpp/sqlite_modern_cpp.h" #define BOT_ADD_MODULE(name) class StaticModuleRegistration##name { \ std::unordered_map 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> on_init, on_deinit; public: template struct Interaction { std::vector names; std::string description; dpp::slashcommand misc; using Callback = std::function; Callback callback; Interaction(const std::vector& names, const std::string& description) : names(names), description(description) {} Interaction(const std::vector& 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; using UserCommand = Interaction; using MessageCommand = Interaction; private: bool inited = false; std::unordered_map loaded_modules; struct Commands { std::vector chat_commands; std::vector user_commands; std::vector message_commands; std::vector> guild_chat_commands; std::vector> guild_user_commands; std::vector> 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 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> properties; Bot(const std::string& token, const std::string& database = "db.sqlite3"); ~Bot(); void start(); static inline void add_on_init(const std::function& cb) {on_init.push_back(cb);} static inline void add_on_deinit(const std::function& cb) {on_deinit.push_back(cb);} void add_module(const std::string& name) {config.modules.push_back(name);} template void add_loaded_module(std::string_view name, T *instance) {loaded_modules[name] = reinterpret_cast(instance);} template T *get_loaded_module(std::string_view name) const {return reinterpret_cast(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 void add_property(std::string_view name, T *value, std::mutex& mutex) {properties[name] = std::pair{value, &mutex};} template std::pair>> get_locked_property(std::string_view name) {auto prop = properties.at(name); return {reinterpret_cast(prop.first), std::make_unique>(*prop.second)};} }; #endif // _BOT_HPP