added new database

This commit is contained in:
Lukas Forsberg 2025-11-16 17:03:18 +01:00
parent dd56a8d57e
commit d1c95d2b8b
10 changed files with 77 additions and 43 deletions

View File

@ -1,6 +1,8 @@
cmake_minimum_required(VERSION 3.10) cmake_minimum_required(VERSION 3.10)
project(CrowHTMX) project(CrowHTMX)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
set(TARGET_NAME lf-server-admin-panel ) set(TARGET_NAME lf-server-admin-panel )
set(CMAKE_CXX_STANDARD 23) set(CMAKE_CXX_STANDARD 23)
@ -31,6 +33,9 @@ foreach(file IN LISTS TEMPLATE_FILES)
configure_file("${file}" "${CMAKE_BINARY_DIR}/${rel_path}" COPYONLY) configure_file("${file}" "${CMAKE_BINARY_DIR}/${rel_path}" COPYONLY)
endforeach() endforeach()
add_compile_options(-Wno-deprecated-declarations)
add_compile_options(-Wno-deprecated-literal-operator)
# Use Crow from system include (installed via yay -S crow + asio) # Use Crow from system include (installed via yay -S crow + asio)
include_directories(/usr/include src src/htmx src/shadowrun src/database src/login) include_directories(/usr/include src src/htmx src/shadowrun src/database src/login)

View File

@ -12,6 +12,14 @@ Database::~Database() {
sqlite3_close(m_db); sqlite3_close(m_db);
} }
string Database::currentTime(){
auto now = std::chrono::system_clock::now();
std::time_t t = std::chrono::system_clock::to_time_t(now);
std::stringstream ss;
ss << std::put_time(std::gmtime(&t), "%Y-%m-%d %H:%M:%S");
return ss.str();
}
sqlite3_stmt* Database::prepareStmt(const string& sql){ sqlite3_stmt* Database::prepareStmt(const string& sql){
sqlite3_stmt* stmt = nullptr; sqlite3_stmt* stmt = nullptr;
if (sqlite3_prepare_v2(m_db, sql.c_str(), -1, &stmt, nullptr) != SQLITE_OK) { if (sqlite3_prepare_v2(m_db, sql.c_str(), -1, &stmt, nullptr) != SQLITE_OK) {

View File

@ -17,7 +17,7 @@ class Database {
typedef std::vector<std::variant<int64_t, std::string>> QueryData; typedef std::vector<std::variant<int64_t, std::string>> QueryData;
public: public:
static constexpr std::string dbFile = "app.db"; static constexpr std::string dbFile = "test.db";
Database(); Database();
~Database(); ~Database();
@ -30,6 +30,8 @@ public:
std::set<std::string> getStrSet(const std::string& sql); std::set<std::string> getStrSet(const std::string& sql);
static std::string currentTime();
template <typename T> template <typename T>
std::optional<T> getSqlData(sqlite3_stmt* stmt, int i) std::optional<T> getSqlData(sqlite3_stmt* stmt, int i)
{ {

View File

@ -7,7 +7,6 @@
#include <string> #include <string>
class HtmxObject { class HtmxObject {
public: public:

View File

@ -1,6 +1,6 @@
#include "login.hpp" #include "login.hpp"
#include "sodium.h" #include "sodium.h"
#include "database.hpp" #include "databasepool.h"
#include "utils.hpp" #include "utils.hpp"
#include <iostream> #include <iostream>
namespace login namespace login

View File

@ -1,7 +1,5 @@
#include <crow.h> #include <crow.h>
#include <cstdlib>
#include <string> #include <string>
#include <print>
#include <optional> #include <optional>
#include "json_settings.h" #include "json_settings.h"
#include "htmx_helper.h" #include "htmx_helper.h"

View File

@ -5,6 +5,7 @@
#include "ShadowrunDb.hpp" #include "ShadowrunDb.hpp"
#include "login.hpp" #include "login.hpp"
#include <format> #include <format>
#include <set>
#include <vector> #include <vector>
using namespace std; using namespace std;
@ -83,7 +84,7 @@ void initApi(crow::SimpleApp& app)
auto query = crow::query_string(req.url_params); auto query = crow::query_string(req.url_params);
std::string name = query.get("name") ? query.get("name") : ""; std::string name = query.get("name") ? query.get("name") : "";
auto data = getCharacterData(getKeyOfCharacter(name)); auto data = getCharacterDataMap(getKeyOfCharacter(name));
return crow::response{ShadowrunCharacterForm(data).htmx()}; return crow::response{ShadowrunCharacterForm(data).htmx()};
})); }));
@ -98,8 +99,8 @@ void initApi(crow::SimpleApp& app)
<< "<label>Character Name: " << "<label>Character Name: "
<< "<select name='name'>"; << "<select name='name'>";
for (const auto& name : characters) { for (const auto& character : characters) {
html << "<option value='" << name << "'>" << name << "</option>"; html << "<option value='" << character.name << "'>" << character.name << "</option>";
} }
html << "</select></label>" html << "</select></label>"

View File

@ -4,7 +4,7 @@
#include "htmx/HtmxObject.h" #include "htmx/HtmxObject.h"
#include <map> #include <map>
#include <string> #include <string>
#include <vector>
class ShadowrunCharacterForm : public HtmxObject { class ShadowrunCharacterForm : public HtmxObject {
public: public:

View File

@ -1,4 +1,8 @@
#include "ShadowrunDb.hpp"
#include <format> #include <format>
#include <functional>
#include <map>
#include "database.hpp"
#include "databasepool.h" #include "databasepool.h"
#include "crow.h" #include "crow.h"
#include "sqlite_orm.h" #include "sqlite_orm.h"
@ -19,52 +23,69 @@ int64_t getKeyOfCharacter(const string& name){
if (!character.empty()) { if (!character.empty()) {
return character[0].id; return character[0].id;
} else { } else {
return db->insert(ShadowrunCharacter{-1, name, ""}); return db->insert(ShadowrunCharacter{-1, name, Database::currentTime()});
} }
} }
bool storeCharacterData(int64_t characterKey, vector<pair<const string, const string>>& idValues){ bool storeCharacterData(int64_t characterKey, vector<pair<const string, const string>>& idValues){
auto sql = format("SELECT name FROM shadowrun_data WHERE character_id = {};", characterKey); auto characterData = getCharacterData(characterKey);
auto db = Database(); std::map<string, ShadowrunData*> dataMap;
if (!db.open()) for(auto& data : characterData) {
return false; dataMap[data.name] = &data;
}
auto set = db.getStrSet(sql);
auto db = dbpool.acquire();
for (auto& idValue : idValues) { for (auto& idValue : idValues) {
const string& name = idValue.first;
const string& value = idValue.second;
// update if already exist // update if already exist
if(set.contains(idValue.first)){ auto it = dataMap.find(name);
auto sql = format("UPDATE shadowrun_data SET value = '{}', updated_at = CURRENT_TIMESTAMP WHERE name = '{}' AND character_id = {}", idValue.second, idValue.first, characterKey); if(it != dataMap.end()){
if (!db.exec(sql)){ db->update_all(
CROW_LOG_WARNING << "Failed to update " << idValue.first << " with " << idValue.second; sqlite_orm::set(
} assign(&ShadowrunData::value, idValue.second),
assign(&ShadowrunData::updated_at, Database::currentTime())
),
where(
c(&ShadowrunData::name) == name and
c(&ShadowrunData::character_id) == characterKey
)
);
} else { } else {
auto sql = format("INSERT INTO shadowrun_data (character_id, name, value) " ShadowrunData entry {
"VALUES ({}, '{}', '{}')", characterKey, idValue.first, idValue.second); .id = -1,
if (!db.exec(sql)){ .character_id = static_cast<int>(characterKey),
CROW_LOG_WARNING << "Failed to insert " << idValue.first << " with " << idValue.second; .name = name,
} .value = value,
.created_at = Database::currentTime(),
.updated_at = "",
};
db->insert(entry);
} }
} }
return true; return true;
} }
std::set<std::string> getCharacters(){ std::vector<ShadowrunCharacter> getCharacters(){
string sql = "SELECT name FROM shadowrun_characters;"; auto db = dbpool.acquire();
auto db = Database(); return db->get_all<ShadowrunCharacter>();
if (!db.open())
return std::set<std::string>();
return db.getStrSet(sql);
} }
std::map<std::string, std::string> getCharacterData(int64_t characterKey) { std::map<string, string> getCharacterDataMap(int64_t characterKey){
std::string sql = "SELECT name, value FROM shadowrun_data WHERE character_id = ?;"; auto characterData = getCharacterData(characterKey);
auto db = Database(); std::map<string, string> dataMap;
if (!db.open()) for(auto& data : characterData) {
return std::map<std::string, std::string>(); dataMap[data.name] = data.value;
}
return dataMap;
}
return db.getStrMap(sql, {characterKey}); vector<ShadowrunData> getCharacterData(int64_t characterKey) {
auto db = dbpool.acquire();
return db->get_all<ShadowrunData>(
where(c(&ShadowrunData::character_id) == characterKey)
);
} }
} }

View File

@ -4,9 +4,8 @@
#include <cstdint> #include <cstdint>
#include <string> #include <string>
#include <vector> #include <vector>
#include <set>
#include <map> #include <map>
#include <optional>
namespace shadowrun { namespace shadowrun {
struct ShadowrunCharacter { struct ShadowrunCharacter {
int id; int id;
@ -25,9 +24,10 @@ namespace shadowrun {
int64_t getKeyOfCharacter(const std::string& name); int64_t getKeyOfCharacter(const std::string& name);
bool storeCharacterData(int64_t characterKey, std::vector<std::pair<const std::string, const std::string>>& idValues); bool storeCharacterData(int64_t characterKey, std::vector<std::pair<const std::string, const std::string>>& idValues);
std::set<std::string> getCharacters(); std::vector<ShadowrunCharacter> getCharacters();
std::map<std::string, std::string> getCharacterData(int64_t characterKey); std::vector<ShadowrunData> getCharacterData(int64_t characterKey);
std::map<std::string, std::string> getCharacterDataMap(int64_t characterKey);
} }
#endif // __SHADOWRUNDB_H__ #endif // __SHADOWRUNDB_H__