#include "command.hpp" #include #include #include #include #include #include #include #include #include #include #include #include "../bundle.hpp" #include "../modules/notify.hpp" #include "../modules/timer.hpp" #include "../utils/chrono.hpp" #include "commands/lua.hpp" #include "modules/lua.hpp" #include "request.hpp" #include "response.hpp" namespace bot { namespace command { CommandLoader::CommandLoader() { this->add_command(std::make_unique()); this->add_command(std::make_unique()); this->add_command(std::make_unique()); this->add_command(std::make_unique()); this->luaState = std::make_shared(); this->luaState->open_libraries(sol::lib::base, sol::lib::string, sol::lib::table, sol::lib::math); lua::library::add_base_libraries(this->luaState); } void CommandLoader::load_lua_directory(const std::string &folder_path) { for (const auto &entry : std::filesystem::directory_iterator(folder_path)) { load_lua_file(entry.path()); } } void CommandLoader::load_lua_file(const std::string &file_path) { std::ifstream ifs(file_path); if (!ifs.is_open()) { throw new std::runtime_error("Failed to open the Lua file at " + file_path); } std::string content, line; while (std::getline(ifs, line)) { content += line + '\n'; } ifs.close(); this->add_command( std::make_unique(this->luaState, content)); } void CommandLoader::add_command(std::unique_ptr command) { auto it = std::find_if(this->commands.begin(), this->commands.end(), [&command](const auto &x) { return command->get_name() == x->get_name(); }); if (it != this->commands.end()) { this->commands.erase(it); } this->commands.push_back(std::move(command)); } std::optional CommandLoader::run(const InstanceBundle &bundle, const Request &request) { lua::library::add_chat_libraries(this->luaState, request, bundle); auto command = std::find_if( this->commands.begin(), this->commands.end(), [&](const auto &x) { return x->get_name() == request.command_id; }); if (command == this->commands.end()) { return std::nullopt; } if ((*command)->get_permission_level() > request.user_rights.get_level()) { return std::nullopt; } pqxx::work work(request.conn); pqxx::result action_query = work.exec( "SELECT sent_at FROM actions WHERE user_id = " + std::to_string(request.user.get_id()) + " AND channel_id = " + std::to_string(request.channel.get_id()) + " AND command = '" + request.command_id + "' ORDER BY sent_at DESC"); if (!action_query.empty()) { auto last_sent_at = utils::chrono::string_to_time_point( action_query[0][0].as()); auto now = std::chrono::system_clock::now(); auto now_time_it = std::chrono::system_clock::to_time_t(now); auto now_tm = std::gmtime(&now_time_it); now = std::chrono::system_clock::from_time_t(std::mktime(now_tm)); auto difference = std::chrono::duration_cast( now - last_sent_at); if (difference.count() < command->get()->get_delay_seconds()) { return std::nullopt; } } std::string arguments; if (request.subcommand_id.has_value()) { arguments += request.subcommand_id.value() + " "; } if (request.message.has_value()) { arguments += request.message.value(); } work.exec( "INSERT INTO actions(user_id, channel_id, command, arguments, " "full_message) VALUES (" + std::to_string(request.user.get_id()) + ", " + std::to_string(request.channel.get_id()) + ", '" + request.command_id + "', '" + arguments + "', '" + request.irc_message.message + "')"); work.commit(); return (*command)->run(bundle, request); } } }