mirror of
https://github.com/DarkflameUniverse/DarkflameServer.git
synced 2026-03-04 23:59:50 +00:00
WIP working state
This commit is contained in:
@@ -5,6 +5,7 @@
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include "json.hpp"
|
||||
|
||||
enum class eGameMasterLevel : uint8_t;
|
||||
|
||||
@@ -55,6 +56,14 @@ public:
|
||||
|
||||
// Get failed attempt count
|
||||
virtual uint8_t GetFailedAttempts(const uint32_t accountId) = 0;
|
||||
|
||||
// Get paginated list of accounts with optional search/filtering for DataTables
|
||||
// Returns a JSON object with the account data and metadata
|
||||
virtual nlohmann::json GetAccountsTable(uint32_t start, uint32_t length, const std::string_view search = "", uint32_t orderColumn = 0, bool orderAsc = true) = 0;
|
||||
|
||||
// Get a single account by ID
|
||||
// Returns a JSON object with the account details
|
||||
virtual nlohmann::json GetAccountById(uint32_t accountId) = 0;
|
||||
};
|
||||
|
||||
#endif //!__IACCOUNTS__H__
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#define __IBUGREPORTS__H__
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
|
||||
class IBugReports {
|
||||
@@ -16,5 +17,9 @@ public:
|
||||
|
||||
// Add a new bug report to the database.
|
||||
virtual void InsertNewBugReport(const Info& info) = 0;
|
||||
|
||||
// Get paginated list of bug reports with optional search/filtering for DataTables
|
||||
// Returns a JSON-formatted string with the bug report data and metadata
|
||||
virtual std::string GetBugReportsTable(uint32_t start, uint32_t length, const std::string_view search = "", uint32_t orderColumn = 0, bool orderAsc = true) = 0;
|
||||
};
|
||||
#endif //!__IBUGREPORTS__H__
|
||||
|
||||
@@ -33,6 +33,9 @@ public:
|
||||
// Get the character ids for the given account.
|
||||
virtual std::vector<LWOOBJID> GetAccountCharacterIds(const LWOOBJID accountId) = 0;
|
||||
|
||||
// Get the total number of characters in the database.
|
||||
virtual uint32_t GetCharacterCount() = 0;
|
||||
|
||||
// Insert a new character into the database.
|
||||
virtual void InsertNewCharacter(const ICharInfo::Info info) = 0;
|
||||
|
||||
|
||||
@@ -15,6 +15,10 @@ public:
|
||||
|
||||
// Insert the character xml for the given character id.
|
||||
virtual void InsertCharacterXml(const LWOOBJID characterId, const std::string_view lxfml) = 0;
|
||||
|
||||
// Get paginated list of characters with optional search/filtering for DataTables
|
||||
// Returns a JSON-formatted string with the character data and metadata
|
||||
virtual std::string GetCharactersTable(uint32_t start, uint32_t length, const std::string_view search = "", uint32_t orderColumn = 0, bool orderAsc = true) = 0;
|
||||
};
|
||||
|
||||
#endif //!__ICHARXML__H__
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
|
||||
#include <cstdint>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
|
||||
class IPlayKeys {
|
||||
public:
|
||||
@@ -10,6 +12,10 @@ public:
|
||||
// Optional of bool may seem pointless, however the optional indicates if the playkey exists
|
||||
// and the bool indicates if the playkey is active.
|
||||
virtual std::optional<bool> IsPlaykeyActive(const int32_t playkeyId) = 0;
|
||||
|
||||
// Get paginated list of play keys with optional search/filtering for DataTables
|
||||
// Returns a JSON-formatted string with the play key data and metadata
|
||||
virtual std::string GetPlayKeysTable(uint32_t start, uint32_t length, const std::string_view search = "", uint32_t orderColumn = 0, bool orderAsc = true) = 0;
|
||||
};
|
||||
|
||||
#endif //!__IPLAYKEYS__H__
|
||||
|
||||
@@ -64,5 +64,9 @@ public:
|
||||
|
||||
// Insert a new property into the database.
|
||||
virtual void InsertNewProperty(const IProperty::Info& info, const uint32_t templateId, const LWOZONEID& zoneId) = 0;
|
||||
|
||||
// Get paginated list of properties with optional search/filtering for DataTables
|
||||
// Returns a JSON-formatted string with the property data and metadata
|
||||
virtual std::string GetPropertiesTable(uint32_t start, uint32_t length, const std::string_view search = "", uint32_t orderColumn = 0, bool orderAsc = true) = 0;
|
||||
};
|
||||
#endif //!__IPROPERTY__H__
|
||||
|
||||
@@ -60,6 +60,7 @@ public:
|
||||
std::optional<IAccounts::Info> GetAccountInfo(const std::string_view username) override;
|
||||
void InsertNewCharacter(const ICharInfo::Info info) override;
|
||||
void InsertCharacterXml(const LWOOBJID accountId, const std::string_view lxfml) override;
|
||||
std::string GetCharactersTable(uint32_t start, uint32_t length, const std::string_view search = "", uint32_t orderColumn = 0, bool orderAsc = true) override;
|
||||
std::vector<LWOOBJID> GetAccountCharacterIds(LWOOBJID accountId) override;
|
||||
void DeleteCharacter(const LWOOBJID characterId) override;
|
||||
void SetCharacterName(const LWOOBJID characterId, const std::string_view name) override;
|
||||
@@ -79,6 +80,7 @@ public:
|
||||
void RemoveModel(const LWOOBJID& modelId) override;
|
||||
void UpdatePerformanceCost(const LWOZONEID& zoneId, const float performanceCost) override;
|
||||
void InsertNewBugReport(const IBugReports::Info& info) override;
|
||||
std::string GetBugReportsTable(uint32_t start, uint32_t length, const std::string_view search = "", uint32_t orderColumn = 0, bool orderAsc = true) override;
|
||||
void InsertCheatDetection(const IPlayerCheatDetections::Info& info) override;
|
||||
void InsertNewMail(const MailInfo& mail) override;
|
||||
void InsertNewUgcModel(
|
||||
@@ -103,6 +105,7 @@ public:
|
||||
void InsertDefaultPersistentId() override;
|
||||
std::optional<uint32_t> GetDonationTotal(const uint32_t activityId) override;
|
||||
std::optional<bool> IsPlaykeyActive(const int32_t playkeyId) override;
|
||||
std::string GetPlayKeysTable(uint32_t start, uint32_t length, const std::string_view search = "", uint32_t orderColumn = 0, bool orderAsc = true) override;
|
||||
std::vector<IUgc::Model> GetUgcModels(const LWOOBJID& propertyId) override;
|
||||
void AddIgnore(const LWOOBJID playerId, const LWOOBJID ignoredPlayerId) override;
|
||||
void RemoveIgnore(const LWOOBJID playerId, const LWOOBJID ignoredPlayerId) override;
|
||||
@@ -126,15 +129,19 @@ public:
|
||||
void InsertUgcBuild(const std::string& modules, const LWOOBJID bigId, const std::optional<LWOOBJID> characterId) override;
|
||||
void DeleteUgcBuild(const LWOOBJID bigId) override;
|
||||
uint32_t GetAccountCount() override;
|
||||
uint32_t GetCharacterCount() override;
|
||||
void RecordFailedAttempt(const uint32_t accountId) override;
|
||||
void ClearFailedAttempts(const uint32_t accountId) override;
|
||||
void SetLockout(const uint32_t accountId, const int64_t lockoutUntil) override;
|
||||
bool IsLockedOut(const uint32_t accountId) override;
|
||||
uint8_t GetFailedAttempts(const uint32_t accountId) override;
|
||||
nlohmann::json GetAccountsTable(uint32_t start, uint32_t length, const std::string_view search = "", uint32_t orderColumn = 0, bool orderAsc = true) override;
|
||||
nlohmann::json GetAccountById(uint32_t accountId) override;
|
||||
bool IsNameInUse(const std::string_view name) override;
|
||||
std::optional<IPropertyContents::Model> GetModel(const LWOOBJID modelID) override;
|
||||
std::optional<IUgc::Model> GetUgcModel(const LWOOBJID ugcId) override;
|
||||
std::optional<IProperty::Info> GetPropertyInfo(const LWOOBJID id) override;
|
||||
std::string GetPropertiesTable(uint32_t start, uint32_t length, const std::string_view search = "", uint32_t orderColumn = 0, bool orderAsc = true) override;
|
||||
sql::PreparedStatement* CreatePreppedStmt(const std::string& query);
|
||||
private:
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include "MySQLDatabase.h"
|
||||
|
||||
#include "eGameMasterLevel.h"
|
||||
#include "json.hpp"
|
||||
|
||||
std::optional<IAccounts::Info> MySQLDatabase::GetAccountInfo(const std::string_view username) {
|
||||
auto result = ExecuteSelect("SELECT id, password, banned, locked, play_key_id, gm_level, mute_expire FROM accounts WHERE name = ? LIMIT 1;", username);
|
||||
@@ -82,3 +83,105 @@ uint8_t MySQLDatabase::GetFailedAttempts(const uint32_t accountId) {
|
||||
|
||||
return result->getUInt("failed_attempts");
|
||||
}
|
||||
|
||||
nlohmann::json MySQLDatabase::GetAccountsTable(uint32_t start, uint32_t length, const std::string_view search, uint32_t orderColumn, bool orderAsc) {
|
||||
// Build base query
|
||||
std::string baseQuery = "SELECT id, name, banned, locked, gm_level, mute_expire, created_at FROM accounts";
|
||||
std::string whereClause;
|
||||
std::string orderClause;
|
||||
|
||||
// Add search filter if provided
|
||||
if (!search.empty()) {
|
||||
whereClause = " WHERE name LIKE CONCAT('%', ?, '%')";
|
||||
}
|
||||
|
||||
// Map column indices to database columns
|
||||
std::string orderColumnName = "id";
|
||||
switch (orderColumn) {
|
||||
case 0: orderColumnName = "id"; break;
|
||||
case 1: orderColumnName = "name"; break;
|
||||
case 2: orderColumnName = "banned"; break;
|
||||
case 3: orderColumnName = "locked"; break;
|
||||
case 4: orderColumnName = "gm_level"; break;
|
||||
case 5: orderColumnName = "mute_expire"; break;
|
||||
case 6: orderColumnName = "created_at"; break;
|
||||
default: orderColumnName = "id";
|
||||
}
|
||||
|
||||
orderClause = " ORDER BY " + orderColumnName + (orderAsc ? " ASC" : " DESC");
|
||||
|
||||
// Build the main query
|
||||
std::string mainQuery = baseQuery + whereClause + orderClause + " LIMIT ?, ?;";
|
||||
|
||||
// Get total count
|
||||
std::string totalCountQuery = "SELECT COUNT(*) as count FROM accounts;";
|
||||
auto totalCountResult = ExecuteSelect(totalCountQuery);
|
||||
uint32_t totalRecords = totalCountResult->next() ? totalCountResult->getUInt("count") : 0;
|
||||
|
||||
// Get filtered count
|
||||
uint32_t filteredRecords = totalRecords;
|
||||
if (!search.empty()) {
|
||||
std::string filteredCountQuery = "SELECT COUNT(*) as count FROM accounts WHERE name LIKE CONCAT('%', ?, '%');";
|
||||
auto filteredCountResult = ExecuteSelect(filteredCountQuery, search);
|
||||
filteredRecords = filteredCountResult->next() ? filteredCountResult->getUInt("count") : 0;
|
||||
}
|
||||
|
||||
// Execute main query
|
||||
std::unique_ptr<sql::ResultSet> result;
|
||||
if (!search.empty()) {
|
||||
result = ExecuteSelect(mainQuery, search, start, length);
|
||||
} else {
|
||||
result = ExecuteSelect(mainQuery, start, length);
|
||||
}
|
||||
|
||||
// Build response JSON
|
||||
nlohmann::json accountsArray = nlohmann::json::array();
|
||||
|
||||
while (result->next()) {
|
||||
nlohmann::json account = {
|
||||
{"id", result->getUInt("id")},
|
||||
{"name", result->getString("name")},
|
||||
{"banned", result->getBoolean("banned")},
|
||||
{"locked", result->getBoolean("locked")},
|
||||
{"gm_level", result->getInt("gm_level")},
|
||||
{"mute_expire", result->getUInt64("mute_expire")},
|
||||
{"created_at", result->getString("created_at")}
|
||||
};
|
||||
accountsArray.push_back(account);
|
||||
}
|
||||
|
||||
nlohmann::json response = {
|
||||
{"draw", 1},
|
||||
{"recordsTotal", totalRecords},
|
||||
{"recordsFiltered", filteredRecords},
|
||||
{"data", accountsArray}
|
||||
};
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
nlohmann::json MySQLDatabase::GetAccountById(uint32_t accountId) {
|
||||
try {
|
||||
const std::string query = "SELECT id, name, banned, locked, gm_level, mute_expire, created_at FROM accounts WHERE id = ?;";
|
||||
auto result = ExecuteSelect(query, accountId);
|
||||
|
||||
if (!result->next()) {
|
||||
return nlohmann::json{{"error", "Account not found"}};
|
||||
}
|
||||
|
||||
nlohmann::json account = {
|
||||
{"id", result->getUInt("id")},
|
||||
{"name", result->getString("name")},
|
||||
{"banned", result->getBoolean("banned")},
|
||||
{"locked", result->getBoolean("locked")},
|
||||
{"gm_level", result->getInt("gm_level")},
|
||||
{"mute_expire", result->getUInt64("mute_expire")},
|
||||
{"created_at", result->getString("created_at")}
|
||||
};
|
||||
|
||||
return account;
|
||||
} catch (const sql::SQLException& e) {
|
||||
LOG_DEBUG("SQL Error: %s", e.what());
|
||||
return nlohmann::json{{"error", "Database error"}};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,3 +4,77 @@ void MySQLDatabase::InsertNewBugReport(const IBugReports::Info& info) {
|
||||
ExecuteInsert("INSERT INTO `bug_reports`(body, client_version, other_player_id, selection, reporter_id) VALUES (?, ?, ?, ?, ?)",
|
||||
info.body, info.clientVersion, info.otherPlayer, info.selection, info.characterId);
|
||||
}
|
||||
|
||||
#include "json.hpp"
|
||||
|
||||
std::string MySQLDatabase::GetBugReportsTable(uint32_t start, uint32_t length, const std::string_view search, uint32_t orderColumn, bool orderAsc) {
|
||||
// Build base query
|
||||
std::string baseQuery = "SELECT id, body, client_version, other_player_id, selection, submitted FROM bug_reports";
|
||||
std::string whereClause;
|
||||
std::string orderClause;
|
||||
|
||||
// Add search filter if provided
|
||||
if (!search.empty()) {
|
||||
whereClause = " WHERE body LIKE CONCAT('%', ?, '%') OR other_player_id LIKE CONCAT('%', ?, '%')";
|
||||
}
|
||||
|
||||
// Map column indices to database columns
|
||||
std::string orderColumnName = "id";
|
||||
switch (orderColumn) {
|
||||
case 0: orderColumnName = "id"; break;
|
||||
case 1: orderColumnName = "other_player_id"; break;
|
||||
case 2: orderColumnName = "client_version"; break;
|
||||
case 3: orderColumnName = "submitted"; break;
|
||||
default: orderColumnName = "id";
|
||||
}
|
||||
|
||||
orderClause = " ORDER BY " + orderColumnName + (orderAsc ? " ASC" : " DESC");
|
||||
|
||||
// Build the main query
|
||||
std::string mainQuery = baseQuery + whereClause + orderClause + " LIMIT ?, ?;";
|
||||
|
||||
// Get total count
|
||||
std::string totalCountQuery = "SELECT COUNT(*) as count FROM bug_reports;";
|
||||
auto totalCountResult = ExecuteSelect(totalCountQuery);
|
||||
uint32_t totalRecords = totalCountResult->next() ? totalCountResult->getUInt("count") : 0;
|
||||
|
||||
// Get filtered count
|
||||
uint32_t filteredRecords = totalRecords;
|
||||
if (!search.empty()) {
|
||||
std::string filteredCountQuery = "SELECT COUNT(*) as count FROM bug_reports WHERE body LIKE CONCAT('%', ?, '%') OR other_player_id LIKE CONCAT('%', ?, '%');";
|
||||
auto filteredCountResult = ExecuteSelect(filteredCountQuery, search, search);
|
||||
filteredRecords = filteredCountResult->next() ? filteredCountResult->getUInt("count") : 0;
|
||||
}
|
||||
|
||||
// Execute main query
|
||||
std::unique_ptr<sql::ResultSet> result;
|
||||
if (!search.empty()) {
|
||||
result = ExecuteSelect(mainQuery, search, search, start, length);
|
||||
} else {
|
||||
result = ExecuteSelect(mainQuery, start, length);
|
||||
}
|
||||
|
||||
// Build response JSON
|
||||
nlohmann::json reportsArray = nlohmann::json::array();
|
||||
|
||||
while (result->next()) {
|
||||
nlohmann::json report = {
|
||||
{"id", result->getUInt("id")},
|
||||
{"other_player_id", result->getString("other_player_id")},
|
||||
{"client_version", result->getString("client_version")},
|
||||
{"selection", result->getString("selection")},
|
||||
{"submitted", result->getString("submitted")},
|
||||
{"body", result->getString("body")}
|
||||
};
|
||||
reportsArray.push_back(report);
|
||||
}
|
||||
|
||||
nlohmann::json response = {
|
||||
{"draw", 0},
|
||||
{"recordsTotal", totalRecords},
|
||||
{"recordsFiltered", filteredRecords},
|
||||
{"data", reportsArray}
|
||||
};
|
||||
|
||||
return response.dump();
|
||||
}
|
||||
|
||||
@@ -54,6 +54,11 @@ std::vector<LWOOBJID> MySQLDatabase::GetAccountCharacterIds(const LWOOBJID accou
|
||||
return toReturn;
|
||||
}
|
||||
|
||||
uint32_t MySQLDatabase::GetCharacterCount() {
|
||||
auto res = ExecuteSelect("SELECT COUNT(*) as count FROM charinfo;");
|
||||
return res->next() ? res->getUInt("count") : 0;
|
||||
}
|
||||
|
||||
void MySQLDatabase::InsertNewCharacter(const ICharInfo::Info info) {
|
||||
ExecuteInsert(
|
||||
"INSERT INTO `charinfo`(`id`, `account_id`, `name`, `pending_name`, `needs_rename`, `last_login`) VALUES (?,?,?,?,?,?)",
|
||||
|
||||
@@ -17,3 +17,75 @@ void MySQLDatabase::UpdateCharacterXml(const LWOOBJID charId, const std::string_
|
||||
void MySQLDatabase::InsertCharacterXml(const LWOOBJID characterId, const std::string_view lxfml) {
|
||||
ExecuteInsert("INSERT INTO `charxml` (`id`, `xml_data`) VALUES (?,?)", characterId, lxfml);
|
||||
}
|
||||
|
||||
#include "json.hpp"
|
||||
|
||||
std::string MySQLDatabase::GetCharactersTable(uint32_t start, uint32_t length, const std::string_view search, uint32_t orderColumn, bool orderAsc) {
|
||||
// Build base query
|
||||
std::string baseQuery = "SELECT c.id, c.name, c.account_id, c.last_login, a.name as account_name FROM charinfo c JOIN accounts a ON c.account_id = a.id";
|
||||
std::string whereClause;
|
||||
std::string orderClause;
|
||||
|
||||
// Add search filter if provided
|
||||
if (!search.empty()) {
|
||||
whereClause = " WHERE c.name LIKE CONCAT('%', ?, '%')";
|
||||
}
|
||||
|
||||
// Map column indices to database columns
|
||||
std::string orderColumnName = "c.id";
|
||||
switch (orderColumn) {
|
||||
case 0: orderColumnName = "c.id"; break;
|
||||
case 1: orderColumnName = "c.name"; break;
|
||||
case 2: orderColumnName = "a.name"; break;
|
||||
case 3: orderColumnName = "c.last_login"; break;
|
||||
default: orderColumnName = "c.id";
|
||||
}
|
||||
|
||||
orderClause = " ORDER BY " + orderColumnName + (orderAsc ? " ASC" : " DESC");
|
||||
|
||||
// Build the main query
|
||||
std::string mainQuery = baseQuery + whereClause + orderClause + " LIMIT ?, ?;";
|
||||
|
||||
// Get total count
|
||||
std::string totalCountQuery = "SELECT COUNT(*) as count FROM charinfo;";
|
||||
auto totalCountResult = ExecuteSelect(totalCountQuery);
|
||||
uint32_t totalRecords = totalCountResult->next() ? totalCountResult->getUInt("count") : 0;
|
||||
|
||||
// Get filtered count
|
||||
uint32_t filteredRecords = totalRecords;
|
||||
if (!search.empty()) {
|
||||
std::string filteredCountQuery = "SELECT COUNT(*) as count FROM charinfo WHERE name LIKE CONCAT('%', ?, '%');";
|
||||
auto filteredCountResult = ExecuteSelect(filteredCountQuery, search);
|
||||
filteredRecords = filteredCountResult->next() ? filteredCountResult->getUInt("count") : 0;
|
||||
}
|
||||
|
||||
// Execute main query
|
||||
std::unique_ptr<sql::ResultSet> result;
|
||||
if (!search.empty()) {
|
||||
result = ExecuteSelect(mainQuery, search, start, length);
|
||||
} else {
|
||||
result = ExecuteSelect(mainQuery, start, length);
|
||||
}
|
||||
|
||||
// Build response JSON
|
||||
nlohmann::json charactersArray = nlohmann::json::array();
|
||||
|
||||
while (result->next()) {
|
||||
nlohmann::json character = {
|
||||
{"id", result->getUInt64("id")},
|
||||
{"name", result->getString("name")},
|
||||
{"account_name", result->getString("account_name")},
|
||||
{"last_login", result->getUInt64("last_login")}
|
||||
};
|
||||
charactersArray.push_back(character);
|
||||
}
|
||||
|
||||
nlohmann::json response = {
|
||||
{"draw", 0},
|
||||
{"recordsTotal", totalRecords},
|
||||
{"recordsFiltered", filteredRecords},
|
||||
{"data", charactersArray}
|
||||
};
|
||||
|
||||
return response.dump();
|
||||
}
|
||||
|
||||
@@ -9,3 +9,77 @@ std::optional<bool> MySQLDatabase::IsPlaykeyActive(const int32_t playkeyId) {
|
||||
|
||||
return keyCheckRes->getBoolean("active");
|
||||
}
|
||||
|
||||
#include "json.hpp"
|
||||
|
||||
std::string MySQLDatabase::GetPlayKeysTable(uint32_t start, uint32_t length, const std::string_view search, uint32_t orderColumn, bool orderAsc) {
|
||||
// Build base query
|
||||
std::string baseQuery = "SELECT id, key_string, key_uses, created_at, active FROM play_keys";
|
||||
std::string whereClause;
|
||||
std::string orderClause;
|
||||
|
||||
// Add search filter if provided
|
||||
if (!search.empty()) {
|
||||
whereClause = " WHERE key_string LIKE CONCAT('%', ?, '%')";
|
||||
}
|
||||
|
||||
// Map column indices to database columns
|
||||
std::string orderColumnName = "id";
|
||||
switch (orderColumn) {
|
||||
case 0: orderColumnName = "id"; break;
|
||||
case 1: orderColumnName = "key_string"; break;
|
||||
case 2: orderColumnName = "key_uses"; break;
|
||||
case 3: orderColumnName = "created_at"; break;
|
||||
case 4: orderColumnName = "active"; break;
|
||||
default: orderColumnName = "id";
|
||||
}
|
||||
|
||||
orderClause = " ORDER BY " + orderColumnName + (orderAsc ? " ASC" : " DESC");
|
||||
|
||||
// Build the main query
|
||||
std::string mainQuery = baseQuery + whereClause + orderClause + " LIMIT ?, ?;";
|
||||
|
||||
// Get total count
|
||||
std::string totalCountQuery = "SELECT COUNT(*) as count FROM play_keys;";
|
||||
auto totalCountResult = ExecuteSelect(totalCountQuery);
|
||||
uint32_t totalRecords = totalCountResult->next() ? totalCountResult->getUInt("count") : 0;
|
||||
|
||||
// Get filtered count
|
||||
uint32_t filteredRecords = totalRecords;
|
||||
if (!search.empty()) {
|
||||
std::string filteredCountQuery = "SELECT COUNT(*) as count FROM play_keys WHERE key_string LIKE CONCAT('%', ?, '%');";
|
||||
auto filteredCountResult = ExecuteSelect(filteredCountQuery, search);
|
||||
filteredRecords = filteredCountResult->next() ? filteredCountResult->getUInt("count") : 0;
|
||||
}
|
||||
|
||||
// Execute main query
|
||||
std::unique_ptr<sql::ResultSet> result;
|
||||
if (!search.empty()) {
|
||||
result = ExecuteSelect(mainQuery, search, start, length);
|
||||
} else {
|
||||
result = ExecuteSelect(mainQuery, start, length);
|
||||
}
|
||||
|
||||
// Build response JSON
|
||||
nlohmann::json keysArray = nlohmann::json::array();
|
||||
|
||||
while (result->next()) {
|
||||
nlohmann::json key = {
|
||||
{"id", result->getUInt("id")},
|
||||
{"key_string", result->getString("key_string")},
|
||||
{"key_uses", result->getUInt("key_uses")},
|
||||
{"created_at", result->getString("created_at")},
|
||||
{"active", result->getBoolean("active")}
|
||||
};
|
||||
keysArray.push_back(key);
|
||||
}
|
||||
|
||||
nlohmann::json response = {
|
||||
{"draw", 0},
|
||||
{"recordsTotal", totalRecords},
|
||||
{"recordsFiltered", filteredRecords},
|
||||
{"data", keysArray}
|
||||
};
|
||||
|
||||
return response.dump();
|
||||
}
|
||||
|
||||
@@ -198,3 +198,79 @@ std::optional<IProperty::Info> MySQLDatabase::GetPropertyInfo(const LWOOBJID id)
|
||||
|
||||
return ReadPropertyInfo(propertyEntry);
|
||||
}
|
||||
|
||||
#include "json.hpp"
|
||||
|
||||
std::string MySQLDatabase::GetPropertiesTable(uint32_t start, uint32_t length, const std::string_view search, uint32_t orderColumn, bool orderAsc) {
|
||||
// Build base query
|
||||
std::string baseQuery = "SELECT id, owner_id, name, mod_approved, reputation, zone_id FROM properties";
|
||||
std::string whereClause;
|
||||
std::string orderClause;
|
||||
|
||||
// Add search filter if provided
|
||||
if (!search.empty()) {
|
||||
whereClause = " WHERE name LIKE CONCAT('%', ?, '%')";
|
||||
}
|
||||
|
||||
// Map column indices to database columns
|
||||
std::string orderColumnName = "id";
|
||||
switch (orderColumn) {
|
||||
case 0: orderColumnName = "id"; break;
|
||||
case 1: orderColumnName = "name"; break;
|
||||
case 2: orderColumnName = "owner_id"; break;
|
||||
case 3: orderColumnName = "mod_approved"; break;
|
||||
case 4: orderColumnName = "reputation"; break;
|
||||
case 5: orderColumnName = "zone_id"; break;
|
||||
default: orderColumnName = "id";
|
||||
}
|
||||
|
||||
orderClause = " ORDER BY " + orderColumnName + (orderAsc ? " ASC" : " DESC");
|
||||
|
||||
// Build the main query
|
||||
std::string mainQuery = baseQuery + whereClause + orderClause + " LIMIT ?, ?;";
|
||||
|
||||
// Get total count
|
||||
std::string totalCountQuery = "SELECT COUNT(*) as count FROM properties;";
|
||||
auto totalCountResult = ExecuteSelect(totalCountQuery);
|
||||
uint32_t totalRecords = totalCountResult->next() ? totalCountResult->getUInt("count") : 0;
|
||||
|
||||
// Get filtered count
|
||||
uint32_t filteredRecords = totalRecords;
|
||||
if (!search.empty()) {
|
||||
std::string filteredCountQuery = "SELECT COUNT(*) as count FROM properties WHERE name LIKE CONCAT('%', ?, '%');";
|
||||
auto filteredCountResult = ExecuteSelect(filteredCountQuery, search);
|
||||
filteredRecords = filteredCountResult->next() ? filteredCountResult->getUInt("count") : 0;
|
||||
}
|
||||
|
||||
// Execute main query
|
||||
std::unique_ptr<sql::ResultSet> result;
|
||||
if (!search.empty()) {
|
||||
result = ExecuteSelect(mainQuery, search, start, length);
|
||||
} else {
|
||||
result = ExecuteSelect(mainQuery, start, length);
|
||||
}
|
||||
|
||||
// Build response JSON
|
||||
nlohmann::json propertiesArray = nlohmann::json::array();
|
||||
|
||||
while (result->next()) {
|
||||
nlohmann::json property = {
|
||||
{"id", result->getUInt64("id")},
|
||||
{"owner_id", result->getUInt64("owner_id")},
|
||||
{"name", result->getString("name")},
|
||||
{"mod_approved", result->getBoolean("mod_approved")},
|
||||
{"reputation", result->getUInt64("reputation")},
|
||||
{"zone_id", result->getUInt("zone_id")}
|
||||
};
|
||||
propertiesArray.push_back(property);
|
||||
}
|
||||
|
||||
nlohmann::json response = {
|
||||
{"draw", 0},
|
||||
{"recordsTotal", totalRecords},
|
||||
{"recordsFiltered", filteredRecords},
|
||||
{"data", propertiesArray}
|
||||
};
|
||||
|
||||
return response.dump();
|
||||
}
|
||||
|
||||
@@ -58,6 +58,7 @@ public:
|
||||
std::optional<IAccounts::Info> GetAccountInfo(const std::string_view username) override;
|
||||
void InsertNewCharacter(const ICharInfo::Info info) override;
|
||||
void InsertCharacterXml(const LWOOBJID accountId, const std::string_view lxfml) override;
|
||||
std::string GetCharactersTable(uint32_t start, uint32_t length, const std::string_view search = "", uint32_t orderColumn = 0, bool orderAsc = true) override;
|
||||
std::vector<LWOOBJID> GetAccountCharacterIds(LWOOBJID accountId) override;
|
||||
void DeleteCharacter(const LWOOBJID characterId) override;
|
||||
void SetCharacterName(const LWOOBJID characterId, const std::string_view name) override;
|
||||
@@ -77,6 +78,7 @@ public:
|
||||
void RemoveModel(const LWOOBJID& modelId) override;
|
||||
void UpdatePerformanceCost(const LWOZONEID& zoneId, const float performanceCost) override;
|
||||
void InsertNewBugReport(const IBugReports::Info& info) override;
|
||||
std::string GetBugReportsTable(uint32_t start, uint32_t length, const std::string_view search = "", uint32_t orderColumn = 0, bool orderAsc = true) override;
|
||||
void InsertCheatDetection(const IPlayerCheatDetections::Info& info) override;
|
||||
void InsertNewMail(const MailInfo& mail) override;
|
||||
void InsertNewUgcModel(
|
||||
@@ -101,6 +103,7 @@ public:
|
||||
void InsertDefaultPersistentId() override;
|
||||
std::optional<uint32_t> GetDonationTotal(const uint32_t activityId) override;
|
||||
std::optional<bool> IsPlaykeyActive(const int32_t playkeyId) override;
|
||||
std::string GetPlayKeysTable(uint32_t start, uint32_t length, const std::string_view search = "", uint32_t orderColumn = 0, bool orderAsc = true) override;
|
||||
std::vector<IUgc::Model> GetUgcModels(const LWOOBJID& propertyId) override;
|
||||
void AddIgnore(const LWOOBJID playerId, const LWOOBJID ignoredPlayerId) override;
|
||||
void RemoveIgnore(const LWOOBJID playerId, const LWOOBJID ignoredPlayerId) override;
|
||||
@@ -124,15 +127,19 @@ public:
|
||||
void InsertUgcBuild(const std::string& modules, const LWOOBJID bigId, const std::optional<LWOOBJID> characterId) override;
|
||||
void DeleteUgcBuild(const LWOOBJID bigId) override;
|
||||
uint32_t GetAccountCount() override;
|
||||
uint32_t GetCharacterCount() override;
|
||||
void RecordFailedAttempt(const uint32_t accountId) override;
|
||||
void ClearFailedAttempts(const uint32_t accountId) override;
|
||||
void SetLockout(const uint32_t accountId, const int64_t lockoutUntil) override;
|
||||
bool IsLockedOut(const uint32_t accountId) override;
|
||||
uint8_t GetFailedAttempts(const uint32_t accountId) override;
|
||||
nlohmann::json GetAccountsTable(uint32_t start, uint32_t length, const std::string_view search = "", uint32_t orderColumn = 0, bool orderAsc = true) override;
|
||||
nlohmann::json GetAccountById(uint32_t accountId) override;
|
||||
bool IsNameInUse(const std::string_view name) override;
|
||||
std::optional<IPropertyContents::Model> GetModel(const LWOOBJID modelID) override;
|
||||
std::optional<IUgc::Model> GetUgcModel(const LWOOBJID ugcId) override;
|
||||
std::optional<IProperty::Info> GetPropertyInfo(const LWOOBJID id) override;
|
||||
std::string GetPropertiesTable(uint32_t start, uint32_t length, const std::string_view search = "", uint32_t orderColumn = 0, bool orderAsc = true) override;
|
||||
private:
|
||||
CppSQLite3Statement CreatePreppedStmt(const std::string& query);
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
#include "eGameMasterLevel.h"
|
||||
#include "Database.h"
|
||||
#include "json.hpp"
|
||||
|
||||
std::optional<IAccounts::Info> SQLiteDatabase::GetAccountInfo(const std::string_view username) {
|
||||
auto [_, result] = ExecuteSelect("SELECT * FROM accounts WHERE name = ? LIMIT 1", username);
|
||||
@@ -83,4 +84,102 @@ uint8_t SQLiteDatabase::GetFailedAttempts(const uint32_t accountId) {
|
||||
}
|
||||
|
||||
return result.getIntField("failed_attempts");
|
||||
}
|
||||
|
||||
nlohmann::json SQLiteDatabase::GetAccountsTable(uint32_t start, uint32_t length, const std::string_view search, uint32_t orderColumn, bool orderAsc) {
|
||||
// Build base query
|
||||
std::string baseQuery = "SELECT id, name, banned, locked, gm_level, mute_expire, created_at FROM accounts";
|
||||
std::string whereClause;
|
||||
std::string orderClause;
|
||||
|
||||
// Add search filter if provided
|
||||
if (!search.empty()) {
|
||||
whereClause = " WHERE name LIKE '%' || ? || '%'";
|
||||
}
|
||||
|
||||
// Map column indices to database columns
|
||||
std::string orderColumnName = "id";
|
||||
switch (orderColumn) {
|
||||
case 0: orderColumnName = "id"; break;
|
||||
case 1: orderColumnName = "name"; break;
|
||||
case 2: orderColumnName = "banned"; break;
|
||||
case 3: orderColumnName = "locked"; break;
|
||||
case 4: orderColumnName = "gm_level"; break;
|
||||
case 5: orderColumnName = "mute_expire"; break;
|
||||
case 6: orderColumnName = "created_at"; break;
|
||||
default: orderColumnName = "id";
|
||||
}
|
||||
|
||||
orderClause = " ORDER BY " + orderColumnName + (orderAsc ? " ASC" : " DESC");
|
||||
|
||||
// Build the main query
|
||||
std::string mainQuery = baseQuery + whereClause + orderClause + " LIMIT ? OFFSET ?;";
|
||||
|
||||
// Get total count
|
||||
std::string totalCountQuery = "SELECT COUNT(*) as count FROM accounts;";
|
||||
auto [_, totalCountResult] = ExecuteSelect(totalCountQuery);
|
||||
uint32_t totalRecords = totalCountResult.eof() ? 0 : totalCountResult.getIntField("count");
|
||||
|
||||
// Get filtered count
|
||||
uint32_t filteredRecords = totalRecords;
|
||||
if (!search.empty()) {
|
||||
std::string filteredCountQuery = "SELECT COUNT(*) as count FROM accounts WHERE name LIKE '%' || ? || '%';";
|
||||
auto [__, filteredCountResult] = ExecuteSelect(filteredCountQuery, search);
|
||||
filteredRecords = filteredCountResult.eof() ? 0 : filteredCountResult.getIntField("count");
|
||||
}
|
||||
|
||||
// Execute main query
|
||||
auto [stmt, result] = !search.empty() ?
|
||||
ExecuteSelect(mainQuery, search, length, start) :
|
||||
ExecuteSelect(mainQuery, length, start);
|
||||
|
||||
// Build response JSON
|
||||
nlohmann::json accountsArray = nlohmann::json::array();
|
||||
|
||||
while (!result.eof()) {
|
||||
nlohmann::json account = {
|
||||
{"id", result.getIntField("id")},
|
||||
{"name", result.getStringField("name")},
|
||||
{"banned", result.getIntField("banned")},
|
||||
{"locked", result.getIntField("locked")},
|
||||
{"gm_level", result.getIntField("gm_level")},
|
||||
{"mute_expire", result.getInt64Field("mute_expire")},
|
||||
{"created_at", result.getStringField("created_at")}
|
||||
};
|
||||
accountsArray.push_back(account);
|
||||
result.nextRow();
|
||||
}
|
||||
|
||||
nlohmann::json response = {
|
||||
{"draw", 1},
|
||||
{"recordsTotal", totalRecords},
|
||||
{"recordsFiltered", filteredRecords},
|
||||
{"data", accountsArray}
|
||||
};
|
||||
|
||||
return response;
|
||||
}
|
||||
nlohmann::json SQLiteDatabase::GetAccountById(uint32_t accountId) {
|
||||
try {
|
||||
auto [_, result] = ExecuteSelect("SELECT * FROM accounts WHERE id = ? LIMIT 1;", accountId);
|
||||
|
||||
if (result.eof()) {
|
||||
return nlohmann::json{{"error", "Account not found"}};
|
||||
}
|
||||
|
||||
nlohmann::json account = {
|
||||
{"id", result.getIntField("id")},
|
||||
{"name", result.getStringField("name")},
|
||||
{"banned", result.getIntField("banned")},
|
||||
{"locked", result.getIntField("locked")},
|
||||
{"gm_level", result.getIntField("gm_level")},
|
||||
{"mute_expire", result.getInt64Field("mute_expire")},
|
||||
{"created_at", result.getStringField("created_at")}
|
||||
};
|
||||
|
||||
return account;
|
||||
} catch (const CppSQLite3Exception& e) {
|
||||
LOG_DEBUG("SQLite Error: %s", e.errorMessage());
|
||||
return nlohmann::json{{"error", "Database error"}};
|
||||
}
|
||||
}
|
||||
@@ -4,3 +4,75 @@ void SQLiteDatabase::InsertNewBugReport(const IBugReports::Info& info) {
|
||||
ExecuteInsert("INSERT INTO `bug_reports`(body, client_version, other_player_id, selection, reporter_id) VALUES (?, ?, ?, ?, ?)",
|
||||
info.body, info.clientVersion, info.otherPlayer, info.selection, info.characterId);
|
||||
}
|
||||
|
||||
#include "json.hpp"
|
||||
|
||||
std::string SQLiteDatabase::GetBugReportsTable(uint32_t start, uint32_t length, const std::string_view search, uint32_t orderColumn, bool orderAsc) {
|
||||
// Build base query
|
||||
std::string baseQuery = "SELECT id, body, client_version, other_player_id, selection, submitted FROM bug_reports";
|
||||
std::string whereClause;
|
||||
std::string orderClause;
|
||||
|
||||
// Add search filter if provided
|
||||
if (!search.empty()) {
|
||||
whereClause = " WHERE body LIKE '%' || ? || '%' OR other_player_id LIKE '%' || ? || '%'";
|
||||
}
|
||||
|
||||
// Map column indices to database columns
|
||||
std::string orderColumnName = "id";
|
||||
switch (orderColumn) {
|
||||
case 0: orderColumnName = "id"; break;
|
||||
case 1: orderColumnName = "other_player_id"; break;
|
||||
case 2: orderColumnName = "client_version"; break;
|
||||
case 3: orderColumnName = "submitted"; break;
|
||||
default: orderColumnName = "id";
|
||||
}
|
||||
|
||||
orderClause = " ORDER BY " + orderColumnName + (orderAsc ? " ASC" : " DESC");
|
||||
|
||||
// Build the main query
|
||||
std::string mainQuery = baseQuery + whereClause + orderClause + " LIMIT ? OFFSET ?;";
|
||||
|
||||
// Get total count
|
||||
std::string totalCountQuery = "SELECT COUNT(*) as count FROM bug_reports;";
|
||||
auto [__, totalCountResult] = ExecuteSelect(totalCountQuery);
|
||||
uint32_t totalRecords = totalCountResult.eof() ? 0 : totalCountResult.getIntField("count");
|
||||
|
||||
// Get filtered count
|
||||
uint32_t filteredRecords = totalRecords;
|
||||
if (!search.empty()) {
|
||||
std::string filteredCountQuery = "SELECT COUNT(*) as count FROM bug_reports WHERE body LIKE '%' || ? || '%' OR other_player_id LIKE '%' || ? || '%';";
|
||||
auto [___, filteredCountResult] = ExecuteSelect(filteredCountQuery, search, search);
|
||||
filteredRecords = filteredCountResult.eof() ? 0 : filteredCountResult.getIntField("count");
|
||||
}
|
||||
|
||||
// Execute main query
|
||||
auto [stmt, result] = !search.empty() ?
|
||||
ExecuteSelect(mainQuery, search, search, length, start) :
|
||||
ExecuteSelect(mainQuery, length, start);
|
||||
|
||||
// Build response JSON
|
||||
nlohmann::json reportsArray = nlohmann::json::array();
|
||||
|
||||
while (!result.eof()) {
|
||||
nlohmann::json report = {
|
||||
{"id", result.getIntField("id")},
|
||||
{"other_player_id", result.getStringField("other_player_id")},
|
||||
{"client_version", result.getStringField("client_version")},
|
||||
{"selection", result.getStringField("selection")},
|
||||
{"submitted", result.getStringField("submitted")},
|
||||
{"body", result.getStringField("body")}
|
||||
};
|
||||
reportsArray.push_back(report);
|
||||
result.nextRow();
|
||||
}
|
||||
|
||||
nlohmann::json response = {
|
||||
{"draw", 0},
|
||||
{"recordsTotal", totalRecords},
|
||||
{"recordsFiltered", filteredRecords},
|
||||
{"data", reportsArray}
|
||||
};
|
||||
|
||||
return response.dump();
|
||||
}
|
||||
|
||||
@@ -55,6 +55,13 @@ std::vector<LWOOBJID> SQLiteDatabase::GetAccountCharacterIds(const LWOOBJID acco
|
||||
return toReturn;
|
||||
}
|
||||
|
||||
uint32_t SQLiteDatabase::GetCharacterCount() {
|
||||
auto [_, res] = ExecuteSelect("SELECT COUNT(*) as count FROM charinfo;");
|
||||
if (res.eof()) return 0;
|
||||
|
||||
return res.getIntField("count");
|
||||
}
|
||||
|
||||
void SQLiteDatabase::InsertNewCharacter(const ICharInfo::Info info) {
|
||||
ExecuteInsert(
|
||||
"INSERT INTO `charinfo`(`id`, `account_id`, `name`, `pending_name`, `needs_rename`, `last_login`, `prop_clone_id`) VALUES (?,?,?,?,?,?,(SELECT IFNULL(MAX(`prop_clone_id`), 0) + 1 FROM `charinfo`))",
|
||||
|
||||
@@ -17,3 +17,73 @@ void SQLiteDatabase::UpdateCharacterXml(const LWOOBJID charId, const std::string
|
||||
void SQLiteDatabase::InsertCharacterXml(const LWOOBJID characterId, const std::string_view lxfml) {
|
||||
ExecuteInsert("INSERT INTO `charxml` (`id`, `xml_data`) VALUES (?,?)", characterId, lxfml);
|
||||
}
|
||||
|
||||
#include "json.hpp"
|
||||
|
||||
std::string SQLiteDatabase::GetCharactersTable(uint32_t start, uint32_t length, const std::string_view search, uint32_t orderColumn, bool orderAsc) {
|
||||
// Build base query
|
||||
std::string baseQuery = "SELECT c.id, c.name, c.account_id, c.last_login, a.name as account_name FROM charinfo c JOIN accounts a ON c.account_id = a.id";
|
||||
std::string whereClause;
|
||||
std::string orderClause;
|
||||
|
||||
// Add search filter if provided
|
||||
if (!search.empty()) {
|
||||
whereClause = " WHERE c.name LIKE '%' || ? || '%'";
|
||||
}
|
||||
|
||||
// Map column indices to database columns
|
||||
std::string orderColumnName = "c.id";
|
||||
switch (orderColumn) {
|
||||
case 0: orderColumnName = "c.id"; break;
|
||||
case 1: orderColumnName = "c.name"; break;
|
||||
case 2: orderColumnName = "a.name"; break;
|
||||
case 3: orderColumnName = "c.last_login"; break;
|
||||
default: orderColumnName = "c.id";
|
||||
}
|
||||
|
||||
orderClause = " ORDER BY " + orderColumnName + (orderAsc ? " ASC" : " DESC");
|
||||
|
||||
// Build the main query
|
||||
std::string mainQuery = baseQuery + whereClause + orderClause + " LIMIT ? OFFSET ?;";
|
||||
|
||||
// Get total count
|
||||
std::string totalCountQuery = "SELECT COUNT(*) as count FROM charinfo;";
|
||||
auto [__, totalCountResult] = ExecuteSelect(totalCountQuery);
|
||||
uint32_t totalRecords = totalCountResult.eof() ? 0 : totalCountResult.getIntField("count");
|
||||
|
||||
// Get filtered count
|
||||
uint32_t filteredRecords = totalRecords;
|
||||
if (!search.empty()) {
|
||||
std::string filteredCountQuery = "SELECT COUNT(*) as count FROM charinfo WHERE name LIKE '%' || ? || '%';";
|
||||
auto [___, filteredCountResult] = ExecuteSelect(filteredCountQuery, search);
|
||||
filteredRecords = filteredCountResult.eof() ? 0 : filteredCountResult.getIntField("count");
|
||||
}
|
||||
|
||||
// Execute main query
|
||||
auto [stmt, result] = !search.empty() ?
|
||||
ExecuteSelect(mainQuery, search, length, start) :
|
||||
ExecuteSelect(mainQuery, length, start);
|
||||
|
||||
// Build response JSON
|
||||
nlohmann::json charactersArray = nlohmann::json::array();
|
||||
|
||||
while (!result.eof()) {
|
||||
nlohmann::json character = {
|
||||
{"id", result.getInt64Field("id")},
|
||||
{"name", result.getStringField("name")},
|
||||
{"account_name", result.getStringField("account_name")},
|
||||
{"last_login", result.getInt64Field("last_login")}
|
||||
};
|
||||
charactersArray.push_back(character);
|
||||
result.nextRow();
|
||||
}
|
||||
|
||||
nlohmann::json response = {
|
||||
{"draw", 0},
|
||||
{"recordsTotal", totalRecords},
|
||||
{"recordsFiltered", filteredRecords},
|
||||
{"data", charactersArray}
|
||||
};
|
||||
|
||||
return response.dump();
|
||||
}
|
||||
|
||||
@@ -9,3 +9,75 @@ std::optional<bool> SQLiteDatabase::IsPlaykeyActive(const int32_t playkeyId) {
|
||||
|
||||
return keyCheckRes.getIntField("active");
|
||||
}
|
||||
|
||||
#include "json.hpp"
|
||||
|
||||
std::string SQLiteDatabase::GetPlayKeysTable(uint32_t start, uint32_t length, const std::string_view search, uint32_t orderColumn, bool orderAsc) {
|
||||
// Build base query
|
||||
std::string baseQuery = "SELECT id, key_string, key_uses, created_at, active FROM play_keys";
|
||||
std::string whereClause;
|
||||
std::string orderClause;
|
||||
|
||||
// Add search filter if provided
|
||||
if (!search.empty()) {
|
||||
whereClause = " WHERE key_string LIKE '%' || ? || '%'";
|
||||
}
|
||||
|
||||
// Map column indices to database columns
|
||||
std::string orderColumnName = "id";
|
||||
switch (orderColumn) {
|
||||
case 0: orderColumnName = "id"; break;
|
||||
case 1: orderColumnName = "key_string"; break;
|
||||
case 2: orderColumnName = "key_uses"; break;
|
||||
case 3: orderColumnName = "created_at"; break;
|
||||
case 4: orderColumnName = "active"; break;
|
||||
default: orderColumnName = "id";
|
||||
}
|
||||
|
||||
orderClause = " ORDER BY " + orderColumnName + (orderAsc ? " ASC" : " DESC");
|
||||
|
||||
// Build the main query
|
||||
std::string mainQuery = baseQuery + whereClause + orderClause + " LIMIT ? OFFSET ?;";
|
||||
|
||||
// Get total count
|
||||
std::string totalCountQuery = "SELECT COUNT(*) as count FROM play_keys;";
|
||||
auto [__, totalCountResult] = ExecuteSelect(totalCountQuery);
|
||||
uint32_t totalRecords = totalCountResult.eof() ? 0 : totalCountResult.getIntField("count");
|
||||
|
||||
// Get filtered count
|
||||
uint32_t filteredRecords = totalRecords;
|
||||
if (!search.empty()) {
|
||||
std::string filteredCountQuery = "SELECT COUNT(*) as count FROM play_keys WHERE key_string LIKE '%' || ? || '%';";
|
||||
auto [___, filteredCountResult] = ExecuteSelect(filteredCountQuery, search);
|
||||
filteredRecords = filteredCountResult.eof() ? 0 : filteredCountResult.getIntField("count");
|
||||
}
|
||||
|
||||
// Execute main query
|
||||
auto [stmt, result] = !search.empty() ?
|
||||
ExecuteSelect(mainQuery, search, length, start) :
|
||||
ExecuteSelect(mainQuery, length, start);
|
||||
|
||||
// Build response JSON
|
||||
nlohmann::json keysArray = nlohmann::json::array();
|
||||
|
||||
while (!result.eof()) {
|
||||
nlohmann::json key = {
|
||||
{"id", result.getIntField("id")},
|
||||
{"key_string", result.getStringField("key_string")},
|
||||
{"key_uses", result.getIntField("key_uses")},
|
||||
{"created_at", result.getStringField("created_at")},
|
||||
{"active", result.getIntField("active")}
|
||||
};
|
||||
keysArray.push_back(key);
|
||||
result.nextRow();
|
||||
}
|
||||
|
||||
nlohmann::json response = {
|
||||
{"draw", 0},
|
||||
{"recordsTotal", totalRecords},
|
||||
{"recordsFiltered", filteredRecords},
|
||||
{"data", keysArray}
|
||||
};
|
||||
|
||||
return response.dump();
|
||||
}
|
||||
|
||||
@@ -200,3 +200,77 @@ std::optional<IProperty::Info> SQLiteDatabase::GetPropertyInfo(const LWOOBJID id
|
||||
|
||||
return ReadPropertyInfo(propertyEntry);
|
||||
}
|
||||
|
||||
#include "json.hpp"
|
||||
|
||||
std::string SQLiteDatabase::GetPropertiesTable(uint32_t start, uint32_t length, const std::string_view search, uint32_t orderColumn, bool orderAsc) {
|
||||
// Build base query
|
||||
std::string baseQuery = "SELECT id, owner_id, name, mod_approved, reputation, zone_id FROM properties";
|
||||
std::string whereClause;
|
||||
std::string orderClause;
|
||||
|
||||
// Add search filter if provided
|
||||
if (!search.empty()) {
|
||||
whereClause = " WHERE name LIKE '%' || ? || '%'";
|
||||
}
|
||||
|
||||
// Map column indices to database columns
|
||||
std::string orderColumnName = "id";
|
||||
switch (orderColumn) {
|
||||
case 0: orderColumnName = "id"; break;
|
||||
case 1: orderColumnName = "name"; break;
|
||||
case 2: orderColumnName = "owner_id"; break;
|
||||
case 3: orderColumnName = "mod_approved"; break;
|
||||
case 4: orderColumnName = "reputation"; break;
|
||||
case 5: orderColumnName = "zone_id"; break;
|
||||
default: orderColumnName = "id";
|
||||
}
|
||||
|
||||
orderClause = " ORDER BY " + orderColumnName + (orderAsc ? " ASC" : " DESC");
|
||||
|
||||
// Build the main query
|
||||
std::string mainQuery = baseQuery + whereClause + orderClause + " LIMIT ? OFFSET ?;";
|
||||
|
||||
// Get total count
|
||||
std::string totalCountQuery = "SELECT COUNT(*) as count FROM properties;";
|
||||
auto [__, totalCountResult] = ExecuteSelect(totalCountQuery);
|
||||
uint32_t totalRecords = totalCountResult.eof() ? 0 : totalCountResult.getIntField("count");
|
||||
|
||||
// Get filtered count
|
||||
uint32_t filteredRecords = totalRecords;
|
||||
if (!search.empty()) {
|
||||
std::string filteredCountQuery = "SELECT COUNT(*) as count FROM properties WHERE name LIKE '%' || ? || '%';";
|
||||
auto [___, filteredCountResult] = ExecuteSelect(filteredCountQuery, search);
|
||||
filteredRecords = filteredCountResult.eof() ? 0 : filteredCountResult.getIntField("count");
|
||||
}
|
||||
|
||||
// Execute main query
|
||||
auto [stmt, result] = !search.empty() ?
|
||||
ExecuteSelect(mainQuery, search, length, start) :
|
||||
ExecuteSelect(mainQuery, length, start);
|
||||
|
||||
// Build response JSON
|
||||
nlohmann::json propertiesArray = nlohmann::json::array();
|
||||
|
||||
while (!result.eof()) {
|
||||
nlohmann::json property = {
|
||||
{"id", result.getInt64Field("id")},
|
||||
{"owner_id", result.getInt64Field("owner_id")},
|
||||
{"name", result.getStringField("name")},
|
||||
{"mod_approved", result.getIntField("mod_approved")},
|
||||
{"reputation", result.getInt64Field("reputation")},
|
||||
{"zone_id", result.getIntField("zone_id")}
|
||||
};
|
||||
propertiesArray.push_back(property);
|
||||
result.nextRow();
|
||||
}
|
||||
|
||||
nlohmann::json response = {
|
||||
{"draw", 0},
|
||||
{"recordsTotal", totalRecords},
|
||||
{"recordsFiltered", filteredRecords},
|
||||
{"data", propertiesArray}
|
||||
};
|
||||
|
||||
return response.dump();
|
||||
}
|
||||
|
||||
@@ -103,11 +103,18 @@ class TestSQLDatabase : public GameDatabase {
|
||||
void InsertUgcBuild(const std::string& modules, const LWOOBJID bigId, const std::optional<LWOOBJID> characterId) override {};
|
||||
void DeleteUgcBuild(const LWOOBJID bigId) override {};
|
||||
uint32_t GetAccountCount() override { return 0; };
|
||||
uint32_t GetCharacterCount() override { return 0; };
|
||||
void RecordFailedAttempt(const uint32_t accountId) override {};
|
||||
void ClearFailedAttempts(const uint32_t accountId) override {};
|
||||
void SetLockout(const uint32_t accountId, const int64_t lockoutUntil) override {};
|
||||
bool IsLockedOut(const uint32_t accountId) override { return false; };
|
||||
uint8_t GetFailedAttempts(const uint32_t accountId) override { return 0; };
|
||||
nlohmann::json GetAccountsTable(uint32_t start, uint32_t length, const std::string_view search = "", uint32_t orderColumn = 0, bool orderAsc = true) override { return nlohmann::json::object(); };
|
||||
nlohmann::json GetAccountById(uint32_t accountId) override { return nlohmann::json::object(); };
|
||||
std::string GetCharactersTable(uint32_t start, uint32_t length, const std::string_view search = "", uint32_t orderColumn = 0, bool orderAsc = true) override { return "{}"; };
|
||||
std::string GetPlayKeysTable(uint32_t start, uint32_t length, const std::string_view search = "", uint32_t orderColumn = 0, bool orderAsc = true) override { return "{}"; };
|
||||
std::string GetPropertiesTable(uint32_t start, uint32_t length, const std::string_view search = "", uint32_t orderColumn = 0, bool orderAsc = true) override { return "{}"; };
|
||||
std::string GetBugReportsTable(uint32_t start, uint32_t length, const std::string_view search = "", uint32_t orderColumn = 0, bool orderAsc = true) override { return "{}"; };
|
||||
|
||||
bool IsNameInUse(const std::string_view name) override { return false; };
|
||||
std::optional<IPropertyContents::Model> GetModel(const LWOOBJID modelID) override { return {}; }
|
||||
|
||||
Reference in New Issue
Block a user