diff --git a/.travis.yml b/.travis.yml
index b21301597c..66b128f565 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -12,7 +12,11 @@ env:
global:
- secure: XkhMC3ytOrlgL4wNFRF3Wi3WxQl1vef1WxUpHn5/k4Y3oLDEJVTv5r06VhJz+hU+drdMPy1cJPmOCRleP+gNdM+Ka53aBaIJ1Hdmxw4vboZ05qHcNR29mi4F0EDvzZf3FtdWz4oXsLF/aW5+ZP4UzPa+jvpYmkvQa7MEM070mDUdWtYP/4N72aa934B/0lbmGithVbItuNabvYb4S+0MEXSTM6WAGE5I+Q+UbOwatHqqwzMZDuScA556XOc9NSDffcwgNKOuD7SmK3JETn3iFMXvSaMv21dL5ehiIJlUDVpQhMLWKlCj9Hh3VqX3ojML12CwO58+oAz4BvnR+pfQR6cC+Q7DyghxGs/+J02rBAJYIFlCCS/PqmrfdmriU8ejb/uiyPCsDNTgpEY9+92Puq/DswliRG+9YI0swN7qDSGzPWqriG7hoFmELHk6OZtX7VlRYNK6M+jfyY12SuPjQF2Mm1h18+A8thq8IXrTAB1FgtH5Or3ZVTuAPwEDBhJuk63uYZd19klINEzktxiB3WEgKCX4YMICKnxikBDXvCMid+tFV9nJclw7xFlOab9+GgkBHDbjcCBVwwPci2ieGVSC3sZb/5SS6whNYBFIO16rNTN+KyAONX4P6WQ6Ffg4FZEzKiU1c+HS0T87x2gUMJsAlTL9dUEcwvWCYLIPsBM=
- secure: sH3m1bxlyUt/wy7edGEhAMvmk65SEKPPFW0rkC2h5dPXNScLmMtnv9Hk+AfmqWHervU0os1OuJjviocjyemY/Hp45WDweNBre4cQK/WBQwPKv+lcOMwqVbqQpQoeuauw42Lz1VBmQ/MqcCxhnXPdagEETgFYPaMYIN0LiUq4j6CMqHMGu1maljJgDc2fRe/OdKU+aAzksfAX+2ZAH3tQ7EBvJT3pP1FoJAOqQqQ5TGWYQ8R/jZSuDQXsBLdvmXzR2J9OPSzByk9PJaYtbKNrpynP9XzpXbr03Jq7Z6Fq1rxv/gjgzi8Rid6e1rJ6R93TbgzOltA8qQF6cVT73MzDCFHte8qCimN7WrH6Rt/Fw+b+t7ROjUjFWLGeJE5ujSbLDtlyaMccmyRx1tmxpTZg3F7FxhhbeYSYWZJ5W7u3Qi3vDKRVQvRh45EIAHVllDX/5hUZB8F8U517DpkXUdUCOPLiDbosJLow2L6RLywmQswIeD3oRGxQjbZ8x90glalq2dm/QIS0Q0s0OOO0+C/CNrEcEQqufSFQRT7m+XU5XMf5Wu/kpPNsRcXGXYj8aXi5mZbnXc3E0XyJhgQlrrWzJUTMI/U0jfFW1+ZZO/8YWlsShIdazWriPuXwBQqJG4Kshe95TcJY1RJc7McN8VUAuCAiJ/KsF3GUbsfWSejt3o0=
- # RUNELITE_BACKEND
+ # RUNELITE_BACKEND
- secure: psryZwj3/+xW2ZF/pjJR2UqCBVnUOdb8pbMia34yc5vQ2CCB2+ZrtIJyCEBXVpyZEgNj3qwgNtuj2tl1wameBVdrfVBBlkotlM120aeRwvMkmsggcNhTexf9SXcuRD34xGWvN7hF19ZiKBZk6rHWgzkDupFOPEAk/Q0E2swHW/YPeK8MKvRbY+UAK1WkY+TO4aJoVvDq9tc7Jbpj5XDhY6RLUb/96D+SnpBsnUG7GCpZxzavEZPMrGnMgntPlew9nWLHHcBKZbkMgTfD+X1fOrEG+kylOKIkV0afby5diKknVmLTfUUi1HrHUsvmoojcMtpBFN6yFGG7qrQV1DpZ/gZUcavWMNcBqrp03Dkb9Mtv2pnAI/KTERF3EmuzBM7/dmV/gw7Q+DmZBk97MV1ZFTvRcMu8u9OqC2TV9Xao3DqJV4dBA/d2CJrQHHdJopnh5kiEQtsWJvvqV1eLLBXY7EukMgmbYSb8ihOBY8Hi5tlIMit7j/RJCqM6jHlHEN9XcPOmNNab2liPiviWTQrvrantc2UxhgTX40DyhnDmVZIXIyS0ubqhRCgdxKuABS5aLY6SI0byXlQVj1GS1onZm9LxiTM1tq5EgCyQGBa0/6EpQNk1CNUF1dpZC7gOOFLC9nSQaBgRhqU19+6ctWTJjiTo+4WnTvutRZ3ZXoR9CE8=
+ # TOMCAT_USERNAME
+ - secure: ojn19kLrRjfNGEindivufyogtYVMbUHo5pyQmB5dXd3SojxEUIyYx7o7tYCfFcCQ0AmVZCEwmpU651R/m4cKobbx0suF6epozizhvS93Egc0RR5xXyUAHi0SgEUOf8fsv1V3SYy8gdaqcFFXTg5owtkdnfjjspIqrX8xZoVHItH21g06Izu1Zag+3/ovUrINY6TQM1voMQdBWlLzJ5N/gtY2AfhBGzdqa0tfSrpv23xRu1jrD0jZtE271tCHVlAFM9uJOLOP9nQYBxXC5DAoTgEVZb3yPgyiJgw0vWHneTEF5X+CQ5o7RXJQOWVdLJw5ZKfjLyFyHai44S1TA+x0WvAZjmwQvMlqD3PoTOd8dyz94eRU4lv2FE+bnzLjpBeSwLBl9tk9CketJIaQcOMUUOnuAidvgiKfDkNuMt2q5LcE0qFfjrgY8k8DBtYI13hodGMIIuUP3zXaH4nK2jOfgzVzshCpVk3pwsqtxwDjnTUIFvv8IJO5K5kC6dDlWbH+J7yrX4kPj7GKFxYcdWsjSg59E/qjeeHomqzq7PMj1XqWRgDo4JmqZxU+qgr3f2tabyP8whFdbDZTQgLuX1y0lP+7hUzOwkoi/mnqUAHlj81vRylBcX/gFtI+pJQwD7ZDwLfAmBPrkizetavxTWROnAuOoeRlzseVpclAscM2SEo=
+ # TOMCAT_PASSWORD
+ - secure: Hwsrlm4AblXCNdW837Z6Omsjw8sRrWA3V5/b+EtFEIzHEQE3Yd+LpKG6nW79QIKNQAwDxWb6YiDd7iFUPXYuPGW30HNvkq0VBUbWetuXF87tz9oJLwTZal8xhAk7LS9P+edf7f22UI1rdMj7nBG8VKTF9zWqm2vWphhJIMJBHIsAlk04qxOgDVPbhiccbJJ7TBpt3sIADmWeD8Z1gl23VolW+u/OELUg0Q+2JA+8RChL6vcju2/uh7pUrkMl3nqMrm8Go6EC6EDvtpOW8jcd5ov76t8opAmU6gfNWE5ZP72s9UHXuHsw+iFyO5QU3LdYMNBYRCisoYCRudy7O8uOEVsD35GaFhZmjAggawHu8FVUrnCAHYla23vEpgwxhyt0tCn9jVNJlViQMrF0S8ph7tQtykv+jpVZa+JZIyQOLDItbTxSnRqNswTEpFqZgYKbXL9DMtnt2rKeJKb48GUY8KTxM7RswczQOJ/X5nA+n2d86kPf8d4etQcXAoyfAzOv7N8JTW2lLnY/AFJpg1sHUnXKOQTNpXxHXJGrT9tHsNVHzY+IOZKqvCsfB0T5IlOslD62OgHGO5V5N9EycKyHON0nCPzFRx+0Ej+pm+leq+WQq4NYCO605qyE+WnA96L8ZiVhTTxQYeqcWxISzi+UTv9o/Mw4tcJJBz8ePmZVkAY=
notifications:
irc: "irc.rizon.net#runelite"
diff --git a/http-api/pom.xml b/http-api/pom.xml
new file mode 100644
index 0000000000..25e1c376b9
--- /dev/null
+++ b/http-api/pom.xml
@@ -0,0 +1,84 @@
+
+
+
+ 4.0.0
+
+ net.runelite
+ runelite-parent
+ 1.1.20-SNAPSHOT
+
+
+ Web API
+ http-api
+
+
+
+ org.apache.httpcomponents
+ httpclient
+ 4.5.3
+
+
+ com.google.code.gson
+ gson
+ 2.4
+
+
+ org.slf4j
+ slf4j-api
+ 1.7.12
+
+
+
+ junit
+ junit
+ 4.12
+ test
+
+
+ org.slf4j
+ slf4j-simple
+ 1.7.12
+ test
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-jar-plugin
+
+
+
+ true
+ true
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/http-api/src/main/java/net/runelite/http/api/RuneliteAPI.java b/http-api/src/main/java/net/runelite/http/api/RuneliteAPI.java
new file mode 100644
index 0000000000..a90557c7ff
--- /dev/null
+++ b/http-api/src/main/java/net/runelite/http/api/RuneliteAPI.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2017, 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.api;
+
+public class RuneliteAPI
+{
+ private static final String BASE = "https://api.runelite.net/runelite-";
+ private static String version = RuneliteAPI.class.getPackage().getImplementationVersion();
+
+ public static String getApiBase()
+ {
+ return BASE + getVersion();
+ }
+
+ public static String getVersion()
+ {
+ return version;
+ }
+
+ public static void setVersion(String version)
+ {
+ RuneliteAPI.version = version;
+ }
+
+}
diff --git a/http-api/src/main/java/net/runelite/http/api/hiscore/HiscoreClient.java b/http-api/src/main/java/net/runelite/http/api/hiscore/HiscoreClient.java
new file mode 100644
index 0000000000..d8e0e6a938
--- /dev/null
+++ b/http-api/src/main/java/net/runelite/http/api/hiscore/HiscoreClient.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2017, 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.api.hiscore;
+
+import com.google.gson.Gson;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.net.URI;
+import java.net.URISyntaxException;
+import net.runelite.http.api.RuneliteAPI;
+import org.apache.http.client.methods.CloseableHttpResponse;
+import org.apache.http.client.methods.HttpGet;
+import org.apache.http.client.methods.HttpUriRequest;
+import org.apache.http.client.utils.URIBuilder;
+import org.apache.http.impl.client.CloseableHttpClient;
+import org.apache.http.impl.client.HttpClients;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class HiscoreClient
+{
+ private static final Logger logger = LoggerFactory.getLogger(HiscoreClient.class);
+
+ private static final String URL = RuneliteAPI.getApiBase() + "/hiscore";
+
+ private final Gson gson = new Gson();
+
+ public HiscoreResult lookup(String username) throws IOException, URISyntaxException
+ {
+ URIBuilder builder = new URIBuilder(URL)
+ .addParameter("username", username);
+
+ URI uri = builder.build();
+
+ logger.debug("Built URI: {}", uri);
+
+ HttpUriRequest request = new HttpGet(uri);
+
+ try (CloseableHttpClient client = HttpClients.createDefault();
+ CloseableHttpResponse response = client.execute(request))
+ {
+ InputStream in = response.getEntity().getContent();
+ return gson.fromJson(new InputStreamReader(in), HiscoreResult.class);
+ }
+ }
+}
diff --git a/http-api/src/main/java/net/runelite/http/api/hiscore/HiscoreResult.java b/http-api/src/main/java/net/runelite/http/api/hiscore/HiscoreResult.java
new file mode 100644
index 0000000000..fb9738a1c3
--- /dev/null
+++ b/http-api/src/main/java/net/runelite/http/api/hiscore/HiscoreResult.java
@@ -0,0 +1,463 @@
+/*
+ * Copyright (c) 2017, 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.api.hiscore;
+
+import java.util.Objects;
+
+public class HiscoreResult
+{
+ private String player;
+ private Skill overall;
+ private Skill attack;
+ private Skill defence;
+ private Skill strength;
+ private Skill hitpoints;
+ private Skill ranged;
+ private Skill prayer;
+ private Skill magic;
+ private Skill cooking;
+ private Skill woodcutting;
+ private Skill fletching;
+ private Skill fishing;
+ private Skill firemaking;
+ private Skill crafting;
+ private Skill smithing;
+ private Skill mining;
+ private Skill herblore;
+ private Skill agility;
+ private Skill thieving;
+ private Skill slayer;
+ private Skill farming;
+ private Skill runecraft;
+ private Skill hunter;
+ private Skill construction;
+
+ public String getPlayer()
+ {
+ return player;
+ }
+
+ public void setPlayer(String player)
+ {
+ this.player = player;
+ }
+
+ public Skill getOverall()
+ {
+ return overall;
+ }
+
+ public void setOverall(Skill overall)
+ {
+ this.overall = overall;
+ }
+
+ public Skill getAttack()
+ {
+ return attack;
+ }
+
+ public void setAttack(Skill attack)
+ {
+ this.attack = attack;
+ }
+
+ public Skill getDefence()
+ {
+ return defence;
+ }
+
+ public void setDefence(Skill defence)
+ {
+ this.defence = defence;
+ }
+
+ public Skill getStrength()
+ {
+ return strength;
+ }
+
+ public void setStrength(Skill strength)
+ {
+ this.strength = strength;
+ }
+
+ public Skill getHitpoints()
+ {
+ return hitpoints;
+ }
+
+ public void setHitpoints(Skill hitpoints)
+ {
+ this.hitpoints = hitpoints;
+ }
+
+ public Skill getRanged()
+ {
+ return ranged;
+ }
+
+ public void setRanged(Skill ranged)
+ {
+ this.ranged = ranged;
+ }
+
+ public Skill getPrayer()
+ {
+ return prayer;
+ }
+
+ public void setPrayer(Skill prayer)
+ {
+ this.prayer = prayer;
+ }
+
+ public Skill getMagic()
+ {
+ return magic;
+ }
+
+ public void setMagic(Skill magic)
+ {
+ this.magic = magic;
+ }
+
+ public Skill getCooking()
+ {
+ return cooking;
+ }
+
+ public void setCooking(Skill cooking)
+ {
+ this.cooking = cooking;
+ }
+
+ public Skill getWoodcutting()
+ {
+ return woodcutting;
+ }
+
+ public void setWoodcutting(Skill woodcutting)
+ {
+ this.woodcutting = woodcutting;
+ }
+
+ public Skill getFletching()
+ {
+ return fletching;
+ }
+
+ public void setFletching(Skill fletching)
+ {
+ this.fletching = fletching;
+ }
+
+ public Skill getFishing()
+ {
+ return fishing;
+ }
+
+ public void setFishing(Skill fishing)
+ {
+ this.fishing = fishing;
+ }
+
+ public Skill getFiremaking()
+ {
+ return firemaking;
+ }
+
+ public void setFiremaking(Skill firemaking)
+ {
+ this.firemaking = firemaking;
+ }
+
+ public Skill getCrafting()
+ {
+ return crafting;
+ }
+
+ public void setCrafting(Skill crafting)
+ {
+ this.crafting = crafting;
+ }
+
+ public Skill getSmithing()
+ {
+ return smithing;
+ }
+
+ public void setSmithing(Skill smithing)
+ {
+ this.smithing = smithing;
+ }
+
+ public Skill getMining()
+ {
+ return mining;
+ }
+
+ public void setMining(Skill mining)
+ {
+ this.mining = mining;
+ }
+
+ public Skill getHerblore()
+ {
+ return herblore;
+ }
+
+ public void setHerblore(Skill herblore)
+ {
+ this.herblore = herblore;
+ }
+
+ public Skill getAgility()
+ {
+ return agility;
+ }
+
+ public void setAgility(Skill agility)
+ {
+ this.agility = agility;
+ }
+
+ public Skill getThieving()
+ {
+ return thieving;
+ }
+
+ public void setThieving(Skill thieving)
+ {
+ this.thieving = thieving;
+ }
+
+ public Skill getSlayer()
+ {
+ return slayer;
+ }
+
+ public void setSlayer(Skill slayer)
+ {
+ this.slayer = slayer;
+ }
+
+ public Skill getFarming()
+ {
+ return farming;
+ }
+
+ public void setFarming(Skill farming)
+ {
+ this.farming = farming;
+ }
+
+ public Skill getRunecraft()
+ {
+ return runecraft;
+ }
+
+ public void setRunecraft(Skill runecraft)
+ {
+ this.runecraft = runecraft;
+ }
+
+ public Skill getHunter()
+ {
+ return hunter;
+ }
+
+ public void setHunter(Skill hunter)
+ {
+ this.hunter = hunter;
+ }
+
+ public Skill getConstruction()
+ {
+ return construction;
+ }
+
+ public void setConstruction(Skill construction)
+ {
+ this.construction = construction;
+ }
+
+ @Override
+ public int hashCode()
+ {
+ int hash = 7;
+ hash = 29 * hash + Objects.hashCode(this.player);
+ hash = 29 * hash + Objects.hashCode(this.overall);
+ hash = 29 * hash + Objects.hashCode(this.attack);
+ hash = 29 * hash + Objects.hashCode(this.defence);
+ hash = 29 * hash + Objects.hashCode(this.strength);
+ hash = 29 * hash + Objects.hashCode(this.hitpoints);
+ hash = 29 * hash + Objects.hashCode(this.ranged);
+ hash = 29 * hash + Objects.hashCode(this.prayer);
+ hash = 29 * hash + Objects.hashCode(this.magic);
+ hash = 29 * hash + Objects.hashCode(this.cooking);
+ hash = 29 * hash + Objects.hashCode(this.woodcutting);
+ hash = 29 * hash + Objects.hashCode(this.fletching);
+ hash = 29 * hash + Objects.hashCode(this.fishing);
+ hash = 29 * hash + Objects.hashCode(this.firemaking);
+ hash = 29 * hash + Objects.hashCode(this.crafting);
+ hash = 29 * hash + Objects.hashCode(this.smithing);
+ hash = 29 * hash + Objects.hashCode(this.mining);
+ hash = 29 * hash + Objects.hashCode(this.herblore);
+ hash = 29 * hash + Objects.hashCode(this.agility);
+ hash = 29 * hash + Objects.hashCode(this.thieving);
+ hash = 29 * hash + Objects.hashCode(this.slayer);
+ hash = 29 * hash + Objects.hashCode(this.farming);
+ hash = 29 * hash + Objects.hashCode(this.runecraft);
+ hash = 29 * hash + Objects.hashCode(this.hunter);
+ hash = 29 * hash + Objects.hashCode(this.construction);
+ return hash;
+ }
+
+ @Override
+ public boolean equals(Object obj)
+ {
+ if (this == obj)
+ {
+ return true;
+ }
+ if (obj == null)
+ {
+ return false;
+ }
+ if (getClass() != obj.getClass())
+ {
+ return false;
+ }
+ final HiscoreResult other = (HiscoreResult) obj;
+ if (!Objects.equals(this.player, other.player))
+ {
+ return false;
+ }
+ if (!Objects.equals(this.overall, other.overall))
+ {
+ return false;
+ }
+ if (!Objects.equals(this.attack, other.attack))
+ {
+ return false;
+ }
+ if (!Objects.equals(this.defence, other.defence))
+ {
+ return false;
+ }
+ if (!Objects.equals(this.strength, other.strength))
+ {
+ return false;
+ }
+ if (!Objects.equals(this.hitpoints, other.hitpoints))
+ {
+ return false;
+ }
+ if (!Objects.equals(this.ranged, other.ranged))
+ {
+ return false;
+ }
+ if (!Objects.equals(this.prayer, other.prayer))
+ {
+ return false;
+ }
+ if (!Objects.equals(this.magic, other.magic))
+ {
+ return false;
+ }
+ if (!Objects.equals(this.cooking, other.cooking))
+ {
+ return false;
+ }
+ if (!Objects.equals(this.woodcutting, other.woodcutting))
+ {
+ return false;
+ }
+ if (!Objects.equals(this.fletching, other.fletching))
+ {
+ return false;
+ }
+ if (!Objects.equals(this.fishing, other.fishing))
+ {
+ return false;
+ }
+ if (!Objects.equals(this.firemaking, other.firemaking))
+ {
+ return false;
+ }
+ if (!Objects.equals(this.crafting, other.crafting))
+ {
+ return false;
+ }
+ if (!Objects.equals(this.smithing, other.smithing))
+ {
+ return false;
+ }
+ if (!Objects.equals(this.mining, other.mining))
+ {
+ return false;
+ }
+ if (!Objects.equals(this.herblore, other.herblore))
+ {
+ return false;
+ }
+ if (!Objects.equals(this.agility, other.agility))
+ {
+ return false;
+ }
+ if (!Objects.equals(this.thieving, other.thieving))
+ {
+ return false;
+ }
+ if (!Objects.equals(this.slayer, other.slayer))
+ {
+ return false;
+ }
+ if (!Objects.equals(this.farming, other.farming))
+ {
+ return false;
+ }
+ if (!Objects.equals(this.runecraft, other.runecraft))
+ {
+ return false;
+ }
+ if (!Objects.equals(this.hunter, other.hunter))
+ {
+ return false;
+ }
+ if (!Objects.equals(this.construction, other.construction))
+ {
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public String toString()
+ {
+ return "HiscoreResult{" + "player=" + player + ", overall=" + overall + ", attack=" + attack + ", defence=" + defence + ", strength=" + strength + ", hitpoints=" + hitpoints + ", ranged=" + ranged + ", prayer=" + prayer + ", magic=" + magic + ", cooking=" + cooking + ", woodcutting=" + woodcutting + ", fletching=" + fletching + ", fishing=" + fishing + ", firemaking=" + firemaking + ", crafting=" + crafting + ", smithing=" + smithing + ", mining=" + mining + ", herblore=" + herblore + ", agility=" + agility + ", thieving=" + thieving + ", slayer=" + slayer + ", farming=" + farming + ", runecraft=" + runecraft + ", hunter=" + hunter + ", construction=" + construction + '}';
+ }
+}
diff --git a/http-api/src/main/java/net/runelite/http/api/hiscore/Skill.java b/http-api/src/main/java/net/runelite/http/api/hiscore/Skill.java
new file mode 100644
index 0000000000..fa779381bc
--- /dev/null
+++ b/http-api/src/main/java/net/runelite/http/api/hiscore/Skill.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2017, 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.api.hiscore;
+
+public class Skill
+{
+ private final int rank;
+ private final int level;
+ private final long experience;
+
+ public Skill(int rank, int level, long experience)
+ {
+ this.rank = rank;
+ this.level = level;
+ this.experience = experience;
+ }
+
+ public int getRank()
+ {
+ return rank;
+ }
+
+ public int getLevel()
+ {
+ return level;
+ }
+
+ public long getExperience()
+ {
+ return experience;
+ }
+
+ @Override
+ public int hashCode()
+ {
+ int hash = 3;
+ hash = 59 * hash + this.rank;
+ hash = 59 * hash + this.level;
+ hash = 59 * hash + (int) (this.experience ^ (this.experience >>> 32));
+ return hash;
+ }
+
+ @Override
+ public boolean equals(Object obj)
+ {
+ if (this == obj)
+ {
+ return true;
+ }
+ if (obj == null)
+ {
+ return false;
+ }
+ if (getClass() != obj.getClass())
+ {
+ return false;
+ }
+ final Skill other = (Skill) obj;
+ if (this.rank != other.rank)
+ {
+ return false;
+ }
+ if (this.level != other.level)
+ {
+ return false;
+ }
+ if (this.experience != other.experience)
+ {
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public String toString()
+ {
+ return "Skill{" + "rank=" + rank + ", level=" + level + ", experience=" + experience + '}';
+ }
+}
diff --git a/http-service/pom.xml b/http-service/pom.xml
new file mode 100644
index 0000000000..7a832fb128
--- /dev/null
+++ b/http-service/pom.xml
@@ -0,0 +1,105 @@
+
+
+
+ 4.0.0
+
+ net.runelite
+ runelite-parent
+ 1.1.20-SNAPSHOT
+
+
+ Web Service
+ http-service
+ war
+
+
+
+ net.runelite
+ http-api
+ ${project.version}
+
+
+
+ com.sparkjava
+ spark-core
+ 2.5.5
+
+
+
+ org.apache.commons
+ commons-csv
+ 1.4
+
+
+
+ org.slf4j
+ slf4j-api
+ 1.7.12
+
+
+ org.slf4j
+ slf4j-simple
+ 1.7.12
+
+
+
+ junit
+ junit
+ 4.12
+ test
+
+
+ org.mockito
+ mockito-all
+ 1.10.19
+ test
+
+
+
+
+
+
+ org.apache.tomcat.maven
+ tomcat7-maven-plugin
+ 2.2
+
+ ${runelite.tomcat.url}
+ runelite-tomcat
+ /runelite-${project.version}
+
+
+
+ tomcat-deploy
+ deploy
+
+ redeploy
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/http-service/src/main/java/net/runelite/http/service/HttpClient.java b/http-service/src/main/java/net/runelite/http/service/HttpClient.java
new file mode 100644
index 0000000000..379226f32c
--- /dev/null
+++ b/http-service/src/main/java/net/runelite/http/service/HttpClient.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2017, 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;
+
+import java.io.IOException;
+import java.net.URI;
+import org.apache.http.client.methods.CloseableHttpResponse;
+import org.apache.http.client.methods.HttpGet;
+import org.apache.http.impl.client.CloseableHttpClient;
+import org.apache.http.impl.client.HttpClients;
+import org.apache.http.util.EntityUtils;
+
+public class HttpClient
+{
+ public String get(URI uri) throws IOException
+ {
+ HttpGet request = new HttpGet(uri);
+
+ try (CloseableHttpClient client = HttpClients.createDefault();
+ CloseableHttpResponse response = client.execute(request))
+ {
+ return EntityUtils.toString(response.getEntity());
+ }
+ }
+}
diff --git a/http-service/src/main/java/net/runelite/http/service/JsonTransformer.java b/http-service/src/main/java/net/runelite/http/service/JsonTransformer.java
new file mode 100644
index 0000000000..d6abb61459
--- /dev/null
+++ b/http-service/src/main/java/net/runelite/http/service/JsonTransformer.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2017, 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;
+
+import com.google.gson.Gson;
+import spark.ResponseTransformer;
+
+public class JsonTransformer implements ResponseTransformer
+{
+ private final Gson gson = new Gson();
+
+ @Override
+ public String render(Object model) throws Exception
+ {
+ return gson.toJson(model);
+ }
+}
diff --git a/http-service/src/main/java/net/runelite/http/service/Service.java b/http-service/src/main/java/net/runelite/http/service/Service.java
new file mode 100644
index 0000000000..592d28a715
--- /dev/null
+++ b/http-service/src/main/java/net/runelite/http/service/Service.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2017, 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;
+
+import net.runelite.http.api.RuneliteAPI;
+import net.runelite.http.service.hiscore.HiscoreService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import spark.servlet.SparkApplication;
+import static spark.Spark.*;
+
+public class Service implements SparkApplication
+{
+ private static final Logger logger = LoggerFactory.getLogger(Service.class);
+
+ private final JsonTransformer transformer = new JsonTransformer();
+
+ private HiscoreService hiscores = new HiscoreService();
+
+ @Override
+ public void init()
+ {
+ get("/version", (request, response) -> RuneliteAPI.getVersion());
+ get("/hiscore", (request, response) -> hiscores.lookup(request.queryParams("username")), transformer);
+
+ exception(Exception.class, (exception, request, response) -> logger.warn(null, exception));
+ }
+
+ public HiscoreService getHiscores()
+ {
+ return hiscores;
+ }
+
+ public void setHiscores(HiscoreService hiscores)
+ {
+ this.hiscores = hiscores;
+ }
+
+}
diff --git a/http-service/src/main/java/net/runelite/http/service/hiscore/HiscoreResultBuilder.java b/http-service/src/main/java/net/runelite/http/service/hiscore/HiscoreResultBuilder.java
new file mode 100644
index 0000000000..c082e4816e
--- /dev/null
+++ b/http-service/src/main/java/net/runelite/http/service/hiscore/HiscoreResultBuilder.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2017, 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.hiscore;
+
+import java.util.function.Consumer;
+import net.runelite.http.api.hiscore.HiscoreResult;
+import net.runelite.http.api.hiscore.Skill;
+
+public class HiscoreResultBuilder
+{
+ public static final int NUM_SKILLS = 24;
+
+ private final HiscoreResult result = new HiscoreResult();
+
+ private final Consumer[] consumers = new Consumer[]
+ {
+ (s) -> result.setOverall((Skill) s),
+ (s) -> result.setAttack((Skill) s),
+ (s) -> result.setDefence((Skill) s),
+ (s) -> result.setStrength((Skill) s),
+ (s) -> result.setHitpoints((Skill) s),
+ (s) -> result.setRanged((Skill) s),
+ (s) -> result.setPrayer((Skill) s),
+ (s) -> result.setMagic((Skill) s),
+ (s) -> result.setCooking((Skill) s),
+ (s) -> result.setWoodcutting((Skill) s),
+ (s) -> result.setFletching((Skill) s),
+ (s) -> result.setFishing((Skill) s),
+ (s) -> result.setFiremaking((Skill) s),
+ (s) -> result.setCrafting((Skill) s),
+ (s) -> result.setSmithing((Skill) s),
+ (s) -> result.setMining((Skill) s),
+ (s) -> result.setHerblore((Skill) s),
+ (s) -> result.setAgility((Skill) s),
+ (s) -> result.setThieving((Skill) s),
+ (s) -> result.setSlayer((Skill) s),
+ (s) -> result.setFarming((Skill) s),
+ (s) -> result.setRunecraft((Skill) s),
+ (s) -> result.setHunter((Skill) s),
+ (s) -> result.setConstruction((Skill) s),
+ };
+
+ private int position;
+
+ public void setPlayer(String player)
+ {
+ result.setPlayer(player);
+ }
+
+ public void setNextSkill(Skill skill)
+ {
+ consumers[position++].accept(skill);
+ }
+
+ public HiscoreResult build()
+ {
+ return result;
+ }
+}
diff --git a/http-service/src/main/java/net/runelite/http/service/hiscore/HiscoreService.java b/http-service/src/main/java/net/runelite/http/service/hiscore/HiscoreService.java
new file mode 100644
index 0000000000..82eea34fcb
--- /dev/null
+++ b/http-service/src/main/java/net/runelite/http/service/hiscore/HiscoreService.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2017, 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.hiscore;
+
+import java.io.IOException;
+import java.net.URISyntaxException;
+import net.runelite.http.api.hiscore.HiscoreResult;
+import net.runelite.http.api.hiscore.Skill;
+import net.runelite.http.service.HttpClient;
+import org.apache.commons.csv.CSVFormat;
+import org.apache.commons.csv.CSVParser;
+import org.apache.commons.csv.CSVRecord;
+import org.apache.http.client.utils.URIBuilder;
+
+public class HiscoreService
+{
+ private static final String RUNESCAPE_HISCORE_SERVICE = "http://services.runescape.com/m=hiscore_oldschool/index_lite.ws";
+
+ private HttpClient client = new HttpClient();
+
+ public HiscoreResult lookup(String username) throws IOException, URISyntaxException
+ {
+ URIBuilder builder = new URIBuilder(RUNESCAPE_HISCORE_SERVICE)
+ .addParameter("player", username);
+
+ String csv = client.get(builder.build());
+ CSVParser parser = CSVParser.parse(csv, CSVFormat.DEFAULT);
+
+ HiscoreResultBuilder hiscoreBuilder = new HiscoreResultBuilder();
+ hiscoreBuilder.setPlayer(username);
+
+ int count = 0;
+
+ for (CSVRecord record : parser.getRecords())
+ {
+ if (count++ >= HiscoreResultBuilder.NUM_SKILLS)
+ {
+ break; // rest is other things?
+ }
+
+ // rank, level, experience
+ int rank = Integer.parseInt(record.get(0));
+ int level = Integer.parseInt(record.get(1));
+ long experience = Long.parseLong(record.get(2));
+
+ Skill skill = new Skill(rank, level, experience);
+ hiscoreBuilder.setNextSkill(skill);
+ }
+
+ return hiscoreBuilder.build();
+ }
+
+ public HttpClient getClient()
+ {
+ return client;
+ }
+
+ public void setClient(HttpClient client)
+ {
+ this.client = client;
+ }
+}
diff --git a/http-service/src/main/webapp/WEB-INF/web.xml b/http-service/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000000..7ebcddad92
--- /dev/null
+++ b/http-service/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,43 @@
+
+
+
+
+ SparkFilter
+ spark.servlet.SparkFilter
+
+ applicationClass
+ net.runelite.http.service.Service
+
+
+
+
+ SparkFilter
+ /*
+
+
\ No newline at end of file
diff --git a/http-service/src/test/java/net/runelite/http/service/ServiceTest.java b/http-service/src/test/java/net/runelite/http/service/ServiceTest.java
new file mode 100644
index 0000000000..488250e9c8
--- /dev/null
+++ b/http-service/src/test/java/net/runelite/http/service/ServiceTest.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2017, 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;
+
+import com.google.gson.Gson;
+import java.io.InputStreamReader;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import net.runelite.http.api.hiscore.HiscoreResult;
+import net.runelite.http.api.hiscore.Skill;
+import net.runelite.http.service.hiscore.HiscoreService;
+import org.junit.AfterClass;
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+import spark.Spark;
+
+public class ServiceTest
+{
+ private static final String URL_BASE = "http://localhost:4567";
+
+ private static Service service;
+
+ @BeforeClass
+ public static void before()
+ {
+ service = new Service();
+ service.init();
+
+ Spark.awaitInitialization();
+ }
+
+ @AfterClass
+ public static void after()
+ {
+ Spark.stop();
+ }
+
+ @Test
+ public void testInit() throws Exception
+ {
+ HiscoreService hiscoreService = mock(HiscoreService.class);
+ service.setHiscores(hiscoreService);
+
+ HiscoreResult result = new HiscoreResult();
+ result.setAttack(new Skill(1, 99, 42));
+
+ when(hiscoreService.lookup("zezima")).thenReturn(result);
+
+ URL url = new URL(URL_BASE + "/hiscore?username=zezima");
+ HttpURLConnection connection = (HttpURLConnection) url.openConnection();
+ connection.setRequestMethod("GET");
+ connection.connect();
+
+ Gson gson = new Gson();
+ HiscoreResult res = gson.fromJson(new InputStreamReader(connection.getInputStream()), HiscoreResult.class);
+
+ Assert.assertEquals(result, res);
+
+ Spark.stop();
+ }
+
+}
diff --git a/http-service/src/test/java/net/runelite/http/service/hiscore/HiscoreServiceTest.java b/http-service/src/test/java/net/runelite/http/service/hiscore/HiscoreServiceTest.java
new file mode 100644
index 0000000000..d70968e2d4
--- /dev/null
+++ b/http-service/src/test/java/net/runelite/http/service/hiscore/HiscoreServiceTest.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2017, 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.hiscore;
+
+import java.net.URI;
+import net.runelite.http.api.hiscore.HiscoreResult;
+import net.runelite.http.service.HttpClient;
+import org.junit.Assert;
+import org.junit.Test;
+import org.mockito.Matchers;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+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"
+ + "-1,-1\n"
+ + "-1,-1\n"
+ + "-1,-1\n"
+ + "-1,-1\n"
+ + "-1,-1\n"
+ + "-1,-1\n"
+ + "-1,-1\n"
+ + "-1,-1\n"
+ + "-1,-1";
+
+ @Test
+ public void testLookup() throws Exception
+ {
+ HttpClient client = mock(HttpClient.class);
+ when(client.get(Matchers.any(URI.class)))
+ .thenReturn(RESPONSE);
+
+ HiscoreService hiscores = new HiscoreService();
+ hiscores.setClient(client);
+
+ HiscoreResult result = hiscores.lookup("zezima");
+
+ Assert.assertEquals(50, result.getAttack().getLevel());
+ Assert.assertEquals(159727L, result.getFishing().getExperience());
+ Assert.assertEquals(492790, result.getConstruction().getRank());
+ }
+
+}
diff --git a/pom.xml b/pom.xml
index b6e3d6e918..e40e833abc 100644
--- a/pom.xml
+++ b/pom.xml
@@ -72,6 +72,8 @@
runescape-client
runescape-client-injector
runescape-client-injector-plugin
+ http-api
+ http-service
@@ -79,7 +81,6 @@
org.apache.maven.plugins
maven-surefire-plugin
- 2.19
true
-Xmx512m
diff --git a/travis/settings.xml b/travis/settings.xml
index 1a3ec098d5..dab99d4005 100644
--- a/travis/settings.xml
+++ b/travis/settings.xml
@@ -137,6 +137,11 @@ under the License.
runelite
${user.home}/.ssh/runelite
+
+ runelite-tomcat
+ ${env.TOMCAT_USERNAME}
+ ${env.TOMCAT_PASSWORD}
+
@@ -258,6 +263,7 @@ under the License.
${env.RUNELITE_REPOSITORY_URL}
+ http://api.runelite.net/manager/text