Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: include owned pets in login notifications #347

Merged
merged 8 commits into from
Nov 4, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
## Unreleased

- Minor: Include owned pets in login notification metadata. (#347)
- Minor: Include individual skill XP in login notification metadata. (#345)
- Bugfix: Improve handling of queued notifications upon concurrent config changes. (#355)

Expand Down
14 changes: 13 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -859,13 +859,25 @@ On login, Dink can submit a character summary containing data that spans multipl
"slayer": {
"points": 2204,
"streak": 1074
}
},
"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` requires the base Chat Commands plugin to be enabled.

</details>

## Credits
Expand Down
45 changes: 44 additions & 1 deletion src/main/java/dinkplugin/notifiers/MetaNotifier.java
Original file line number Diff line number Diff line change
@@ -1,32 +1,44 @@
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;
import dinkplugin.message.templating.Replacements;
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;
import net.runelite.api.GameState;
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.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.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;

@Slf4j
@Singleton
public class MetaNotifier extends BaseNotifier {
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);
Expand All @@ -35,6 +47,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();
Expand Down Expand Up @@ -123,7 +141,8 @@ private void notifyLogin() {
new LoginNotificationData.SkillData(experienceTotal, levelTotal, skillLevels, skillExperience),
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)
Expand All @@ -134,4 +153,28 @@ private void notifyLogin() {
);
}

@VisibleForTesting
List<SerializedPet> 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.isEmpty())
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;
}

List<SerializedPet> pets = new ArrayList<>(petItemIds.length);
for (int itemId : petItemIds) {
pets.add(new SerializedPet(itemId, client.getItemDefinition(itemId).getMembersName()));
}
return pets;
}

}
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -21,6 +23,8 @@ public class LoginNotificationData extends NotificationData {
Progress questCount;
Progress questPoints;
SlayerData slayer;
@Nullable // requires Chat Commands plugin to be enabled
List<SerializedPet> pets;

@Value
public static class SkillData {
Expand Down
9 changes: 9 additions & 0 deletions src/main/java/dinkplugin/util/SerializedPet.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package dinkplugin.util;

import lombok.Value;

@Value
public class SerializedPet {
int itemId;
String name;
}
29 changes: 27 additions & 2 deletions src/test/java/dinkplugin/notifiers/MetaNotifierTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,23 @@
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;
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;

import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
Expand Down Expand Up @@ -100,7 +105,8 @@ void testNotify() {
new LoginNotificationData.BarbarianAssault(666),
new LoginNotificationData.SkillData(xp * skillCount, level * skillCount, levels, exp),
Progress.of(21, 158), Progress.of(43, 300),
new LoginNotificationData.SlayerData(2484, 300)
new LoginNotificationData.SlayerData(2484, 300),
null
);
verify(messageHandler).createMessage(
url,
Expand Down Expand Up @@ -139,7 +145,8 @@ void testNotifyWithoutCollection() {
new LoginNotificationData.BarbarianAssault(666),
new LoginNotificationData.SkillData(xp * skillCount, level * skillCount, levels, exp),
Progress.of(21, 158), Progress.of(43, 300),
new LoginNotificationData.SlayerData(2484, 300)
new LoginNotificationData.SlayerData(2484, 300),
null
);
verify(messageHandler).createMessage(
url,
Expand Down Expand Up @@ -168,6 +175,24 @@ 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");

List<SerializedPet> expected = List.of(
new SerializedPet(ItemID.HERBI, "Herbi"),
new SerializedPet(ItemID.BABY_MOLE, "Baby mole")
);
Assertions.assertEquals(expected, notifier.getPets());
}

private static GameStateChanged event(GameState state) {
GameStateChanged event = new GameStateChanged();
event.setGameState(state);
Expand Down
1 change: 1 addition & 0 deletions src/test/java/dinkplugin/notifiers/MockedNotifierTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand Down