Merge remote-tracking branch 'upstream/master' into runelite
Also pulled out a couple of our merged apis into our own classes. Getting much easier to keep up to date with their data # Conflicts: # .github/FUNDING.yml # .github/workflows/CI.yml # cache-client/pom.xml # cache-updater/pom.xml # cache/pom.xml # cache/src/main/java/net/runelite/cache/fs/jagex/DiskStorage.java # ci/build.sh # http-api/pom.xml # http-service/pom.xml # http-service/src/main/java/net/runelite/http/service/chat/ChatController.java # http-service/src/main/java/net/runelite/http/service/config/ConfigController.java # http-service/src/main/java/net/runelite/http/service/config/ConfigService.java # http-service/src/main/java/net/runelite/http/service/ge/GrandExchangeController.java # http-service/src/main/java/net/runelite/http/service/ge/Trade.java # http-service/src/test/java/net/runelite/http/service/config/ConfigServiceTest.java # http-service/src/test/java/net/runelite/http/service/hiscore/HiscoreServiceTest.java # pom.xml # runelite-api/pom.xml # runelite-api/src/main/java/net/runelite/api/Client.java # runelite-api/src/main/java/net/runelite/api/ObjectID.java # runelite-api/src/main/java/net/runelite/api/ParamHolder.java # runelite-api/src/main/java/net/runelite/api/ParamID.java # runelite-api/src/main/java/net/runelite/api/Preferences.java # runelite-api/src/main/java/net/runelite/api/ScriptEvent.java # runelite-api/src/main/java/net/runelite/api/ScriptID.java # runelite-api/src/main/java/net/runelite/api/SettingID.java # runelite-api/src/main/java/net/runelite/api/StructComposition.java # runelite-api/src/main/java/net/runelite/api/StructID.java # runelite-api/src/main/java/net/runelite/api/Varbits.java # runelite-api/src/main/java/net/runelite/api/events/PlayerChanged.java # runelite-api/src/main/java/net/runelite/api/events/PostStructComposition.java # runelite-api/src/main/java/net/runelite/api/events/WidgetClosed.java # runelite-api/src/main/java/net/runelite/api/events/WidgetHiddenChanged.java # runelite-api/src/main/java/net/runelite/api/events/WidgetPositioned.java # runelite-api/src/main/java/net/runelite/api/events/WorldChanged.java # runelite-api/src/main/java/net/runelite/api/widgets/Widget.java # runelite-api/src/main/java/net/runelite/api/widgets/WidgetID.java # runelite-api/src/main/java/net/runelite/api/widgets/WidgetInfo.java # runelite-api/src/main/java/net/runelite/api/widgets/WidgetModalMode.java # runelite-api/src/test/java/net/runelite/api/plugins/combatlevel/CombatLevelOverlayTest.java # runelite-client/pom.xml # runelite-client/src/main/java/net/runelite/client/RuneLiteModule.java # runelite-client/src/main/java/net/runelite/client/callback/Hooks.java # runelite-client/src/main/java/net/runelite/client/plugins/config/PluginToggleButton.java # runelite-client/src/main/java/net/runelite/client/plugins/customcursor/CustomCursor.java # runelite-client/src/main/java/net/runelite/client/plugins/menuentryswapper/MenuEntrySwapperConfig.java # runelite-client/src/main/java/net/runelite/client/plugins/mta/alchemy/AlchemyRoomTimer.java # runelite-client/src/main/java/net/runelite/client/plugins/tearsofguthix/TearsOfGuthixOverlay.java # runelite-client/src/main/java/net/runelite/client/plugins/tearsofguthix/TearsOfGuthixPlugin.java # runelite-client/src/main/java/net/runelite/client/plugins/worldhopper/WorldTableHeader.java # runelite-client/src/main/java/net/runelite/client/plugins/worldhopper/WorldTableRow.java # runelite-client/src/main/java/net/runelite/client/ui/ClientUI.java # runelite-client/src/main/resources/net/runelite/client/runelite.properties # runelite-client/src/main/scripts/OptionsPanelZoomUpdater.hash # runelite-client/src/test/java/net/runelite/client/config/ConfigManagerTest.java # runelite-client/src/test/java/net/runelite/client/plugins/chatcommands/ChatCommandsPluginTest.java # runelite-client/src/test/java/net/runelite/client/plugins/chatfilter/ChatFilterPluginTest.java # runelite-client/src/test/java/net/runelite/client/plugins/chatnotifications/ChatNotificationsPluginTest.java # runelite-client/src/test/java/net/runelite/client/plugins/discord/DiscordStateTest.java # runelite-client/src/test/java/net/runelite/client/plugins/grandexchange/GrandExchangePluginTest.java # runelite-client/src/test/java/net/runelite/client/plugins/screenshot/ScreenshotPluginTest.java # runelite-client/src/test/java/net/runelite/client/plugins/specialcounter/SpecialCounterPluginTest.java # runelite-client/src/test/java/net/runelite/client/plugins/timers/TimersPluginTest.java # runelite-client/src/test/java/net/runelite/client/util/ColorUtilTest.java # runelite-script-assembler-plugin/pom.xml
This commit is contained in:
@@ -0,0 +1,250 @@
|
||||
/*
|
||||
* Copyright (c) 2018, Adam <Adam@sigterm.info>
|
||||
* 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.chat;
|
||||
|
||||
import com.google.common.cache.Cache;
|
||||
import com.google.common.cache.CacheBuilder;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import net.runelite.http.api.chat.Duels;
|
||||
import net.runelite.http.api.chat.LayoutRoom;
|
||||
import net.runelite.http.api.chat.Task;
|
||||
import net.runelite.http.service.util.exception.NotFoundException;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.CacheControl;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/chat")
|
||||
public class ChatController
|
||||
{
|
||||
private static final Pattern STRING_VALIDATION = Pattern.compile("[^a-zA-Z0-9' -]");
|
||||
private static final int STRING_MAX_LENGTH = 50;
|
||||
private static final int MAX_LAYOUT_ROOMS = 16;
|
||||
|
||||
private final Cache<KillCountKey, Integer> killCountCache = CacheBuilder.newBuilder()
|
||||
.expireAfterWrite(2, TimeUnit.MINUTES)
|
||||
.maximumSize(128L)
|
||||
.build();
|
||||
|
||||
@Autowired
|
||||
private ChatService chatService;
|
||||
|
||||
@PostMapping("/kc")
|
||||
public void submitKc(@RequestParam String name, @RequestParam String boss, @RequestParam int kc)
|
||||
{
|
||||
if (kc <= 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
chatService.setKc(name, boss, kc);
|
||||
killCountCache.put(new KillCountKey(name, boss), kc);
|
||||
}
|
||||
|
||||
@GetMapping("/kc")
|
||||
public int getKc(@RequestParam String name, @RequestParam String boss)
|
||||
{
|
||||
Integer kc = killCountCache.getIfPresent(new KillCountKey(name, boss));
|
||||
if (kc == null)
|
||||
{
|
||||
kc = chatService.getKc(name, boss);
|
||||
if (kc != null)
|
||||
{
|
||||
killCountCache.put(new KillCountKey(name, boss), kc);
|
||||
}
|
||||
}
|
||||
|
||||
if (kc == null)
|
||||
{
|
||||
throw new NotFoundException();
|
||||
}
|
||||
return kc;
|
||||
}
|
||||
|
||||
@PostMapping("/qp")
|
||||
public void submitQp(@RequestParam String name, @RequestParam int qp)
|
||||
{
|
||||
if (qp < 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
chatService.setQp(name, qp);
|
||||
}
|
||||
|
||||
@GetMapping("/qp")
|
||||
public int getQp(@RequestParam String name)
|
||||
{
|
||||
Integer kc = chatService.getQp(name);
|
||||
if (kc == null)
|
||||
{
|
||||
throw new NotFoundException();
|
||||
}
|
||||
return kc;
|
||||
}
|
||||
|
||||
@PostMapping("/gc")
|
||||
public void submitGc(@RequestParam String name, @RequestParam int gc)
|
||||
{
|
||||
if (gc < 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
chatService.setGc(name, gc);
|
||||
}
|
||||
|
||||
@GetMapping("/gc")
|
||||
public int getKc(@RequestParam String name)
|
||||
{
|
||||
Integer gc = chatService.getGc(name);
|
||||
if (gc == null)
|
||||
{
|
||||
throw new NotFoundException();
|
||||
}
|
||||
return gc;
|
||||
}
|
||||
|
||||
@PostMapping("/task")
|
||||
public void submitTask(@RequestParam String name, @RequestParam("task") String taskName, @RequestParam int amount,
|
||||
@RequestParam int initialAmount, @RequestParam String location)
|
||||
{
|
||||
Matcher mTask = STRING_VALIDATION.matcher(taskName);
|
||||
Matcher mLocation = STRING_VALIDATION.matcher(location);
|
||||
if (mTask.find() || taskName.length() > STRING_MAX_LENGTH ||
|
||||
mLocation.find() || location.length() > STRING_MAX_LENGTH)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Task task = new Task();
|
||||
task.setTask(taskName);
|
||||
task.setAmount(amount);
|
||||
task.setInitialAmount(initialAmount);
|
||||
task.setLocation(location);
|
||||
|
||||
chatService.setTask(name, task);
|
||||
}
|
||||
|
||||
@GetMapping("/task")
|
||||
public ResponseEntity<Task> getTask(@RequestParam String name)
|
||||
{
|
||||
Task task = chatService.getTask(name);
|
||||
if (task == null)
|
||||
{
|
||||
return ResponseEntity.status(HttpStatus.NOT_FOUND)
|
||||
.build();
|
||||
}
|
||||
|
||||
return ResponseEntity.ok()
|
||||
.cacheControl(CacheControl.maxAge(2, TimeUnit.MINUTES).cachePublic())
|
||||
.body(task);
|
||||
}
|
||||
|
||||
@PostMapping("/pb")
|
||||
public void submitPb(@RequestParam String name, @RequestParam String boss, @RequestParam int pb)
|
||||
{
|
||||
if (pb < 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
chatService.setPb(name, boss, pb);
|
||||
}
|
||||
|
||||
@GetMapping("/pb")
|
||||
public int getPb(@RequestParam String name, @RequestParam String boss)
|
||||
{
|
||||
Integer pb = chatService.getPb(name, boss);
|
||||
if (pb == null)
|
||||
{
|
||||
throw new NotFoundException();
|
||||
}
|
||||
return pb;
|
||||
}
|
||||
|
||||
@PostMapping("/duels")
|
||||
public void submitDuels(@RequestParam String name, @RequestParam int wins,
|
||||
@RequestParam int losses,
|
||||
@RequestParam int winningStreak, @RequestParam int losingStreak)
|
||||
{
|
||||
if (wins < 0 || losses < 0 || winningStreak < 0 || losingStreak < 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Duels duels = new Duels();
|
||||
duels.setWins(wins);
|
||||
duels.setLosses(losses);
|
||||
duels.setWinningStreak(winningStreak);
|
||||
duels.setLosingStreak(losingStreak);
|
||||
|
||||
chatService.setDuels(name, duels);
|
||||
}
|
||||
|
||||
@GetMapping("/duels")
|
||||
public Duels getDuels(@RequestParam String name)
|
||||
{
|
||||
Duels duels = chatService.getDuels(name);
|
||||
if (duels == null)
|
||||
{
|
||||
throw new NotFoundException();
|
||||
}
|
||||
return duels;
|
||||
}
|
||||
|
||||
@PostMapping("/layout")
|
||||
public void submitLayout(@RequestParam String name, @RequestBody LayoutRoom[] rooms)
|
||||
{
|
||||
if (rooms.length > MAX_LAYOUT_ROOMS)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
chatService.setLayout(name, rooms);
|
||||
}
|
||||
|
||||
@GetMapping("/layout")
|
||||
public LayoutRoom[] getLayout(@RequestParam String name)
|
||||
{
|
||||
LayoutRoom[] layout = chatService.getLayout(name);
|
||||
|
||||
if (layout == null)
|
||||
{
|
||||
throw new NotFoundException();
|
||||
}
|
||||
|
||||
return layout;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,134 @@
|
||||
/*
|
||||
* Copyright (c) 2019, Adam <Adam@sigterm.info>
|
||||
* 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 java.io.IOException;
|
||||
import java.util.List;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import net.runelite.http.api.config.Configuration;
|
||||
import net.runelite.http.service.account.AuthFilter;
|
||||
import net.runelite.http.service.account.beans.SessionEntry;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PatchMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import static org.springframework.web.bind.annotation.RequestMethod.DELETE;
|
||||
import static org.springframework.web.bind.annotation.RequestMethod.PUT;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/config")
|
||||
public class ConfigController
|
||||
{
|
||||
private final ConfigService configService;
|
||||
private final AuthFilter authFilter;
|
||||
|
||||
@Autowired
|
||||
public ConfigController(ConfigService configService, AuthFilter authFilter)
|
||||
{
|
||||
this.configService = configService;
|
||||
this.authFilter = authFilter;
|
||||
}
|
||||
|
||||
@GetMapping
|
||||
public Configuration get(HttpServletRequest request, HttpServletResponse response) throws IOException
|
||||
{
|
||||
SessionEntry session = authFilter.handle(request, response);
|
||||
|
||||
if (session == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return configService.get(session.getUser());
|
||||
}
|
||||
|
||||
@PatchMapping
|
||||
public List<String> patch(
|
||||
HttpServletRequest request,
|
||||
HttpServletResponse response,
|
||||
@RequestBody Configuration changes
|
||||
) throws IOException
|
||||
{
|
||||
SessionEntry session = authFilter.handle(request, response);
|
||||
if (session == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
List<String> failures = configService.patch(session.getUser(), changes);
|
||||
if (failures.size() != 0)
|
||||
{
|
||||
response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
|
||||
return failures;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@RequestMapping(path = "/{key:.+}", method = PUT)
|
||||
public void setKey(
|
||||
HttpServletRequest request,
|
||||
HttpServletResponse response,
|
||||
@PathVariable String key,
|
||||
@RequestBody(required = false) String value
|
||||
) throws IOException
|
||||
{
|
||||
SessionEntry session = authFilter.handle(request, response);
|
||||
|
||||
if (session == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!configService.setKey(session.getUser(), key, value))
|
||||
{
|
||||
response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
@RequestMapping(path = "/{key:.+}", method = DELETE)
|
||||
public void unsetKey(
|
||||
HttpServletRequest request,
|
||||
HttpServletResponse response,
|
||||
@PathVariable String key
|
||||
) throws IOException
|
||||
{
|
||||
SessionEntry session = authFilter.handle(request, response);
|
||||
|
||||
if (session == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!configService.unsetKey(session.getUser(), key))
|
||||
{
|
||||
response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,341 @@
|
||||
/*
|
||||
* Copyright (c) 2017-2019, Adam <Adam@sigterm.info>
|
||||
* 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.annotations.VisibleForTesting;
|
||||
import com.google.common.base.Strings;
|
||||
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;
|
||||
import com.mongodb.client.MongoDatabase;
|
||||
import static com.mongodb.client.model.Filters.eq;
|
||||
import com.mongodb.client.model.IndexOptions;
|
||||
import com.mongodb.client.model.Indexes;
|
||||
import com.mongodb.client.model.UpdateOptions;
|
||||
import static com.mongodb.client.model.Updates.combine;
|
||||
import static com.mongodb.client.model.Updates.set;
|
||||
import static com.mongodb.client.model.Updates.unset;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import javax.annotation.Nullable;
|
||||
import net.runelite.http.api.RuneLiteAPI;
|
||||
import net.runelite.http.api.config.ConfigEntry;
|
||||
import net.runelite.http.api.config.Configuration;
|
||||
import org.bson.Document;
|
||||
import org.bson.conversions.Bson;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
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);
|
||||
|
||||
private final MongoCollection<Document> mongoCollection;
|
||||
|
||||
@Autowired
|
||||
public ConfigService(
|
||||
MongoClient mongoClient,
|
||||
@Value("${mongo.database}") String databaseName
|
||||
)
|
||||
{
|
||||
|
||||
MongoDatabase database = mongoClient.getDatabase(databaseName);
|
||||
MongoCollection<Document> collection = database.getCollection("config");
|
||||
this.mongoCollection = collection;
|
||||
|
||||
// Create unique index on _userId
|
||||
IndexOptions indexOptions = new IndexOptions().unique(true);
|
||||
collection.createIndex(Indexes.ascending("_userId"), indexOptions);
|
||||
}
|
||||
|
||||
private Document getConfig(int userId)
|
||||
{
|
||||
return mongoCollection.find(eq("_userId", userId)).first();
|
||||
}
|
||||
|
||||
public Configuration get(int userId)
|
||||
{
|
||||
Map<String, Object> configMap = getConfig(userId);
|
||||
|
||||
if (configMap == null || configMap.isEmpty())
|
||||
{
|
||||
return new Configuration(Collections.emptyList());
|
||||
}
|
||||
|
||||
List<ConfigEntry> config = new ArrayList<>();
|
||||
|
||||
for (String group : configMap.keySet())
|
||||
{
|
||||
// Reserved keys
|
||||
if (group.startsWith("_") || group.startsWith("$"))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
Map<String, Object> groupMap = (Map) configMap.get(group);
|
||||
|
||||
for (Map.Entry<String, Object> entry : groupMap.entrySet())
|
||||
{
|
||||
String key = entry.getKey();
|
||||
Object value = entry.getValue();
|
||||
|
||||
if (value instanceof Map || value instanceof Collection)
|
||||
{
|
||||
value = GSON.toJson(entry.getValue());
|
||||
}
|
||||
else if (value == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
ConfigEntry configEntry = new ConfigEntry();
|
||||
configEntry.setKey(group + "." + key.replace(':', '.'));
|
||||
configEntry.setValue(value.toString());
|
||||
config.add(configEntry);
|
||||
}
|
||||
}
|
||||
|
||||
return new Configuration(config);
|
||||
}
|
||||
|
||||
public List<String> patch(int userID, Configuration config)
|
||||
{
|
||||
List<String> failures = new ArrayList<>();
|
||||
List<Bson> sets = new ArrayList<>(config.getConfig().size());
|
||||
for (ConfigEntry entry : config.getConfig())
|
||||
{
|
||||
Bson s = setForKV(entry.getKey(), entry.getValue());
|
||||
if (s == null)
|
||||
{
|
||||
failures.add(entry.getKey());
|
||||
}
|
||||
else
|
||||
{
|
||||
sets.add(s);
|
||||
}
|
||||
}
|
||||
|
||||
if (sets.size() > 0)
|
||||
{
|
||||
mongoCollection.updateOne(
|
||||
eq("_userId", userID),
|
||||
combine(sets),
|
||||
upsertUpdateOptions
|
||||
);
|
||||
}
|
||||
|
||||
return failures;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private Bson setForKV(String key, @Nullable String value)
|
||||
{
|
||||
if (key.startsWith("$") || key.startsWith("_"))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
String[] split = key.split("\\.", 2);
|
||||
if (split.length != 2)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
String dbKey = split[0] + "." + split[1].replace('.', ':');
|
||||
|
||||
if (Strings.isNullOrEmpty(value))
|
||||
{
|
||||
return unset(dbKey);
|
||||
}
|
||||
|
||||
if (!validateJson(value))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
Object jsonValue = parseJsonString(value);
|
||||
return set(dbKey, jsonValue);
|
||||
}
|
||||
|
||||
public boolean setKey(
|
||||
int userId,
|
||||
String key,
|
||||
@Nullable String value
|
||||
)
|
||||
{
|
||||
Bson set = setForKV(key, value);
|
||||
if (set == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
mongoCollection.updateOne(eq("_userId", userId),
|
||||
set,
|
||||
upsertUpdateOptions);
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean unsetKey(
|
||||
int userId,
|
||||
String key
|
||||
)
|
||||
{
|
||||
Bson set = setForKV(key, null);
|
||||
if (set == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
mongoCollection.updateOne(eq("_userId", userId), set);
|
||||
return true;
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
static Object parseJsonString(String value)
|
||||
{
|
||||
Object jsonValue;
|
||||
try
|
||||
{
|
||||
jsonValue = RuneLiteAPI.GSON.fromJson(value, Object.class);
|
||||
if (jsonValue == null)
|
||||
{
|
||||
return value;
|
||||
}
|
||||
else if (jsonValue instanceof Double || jsonValue instanceof Float)
|
||||
{
|
||||
Number number = (Number) jsonValue;
|
||||
if (Math.floor(number.doubleValue()) == number.doubleValue() && !Double.isInfinite(number.doubleValue()))
|
||||
{
|
||||
// value is an int or long. 'number' might be truncated so parse it from 'value'
|
||||
try
|
||||
{
|
||||
jsonValue = Integer.parseInt(value);
|
||||
}
|
||||
catch (NumberFormatException ex)
|
||||
{
|
||||
try
|
||||
{
|
||||
jsonValue = Long.parseLong(value);
|
||||
}
|
||||
catch (NumberFormatException ex2)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (JsonSyntaxException ex)
|
||||
{
|
||||
jsonValue = value;
|
||||
}
|
||||
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);
|
||||
if (jsonElement == null)
|
||||
{
|
||||
return value.length() < MAX_VALUE_LENGTH;
|
||||
}
|
||||
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<String, JsonElement> 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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,158 @@
|
||||
/*
|
||||
* Copyright (c) 2019, Adam <Adam@sigterm.info>
|
||||
* 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.ge;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import java.io.IOException;
|
||||
import java.time.Instant;
|
||||
import java.util.Collection;
|
||||
import java.util.stream.Collectors;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import net.runelite.http.api.RuneLiteAPI;
|
||||
import net.runelite.http.api.ge.GrandExchangeTrade;
|
||||
import net.runelite.http.service.account.AuthFilter;
|
||||
import net.runelite.http.service.account.beans.SessionEntry;
|
||||
import net.runelite.http.service.util.redis.RedisPool;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.DeleteMapping;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import redis.clients.jedis.Jedis;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/ge")
|
||||
public class GrandExchangeController
|
||||
{
|
||||
private static final Gson GSON = RuneLiteAPI.GSON;
|
||||
|
||||
private final GrandExchangeService grandExchangeService;
|
||||
private final AuthFilter authFilter;
|
||||
private final RedisPool redisPool;
|
||||
|
||||
@Autowired
|
||||
public GrandExchangeController(GrandExchangeService grandExchangeService, AuthFilter authFilter, RedisPool redisPool)
|
||||
{
|
||||
this.grandExchangeService = grandExchangeService;
|
||||
this.authFilter = authFilter;
|
||||
this.redisPool = redisPool;
|
||||
}
|
||||
|
||||
@PostMapping
|
||||
public void submit(HttpServletRequest request, HttpServletResponse response, @RequestBody GrandExchangeTrade grandExchangeTrade) throws IOException
|
||||
{
|
||||
SessionEntry session = null;
|
||||
if (request.getHeader(RuneLiteAPI.RUNELITE_AUTH) != null)
|
||||
{
|
||||
session = authFilter.handle(request, response);
|
||||
if (session == null)
|
||||
{
|
||||
// error is set here on the response, so we shouldn't continue
|
||||
return;
|
||||
}
|
||||
}
|
||||
Integer userId = session == null ? null : session.getUser();
|
||||
|
||||
// We don't keep track of pending trades in the web UI, so only add cancelled or completed trades
|
||||
if (userId != null &&
|
||||
grandExchangeTrade.getQty() > 0 &&
|
||||
(grandExchangeTrade.isCancel() || grandExchangeTrade.getQty() == grandExchangeTrade.getTotal()))
|
||||
{
|
||||
grandExchangeService.add(userId, grandExchangeTrade);
|
||||
}
|
||||
|
||||
Trade trade = new Trade();
|
||||
trade.setBuy(grandExchangeTrade.isBuy());
|
||||
trade.setCancel(grandExchangeTrade.isCancel());
|
||||
trade.setLogin(grandExchangeTrade.isLogin());
|
||||
trade.setItemId(grandExchangeTrade.getItemId());
|
||||
trade.setQty(grandExchangeTrade.getQty());
|
||||
trade.setDqty(grandExchangeTrade.getDqty());
|
||||
trade.setTotal(grandExchangeTrade.getTotal());
|
||||
trade.setSpent(grandExchangeTrade.getDspent());
|
||||
trade.setOffer(grandExchangeTrade.getOffer());
|
||||
trade.setSlot(grandExchangeTrade.getSlot());
|
||||
trade.setTime((int) (System.currentTimeMillis() / 1000L));
|
||||
trade.setMachineId(request.getHeader(RuneLiteAPI.RUNELITE_MACHINEID));
|
||||
trade.setUserId(userId);
|
||||
trade.setIp(request.getHeader("X-Forwarded-For"));
|
||||
trade.setUa(request.getHeader("User-Agent"));
|
||||
trade.setWorldType(grandExchangeTrade.getWorldType());
|
||||
trade.setSeq(grandExchangeTrade.getSeq());
|
||||
Instant resetTime = grandExchangeTrade.getResetTime();
|
||||
trade.setResetTime(resetTime == null ? 0L : resetTime.getEpochSecond());
|
||||
|
||||
String json = GSON.toJson(trade);
|
||||
try (Jedis jedis = redisPool.getResource())
|
||||
{
|
||||
jedis.publish("ge", json);
|
||||
}
|
||||
}
|
||||
|
||||
@GetMapping
|
||||
public Collection<GrandExchangeTradeHistory> get(HttpServletRequest request, HttpServletResponse response,
|
||||
@RequestParam(required = false, defaultValue = "1024") int limit,
|
||||
@RequestParam(required = false, defaultValue = "0") int offset) throws IOException
|
||||
{
|
||||
SessionEntry session = authFilter.handle(request, response);
|
||||
|
||||
if (session == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return grandExchangeService.get(session.getUser(), limit, offset).stream()
|
||||
.map(GrandExchangeController::convert)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
private static GrandExchangeTradeHistory convert(TradeEntry tradeEntry)
|
||||
{
|
||||
GrandExchangeTradeHistory grandExchangeTrade = new GrandExchangeTradeHistory();
|
||||
grandExchangeTrade.setBuy(tradeEntry.getAction() == TradeAction.BUY);
|
||||
grandExchangeTrade.setItemId(tradeEntry.getItem());
|
||||
grandExchangeTrade.setQuantity(tradeEntry.getQuantity());
|
||||
grandExchangeTrade.setPrice(tradeEntry.getPrice());
|
||||
grandExchangeTrade.setTime(tradeEntry.getTime());
|
||||
return grandExchangeTrade;
|
||||
}
|
||||
|
||||
@DeleteMapping
|
||||
public void delete(HttpServletRequest request, HttpServletResponse response) throws IOException
|
||||
{
|
||||
SessionEntry session = authFilter.handle(request, response);
|
||||
|
||||
if (session == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
grandExchangeService.delete(session.getUser());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright (c) 2019, Adam <Adam@sigterm.info>
|
||||
* 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 static org.junit.Assert.assertTrue;
|
||||
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\"}"));
|
||||
}
|
||||
|
||||
@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\"}"));
|
||||
assertTrue(ConfigService.validateJson("\n"));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,161 @@
|
||||
/*
|
||||
* Copyright (c) 2017, Adam <Adam@sigterm.info>
|
||||
* 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.hiscore;
|
||||
|
||||
import java.io.IOException;
|
||||
import net.runelite.http.api.hiscore.HiscoreEndpoint;
|
||||
import net.runelite.http.api.hiscore.HiscoreResult;
|
||||
import okhttp3.mockwebserver.MockResponse;
|
||||
import okhttp3.mockwebserver.MockWebServer;
|
||||
import org.junit.After;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
public class HiscoreServiceTest
|
||||
{
|
||||
private static final String RESPONSE = "654683,705,1304518\n"
|
||||
+ "679419,50,107181\n"
|
||||
+ "550667,48,85764\n"
|
||||
+ "861497,50,101366\n"
|
||||
+ "891591,48,87843\n"
|
||||
+ "-1,1,4\n"
|
||||
+ "840255,27,10073\n"
|
||||
+ "1371912,10,1310\n"
|
||||
+ "432193,56,199795\n"
|
||||
+ "495638,56,198304\n"
|
||||
+ "514466,37,27502\n"
|
||||
+ "456981,54,159727\n"
|
||||
+ "459159,49,93010\n"
|
||||
+ "1028855,8,823\n"
|
||||
+ "862906,29,12749\n"
|
||||
+ "795020,31,16097\n"
|
||||
+ "673591,5,495\n"
|
||||
+ "352676,51,112259\n"
|
||||
+ "428419,40,37235\n"
|
||||
+ "461887,43,51971\n"
|
||||
+ "598582,1,10\n"
|
||||
+ "638177,1,0\n"
|
||||
+ "516239,9,1000\n"
|
||||
+ "492790,1,0\n"
|
||||
+ "2,2460\n" // leagues
|
||||
+ "-1,-1\n"
|
||||
+ "73,1738\n"
|
||||
+ "531,1432\n"
|
||||
+ "324,212\n"
|
||||
+ "8008,131\n"
|
||||
+ "1337,911\n"
|
||||
+ "42,14113\n"
|
||||
+ "1,777\n"
|
||||
+ "254,92\n"
|
||||
+ "-1,-1\n" // lms
|
||||
+ "1,241\n" // soul wars
|
||||
+ "24870,37\n"
|
||||
+ "15020,388\n"
|
||||
+ "50463,147\n"
|
||||
+ "-1,-1\n"
|
||||
+ "92357,1\n"
|
||||
+ "22758,637\n"
|
||||
+ "22744,107\n"
|
||||
+ "-1,-1\n"
|
||||
+ "20150,17\n"
|
||||
+ "29400,18\n"
|
||||
+ "13465,172\n"
|
||||
+ "1889,581\n"
|
||||
+ "42891,11\n"
|
||||
+ "1624,1957\n"
|
||||
+ "1243,2465\n"
|
||||
+ "1548,2020\n"
|
||||
+ "-1,-1\n"
|
||||
+ "16781,327\n"
|
||||
+ "19004,149\n"
|
||||
+ "-1,-1\n"
|
||||
+ "72046,5\n"
|
||||
+ "5158,374\n"
|
||||
+ "20902,279\n"
|
||||
+ "702,6495\n"
|
||||
+ "10170,184\n"
|
||||
+ "8064,202\n"
|
||||
+ "6936,2\n"
|
||||
+ "2335,9\n"
|
||||
+ "-1,-1\n"
|
||||
+ "-1,-1\n"
|
||||
+ "19779,22\n"
|
||||
+ "58283,10\n"
|
||||
+ "-1,-1\n"
|
||||
+ "-1,-1\n"
|
||||
+ "-1,-1\n"
|
||||
+ "29347,130\n"
|
||||
+ "723,4\n"
|
||||
+ "1264,38\n"
|
||||
+ "44595,4\n"
|
||||
+ "24820,4\n"
|
||||
+ "12116,782\n"
|
||||
+ "2299,724\n"
|
||||
+ "19301,62\n"
|
||||
+ "1498,5847\n";
|
||||
|
||||
private final MockWebServer server = new MockWebServer();
|
||||
|
||||
@Before
|
||||
public void before() throws IOException
|
||||
{
|
||||
server.enqueue(new MockResponse().setBody(RESPONSE));
|
||||
|
||||
server.start();
|
||||
}
|
||||
|
||||
@After
|
||||
public void after() throws IOException
|
||||
{
|
||||
server.shutdown();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNormalLookup() throws Exception
|
||||
{
|
||||
HiscoreTestService hiscores = new HiscoreTestService(server.url("/"));
|
||||
|
||||
HiscoreResult result = hiscores.lookupUsername("zezima", HiscoreEndpoint.NORMAL.getHiscoreURL());
|
||||
|
||||
Assert.assertEquals(50, result.getAttack().getLevel());
|
||||
Assert.assertEquals(159727L, result.getFishing().getExperience());
|
||||
Assert.assertEquals(492790, result.getConstruction().getRank());
|
||||
Assert.assertEquals(1432, result.getClueScrollAll().getLevel());
|
||||
Assert.assertEquals(324, result.getClueScrollBeginner().getRank());
|
||||
Assert.assertEquals(8008, result.getClueScrollEasy().getRank());
|
||||
Assert.assertEquals(911, result.getClueScrollMedium().getLevel());
|
||||
Assert.assertEquals(42, result.getClueScrollHard().getRank());
|
||||
Assert.assertEquals(777, result.getClueScrollElite().getLevel());
|
||||
Assert.assertEquals(254, result.getClueScrollMaster().getRank());
|
||||
Assert.assertEquals(-1, result.getLastManStanding().getLevel());
|
||||
Assert.assertEquals(241, result.getSoulWarsZeal().getLevel());
|
||||
Assert.assertEquals(2460, result.getLeaguePoints().getLevel());
|
||||
Assert.assertEquals(37, result.getAbyssalSire().getLevel());
|
||||
Assert.assertEquals(92357, result.getCallisto().getRank());
|
||||
Assert.assertEquals(5847, result.getZulrah().getLevel());
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user