chat notifications: fix matching messages with color
This commit is contained in:
@@ -25,6 +25,7 @@
|
||||
*/
|
||||
package net.runelite.client.plugins.chatnotifications;
|
||||
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import com.google.common.base.Strings;
|
||||
import com.google.inject.Provides;
|
||||
import java.util.List;
|
||||
@@ -115,7 +116,7 @@ public class ChatNotificationsPlugin extends Plugin
|
||||
List<String> items = Text.fromCSV(config.highlightWordsString());
|
||||
String joined = items.stream()
|
||||
.map(Text::escapeJagex) // we compare these strings to the raw Jagex ones
|
||||
.map(Pattern::quote)
|
||||
.map(this::quoteAndIgnoreColor) // regex escape and ignore nested colors in the target message
|
||||
.collect(Collectors.joining("|"));
|
||||
// To match <word> \b doesn't work due to <> not being in \w,
|
||||
// so match \b or \s
|
||||
@@ -184,7 +185,26 @@ public class ChatNotificationsPlugin extends Plugin
|
||||
while (matcher.find())
|
||||
{
|
||||
String value = matcher.group();
|
||||
matcher.appendReplacement(stringBuffer, "<col" + ChatColorType.HIGHLIGHT + ">" + value + "<col" + ChatColorType.NORMAL + ">");
|
||||
|
||||
// Determine the ending color by:
|
||||
// 1) use the color from value if it has one
|
||||
// 2) use the last color from stringBuffer + <content between last match and current match>
|
||||
// To do #2 we just search for the last col tag after calling appendReplacement
|
||||
String endColor = getLastColor(value);
|
||||
|
||||
// Strip color tags from the highlighted region so that it remains highlighted correctly
|
||||
value = stripColor(value);
|
||||
|
||||
matcher.appendReplacement(stringBuffer, "<col" + ChatColorType.HIGHLIGHT + '>' + value);
|
||||
|
||||
if (endColor == null)
|
||||
{
|
||||
endColor = getLastColor(stringBuffer.toString());
|
||||
}
|
||||
|
||||
// Append end color
|
||||
stringBuffer.append(endColor == null ? "<col" + ChatColorType.NORMAL + ">" : endColor);
|
||||
|
||||
update = true;
|
||||
found = true;
|
||||
}
|
||||
@@ -228,4 +248,61 @@ public class ChatNotificationsPlugin extends Plugin
|
||||
String notification = stringBuilder.toString();
|
||||
notifier.notify(notification);
|
||||
}
|
||||
|
||||
private String quoteAndIgnoreColor(String str)
|
||||
{
|
||||
StringBuilder stringBuilder = new StringBuilder();
|
||||
|
||||
for (int i = 0; i < str.length(); ++i)
|
||||
{
|
||||
char c = str.charAt(i);
|
||||
stringBuilder.append(Pattern.quote(String.valueOf(c)));
|
||||
stringBuilder.append("(?:<col=[^>]*?>)?");
|
||||
}
|
||||
|
||||
return stringBuilder.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the last color tag from a string, or null if there was none
|
||||
*
|
||||
* @param str
|
||||
* @return
|
||||
*/
|
||||
private static String getLastColor(String str)
|
||||
{
|
||||
int colIdx = str.lastIndexOf("<col=");
|
||||
int colEndIdx = str.lastIndexOf("</col>");
|
||||
|
||||
if (colEndIdx > colIdx)
|
||||
{
|
||||
// ends in a </col> which resets the color to normal
|
||||
return "<col" + ChatColorType.NORMAL + ">";
|
||||
}
|
||||
|
||||
if (colIdx == -1)
|
||||
{
|
||||
return null; // no color
|
||||
}
|
||||
|
||||
int closeIdx = str.indexOf('>', colIdx);
|
||||
if (closeIdx == -1)
|
||||
{
|
||||
return null; // unclosed col tag
|
||||
}
|
||||
|
||||
return str.substring(colIdx, closeIdx + 1); // include the >
|
||||
}
|
||||
|
||||
/**
|
||||
* Strip color tags from a string.
|
||||
*
|
||||
* @param str
|
||||
* @return
|
||||
*/
|
||||
@VisibleForTesting
|
||||
static String stripColor(String str)
|
||||
{
|
||||
return str.replaceAll("(<col=[0-9a-f]+>|</col>)", "");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -131,6 +131,82 @@ public class ChatNotificationsPluginTest
|
||||
verify(messageNode).setValue("foo <colHIGHLIGHT>test<colNORMAL>. bar");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testColor()
|
||||
{
|
||||
when(config.highlightWordsString()).thenReturn("you. It");
|
||||
|
||||
String message = "Your dodgy necklace protects you. <col=ff0000>It has 1 charge left.</col>";
|
||||
MessageNode messageNode = mock(MessageNode.class);
|
||||
when(messageNode.getValue()).thenReturn(message);
|
||||
|
||||
ChatMessage chatMessage = new ChatMessage();
|
||||
chatMessage.setType(ChatMessageType.PUBLICCHAT);
|
||||
chatMessage.setMessageNode(messageNode);
|
||||
|
||||
chatNotificationsPlugin.startUp(); // load highlight config
|
||||
chatNotificationsPlugin.onChatMessage(chatMessage);
|
||||
|
||||
verify(messageNode).setValue("Your dodgy necklace protects <colHIGHLIGHT>you. It<col=ff0000> has 1 charge left.</col>");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPreceedingColor()
|
||||
{
|
||||
when(config.highlightWordsString()).thenReturn("you. It");
|
||||
|
||||
String message = "Your dodgy <col=00ff00>necklace protects you. It has 1 charge left.</col>";
|
||||
MessageNode messageNode = mock(MessageNode.class);
|
||||
when(messageNode.getValue()).thenReturn(message);
|
||||
|
||||
ChatMessage chatMessage = new ChatMessage();
|
||||
chatMessage.setType(ChatMessageType.PUBLICCHAT);
|
||||
chatMessage.setMessageNode(messageNode);
|
||||
|
||||
chatNotificationsPlugin.startUp(); // load highlight config
|
||||
chatNotificationsPlugin.onChatMessage(chatMessage);
|
||||
|
||||
verify(messageNode).setValue("Your dodgy <col=00ff00>necklace protects <colHIGHLIGHT>you. It<col=00ff00> has 1 charge left.</col>");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEmoji()
|
||||
{
|
||||
when(config.highlightWordsString()).thenReturn("test");
|
||||
|
||||
String message = "emoji test <img=29>";
|
||||
MessageNode messageNode = mock(MessageNode.class);
|
||||
when(messageNode.getValue()).thenReturn(message);
|
||||
|
||||
ChatMessage chatMessage = new ChatMessage();
|
||||
chatMessage.setType(ChatMessageType.PUBLICCHAT);
|
||||
chatMessage.setMessageNode(messageNode);
|
||||
|
||||
chatNotificationsPlugin.startUp(); // load highlight config
|
||||
chatNotificationsPlugin.onChatMessage(chatMessage);
|
||||
|
||||
verify(messageNode).setValue("emoji <colHIGHLIGHT>test<colNORMAL> <img=29>");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNonMatchedColors()
|
||||
{
|
||||
when(config.highlightWordsString()).thenReturn("test");
|
||||
|
||||
String message = "<col=ff0000>color</col> test <img=29>";
|
||||
MessageNode messageNode = mock(MessageNode.class);
|
||||
when(messageNode.getValue()).thenReturn(message);
|
||||
|
||||
ChatMessage chatMessage = new ChatMessage();
|
||||
chatMessage.setType(ChatMessageType.PUBLICCHAT);
|
||||
chatMessage.setMessageNode(messageNode);
|
||||
|
||||
chatNotificationsPlugin.startUp(); // load highlight config
|
||||
chatNotificationsPlugin.onChatMessage(chatMessage);
|
||||
|
||||
verify(messageNode).setValue("<col=ff0000>color</col> <colHIGHLIGHT>test<colNORMAL> <img=29>");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void highlightListTest()
|
||||
{
|
||||
@@ -144,4 +220,10 @@ public class ChatNotificationsPluginTest
|
||||
assertEquals("a", iterator.next());
|
||||
assertEquals("test", iterator.next());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStripColor()
|
||||
{
|
||||
assertEquals("you. It", ChatNotificationsPlugin.stripColor("you. <col=ff0000>It"));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user