From 4206dd79626773b3f667e9af0ca007aa35a7c6f3 Mon Sep 17 00:00:00 2001 From: ilotterytea Date: Wed, 2 Jul 2025 15:24:16 +0500 Subject: feat: lua storage --- bot/src/commands/lua.cpp | 116 ++++++++++++++++++++- bot/src/commands/lua.hpp | 9 +- migrations/2025-07-02T10-01-06_luastorage/down.sql | 3 + migrations/2025-07-02T10-01-06_luastorage/up.sql | 18 ++++ 4 files changed, 143 insertions(+), 3 deletions(-) create mode 100644 migrations/2025-07-02T10-01-06_luastorage/down.sql create mode 100644 migrations/2025-07-02T10-01-06_luastorage/up.sql diff --git a/bot/src/commands/lua.cpp b/bot/src/commands/lua.cpp index 2c1b176..a67bd17 100644 --- a/bot/src/commands/lua.cpp +++ b/bot/src/commands/lua.cpp @@ -728,6 +728,114 @@ namespace bot::command::lua { return o; }); } + + void add_storage_library(std::shared_ptr state, + const Request &request, const Configuration &cfg, + const std::string &lua_id) { + state->set_function("storage_get", [state, &request, &cfg, &lua_id]() { + std::unique_ptr conn = db::create_connection(cfg); + std::vector params{std::to_string(request.user.get_id()), + lua_id}; + + db::DatabaseRows rows = conn->exec( + "SELECT value FROM lua_user_storage WHERE user_id = $1 AND " + "lua_id = $2", + params); + + std::string value = ""; + + if (rows.empty()) { + conn->exec( + "INSERT INTO lua_user_storage(user_id, lua_id) VALUES ($1, " + "$2)", + params); + } else { + value = rows[0].at("value"); + } + + return value; + }); + + state->set_function("storage_put", [state, &request, &cfg, + &lua_id](const std::string &value) { + std::unique_ptr conn = db::create_connection(cfg); + std::vector params{std::to_string(request.user.get_id()), + lua_id}; + + db::DatabaseRows rows = conn->exec( + "SELECT id FROM lua_user_storage WHERE user_id = $1 AND " + "lua_id = $2", + params); + + if (rows.empty()) { + params.push_back(value); + conn->exec( + "INSERT INTO lua_user_storage(user_id, lua_id, value) VALUES " + "($1, " + "$2, $3)", + params); + } else { + conn->exec("UPDATE lua_user_storage SET value = $1 WHERE id = $2", + {value, rows[0].at("id")}); + } + + return true; + }); + + state->set_function("storage_channel_get", [state, &request, &cfg, + &lua_id]() { + std::unique_ptr conn = db::create_connection(cfg); + std::vector params{ + std::to_string(request.channel.get_id()), lua_id}; + + db::DatabaseRows rows = conn->exec( + "SELECT value FROM lua_channel_storage WHERE channel_id = $1 AND " + "lua_id = $2", + params); + + std::string value = ""; + + if (rows.empty()) { + conn->exec( + "INSERT INTO lua_channel_storage(channel_id, lua_id) VALUES ($1, " + "$2)", + params); + } else { + value = rows[0].at("value"); + } + + return value; + }); + + state->set_function( + "storage_channel_put", + [state, &request, &cfg, &lua_id](const std::string &value) { + std::unique_ptr conn = db::create_connection(cfg); + std::vector params{ + std::to_string(request.channel.get_id()), lua_id}; + + db::DatabaseRows rows = conn->exec( + "SELECT id FROM lua_channel_storage WHERE channel_id = $1 AND " + "lua_id = $2", + params); + + if (rows.empty()) { + params.push_back(value); + conn->exec( + "INSERT INTO lua_channel_storage(channel_id, lua_id, value) " + "VALUES " + "($1, " + "$2, $3)", + params); + } else { + conn->exec( + "UPDATE lua_channel_storage SET value = $1 WHERE id = $2", + {value, rows[0].at("id")}); + } + + return true; + }); + } } Response parse_lua_response(const sol::table &r, sol::object &res, @@ -761,13 +869,19 @@ namespace bot::command::lua { command::Response run_safe_lua_script(const Request &request, const InstanceBundle &bundle, - const std::string &script) { + const std::string &script, + std::string lua_id) { // shared_ptr is unnecessary here, but my library needs it. std::shared_ptr state = std::make_shared(); state->open_libraries(sol::lib::base, sol::lib::table, sol::lib::string); library::add_base_libraries(state); + if (!lua_id.empty()) { + library::add_storage_library(state, request, bundle.configuration, + lua_id); + } + sol::load_result s = state->load("return " + script); if (!s.valid()) { s = state->load(script); diff --git a/bot/src/commands/lua.hpp b/bot/src/commands/lua.hpp index bde317b..422f79e 100644 --- a/bot/src/commands/lua.hpp +++ b/bot/src/commands/lua.hpp @@ -37,6 +37,9 @@ namespace bot::command::lua { const InstanceBundle &bundle); void add_l10n_library(std::shared_ptr state, const InstanceBundle &bundle); + void add_storage_library(std::shared_ptr state, + const Request &request, const Configuration &cfg, + const std::string &lua_id); void add_base_libraries(std::shared_ptr state); void add_chat_libraries(std::shared_ptr state, @@ -46,7 +49,8 @@ namespace bot::command::lua { command::Response run_safe_lua_script(const Request &request, const InstanceBundle &bundle, - const std::string &script); + const std::string &script, + std::string lua_id = ""); class LuaCommand : public Command { public: @@ -133,7 +137,8 @@ namespace bot::command::lua { std::string script = response.text; - return command::lua::run_safe_lua_script(request, bundle, script); + return command::lua::run_safe_lua_script(request, bundle, script, + url); } }; } diff --git a/migrations/2025-07-02T10-01-06_luastorage/down.sql b/migrations/2025-07-02T10-01-06_luastorage/down.sql new file mode 100644 index 0000000..4711155 --- /dev/null +++ b/migrations/2025-07-02T10-01-06_luastorage/down.sql @@ -0,0 +1,3 @@ +-- This file should undo anything in 'up.sql' +DROP TABLE lua_user_storage; +DROP TABLE lua_channel_storage; \ No newline at end of file diff --git a/migrations/2025-07-02T10-01-06_luastorage/up.sql b/migrations/2025-07-02T10-01-06_luastorage/up.sql new file mode 100644 index 0000000..dd61116 --- /dev/null +++ b/migrations/2025-07-02T10-01-06_luastorage/up.sql @@ -0,0 +1,18 @@ +-- Your SQL goes here +CREATE TABLE IF NOT EXISTS lua_channel_storage( + id INTEGER NOT NULL PRIMARY KEY AUTO_INCREMENT, + channel_id INTEGER NOT NULL REFERENCES channels(id) ON DELETE CASCADE, + lua_id TEXT NOT NULL, + value TEXT NOT NULL DEFAULT '', + + CONSTRAINT unique_lua_script_per_channel UNIQUE (channel_id, lua_id) +); + +CREATE TABLE IF NOT EXISTS lua_user_storage( + id INTEGER NOT NULL PRIMARY KEY AUTO_INCREMENT, + user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE, + lua_id TEXT NOT NULL, + value TEXT NOT NULL DEFAULT '', + + CONSTRAINT unique_lua_script_per_channel UNIQUE (user_id, lua_id) +); \ No newline at end of file -- cgit v1.2.3