mirror of
https://github.com/EQEmu/Server.git
synced 2026-05-19 13:28:25 +00:00
[Rules] Add rule to allow players to permanently save chat channels to database, up to a limit. (#2706)
* Initial code * Tweak * Rule description tweak * More channel work * More adjustments * Auto-join saved permanent player channels * Fix UCS crash if player has no channels to load from table. * Implemented channel blocking feature * Update database when player channel's owner or password change * First round of requested changes. * Logic tweak to ensure player channels are sets to permanent when appropraite * name_filter table integration and some refactoring * Use new `reserved_channel_names` table to block specific channel names. * Remove some legacy channel block code * Setup required SQL update to create `reserved_channel_names` table. * Update db_update_manifest.txt * Update db_update_manifest.txt * Update chatchannel.cpp * Code review * Database to UCSDatabase * Repository SaveChatChannel * CurrentPlayerChannelCount repository * Cleanup name filter * CreateChannel * Update websocketpp * Increment CURRENT_BINARY_DATABASE_VERSION Set to 9216 * Minor tweaks to blocked channel name checks & other related areas. - Enforce blocked channel names on channel creation. - Also enforce blocked channel names on channel join. - Add channel status check to Debug logging. - Minor formatting adjustments. - Add single quotes to column name value in query. * Minor log change * Increment DB Version * Formatting Tweaks - Made formatting adjustments consistent with KinglyKrab's recommended changes. - This compiles successfully with these changes, but unable to test the changes until this weekend. Co-authored-by: Akkadius <akkadius1@gmail.com>
This commit is contained in:
+140
-28
@@ -49,6 +49,9 @@
|
||||
#include "../common/misc_functions.h"
|
||||
#include "../common/strings.h"
|
||||
#include "chatchannel.h"
|
||||
#include "../common/repositories/chatchannel_reserved_names_repository.h"
|
||||
#include "../common/repositories/chatchannels_repository.h"
|
||||
#include "../common/repositories/name_filter_repository.h"
|
||||
|
||||
extern Clientlist *g_Clientlist;
|
||||
extern std::string GetMailPrefix();
|
||||
@@ -219,51 +222,160 @@ bool UCSDatabase::GetVariable(const char *varname, char *varvalue, uint16 varval
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool UCSDatabase::LoadChatChannels()
|
||||
{
|
||||
|
||||
LoadReservedNamesFromDB();
|
||||
LogInfo("Loading chat channels from the database");
|
||||
|
||||
const std::string query = "SELECT `name`, `owner`, `password`, `minstatus` FROM `chatchannels`";
|
||||
auto results = QueryDatabase(query);
|
||||
auto results = QueryDatabase(query);
|
||||
if (!results.Success()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (auto row = results.begin(); row != results.end(); ++row) {
|
||||
std::string channelName = row[0];
|
||||
std::string channelOwner = row[1];
|
||||
std::string channelPassword = row[2];
|
||||
std::string channel_name = row[0];
|
||||
std::string channel_owner = row[1];
|
||||
std::string channel_password = row[2];
|
||||
auto channel_min_status = row[3];
|
||||
|
||||
ChannelList->CreateChannel(channelName, channelOwner, channelPassword, true, atoi(row[3]));
|
||||
if (!ChannelList->FindChannel(channel_name)) {
|
||||
ChannelList->CreateChannel(channel_name, channel_owner, channel_password, true, atoi(channel_min_status), false);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void UCSDatabase::SetChannelPassword(std::string channelName, std::string password)
|
||||
void UCSDatabase::LoadReservedNamesFromDB()
|
||||
{
|
||||
LogInfo("UCSDatabase::SetChannelPassword([{}], [{}])", channelName.c_str(), password.c_str());
|
||||
ChatChannelList::ClearChannelBlockList();
|
||||
|
||||
std::string query = StringFormat(
|
||||
"UPDATE `chatchannels` SET `password` = '%s' WHERE `name` = '%s'",
|
||||
password.c_str(), channelName.c_str());
|
||||
auto channels = ChatchannelReservedNamesRepository::All(*this);
|
||||
if (channels.empty()) {
|
||||
LogDebug("No reserved names exist in the database...");
|
||||
}
|
||||
|
||||
for (auto &e: channels) {
|
||||
ChatChannelList::AddToChannelBlockList(e.name);
|
||||
LogInfo("Adding channel [{}] to blocked list from database...", e.name);
|
||||
}
|
||||
|
||||
LogInfo("Loaded [{}] reserved channel name(s)", channels.size());
|
||||
}
|
||||
|
||||
bool UCSDatabase::IsChatChannelInDB(const std::string& channel_name)
|
||||
{
|
||||
auto r = ChatchannelsRepository::Count(
|
||||
*this,
|
||||
fmt::format(
|
||||
"name = {}", Strings::Escape(channel_name)
|
||||
)
|
||||
);
|
||||
|
||||
return r > 0;
|
||||
}
|
||||
|
||||
void UCSDatabase::SaveChatChannel(
|
||||
const std::string& channel_name,
|
||||
const std::string& channel_owner,
|
||||
const std::string& channel_password,
|
||||
const uint16& min_status
|
||||
)
|
||||
{
|
||||
auto e = ChatchannelsRepository::GetWhere(
|
||||
*this,
|
||||
fmt::format(
|
||||
"`name` = '{}' LIMIT 1", Strings::Escape(channel_name)
|
||||
)
|
||||
);
|
||||
|
||||
// If channel name is blocked, do not save it to the database
|
||||
if (ChatChannelList::IsOnChannelBlockList(channel_name)) {
|
||||
LogInfo("Channel [{}] already found on the block list, ignoring", channel_name);
|
||||
return;
|
||||
}
|
||||
|
||||
// update if exists, create new if it doesn't
|
||||
auto c = !e.empty() ? e[0] : ChatchannelsRepository::NewEntity();
|
||||
c.name = channel_name;
|
||||
c.owner = channel_owner;
|
||||
c.password = channel_password;
|
||||
c.minstatus = min_status;
|
||||
|
||||
if (e.empty()) {
|
||||
ChatchannelsRepository::InsertOne(*this, c);
|
||||
return;
|
||||
}
|
||||
|
||||
ChatchannelsRepository::UpdateOne(*this, c);
|
||||
}
|
||||
|
||||
void UCSDatabase::DeleteChatChannel(const std::string& channel_name)
|
||||
{
|
||||
ChatchannelsRepository::DeleteWhere(*this, fmt::format("`name` = '{}'", Strings::Escape(channel_name)));
|
||||
LogInfo("Deleting channel [{}] from the database.", channel_name);
|
||||
}
|
||||
|
||||
std::string UCSDatabase::CurrentPlayerChannels(const std::string& player_name) {
|
||||
int current_player_channel_count = CurrentPlayerChannelCount(player_name);
|
||||
if (current_player_channel_count == 0) {
|
||||
return "";
|
||||
}
|
||||
const auto rquery = fmt::format("SELECT GROUP_CONCAT(`name` SEPARATOR ', ') FROM chatchannels WHERE `owner` = '{}'; ", Strings::Escape(player_name));
|
||||
auto results = QueryDatabase(rquery);
|
||||
auto row = results.begin();
|
||||
std::string channels = row[0];
|
||||
LogDebug("Player [{}] has the following permanent channels saved to the database: [{}].", player_name, channels);
|
||||
return channels;
|
||||
}
|
||||
|
||||
int UCSDatabase::CurrentPlayerChannelCount(const std::string& player_name)
|
||||
{
|
||||
return (int) ChatchannelsRepository::Count(*this, fmt::format("`owner` = '{}'", Strings::Escape(player_name)));
|
||||
}
|
||||
|
||||
void UCSDatabase::SetChannelPassword(const std::string& channel_name, const std::string& password)
|
||||
{
|
||||
LogInfo("UCSDatabase::SetChannelPassword([{}], [{}])", channel_name.c_str(), password.c_str());
|
||||
|
||||
std::string query = fmt::format(
|
||||
"UPDATE `chatchannels` SET `password` = '{}' WHERE `name` = '{}'",
|
||||
Strings::Escape(password), Strings::Escape(channel_name));
|
||||
QueryDatabase(query);
|
||||
}
|
||||
|
||||
void UCSDatabase::SetChannelOwner(std::string channelName, std::string owner)
|
||||
void UCSDatabase::SetChannelOwner(const std::string& channel_name, const std::string& owner)
|
||||
{
|
||||
LogInfo("UCSDatabase::SetChannelOwner([{}], [{}])", channelName.c_str(), owner.c_str());
|
||||
LogInfo("Setting channel [{}] owner to [{}]", channel_name, owner);
|
||||
|
||||
std::string query = StringFormat(
|
||||
"UPDATE `chatchannels` SET `owner` = '%s' WHERE `name` = '%s'",
|
||||
owner.c_str(),
|
||||
channelName.c_str()
|
||||
std::string query = fmt::format(
|
||||
"UPDATE `chatchannels` SET `owner` = '{}' WHERE `name` = '{}'",
|
||||
Strings::Escape(owner),
|
||||
Strings::Escape(channel_name)
|
||||
);
|
||||
|
||||
QueryDatabase(query);
|
||||
}
|
||||
|
||||
bool UCSDatabase::CheckChannelNameFilter(const std::string& channel_name)
|
||||
{
|
||||
LogDebug("Checking if [{}] is on the name filter", channel_name);
|
||||
|
||||
// TODO: This should potentially just be pulled into memory at some other point
|
||||
// This if fine for now
|
||||
for (auto &e: NameFilterRepository::All(*this)) {
|
||||
if (Strings::Contains(Strings::ToLower(channel_name), Strings::ToLower(e.name))) {
|
||||
LogInfo("Failed to pass name filter check for [{}] against word [{}]", channel_name, e.name);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
LogDebug("Name Filter Check Passed!");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void UCSDatabase::SendHeaders(Client *client)
|
||||
{
|
||||
|
||||
@@ -356,7 +468,7 @@ void UCSDatabase::SendHeaders(Client *client)
|
||||
|
||||
}
|
||||
|
||||
void UCSDatabase::SendBody(Client *client, int messageNumber)
|
||||
void UCSDatabase::SendBody(Client *client, const int& messageNumber)
|
||||
{
|
||||
|
||||
int characterID = FindCharacter(client->MailBoxName().c_str());
|
||||
@@ -412,11 +524,11 @@ void UCSDatabase::SendBody(Client *client, int messageNumber)
|
||||
}
|
||||
|
||||
bool UCSDatabase::SendMail(
|
||||
std::string recipient,
|
||||
std::string from,
|
||||
std::string subject,
|
||||
std::string body,
|
||||
std::string recipientsString
|
||||
const std::string& recipient,
|
||||
const std::string& from,
|
||||
const std::string& subject,
|
||||
const std::string& body,
|
||||
const std::string& recipientsString
|
||||
)
|
||||
{
|
||||
|
||||
@@ -484,7 +596,7 @@ bool UCSDatabase::SendMail(
|
||||
return true;
|
||||
}
|
||||
|
||||
void UCSDatabase::SetMessageStatus(int messageNumber, int status)
|
||||
void UCSDatabase::SetMessageStatus(const int& messageNumber, const int& status)
|
||||
{
|
||||
|
||||
LogInfo("SetMessageStatus [{}] [{}]", messageNumber, status);
|
||||
@@ -557,7 +669,7 @@ void UCSDatabase::ExpireMail()
|
||||
}
|
||||
}
|
||||
|
||||
void UCSDatabase::AddFriendOrIgnore(int charID, int type, std::string name)
|
||||
void UCSDatabase::AddFriendOrIgnore(const int& charID, const int& type, const std::string& name)
|
||||
{
|
||||
std::string query = StringFormat(
|
||||
"INSERT INTO `friends` (`charid`, `type`, `name`) "
|
||||
@@ -579,7 +691,7 @@ void UCSDatabase::AddFriendOrIgnore(int charID, int type, std::string name)
|
||||
}
|
||||
}
|
||||
|
||||
void UCSDatabase::RemoveFriendOrIgnore(int charID, int type, std::string name)
|
||||
void UCSDatabase::RemoveFriendOrIgnore(const int& charID, const int& type, const std::string& name)
|
||||
{
|
||||
std::string query = StringFormat(
|
||||
"DELETE FROM `friends` WHERE `charid` = %i AND `type` = %i AND `name` = '%s'",
|
||||
@@ -600,7 +712,7 @@ void UCSDatabase::RemoveFriendOrIgnore(int charID, int type, std::string name)
|
||||
}
|
||||
}
|
||||
|
||||
void UCSDatabase::GetFriendsAndIgnore(int charID, std::vector<std::string> &friends, std::vector<std::string> &ignorees)
|
||||
void UCSDatabase::GetFriendsAndIgnore(const int& charID, std::vector<std::string> &friends, std::vector<std::string> &ignorees)
|
||||
{
|
||||
|
||||
std::string query = StringFormat("select `type`, `name` FROM `friends` WHERE `charid`=%i", charID);
|
||||
|
||||
Reference in New Issue
Block a user