From 730ad1c3c6b5389bf8e0be1c7e96bf8dbf340df1 Mon Sep 17 00:00:00 2001 From: Adam Date: Thu, 8 Aug 2019 12:57:38 -0400 Subject: [PATCH 1/8] config service: return status based on whether set/unset were successful --- .../http/service/config/ConfigController.java | 10 ++++++++-- .../http/service/config/ConfigService.java | 14 ++++++++------ .../http/service/config/ConfigControllerTest.java | 3 +++ 3 files changed, 19 insertions(+), 8 deletions(-) diff --git a/http-service/src/main/java/net/runelite/http/service/config/ConfigController.java b/http-service/src/main/java/net/runelite/http/service/config/ConfigController.java index b14a03659c..971094a585 100644 --- a/http-service/src/main/java/net/runelite/http/service/config/ConfigController.java +++ b/http-service/src/main/java/net/runelite/http/service/config/ConfigController.java @@ -81,7 +81,10 @@ public class ConfigController return; } - configService.setKey(session.getUser(), key, value); + if (!configService.setKey(session.getUser(), key, value)) + { + response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); + } } @RequestMapping(path = "/{key:.+}", method = DELETE) @@ -98,6 +101,9 @@ public class ConfigController return; } - configService.unsetKey(session.getUser(), key); + if (!configService.unsetKey(session.getUser(), key)) + { + response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); + } } } diff --git a/http-service/src/main/java/net/runelite/http/service/config/ConfigService.java b/http-service/src/main/java/net/runelite/http/service/config/ConfigService.java index 9fa47ec98c..8a21014b51 100644 --- a/http-service/src/main/java/net/runelite/http/service/config/ConfigService.java +++ b/http-service/src/main/java/net/runelite/http/service/config/ConfigService.java @@ -121,7 +121,7 @@ public class ConfigService return new Configuration(config); } - public void setKey( + public boolean setKey( int userId, String key, @Nullable String value @@ -129,39 +129,41 @@ public class ConfigService { if (key.startsWith("$") || key.startsWith("_")) { - return; + return false; } String[] split = key.split("\\.", 2); if (split.length != 2) { - return; + return false; } Object jsonValue = parseJsonString(value); mongoCollection.updateOne(eq("_userId", userId), set(split[0] + "." + split[1].replace('.', ':'), jsonValue), upsertUpdateOptions); + return true; } - public void unsetKey( + public boolean unsetKey( int userId, String key ) { if (key.startsWith("$") || key.startsWith("_")) { - return; + return false; } String[] split = key.split("\\.", 2); if (split.length != 2) { - return; + return false; } mongoCollection.updateOne(eq("_userId", userId), unset(split[0] + "." + split[1].replace('.', ':'))); + return true; } private static Object parseJsonString(String value) diff --git a/http-service/src/test/java/net/runelite/http/service/config/ConfigControllerTest.java b/http-service/src/test/java/net/runelite/http/service/config/ConfigControllerTest.java index 88657ca04c..27320f3f72 100644 --- a/http-service/src/test/java/net/runelite/http/service/config/ConfigControllerTest.java +++ b/http-service/src/test/java/net/runelite/http/service/config/ConfigControllerTest.java @@ -34,6 +34,7 @@ import org.junit.Test; import org.junit.runner.RunWith; import static org.mockito.Matchers.any; import static org.mockito.Matchers.anyInt; +import static org.mockito.Matchers.anyString; import static org.mockito.Matchers.eq; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; @@ -67,6 +68,8 @@ public class ConfigControllerTest { when(authFilter.handle(any(HttpServletRequest.class), any(HttpServletResponse.class))) .thenReturn(mock(SessionEntry.class)); + + when(configService.setKey(anyInt(), anyString(), anyString())).thenReturn(true); } @Test From 4286c680f20a275ba44a93b2d221699770b24986 Mon Sep 17 00:00:00 2001 From: Adam Date: Thu, 8 Aug 2019 12:59:31 -0400 Subject: [PATCH 2/8] config service: add test for parseJsonString --- .../http/service/config/ConfigService.java | 4 +- .../service/config/ConfigServiceTest.java | 43 +++++++++++++++++++ 2 files changed, 46 insertions(+), 1 deletion(-) create mode 100644 http-service/src/test/java/net/runelite/http/service/config/ConfigServiceTest.java diff --git a/http-service/src/main/java/net/runelite/http/service/config/ConfigService.java b/http-service/src/main/java/net/runelite/http/service/config/ConfigService.java index 8a21014b51..395c46f64d 100644 --- a/http-service/src/main/java/net/runelite/http/service/config/ConfigService.java +++ b/http-service/src/main/java/net/runelite/http/service/config/ConfigService.java @@ -24,6 +24,7 @@ */ package net.runelite.http.service.config; +import com.google.common.annotations.VisibleForTesting; import com.google.gson.Gson; import com.google.gson.JsonSyntaxException; import com.mongodb.client.MongoClient; @@ -166,7 +167,8 @@ public class ConfigService return true; } - private static Object parseJsonString(String value) + @VisibleForTesting + static Object parseJsonString(String value) { Object jsonValue; try diff --git a/http-service/src/test/java/net/runelite/http/service/config/ConfigServiceTest.java b/http-service/src/test/java/net/runelite/http/service/config/ConfigServiceTest.java new file mode 100644 index 0000000000..09e94c5d56 --- /dev/null +++ b/http-service/src/test/java/net/runelite/http/service/config/ConfigServiceTest.java @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2019, 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.http.service.config; + +import com.google.common.collect.ImmutableMap; +import static org.junit.Assert.assertEquals; +import org.junit.Test; + +public class ConfigServiceTest +{ + @Test + public void testParseJsonString() + { + assertEquals(1, ConfigService.parseJsonString("1")); + assertEquals(3.14, ConfigService.parseJsonString("3.14")); + assertEquals(1L << 32, ConfigService.parseJsonString("4294967296")); + assertEquals("test", ConfigService.parseJsonString("test")); + assertEquals("test", ConfigService.parseJsonString("\"test\"")); + assertEquals(ImmutableMap.of("key", "value"), ConfigService.parseJsonString("{\"key\": \"value\"}")); + } +} \ No newline at end of file From edfd52af23588922e5172d1c07c58dd62ed3f52a Mon Sep 17 00:00:00 2001 From: Adam Date: Thu, 8 Aug 2019 13:00:22 -0400 Subject: [PATCH 3/8] config service: validate config values --- .../http/service/config/ConfigService.java | 79 +++++++++++++++++++ .../service/config/ConfigServiceTest.java | 12 +++ 2 files changed, 91 insertions(+) diff --git a/http-service/src/main/java/net/runelite/http/service/config/ConfigService.java b/http-service/src/main/java/net/runelite/http/service/config/ConfigService.java index 395c46f64d..bbe8557d88 100644 --- a/http-service/src/main/java/net/runelite/http/service/config/ConfigService.java +++ b/http-service/src/main/java/net/runelite/http/service/config/ConfigService.java @@ -26,6 +26,10 @@ package net.runelite.http.service.config; import com.google.common.annotations.VisibleForTesting; import com.google.gson.Gson; +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonPrimitive; import com.google.gson.JsonSyntaxException; import com.mongodb.client.MongoClient; import com.mongodb.client.MongoCollection; @@ -52,6 +56,9 @@ import org.springframework.stereotype.Service; @Service public class ConfigService { + private static final int MAX_DEPTH = 8; + private static final int MAX_VALUE_LENGTH = 262144; + private final Gson GSON = RuneLiteAPI.GSON; private final UpdateOptions upsertUpdateOptions = new UpdateOptions().upsert(true); @@ -139,6 +146,11 @@ public class ConfigService return false; } + if (!validateJson(value)) + { + return false; + } + Object jsonValue = parseJsonString(value); mongoCollection.updateOne(eq("_userId", userId), set(split[0] + "." + split[1].replace('.', ':'), jsonValue), @@ -205,4 +217,71 @@ public class ConfigService } return jsonValue; } + + @VisibleForTesting + static boolean validateJson(String value) + { + try + { + // I couldn't figure out a better way to do this than a second json parse + JsonElement jsonElement = RuneLiteAPI.GSON.fromJson(value, JsonElement.class); + return validateObject(jsonElement, 1); + } + catch (JsonSyntaxException ex) + { + // the client submits the string representation of objects which is not always valid json, + // eg. a value with a ':' in it. We just ignore it now. We can't json encode the values client + // side due to them already being strings, which prevents gson from being able to convert them + // to ints/floats/maps etc. + return value.length() < MAX_VALUE_LENGTH; + } + } + + private static boolean validateObject(JsonElement jsonElement, int depth) + { + if (depth >= MAX_DEPTH) + { + return false; + } + + if (jsonElement.isJsonObject()) + { + JsonObject jsonObject = jsonElement.getAsJsonObject(); + + for (Map.Entry entry : jsonObject.entrySet()) + { + JsonElement element = entry.getValue(); + + if (!validateObject(element, depth + 1)) + { + return false; + } + } + } + else if (jsonElement.isJsonArray()) + { + JsonArray jsonArray = jsonElement.getAsJsonArray(); + + for (int i = 0; i < jsonArray.size(); ++i) + { + JsonElement element = jsonArray.get(i); + + if (!validateObject(element, depth + 1)) + { + return false; + } + } + } + else if (jsonElement.isJsonPrimitive()) + { + JsonPrimitive jsonPrimitive = jsonElement.getAsJsonPrimitive(); + String value = jsonPrimitive.getAsString(); + if (value.length() >= MAX_VALUE_LENGTH) + { + return false; + } + } + + return true; + } } diff --git a/http-service/src/test/java/net/runelite/http/service/config/ConfigServiceTest.java b/http-service/src/test/java/net/runelite/http/service/config/ConfigServiceTest.java index 09e94c5d56..64c4ef574c 100644 --- a/http-service/src/test/java/net/runelite/http/service/config/ConfigServiceTest.java +++ b/http-service/src/test/java/net/runelite/http/service/config/ConfigServiceTest.java @@ -26,6 +26,7 @@ package net.runelite.http.service.config; import com.google.common.collect.ImmutableMap; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; import org.junit.Test; public class ConfigServiceTest @@ -40,4 +41,15 @@ public class ConfigServiceTest assertEquals("test", ConfigService.parseJsonString("\"test\"")); assertEquals(ImmutableMap.of("key", "value"), ConfigService.parseJsonString("{\"key\": \"value\"}")); } + + @Test + public void testValidateJson() + { + assertTrue(ConfigService.validateJson("1")); + assertTrue(ConfigService.validateJson("3.14")); + assertTrue(ConfigService.validateJson("test")); + assertTrue(ConfigService.validateJson("\"test\"")); + assertTrue(ConfigService.validateJson("key:value")); + assertTrue(ConfigService.validateJson("{\"key\": \"value\"}")); + } } \ No newline at end of file From f300c541dc6a9da480abcaf24abffeb20bee4c6d Mon Sep 17 00:00:00 2001 From: Adam Date: Wed, 7 Aug 2019 19:07:14 -0400 Subject: [PATCH 4/8] xptracker: update lastXp after submitting xp gains This prevents continious updates on logout after the threshold has been reached. Also initialize lastXp when the plugin starts in the event the player is already logged in. --- .../runelite/client/plugins/xptracker/XpTrackerPlugin.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/xptracker/XpTrackerPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/xptracker/XpTrackerPlugin.java index 2da0ffff2c..d178730ae5 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/xptracker/XpTrackerPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/xptracker/XpTrackerPlugin.java @@ -118,7 +118,7 @@ public class XpTrackerPlugin extends Plugin private XpWorldType lastWorldType; private String lastUsername; private long lastTickMillis = 0; - private boolean fetchXp; + private boolean fetchXp; // fetch lastXp for the online xp tracker private long lastXp = 0; private final XpClient xpClient = new XpClient(); @@ -152,6 +152,9 @@ public class XpTrackerPlugin extends Plugin .build(); clientToolbar.addNavigation(navButton); + + // Initialize the last xp if already logged in + fetchXp = true; } @Override @@ -206,6 +209,7 @@ public class XpTrackerPlugin extends Plugin if (Math.abs(totalXp - lastXp) > XP_THRESHOLD) { xpClient.update(username); + lastXp = totalXp; } } } From 3b40f945a71927e2c75bd2da528f3ed25a2577b0 Mon Sep 17 00:00:00 2001 From: Adam Date: Wed, 7 Aug 2019 19:08:26 -0400 Subject: [PATCH 5/8] xptracker: move initialization until after login This fixes the xptracker not being properly initialized if it starts up after the player is already logged in. --- .../plugins/xptracker/XpTrackerPlugin.java | 64 +++++++++++++++---- 1 file changed, 50 insertions(+), 14 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/xptracker/XpTrackerPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/xptracker/XpTrackerPlugin.java index d178730ae5..6de3527bc9 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/xptracker/XpTrackerPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/xptracker/XpTrackerPlugin.java @@ -120,6 +120,7 @@ public class XpTrackerPlugin extends Plugin private long lastTickMillis = 0; private boolean fetchXp; // fetch lastXp for the online xp tracker private long lastXp = 0; + private boolean initializeTracker; private final XpClient xpClient = new XpClient(); private final XpState xpState = new XpState(); @@ -153,8 +154,9 @@ public class XpTrackerPlugin extends Plugin clientToolbar.addNavigation(navButton); - // Initialize the last xp if already logged in + // Initialize the tracker & last xp if already logged in fetchXp = true; + initializeTracker = true; } @Override @@ -188,8 +190,14 @@ public class XpTrackerPlugin extends Plugin fetchXp = true; lastWorldType = type; resetState(); + // Must be set from hitting the LOGGING_IN case below + assert initializeTracker; } } + else if (state == GameState.LOGGING_IN) + { + initializeTracker = true; + } else if (state == GameState.LOGIN_SCREEN) { Player local = client.getLocalPlayer(); @@ -327,6 +335,12 @@ public class XpTrackerPlugin extends Plugin final int startGoalXp = startGoal != null ? client.getVar(startGoal) : -1; final int endGoalXp = endGoal != null ? client.getVar(endGoal) : -1; + if (initializeTracker) + { + // This is the XP sync on login, wait until after login to begin counting + return; + } + if (xpTrackerConfig.hideMaxed() && currentLevel >= Experience.MAX_REAL_LEVEL) { return; @@ -345,18 +359,9 @@ public class XpTrackerPlugin extends Plugin final XpUpdateResult updateResult = xpState.updateSkill(skill, currentXp, startGoalXp, endGoalXp); xpPanel.updateSkillExperience(updateResult == XpUpdateResult.UPDATED, xpPauseState.isPaused(skill), skill, xpState.getSkillSnapshot(skill)); - if (skill == Skill.CONSTRUCTION && updateResult == XpUpdateResult.INITIALIZED) - { - // Construction is the last skill initialized on login, now initialize the total experience - long overallXp = client.getOverallExperience(); - log.debug("Initializing XP tracker with {} overall exp", overallXp); - xpState.initializeSkill(Skill.OVERALL, overallXp); - } - else if (xpState.isInitialized(Skill.OVERALL)) - { - xpState.updateSkill(Skill.OVERALL, client.getOverallExperience(), -1, -1); - xpPanel.updateTotal(xpState.getTotalSnapshot()); - } + // Also update the total experience + xpState.updateSkill(Skill.OVERALL, client.getOverallExperience(), -1, -1); + xpPanel.updateTotal(xpState.getTotalSnapshot()); } @Subscribe @@ -382,12 +387,43 @@ public class XpTrackerPlugin extends Plugin @Subscribe public void onGameTick(GameTick event) { - rebuildSkills(); + if (initializeTracker) + { + initializeTracker = false; + + // Initialize the tracker with the initial xp if not already initialized + for (Skill skill : Skill.values()) + { + if (skill == Skill.OVERALL) + { + continue; + } + + if (!xpState.isInitialized(skill)) + { + final int currentXp = client.getSkillExperience(skill); + // goal exps are not necessary for skill initialization + XpUpdateResult xpUpdateResult = xpState.updateSkill(skill, currentXp, -1, -1); + assert xpUpdateResult == XpUpdateResult.INITIALIZED; + } + } + + // Initialize the overall xp + if (!xpState.isInitialized(Skill.OVERALL)) + { + long overallXp = client.getOverallExperience(); + log.debug("Initializing XP tracker with {} overall exp", overallXp); + xpState.initializeSkill(Skill.OVERALL, overallXp); + } + } + if (fetchXp) { lastXp = client.getOverallExperience(); fetchXp = false; } + + rebuildSkills(); } @Subscribe From 2ef1f29c13975ff45400ce3e1d4d0e5bcfe331ed Mon Sep 17 00:00:00 2001 From: Adam Date: Wed, 7 Aug 2019 19:08:31 -0400 Subject: [PATCH 6/8] xptracker: support xp gains when offline When xp is gained when offline, the tracker calculates it into the xp/hr, which can lead to very skewed stats due to the tracker being generally paused when the player is offline. This offsets the start xp by the gains when offline to correct for it. --- .../plugins/xptracker/XpStateSingle.java | 13 +++++++--- .../plugins/xptracker/XpTrackerPlugin.java | 26 +++++++++++++++++++ 2 files changed, 35 insertions(+), 4 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/xptracker/XpStateSingle.java b/runelite-client/src/main/java/net/runelite/client/plugins/xptracker/XpStateSingle.java index 2b6c694ba1..af37a7ec3c 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/xptracker/XpStateSingle.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/xptracker/XpStateSingle.java @@ -28,21 +28,20 @@ package net.runelite.client.plugins.xptracker; import java.util.HashMap; import java.util.Map; import lombok.Getter; -import lombok.RequiredArgsConstructor; import lombok.Setter; import lombok.extern.slf4j.Slf4j; import net.runelite.api.Experience; import net.runelite.api.Skill; @Slf4j -@RequiredArgsConstructor class XpStateSingle { private final Skill skill; private final Map actions = new HashMap<>(); @Getter - private final long startXp; + @Setter + private long startXp; @Getter private int xpGained = 0; @@ -54,13 +53,19 @@ class XpStateSingle private int startLevelExp = 0; private int endLevelExp = 0; + XpStateSingle(Skill skill, long startXp) + { + this.skill = skill; + this.startXp = startXp; + } + XpAction getXpAction(final XpActionType type) { actions.putIfAbsent(type, new XpAction()); return actions.get(type); } - private long getCurrentXp() + long getCurrentXp() { return startXp + xpGained; } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/xptracker/XpTrackerPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/xptracker/XpTrackerPlugin.java index 6de3527bc9..6aa4238299 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/xptracker/XpTrackerPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/xptracker/XpTrackerPlugin.java @@ -391,6 +391,32 @@ public class XpTrackerPlugin extends Plugin { initializeTracker = false; + // Check for xp gained while logged out + for (Skill skill : Skill.values()) + { + if (skill == Skill.OVERALL || !xpState.isInitialized(skill)) + { + continue; + } + + XpStateSingle skillState = xpState.getSkill(skill); + final int currentXp = client.getSkillExperience(skill); + if (skillState.getCurrentXp() != currentXp) + { + if (currentXp < skillState.getCurrentXp()) + { + log.debug("Xp is going backwards! {} {} -> {}", skill, skillState.getCurrentXp(), currentXp); + resetState(); + break; + } + + log.debug("Skill xp for {} changed when offline: {} -> {}", skill, skillState.getCurrentXp(), currentXp); + // Offset start xp for offline gains + long diff = skillState.getCurrentXp() - currentXp; + skillState.setStartXp(skillState.getStartXp() + diff); + } + } + // Initialize the tracker with the initial xp if not already initialized for (Skill skill : Skill.values()) { From 05ca96c3db49257f6adce9280f143966fc86cd08 Mon Sep 17 00:00:00 2001 From: Adam Date: Wed, 7 Aug 2019 19:18:29 -0400 Subject: [PATCH 7/8] cml plugin: fix request throttling Also update xp threshold to 10k xp --- .../crystalmathlabs/CrystalMathLabs.java | 26 ++++++++----------- 1 file changed, 11 insertions(+), 15 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/crystalmathlabs/CrystalMathLabs.java b/runelite-client/src/main/java/net/runelite/client/plugins/crystalmathlabs/CrystalMathLabs.java index 155b3bfcc6..65b45bdef0 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/crystalmathlabs/CrystalMathLabs.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/crystalmathlabs/CrystalMathLabs.java @@ -31,7 +31,6 @@ import lombok.extern.slf4j.Slf4j; import net.runelite.api.Client; import net.runelite.api.GameState; import net.runelite.api.Player; -import net.runelite.api.Skill; import net.runelite.api.events.GameStateChanged; import net.runelite.api.events.GameTick; import net.runelite.client.eventbus.Subscribe; @@ -57,7 +56,7 @@ public class CrystalMathLabs extends Plugin /** * Amount of EXP that must be gained for an update to be submitted. */ - private static final int XP_THRESHOLD = 1000; + private static final int XP_THRESHOLD = 10000; @Inject private Client client; @@ -66,6 +65,12 @@ public class CrystalMathLabs extends Plugin private boolean fetchXp; private long lastXp; + @Override + protected void startUp() + { + fetchXp = true; + } + @Subscribe public void onGameStateChanged(GameStateChanged gameStateChanged) { @@ -75,7 +80,7 @@ public class CrystalMathLabs extends Plugin if (!Objects.equals(client.getUsername(), lastUsername)) { lastUsername = client.getUsername(); - lastXp = getTotalXp(); + fetchXp = true; } } else if (state == GameState.LOGIN_SCREEN) @@ -86,12 +91,13 @@ public class CrystalMathLabs extends Plugin return; } - long totalXp = getTotalXp(); + long totalXp = client.getOverallExperience(); // Don't submit update unless xp threshold is reached if (Math.abs(totalXp - lastXp) > XP_THRESHOLD) { log.debug("Submitting update for {}", local.getName()); sendUpdateRequest(local.getName()); + lastXp = totalXp; } } } @@ -101,21 +107,11 @@ public class CrystalMathLabs extends Plugin { if (fetchXp) { - lastXp = getTotalXp(); + lastXp = client.getOverallExperience(); fetchXp = false; } } - private long getTotalXp() - { - long total = 0; - for (Skill skill : Skill.values()) - { - total += client.getSkillExperience(skill); - } - return total; - } - private void sendUpdateRequest(String username) { String reformedUsername = username.replace(" ", "_"); From 277a3ccd35e55a3010c18bdb9c97d819418f3e06 Mon Sep 17 00:00:00 2001 From: Adam Date: Thu, 8 Aug 2019 16:26:51 -0400 Subject: [PATCH 8/8] http-service: use jndi provided mongo --- http-service/pom.xml | 3 ++- .../http/service/SpringBootWebApplication.java | 18 ++++++++++++++++-- .../src/main/resources/application-dev.yaml | 5 +++++ .../src/main/resources/application.yaml | 2 +- .../src/test/resources/application-test.yaml | 4 ++++ 5 files changed, 28 insertions(+), 4 deletions(-) diff --git a/http-service/pom.xml b/http-service/pom.xml index 62edc0538b..6b650c3205 100644 --- a/http-service/pom.xml +++ b/http-service/pom.xml @@ -125,7 +125,8 @@ org.mongodb mongodb-driver-sync - 3.10.1 + 3.10.2 + provided diff --git a/http-service/src/main/java/net/runelite/http/service/SpringBootWebApplication.java b/http-service/src/main/java/net/runelite/http/service/SpringBootWebApplication.java index 376ef11ec7..5410fc5433 100644 --- a/http-service/src/main/java/net/runelite/http/service/SpringBootWebApplication.java +++ b/http-service/src/main/java/net/runelite/http/service/SpringBootWebApplication.java @@ -32,6 +32,7 @@ import java.io.IOException; import java.time.Instant; import java.util.HashMap; import java.util.Map; +import javax.naming.NamingException; import javax.servlet.ServletContext; import javax.servlet.ServletContextEvent; import javax.servlet.ServletContextListener; @@ -55,6 +56,7 @@ import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.web.support.SpringBootServletInitializer; import org.springframework.context.annotation.Bean; import org.springframework.jdbc.datasource.lookup.JndiDataSourceLookup; +import org.springframework.jndi.JndiTemplate; import org.springframework.scheduling.annotation.EnableScheduling; import org.sql2o.Sql2o; import org.sql2o.converters.Converter; @@ -160,9 +162,21 @@ public class SpringBootWebApplication extends SpringBootServletInitializer } @Bean - public MongoClient mongoClient(@Value("${mongo.host}") String host) + public MongoClient mongoClient(@Value("${mongo.host:}") String host, @Value("${mongo.jndiName:}") String jndiName) throws NamingException { - return MongoClients.create(host); + if (!Strings.isNullOrEmpty(jndiName)) + { + JndiTemplate jndiTemplate = new JndiTemplate(); + return jndiTemplate.lookup(jndiName, MongoClient.class); + } + else if (!Strings.isNullOrEmpty(host)) + { + return MongoClients.create(host); + } + else + { + throw new RuntimeException("Either mongo.host or mongo.jndiName must be set"); + } } private static DataSource getDataSource(DataSourceProperties dataSourceProperties) diff --git a/http-service/src/main/resources/application-dev.yaml b/http-service/src/main/resources/application-dev.yaml index cc2286e9b3..9397951858 100644 --- a/http-service/src/main/resources/application-dev.yaml +++ b/http-service/src/main/resources/application-dev.yaml @@ -26,6 +26,11 @@ datasource: username: runelite password: runelite +# Development mongo +mongo: + jndiName: + host: mongodb://localhost:27017 + # Development oauth callback (without proxy) oauth: callback: http://localhost:8080/account/callback diff --git a/http-service/src/main/resources/application.yaml b/http-service/src/main/resources/application.yaml index 9905e61695..3c6fc451fe 100644 --- a/http-service/src/main/resources/application.yaml +++ b/http-service/src/main/resources/application.yaml @@ -31,7 +31,7 @@ redis: host: http://localhost:6379 mongo: - host: mongodb://localhost:27017 + jndiName: java:comp/env/mongodb/runelite # Twitter client for feed runelite: diff --git a/http-service/src/test/resources/application-test.yaml b/http-service/src/test/resources/application-test.yaml index 0532963ade..3a8e416a54 100644 --- a/http-service/src/test/resources/application-test.yaml +++ b/http-service/src/test/resources/application-test.yaml @@ -15,3 +15,7 @@ datasource: driverClassName: org.h2.Driver type: org.h2.jdbcx.JdbcDataSource url: jdbc:h2:mem:xptracker + +mongo: + jndiName: + host: mongodb://localhost:27017 \ No newline at end of file