From ab970764fcc3849f094c6473681b3eb7af2548b0 Mon Sep 17 00:00:00 2001 From: gir489 <100792176+gir489returns@users.noreply.github.com> Date: Thu, 7 Dec 2023 14:04:00 -0500 Subject: [PATCH] Added more spam messages to the filter. (#2488) * Added more spam messages to the filter. * Removed duplicate remote control vehicle button from the player vehicle menu. * Added heuristical spam detector. * Fixed clock in spam logger. * Added date output to the chat logger. * Added a message to show the user when someone is spamming. More static text translations. * Removed redundant mobile global in scr_globals.hpp. * Added a spam reason to the spam logger. * Added team/all to the chat logger. Added a logger call for the user's chats. --- src/backend/looped/tunables/disable_phone.cpp | 4 +- src/core/enums.hpp | 7 +++ src/core/scr_globals.hpp | 2 - src/core/settings.hpp | 5 +- src/gta/net_game_event.hpp | 12 ++--- src/hooks/misc/send_chat_message.cpp | 4 ++ src/hooks/protections/receive_net_message.cpp | 12 +++-- src/native_hooks/shop_controller.hpp | 2 +- .../context_menu/context_menu_service.hpp | 12 ++--- src/services/players/player.hpp | 1 + src/util/spam.hpp | 49 ++++++++++++++++--- src/views/network/view_network.cpp | 6 +++ src/views/players/player/player_vehicle.cpp | 2 - 13 files changed, 87 insertions(+), 31 deletions(-) diff --git a/src/backend/looped/tunables/disable_phone.cpp b/src/backend/looped/tunables/disable_phone.cpp index ad6c043f..49fae5e8 100644 --- a/src/backend/looped/tunables/disable_phone.cpp +++ b/src/backend/looped/tunables/disable_phone.cpp @@ -10,12 +10,12 @@ namespace big virtual void on_tick() override { - *scr_globals::mobile.as() = TRUE; + *scr_globals::transaction_overlimit.as() = TRUE; } virtual void on_disable() override { - *scr_globals::mobile.as() = FALSE; + *scr_globals::transaction_overlimit.as() = FALSE; } }; diff --git a/src/core/enums.hpp b/src/core/enums.hpp index 5b0008b2..384b91aa 100644 --- a/src/core/enums.hpp +++ b/src/core/enums.hpp @@ -378,4 +378,11 @@ namespace big RELEASE = WM_KEYUP, DOWN = WM_KEYDOWN }; + + enum SpamReason : int + { + NOT_A_SPAMMER, + STATIC_DETECTION, + TIMER_DETECTION + }; } diff --git a/src/core/scr_globals.hpp b/src/core/scr_globals.hpp index 77df6d0f..8759752c 100644 --- a/src/core/scr_globals.hpp +++ b/src/core/scr_globals.hpp @@ -41,8 +41,6 @@ namespace big::scr_globals static inline const script_global dance_state(1950837); - static inline const script_global mobile(20483); - static inline const script_global transaction_overlimit(20483); static inline const script_global stats(2359296); diff --git a/src/core/settings.hpp b/src/core/settings.hpp index e5302245..7fbe2bda 100644 --- a/src/core/settings.hpp +++ b/src/core/settings.hpp @@ -402,6 +402,9 @@ namespace big bool allow_friends_into_locked_session = false; bool trust_friends = false; bool trust_session = false; + bool use_spam_timer = true; + float spam_timer = 2.5f; + int spam_length = 55; const char chat_command_prefix = '/'; const char chat_output_prefix = '>'; @@ -442,7 +445,7 @@ namespace big bool fast_join = false; - NLOHMANN_DEFINE_TYPE_INTRUSIVE(session, log_chat_messages, log_text_messages, decloak_players, force_session_host, force_script_host, player_magnet_enabled, player_magnet_count, is_team, join_in_sctv_slots, kick_chat_spammers, kick_host_when_forcing_host, explosion_karma, damage_karma, disable_traffic, disable_peds, force_thunder, block_ceo_money, randomize_ceo_colors, block_jobs, block_muggers, block_ceo_raids, send_to_apartment_idx, send_to_warehouse_idx, chat_commands, chat_command_default_access_level, show_cheating_message, anonymous_bounty, lock_session, fast_join, unhide_players_from_player_list, allow_friends_into_locked_session, trust_friends) + NLOHMANN_DEFINE_TYPE_INTRUSIVE(session, log_chat_messages, log_text_messages, decloak_players, force_session_host, force_script_host, player_magnet_enabled, player_magnet_count, is_team, join_in_sctv_slots, kick_chat_spammers, kick_host_when_forcing_host, explosion_karma, damage_karma, disable_traffic, disable_peds, force_thunder, block_ceo_money, randomize_ceo_colors, block_jobs, block_muggers, block_ceo_raids, send_to_apartment_idx, send_to_warehouse_idx, chat_commands, chat_command_default_access_level, show_cheating_message, anonymous_bounty, lock_session, fast_join, unhide_players_from_player_list, allow_friends_into_locked_session, trust_friends, use_spam_timer, spam_timer, spam_length) } session{}; struct settings diff --git a/src/gta/net_game_event.hpp b/src/gta/net_game_event.hpp index 0f12398f..f7214075 100644 --- a/src/gta/net_game_event.hpp +++ b/src/gta/net_game_event.hpp @@ -83,17 +83,17 @@ namespace rage } return false; } - bool WriteBool(bool integer) + bool WriteBool(bool boolean) { - return big::g_pointers->m_gta.m_write_bitbuf_bool(this, integer, 1); + return big::g_pointers->m_gta.m_write_bitbuf_bool(this, boolean, 1); } - bool ReadBool(bool* integer) + bool ReadBool(bool* boolean) { - return big::g_pointers->m_gta.m_read_bitbuf_bool(this, integer, 1); + return big::g_pointers->m_gta.m_read_bitbuf_bool(this, boolean, 1); } - bool ReadPeerId(uint64_t* integer) + bool ReadPeerId(uint64_t* peer_id) { - return this->ReadQWord(integer, 0x40); + return this->ReadQWord(peer_id, 0x40); } uint64_t ReadBits(size_t numBits) { diff --git a/src/hooks/misc/send_chat_message.cpp b/src/hooks/misc/send_chat_message.cpp index 8638825a..2ecdf76d 100644 --- a/src/hooks/misc/send_chat_message.cpp +++ b/src/hooks/misc/send_chat_message.cpp @@ -5,6 +5,7 @@ #include "hooking.hpp" #include "packet.hpp" #include "services/players/player_service.hpp" +#include "util/spam.hpp" namespace big { @@ -27,6 +28,9 @@ namespace big gamer_handle_serialize(g_player_service->get_self()->get_net_data()->m_gamer_handle, msg.m_buffer); msg.write(is_team, 1); + if (g.session.log_chat_messages) + spam::log_chat(message, g_player_service->get_self(), SpamReason::NOT_A_SPAMMER, is_team); + if (*g_pointers->m_gta.m_is_session_started) for (auto& player : g_player_service->players()) if (player.second && player.second->is_valid()) diff --git a/src/hooks/protections/receive_net_message.cpp b/src/hooks/protections/receive_net_message.cpp index b5d65ca0..5502c5ac 100644 --- a/src/hooks/protections/receive_net_message.cpp +++ b/src/hooks/protections/receive_net_message.cpp @@ -107,14 +107,18 @@ namespace big { char message[256]; buffer.ReadString(message, 256); + bool is_team; + buffer.ReadBool(&is_team); if (player->is_spammer) return true; - if (spam::is_text_spam(message)) + if (auto spam_reason = spam::is_text_spam(message, player)) { if (g.session.log_chat_messages) - spam::log_chat(message, player, true); + spam::log_chat(message, player, spam_reason, is_team); + g_notification_service->push("PROTECTIONS"_T.data(), + std::format("{} {}", player->get_name(), "IS_A_SPAMMER"_T.data())); player->is_spammer = true; if (g.session.kick_chat_spammers && !(player->is_trusted || (player->is_friend() && g.session.trust_friends) || g.session.trust_session)) @@ -131,7 +135,7 @@ namespace big else { if (g.session.log_chat_messages) - spam::log_chat(message, player, false); + spam::log_chat(message, player, SpamReason::NOT_A_SPAMMER, is_team); if (g.session.chat_commands && message[0] == g.session.chat_command_prefix) command::process(std::string(message + 1), std::make_shared(player)); @@ -204,7 +208,7 @@ namespace big if (reason == KickReason::VOTED_OUT) { - g_notification_service->push_warning("Protections", "You have been kicked by the host"); + g_notification_service->push_warning("PROTECTIONS"_T.data(), "YOU_HAVE_BEEN_KICKED"_T.data()); return true; } diff --git a/src/native_hooks/shop_controller.hpp b/src/native_hooks/shop_controller.hpp index 52047379..34f6e766 100644 --- a/src/native_hooks/shop_controller.hpp +++ b/src/native_hooks/shop_controller.hpp @@ -13,7 +13,7 @@ namespace big if (g.notifications.transaction_rate_limit.log) LOG(WARNING) << "Received transaction rate limit"; if (g.notifications.transaction_rate_limit.notify) - g_notification_service->push_warning("Transaction Rate Limit", "You're receiving transaction rate limits, whatever you're doing do it less."); + g_notification_service->push_warning("TRANSACTION_RATE_LIMIT"_T.data(), "TRANSACTION_RATE_LIMIT_MESSAGE"_T.data()); *scr_globals::transaction_overlimit.as() = FALSE; diff --git a/src/services/context_menu/context_menu_service.hpp b/src/services/context_menu/context_menu_service.hpp index eb4d3402..a6966d4e 100644 --- a/src/services/context_menu/context_menu_service.hpp +++ b/src/services/context_menu/context_menu_service.hpp @@ -71,7 +71,7 @@ namespace big VEHICLE::SET_VEHICLE_ENGINE_ON(m_handle, false, true, false); } else - g_notification_service->push_warning("Toxic", "Failed to take control of vehicle."); + g_notification_service->push_warning("TOXIC"_T.data(), "VEHICLE_FAILED_CONTROL"_T.data()); }}, {"FIX VEHICLE", [this] { @@ -83,7 +83,7 @@ namespace big VEHICLE::SET_VEHICLE_DIRT_LEVEL(m_handle, 0.f); } else - g_notification_service->push_warning("Warning", "Failed to take control of vehicle."); + g_notification_service->push_warning("WARNING"_T.data(), "VEHICLE_FAILED_CONTROL"_T.data()); }}, {"BURST TIRES", [this] { @@ -97,7 +97,7 @@ namespace big } } else - g_notification_service->push_warning("Toxic", "Failed to take control of vehicle."); + g_notification_service->push_warning("TOXIC"_T.data(), "VEHICLE_FAILED_CONTROL"_T.data()); }}, {"HALT", [this] { @@ -106,7 +106,7 @@ namespace big VEHICLE::BRING_VEHICLE_TO_HALT(m_handle, 1, 5, true); } else - g_notification_service->push_warning("Toxic", "Failed to take control of vehicle."); + g_notification_service->push_warning("TOXIC"_T.data(), "VEHICLE_FAILED_CONTROL"_T.data()); }}, {"COPY VEHICLE", [this] { @@ -119,14 +119,14 @@ namespace big if (entity::take_control_of(m_handle)) VEHICLE::SET_VEHICLE_FORWARD_SPEED(m_handle, 79); else - g_notification_service->push_warning("Toxic", "Failed to take control of vehicle."); + g_notification_service->push_warning("TOXIC"_T.data(), "VEHICLE_FAILED_CONTROL"_T.data()); }}, {"LAUNCH", [this] { if (entity::take_control_of(m_handle)) ENTITY::APPLY_FORCE_TO_ENTITY(m_handle, 1, 0.f, 0.f, 50000.f, 0.f, 0.f, 0.f, 0, 0, 1, 1, 0, 1); else - g_notification_service->push_warning("Toxic", "Failed to take control of vehicle."); + g_notification_service->push_warning("TOXIC"_T.data(), "VEHICLE_FAILED_CONTROL"_T.data()); }}, {"EJECT", [this] { diff --git a/src/services/players/player.hpp b/src/services/players/player.hpp index 2b3ed80d..f95b3037 100644 --- a/src/services/players/player.hpp +++ b/src/services/players/player.hpp @@ -88,6 +88,7 @@ namespace big std::optional player_time_value; std::optional> player_time_value_received_time; std::optional time_difference; + std::optional> last_message_time; uint32_t num_time_syncs_sent = 9999; bool block_explosions = false; diff --git a/src/util/spam.hpp b/src/util/spam.hpp index 18461f4e..32b629c0 100644 --- a/src/util/spam.hpp +++ b/src/util/spam.hpp @@ -1,6 +1,7 @@ #pragma once #include "file_manager/file.hpp" #include "services/players/player_service.hpp" +#include "core/enums.hpp" namespace { @@ -59,32 +60,66 @@ namespace "LevelLifters", ". com", "$1,000,000,000", + "Instant Delivery", + "0 Ban Risk", + "Discord For Cheap Money", }; } namespace big::spam { - inline bool is_text_spam(const char* text) + inline SpamReason is_text_spam(const char* text, player_ptr player) { + if (g.session.use_spam_timer) + { + if (player->last_message_time.has_value()) + { + auto currentTime = std::chrono::steady_clock::now(); + auto diff = std::chrono::duration_cast(currentTime - player->last_message_time.value()); + player->last_message_time.emplace(currentTime); + + if (strlen(text) > g.session.spam_length && diff.count() <= g.session.spam_timer) + return SpamReason::TIMER_DETECTION; + } + else + { + player->last_message_time.emplace(std::chrono::steady_clock::now()); + } + } for (auto e : spam_texts) if (strstr(text, e) != 0) - return true; + return SpamReason::STATIC_DETECTION; - return false; + return SpamReason::NOT_A_SPAMMER; } - inline void log_chat(char* msg, player_ptr player, bool is_spam) + inline void log_chat(char* msg, player_ptr player, SpamReason spam_reason, bool is_team) { - std::ofstream log(g_file_manager.get_project_file(is_spam ? "./spam.log" : "./chat.log").get_path(), std::ios::app); + std::ofstream log(g_file_manager.get_project_file(spam_reason != SpamReason::NOT_A_SPAMMER ? "./spam.log" : "./chat.log").get_path(), std::ios::app); auto& data = *player->get_net_data(); auto ip = player->get_ip_address(); + auto now = std::chrono::system_clock::now(); + auto ms = std::chrono::duration_cast(now.time_since_epoch()) % 1000; + auto timer = std::chrono::system_clock::to_time_t(now); + auto local_time = *std::localtime(&timer); + + std::string spam_reason_str = ""; + + switch (spam_reason) + { + case SpamReason::STATIC_DETECTION: spam_reason_str = "(Static Detection) "; break; + case SpamReason::TIMER_DETECTION: spam_reason_str = "(Timer Detection) "; break; + } + + log << spam_reason_str << "[" << std::put_time(&local_time, "%m/%d/%Y %I:%M:%S") << ":" << std::setfill('0') << std::setw(3) << ms.count() << " " << std::put_time(&local_time, "%p") << "] "; + if (ip) log << player->get_name() << " (" << data.m_gamer_handle.m_rockstar_id << ") <" << (int)ip.value().m_field1 << "." - << (int)ip.value().m_field2 << "." << (int)ip.value().m_field3 << "." << (int)ip.value().m_field4 << ">: " << msg << std::endl; + << (int)ip.value().m_field2 << "." << (int)ip.value().m_field3 << "." << (int)ip.value().m_field4 << "> " << ((is_team == true) ? "[TEAM]: " : "[ALL]: ") << msg << std::endl; else - log << player->get_name() << " (" << data.m_gamer_handle.m_rockstar_id << ") : " << msg << std::endl; + log << player->get_name() << " (" << data.m_gamer_handle.m_rockstar_id << ") " << ((is_team == true) ? "[TEAM]: " : "[ALL]: ") << msg << std::endl; log.close(); } diff --git a/src/views/network/view_network.cpp b/src/views/network/view_network.cpp index 67a50803..79b31cb4 100644 --- a/src/views/network/view_network.cpp +++ b/src/views/network/view_network.cpp @@ -196,6 +196,12 @@ namespace big if (ImGui::BeginListBox("##chat", get_listbox_dimensions())) { static char msg[256]; + ImGui::Checkbox("USE_SPAM_TIMER"_T.data(), &g.session.use_spam_timer); + if (g.session.use_spam_timer) + { + ImGui::SliderFloat("SPAM_TIMER"_T.data(), &g.session.spam_timer, 0.5f, 5.0f); + ImGui::SliderInt("SPAM_LENGTH"_T.data(), &g.session.spam_length, 1, 256); + } ImGui::Checkbox("AUTO_KICK_CHAT_SPAMMERS"_T.data(), &g.session.kick_chat_spammers); ImGui::Checkbox("LOG_CHAT_MSG"_T.data(), &g.session.log_chat_messages); ImGui::Checkbox("LOG_TXT_MSG"_T.data(), &g.session.log_text_messages); diff --git a/src/views/players/player/player_vehicle.cpp b/src/views/players/player/player_vehicle.cpp index 3eb02f3e..028f0dea 100644 --- a/src/views/players/player/player_vehicle.cpp +++ b/src/views/players/player/player_vehicle.cpp @@ -50,8 +50,6 @@ namespace big ImGui::SameLine(); components::player_command_button<"sshuntright">(g_player_service->get_selected(), {}); - components::player_command_button<"rcplayer">(g_player_service->get_selected()); - ImGui::EndListBox(); } ImGui::EndGroup();