Skip to content

Commit

Permalink
feat(chat): allow matching on runelite notifications (#493)
Browse files Browse the repository at this point in the history
  • Loading branch information
iProdigy authored Jun 15, 2024
1 parent 62355b8 commit 9d51ca9
Show file tree
Hide file tree
Showing 7 changed files with 53 additions and 2 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
## Unreleased

- Minor: Allow RuneLite notifier messages to trigger the Dink chat notifier. (#493)
- Minor: Include player region and world for non-Discord custom webhook handlers via metadata for all notifiers. (#490)
- Minor: Allow client commands to trigger the chat notifier. (#489)
- Minor: Send logout notifications to the Custom Metadata Handler in advanced settings. (#492)
Expand Down
2 changes: 2 additions & 0 deletions docs/json-examples.md
Original file line number Diff line number Diff line change
Expand Up @@ -720,6 +720,8 @@ Note: The possible values for `extra.type` are documented in RuneLite's [javadoc
When `extra.type` corresponds to a player-sent message (e.g., `PUBLICCHAT`, `PRIVATECHAT`, `FRIENDSCHAT`, `CLAN_CHAT`, `CLAN_GUEST_CHAT`),
the `extra.source` value is set to the player's name that sent the message.
When `extra.type` is `UNKNOWN`, the `extra.source` value is set to the originating runelite event (e.g., `CommandExecuted`, `NotificationFired`).
### Metadata
JSON for Login Notifications:
Expand Down
6 changes: 6 additions & 0 deletions src/main/java/dinkplugin/DinkPlugin.java
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
import net.runelite.client.config.ConfigManager;
import net.runelite.client.eventbus.Subscribe;
import net.runelite.client.events.ConfigChanged;
import net.runelite.client.events.NotificationFired;
import net.runelite.client.events.NpcLootReceived;
import net.runelite.client.events.PlayerLootReceived;
import net.runelite.client.events.ProfileChanged;
Expand Down Expand Up @@ -299,6 +300,11 @@ public void onLootReceived(LootReceived lootReceived) {
lootNotifier.onLootReceived(lootReceived);
}

@Subscribe
public void onNotificationFired(NotificationFired event) {
chatNotifier.onNotification(event);
}

@Subscribe
public void onVarbitChanged(VarbitChanged event) {
settingsManager.onVarbitChanged(event);
Expand Down
3 changes: 2 additions & 1 deletion src/main/java/dinkplugin/domain/ChatNotificationType.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ public enum ChatNotificationType {
TRADES("Trades and Duels", TRADE, TRADE_SENT, TRADEREQ, CHALREQ_TRADE, CHALREQ_FRIENDSCHAT, CHALREQ_CLANCHAT),
PUBLIC("Public Chats", PUBLICCHAT, MODCHAT, AUTOTYPER, MODAUTOTYPER),
PRIVATE("Non-Public Chats", PRIVATECHAT, PRIVATECHATOUT, MODPRIVATECHAT, FRIENDSCHAT, CLAN_CHAT, CLAN_GUEST_CHAT),
COMMAND("Client Commands");
COMMAND("Client Commands"),
RUNELITE("RuneLite Notifications");

public static final Map<ChatMessageType, ChatNotificationType> MAPPINGS;

Expand Down
12 changes: 12 additions & 0 deletions src/main/java/dinkplugin/notifiers/ChatNotifier.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@
import dinkplugin.util.Utils;
import lombok.Synchronized;
import net.runelite.api.ChatMessageType;
import net.runelite.api.GameState;
import net.runelite.api.events.CommandExecuted;
import net.runelite.client.events.NotificationFired;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

Expand Down Expand Up @@ -68,6 +70,16 @@ public void onCommand(CommandExecuted event) {
}
}

public void onNotification(NotificationFired event) {
var types = config.chatMessageTypes();
if (event.getNotification().isGameMessage() && client.getGameState() == GameState.LOGGED_IN && types.contains(ChatNotificationType.GAME)) {
return; // avoid duplicate notification (since runelite will also post to chat)
}
if (types.contains(ChatNotificationType.RUNELITE) && isEnabled() && hasMatch(event.getMessage())) {
this.handleNotify(ChatMessageType.UNKNOWN, "NotificationFired", event.getMessage());
}
}

private void handleNotify(ChatMessageType type, String source, String message) {
String playerName = Utils.getPlayerName(client);
Template template = Template.builder()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ public class ChatNotificationData extends NotificationData {

/**
* {@link ChatMessage#getName()} when available; otherwise {@link ChatMessage#getSender()}.
* When {@link #getType()} is {@link ChatMessageType#UNKNOWN}, this field corresponds to the originating runelite event.
*/
@Nullable
String source;
Expand Down
30 changes: 29 additions & 1 deletion src/test/java/dinkplugin/notifiers/ChatNotifierTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,13 @@
import dinkplugin.notifiers.data.ChatNotificationData;
import net.runelite.api.ChatMessageType;
import net.runelite.api.events.CommandExecuted;
import net.runelite.client.config.Notification;
import net.runelite.client.events.NotificationFired;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.InjectMocks;

import java.awt.TrayIcon;
import java.util.EnumSet;

import static org.mockito.ArgumentMatchers.any;
Expand All @@ -33,10 +36,11 @@ protected void setUp() {

// config mocks
when(config.notifyChat()).thenReturn(true);
when(config.chatMessageTypes()).thenReturn(EnumSet.of(ChatNotificationType.GAME, ChatNotificationType.COMMAND));
when(config.chatMessageTypes()).thenReturn(EnumSet.of(ChatNotificationType.GAME, ChatNotificationType.COMMAND, ChatNotificationType.RUNELITE));
when(config.chatNotifyMessage()).thenReturn("%USERNAME% received a chat message:\n\n```\n%MESSAGE%\n```");
setPatterns("You will be logged out in approximately 10 minutes.*\n" +
"You will be logged out in approximately 5 minutes.*\n" +
"Dragon impling is in the area\n" +
"::TriggerDink\n");
}

Expand Down Expand Up @@ -86,6 +90,29 @@ void testNotifyCommand() {
);
}

@Test
void testNotifyTray() {
// fire event
String message = "Dragon impling is in the area";
notifier.onNotification(new NotificationFired(Notification.ON, message, TrayIcon.MessageType.INFO));

// verify notification message
verify(messageHandler).createMessage(
PRIMARY_WEBHOOK_URL,
false,
NotificationBody.builder()
.text(
Template.builder()
.template(PLAYER_NAME + " received a chat message:\n\n```\n" + message + "\n```")
.build()
)
.extra(new ChatNotificationData(ChatMessageType.UNKNOWN, "NotificationFired", message))
.type(NotificationType.CHAT)
.playerName(PLAYER_NAME)
.build()
);
}

@Test
void testIgnore() {
// fire event
Expand All @@ -95,6 +122,7 @@ void testIgnore() {
notifier.onMessage(ChatMessageType.CLAN_MESSAGE, null, "You will be logged out in approximately 10 minutes.");
notifier.onCommand(new CommandExecuted("You", "will be logged out in approximately 10 minutes.".split(" ")));
notifier.onCommand(new CommandExecuted("DontTriggerDink", new String[0]));
notifier.onNotification(new NotificationFired(Notification.ON, "TriggerDink", TrayIcon.MessageType.INFO));

// ensure no notification occurred
verify(messageHandler, never()).createMessage(any(), anyBoolean(), any());
Expand Down

0 comments on commit 9d51ca9

Please sign in to comment.