From 6d204fa5223dba5584150278d965328c6ead9731 Mon Sep 17 00:00:00 2001 From: iProdigy Date: Thu, 26 Oct 2023 01:48:28 -0700 Subject: [PATCH 1/6] feat: include owned pets in login notifications --- .../dinkplugin/notifiers/MetaNotifier.java | 42 ++++++++++++++++++- .../notifiers/data/LoginNotificationData.java | 2 + .../notifiers/MetaNotifierTest.java | 6 ++- 3 files changed, 47 insertions(+), 3 deletions(-) diff --git a/src/main/java/dinkplugin/notifiers/MetaNotifier.java b/src/main/java/dinkplugin/notifiers/MetaNotifier.java index 6d51781d..05b95dbe 100644 --- a/src/main/java/dinkplugin/notifiers/MetaNotifier.java +++ b/src/main/java/dinkplugin/notifiers/MetaNotifier.java @@ -1,5 +1,7 @@ package dinkplugin.notifiers; +import com.google.gson.Gson; +import com.google.gson.JsonSyntaxException; import dinkplugin.domain.AchievementDiary; import dinkplugin.message.NotificationBody; import dinkplugin.message.NotificationType; @@ -8,6 +10,7 @@ import dinkplugin.notifiers.data.LoginNotificationData; import dinkplugin.notifiers.data.Progress; import dinkplugin.util.Utils; +import lombok.extern.slf4j.Slf4j; import net.runelite.api.Experience; import net.runelite.api.GameState; import net.runelite.api.Skill; @@ -15,19 +18,26 @@ import net.runelite.api.Varbits; import net.runelite.api.events.GameStateChanged; import net.runelite.client.callback.ClientThread; +import net.runelite.client.config.ConfigManager; +import net.runelite.client.config.RuneLiteConfig; +import net.runelite.client.plugins.chatcommands.ChatCommandsPlugin; import org.apache.commons.lang3.StringUtils; import org.jetbrains.annotations.VisibleForTesting; import javax.inject.Inject; import javax.inject.Singleton; import java.util.Arrays; +import java.util.HashMap; import java.util.Map; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicReference; import java.util.stream.Collectors; +@Slf4j @Singleton public class MetaNotifier extends BaseNotifier { + private static final String RL_CHAT_CMD_PLUGIN_NAME = ChatCommandsPlugin.class.getSimpleName().toLowerCase(); + static final @VisibleForTesting int INIT_TICKS = 10; // 6 seconds after login private final AtomicInteger loginTicks = new AtomicInteger(-1); @@ -36,6 +46,12 @@ public class MetaNotifier extends BaseNotifier { @Inject private ClientThread clientThread; + @Inject + private ConfigManager configManager; + + @Inject + private Gson gson; + @Override public boolean isEnabled() { return StringUtils.isNotBlank(config.metadataWebhook()) && super.isEnabled(); @@ -119,7 +135,8 @@ private void notifyLogin() { new LoginNotificationData.SkillData(experienceTotal, levelTotal, skillLevels), Progress.of(questsCompleted, questsTotal), Progress.of(questPoints, questPointsTotal), - new LoginNotificationData.SlayerData(slayerPoints, slayerStreak) + new LoginNotificationData.SlayerData(slayerPoints, slayerStreak), + getPets() ); createMessage(false, NotificationBody.builder() .type(NotificationType.LOGIN) @@ -130,4 +147,27 @@ private void notifyLogin() { ); } + private Map getPets() { + if ("false".equals(configManager.getConfiguration(RuneLiteConfig.GROUP_NAME, RL_CHAT_CMD_PLUGIN_NAME))) + return null; + + String json = configManager.getRSProfileConfiguration("chatcommands", "pets2"); + if (json == null || !json.startsWith("[") || !json.endsWith("]")) + return null; + + int[] petItemIds; + try { + petItemIds = gson.fromJson(json, int[].class); + } catch (JsonSyntaxException e) { + log.info("Failed to deserialize owned pet IDs", e); + return null; + } + + Map pets = new HashMap<>(petItemIds.length * 4 / 3); + for (int itemId : petItemIds) { + pets.put(itemId, client.getItemDefinition(itemId).getMembersName()); + } + return pets; + } + } diff --git a/src/main/java/dinkplugin/notifiers/data/LoginNotificationData.java b/src/main/java/dinkplugin/notifiers/data/LoginNotificationData.java index 7ad9ed89..d7413a82 100644 --- a/src/main/java/dinkplugin/notifiers/data/LoginNotificationData.java +++ b/src/main/java/dinkplugin/notifiers/data/LoginNotificationData.java @@ -21,6 +21,8 @@ public class LoginNotificationData extends NotificationData { Progress questCount; Progress questPoints; SlayerData slayer; + @Nullable // requires Chat Commands plugin to be enabled + Map petNamesById; @Value public static class SkillData { diff --git a/src/test/java/dinkplugin/notifiers/MetaNotifierTest.java b/src/test/java/dinkplugin/notifiers/MetaNotifierTest.java index 9631215d..87002c3c 100644 --- a/src/test/java/dinkplugin/notifiers/MetaNotifierTest.java +++ b/src/test/java/dinkplugin/notifiers/MetaNotifierTest.java @@ -97,7 +97,8 @@ void testNotify() { new LoginNotificationData.BarbarianAssault(666), new LoginNotificationData.SkillData(xp * skillCount, level * skillCount, levels), Progress.of(21, 158), Progress.of(43, 300), - new LoginNotificationData.SlayerData(2484, 300) + new LoginNotificationData.SlayerData(2484, 300), + null ); verify(messageHandler).createMessage( url, @@ -134,7 +135,8 @@ void testNotifyWithoutCollection() { new LoginNotificationData.BarbarianAssault(666), new LoginNotificationData.SkillData(xp * skillCount, level * skillCount, levels), Progress.of(21, 158), Progress.of(43, 300), - new LoginNotificationData.SlayerData(2484, 300) + new LoginNotificationData.SlayerData(2484, 300), + null ); verify(messageHandler).createMessage( url, From 4ffd9604a7f13c9e7adbaf75a2e50f8916604c3c Mon Sep 17 00:00:00 2001 From: iProdigy Date: Thu, 26 Oct 2023 01:58:19 -0700 Subject: [PATCH 2/6] chore: add test case --- .../dinkplugin/notifiers/MetaNotifier.java | 6 +++--- .../dinkplugin/notifiers/MetaNotifierTest.java | 18 ++++++++++++++++++ .../notifiers/MockedNotifierTest.java | 1 + 3 files changed, 22 insertions(+), 3 deletions(-) diff --git a/src/main/java/dinkplugin/notifiers/MetaNotifier.java b/src/main/java/dinkplugin/notifiers/MetaNotifier.java index 05b95dbe..0efd9469 100644 --- a/src/main/java/dinkplugin/notifiers/MetaNotifier.java +++ b/src/main/java/dinkplugin/notifiers/MetaNotifier.java @@ -36,8 +36,7 @@ @Slf4j @Singleton public class MetaNotifier extends BaseNotifier { - private static final String RL_CHAT_CMD_PLUGIN_NAME = ChatCommandsPlugin.class.getSimpleName().toLowerCase(); - + static final @VisibleForTesting String RL_CHAT_CMD_PLUGIN_NAME = ChatCommandsPlugin.class.getSimpleName().toLowerCase(); static final @VisibleForTesting int INIT_TICKS = 10; // 6 seconds after login private final AtomicInteger loginTicks = new AtomicInteger(-1); @@ -147,7 +146,8 @@ private void notifyLogin() { ); } - private Map getPets() { + @VisibleForTesting + Map getPets() { if ("false".equals(configManager.getConfiguration(RuneLiteConfig.GROUP_NAME, RL_CHAT_CMD_PLUGIN_NAME))) return null; diff --git a/src/test/java/dinkplugin/notifiers/MetaNotifierTest.java b/src/test/java/dinkplugin/notifiers/MetaNotifierTest.java index 87002c3c..4f562cf8 100644 --- a/src/test/java/dinkplugin/notifiers/MetaNotifierTest.java +++ b/src/test/java/dinkplugin/notifiers/MetaNotifierTest.java @@ -7,11 +7,14 @@ import dinkplugin.notifiers.data.Progress; import net.runelite.api.Experience; import net.runelite.api.GameState; +import net.runelite.api.ItemID; import net.runelite.api.Skill; import net.runelite.api.VarPlayer; import net.runelite.api.Varbits; import net.runelite.api.events.GameStateChanged; +import net.runelite.client.config.RuneLiteConfig; import org.apache.commons.lang3.StringUtils; +import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.mockito.InjectMocks; @@ -165,6 +168,21 @@ void testDisabled() { verify(messageHandler, never()).createMessage(any(), anyBoolean(), any()); } + @Test + void testPetDeserialization() { + when(configManager.getConfiguration(RuneLiteConfig.GROUP_NAME, MetaNotifier.RL_CHAT_CMD_PLUGIN_NAME)) + .thenReturn(Boolean.TRUE.toString()); + + when(configManager.getRSProfileConfiguration("chatcommands", "pets2")) + .thenReturn(String.format("[%d, %d]", ItemID.HERBI, ItemID.BABY_MOLE)); + + mockItem(ItemID.HERBI, 0, "Herbi"); + mockItem(ItemID.BABY_MOLE, 0, "Baby mole"); + + Map expected = Map.of(ItemID.HERBI, "Herbi", ItemID.BABY_MOLE, "Baby mole"); + Assertions.assertEquals(expected, notifier.getPets()); + } + private static GameStateChanged event(GameState state) { GameStateChanged event = new GameStateChanged(); event.setGameState(state); diff --git a/src/test/java/dinkplugin/notifiers/MockedNotifierTest.java b/src/test/java/dinkplugin/notifiers/MockedNotifierTest.java index 46647534..fd99d9a6 100644 --- a/src/test/java/dinkplugin/notifiers/MockedNotifierTest.java +++ b/src/test/java/dinkplugin/notifiers/MockedNotifierTest.java @@ -138,6 +138,7 @@ protected void mockItem(int id, int price, String name) { ItemComposition item = mock(ItemComposition.class); when(item.getName()).thenReturn(name); when(item.getMembersName()).thenReturn(name); + when(client.getItemDefinition(id)).thenReturn(item); when(itemManager.getItemComposition(id)).thenReturn(item); when(itemManager.canonicalize(id)).thenReturn(id); } From 1cfdccbf56371e785711812ee1bd1f3c79bcf6bb Mon Sep 17 00:00:00 2001 From: iProdigy <8106344+iProdigy@users.noreply.github.com> Date: Thu, 26 Oct 2023 02:00:24 -0700 Subject: [PATCH 3/6] chore: update changelog --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 85d80c2c..1a155b96 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,7 @@ ## Unreleased +- Minor: Include owned pets in login notification metadata. (#347) + ## 1.6.4 - Minor: Add task progress metadata for diary notifications. (#331) From eebdb7bcef930b00a273bceeebbcfe7135a95dcc Mon Sep 17 00:00:00 2001 From: iProdigy Date: Thu, 26 Oct 2023 10:31:53 -0700 Subject: [PATCH 4/6] chore: rename metadata field --- README.md | 6 ++++++ .../dinkplugin/notifiers/data/LoginNotificationData.java | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 3357049a..a6631c48 100644 --- a/README.md +++ b/README.md @@ -834,6 +834,10 @@ On login, Dink can submit a character summary containing data that spans multipl "slayer": { "points": 2204, "streak": 1074 + }, + "pets": { + "11995": "Pet chaos elemental", + "13071": "Chompy chick" } } } @@ -841,6 +845,8 @@ On login, Dink can submit a character summary containing data that spans multipl Note: `clanName` requires `Advanced > Send Clan Name` to be enabled (default: on). The `groupIronClanName` and `discordUser` fields also have similar toggles in the Advanced config section. +Note: `extra.pets` is a mapping of item ID to the pet's name. This requires the base Chat Commands plugin to be enabled. + ## Credits diff --git a/src/main/java/dinkplugin/notifiers/data/LoginNotificationData.java b/src/main/java/dinkplugin/notifiers/data/LoginNotificationData.java index d7413a82..75f05981 100644 --- a/src/main/java/dinkplugin/notifiers/data/LoginNotificationData.java +++ b/src/main/java/dinkplugin/notifiers/data/LoginNotificationData.java @@ -22,7 +22,7 @@ public class LoginNotificationData extends NotificationData { Progress questPoints; SlayerData slayer; @Nullable // requires Chat Commands plugin to be enabled - Map petNamesById; + Map pets; @Value public static class SkillData { From 3c549bd371da8c71a2a64bbea607444860a6f19d Mon Sep 17 00:00:00 2001 From: iProdigy Date: Thu, 26 Oct 2023 10:51:06 -0700 Subject: [PATCH 5/6] refactor: serialize pets as an array of objects --- README.md | 16 +++++++++++----- .../java/dinkplugin/notifiers/MetaNotifier.java | 10 ++++++---- .../notifiers/data/LoginNotificationData.java | 4 +++- src/main/java/dinkplugin/util/SerializedPet.java | 9 +++++++++ .../dinkplugin/notifiers/MetaNotifierTest.java | 7 ++++++- 5 files changed, 35 insertions(+), 11 deletions(-) create mode 100644 src/main/java/dinkplugin/util/SerializedPet.java diff --git a/README.md b/README.md index a6631c48..195a68be 100644 --- a/README.md +++ b/README.md @@ -835,17 +835,23 @@ On login, Dink can submit a character summary containing data that spans multipl "points": 2204, "streak": 1074 }, - "pets": { - "11995": "Pet chaos elemental", - "13071": "Chompy chick" - } + "pets": [ + { + "itemId": 11995, + "name": "Pet chaos elemental" + }, + { + "itemId": 13071, + "name": "Chompy chick" + } + ] } } ``` Note: `clanName` requires `Advanced > Send Clan Name` to be enabled (default: on). The `groupIronClanName` and `discordUser` fields also have similar toggles in the Advanced config section. -Note: `extra.pets` is a mapping of item ID to the pet's name. This requires the base Chat Commands plugin to be enabled. +Note: `extra.pets` requires the base Chat Commands plugin to be enabled. diff --git a/src/main/java/dinkplugin/notifiers/MetaNotifier.java b/src/main/java/dinkplugin/notifiers/MetaNotifier.java index 0efd9469..79bf7968 100644 --- a/src/main/java/dinkplugin/notifiers/MetaNotifier.java +++ b/src/main/java/dinkplugin/notifiers/MetaNotifier.java @@ -9,6 +9,7 @@ import dinkplugin.message.templating.Template; import dinkplugin.notifiers.data.LoginNotificationData; import dinkplugin.notifiers.data.Progress; +import dinkplugin.util.SerializedPet; import dinkplugin.util.Utils; import lombok.extern.slf4j.Slf4j; import net.runelite.api.Experience; @@ -26,8 +27,9 @@ import javax.inject.Inject; import javax.inject.Singleton; +import java.util.ArrayList; import java.util.Arrays; -import java.util.HashMap; +import java.util.List; import java.util.Map; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicReference; @@ -147,7 +149,7 @@ private void notifyLogin() { } @VisibleForTesting - Map getPets() { + List getPets() { if ("false".equals(configManager.getConfiguration(RuneLiteConfig.GROUP_NAME, RL_CHAT_CMD_PLUGIN_NAME))) return null; @@ -163,9 +165,9 @@ Map getPets() { return null; } - Map pets = new HashMap<>(petItemIds.length * 4 / 3); + List pets = new ArrayList<>(petItemIds.length); for (int itemId : petItemIds) { - pets.put(itemId, client.getItemDefinition(itemId).getMembersName()); + pets.add(new SerializedPet(itemId, client.getItemDefinition(itemId).getMembersName())); } return pets; } diff --git a/src/main/java/dinkplugin/notifiers/data/LoginNotificationData.java b/src/main/java/dinkplugin/notifiers/data/LoginNotificationData.java index 75f05981..5cde675c 100644 --- a/src/main/java/dinkplugin/notifiers/data/LoginNotificationData.java +++ b/src/main/java/dinkplugin/notifiers/data/LoginNotificationData.java @@ -1,9 +1,11 @@ package dinkplugin.notifiers.data; +import dinkplugin.util.SerializedPet; import lombok.EqualsAndHashCode; import lombok.Value; import org.jetbrains.annotations.Nullable; +import java.util.List; import java.util.Map; @Value @@ -22,7 +24,7 @@ public class LoginNotificationData extends NotificationData { Progress questPoints; SlayerData slayer; @Nullable // requires Chat Commands plugin to be enabled - Map pets; + List pets; @Value public static class SkillData { diff --git a/src/main/java/dinkplugin/util/SerializedPet.java b/src/main/java/dinkplugin/util/SerializedPet.java new file mode 100644 index 00000000..2cac4bfe --- /dev/null +++ b/src/main/java/dinkplugin/util/SerializedPet.java @@ -0,0 +1,9 @@ +package dinkplugin.util; + +import lombok.Value; + +@Value +public class SerializedPet { + int itemId; + String name; +} diff --git a/src/test/java/dinkplugin/notifiers/MetaNotifierTest.java b/src/test/java/dinkplugin/notifiers/MetaNotifierTest.java index 4f562cf8..b8026c1d 100644 --- a/src/test/java/dinkplugin/notifiers/MetaNotifierTest.java +++ b/src/test/java/dinkplugin/notifiers/MetaNotifierTest.java @@ -5,6 +5,7 @@ import dinkplugin.message.NotificationType; import dinkplugin.notifiers.data.LoginNotificationData; import dinkplugin.notifiers.data.Progress; +import dinkplugin.util.SerializedPet; import net.runelite.api.Experience; import net.runelite.api.GameState; import net.runelite.api.ItemID; @@ -20,6 +21,7 @@ import org.mockito.InjectMocks; import java.util.Arrays; +import java.util.List; import java.util.Map; import java.util.stream.Collectors; import java.util.stream.IntStream; @@ -179,7 +181,10 @@ void testPetDeserialization() { mockItem(ItemID.HERBI, 0, "Herbi"); mockItem(ItemID.BABY_MOLE, 0, "Baby mole"); - Map expected = Map.of(ItemID.HERBI, "Herbi", ItemID.BABY_MOLE, "Baby mole"); + List expected = List.of( + new SerializedPet(ItemID.HERBI, "Herbi"), + new SerializedPet(ItemID.BABY_MOLE, "Baby mole") + ); Assertions.assertEquals(expected, notifier.getPets()); } From 2e5ac4ccf5bc4e8477e036982c7dd9795654ef4e Mon Sep 17 00:00:00 2001 From: iProdigy Date: Thu, 26 Oct 2023 10:56:51 -0700 Subject: [PATCH 6/6] chore: simplify stored config value check --- src/main/java/dinkplugin/notifiers/MetaNotifier.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/dinkplugin/notifiers/MetaNotifier.java b/src/main/java/dinkplugin/notifiers/MetaNotifier.java index 79bf7968..6c2d8a12 100644 --- a/src/main/java/dinkplugin/notifiers/MetaNotifier.java +++ b/src/main/java/dinkplugin/notifiers/MetaNotifier.java @@ -154,7 +154,7 @@ List getPets() { return null; String json = configManager.getRSProfileConfiguration("chatcommands", "pets2"); - if (json == null || !json.startsWith("[") || !json.endsWith("]")) + if (json == null || json.isEmpty()) return null; int[] petItemIds;