summaryrefslogtreecommitdiff
path: root/bot/src/commands
diff options
context:
space:
mode:
authorilotterytea <iltsu@alright.party>2025-04-06 17:28:47 +0400
committerilotterytea <iltsu@alright.party>2025-04-06 17:28:47 +0400
commit2a49844a95593ac98e919c18651320e62f276fa7 (patch)
tree01b7e2ebb1dc7a9ac92e7c3105edfd098271f29a /bot/src/commands
parenta1a36cf4d4999b5ce89dce95364c9fd839b54b5d (diff)
feat: implementing lua coding
Diffstat (limited to 'bot/src/commands')
-rw-r--r--bot/src/commands/command.cpp30
-rw-r--r--bot/src/commands/command.hpp5
-rw-r--r--bot/src/commands/lua.cpp68
-rw-r--r--bot/src/commands/lua.hpp45
-rw-r--r--bot/src/commands/request.cpp28
-rw-r--r--bot/src/commands/request.hpp5
6 files changed, 181 insertions, 0 deletions
diff --git a/bot/src/commands/command.cpp b/bot/src/commands/command.cpp
index bd33c68..97dd88b 100644
--- a/bot/src/commands/command.cpp
+++ b/bot/src/commands/command.cpp
@@ -3,9 +3,13 @@
#include <algorithm>
#include <chrono>
#include <ctime>
+#include <fstream>
#include <memory>
#include <optional>
#include <pqxx/pqxx>
+#include <sol/state.hpp>
+#include <sol/types.hpp>
+#include <stdexcept>
#include <string>
#include "../bundle.hpp"
@@ -23,6 +27,8 @@
#include "../modules/timer.hpp"
#include "../modules/user.hpp"
#include "../utils/chrono.hpp"
+#include "commands/lua.hpp"
+#include "logger.hpp"
#include "request.hpp"
#include "response.hpp"
@@ -42,6 +48,30 @@ namespace bot {
this->add_command(std::make_unique<mod::Settings>());
this->add_command(std::make_unique<mod::User>());
this->add_command(std::make_unique<mod::MinecraftServerCheck>());
+
+ this->luaState = std::make_shared<sol::state>();
+ this->luaState->open_libraries(sol::lib::base, sol::lib::string);
+ }
+
+ void CommandLoader::load_lua_directory(const std::string &folder_path) {
+ for (const auto &entry :
+ std::filesystem::directory_iterator(folder_path)) {
+ std::ifstream ifs(entry.path());
+ if (!ifs.is_open()) {
+ throw new std::runtime_error("Failed to open the Lua file at " +
+ entry.path().string());
+ }
+ std::string content, line;
+
+ while (std::getline(ifs, line)) {
+ content += line + '\n';
+ }
+
+ ifs.close();
+
+ this->add_command(
+ std::make_unique<lua::LuaCommand>(this->luaState, content));
+ }
}
void CommandLoader::add_command(std::unique_ptr<Command> command) {
diff --git a/bot/src/commands/command.hpp b/bot/src/commands/command.hpp
index 793446e..c2398ec 100644
--- a/bot/src/commands/command.hpp
+++ b/bot/src/commands/command.hpp
@@ -2,6 +2,8 @@
#include <memory>
#include <optional>
+#include <sol/sol.hpp>
+#include <sol/state.hpp>
#include <string>
#include <vector>
@@ -41,6 +43,7 @@ namespace bot {
~CommandLoader() = default;
void add_command(std::unique_ptr<Command> cmd);
+ void load_lua_directory(const std::string &folder_path);
std::optional<Response> run(const InstanceBundle &bundle,
const Request &msg) const;
@@ -50,6 +53,8 @@ namespace bot {
private:
std::vector<std::unique_ptr<Command>> commands;
+
+ std::shared_ptr<sol::state> luaState;
};
}
}
diff --git a/bot/src/commands/lua.cpp b/bot/src/commands/lua.cpp
new file mode 100644
index 0000000..cd7bc84
--- /dev/null
+++ b/bot/src/commands/lua.cpp
@@ -0,0 +1,68 @@
+#include "commands/lua.hpp"
+
+#include <sol/table.hpp>
+#include <string>
+
+#include "bundle.hpp"
+#include "commands/request.hpp"
+#include "commands/response.hpp"
+#include "schemas/user.hpp"
+
+namespace bot::command::lua {
+ LuaCommand::LuaCommand(std::shared_ptr<sol::state> luaState,
+ const std::string &script) {
+ this->luaState = luaState;
+
+ sol::table data = luaState->script(script);
+ this->name = data["name"];
+ this->delay = data["delay_sec"];
+
+ sol::table subcommands = data["subcommands"];
+ for (auto &k : subcommands) {
+ sol::object value = k.second;
+ if (value.is<std::string>()) {
+ this->subcommands.push_back(value.as<std::string>());
+ }
+ }
+
+ std::string rights_text = data["minimal_rights"];
+ if (rights_text == "suspended") {
+ this->level = schemas::PermissionLevel::SUSPENDED;
+ } else if (rights_text == "user") {
+ this->level = schemas::PermissionLevel::USER;
+ } else if (rights_text == "vip") {
+ this->level = schemas::PermissionLevel::VIP;
+ } else if (rights_text == "moderator") {
+ this->level = schemas::PermissionLevel::MODERATOR;
+ } else if (rights_text == "broadcaster") {
+ this->level = schemas::PermissionLevel::BROADCASTER;
+ } else {
+ this->level = schemas::PermissionLevel::USER;
+ }
+
+ this->handle = data["run"];
+ }
+
+ Response LuaCommand::run(const InstanceBundle &bundle,
+ const Request &request) const {
+ sol::object response = this->handle(request.as_lua_table(this->luaState));
+
+ if (response.is<std::string>()) {
+ return {response.as<std::string>()};
+ } else if (response.is<sol::table>()) {
+ sol::table tbl = response.as<sol::table>();
+ std::vector<std::string> items;
+
+ for (auto &kv : tbl) {
+ sol::object value = kv.second;
+ if (value.is<std::string>()) {
+ items.push_back(value.as<std::string>());
+ }
+ }
+
+ return items;
+ }
+
+ return {};
+ }
+} \ No newline at end of file
diff --git a/bot/src/commands/lua.hpp b/bot/src/commands/lua.hpp
new file mode 100644
index 0000000..11e98d3
--- /dev/null
+++ b/bot/src/commands/lua.hpp
@@ -0,0 +1,45 @@
+#pragma once
+
+#include <sol/sol.hpp>
+#include <sol/state.hpp>
+#include <sol/table.hpp>
+#include <sol/types.hpp>
+#include <string>
+#include <vector>
+
+#include "commands/command.hpp"
+#include "commands/response.hpp"
+#include "schemas/user.hpp"
+
+void print_lua_object_type(const sol::object &obj);
+
+namespace bot::command::lua {
+ class LuaCommand : public Command {
+ public:
+ LuaCommand(std::shared_ptr<sol::state> luaState,
+ const std::string &content);
+ ~LuaCommand() = default;
+
+ Response run(const InstanceBundle &bundle,
+ const Request &request) const override;
+
+ std::string get_name() const override { return this->name; }
+ int get_delay_seconds() const override { return this->delay; }
+ schemas::PermissionLevel get_permission_level() const override {
+ return this->level;
+ }
+ std::vector<std::string> get_subcommand_ids() const override {
+ return this->subcommands;
+ }
+
+ private:
+ std::string name;
+ int delay;
+ schemas::PermissionLevel level;
+ std::vector<std::string> subcommands;
+
+ sol::function handle;
+
+ std::shared_ptr<sol::state> luaState;
+ };
+} \ No newline at end of file
diff --git a/bot/src/commands/request.cpp b/bot/src/commands/request.cpp
new file mode 100644
index 0000000..7acc107
--- /dev/null
+++ b/bot/src/commands/request.cpp
@@ -0,0 +1,28 @@
+#include "commands/request.hpp"
+
+#include <sol/types.hpp>
+
+namespace bot::command {
+ sol::table Request::as_lua_table(std::shared_ptr<sol::state> luaState) const {
+ sol::table o = luaState->create_table();
+
+ o["command_id"] = this->command_id;
+ if (this->subcommand_id.has_value()) {
+ o["subcommand_id"] = this->subcommand_id.value();
+ } else {
+ o["subcommand_id"] = sol::lua_nil;
+ }
+ if (this->message.has_value()) {
+ o["message"] = this->message.value();
+ } else {
+ o["message"] = sol::lua_nil;
+ }
+
+ o["sender"] = this->user.as_lua_table(luaState);
+ o["channel"] = this->channel.as_lua_table(luaState);
+ o["channel_preference"] = this->channel_preferences.as_lua_table(luaState);
+ o["rights"] = this->user_rights.as_lua_table(luaState);
+
+ return o;
+ }
+} \ No newline at end of file
diff --git a/bot/src/commands/request.hpp b/bot/src/commands/request.hpp
index e2685f1..b6ed534 100644
--- a/bot/src/commands/request.hpp
+++ b/bot/src/commands/request.hpp
@@ -1,7 +1,10 @@
#pragma once
+#include <memory>
#include <optional>
#include <pqxx/pqxx>
+#include <sol/state.hpp>
+#include <sol/table.hpp>
#include <string>
#include "../irc/message.hpp"
@@ -21,5 +24,7 @@ namespace bot::command {
schemas::UserRights user_rights;
pqxx::connection &conn;
+
+ sol::table as_lua_table(std::shared_ptr<sol::state> luaState) const;
};
}