+ * 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 enum WorldType
+{
+ MEMBERS,
+ PVP,
+ BOUNTY,
+ SKILL_TOTAL,
+ HIGH_RISK,
+ LAST_MAN_STANDING,
+ TOURNAMENT,
+ DEADMAN,
+ SEASONAL_DEADMAN,
+ DEADMAN_TOURNAMENT
+}
diff --git a/http-api/src/main/java/net/runelite/http/api/ws/RuntimeTypeAdapterFactory.java b/http-api/src/main/java/net/runelite/http/api/ws/RuntimeTypeAdapterFactory.java
new file mode 100644
index 0000000000..2819c92ceb
--- /dev/null
+++ b/http-api/src/main/java/net/runelite/http/api/ws/RuntimeTypeAdapterFactory.java
@@ -0,0 +1,240 @@
+/*
+ * Copyright (C) 2011 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.runelite.http.api.ws;
+
+import java.io.IOException;
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+import com.google.gson.Gson;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonParseException;
+import com.google.gson.JsonPrimitive;
+import com.google.gson.TypeAdapter;
+import com.google.gson.TypeAdapterFactory;
+import com.google.gson.internal.Streams;
+import com.google.gson.reflect.TypeToken;
+import com.google.gson.stream.JsonReader;
+import com.google.gson.stream.JsonWriter;
+
+/**
+ * Adapts values whose runtime type may differ from their declaration type. This
+ * is necessary when a field's type is not the same type that GSON should create
+ * when deserializing that field. For example, consider these types:
+ * {@code
+ * abstract class Shape {
+ * int x;
+ * int y;
+ * }
+ * class Circle extends Shape {
+ * int radius;
+ * }
+ * class Rectangle extends Shape {
+ * int width;
+ * int height;
+ * }
+ * class Diamond extends Shape {
+ * int width;
+ * int height;
+ * }
+ * class Drawing {
+ * Shape bottomShape;
+ * Shape topShape;
+ * }
+ * }
+ * Without additional type information, the serialized JSON is ambiguous. Is
+ * the bottom shape in this drawing a rectangle or a diamond?
{@code
+ * {
+ * "bottomShape": {
+ * "width": 10,
+ * "height": 5,
+ * "x": 0,
+ * "y": 0
+ * },
+ * "topShape": {
+ * "radius": 2,
+ * "x": 4,
+ * "y": 1
+ * }
+ * }}
+ * This class addresses this problem by adding type information to the
+ * serialized JSON and honoring that type information when the JSON is
+ * deserialized: {@code
+ * {
+ * "bottomShape": {
+ * "type": "Diamond",
+ * "width": 10,
+ * "height": 5,
+ * "x": 0,
+ * "y": 0
+ * },
+ * "topShape": {
+ * "type": "Circle",
+ * "radius": 2,
+ * "x": 4,
+ * "y": 1
+ * }
+ * }}
+ * Both the type field name ({@code "type"}) and the type labels ({@code
+ * "Rectangle"}) are configurable.
+ *
+ * Registering Types
+ * Create a {@code RuntimeTypeAdapterFactory} by passing the base type and type field
+ * name to the {@link #of} factory method. If you don't supply an explicit type
+ * field name, {@code "type"} will be used. {@code
+ * RuntimeTypeAdapterFactory shapeAdapterFactory
+ * = RuntimeTypeAdapterFactory.of(Shape.class, "type");
+ * }
+ * Next register all of your subtypes. Every subtype must be explicitly
+ * registered. This protects your application from injection attacks. If you
+ * don't supply an explicit type label, the type's simple name will be used.
+ * {@code
+ * shapeAdapter.registerSubtype(Rectangle.class, "Rectangle");
+ * shapeAdapter.registerSubtype(Circle.class, "Circle");
+ * shapeAdapter.registerSubtype(Diamond.class, "Diamond");
+ * }
+ * Finally, register the type adapter factory in your application's GSON builder:
+ * {@code
+ * Gson gson = new GsonBuilder()
+ * .registerTypeAdapterFactory(shapeAdapterFactory)
+ * .create();
+ * }
+ * Like {@code GsonBuilder}, this API supports chaining: {@code
+ * RuntimeTypeAdapterFactory shapeAdapterFactory = RuntimeTypeAdapterFactory.of(Shape.class)
+ * .registerSubtype(Rectangle.class)
+ * .registerSubtype(Circle.class)
+ * .registerSubtype(Diamond.class);
+ * }
+ */
+public final class RuntimeTypeAdapterFactory implements TypeAdapterFactory {
+ private final Class> baseType;
+ private final String typeFieldName;
+ private final Map> labelToSubtype = new LinkedHashMap>();
+ private final Map, String> subtypeToLabel = new LinkedHashMap, String>();
+
+ private RuntimeTypeAdapterFactory(Class> baseType, String typeFieldName) {
+ if (typeFieldName == null || baseType == null) {
+ throw new NullPointerException();
+ }
+ this.baseType = baseType;
+ this.typeFieldName = typeFieldName;
+ }
+
+ /**
+ * Creates a new runtime type adapter using for {@code baseType} using {@code
+ * typeFieldName} as the type field name. Type field names are case sensitive.
+ */
+ public static RuntimeTypeAdapterFactory of(Class baseType, String typeFieldName) {
+ return new RuntimeTypeAdapterFactory(baseType, typeFieldName);
+ }
+
+ /**
+ * Creates a new runtime type adapter for {@code baseType} using {@code "type"} as
+ * the type field name.
+ */
+ public static RuntimeTypeAdapterFactory of(Class baseType) {
+ return new RuntimeTypeAdapterFactory(baseType, "type");
+ }
+
+ /**
+ * Registers {@code type} identified by {@code label}. Labels are case
+ * sensitive.
+ *
+ * @throws IllegalArgumentException if either {@code type} or {@code label}
+ * have already been registered on this type adapter.
+ */
+ public RuntimeTypeAdapterFactory registerSubtype(Class extends T> type, String label) {
+ if (type == null || label == null) {
+ throw new NullPointerException();
+ }
+ if (subtypeToLabel.containsKey(type) || labelToSubtype.containsKey(label)) {
+ throw new IllegalArgumentException("types and labels must be unique");
+ }
+ labelToSubtype.put(label, type);
+ subtypeToLabel.put(type, label);
+ return this;
+ }
+
+ /**
+ * Registers {@code type} identified by its {@link Class#getSimpleName simple
+ * name}. Labels are case sensitive.
+ *
+ * @throws IllegalArgumentException if either {@code type} or its simple name
+ * have already been registered on this type adapter.
+ */
+ public RuntimeTypeAdapterFactory registerSubtype(Class extends T> type) {
+ return registerSubtype(type, type.getSimpleName());
+ }
+
+ public TypeAdapter create(Gson gson, TypeToken type) {
+ if (type.getRawType() != baseType) {
+ return null;
+ }
+
+ final Map> labelToDelegate
+ = new LinkedHashMap>();
+ final Map, TypeAdapter>> subtypeToDelegate
+ = new LinkedHashMap, TypeAdapter>>();
+ for (Map.Entry> entry : labelToSubtype.entrySet()) {
+ TypeAdapter> delegate = gson.getDelegateAdapter(this, TypeToken.get(entry.getValue()));
+ labelToDelegate.put(entry.getKey(), delegate);
+ subtypeToDelegate.put(entry.getValue(), delegate);
+ }
+
+ return new TypeAdapter() {
+ @Override public R read(JsonReader in) throws IOException {
+ JsonElement jsonElement = Streams.parse(in);
+ JsonElement labelJsonElement = jsonElement.getAsJsonObject().remove(typeFieldName);
+ if (labelJsonElement == null) {
+ throw new JsonParseException("cannot deserialize " + baseType
+ + " because it does not define a field named " + typeFieldName);
+ }
+ String label = labelJsonElement.getAsString();
+ @SuppressWarnings("unchecked") // registration requires that subtype extends T
+ TypeAdapter delegate = (TypeAdapter) labelToDelegate.get(label);
+ if (delegate == null) {
+ throw new JsonParseException("cannot deserialize " + baseType + " subtype named "
+ + label + "; did you forget to register a subtype?");
+ }
+ return delegate.fromJsonTree(jsonElement);
+ }
+
+ @Override public void write(JsonWriter out, R value) throws IOException {
+ Class> srcType = value.getClass();
+ String label = subtypeToLabel.get(srcType);
+ @SuppressWarnings("unchecked") // registration requires that subtype extends T
+ TypeAdapter delegate = (TypeAdapter) subtypeToDelegate.get(srcType);
+ if (delegate == null) {
+ throw new JsonParseException("cannot serialize " + srcType.getName()
+ + "; did you forget to register a subtype?");
+ }
+ JsonObject jsonObject = delegate.toJsonTree(value).getAsJsonObject();
+ if (jsonObject.has(typeFieldName)) {
+ throw new JsonParseException("cannot serialize " + srcType.getName()
+ + " because it already defines a field named " + typeFieldName);
+ }
+ JsonObject clone = new JsonObject();
+ clone.add(typeFieldName, new JsonPrimitive(label));
+ for (Map.Entry e : jsonObject.entrySet()) {
+ clone.add(e.getKey(), e.getValue());
+ }
+ Streams.write(clone, out);
+ }
+ }.nullSafe();
+ }
+}
diff --git a/http-api/src/main/java/net/runelite/http/api/ws/WebsocketGsonFactory.java b/http-api/src/main/java/net/runelite/http/api/ws/WebsocketGsonFactory.java
new file mode 100644
index 0000000000..589a538de3
--- /dev/null
+++ b/http-api/src/main/java/net/runelite/http/api/ws/WebsocketGsonFactory.java
@@ -0,0 +1,86 @@
+/*
+ * 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.ws;
+
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import net.runelite.http.api.ws.messages.Handshake;
+import net.runelite.http.api.ws.messages.LoginResponse;
+import net.runelite.http.api.ws.messages.party.Join;
+import net.runelite.http.api.ws.messages.party.Part;
+import net.runelite.http.api.ws.messages.party.UserJoin;
+import net.runelite.http.api.ws.messages.party.UserPart;
+import net.runelite.http.api.ws.messages.party.UserSync;
+
+public class WebsocketGsonFactory
+{
+ private static final Collection> MESSAGES;
+
+ static
+ {
+ final List> messages = new ArrayList<>();
+ messages.add(Handshake.class);
+ messages.add(LoginResponse.class);
+ messages.add(Join.class);
+ messages.add(Part.class);
+ messages.add(UserJoin.class);
+ messages.add(UserPart.class);
+ messages.add(UserSync.class);
+ MESSAGES = messages;
+ }
+
+ public static RuntimeTypeAdapterFactory factory(final Collection> messages)
+ {
+ final RuntimeTypeAdapterFactory factory = RuntimeTypeAdapterFactory.of(WebsocketMessage.class);
+
+ for (Class extends WebsocketMessage> message : MESSAGES)
+ {
+ factory.registerSubtype(message);
+ }
+
+ for (Class extends WebsocketMessage> message : messages)
+ {
+ factory.registerSubtype(message);
+ }
+
+ return factory;
+ }
+
+ public static Gson build(final RuntimeTypeAdapterFactory factory)
+ {
+ return new GsonBuilder()
+ .registerTypeAdapterFactory(factory)
+ .create();
+ }
+
+ public static Gson build()
+ {
+ return build(factory(Collections.emptyList()));
+ }
+}
diff --git a/http-api/src/main/java/net/runelite/http/api/ws/WebsocketMessage.java b/http-api/src/main/java/net/runelite/http/api/ws/WebsocketMessage.java
new file mode 100644
index 0000000000..d732c110cd
--- /dev/null
+++ b/http-api/src/main/java/net/runelite/http/api/ws/WebsocketMessage.java
@@ -0,0 +1,35 @@
+/*
+ * 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.ws;
+
+public class WebsocketMessage
+{
+ protected boolean _party;
+
+ public boolean isParty()
+ {
+ return _party;
+ }
+}
diff --git a/http-api/src/main/java/net/runelite/http/api/ws/messages/Handshake.java b/http-api/src/main/java/net/runelite/http/api/ws/messages/Handshake.java
new file mode 100644
index 0000000000..557f8f524b
--- /dev/null
+++ b/http-api/src/main/java/net/runelite/http/api/ws/messages/Handshake.java
@@ -0,0 +1,43 @@
+/*
+ * 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.ws.messages;
+
+import java.util.UUID;
+import net.runelite.http.api.ws.WebsocketMessage;
+
+public class Handshake extends WebsocketMessage
+{
+ private UUID session;
+
+ public UUID getSession()
+ {
+ return session;
+ }
+
+ public void setSession(UUID session)
+ {
+ this.session = session;
+ }
+}
diff --git a/http-api/src/main/java/net/runelite/http/api/ws/messages/LoginResponse.java b/http-api/src/main/java/net/runelite/http/api/ws/messages/LoginResponse.java
new file mode 100644
index 0000000000..b517e773a2
--- /dev/null
+++ b/http-api/src/main/java/net/runelite/http/api/ws/messages/LoginResponse.java
@@ -0,0 +1,52 @@
+/*
+ * 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.ws.messages;
+
+import net.runelite.http.api.ws.WebsocketMessage;
+
+/**
+ * Called after a successful login to the server
+ * @author Adam
+ */
+public class LoginResponse extends WebsocketMessage
+{
+ private String username;
+
+ public String getUsername()
+ {
+ return username;
+ }
+
+ public void setUsername(String username)
+ {
+ this.username = username;
+ }
+
+ @Override
+ public String toString()
+ {
+ return "LoginResponse{" + "username=" + username + '}';
+ }
+}
diff --git a/http-api/src/main/java/net/runelite/http/api/ws/messages/party/Join.java b/http-api/src/main/java/net/runelite/http/api/ws/messages/party/Join.java
new file mode 100644
index 0000000000..21aed0f653
--- /dev/null
+++ b/http-api/src/main/java/net/runelite/http/api/ws/messages/party/Join.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2018, Tomas Slusny
+ * 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.ws.messages.party;
+
+import java.util.UUID;
+import lombok.EqualsAndHashCode;
+import lombok.Value;
+import net.runelite.http.api.ws.WebsocketMessage;
+
+@Value
+@EqualsAndHashCode(callSuper = true)
+public class Join extends WebsocketMessage
+{
+ private final UUID partyId;
+ private final String name;
+}
diff --git a/http-api/src/main/java/net/runelite/http/api/ws/messages/party/Part.java b/http-api/src/main/java/net/runelite/http/api/ws/messages/party/Part.java
new file mode 100644
index 0000000000..e284ff0cf8
--- /dev/null
+++ b/http-api/src/main/java/net/runelite/http/api/ws/messages/party/Part.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2018, Tomas Slusny
+ * 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.ws.messages.party;
+
+import net.runelite.http.api.ws.WebsocketMessage;
+
+public class Part extends WebsocketMessage
+{
+}
diff --git a/http-api/src/main/java/net/runelite/http/api/ws/messages/party/PartyMemberMessage.java b/http-api/src/main/java/net/runelite/http/api/ws/messages/party/PartyMemberMessage.java
new file mode 100644
index 0000000000..9d5cab8545
--- /dev/null
+++ b/http-api/src/main/java/net/runelite/http/api/ws/messages/party/PartyMemberMessage.java
@@ -0,0 +1,12 @@
+package net.runelite.http.api.ws.messages.party;
+
+import java.util.UUID;
+import lombok.Getter;
+import lombok.Setter;
+
+@Getter
+@Setter
+public abstract class PartyMemberMessage extends PartyMessage
+{
+ private UUID memberId;
+}
diff --git a/http-api/src/main/java/net/runelite/http/api/ws/messages/party/PartyMessage.java b/http-api/src/main/java/net/runelite/http/api/ws/messages/party/PartyMessage.java
new file mode 100644
index 0000000000..709457ed8c
--- /dev/null
+++ b/http-api/src/main/java/net/runelite/http/api/ws/messages/party/PartyMessage.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2018, Tomas Slusny
+ * 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.ws.messages.party;
+
+import net.runelite.http.api.ws.WebsocketMessage;
+
+public abstract class PartyMessage extends WebsocketMessage
+{
+ public PartyMessage()
+ {
+ _party = true;
+ }
+}
diff --git a/http-api/src/main/java/net/runelite/http/api/ws/messages/party/UserJoin.java b/http-api/src/main/java/net/runelite/http/api/ws/messages/party/UserJoin.java
new file mode 100644
index 0000000000..7f940e8060
--- /dev/null
+++ b/http-api/src/main/java/net/runelite/http/api/ws/messages/party/UserJoin.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2018, Tomas Slusny
+ * 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.ws.messages.party;
+
+import java.util.UUID;
+import lombok.EqualsAndHashCode;
+import lombok.Value;
+import net.runelite.http.api.ws.WebsocketMessage;
+
+@Value
+@EqualsAndHashCode(callSuper = true)
+public class UserJoin extends WebsocketMessage
+{
+ private final UUID memberId;
+ private final UUID partyId;
+ private final String name;
+}
diff --git a/http-api/src/main/java/net/runelite/http/api/ws/messages/party/UserPart.java b/http-api/src/main/java/net/runelite/http/api/ws/messages/party/UserPart.java
new file mode 100644
index 0000000000..e80c6002bd
--- /dev/null
+++ b/http-api/src/main/java/net/runelite/http/api/ws/messages/party/UserPart.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2018, Tomas Slusny
+ * 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.ws.messages.party;
+
+import java.util.UUID;
+import lombok.EqualsAndHashCode;
+import lombok.Value;
+import net.runelite.http.api.ws.WebsocketMessage;
+
+@Value
+@EqualsAndHashCode(callSuper = true)
+public class UserPart extends WebsocketMessage
+{
+ private final UUID memberId;
+}
diff --git a/http-api/src/main/java/net/runelite/http/api/ws/messages/party/UserSync.java b/http-api/src/main/java/net/runelite/http/api/ws/messages/party/UserSync.java
new file mode 100644
index 0000000000..c95038c9fa
--- /dev/null
+++ b/http-api/src/main/java/net/runelite/http/api/ws/messages/party/UserSync.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2018, Tomas Slusny
+ * 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.ws.messages.party;
+
+import lombok.EqualsAndHashCode;
+import lombok.Value;
+
+@Value
+@EqualsAndHashCode(callSuper = true)
+public class UserSync extends PartyMemberMessage
+{
+}
diff --git a/http-api/src/main/java/net/runelite/http/api/xp/XpClient.java b/http-api/src/main/java/net/runelite/http/api/xp/XpClient.java
new file mode 100644
index 0000000000..c45fe2e209
--- /dev/null
+++ b/http-api/src/main/java/net/runelite/http/api/xp/XpClient.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2018, 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.xp;
+
+import java.io.IOException;
+import net.runelite.http.api.RuneLiteAPI;
+import okhttp3.Call;
+import okhttp3.Callback;
+import okhttp3.HttpUrl;
+import okhttp3.Request;
+import okhttp3.Response;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class XpClient
+{
+ private static final Logger logger = LoggerFactory.getLogger(XpClient.class);
+
+ public void update(String username)
+ {
+ HttpUrl url = RuneLiteAPI.getApiBase().newBuilder()
+ .addPathSegment("xp")
+ .addPathSegment("update")
+ .addQueryParameter("username", username)
+ .build();
+
+ Request request = new Request.Builder()
+ .url(url)
+ .build();
+
+ RuneLiteAPI.CLIENT.newCall(request).enqueue(new Callback()
+ {
+ @Override
+ public void onFailure(Call call, IOException e)
+ {
+ logger.warn("Error submitting xp track", e);
+ }
+
+ @Override
+ public void onResponse(Call call, Response response)
+ {
+ response.close();
+ logger.debug("Submitted xp track for {}", username);
+ }
+ });
+ }
+}
diff --git a/http-api/src/main/java/net/runelite/http/api/xp/XpData.java b/http-api/src/main/java/net/runelite/http/api/xp/XpData.java
new file mode 100644
index 0000000000..348faa5c78
--- /dev/null
+++ b/http-api/src/main/java/net/runelite/http/api/xp/XpData.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2018, 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.xp;
+
+import java.time.Instant;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+@Data
+@EqualsAndHashCode(exclude = "time")
+public class XpData
+{
+ private Instant time;
+
+ private int attack_xp;
+ private int defence_xp;
+ private int strength_xp;
+ private int hitpoints_xp;
+ private int ranged_xp;
+ private int prayer_xp;
+ private int magic_xp;
+ private int cooking_xp;
+ private int woodcutting_xp;
+ private int fletching_xp;
+ private int fishing_xp;
+ private int firemaking_xp;
+ private int crafting_xp;
+ private int smithing_xp;
+ private int mining_xp;
+ private int herblore_xp;
+ private int agility_xp;
+ private int thieving_xp;
+ private int slayer_xp;
+ private int farming_xp;
+ private int runecraft_xp;
+ private int hunter_xp;
+ private int construction_xp;
+
+ private int overall_rank;
+ private int attack_rank;
+ private int defence_rank;
+ private int strength_rank;
+ private int hitpoints_rank;
+ private int ranged_rank;
+ private int prayer_rank;
+ private int magic_rank;
+ private int cooking_rank;
+ private int woodcutting_rank;
+ private int fletching_rank;
+ private int fishing_rank;
+ private int firemaking_rank;
+ private int crafting_rank;
+ private int smithing_rank;
+ private int mining_rank;
+ private int herblore_rank;
+ private int agility_rank;
+ private int thieving_rank;
+ private int slayer_rank;
+ private int farming_rank;
+ private int runecraft_rank;
+ private int hunter_rank;
+ private int construction_rank;
+}
diff --git a/http-api/src/main/java/net/runelite/http/api/xtea/XteaClient.java b/http-api/src/main/java/net/runelite/http/api/xtea/XteaClient.java
new file mode 100644
index 0000000000..e4ee2c22b9
--- /dev/null
+++ b/http-api/src/main/java/net/runelite/http/api/xtea/XteaClient.java
@@ -0,0 +1,135 @@
+/*
+ * 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.xtea;
+
+import com.google.gson.JsonParseException;
+import com.google.gson.reflect.TypeToken;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.util.List;
+import net.runelite.http.api.RuneLiteAPI;
+import okhttp3.Call;
+import okhttp3.Callback;
+import okhttp3.HttpUrl;
+import okhttp3.MediaType;
+import okhttp3.Request;
+import okhttp3.RequestBody;
+import okhttp3.Response;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class XteaClient
+{
+ private static final MediaType JSON = MediaType.parse("application/json");
+
+ private static final Logger logger = LoggerFactory.getLogger(XteaClient.class);
+
+ public void submit(XteaRequest xteaRequest)
+ {
+ String json = RuneLiteAPI.GSON.toJson(xteaRequest);
+
+ HttpUrl url = RuneLiteAPI.getApiBase().newBuilder()
+ .addPathSegment("xtea")
+ .build();
+
+ logger.debug("Built URI: {}", url);
+
+ Request request = new Request.Builder()
+ .post(RequestBody.create(JSON, json))
+ .url(url)
+ .build();
+
+ RuneLiteAPI.CLIENT.newCall(request).enqueue(new Callback()
+ {
+ @Override
+ public void onFailure(Call call, IOException e)
+ {
+ logger.warn("unable to submit xtea keys", e);
+ }
+
+ @Override
+ public void onResponse(Call call, Response response)
+ {
+ try
+ {
+ if (!response.isSuccessful())
+ {
+ logger.debug("unsuccessful xtea response");
+ }
+ }
+ finally
+ {
+ response.close();
+ }
+ }
+ });
+ }
+
+ public List get() throws IOException
+ {
+ HttpUrl url = RuneLiteAPI.getApiBase().newBuilder()
+ .addPathSegment("xtea")
+ .build();
+
+ Request request = new Request.Builder()
+ .url(url)
+ .build();
+
+ try (Response response = RuneLiteAPI.CLIENT.newCall(request).execute())
+ {
+ InputStream in = response.body().byteStream();
+ // CHECKSTYLE:OFF
+ return RuneLiteAPI.GSON.fromJson(new InputStreamReader(in), new TypeToken>() { }.getType());
+ // CHECKSTYLE:ON
+ }
+ catch (JsonParseException ex)
+ {
+ throw new IOException(ex);
+ }
+ }
+
+ public XteaKey get(int region) throws IOException
+ {
+ HttpUrl url = RuneLiteAPI.getApiBase().newBuilder()
+ .addPathSegment("xtea")
+ .addPathSegment(Integer.toString(region))
+ .build();
+
+ Request request = new Request.Builder()
+ .url(url)
+ .build();
+
+ try (Response response = RuneLiteAPI.CLIENT.newCall(request).execute())
+ {
+ InputStream in = response.body().byteStream();
+ return RuneLiteAPI.GSON.fromJson(new InputStreamReader(in), XteaKey.class);
+ }
+ catch (JsonParseException ex)
+ {
+ throw new IOException(ex);
+ }
+ }
+}
diff --git a/http-api/src/main/java/net/runelite/http/api/xtea/XteaKey.java b/http-api/src/main/java/net/runelite/http/api/xtea/XteaKey.java
new file mode 100644
index 0000000000..c108f223cb
--- /dev/null
+++ b/http-api/src/main/java/net/runelite/http/api/xtea/XteaKey.java
@@ -0,0 +1,51 @@
+/*
+ * 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.xtea;
+
+public class XteaKey
+{
+ private int region;
+ private int keys[];
+
+ public int getRegion()
+ {
+ return region;
+ }
+
+ public void setRegion(int region)
+ {
+ this.region = region;
+ }
+
+ public int[] getKeys()
+ {
+ return keys;
+ }
+
+ public void setKeys(int[] keys)
+ {
+ this.keys = keys;
+ }
+}
diff --git a/http-api/src/main/java/net/runelite/http/api/xtea/XteaRequest.java b/http-api/src/main/java/net/runelite/http/api/xtea/XteaRequest.java
new file mode 100644
index 0000000000..f84c85b83b
--- /dev/null
+++ b/http-api/src/main/java/net/runelite/http/api/xtea/XteaRequest.java
@@ -0,0 +1,54 @@
+/*
+ * 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.xtea;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class XteaRequest
+{
+ private int revision;
+ private List keys = new ArrayList<>();
+
+ public int getRevision()
+ {
+ return revision;
+ }
+
+ public void setRevision(int revision)
+ {
+ this.revision = revision;
+ }
+
+ public List getKeys()
+ {
+ return keys;
+ }
+
+ public void addKey(XteaKey key)
+ {
+ keys.add(key);
+ }
+}
diff --git a/http-api/src/main/resources/runelite.properties b/http-api/src/main/resources/runelite.properties
new file mode 100644
index 0000000000..4011664529
--- /dev/null
+++ b/http-api/src/main/resources/runelite.properties
@@ -0,0 +1,4 @@
+runelite.version=${project.version}
+rs.version=${rs.version}
+runelite.commit=${git.commit.id.abbrev}
+runelite.dirty=${git.dirty}
\ No newline at end of file
diff --git a/http-api/src/test/java/net/runelite/http/api/RuneLiteAPITest.java b/http-api/src/test/java/net/runelite/http/api/RuneLiteAPITest.java
new file mode 100644
index 0000000000..42fadf4363
--- /dev/null
+++ b/http-api/src/test/java/net/runelite/http/api/RuneLiteAPITest.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2018, 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;
+
+import java.io.IOException;
+import okhttp3.Request;
+import okhttp3.mockwebserver.MockResponse;
+import okhttp3.mockwebserver.MockWebServer;
+import org.junit.After;
+import static org.junit.Assert.assertTrue;
+import org.junit.Before;
+import org.junit.Test;
+
+public class RuneLiteAPITest
+{
+ private final MockWebServer server = new MockWebServer();
+
+ @Before
+ public void before() throws IOException
+ {
+ server.enqueue(new MockResponse().setBody("OK"));
+
+ server.start();
+ }
+
+ @After
+ public void after() throws IOException
+ {
+ server.shutdown();
+ }
+
+ @Test
+ public void testUserAgent() throws IOException, InterruptedException
+ {
+ Request request = new Request.Builder()
+ .url(server.url("/").url())
+ .build();
+ RuneLiteAPI.CLIENT.newCall(request).execute().close();
+
+ // rest of UA depends on if git is found
+ assertTrue(server.takeRequest().getHeader("User-Agent").startsWith("RuneLite/" + RuneLiteAPI.getVersion()));
+ }
+}
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
index 23f3459193..47c4058b97 100644
--- a/pom.xml
+++ b/pom.xml
@@ -37,6 +37,7 @@
pom
1.0-SNAPSHOT
+ http-api
RuneLitePlus
api
rs-client