Add best friend check and complete blacklist

This commit is contained in:
Jett 2022-07-17 09:40:34 +01:00
parent fab8a1e982
commit 945e572493
6 changed files with 82 additions and 32 deletions

View File

@ -19,12 +19,12 @@ dChatFilter::dChatFilter(const std::string& filepath, bool dontGenerateDCF) {
m_DontGenerateDCF = dontGenerateDCF; m_DontGenerateDCF = dontGenerateDCF;
if (!BinaryIO::DoesFileExist(filepath + ".dcf") || m_DontGenerateDCF) { if (!BinaryIO::DoesFileExist(filepath + ".dcf") || m_DontGenerateDCF) {
ReadWordlistPlaintext(filepath + ".txt"); ReadWordlistPlaintext(filepath + ".txt", true);
if (!m_DontGenerateDCF) ExportWordlistToDCF(filepath + ".dcf"); if (!m_DontGenerateDCF) ExportWordlistToDCF(filepath + ".dcf", true);
} }
else if (!ReadWordlistDCF(filepath + ".dcf", true)) { else if (!ReadWordlistDCF(filepath + ".dcf", true)) {
ReadWordlistPlaintext(filepath + ".txt"); ReadWordlistPlaintext(filepath + ".txt", true);
ExportWordlistToDCF(filepath + ".dcf"); ExportWordlistToDCF(filepath + ".dcf", true);
} }
if (BinaryIO::DoesFileExist("blacklist.dcf")) { if (BinaryIO::DoesFileExist("blacklist.dcf")) {
@ -48,14 +48,15 @@ dChatFilter::~dChatFilter() {
m_NoNoWords.clear(); m_NoNoWords.clear();
} }
void dChatFilter::ReadWordlistPlaintext(const std::string& filepath) { void dChatFilter::ReadWordlistPlaintext(const std::string& filepath, bool whiteList) {
std::ifstream file(filepath); std::ifstream file(filepath);
if (file) { if (file) {
std::string line; std::string line;
while (std::getline(file, line)) { while (std::getline(file, line)) {
line.erase(std::remove(line.begin(), line.end(), '\r'), line.end()); line.erase(std::remove(line.begin(), line.end(), '\r'), line.end());
std::transform(line.begin(), line.end(), line.begin(), ::tolower); //Transform to lowercase std::transform(line.begin(), line.end(), line.begin(), ::tolower); //Transform to lowercase
m_YesYesWords.push_back(CalculateHash(line)); if (whiteList) m_YesYesWords.push_back(CalculateHash(line));
else m_NoNoWords.push_back(CalculateHash(line));
} }
} }
} }
@ -94,14 +95,14 @@ bool dChatFilter::ReadWordlistDCF(const std::string& filepath, bool whiteList) {
return false; return false;
} }
void dChatFilter::ExportWordlistToDCF(const std::string& filepath) { void dChatFilter::ExportWordlistToDCF(const std::string& filepath, bool whiteList) {
std::ofstream file(filepath, std::ios::binary | std::ios_base::out); std::ofstream file(filepath, std::ios::binary | std::ios_base::out);
if (file) { if (file) {
BinaryIO::BinaryWrite(file, uint32_t(dChatFilterDCF::header)); BinaryIO::BinaryWrite(file, uint32_t(dChatFilterDCF::header));
BinaryIO::BinaryWrite(file, uint32_t(dChatFilterDCF::formatVersion)); BinaryIO::BinaryWrite(file, uint32_t(dChatFilterDCF::formatVersion));
BinaryIO::BinaryWrite(file, size_t(m_YesYesWords.size())); BinaryIO::BinaryWrite(file, size_t(whiteList ? m_YesYesWords.size() : m_NoNoWords.size()));
for (size_t word : m_YesYesWords) { for (size_t word : whiteList ? m_YesYesWords : m_NoNoWords) {
BinaryIO::BinaryWrite(file, word); BinaryIO::BinaryWrite(file, word);
} }
@ -128,21 +129,18 @@ std::vector<std::string> dChatFilter::IsSentenceOkay(const std::string& message,
size_t hash = CalculateHash(segment); size_t hash = CalculateHash(segment);
if (std::find(m_UserUnapprovedWordCache.begin(), m_UserUnapprovedWordCache.end(), hash) != m_UserUnapprovedWordCache.end()) { if (std::find(m_UserUnapprovedWordCache.begin(), m_UserUnapprovedWordCache.end(), hash) != m_UserUnapprovedWordCache.end() && whiteList) {
listOfBadSegments.push_back(originalSegment); // found word that isn't ok, just deny this code works for both white and black list listOfBadSegments.push_back(originalSegment);
} }
if (!IsInWordlist(hash, whiteList)) { if (std::find(m_YesYesWords.begin(), m_YesYesWords.end(), hash) == m_YesYesWords.end() && whiteList) {
if (whiteList) { m_UserUnapprovedWordCache.push_back(hash);
m_UserUnapprovedWordCache.push_back(hash); listOfBadSegments.push_back(originalSegment);
listOfBadSegments.push_back(originalSegment);
}
} }
else {
if (!whiteList) { if (std::find(m_NoNoWords.begin(), m_NoNoWords.end(), hash) != m_NoNoWords.end() && !whiteList) {
m_UserUnapprovedWordCache.push_back(hash); m_UserUnapprovedWordCache.push_back(hash);
listOfBadSegments.push_back(originalSegment); listOfBadSegments.push_back(originalSegment);
}
} }
} }
@ -155,10 +153,4 @@ size_t dChatFilter::CalculateHash(const std::string& word) {
size_t value = hash(word); size_t value = hash(word);
return value; return value;
}
bool dChatFilter::IsInWordlist(size_t word, bool whiteList) {
auto* list = whiteList ? &m_YesYesWords : &m_NoNoWords;
return std::find(list->begin(), list->end(), word) != list->end();
} }

View File

@ -20,9 +20,9 @@ public:
dChatFilter(const std::string& filepath, bool dontGenerateDCF); dChatFilter(const std::string& filepath, bool dontGenerateDCF);
~dChatFilter(); ~dChatFilter();
void ReadWordlistPlaintext(const std::string& filepath); void ReadWordlistPlaintext(const std::string& filepath, bool whiteList);
bool ReadWordlistDCF(const std::string& filepath, bool whiteList); bool ReadWordlistDCF(const std::string& filepath, bool whiteList);
void ExportWordlistToDCF(const std::string& filepath); void ExportWordlistToDCF(const std::string& filepath, bool whiteList);
std::vector<std::string> IsSentenceOkay(const std::string& message, int gmLevel, bool whiteList = true); std::vector<std::string> IsSentenceOkay(const std::string& message, int gmLevel, bool whiteList = true);
private: private:
@ -33,5 +33,4 @@ private:
//Private functions: //Private functions:
size_t CalculateHash(const std::string& word); size_t CalculateHash(const std::string& word);
bool IsInWordlist(size_t word, bool whiteList);
}; };

View File

@ -18,6 +18,8 @@ User::User(const SystemAddress& sysAddr, const std::string& username, const std:
m_SystemAddress = sysAddr; m_SystemAddress = sysAddr;
m_Username = username; m_Username = username;
m_LoggedInCharID = 0; m_LoggedInCharID = 0;
m_IsBestFriendMap = std::unordered_map<std::string, bool>();
//HACK HACK HACK //HACK HACK HACK
//This needs to be re-enabled / updated whenever the mute stuff is moved to another table. //This needs to be re-enabled / updated whenever the mute stuff is moved to another table.

View File

@ -42,6 +42,9 @@ public:
bool GetLastChatMessageApproved() { return m_LastChatMessageApproved; } bool GetLastChatMessageApproved() { return m_LastChatMessageApproved; }
void SetLastChatMessageApproved(bool approved) { m_LastChatMessageApproved = approved; } void SetLastChatMessageApproved(bool approved) { m_LastChatMessageApproved = approved; }
std::unordered_map<std::string, bool> GetIsBestFriendMap() { return m_IsBestFriendMap; }
void SetIsBestFriendMap(std::unordered_map<std::string, bool> mapToSet) { m_IsBestFriendMap = mapToSet; }
bool GetIsMuted() const; bool GetIsMuted() const;
time_t GetMuteExpire() const; time_t GetMuteExpire() const;
@ -63,6 +66,8 @@ private:
std::vector<Character*> m_Characters; std::vector<Character*> m_Characters;
LWOOBJID m_LoggedInCharID; LWOOBJID m_LoggedInCharID;
std::unordered_map<std::string, bool> m_IsBestFriendMap;
bool m_LastChatMessageApproved = false; bool m_LastChatMessageApproved = false;
int m_AmountOfTimesOutOfSync = 0; int m_AmountOfTimesOutOfSync = 0;
const int m_MaxDesyncAllowed = 12; const int m_MaxDesyncAllowed = 12;

View File

@ -30,6 +30,9 @@
#include "VehiclePhysicsComponent.h" #include "VehiclePhysicsComponent.h"
#include "dConfig.h" #include "dConfig.h"
#include "CharacterComponent.h" #include "CharacterComponent.h"
#include "Database.h"
void ClientPackets::HandleChatMessage(const SystemAddress& sysAddr, Packet* packet) { void ClientPackets::HandleChatMessage(const SystemAddress& sysAddr, Packet* packet) {
User* user = UserManager::Instance()->GetUser(sysAddr); User* user = UserManager::Instance()->GetUser(sysAddr);
@ -276,7 +279,6 @@ void ClientPackets::HandleChatModerationRequest(const SystemAddress& sysAddr, Pa
std::string message = ""; std::string message = "";
stream.Read(chatLevel); stream.Read(chatLevel);
printf("%d", chatLevel);
stream.Read(requestID); stream.Read(requestID);
for (uint32_t i = 0; i < 42; ++i) { for (uint32_t i = 0; i < 42; ++i) {
@ -285,6 +287,12 @@ void ClientPackets::HandleChatModerationRequest(const SystemAddress& sysAddr, Pa
receiver.push_back(static_cast<uint8_t>(character)); receiver.push_back(static_cast<uint8_t>(character));
} }
if (!receiver.empty()) {
if (std::string(receiver.c_str(), 4) == "[GM]") {
receiver = std::string(receiver.c_str() + 4, receiver.size() - 4);
}
}
stream.Read(messageLength); stream.Read(messageLength);
for (uint32_t i = 0; i < messageLength; ++i) { for (uint32_t i = 0; i < messageLength; ++i) {
uint16_t character; uint16_t character;
@ -292,8 +300,52 @@ void ClientPackets::HandleChatModerationRequest(const SystemAddress& sysAddr, Pa
message.push_back(static_cast<uint8_t>(character)); message.push_back(static_cast<uint8_t>(character));
} }
bool isBestFriend = false;
if (chatLevel == 1) {
// Private chat
LWOOBJID idOfReceiver = LWOOBJID_EMPTY;
{
sql::PreparedStatement* stmt = Database::CreatePreppedStmt("SELECT name FROM charinfo WHERE name = ?");
stmt->setString(1, receiver);
sql::ResultSet* res = stmt->executeQuery();
if (res->next()) {
idOfReceiver = res->getInt("id");
}
}
if (user->GetIsBestFriendMap().find(receiver) == user->GetIsBestFriendMap().end() && idOfReceiver != LWOOBJID_EMPTY) {
sql::PreparedStatement* stmt = Database::CreatePreppedStmt("SELECT * FROM friends WHERE (player_id = ? AND friend_id = ?) OR (player_id = ? AND friend_id = ?) LIMIT 1;");
stmt->setInt(1, entity->GetObjectID());
stmt->setInt(2, idOfReceiver);
stmt->setInt(3, idOfReceiver);
stmt->setInt(4, entity->GetObjectID());
sql::ResultSet* res = stmt->executeQuery();
if (res->next()) {
isBestFriend = res->getInt("best_friend") == 3;
}
if (isBestFriend) {
auto tmpBestFriendMap = user->GetIsBestFriendMap();
tmpBestFriendMap[receiver] = true;
user->SetIsBestFriendMap(tmpBestFriendMap);
}
delete res;
delete stmt;
}
else if (user->GetIsBestFriendMap().find(receiver) != user->GetIsBestFriendMap().end()) {
isBestFriend = true;
}
}
std::unordered_map<char, char> unacceptedItems; std::unordered_map<char, char> unacceptedItems;
std::vector<std::string> segments = Game::chatFilter->IsSentenceOkay(message, entity->GetGMLevel()); std::vector<std::string> segments = Game::chatFilter->IsSentenceOkay(message, entity->GetGMLevel(), !(isBestFriend && chatLevel == 1));
bool bAllClean = segments.empty(); bool bAllClean = segments.empty();

Binary file not shown.