diff options
-rw-r--r-- | CMakeLists.txt | 6 | ||||
-rw-r--r-- | include/142bot/bot.hpp | 7 | ||||
-rw-r--r-- | include/142bot/db.hpp | 37 | ||||
-rw-r--r-- | migrations/0001-init.sql | 7 | ||||
-rw-r--r-- | src/bot.cpp | 51 | ||||
-rw-r--r-- | src/db.cpp | 76 | ||||
-rw-r--r-- | src/main.cpp | 2 |
7 files changed, 182 insertions, 4 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 5ac2947..f26e300 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -33,12 +33,16 @@ find_package(fmt) string(ASCII 27 Esc) +find_library(PQXX_LIB pqxx) +find_library(PQ_LIB pq) + include(GNUInstallDirs) aux_source_directory("src" coresrc) add_executable(142bot ${coresrc}) include_directories("include") -target_link_libraries(142bot PRIVATE clog dpp fmt::fmt spdlog::spdlog pcre cpr::cpr) +target_link_libraries(142bot PRIVATE clog dpp fmt::fmt spdlog::spdlog pcre + cpr::cpr ${PQXX_LIB} ${PQ_LIB}) add_dependencies(142bot clog dpp cpr fmt spdlog) install(TARGETS 142bot) diff --git a/include/142bot/bot.hpp b/include/142bot/bot.hpp index 49aa956..a422416 100644 --- a/include/142bot/bot.hpp +++ b/include/142bot/bot.hpp @@ -1,6 +1,7 @@ #include <dpp/snowflake.h> #include <dpp/user.h> #include <dpp/dpp.h> +#include <pqxx/pqxx> #ifndef BOT_HPP @@ -8,9 +9,11 @@ class Module; class ModuleLoader; class Bot { + pqxx::connection conn; bool dev; dpp::snowflake owner_id; - +private: + bool run_database_migrations(); public: class dpp::cluster * core; /* The bot's user from the ready event */ @@ -18,7 +21,7 @@ public: Bot(bool development, dpp::cluster* cluster); //virtual ~Bot(); - + void set_owner_id(dpp::snowflake id); dpp::snowflake get_owner_id(); diff --git a/include/142bot/db.hpp b/include/142bot/db.hpp new file mode 100644 index 0000000..69245d3 --- /dev/null +++ b/include/142bot/db.hpp @@ -0,0 +1,37 @@ +/* + * ===================================================================================== + * + * Filename: db.hpp + * + * Description: + * + * Version: 1.0 + * Created: 04/06/2023 11:38:35 AM + * Revision: none + * Compiler: gcc + * + * Author: Cara Salter (muirrum), cara@devcara.com + * Organization: Worcester Polytechnic Institute + * + * ===================================================================================== + */ + +#pragma once +#include <vector> +#include <map> +#include <string> +#include <variant> +#include <pqxx/pqxx> + + +namespace db { + typedef std::map<std::string, std::string> row; + typedef std::vector<row> resultset; + + typedef std::vector<std::variant<float, std::string, uint64_t, int64_t, bool, int32_t, uint32_t, double>> paramlist; + + pqxx::connection connect(const std::string &host, const std::string &user, const std::string &pass, const std::string &db, int port); + bool close(); + resultset query(const std::string &format, const paramlist ¶meters); + const std::string& error(); +} diff --git a/migrations/0001-init.sql b/migrations/0001-init.sql new file mode 100644 index 0000000..7a00ff0 --- /dev/null +++ b/migrations/0001-init.sql @@ -0,0 +1,7 @@ +CREATE TABLE IF NOT EXISTS spotify ( + id SERIAL PRIMARY KEY, + spotify_username TEXT NOT NULL, + spotify_token TEXT NOT NULL, + spotify_token_expires TIMESTAMP NOT NULL, + spotify_refresh_token TEXT NOT NULL +);
\ No newline at end of file diff --git a/src/bot.cpp b/src/bot.cpp index 03bea02..ad818a0 100644 --- a/src/bot.cpp +++ b/src/bot.cpp @@ -1,21 +1,72 @@ #include <dpp/snowflake.h> #include <stdlib.h> +#include <string> #include <142bot/bot.hpp> #include <dpp/dpp.h> #include <142bot/modules.hpp> #include <142bot/util.hpp> #include <fmt/format.h> #include <fmt/format-inl.h> +#include <pqxx/pqxx> +#include <142bot/db.hpp> +#include <filesystem> + +namespace fs = std::filesystem; Bot::Bot(bool devel, dpp::cluster* cluster) { dev = devel; this->core = cluster; + + std::ifstream f("config.json"); + json cfg = json::parse(f); + std::string token = cfg.value("token", "bad-token"); + + this->conn = db::connect(cfg["postgres"]["host"], cfg["postgres"]["user"], cfg["postgres"]["pass"], cfg["postgres"]["database"], cfg["postgres"]["port"]); + + run_database_migrations(); + this->loader = new ModuleLoader(this); this->loader->load_all(); // this->loader->LoadAll(); } +/** + * Attempts to run migrations stored in a directory local to CWD. + * + * Returns false on any error +*/ +bool Bot::run_database_migrations() { + + // Start a transaction + this->core->log(dpp::ll_info, "Attempting database migrations..."); + pqxx::work w(this->conn); + // Get all files in ./migrations + std::string path = "./migrations"; + for (const auto &entry : fs::directory_iterator(path)) { + std::ifstream f(entry.path()); + std::ostringstream sstr; + sstr << f.rdbuf(); + std::string stmt = sstr.str(); + + this->core->log(dpp::ll_debug, fmt::format("Attempting to migrate database with statement {}", stmt)); + + try { + w.exec0(stmt); + } catch (std::exception &e) { + w.abort(); + this->core->log(dpp::ll_error, e.what()); + return false; + } + + } + + w.commit(); + this->core->log(dpp::ll_info, "Done."); + + return true; +} + bool Bot::isDevMode() { return dev; } diff --git a/src/db.cpp b/src/db.cpp new file mode 100644 index 0000000..92e3d1d --- /dev/null +++ b/src/db.cpp @@ -0,0 +1,76 @@ +/* + * ===================================================================================== + * + * Filename: db.cpp + * + * Description: Connection to a postgres database + * + * Version: 1.0 + * Created: 04/06/2023 11:40:39 AM + * Revision: none + * Compiler: gcc + * + * Author: Cara Salter (muirrum), cara@devcara.com + * Organization: Worcester Polytechnic Institute + * + * ===================================================================================== + */ +#include <fmt/core.h> +#include <mutex> +#include <stdlib.h> +#include <stdio.h> +#include <iostream> +#include <142bot/db.hpp> +#include <pqxx/pqxx> +#include <fmt/format.h> +#include <cstdarg> + +using namespace std; + +namespace db { + std::mutex db_mutex; + std::string _error; + + /** + * Connects to a postgres database, returns false if error + **/ + pqxx::connection connect(const std::string &host, const std::string &user, const std::string &pass, const std::string &db, int port) { + std::lock_guard<std::mutex> db_lock(db_mutex); + + std::string cn_s = "postgresql://"; + + if (!user.empty()) { + cn_s = cn_s + user; + } + if (!pass.empty() && !user.empty()) { + cn_s = cn_s + ":" + pass; + } + + if ((!user.empty() || !pass.empty())) { + cn_s = cn_s + "@"; + } + + if (!host.empty()) { + cn_s = cn_s + "localhost"; + } + if (port != 0 && !host.empty()) { + cn_s = cn_s + ":" + std::to_string(port); + } + if (!db.empty()) { + cn_s = cn_s + "/" + db; + } + + try { + pqxx::connection c{cn_s}; + return c; + } catch (std::exception const &e) { + _error = e.what(); + throw e; + } + } + + const std::string& error() { + return _error; + } + +} diff --git a/src/main.cpp b/src/main.cpp index 8f3ad9a..f54e418 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,6 +1,7 @@ #include <dpp/dpp.h> #include <dpp/json.h> #include <142bot/bot.hpp> +#include <142bot/db.hpp> #include <spdlog/spdlog.h> #include <spdlog/async.h> @@ -17,7 +18,6 @@ int main(int argc, char const *argv[]) { std::ifstream f("config.json"); json cfg = json::parse(f); string token = cfg.value("token", "bad-token"); - dpp::cluster bot(token, dpp::intents::i_all_intents); std::shared_ptr<spdlog::logger> log; |