From ac0dda1f631f4bba2cbac592b316c85cde6089ff Mon Sep 17 00:00:00 2001 From: Adam Date: Tue, 28 Feb 2017 12:30:54 -0500 Subject: [PATCH] http service: add worlds api --- .../net/runelite/http/api/worlds/World.java | 101 +++++++++++++++++ .../runelite/http/api/worlds/WorldResult.java | 42 ++++++++ .../net/runelite/http/service/HttpClient.java | 11 ++ .../net/runelite/http/service/Service.java | 3 + .../http/service/worlds/WorldsService.java | 102 ++++++++++++++++++ .../runelite/http/service/ServiceRunner.java | 46 ++++++++ .../service/worlds/WorldsServiceTest.java | 65 +++++++++++ .../runelite/http/service/worlds/worldlist | Bin 0 -> 5000 bytes 8 files changed, 370 insertions(+) create mode 100644 http-api/src/main/java/net/runelite/http/api/worlds/World.java create mode 100644 http-api/src/main/java/net/runelite/http/api/worlds/WorldResult.java create mode 100644 http-service/src/main/java/net/runelite/http/service/worlds/WorldsService.java create mode 100644 http-service/src/test/java/net/runelite/http/service/ServiceRunner.java create mode 100644 http-service/src/test/java/net/runelite/http/service/worlds/WorldsServiceTest.java create mode 100644 http-service/src/test/resources/net/runelite/http/service/worlds/worldlist diff --git a/http-api/src/main/java/net/runelite/http/api/worlds/World.java b/http-api/src/main/java/net/runelite/http/api/worlds/World.java new file mode 100644 index 0000000000..aa38a8c4c8 --- /dev/null +++ b/http-api/src/main/java/net/runelite/http/api/worlds/World.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.worlds; + +public class World +{ + private int id; + private int mask; + private String address; + private String activity; + private int location; + private int players; + + @Override + public String toString() + { + return "World{" + "id=" + id + ", mask=" + mask + ", address=" + address + ", activity=" + activity + ", location=" + location + ", players=" + players + '}'; + } + + public int getId() + { + return id; + } + + public void setId(int id) + { + this.id = id; + } + + public int getMask() + { + return mask; + } + + public void setMask(int mask) + { + this.mask = mask; + } + + public String getAddress() + { + return address; + } + + public void setAddress(String address) + { + this.address = address; + } + + public String getActivity() + { + return activity; + } + + public void setActivity(String activity) + { + this.activity = activity; + } + + public int getLocation() + { + return location; + } + + public void setLocation(int location) + { + this.location = location; + } + + public int getPlayers() + { + return players; + } + + public void setPlayers(int players) + { + this.players = players; + } +} diff --git a/http-api/src/main/java/net/runelite/http/api/worlds/WorldResult.java b/http-api/src/main/java/net/runelite/http/api/worlds/WorldResult.java new file mode 100644 index 0000000000..329e1d81a0 --- /dev/null +++ b/http-api/src/main/java/net/runelite/http/api/worlds/WorldResult.java @@ -0,0 +1,42 @@ +/* + * 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.worlds; + +import java.util.List; + +public class WorldResult +{ + private List worlds; + + public List getWorlds() + { + return worlds; + } + + public void setWorlds(List worlds) + { + this.worlds = worlds; + } +} 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 index 379226f32c..8ee04eec71 100644 --- a/http-service/src/main/java/net/runelite/http/service/HttpClient.java +++ b/http-service/src/main/java/net/runelite/http/service/HttpClient.java @@ -44,4 +44,15 @@ public class HttpClient return EntityUtils.toString(response.getEntity()); } } + + public byte[] getBytes(URI uri) throws IOException + { + HttpGet request = new HttpGet(uri); + + try (CloseableHttpClient client = HttpClients.createDefault(); + CloseableHttpResponse response = client.execute(request)) + { + return EntityUtils.toByteArray(response.getEntity()); + } + } } 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 index 592d28a715..1dab4e4254 100644 --- a/http-service/src/main/java/net/runelite/http/service/Service.java +++ b/http-service/src/main/java/net/runelite/http/service/Service.java @@ -26,6 +26,7 @@ package net.runelite.http.service; import net.runelite.http.api.RuneliteAPI; import net.runelite.http.service.hiscore.HiscoreService; +import net.runelite.http.service.worlds.WorldsService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import spark.servlet.SparkApplication; @@ -38,12 +39,14 @@ public class Service implements SparkApplication private final JsonTransformer transformer = new JsonTransformer(); private HiscoreService hiscores = new HiscoreService(); + private WorldsService worlds = new WorldsService(); @Override public void init() { get("/version", (request, response) -> RuneliteAPI.getVersion()); get("/hiscore", (request, response) -> hiscores.lookup(request.queryParams("username")), transformer); + get("/worlds", (request, response) -> worlds.listWorlds(), transformer); exception(Exception.class, (exception, request, response) -> logger.warn(null, exception)); } diff --git a/http-service/src/main/java/net/runelite/http/service/worlds/WorldsService.java b/http-service/src/main/java/net/runelite/http/service/worlds/WorldsService.java new file mode 100644 index 0000000000..c8fbeda1e8 --- /dev/null +++ b/http-service/src/main/java/net/runelite/http/service/worlds/WorldsService.java @@ -0,0 +1,102 @@ +/* + * 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.worlds; + +import java.io.IOException; +import java.net.URI; +import java.net.URISyntaxException; +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.List; +import net.runelite.http.api.worlds.World; +import net.runelite.http.api.worlds.WorldResult; +import net.runelite.http.service.HttpClient; + +public class WorldsService +{ + private static final String WORLD_URL = "http://www.runescape.com/g=oldscape/slr.ws?order=LPWM"; + + private HttpClient client = new HttpClient(); + + public WorldResult listWorlds() throws IOException, URISyntaxException + { + byte[] response = client.getBytes(new URI(WORLD_URL)); + + List worlds = new ArrayList<>(); + ByteBuffer buf = ByteBuffer.wrap(response); + + int length = buf.getInt(); + buf.limit(length + 4); + + int num = buf.getShort() & 0xFFFF; + + for (int i = 0; i < num; ++i) + { + World world = new World(); + world.setId(buf.getShort() & 0xFFFF); + world.setMask(buf.getInt()); + world.setAddress(readString(buf)); + world.setActivity(readString(buf)); + world.setLocation(buf.get() & 0xFF); + world.setPlayers(buf.getShort() & 0xFFFF); + + worlds.add(world); + } + + WorldResult result = new WorldResult(); + result.setWorlds(worlds); + return result; + } + + private static String readString(ByteBuffer buf) + { + byte b; + StringBuilder sb = new StringBuilder(); + + for (;;) + { + b = buf.get(); + + if (b == 0) + { + break; + } + + sb.append((char) b); + } + + return sb.toString(); + } + + public HttpClient getClient() + { + return client; + } + + public void setClient(HttpClient client) + { + this.client = client; + } +} diff --git a/http-service/src/test/java/net/runelite/http/service/ServiceRunner.java b/http-service/src/test/java/net/runelite/http/service/ServiceRunner.java new file mode 100644 index 0000000000..cd80592b97 --- /dev/null +++ b/http-service/src/test/java/net/runelite/http/service/ServiceRunner.java @@ -0,0 +1,46 @@ +/* + * 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 org.junit.Test; +import spark.Spark; + +public class ServiceRunner +{ + // not a real test, runs standalone spark + //@Test + public void run() throws InterruptedException + { + Service service = new Service(); + service.init(); + + Spark.awaitInitialization(); + + for (;;) + { + Thread.sleep(1000L); + } + } +} diff --git a/http-service/src/test/java/net/runelite/http/service/worlds/WorldsServiceTest.java b/http-service/src/test/java/net/runelite/http/service/worlds/WorldsServiceTest.java new file mode 100644 index 0000000000..d13587282e --- /dev/null +++ b/http-service/src/test/java/net/runelite/http/service/worlds/WorldsServiceTest.java @@ -0,0 +1,65 @@ +/* + * 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.worlds; + +import java.io.IOException; +import java.io.InputStream; +import java.net.URI; +import net.runelite.http.api.worlds.WorldResult; +import net.runelite.http.service.HttpClient; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.mockito.Matchers; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; +import spark.utils.IOUtils; + +public class WorldsServiceTest +{ + private byte[] worldData; + + @Before + public void before() throws IOException + { + InputStream in = WorldsServiceTest.class.getResourceAsStream("worldlist"); + worldData = IOUtils.toByteArray(in); + } + + @Test + public void testListWorlds() throws Exception + { + HttpClient client = mock(HttpClient.class); + when(client.getBytes(Matchers.any(URI.class))) + .thenReturn(worldData); + + WorldsService worlds = new WorldsService(); + worlds.setClient(client); + + WorldResult worldResult = worlds.listWorlds(); + Assert.assertEquals(82, worldResult.getWorlds().size()); + } + +} diff --git a/http-service/src/test/resources/net/runelite/http/service/worlds/worldlist b/http-service/src/test/resources/net/runelite/http/service/worlds/worldlist new file mode 100644 index 0000000000000000000000000000000000000000..1d1360e5795d066b068e095cf2a033a504405ad6 GIT binary patch literal 5000 zcmeHKOK%%h6uu{Nt&HNnr;&XfUL@?A&0Xv2`>KbrNjykW>2xs2%({goUE2ojRl+UsP2YF3kRF>f)3pl!mq&wAvxSj*vi<` zL+jfJeGeWY1bdoC8M!GddJqr^AHcJOR^c?>rfy383=~o`EgbG-%g){BFW?y(jytE( z4^`J~%Z8WuXg~ztgnJ0Z;z}$8;g*g%lgkR9g4r$CbK^cTzJkXHugooe2$gZDT;KJ# z5d9785>A!3$~+oBz{>`Iajg@H&p1F21Jocycp5{fJHd`3fGmV+CeBADvbNG8Q=gAg+81nq!QO^DM%tc zH84YRq~rOT1m2nR1XRk~LWtMl z2?8qTYY^fMxR-z|?j4iUn{bAJO8M>y@ir_|5ZBq9v=3&$j#M`;+($4^Kz81CLVOIX z1XRx3&dih&0dYfNN^lGwCz$dW(8M2bzu9)u-NWLb!G;%fdpdSwciSv#@4%DfT!$yP zy1S%QDC@Z54Bq;|-nLCR)x1LhZ{@=TRN|n~^~Azc4`7oJ9Bu?UG(mg|W^`uNI=ou5 zV}1u~1XSjxXa=61?0Kqh-a8QA!y^>W{gDj_Pwfn+1K_|vg{*8_w7Fr@Z4pEK3@ao= zi5q7TSJ7xN?r_2eTlg3smkZiQ>aTDSse5UI%lt;=mP-)7LxqI1c!!s9`_+D14&VOS z7COW1M