diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/chatnotifications/ChatNotificationsConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/chatnotifications/ChatNotificationsConfig.java new file mode 100644 index 0000000000..d49fd68d07 --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/chatnotifications/ChatNotificationsConfig.java @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2018, Hydrox6 + * Copyright (c) 2018, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.client.plugins.chatnotifications; + +import net.runelite.client.config.Config; +import net.runelite.client.config.ConfigGroup; +import net.runelite.client.config.ConfigItem; + +@ConfigGroup( + keyName = "chatnotification", + name = "Chat Notifications", + description = "Highlights and notifies you of chat messages" +) +public interface ChatNotificationsConfig extends Config +{ + @ConfigItem( + position = 0, + keyName = "highlightOwnName", + name = "Highlight own name", + description = "Highlights any instance of your username in chat" + ) + default boolean highlightOwnName() + { + return false; + } + + @ConfigItem( + position = 1, + keyName = "highlightWordsString", + name = "Highlight words", + description = "Highlights the following words in chat" + ) + default String highlightWordsString() + { + return ""; + } + + @ConfigItem( + position = 2, + keyName = "notifyOnOwnName", + name = "Notify on own name", + description = "Notifies you whenever your name is mentioned" + ) + default boolean notifyOnOwnName() + { + return false; + } + + @ConfigItem( + position = 3, + keyName = "notifyOnHighlight", + name = "Notify on hightlight", + description = "Notifies you whenever a word is above is highlighted" + ) + default boolean notifyOnHighlight() + { + return false; + } + + @ConfigItem( + position = 4, + keyName = "notifyOnTrade", + name = "Notify on trade", + description = "Notifies you whenever you are traded" + ) + default boolean notifyOnTrade() + { + return false; + } + + @ConfigItem( + position = 5, + keyName = "notifyOnDuel", + name = "Notify on duel", + description = "Notifies you whenever you are challenged to a duel" + ) + default boolean notifyOnDuel() + { + return false; + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/chatnotifications/ChatNotificationsPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/chatnotifications/ChatNotificationsPlugin.java new file mode 100644 index 0000000000..3298f7bd84 --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/chatnotifications/ChatNotificationsPlugin.java @@ -0,0 +1,196 @@ +/* + * Copyright (c) 2018, Hydrox6 + * Copyright (c) 2018, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.client.plugins.chatnotifications; + +import com.google.common.base.Strings; +import com.google.common.eventbus.Subscribe; +import com.google.inject.Inject; +import com.google.inject.Provides; +import java.util.Arrays; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import static java.util.regex.Pattern.quote; +import java.util.stream.Collectors; +import net.runelite.api.Client; +import net.runelite.api.MessageNode; +import net.runelite.api.events.ConfigChanged; +import net.runelite.api.events.GameStateChanged; +import net.runelite.api.events.SetMessage; +import net.runelite.client.Notifier; +import net.runelite.client.chat.ChatColorType; +import net.runelite.client.chat.ChatMessageManager; +import net.runelite.client.config.ConfigManager; +import net.runelite.client.plugins.Plugin; +import net.runelite.client.plugins.PluginDescriptor; + +@PluginDescriptor( + name = "Chat Notifications" +) +public class ChatNotificationsPlugin extends Plugin +{ + @Inject + private Client client; + + @Inject + private ChatNotificationsConfig config; + + @Inject + private ChatMessageManager chatMessageManager; + + @Inject + private Notifier notifier; + + //Custom Highlights + private Pattern usernameMatcher = null; + private String usernameReplacer = ""; + private Pattern highlightMatcher = null; + + @Provides + ChatNotificationsConfig provideConfig(ConfigManager configManager) + { + return configManager.getConfig(ChatNotificationsConfig.class); + } + + @Subscribe + public void onGameStateChanged(GameStateChanged event) + { + switch (event.getGameState()) + { + case LOGIN_SCREEN: + case HOPPING: + usernameMatcher = null; + break; + } + } + + @Subscribe + public void onConfigChanged(ConfigChanged event) + { + if (event.getGroup().equals("chatnotification")) + { + highlightMatcher = null; + + if (!config.highlightWordsString().trim().equals("")) + { + String[] items = config.highlightWordsString().trim().split(", "); + String joined = Arrays.stream(items) + .map(Pattern::quote) + .collect(Collectors.joining("|")); + highlightMatcher = Pattern.compile("\\b(" + joined + ")\\b", Pattern.CASE_INSENSITIVE); + } + } + } + + @Subscribe + public void onSetMessage(SetMessage event) + { + MessageNode messageNode = event.getMessageNode(); + boolean update = false; + + switch (event.getType()) + { + case TRADE: + if (event.getValue().contains("wishes to trade with you.") && config.notifyOnTrade()) + { + notifier.notify(event.getValue()); + } + break; + case DUEL: + if (event.getValue().contains("wishes to duel with you.") && config.notifyOnDuel()) + { + notifier.notify(event.getValue()); + } + break; + } + + if (usernameMatcher == null && client.getLocalPlayer() != null && client.getLocalPlayer().getName() != null) + { + String username = client.getLocalPlayer().getName(); + usernameMatcher = Pattern.compile("\\b(" + quote(username) + ")\\b", Pattern.CASE_INSENSITIVE); + usernameReplacer = "" + username + ""; + } + + if (usernameMatcher != null) + { + Matcher matcher = usernameMatcher.matcher(messageNode.getValue()); + if (matcher.find()) + { + messageNode.setValue(matcher.replaceAll(usernameReplacer)); + update = true; + + if (config.highlightOwnName()) + { + sendNotification(event); + } + } + } + + if (highlightMatcher != null) + { + Matcher matcher = highlightMatcher.matcher(messageNode.getValue()); + boolean found = false; + + while (matcher.find()) + { + String value = matcher.group(); + messageNode.setValue(matcher.replaceFirst("" + value + "")); + update = true; + found = true; + } + + if (found && config.notifyOnHighlight()) + { + sendNotification(event); + } + } + + if (update) + { + messageNode.setRuneLiteFormatMessage(messageNode.getValue()); + chatMessageManager.update(messageNode); + } + } + + private void sendNotification(SetMessage message) + { + String name = message.getName(); + String sender = message.getSender(); + StringBuilder stringBuilder = new StringBuilder(); + + if (!Strings.isNullOrEmpty(sender)) + { + stringBuilder.append('[').append(sender).append("] "); + } + if (!Strings.isNullOrEmpty(name)) + { + stringBuilder.append(name).append(' '); + } + stringBuilder.append(message.getValue()); + + String notification = stringBuilder.toString(); + notifier.notify(notification); + } +}