chat notifications: add regex highlights

Co-authored-by: Adam <Adam@sigterm.info>
This commit is contained in:
David Uhler Brand
2021-01-25 01:15:36 -08:00
committed by Adam
parent ed978d31dd
commit 19cc5dc461
3 changed files with 136 additions and 34 deletions

View File

@@ -28,12 +28,44 @@ package net.runelite.client.plugins.chatnotifications;
import net.runelite.client.config.Config; import net.runelite.client.config.Config;
import net.runelite.client.config.ConfigGroup; import net.runelite.client.config.ConfigGroup;
import net.runelite.client.config.ConfigItem; import net.runelite.client.config.ConfigItem;
import net.runelite.client.config.ConfigSection;
@ConfigGroup("chatnotification") @ConfigGroup("chatnotification")
public interface ChatNotificationsConfig extends Config public interface ChatNotificationsConfig extends Config
{ {
@ConfigSection(
name = "Highlight Lists",
description = "Custom single word and regex filter lists",
position = 0
)
String highlightLists = "highlightLists";
@ConfigItem( @ConfigItem(
position = 0, position = 1,
keyName = "highlightWordsString",
name = "Highlight words",
description = "Highlights the following words in chat",
section = highlightLists
)
default String highlightWordsString()
{
return "";
}
@ConfigItem(
position = 2,
keyName = "highlightRegexString",
name = "Highlight Regex",
description = "Highlights the following regular expressions in chat, one per line",
section = highlightLists
)
default String highlightRegexString()
{
return "";
}
@ConfigItem(
position = 1,
keyName = "highlightOwnName", keyName = "highlightOwnName",
name = "Highlight own name", name = "Highlight own name",
description = "Highlights any instance of your username in chat" description = "Highlights any instance of your username in chat"
@@ -43,17 +75,6 @@ public interface ChatNotificationsConfig extends Config
return true; return true;
} }
@ConfigItem(
position = 1,
keyName = "highlightWordsString",
name = "Highlight words",
description = "Highlights the following words in chat"
)
default String highlightWordsString()
{
return "";
}
@ConfigItem( @ConfigItem(
position = 2, position = 2,
keyName = "notifyOnOwnName", keyName = "notifyOnOwnName",

View File

@@ -27,12 +27,16 @@ package net.runelite.client.plugins.chatnotifications;
import com.google.common.annotations.VisibleForTesting; import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.MoreObjects; import com.google.common.base.MoreObjects;
import com.google.common.base.Splitter;
import com.google.common.base.Strings; import com.google.common.base.Strings;
import com.google.inject.Provides; import com.google.inject.Provides;
import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.Objects;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import javax.inject.Inject; import javax.inject.Inject;
import javax.inject.Named; import javax.inject.Named;
@@ -77,7 +81,7 @@ public class ChatNotificationsPlugin extends Plugin
//Custom Highlights //Custom Highlights
private Pattern usernameMatcher = null; private Pattern usernameMatcher = null;
private Pattern highlightMatcher = null; private final List<Pattern> highlightPatterns = new ArrayList<>();
@Provides @Provides
ChatNotificationsConfig provideConfig(ConfigManager configManager) ChatNotificationsConfig provideConfig(ConfigManager configManager)
@@ -91,6 +95,13 @@ public class ChatNotificationsPlugin extends Plugin
updateHighlights(); updateHighlights();
} }
@Override
protected void shutDown()
{
usernameMatcher = null;
highlightPatterns.clear();
}
@Subscribe @Subscribe
public void onGameStateChanged(GameStateChanged event) public void onGameStateChanged(GameStateChanged event)
{ {
@@ -114,7 +125,7 @@ public class ChatNotificationsPlugin extends Plugin
private void updateHighlights() private void updateHighlights()
{ {
highlightMatcher = null; highlightPatterns.clear();
if (!config.highlightWordsString().trim().equals("")) if (!config.highlightWordsString().trim().equals(""))
{ {
@@ -125,7 +136,28 @@ public class ChatNotificationsPlugin extends Plugin
.collect(Collectors.joining("|")); .collect(Collectors.joining("|"));
// To match <word> \b doesn't work due to <> not being in \w, // To match <word> \b doesn't work due to <> not being in \w,
// so match \b or \s, as well as \A and \z for beginning and end of input respectively // so match \b or \s, as well as \A and \z for beginning and end of input respectively
highlightMatcher = Pattern.compile("(?:\\b|(?<=\\s)|\\A)(?:" + joined + ")(?:\\b|(?=\\s)|\\z)", Pattern.CASE_INSENSITIVE); highlightPatterns.add(Pattern.compile("(?:\\b|(?<=\\s)|\\A)(?:" + joined + ")(?:\\b|(?=\\s)|\\z)", Pattern.CASE_INSENSITIVE));
}
Splitter
.on("\n")
.omitEmptyStrings()
.trimResults()
.splitToList(config.highlightRegexString()).stream()
.map(ChatNotificationsPlugin::compilePattern)
.filter(Objects::nonNull)
.forEach(highlightPatterns::add);
}
private static Pattern compilePattern(String pattern)
{
try
{
return Pattern.compile(pattern, Pattern.CASE_INSENSITIVE);
}
catch (PatternSyntaxException ex)
{
return null;
} }
} }
@@ -225,14 +257,22 @@ public class ChatNotificationsPlugin extends Plugin
} }
} }
if (highlightMatcher != null) boolean matchesHighlight = false;
// Get nodeValue to store and update in between the different pattern passes
// The messageNode value is only set after all patterns have been processed
String nodeValue = messageNode.getValue();
for (Pattern pattern : highlightPatterns)
{ {
String nodeValue = messageNode.getValue(); Matcher matcher = pattern.matcher(nodeValue);
Matcher matcher = highlightMatcher.matcher(nodeValue); if (!matcher.find())
boolean found = false; {
continue;
}
StringBuffer stringBuffer = new StringBuffer(); StringBuffer stringBuffer = new StringBuffer();
while (matcher.find()) do
{ {
String value = matcher.group(); String value = matcher.group();
@@ -256,18 +296,21 @@ public class ChatNotificationsPlugin extends Plugin
stringBuffer.append(endColor == null ? "<col" + ChatColorType.NORMAL + ">" : endColor); stringBuffer.append(endColor == null ? "<col" + ChatColorType.NORMAL + ">" : endColor);
update = true; update = true;
found = true; matchesHighlight = true;
} }
while (matcher.find());
if (found) // Append stringBuffer with remainder of message and update nodeValue
matcher.appendTail(stringBuffer);
nodeValue = stringBuffer.toString();
}
if (matchesHighlight)
{
messageNode.setValue(nodeValue);
if (config.notifyOnHighlight())
{ {
matcher.appendTail(stringBuffer); sendNotification(chatMessage);
messageNode.setValue(stringBuffer.toString());
if (config.notifyOnHighlight())
{
sendNotification(chatMessage);
}
} }
} }

View File

@@ -82,6 +82,8 @@ public class ChatNotificationsPluginTest
public void before() public void before()
{ {
Guice.createInjector(BoundFieldModule.of(this)).injectMembers(this); Guice.createInjector(BoundFieldModule.of(this)).injectMembers(this);
when(config.highlightRegexString()).thenReturn("");
when(config.highlightWordsString()).thenReturn("");
} }
@Test @Test
@@ -102,6 +104,42 @@ public class ChatNotificationsPluginTest
verify(messageNode).setValue("<colHIGHLIGHT>Deathbeam<colNORMAL>, <colHIGHLIGHT>Deathbeam<colNORMAL> OSRS"); verify(messageNode).setValue("<colHIGHLIGHT>Deathbeam<colNORMAL>, <colHIGHLIGHT>Deathbeam<colNORMAL> OSRS");
} }
@Test
public void testRegexMultiplePatternsMessage()
{
when(config.highlightRegexString()).thenReturn("brandie+\ntest");
MessageNode messageNode = mock(MessageNode.class);
when(messageNode.getValue()).thenReturn("brandieeee testing");
ChatMessage chatMessage = new ChatMessage();
chatMessage.setType(ChatMessageType.PUBLICCHAT);
chatMessage.setMessageNode(messageNode);
chatNotificationsPlugin.startUp();
chatNotificationsPlugin.onChatMessage(chatMessage);
verify(messageNode).setValue("<colHIGHLIGHT>brandieeee<colNORMAL> <colHIGHLIGHT>test<colNORMAL>ing");
}
@Test
public void testRegexMultiplePatternsWithOnlyOneMatch()
{
when(config.highlightRegexString()).thenReturn("brandie+\nwillNotMatch");
MessageNode messageNode = mock(MessageNode.class);
when(messageNode.getValue()).thenReturn("brandieeee testing");
ChatMessage chatMessage = new ChatMessage();
chatMessage.setType(ChatMessageType.PUBLICCHAT);
chatMessage.setMessageNode(messageNode);
chatNotificationsPlugin.startUp();
chatNotificationsPlugin.onChatMessage(chatMessage);
verify(messageNode).setValue("<colHIGHLIGHT>brandieeee<colNORMAL> testing");
}
@Test @Test
public void testLtGt() public void testLtGt()
{ {
@@ -179,7 +217,7 @@ public class ChatNotificationsPluginTest
} }
@Test @Test
public void testPreceedingColor() public void testPrecedingColor()
{ {
when(config.highlightWordsString()).thenReturn("you. It"); when(config.highlightWordsString()).thenReturn("you. It");
@@ -239,10 +277,10 @@ public class ChatNotificationsPluginTest
public void highlightListTest() public void highlightListTest()
{ {
when(config.highlightWordsString()).thenReturn("this,is, a , test, "); when(config.highlightWordsString()).thenReturn("this,is, a , test, ");
final List<String> higlights = Text.fromCSV(config.highlightWordsString()); final List<String> highlights = Text.fromCSV(config.highlightWordsString());
assertEquals(4, higlights.size()); assertEquals(4, highlights.size());
final Iterator<String> iterator = higlights.iterator(); final Iterator<String> iterator = highlights.iterator();
assertEquals("this", iterator.next()); assertEquals("this", iterator.next());
assertEquals("is", iterator.next()); assertEquals("is", iterator.next());
assertEquals("a", iterator.next()); assertEquals("a", iterator.next());