eqemu-server/zone/gm_commands/databuckets.cpp
Alex c84df0d5ba
Some checks are pending
Build / Linux (push) Waiting to run
Build / Windows (push) Waiting to run
Build Improvements (#5033)
* Start rewrite, add vcpkg

* Simple vcpkg manifest, will almost certainly need tweaking

* Remove cmake ext we wont be using anymore

* Update vcpkg to no longer be from 2022, update cmake lists (wip)

* Add finds to the toplevel cmakelists

* WIP, luabind and perlbind build.  Common only partially builds.

* Fix common build.

* shared_memory compiles

* client files compile

* Tests and more cmake version updates

* World, had to swap out zlib-ng for now because it wasn't playing nicely along side the zlib install.  May revisit.

* UCS compiles now too!

* queryserv and eqlaunch

* loginserver works

* Zone works but is messy, tomorrow futher cleanup!

* Cleanup main file

* remove old zlibng, remove perlwrap, remove hc

* More cleanup

* vcpkg baseline set for CI

* Remove pkg-config, it's the suggested way to use luajit with vcpkg but it causes issues with CI and might be a pain point for windows users

* Actually add file

* Set perlbind include dir

* Perl link got lost

* PERL_SET_INTERP causes an issue on newer versions of perl on windows because a symbol is not properly exported in their API, change the lines so it's basically what it used to be

* Remove static unix linking, we dont do automated released anymore and this was tightly coupled to that.  Can explore this again if we decide to change that.

* Remove unused submodules, set cmake policy for boost

* Fix some cereal includes

* Improve some boilerplate, I'd still like to do better about getting linker stuff set.

* Going through and cleaning up the build.

* Fix world, separate out data_buckets.

* add fixes for other servers

* fix zone

* Fix client files, loginserver and tests

* Newer versions of libmariadb default to tls forced on, return to the default of not forcing that.
auto_login were breaking on linux builds
loginserver wasn't setting proper openssl compile flag

* Move set out of a giant cpp file include.

* Convert show

* convert find

* Add uuid to unix builds

* Remove some cpp includes.

* Restructure to remove more things.

* change db update manifest to header
change build yml

* Move world CLI include cpps to cmake.

* Move zone cli out of source and into cmake

* Sidecar stuff wont directly include cpp files now too.

* Fix uuid-dev missing on linux runner

* Reorg common cmake file

* Some cleanup

* Fix libsodium support (oops). Fix perl support (more oops)

* Change doc

---------

Co-authored-by: KimLS <KimLS@peqtgc.com>
2025-12-13 19:56:37 -08:00

263 lines
6.5 KiB
C++
Executable File

#include "../client.h"
#include "../../common/data_bucket.h"
#include "../dialogue_window.h"
#include "../../common/repositories/data_buckets_repository.h"
void SendDataBucketsSubCommands(Client *c)
{
c->Message(Chat::White, "Usage: #databuckets delete [Key] [Character ID] [NPC ID] [Bot ID]");
c->Message(Chat::White, "Usage: #databuckets edit [Key] [Character ID] [NPC ID] [Bot ID] [Value] [Expires]");
c->Message(Chat::White, "Usage: #databuckets view [Partial Key] [Character ID] [NPC ID] [Bot ID]");
c->Message(Chat::White, "Note: Character ID, NPC ID, and Bot ID are optional if not needed, if needed they are required for specificity");
c->Message(Chat::White, "Note: Edit requires Character ID, NPC ID, Bot ID, and Value, Expires is optional and does not modify the existing expiration time if not provided");
}
void command_databuckets(Client *c, const Seperator *sep)
{
const int arguments = sep->argnum;
if (!arguments) {
SendDataBucketsSubCommands(c);
return;
}
const bool is_delete = !strcasecmp(sep->arg[1], "delete");
const bool is_edit = !strcasecmp(sep->arg[1], "edit");
const bool is_view = !strcasecmp(sep->arg[1], "view");
if (
!is_delete &&
!is_edit &&
!is_view
) {
SendDataBucketsSubCommands(c);
return;
}
if (is_delete) {
if (arguments < 2) {
SendDataBucketsSubCommands(c);
return;
}
const std::string& key_filter = sep->arg[2];
const uint32 character_id = sep->IsNumber(3) ? Strings::ToUnsignedInt(sep->arg[3]) : 0;
const uint32 npc_id = sep->IsNumber(4) ? Strings::ToUnsignedInt(sep->arg[4]) : 0;
const uint32 bot_id = sep->IsNumber(5) ? Strings::ToUnsignedInt(sep->arg[5]) : 0;
if (
!character_id &&
!npc_id &&
!bot_id
) {
if (!DataBucket::DeleteData(&database, key_filter)) {
c->Message(
Chat::White,
fmt::format(
"An error occurred deleting data bucket '{}'.",
key_filter
).c_str()
);
return;
}
c->Message(
Chat::White,
fmt::format(
"Data bucket '{}' deleted.",
key_filter
).c_str()
);
} else {
DataBucketKey k = {};
k.key = key_filter;
k.character_id = character_id;
k.npc_id = npc_id;
k.bot_id = bot_id;
if (!DataBucket::DeleteData(&database, k)) {
c->Message(
Chat::White,
fmt::format(
"An error occurred deleting data bucket '{}'.",
key_filter
).c_str()
);
return;
}
c->Message(
Chat::White,
fmt::format(
"Data bucket '{}' deleted.",
key_filter
).c_str()
);
}
} else if (is_edit) {
if (arguments < 6) {
SendDataBucketsSubCommands(c);
return;
}
const std::string& key_filter = sep->arg[2];
const std::string& value = sep->arg[6];
const uint32 character_id = sep->IsNumber(3) ? Strings::ToUnsignedInt(sep->arg[3]) : 0;
const uint32 npc_id = sep->IsNumber(4) ? Strings::ToUnsignedInt(sep->arg[4]) : 0;
const uint32 bot_id = sep->IsNumber(5) ? Strings::ToUnsignedInt(sep->arg[5]) : 0;
const uint32 expires = arguments > 6 && sep->IsNumber(7) ? Strings::ToUnsignedInt(sep->arg[7]) : 0;
DataBucketKey k = {};
k.key = key_filter;
k.character_id = character_id;
k.npc_id = npc_id;
k.bot_id = bot_id;
k.value = value;
if (arguments > 6) {
k.expires = expires;
}
const std::string& expires_string = expires == 0 ? "Never" : std::to_string(expires);
DataBucket::SetData(&database, k);
c->Message(
Chat::White,
fmt::format(
"Bucket Edited | Key: {} Value: {} Expires: {} Character ID: {} NPC ID: {} Bot ID: {}",
key_filter,
value,
expires_string,
character_id,
npc_id,
bot_id
).c_str()
);
} else if (is_view) {
if (arguments < 2) {
SendDataBucketsSubCommands(c);
return;
}
const std::string& key_filter = sep->arg[2];
const uint32 character_id = sep->IsNumber(3) ? Strings::ToUnsignedInt(sep->arg[3]) : 0;
const uint32 npc_id = sep->IsNumber(4) ? Strings::ToUnsignedInt(sep->arg[4]) : 0;
const uint32 bot_id = sep->IsNumber(5) ? Strings::ToUnsignedInt(sep->arg[5]) : 0;
std::string where_filter = fmt::format(
"`key` LIKE '%{}%'",
Strings::Escape(key_filter)
);
if (character_id) {
where_filter += fmt::format(
" AND `character_id` = {}",
character_id
);
}
if (npc_id) {
where_filter += fmt::format(
" AND `npc_id` = {}",
npc_id
);
}
if (bot_id) {
where_filter += fmt::format(
" AND `bot_id` = {}",
bot_id
);
}
where_filter += " LIMIT 50";
const auto& l = DataBucketsRepository::GetWhere(database, where_filter);
if (l.empty()) {
c->Message(
Chat::White,
fmt::format(
"No data buckets found matching '{}'.",
key_filter
).c_str()
);
return;
}
std::string window_text = DialogueWindow::TableRow(
DialogueWindow::TableCell("ID") +
DialogueWindow::TableCell("Key") +
DialogueWindow::TableCell("Value") +
DialogueWindow::TableCell("Expires") +
DialogueWindow::TableCell("Character ID") +
DialogueWindow::TableCell("NPC ID") +
DialogueWindow::TableCell("Bot ID")
);
uint16 bucket_count = 0;
uint16 bucket_number = 1;
for (const auto& e : l) {
const std::string& expires_string = e.expires == 0 ? "Never" : std::to_string(e.expires);
window_text += DialogueWindow::TableRow(
DialogueWindow::TableCell(std::to_string(e.id)) +
DialogueWindow::TableCell(e.key_) +
DialogueWindow::TableCell(e.value) +
DialogueWindow::TableCell(expires_string) +
DialogueWindow::TableCell(std::to_string(e.character_id)) +
DialogueWindow::TableCell(std::to_string(e.npc_id)) +
DialogueWindow::TableCell(std::to_string(e.bot_id))
);
const std::string& delete_link = Saylink::Silent(
fmt::format(
"#databuckets delete {} {} {} {}",
e.key_,
e.character_id,
e.npc_id,
e.bot_id
),
"Delete"
);
c->Message(
Chat::White,
fmt::format(
"Bucket {} | Key: {} | Value: {} | Character ID: {} NPC ID: {} Bot ID: {} | {}",
bucket_number,
e.key_,
e.value,
e.character_id,
e.npc_id,
e.bot_id,
delete_link
).c_str()
);
bucket_count++;
bucket_number++;
}
window_text = DialogueWindow::Table(window_text);
c->SendPopupToClient("Data Buckets", window_text.c_str());
const std::string& response = fmt::format(
"Found {} data bucket{} matching '{}'{}.",
bucket_count,
bucket_count != 1 ? "s" : "",
key_filter,
bucket_count == 50 ? ", max reached" : ""
);
c->Message(Chat::White, response.c_str());
}
}