From 9c4df28f2b59a18e004413e22e3fad6b6b17991e Mon Sep 17 00:00:00 2001 From: Adam Date: Fri, 25 Jan 2019 17:27:19 -0500 Subject: [PATCH 1/3] chat controller: fix method name of getQp --- .../java/net/runelite/http/service/chat/ChatController.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/http-service/src/main/java/net/runelite/http/service/chat/ChatController.java b/http-service/src/main/java/net/runelite/http/service/chat/ChatController.java index 0a95b71336..d1c6d71b7a 100644 --- a/http-service/src/main/java/net/runelite/http/service/chat/ChatController.java +++ b/http-service/src/main/java/net/runelite/http/service/chat/ChatController.java @@ -97,7 +97,7 @@ public class ChatController } @GetMapping("/qp") - public int getKc(@RequestParam String name) + public int getQp(@RequestParam String name) { Integer kc = chatService.getQp(name); if (kc == null) From 9d5dad5cad319221dee94e9d3764b820fb51ffa7 Mon Sep 17 00:00:00 2001 From: Adam Date: Fri, 25 Jan 2019 17:03:30 -0500 Subject: [PATCH 2/3] Add !pb chat command --- .../runelite/http/api/chat/ChatClient.java | 44 ++++++ .../http/service/chat/ChatController.java | 22 +++ .../http/service/chat/ChatService.java | 18 +++ .../chatcommands/ChatCommandsConfig.java | 11 ++ .../chatcommands/ChatCommandsPlugin.java | 140 +++++++++++++++++- .../chatcommands/ChatCommandsPluginTest.java | 35 +++++ 6 files changed, 269 insertions(+), 1 deletion(-) diff --git a/http-api/src/main/java/net/runelite/http/api/chat/ChatClient.java b/http-api/src/main/java/net/runelite/http/api/chat/ChatClient.java index 8ec5b2a351..1de7d524f1 100644 --- a/http-api/src/main/java/net/runelite/http/api/chat/ChatClient.java +++ b/http-api/src/main/java/net/runelite/http/api/chat/ChatClient.java @@ -172,4 +172,48 @@ public class ChatClient throw new IOException(ex); } } + + public boolean submitPb(String username, String boss, int pb) throws IOException + { + HttpUrl url = RuneLiteAPI.getApiBase().newBuilder() + .addPathSegment("chat") + .addPathSegment("pb") + .addQueryParameter("name", username) + .addQueryParameter("boss", boss) + .addQueryParameter("pb", Integer.toString(pb)) + .build(); + + Request request = new Request.Builder() + .post(RequestBody.create(null, new byte[0])) + .url(url) + .build(); + + try (Response response = RuneLiteAPI.CLIENT.newCall(request).execute()) + { + return response.isSuccessful(); + } + } + + public int getPb(String username, String boss) throws IOException + { + HttpUrl url = RuneLiteAPI.getApiBase().newBuilder() + .addPathSegment("chat") + .addPathSegment("pb") + .addQueryParameter("name", username) + .addQueryParameter("boss", boss) + .build(); + + Request request = new Request.Builder() + .url(url) + .build(); + + try (Response response = RuneLiteAPI.CLIENT.newCall(request).execute()) + { + if (!response.isSuccessful()) + { + throw new IOException("Unable to look up personal best!"); + } + return Integer.parseInt(response.body().string()); + } + } } diff --git a/http-service/src/main/java/net/runelite/http/service/chat/ChatController.java b/http-service/src/main/java/net/runelite/http/service/chat/ChatController.java index d1c6d71b7a..5b7b6b6b98 100644 --- a/http-service/src/main/java/net/runelite/http/service/chat/ChatController.java +++ b/http-service/src/main/java/net/runelite/http/service/chat/ChatController.java @@ -133,4 +133,26 @@ public class ChatController { return chatService.getTask(name); } + + @PostMapping("/pb") + public void submitPb(@RequestParam String name, @RequestParam int pb) + { + if (pb < 0) + { + return; + } + + chatService.setPb(name, pb); + } + + @GetMapping("/pb") + public int getPb(@RequestParam String name) + { + Integer pb = chatService.getPb(name); + if (pb == null) + { + throw new NotFoundException(); + } + return pb; + } } diff --git a/http-service/src/main/java/net/runelite/http/service/chat/ChatService.java b/http-service/src/main/java/net/runelite/http/service/chat/ChatService.java index 24b16086f8..78c16b4482 100644 --- a/http-service/src/main/java/net/runelite/http/service/chat/ChatService.java +++ b/http-service/src/main/java/net/runelite/http/service/chat/ChatService.java @@ -121,4 +121,22 @@ public class ChatService jedis.expire(key, (int) EXPIRE.getSeconds()); } } + + public Integer getPb(String name) + { + String value; + try (Jedis jedis = jedisPool.getResource()) + { + value = jedis.get("pb." + name); + } + return value == null ? null : Integer.parseInt(value); + } + + public void setPb(String name, int pb) + { + try (Jedis jedis = jedisPool.getResource()) + { + jedis.setex("pb." + name, (int) EXPIRE.getSeconds(), Integer.toString(pb)); + } + } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/chatcommands/ChatCommandsConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/chatcommands/ChatCommandsConfig.java index 2c2c321713..16c40d54b7 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/chatcommands/ChatCommandsConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/chatcommands/ChatCommandsConfig.java @@ -88,6 +88,17 @@ public interface ChatCommandsConfig extends Config @ConfigItem( position = 5, + keyName = "pb", + name = "PB Command", + description = "Configures whether the personal best command is enabled
!pb" + ) + default boolean pb() + { + return true; + } + + @ConfigItem( + position = 6, keyName = "clearShortcuts", name = "Clear shortcuts", description = "Enable shortcuts (ctrl+w and backspace) for clearing the chatbox" diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/chatcommands/ChatCommandsPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/chatcommands/ChatCommandsPlugin.java index 1245ab1991..4a6034a887 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/chatcommands/ChatCommandsPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/chatcommands/ChatCommandsPlugin.java @@ -85,6 +85,8 @@ public class ChatCommandsPlugin extends Plugin private static final Pattern RAIDS_PATTERN = Pattern.compile("Your completed (.+) count is: (\\d+)."); private static final Pattern WINTERTODT_PATTERN = Pattern.compile("Your subdued Wintertodt count is: (\\d+)."); private static final Pattern BARROWS_PATTERN = Pattern.compile("Your Barrows chest count is: (\\d+)."); + private static final Pattern KILL_DURATION_PATTERN = Pattern.compile("Fight duration: [0-9:]+. Personal best: ([0-9:]+)."); + private static final Pattern NEW_PB_PATTERN = Pattern.compile("Fight duration: ([0-9:]+) \\(new personal best\\)."); private static final String TOTAL_LEVEL_COMMAND_STRING = "!total"; private static final String PRICE_COMMAND_STRING = "!price"; private static final String LEVEL_COMMAND_STRING = "!lvl"; @@ -92,12 +94,14 @@ public class ChatCommandsPlugin extends Plugin private static final String KILLCOUNT_COMMAND_STRING = "!kc"; private static final String CMB_COMMAND_STRING = "!cmb"; private static final String QP_COMMAND_STRING = "!qp"; + private static final String PB_COMMAND = "!pb"; private final HiscoreClient hiscoreClient = new HiscoreClient(); private final ChatClient chatClient = new ChatClient(); private boolean logKills; private HiscoreEndpoint hiscoreEndpoint; // hiscore endpoint for current player + private String lastBossKill; @Inject private Client client; @@ -138,11 +142,14 @@ public class ChatCommandsPlugin extends Plugin chatCommandManager.registerCommandAsync(CLUES_COMMAND_STRING, this::clueLookup); chatCommandManager.registerCommandAsync(KILLCOUNT_COMMAND_STRING, this::killCountLookup, this::killCountSubmit); chatCommandManager.registerCommandAsync(QP_COMMAND_STRING, this::questPointsLookup, this::questPointsSubmit); + chatCommandManager.registerCommandAsync(PB_COMMAND, this::personalBestLookup, this::personalBestSubmit); } @Override public void shutDown() { + lastBossKill = null; + keyManager.unregisterKeyListener(chatKeyboardListener); chatCommandManager.unregisterCommand(TOTAL_LEVEL_COMMAND_STRING); @@ -152,6 +159,7 @@ public class ChatCommandsPlugin extends Plugin chatCommandManager.unregisterCommand(CLUES_COMMAND_STRING); chatCommandManager.unregisterCommand(KILLCOUNT_COMMAND_STRING); chatCommandManager.unregisterCommand(QP_COMMAND_STRING); + chatCommandManager.unregisterCommand(PB_COMMAND); } @Provides @@ -173,6 +181,19 @@ public class ChatCommandsPlugin extends Plugin return killCount == null ? 0 : killCount; } + private void setPb(String boss, int seconds) + { + configManager.setConfiguration("personalbest." + client.getUsername().toLowerCase(), + boss.toLowerCase(), seconds); + } + + private int getPb(String boss) + { + Integer personalBest = configManager.getConfiguration("personalbest." + client.getUsername().toLowerCase(), + boss.toLowerCase(), int.class); + return personalBest == null ? 0 : personalBest; + } + @Subscribe public void onChatMessage(ChatMessage chatMessage) { @@ -189,6 +210,8 @@ public class ChatCommandsPlugin extends Plugin int kc = Integer.parseInt(matcher.group(2)); setKc(boss, kc); + lastBossKill = boss; + return; } matcher = WINTERTODT_PATTERN.matcher(message); @@ -206,6 +229,8 @@ public class ChatCommandsPlugin extends Plugin int kc = Integer.parseInt(matcher.group(2)); setKc(boss, kc); + lastBossKill = boss; + return; } matcher = BARROWS_PATTERN.matcher(message); @@ -215,6 +240,35 @@ public class ChatCommandsPlugin extends Plugin setKc("Barrows Chests", kc); } + + if (lastBossKill != null) + { + matcher = KILL_DURATION_PATTERN.matcher(message); + if (matcher.find()) + { + matchPb(matcher); + } + + matcher = NEW_PB_PATTERN.matcher(message); + if (matcher.find()) + { + matchPb(matcher); + } + } + + lastBossKill = null; + } + + private void matchPb(Matcher matcher) + { + String personalBest = matcher.group(1); + String[] s = personalBest.split(":"); + if (s.length == 2) + { + int seconds = Integer.parseInt(s[0]) * 60 + Integer.parseInt(s[1]); + log.debug("Got personal best for {}: {}", lastBossKill, seconds); + setPb(lastBossKill, seconds); + } } @Subscribe @@ -411,7 +465,91 @@ public class ChatCommandsPlugin extends Plugin } catch (Exception ex) { - log.warn("unable to submit quest poinits", ex); + log.warn("unable to submit quest points", ex); + } + finally + { + chatInput.resume(); + } + }); + + return true; + } + + private void personalBestLookup(SetMessage setMessage, String message) + { + if (!config.pb()) + { + return; + } + + ChatMessageType type = setMessage.getType(); + String search = message.substring(PB_COMMAND.length() + 1); + + final String player; + if (type.equals(ChatMessageType.PRIVATE_MESSAGE_SENT)) + { + player = client.getLocalPlayer().getName(); + } + else + { + player = sanitize(setMessage.getName()); + } + + search = longBossName(search); + + final int pb; + try + { + pb = chatClient.getPb(player, search); + } + catch (IOException ex) + { + log.debug("unable to lookup personal best", ex); + return; + } + + int minutes = pb / 60; + int seconds = pb % 60; + + String response = new ChatMessageBuilder() + .append(ChatColorType.HIGHLIGHT) + .append(search) + .append(ChatColorType.NORMAL) + .append(" personal best: ") + .append(ChatColorType.HIGHLIGHT) + .append(String.format("%d:%02d", minutes, seconds)) + .build(); + + log.debug("Setting response {}", response); + final MessageNode messageNode = setMessage.getMessageNode(); + messageNode.setRuneLiteFormatMessage(response); + chatMessageManager.update(messageNode); + client.refreshChat(); + } + + private boolean personalBestSubmit(ChatInput chatInput, String value) + { + int idx = value.indexOf(' '); + final String boss = longBossName(value.substring(idx + 1)); + + final int pb = getPb(boss); + if (pb <= 0) + { + return false; + } + + final String playerName = client.getLocalPlayer().getName(); + + executor.execute(() -> + { + try + { + chatClient.submitPb(playerName, boss, pb); + } + catch (Exception ex) + { + log.warn("unable to submit personal best", ex); } finally { diff --git a/runelite-client/src/test/java/net/runelite/client/plugins/chatcommands/ChatCommandsPluginTest.java b/runelite-client/src/test/java/net/runelite/client/plugins/chatcommands/ChatCommandsPluginTest.java index 858f72ac8d..a553b73f89 100644 --- a/runelite-client/src/test/java/net/runelite/client/plugins/chatcommands/ChatCommandsPluginTest.java +++ b/runelite-client/src/test/java/net/runelite/client/plugins/chatcommands/ChatCommandsPluginTest.java @@ -37,6 +37,7 @@ import net.runelite.client.config.ConfigManager; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import static org.mockito.Matchers.eq; import org.mockito.Mock; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -128,4 +129,38 @@ public class ChatCommandsPluginTest verify(configManager).setConfiguration("killcount.adam", "barrows chests", 277); } + + @Test + public void testPersonalBest() + { + final String FIGHT_DURATION = "Fight duration: 2:06. Personal best: 1:19."; + + when(client.getUsername()).thenReturn("Adam"); + + // This sets lastBoss + ChatMessage chatMessage = new ChatMessage(SERVER, "", "Your Kree'arra kill count is: 4.", null); + chatCommandsPlugin.onChatMessage(chatMessage); + + chatMessage = new ChatMessage(SERVER, "", FIGHT_DURATION, null); + chatCommandsPlugin.onChatMessage(chatMessage); + + verify(configManager).setConfiguration(eq("personalbest.adam"), eq("kree'arra"), eq(79)); + } + + @Test + public void testNewPersonalBest() + { + final String NEW_PB = "Fight duration: 3:01 (new personal best)."; + + when(client.getUsername()).thenReturn("Adam"); + + // This sets lastBoss + ChatMessage chatMessage = new ChatMessage(SERVER, "", "Your Kree'arra kill count is: 4.", null); + chatCommandsPlugin.onChatMessage(chatMessage); + + chatMessage = new ChatMessage(SERVER, "", NEW_PB, null); + chatCommandsPlugin.onChatMessage(chatMessage); + + verify(configManager).setConfiguration(eq("personalbest.adam"), eq("kree'arra"), eq(181)); + } } \ No newline at end of file From f95ce29cbb95459c0e368d7d2a4a3be96ef208c9 Mon Sep 17 00:00:00 2001 From: Adam Date: Fri, 25 Jan 2019 17:23:12 -0500 Subject: [PATCH 3/3] chat commands: capitalize boss names --- .../client/plugins/chatcommands/ChatCommandsPlugin.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/chatcommands/ChatCommandsPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/chatcommands/ChatCommandsPlugin.java index 4a6034a887..5155cdecdd 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/chatcommands/ChatCommandsPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/chatcommands/ChatCommandsPlugin.java @@ -71,6 +71,7 @@ import net.runelite.http.api.hiscore.HiscoreSkill; import net.runelite.http.api.hiscore.SingleHiscoreSkillResult; import net.runelite.http.api.hiscore.Skill; import net.runelite.http.api.item.ItemPrice; +import org.apache.commons.text.WordUtils; @PluginDescriptor( name = "Chat Commands", @@ -1103,7 +1104,7 @@ public class ChatCommandsPlugin extends Plugin return "Theatre of Blood"; default: - return boss; + return WordUtils.capitalize(boss); } } }