Skip to content

Commit

Permalink
chat filter: cache filter results
Browse files Browse the repository at this point in the history
  • Loading branch information
Adam- committed Dec 11, 2023
1 parent fb98120 commit 43b0e36
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 16 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
import com.google.inject.Provides;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
Expand Down Expand Up @@ -104,7 +105,7 @@ private static class Duplicate
int count;
}

private final LinkedHashMap<String, Duplicate> duplicateChatCache = new LinkedHashMap<String, Duplicate>()
private final LinkedHashMap<String, Duplicate> duplicateChatCache = new LinkedHashMap<>()
{
private static final int MAX_ENTRIES = 100;

Expand All @@ -115,6 +116,19 @@ protected boolean removeEldestEntry(Map.Entry<String, Duplicate> eldest)
}
};

private static class FilterCacheMap extends LinkedHashMap<Integer, String>
{
private static final int MAX_ENTRIES = 100;

@Override
protected boolean removeEldestEntry(Map.Entry<Integer, String> eldest)
{
return size() > MAX_ENTRIES;
}
}

private final Map<ChatMessageType, FilterCacheMap> filterCache = new HashMap<>();

@Inject
private Client client;

Expand All @@ -139,6 +153,8 @@ protected void shutDown() throws Exception
{
filteredPatterns = Collections.emptyList();
filteredNamePatterns = Collections.emptyList();
duplicateChatCache.clear();
filterCache.clear();
client.refreshChat();
}

Expand All @@ -149,9 +165,11 @@ public void onGameStateChanged(GameStateChanged gameStateChanged)
{
// Login drops references to all messages and also resets the global message id counter.
// Invalidate the message id so it doesn't collide later when rebuilding the chatfilter.
case CONNECTION_LOST:
case HOPPING:
case LOGGING_IN:
duplicateChatCache.values().forEach(d -> d.messageId = -1);
filterCache.clear();
}
}

Expand Down Expand Up @@ -190,9 +208,9 @@ public void onScriptCallbackEvent(ScriptCallbackEvent event)
case CLAN_CHAT:
case CLAN_GUEST_CHAT:
case CLAN_GIM_CHAT:
if (shouldFilterPlayerMessage(Text.removeTags(name)))
if (canFilterPlayer(Text.removeTags(name)))
{
message = censorMessage(name, message);
message = censorMessageCache(messageNode, name, message);
blockMessage = message == null;
}
break;
Expand All @@ -207,7 +225,7 @@ public void onScriptCallbackEvent(ScriptCallbackEvent event)
case CLAN_GIM_MESSAGE:
if (config.filterGameChat())
{
message = censorMessage(null, message);
message = censorMessageCache(messageNode, null, message);
blockMessage = message == null;
}
break;
Expand Down Expand Up @@ -251,7 +269,7 @@ public void onScriptCallbackEvent(ScriptCallbackEvent event)
@Subscribe
public void onOverheadTextChanged(OverheadTextChanged event)
{
if (!(event.getActor() instanceof Player) || event.getActor().getName() == null || !shouldFilterPlayerMessage(event.getActor().getName())) // NOPMD: SimplifyConditional
if (!(event.getActor() instanceof Player) || event.getActor().getName() == null || !canFilterPlayer(event.getActor().getName())) // NOPMD: SimplifyConditional
{
return;
}
Expand Down Expand Up @@ -286,7 +304,7 @@ public void onChatMessage(ChatMessage chatMessage)
}
}

boolean shouldFilterPlayerMessage(String playerName)
boolean canFilterPlayer(String playerName)
{
boolean isMessageFromSelf = playerName.equals(client.getLocalPlayer().getName());
return !isMessageFromSelf &&
Expand Down Expand Up @@ -327,7 +345,7 @@ String censorMessage(final String username, final String message)
String strippedAccents = stripAccents(strippedMessage);
assert strippedMessage.length() == strippedAccents.length();

if (username != null && shouldFilterByName(username))
if (username != null && isNameFiltered(username))
{
switch (config.filterType())
{
Expand Down Expand Up @@ -374,6 +392,25 @@ String censorMessage(final String username, final String message)
return filtered ? strippedMessage : message;
}

private String censorMessageCache(MessageNode messageNode, String username, String message)
{
FilterCacheMap map = this.filterCache.get(messageNode.getType());
if (map == null)
{
map = new FilterCacheMap();
this.filterCache.put(messageNode.getType(), map);
}

if (map.containsKey(messageNode.getId()))
{
return map.get(messageNode.getId());
}

String censoredMessage = censorMessage(username, message);
map.put(messageNode.getId(), censoredMessage);
return censoredMessage;
}

void updateFilteredPatterns()
{
List<Pattern> patterns = new ArrayList<>();
Expand All @@ -398,6 +435,8 @@ void updateFilteredPatterns()

filteredPatterns = patterns;
filteredNamePatterns = namePatterns;

filterCache.clear();
}

private String stripAccents(String input)
Expand Down Expand Up @@ -432,7 +471,7 @@ public void onConfigChanged(ConfigChanged event)
}

@VisibleForTesting
boolean shouldFilterByName(final String playerName)
boolean isNameFiltered(final String playerName)
{
String sanitizedName = Text.standardize(playerName);
for (Pattern pattern : filteredNamePatterns)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -222,45 +222,45 @@ public void testMixedUnicodeFiltersUnicode()
public void testMessageFromFriendIsFiltered()
{
when(chatFilterConfig.filterFriends()).thenReturn(true);
assertTrue(chatFilterPlugin.shouldFilterPlayerMessage("Iron Mammal"));
assertTrue(chatFilterPlugin.canFilterPlayer("Iron Mammal"));
}

@Test
public void testMessageFromFriendIsNotFiltered()
{
when(client.isFriended("Iron Mammal", false)).thenReturn(true);
when(chatFilterConfig.filterFriends()).thenReturn(false);
assertFalse(chatFilterPlugin.shouldFilterPlayerMessage("Iron Mammal"));
assertFalse(chatFilterPlugin.canFilterPlayer("Iron Mammal"));
}

@Test
public void testMessageFromFriendsChatIsFiltered()
{
when(client.isFriended("B0aty", false)).thenReturn(false);
when(chatFilterConfig.filterFriendsChat()).thenReturn(true);
assertTrue(chatFilterPlugin.shouldFilterPlayerMessage("B0aty"));
assertTrue(chatFilterPlugin.canFilterPlayer("B0aty"));
}

@Test
public void testMessageFromFriendsChatIsNotFiltered()
{
when(friendsChatManager.findByName("B0aty")).thenReturn(mock(FriendsChatMember.class));
when(chatFilterConfig.filterFriendsChat()).thenReturn(false);
assertFalse(chatFilterPlugin.shouldFilterPlayerMessage("B0aty"));
assertFalse(chatFilterPlugin.canFilterPlayer("B0aty"));
}

@Test
public void testMessageFromSelfIsNotFiltered()
{
when(localPlayer.getName()).thenReturn("Swampletics");
assertFalse(chatFilterPlugin.shouldFilterPlayerMessage("Swampletics"));
assertFalse(chatFilterPlugin.canFilterPlayer("Swampletics"));
}

@Test
public void testMessageFromNonFriendNonFCIsFiltered()
{
when(client.isFriended("Woox", false)).thenReturn(false);
assertTrue(chatFilterPlugin.shouldFilterPlayerMessage("Woox"));
assertTrue(chatFilterPlugin.canFilterPlayer("Woox"));
}

@Test
Expand All @@ -269,8 +269,8 @@ public void testShouldFilterByName()
when(chatFilterConfig.filteredNames()).thenReturn("Gamble [0-9]*");

chatFilterPlugin.updateFilteredPatterns();
assertTrue(chatFilterPlugin.shouldFilterByName("Gamble 1234"));
assertFalse(chatFilterPlugin.shouldFilterByName("Adam"));
assertTrue(chatFilterPlugin.isNameFiltered("Gamble 1234"));
assertFalse(chatFilterPlugin.isNameFiltered("Adam"));
}

@Test
Expand Down

0 comments on commit 43b0e36

Please sign in to comment.