From ff0ab6196abbd900849c7b047946315e8034ae39 Mon Sep 17 00:00:00 2001
From: Jean-Baptiste Emmanuel Zorg <zorgjeanbe@proton.me>
Date: Thu, 16 Feb 2023 19:47:28 +0100
Subject: [PATCH] Make sure the sensory-deprivation doesn't go overboard

If someone with a short-enough name would get caught into
sensory-deprivation processing, it would lead to all occurrences being
replaced by "Someone", leading to gems like `*Someone nods,
squSomeoneaking thrSomeoneatSomeoneningly*`.

Refactor that part into a function, build the whole regex in one step,
add boundary markers (\b) around it so it only matches on words, and
make it respect case.

This correctly translates:
```
**As e nods, squeaking threateningly, then moves up to Kathy and fingers her while she gently strokes Clara's breast.
```
into

```
*As someone nods, squeaking threateningly, then moves up to someone and fingers her while she gently strokes Clara's breast.*
```
Clara being the character under sensory-deprivation in that case.
---
 .../Screens/Online/ChatRoom/ChatRoom.js       | 14 +------
 BondageClub/Scripts/Speech.js                 | 37 +++++++++++++++++++
 2 files changed, 38 insertions(+), 13 deletions(-)

diff --git a/BondageClub/Screens/Online/ChatRoom/ChatRoom.js b/BondageClub/Screens/Online/ChatRoom/ChatRoom.js
index 13fc901c90..cbfb0dccf8 100644
--- a/BondageClub/Screens/Online/ChatRoom/ChatRoom.js
+++ b/BondageClub/Screens/Online/ChatRoom/ChatRoom.js
@@ -2390,19 +2390,7 @@ var ChatRoomMessageHandlers = [
 				if (ChatRoomIsCharacterImpactedBySensoryDeprivation(sender)) {
 					metadata.senderName = DialogFindPlayer("Someone");
 
-					for (const C of ChatRoomCharacter) {
-						if (C && C.Name && C.ID != 0 && (!ChatRoomSenseDepBypass || !ChatRoomCharacterDrawlist.includes(C))) {
-							const nick = CharacterNickname(C);
-							let s = C.Name;
-							if (nick) {
-								s += "|" + nick;
-							}
-
-							// Hopefully there are no regex characters to escape from that pattern :-S
-							const r = new RegExp(s, "ig");
-							msg = msg.replace(r, DialogFindPlayer("Someone"));
-						}
-					}
+					msg = SpeechAnonymize(msg, ChatRoomCharacter);
 				}
 			}
 
diff --git a/BondageClub/Scripts/Speech.js b/BondageClub/Scripts/Speech.js
index d38a370c36..b2ef16af80 100644
--- a/BondageClub/Scripts/Speech.js
+++ b/BondageClub/Scripts/Speech.js
@@ -642,3 +642,40 @@ function SpeechBabyTalk(C, CD) {
 	// Not drunk the milk, we return the regular text
 	return CD;
 }
+
+/**
+ * Anonymize character names from a string, replacing them with "Someone".
+ *
+ * Used as part of sensory-deprivation processing.
+ *
+ * @param {string} msg
+ * @param {Character[]} characters
+ */
+function SpeechAnonymize(msg, characters) {
+	const names = [];
+	for (const C of characters) {
+		if (!ChatRoomIsCharacterImpactedBySensoryDeprivation(C)) continue;
+		names.push(C.Name);
+
+		const nick = CharacterNickname(C);
+		if (nick && nick !== C.Name) {
+			names.push(nick);
+		}
+	}
+
+	if (names.length === 0) return msg;
+
+	names.sort((a, b) => b.length - a.length);
+
+	// Hopefully there are no regex characters to escape from that pattern :-S
+	const reg = new RegExp(`\\b(?:${names.join("|")})\\b`, "g");
+
+	// Now replace with the placeholder, lowercasing if it's not the first thing in the string
+	const replacement = DialogFindPlayer("Someone");
+	function replacer(_match, offset, _string, _groups) {
+		return offset === 0 ? replacement : replacement.toLowerCase();
+	}
+	msg = msg.replace(reg, replacer);
+
+	return msg;
+}
-- 
GitLab