From 88af9303a606475e5aa8e7a601e066fa5c59d72a Mon Sep 17 00:00:00 2001 From: Justin Date: Mon, 3 Jan 2022 02:56:01 +1100 Subject: [PATCH] upstream: merge --- buildSrc/src/main/kotlin/Dependencies.kt | 4 +- .../runelite/cache/region/RegionLoader.java | 6 +- .../runelite/cache/util/XteaKeyManager.java | 25 +- config/checkstyle/checkstyle.xml | 8 +- http-api/http-api.gradle.kts | 1 + .../http/api/discord/DiscordClient.java | 6 +- .../net/runelite/http/api/RuneLiteAPI.java | 28 +- .../http/api/ge/GrandExchangeClient.java | 105 +++-- .../api/ws/RuntimeTypeAdapterFactory.java | 12 +- .../runelite/http/api}/xtea/XteaClient.java | 6 +- http-service/pom.xml | 269 ------------- .../service/SpringBootWebApplication.java | 228 ----------- .../service/SpringSchedulingConfigurer.java | 52 --- .../http/service/SpringWebMvcConfigurer.java | 65 ---- .../http/service/account/AccountService.java | 284 -------------- .../http/service/account/AuthFilter.java | 116 ------ .../runelite/http/service/account/State.java | 35 -- .../http/service/account/UserInfo.java | 46 --- .../service/account/beans/SessionEntry.java | 76 ---- .../http/service/account/beans/UserEntry.java | 57 --- .../runelite/http/service/cache/CacheDAO.java | 123 ------ .../http/service/cache/CacheService.java | 254 ------------ .../service/cache/beans/ArchiveEntry.java | 38 -- .../http/service/cache/beans/CacheEntry.java | 36 -- .../http/service/cache/beans/FileEntry.java | 36 -- .../http/service/cache/beans/IndexEntry.java | 36 -- .../http/service/chat/ChatController.java | 274 ------------- .../http/service/chat/ChatService.java | 263 ------------- .../http/service/chat/KillCountKey.java | 34 -- .../http/service/config/ConfigController.java | 134 ------- .../http/service/config/ConfigService.java | 367 ------------------ .../http/service/feed/FeedController.java | 137 ------- .../http/service/feed/blog/BlogService.java | 143 ------- .../feed/osrsnews/OSRSNewsService.java | 143 ------- .../twitter/TwitterOAuth2TokenResponse.java | 38 -- .../service/feed/twitter/TwitterService.java | 183 --------- .../twitter/TwitterStatusesResponseItem.java | 35 -- .../TwitterStatusesResponseItemUser.java | 38 -- .../service/ge/GrandExchangeController.java | 158 -------- .../http/service/ge/GrandExchangeService.java | 119 ------ .../service/ge/GrandExchangeTradeHistory.java | 38 -- .../net/runelite/http/service/ge/Trade.java | 51 --- .../runelite/http/service/ge/TradeAction.java | 31 -- .../runelite/http/service/ge/TradeEntry.java | 40 -- .../http/service/item/ItemController.java | 113 ------ .../runelite/http/service/item/ItemEntry.java | 39 -- .../http/service/item/ItemService.java | 287 -------------- .../http/service/item/PriceEntry.java | 40 -- .../runelite/http/service/item/RSItem.java | 36 -- .../http/service/item/RSItemResponse.java | 33 -- .../runelite/http/service/item/RSPrices.java | 37 -- .../http/service/loottracker/LootResult.java | 42 -- .../loottracker/LootTrackerController.java | 118 ------ .../loottracker/LootTrackerService.java | 259 ------------ .../pluginhub/PluginHubController.java | 144 ------- .../http/service/util/InstantConverter.java | 48 --- .../InternalServerErrorException.java | 38 -- .../util/exception/NotFoundException.java | 35 -- .../http/service/wiki/PriceResult.java | 44 --- .../http/service/wiki/WikiPriceService.java | 140 ------- .../http/service/worlds/ServiceWorldType.java | 60 --- .../http/service/worlds/WorldController.java | 68 ---- .../http/service/worlds/WorldsService.java | 132 ------- .../runelite/http/service/xtea/XteaCache.java | 39 -- .../http/service/xtea/XteaController.java | 86 ---- .../runelite/http/service/xtea/XteaEntry.java | 40 -- .../http/service/xtea/XteaService.java | 250 ------------ .../src/main/resources/application-dev.yaml | 29 -- .../src/main/resources/application.yaml | 61 --- http-service/src/main/templates/markdown.hbs | 110 ------ http-service/src/main/templates/operation.hbs | 71 ---- http-service/src/main/templates/security.hbs | 88 ----- .../src/main/templates/template.html.hbs | 49 --- http-service/src/main/webapp/WEB-INF/web.xml | 32 -- .../service/config/ConfigControllerTest.java | 85 ---- .../service/config/ConfigServiceTest.java | 72 ---- .../LootTrackerControllerTest.java | 104 ----- .../service/worlds/WorldsServiceTest.java | 79 ---- .../src/test/resources/application-test.yaml | 21 - .../runelite/http/service/worlds/worldlist | Bin 5000 -> 0 bytes .../net/runelite/client/SessionClient.java | 2 - .../runelite/client/config/ConfigManager.java | 1 - .../net/runelite/client/game/ItemClient.java | 1 - .../client/plugins/xtea/XteaPlugin.java | 5 +- .../net/runelite/client/rs/ClientLoader.java | 2 +- .../runelite/client/ui/MacOSQuitStrategy.java | 37 -- .../net/runelite/client/runelite.properties | 6 +- 87 files changed, 96 insertions(+), 7065 deletions(-) rename http-service/src/main/java/net/runelite/http/service/util/redis/RedisPool.java => http-api/src/main/java/net/runelite/http/api/ge/GrandExchangeClient.java (50%) rename {runelite-client/src/main/java/net/runelite/client/plugins => http-api/src/main/java/net/runelite/http/api}/xtea/XteaClient.java (94%) delete mode 100644 http-service/pom.xml delete mode 100644 http-service/src/main/java/net/runelite/http/service/SpringBootWebApplication.java delete mode 100644 http-service/src/main/java/net/runelite/http/service/SpringSchedulingConfigurer.java delete mode 100644 http-service/src/main/java/net/runelite/http/service/SpringWebMvcConfigurer.java delete mode 100644 http-service/src/main/java/net/runelite/http/service/account/AccountService.java delete mode 100644 http-service/src/main/java/net/runelite/http/service/account/AuthFilter.java delete mode 100644 http-service/src/main/java/net/runelite/http/service/account/State.java delete mode 100644 http-service/src/main/java/net/runelite/http/service/account/UserInfo.java delete mode 100644 http-service/src/main/java/net/runelite/http/service/account/beans/SessionEntry.java delete mode 100644 http-service/src/main/java/net/runelite/http/service/account/beans/UserEntry.java delete mode 100644 http-service/src/main/java/net/runelite/http/service/cache/CacheDAO.java delete mode 100644 http-service/src/main/java/net/runelite/http/service/cache/CacheService.java delete mode 100644 http-service/src/main/java/net/runelite/http/service/cache/beans/ArchiveEntry.java delete mode 100644 http-service/src/main/java/net/runelite/http/service/cache/beans/CacheEntry.java delete mode 100644 http-service/src/main/java/net/runelite/http/service/cache/beans/FileEntry.java delete mode 100644 http-service/src/main/java/net/runelite/http/service/cache/beans/IndexEntry.java delete mode 100644 http-service/src/main/java/net/runelite/http/service/chat/ChatController.java delete mode 100644 http-service/src/main/java/net/runelite/http/service/chat/ChatService.java delete mode 100644 http-service/src/main/java/net/runelite/http/service/chat/KillCountKey.java delete mode 100644 http-service/src/main/java/net/runelite/http/service/config/ConfigController.java delete mode 100644 http-service/src/main/java/net/runelite/http/service/config/ConfigService.java delete mode 100644 http-service/src/main/java/net/runelite/http/service/feed/FeedController.java delete mode 100644 http-service/src/main/java/net/runelite/http/service/feed/blog/BlogService.java delete mode 100644 http-service/src/main/java/net/runelite/http/service/feed/osrsnews/OSRSNewsService.java delete mode 100644 http-service/src/main/java/net/runelite/http/service/feed/twitter/TwitterOAuth2TokenResponse.java delete mode 100644 http-service/src/main/java/net/runelite/http/service/feed/twitter/TwitterService.java delete mode 100644 http-service/src/main/java/net/runelite/http/service/feed/twitter/TwitterStatusesResponseItem.java delete mode 100644 http-service/src/main/java/net/runelite/http/service/feed/twitter/TwitterStatusesResponseItemUser.java delete mode 100644 http-service/src/main/java/net/runelite/http/service/ge/GrandExchangeController.java delete mode 100644 http-service/src/main/java/net/runelite/http/service/ge/GrandExchangeService.java delete mode 100644 http-service/src/main/java/net/runelite/http/service/ge/GrandExchangeTradeHistory.java delete mode 100644 http-service/src/main/java/net/runelite/http/service/ge/Trade.java delete mode 100644 http-service/src/main/java/net/runelite/http/service/ge/TradeAction.java delete mode 100644 http-service/src/main/java/net/runelite/http/service/ge/TradeEntry.java delete mode 100644 http-service/src/main/java/net/runelite/http/service/item/ItemController.java delete mode 100644 http-service/src/main/java/net/runelite/http/service/item/ItemEntry.java delete mode 100644 http-service/src/main/java/net/runelite/http/service/item/ItemService.java delete mode 100644 http-service/src/main/java/net/runelite/http/service/item/PriceEntry.java delete mode 100644 http-service/src/main/java/net/runelite/http/service/item/RSItem.java delete mode 100644 http-service/src/main/java/net/runelite/http/service/item/RSItemResponse.java delete mode 100644 http-service/src/main/java/net/runelite/http/service/item/RSPrices.java delete mode 100644 http-service/src/main/java/net/runelite/http/service/loottracker/LootResult.java delete mode 100644 http-service/src/main/java/net/runelite/http/service/loottracker/LootTrackerController.java delete mode 100644 http-service/src/main/java/net/runelite/http/service/loottracker/LootTrackerService.java delete mode 100644 http-service/src/main/java/net/runelite/http/service/pluginhub/PluginHubController.java delete mode 100644 http-service/src/main/java/net/runelite/http/service/util/InstantConverter.java delete mode 100644 http-service/src/main/java/net/runelite/http/service/util/exception/InternalServerErrorException.java delete mode 100644 http-service/src/main/java/net/runelite/http/service/util/exception/NotFoundException.java delete mode 100644 http-service/src/main/java/net/runelite/http/service/wiki/PriceResult.java delete mode 100644 http-service/src/main/java/net/runelite/http/service/wiki/WikiPriceService.java delete mode 100644 http-service/src/main/java/net/runelite/http/service/worlds/ServiceWorldType.java delete mode 100644 http-service/src/main/java/net/runelite/http/service/worlds/WorldController.java delete mode 100644 http-service/src/main/java/net/runelite/http/service/worlds/WorldsService.java delete mode 100644 http-service/src/main/java/net/runelite/http/service/xtea/XteaCache.java delete mode 100644 http-service/src/main/java/net/runelite/http/service/xtea/XteaController.java delete mode 100644 http-service/src/main/java/net/runelite/http/service/xtea/XteaEntry.java delete mode 100644 http-service/src/main/java/net/runelite/http/service/xtea/XteaService.java delete mode 100644 http-service/src/main/resources/application-dev.yaml delete mode 100644 http-service/src/main/resources/application.yaml delete mode 100644 http-service/src/main/templates/markdown.hbs delete mode 100644 http-service/src/main/templates/operation.hbs delete mode 100644 http-service/src/main/templates/security.hbs delete mode 100644 http-service/src/main/templates/template.html.hbs delete mode 100644 http-service/src/main/webapp/WEB-INF/web.xml delete mode 100644 http-service/src/test/java/net/runelite/http/service/config/ConfigControllerTest.java delete mode 100644 http-service/src/test/java/net/runelite/http/service/config/ConfigServiceTest.java delete mode 100644 http-service/src/test/java/net/runelite/http/service/loottracker/LootTrackerControllerTest.java delete mode 100644 http-service/src/test/java/net/runelite/http/service/worlds/WorldsServiceTest.java delete mode 100644 http-service/src/test/resources/application-test.yaml delete mode 100644 http-service/src/test/resources/net/runelite/http/service/worlds/worldlist delete mode 100644 runelite-client/src/main/java11/net/runelite/client/ui/MacOSQuitStrategy.java diff --git a/buildSrc/src/main/kotlin/Dependencies.kt b/buildSrc/src/main/kotlin/Dependencies.kt index c49cb897aa..0443812cbf 100644 --- a/buildSrc/src/main/kotlin/Dependencies.kt +++ b/buildSrc/src/main/kotlin/Dependencies.kt @@ -25,9 +25,9 @@ object ProjectVersions { const val launcherVersion = "2.2.0" - const val rlVersion = "1.8.7.1" + const val rlVersion = "1.8.8" - const val openosrsVersion = "4.17.1" + const val openosrsVersion = "4.17.2" const val rsversion = 202 const val cacheversion = 165 diff --git a/cache/src/main/java/net/runelite/cache/region/RegionLoader.java b/cache/src/main/java/net/runelite/cache/region/RegionLoader.java index 2dc3176678..21f4868a9a 100644 --- a/cache/src/main/java/net/runelite/cache/region/RegionLoader.java +++ b/cache/src/main/java/net/runelite/cache/region/RegionLoader.java @@ -60,7 +60,6 @@ public class RegionLoader this.store = store; index = store.getIndex(IndexType.MAPS); keyManager = new XteaKeyManager(); - keyManager.loadKeys(); } public void loadRegions() throws IOException @@ -98,10 +97,9 @@ public class RegionLoader Region region = new Region(i); region.loadTerrain(mapDef); - Integer[] keysTmp = keyManager.getKeys(i); - if (keysTmp != null) + int[] keys = keyManager.getKeys(i); + if (keys != null) { - int[] keys = {keysTmp[0], keysTmp[1], keysTmp[2], keysTmp[3]}; try { data = land.decompress(storage.loadArchive(land), keys); diff --git a/cache/src/main/java/net/runelite/cache/util/XteaKeyManager.java b/cache/src/main/java/net/runelite/cache/util/XteaKeyManager.java index 08ffbfb3ba..b139026c3c 100644 --- a/cache/src/main/java/net/runelite/cache/util/XteaKeyManager.java +++ b/cache/src/main/java/net/runelite/cache/util/XteaKeyManager.java @@ -24,10 +24,15 @@ */ package net.runelite.cache.util; +import com.google.gson.Gson; +import com.google.gson.reflect.TypeToken; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.nio.charset.StandardCharsets; import java.util.HashMap; +import java.util.List; import java.util.Map; -import net.runelite.http.api.RuneLiteAPI; -import net.runelite.http.api.xtea.XteaClient; +import net.runelite.http.api.xtea.XteaKey; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -35,18 +40,24 @@ public class XteaKeyManager { private static final Logger logger = LoggerFactory.getLogger(XteaKeyManager.class); - private Map keys = new HashMap<>(); + private final Map keys = new HashMap<>(); - public void loadKeys() + public void loadKeys(InputStream in) { - XteaClient xteaClient = new XteaClient(RuneLiteAPI.CLIENT); + // CHECKSTYLE:OFF + List k = new Gson() + .fromJson(new InputStreamReader(in, StandardCharsets.UTF_8), new TypeToken>() { }.getType()); + // CHECKSTYLE:ON - keys = null; + for (XteaKey key : k) + { + keys.put(key.getRegion(), key.getKeys()); + } logger.info("Loaded {} keys", keys.size()); } - public Integer[] getKeys(int region) + public int[] getKeys(int region) { return keys.get(region); } diff --git a/config/checkstyle/checkstyle.xml b/config/checkstyle/checkstyle.xml index 855e9306fa..85a02c0a69 100644 --- a/config/checkstyle/checkstyle.xml +++ b/config/checkstyle/checkstyle.xml @@ -25,10 +25,11 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. --> + "-//Checkstyle//DTD Checkstyle Configuration 1.3//EN" + "https://checkstyle.org/dtds/configuration_1_3.dtd"> + @@ -60,4 +61,7 @@ + + + diff --git a/http-api/http-api.gradle.kts b/http-api/http-api.gradle.kts index a3997728cc..6acef6f2ef 100644 --- a/http-api/http-api.gradle.kts +++ b/http-api/http-api.gradle.kts @@ -34,6 +34,7 @@ dependencies { implementation(group = "com.google.code.gson", name = "gson", version = "2.8.5") implementation(group = "com.google.guava", name = "guava", version = "30.1.1-jre") + implementation(group = "com.google.inject", name = "guice", version = "5.0.1") implementation(group = "com.squareup.okhttp3", name = "okhttp", version = "4.9.1") implementation(group = "org.apache.commons", name = "commons-csv", version = "1.9.0") implementation(group = "org.slf4j", name = "slf4j-api", version = "1.7.32") diff --git a/http-api/src/main/java/com/openosrs/http/api/discord/DiscordClient.java b/http-api/src/main/java/com/openosrs/http/api/discord/DiscordClient.java index 47b82fdf55..61383bbbc4 100644 --- a/http-api/src/main/java/com/openosrs/http/api/discord/DiscordClient.java +++ b/http-api/src/main/java/com/openosrs/http/api/discord/DiscordClient.java @@ -29,7 +29,7 @@ package com.openosrs.http.api.discord; import com.google.gson.Gson; import java.io.IOException; import lombok.extern.slf4j.Slf4j; -//import net.runelite.http.api.RuneLiteAPI; +import net.runelite.http.api.RuneLiteAPI; import okhttp3.Call; import okhttp3.Callback; import okhttp3.HttpUrl; @@ -60,7 +60,7 @@ public class DiscordClient log.debug("Attempting to message with {}", discordMessage); - /* RuneLiteAPI.CLIENT.newCall(request).enqueue(new Callback() + RuneLiteAPI.CLIENT.newCall(request).enqueue(new Callback() { @Override @@ -95,6 +95,6 @@ public class DiscordClient log.debug("Submitted discord log record"); } } - });*/ + }); } } 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 index 745474880a..b7c91c2f75 100644 --- a/http-api/src/main/java/net/runelite/http/api/RuneLiteAPI.java +++ b/http-api/src/main/java/net/runelite/http/api/RuneLiteAPI.java @@ -51,14 +51,12 @@ public class RuneLiteAPI public static final String RUNELITE_AUTH = "RUNELITE-AUTH"; public static final String RUNELITE_MACHINEID = "RUNELITE-MACHINEID"; - public static final OkHttpClient CLIENT; + public static OkHttpClient CLIENT; public static final Gson GSON; public static final MediaType JSON = MediaType.parse("application/json"); public static String userAgent; private static final String BASE = "https://api.runelite.net"; - private static final String WSBASE = "https://api.runelite.net/ws"; - private static final String STATICBASE = "https://static.runelite.net"; private static final String OPENOSRS_SESSION = "https://session.openosrs.dev"; private static final String OPENOSRS_XTEA = "https://xtea.openosrs.dev"; @@ -140,30 +138,6 @@ public class RuneLiteAPI return HttpUrl.parse(BASE + "/runelite-" + getVersion()); } - public static HttpUrl getStaticBase() - { - final String prop = System.getProperty("runelite.static.url"); - - if (prop != null && !prop.isEmpty()) - { - return HttpUrl.parse(prop); - } - - return HttpUrl.parse(STATICBASE); - } - - public static HttpUrl getWsEndpoint() - { - final String prop = System.getProperty("runelite.ws.url"); - - if (prop != null && !prop.isEmpty()) - { - return HttpUrl.parse(prop); - } - - return HttpUrl.parse(WSBASE); - } - public static HttpUrl getXteaBase() { return HttpUrl.parse(OPENOSRS_XTEA); diff --git a/http-service/src/main/java/net/runelite/http/service/util/redis/RedisPool.java b/http-api/src/main/java/net/runelite/http/api/ge/GrandExchangeClient.java similarity index 50% rename from http-service/src/main/java/net/runelite/http/service/util/redis/RedisPool.java rename to http-api/src/main/java/net/runelite/http/api/ge/GrandExchangeClient.java index c0d4a65a29..1d898ccf27 100644 --- a/http-service/src/main/java/net/runelite/http/service/util/redis/RedisPool.java +++ b/http-api/src/main/java/net/runelite/http/api/ge/GrandExchangeClient.java @@ -22,81 +22,72 @@ * (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.util.redis; +package net.runelite.http.api.ge; -import java.util.concurrent.ArrayBlockingQueue; -import java.util.concurrent.BlockingQueue; -import java.util.concurrent.TimeUnit; +import com.google.gson.Gson; +import java.io.IOException; +import java.util.UUID; +import lombok.RequiredArgsConstructor; +import lombok.Setter; import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.stereotype.Component; -import redis.clients.jedis.Jedis; +import net.runelite.http.api.RuneLiteAPI; +import static net.runelite.http.api.RuneLiteAPI.JSON; +import okhttp3.Call; +import okhttp3.Callback; +import okhttp3.HttpUrl; +import okhttp3.OkHttpClient; +import okhttp3.Request; +import okhttp3.RequestBody; +import okhttp3.Response; -@Component @Slf4j -public class RedisPool +@RequiredArgsConstructor +public class GrandExchangeClient { - private final String redisHost; - private final BlockingQueue queue; + private static final Gson GSON = RuneLiteAPI.GSON; - RedisPool(@Value("${redis.pool.size:10}") int queueSize, @Value("${redis.host:localhost}") String redisHost) + private final OkHttpClient client; + + @Setter + private UUID uuid; + @Setter + private String machineId; + + public void submit(GrandExchangeTrade grandExchangeTrade) { - this.redisHost = redisHost; + final HttpUrl url = RuneLiteAPI.getApiBase().newBuilder() + .addPathSegment("ge") + .build(); - queue = new ArrayBlockingQueue<>(queueSize); - for (int i = 0; i < queueSize; ++i) + Request.Builder builder = new Request.Builder(); + if (uuid != null) { - Jedis jedis = new PooledJedis(redisHost); - queue.offer(jedis); + builder.header(RuneLiteAPI.RUNELITE_AUTH, uuid.toString()); } - } - - public Jedis getResource() - { - Jedis jedis; - try + if (machineId != null) { - jedis = queue.poll(1, TimeUnit.SECONDS); - } - catch (InterruptedException e) - { - throw new RuntimeException(e); - } - if (jedis == null) - { - throw new RuntimeException("Unable to acquire connection from pool, timeout"); - } - return jedis; - } - - class PooledJedis extends Jedis - { - PooledJedis(String host) - { - super(host); + builder.header(RuneLiteAPI.RUNELITE_MACHINEID, machineId); } - @Override - public void close() + Request request = builder + .post(RequestBody.create(JSON, GSON.toJson(grandExchangeTrade))) + .url(url) + .build(); + + client.newCall(request).enqueue(new Callback() { - if (!getClient().isBroken()) + @Override + public void onFailure(Call call, IOException e) { - queue.offer(this); - return; + log.debug("unable to submit trade", e); } - log.warn("jedis client is broken, creating new client"); - - try + @Override + public void onResponse(Call call, Response response) { - super.close(); + log.debug("Submitted trade"); + response.close(); } - catch (Exception e) - { - log.warn("unable to close broken jedis", e); - } - - queue.offer(new PooledJedis(redisHost)); - } + }); } } 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 index 2819c92ceb..b8afb20cec 100644 --- 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 @@ -187,9 +187,9 @@ public final class RuntimeTypeAdapterFactory implements TypeAdapterFactory { } final Map> labelToDelegate - = new LinkedHashMap>(); + = new LinkedHashMap>(); final Map, TypeAdapter> subtypeToDelegate - = new LinkedHashMap, TypeAdapter>(); + = new LinkedHashMap, TypeAdapter>(); for (Map.Entry> entry : labelToSubtype.entrySet()) { TypeAdapter delegate = gson.getDelegateAdapter(this, TypeToken.get(entry.getValue())); labelToDelegate.put(entry.getKey(), delegate); @@ -202,14 +202,14 @@ public final class RuntimeTypeAdapterFactory implements TypeAdapterFactory { JsonElement labelJsonElement = jsonElement.getAsJsonObject().remove(typeFieldName); if (labelJsonElement == null) { throw new JsonParseException("cannot deserialize " + baseType - + " because it does not define a field named " + typeFieldName); + + " 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?"); + + label + "; did you forget to register a subtype?"); } return delegate.fromJsonTree(jsonElement); } @@ -221,12 +221,12 @@ public final class RuntimeTypeAdapterFactory implements TypeAdapterFactory { TypeAdapter delegate = (TypeAdapter) subtypeToDelegate.get(srcType); if (delegate == null) { throw new JsonParseException("cannot serialize " + srcType.getName() - + "; did you forget to register a subtype?"); + + "; 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); + + " because it already defines a field named " + typeFieldName); } JsonObject clone = new JsonObject(); clone.add(typeFieldName, new JsonPrimitive(label)); diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/xtea/XteaClient.java b/http-api/src/main/java/net/runelite/http/api/xtea/XteaClient.java similarity index 94% rename from runelite-client/src/main/java/net/runelite/client/plugins/xtea/XteaClient.java rename to http-api/src/main/java/net/runelite/http/api/xtea/XteaClient.java index d81ea7b6bd..5c9cc34d92 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/xtea/XteaClient.java +++ b/http-api/src/main/java/net/runelite/http/api/xtea/XteaClient.java @@ -22,7 +22,7 @@ * (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.client.plugins.xtea; +package net.runelite.http.api.xtea; import com.google.gson.JsonParseException; import com.google.gson.reflect.TypeToken; @@ -36,8 +36,6 @@ import javax.inject.Named; import lombok.extern.slf4j.Slf4j; import net.runelite.http.api.RuneLiteAPI; import static net.runelite.http.api.RuneLiteAPI.JSON; -import net.runelite.http.api.xtea.XteaKey; -import net.runelite.http.api.xtea.XteaRequest; import okhttp3.Call; import okhttp3.Callback; import okhttp3.HttpUrl; @@ -53,7 +51,7 @@ public class XteaClient private final HttpUrl apiBase; @Inject - private XteaClient(OkHttpClient client, @Named("runelite.api.base") HttpUrl apiBase) + public XteaClient(OkHttpClient client, @Named("runelite.api.base") HttpUrl apiBase) { this.client = client; this.apiBase = apiBase; diff --git a/http-service/pom.xml b/http-service/pom.xml deleted file mode 100644 index d983f9e9da..0000000000 --- a/http-service/pom.xml +++ /dev/null @@ -1,269 +0,0 @@ - - - - 4.0.0 - - - net.runelite - runelite-parent - 1.8.8-SNAPSHOT - - - Web Service - http-service - war - - - 1.5.6.RELEASE - nogit - false - - - - - org.springframework.boot - spring-boot-starter-web - - - org.springframework.boot - spring-boot-starter-tomcat - provided - - - org.springframework.boot - spring-boot-devtools - true - - - org.springframework - spring-jdbc - - - - org.projectlombok - lombok - provided - - - - net.runelite - http-api - ${project.version} - - - net.runelite - cache - ${project.version} - - - - org.mariadb.jdbc - mariadb-java-client - 2.2.3 - provided - - - org.sql2o - sql2o - 1.5.4 - - - com.google.guava - guava - - - com.github.scribejava - scribejava-apis - 4.1.0 - - - io.minio - minio - 3.0.6 - - - redis.clients - jedis - 2.10.0 - - - org.apache.commons - commons-pool2 - - - - - org.mongodb - mongodb-driver-sync - 3.10.2 - provided - - - - org.springframework.boot - spring-boot-starter-test - test - - - com.squareup.okhttp3 - mockwebserver - 3.14.9 - test - - - com.h2database - h2 - test - - - - - - - org.springframework.boot - spring-boot-dependencies - ${spring.boot.version} - pom - import - - - - - - runelite-${project.version} - - - - src/main/resources - true - - - - - - org.apache.maven.plugins - maven-war-plugin - 3.3.1 - - - org.springframework.boot - spring-boot-maven-plugin - ${spring.boot.version} - - - false - - - - com.github.kongchen - swagger-maven-plugin - 3.1.8 - - - - javax.xml.bind - jaxb-api - 2.3.1 - - - - - - true - - net.runelite - - - https - - api.runelite.net - /runelite-${project.version} - - ${project.parent.name} HTTP API - ${project.version} - ${project.description} - - https://tldrlegal.com/license/bsd-2-clause-license-(freebsd) - BSD 2-Clause "Simplified" - - - ${basedir}/src/main/templates/template.html.hbs - ${project.build.directory}/swagger-ui - ${project.build.directory}/site/api.html - true - json - - - - - - compile - - generate - - - - - - pl.project13.maven - git-commit-id-plugin - 2.2.6 - - - query-git-info - - revision - - - false - false - - true - - - git.commit.id.abbrev - git.dirty - - - - - - - - org.apache.maven.plugins - maven-resources-plugin - 2.7 - - - @ - - false - - - - - diff --git a/http-service/src/main/java/net/runelite/http/service/SpringBootWebApplication.java b/http-service/src/main/java/net/runelite/http/service/SpringBootWebApplication.java deleted file mode 100644 index 4c425cb0cf..0000000000 --- a/http-service/src/main/java/net/runelite/http/service/SpringBootWebApplication.java +++ /dev/null @@ -1,228 +0,0 @@ -/* - * 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 ch.qos.logback.classic.LoggerContext; -import com.google.common.base.Strings; -import com.mongodb.client.MongoClient; -import com.mongodb.client.MongoClients; -import java.io.IOException; -import java.time.Instant; -import java.util.HashMap; -import java.util.Map; -import java.util.concurrent.TimeUnit; -import javax.naming.NamingException; -import javax.servlet.ServletContext; -import javax.servlet.ServletContextEvent; -import javax.servlet.ServletContextListener; -import javax.servlet.ServletException; -import javax.sql.DataSource; -import lombok.extern.slf4j.Slf4j; -import net.runelite.http.service.util.InstantConverter; -import okhttp3.Cache; -import okhttp3.OkHttpClient; -import okhttp3.Request; -import org.slf4j.ILoggerFactory; -import org.slf4j.impl.StaticLoggerBinder; -import org.springframework.beans.factory.annotation.Qualifier; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; -import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties; -import org.springframework.boot.builder.SpringApplicationBuilder; -import org.springframework.boot.context.properties.ConfigurationProperties; -import org.springframework.boot.web.support.SpringBootServletInitializer; -import org.springframework.context.annotation.Bean; -import org.springframework.jdbc.datasource.lookup.JndiDataSourceLookup; -import org.springframework.jndi.JndiTemplate; -import org.springframework.scheduling.annotation.EnableScheduling; -import org.sql2o.Sql2o; -import org.sql2o.converters.Converter; -import org.sql2o.quirks.NoQuirks; - -@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class}) -@EnableScheduling -@Slf4j -public class SpringBootWebApplication extends SpringBootServletInitializer -{ - @Bean - protected ServletContextListener listener(OkHttpClient client) - { - return new ServletContextListener() - { - @Override - public void contextInitialized(ServletContextEvent sce) - { - log.info("RuneLite API started"); - } - - @Override - public void contextDestroyed(ServletContextEvent sce) - { - // Destroy okhttp client - client.dispatcher().executorService().shutdown(); - client.connectionPool().evictAll(); - try - { - Cache cache = client.cache(); - if (cache != null) - { - cache.close(); - } - } - catch (IOException ex) - { - log.warn(null, ex); - } - - log.info("RuneLite API stopped"); - } - - }; - } - - @ConfigurationProperties(prefix = "datasource.runelite") - @Bean("dataSourceRuneLite") - public DataSourceProperties dataSourceProperties() - { - return new DataSourceProperties(); - } - - @ConfigurationProperties(prefix = "datasource.runelite-cache") - @Bean("dataSourceRuneLiteCache") - public DataSourceProperties dataSourcePropertiesCache() - { - return new DataSourceProperties(); - } - - @Bean(value = "runelite", destroyMethod = "") - public DataSource runeliteDataSource(@Qualifier("dataSourceRuneLite") DataSourceProperties dataSourceProperties) - { - return getDataSource(dataSourceProperties); - } - - @Bean(value = "runelite-cache", destroyMethod = "") - public DataSource runeliteCache2DataSource(@Qualifier("dataSourceRuneLiteCache") DataSourceProperties dataSourceProperties) - { - return getDataSource(dataSourceProperties); - } - - @Bean("Runelite SQL2O") - public Sql2o sql2o(@Qualifier("runelite") DataSource dataSource) - { - return createSql2oFromDataSource(dataSource); - } - - @Bean("Runelite Cache SQL2O") - public Sql2o cacheSql2o(@Qualifier("runelite-cache") DataSource dataSource) - { - return createSql2oFromDataSource(dataSource); - } - - @Bean(destroyMethod = "") - public MongoClient mongoClient(@Value("${mongo.host:}") String host, @Value("${mongo.jndiName:}") String jndiName) throws NamingException - { - if (!Strings.isNullOrEmpty(jndiName)) - { - JndiTemplate jndiTemplate = new JndiTemplate(); - return jndiTemplate.lookup(jndiName, MongoClient.class); - } - else if (!Strings.isNullOrEmpty(host)) - { - return MongoClients.create(host); - } - else - { - throw new RuntimeException("Either mongo.host or mongo.jndiName must be set"); - } - } - - private static DataSource getDataSource(DataSourceProperties dataSourceProperties) - { - if (!Strings.isNullOrEmpty(dataSourceProperties.getJndiName())) - { - // Use JNDI provided datasource, which is already configured with pooling - JndiDataSourceLookup dataSourceLookup = new JndiDataSourceLookup(); - return dataSourceLookup.getDataSource(dataSourceProperties.getJndiName()); - } - else - { - return dataSourceProperties.initializeDataSourceBuilder().build(); - } - } - - private static Sql2o createSql2oFromDataSource(final DataSource dataSource) - { - final Map converters = new HashMap<>(); - converters.put(Instant.class, new InstantConverter()); - return new Sql2o(dataSource, new NoQuirks(converters)); - } - - @Override - protected SpringApplicationBuilder configure(SpringApplicationBuilder application) - { - return application.sources(SpringBootWebApplication.class); - } - - @Override - public void onStartup(ServletContext servletContext) throws ServletException - { - super.onStartup(servletContext); - ILoggerFactory loggerFactory = StaticLoggerBinder.getSingleton().getLoggerFactory(); - if (loggerFactory instanceof LoggerContext) - { - LoggerContext loggerContext = (LoggerContext) loggerFactory; - loggerContext.setPackagingDataEnabled(false); - log.debug("Disabling logback packaging data"); - } - } - - @Bean - public OkHttpClient okHttpClient( - @Value("${runelite.version}") String version, - @Value("${runelite.commit}") String commit, - @Value("${runelite.dirty}") boolean dirty - ) - { - final String userAgent = "RuneLite/" + version + "-" + commit + (dirty ? "+" : ""); - return new OkHttpClient.Builder() - .pingInterval(30, TimeUnit.SECONDS) - .addNetworkInterceptor(chain -> - { - Request userAgentRequest = chain.request() - .newBuilder() - .header("User-Agent", userAgent) - .build(); - return chain.proceed(userAgentRequest); - }) - .build(); - } - - public static void main(String[] args) - { - SpringApplication.run(SpringBootWebApplication.class, args); - } -} diff --git a/http-service/src/main/java/net/runelite/http/service/SpringSchedulingConfigurer.java b/http-service/src/main/java/net/runelite/http/service/SpringSchedulingConfigurer.java deleted file mode 100644 index 6af0895619..0000000000 --- a/http-service/src/main/java/net/runelite/http/service/SpringSchedulingConfigurer.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (c) 2021, 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.common.util.concurrent.ThreadFactoryBuilder; -import java.util.concurrent.Executors; -import java.util.concurrent.ScheduledExecutorService; -import org.springframework.context.annotation.Configuration; -import org.springframework.scheduling.TaskScheduler; -import org.springframework.scheduling.annotation.SchedulingConfigurer; -import org.springframework.scheduling.concurrent.ConcurrentTaskScheduler; -import org.springframework.scheduling.config.ScheduledTaskRegistrar; - -@Configuration -public class SpringSchedulingConfigurer implements SchedulingConfigurer -{ - @Override - public void configureTasks(ScheduledTaskRegistrar taskRegistrar) - { - // this is from ScheduledTaskRegistrar.scheduleTasks() but modified to give the scheduler thread a - // recognizable name - ScheduledExecutorService scheduledExecutorService = Executors.newSingleThreadScheduledExecutor( - new ThreadFactoryBuilder() - .setNameFormat("scheduler-%d") - .build() - ); - TaskScheduler scheduler = new ConcurrentTaskScheduler(scheduledExecutorService); - taskRegistrar.setTaskScheduler(scheduler); - } -} \ No newline at end of file diff --git a/http-service/src/main/java/net/runelite/http/service/SpringWebMvcConfigurer.java b/http-service/src/main/java/net/runelite/http/service/SpringWebMvcConfigurer.java deleted file mode 100644 index 704e4f9cb2..0000000000 --- a/http-service/src/main/java/net/runelite/http/service/SpringWebMvcConfigurer.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * 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.service; - -import java.util.List; -import net.runelite.http.api.RuneLiteAPI; -import org.springframework.context.annotation.Configuration; -import org.springframework.http.MediaType; -import org.springframework.http.converter.HttpMessageConverter; -import org.springframework.http.converter.json.GsonHttpMessageConverter; -import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; -import org.springframework.web.servlet.config.annotation.ContentNegotiationConfigurer; -import org.springframework.web.servlet.config.annotation.EnableWebMvc; -import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; - -@Configuration -@EnableWebMvc -public class SpringWebMvcConfigurer extends WebMvcConfigurerAdapter -{ - /** - * Configure .js as application/json to trick Cloudflare into caching json responses - */ - @Override - public void configureContentNegotiation(ContentNegotiationConfigurer configurer) - { - configurer.mediaType("js", MediaType.APPLICATION_JSON); - } - - /** - * Use GSON instead of Jackson for JSON serialization - * @param converters - */ - @Override - public void extendMessageConverters(List> converters) - { - // Could not figure out a better way to force GSON - converters.removeIf(MappingJackson2HttpMessageConverter.class::isInstance); - - GsonHttpMessageConverter gsonHttpMessageConverter = new GsonHttpMessageConverter(); - gsonHttpMessageConverter.setGson(RuneLiteAPI.GSON); - converters.add(gsonHttpMessageConverter); - } -} diff --git a/http-service/src/main/java/net/runelite/http/service/account/AccountService.java b/http-service/src/main/java/net/runelite/http/service/account/AccountService.java deleted file mode 100644 index 10a289b927..0000000000 --- a/http-service/src/main/java/net/runelite/http/service/account/AccountService.java +++ /dev/null @@ -1,284 +0,0 @@ -/* - * 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.account; - -import com.github.scribejava.apis.GoogleApi20; -import com.github.scribejava.core.builder.ServiceBuilder; -import com.github.scribejava.core.model.OAuth2AccessToken; -import com.github.scribejava.core.model.OAuthRequest; -import com.github.scribejava.core.model.Response; -import com.github.scribejava.core.model.Verb; -import com.github.scribejava.core.oauth.OAuth20Service; -import com.google.gson.Gson; -import java.io.IOException; -import java.util.HashMap; -import java.util.Map; -import java.util.UUID; -import java.util.concurrent.ExecutionException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import net.runelite.http.api.RuneLiteAPI; -import net.runelite.http.api.account.OAuthResponse; -import net.runelite.http.api.ws.WebsocketGsonFactory; -import net.runelite.http.api.ws.WebsocketMessage; -import net.runelite.http.api.ws.messages.LoginResponse; -import net.runelite.http.service.account.beans.SessionEntry; -import net.runelite.http.service.account.beans.UserEntry; -import net.runelite.http.service.util.redis.RedisPool; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Qualifier; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.bind.annotation.RestController; -import org.sql2o.Connection; -import org.sql2o.Sql2o; -import org.sql2o.Sql2oException; -import redis.clients.jedis.Jedis; - -@RestController -@RequestMapping("/account") -public class AccountService -{ - private static final Logger logger = LoggerFactory.getLogger(AccountService.class); - - private static final String CREATE_SESSIONS = "CREATE TABLE IF NOT EXISTS `sessions` (\n" - + " `user` int(11) NOT NULL PRIMARY KEY,\n" - + " `uuid` varchar(36) NOT NULL,\n" - + " `created` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,\n" - + " `last_used` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,\n" - + " UNIQUE KEY `uuid` (`uuid`),\n" - + " KEY `user` (`user`)\n" - + ") ENGINE=InnoDB"; - - private static final String CREATE_USERS = "CREATE TABLE IF NOT EXISTS `users` (\n" - + " `id` int(11) NOT NULL AUTO_INCREMENT,\n" - + " `username` tinytext NOT NULL,\n" - + " `created` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,\n" - + " PRIMARY KEY (`id`),\n" - + " UNIQUE KEY `username` (`username`(64))\n" - + ") ENGINE=InnoDB"; - - private static final String SESSIONS_FK = "ALTER TABLE `sessions`\n" - + " ADD CONSTRAINT `id` FOREIGN KEY (`user`) REFERENCES `users` (`id`) ON DELETE CASCADE ON UPDATE CASCADE;"; - - private static final String SCOPE = "https://www.googleapis.com/auth/userinfo.email"; - private static final String USERINFO = "https://www.googleapis.com/oauth2/v2/userinfo"; - private static final String RL_REDIR = "https://runelite.net/logged-in"; - - private final Gson gson = RuneLiteAPI.GSON; - private final Gson websocketGson = WebsocketGsonFactory.build(); - - private final Sql2o sql2o; - private final String oauthClientId; - private final String oauthClientSecret; - private final String oauthCallback; - private final String runeliteVersion; - private final AuthFilter auth; - private final RedisPool jedisPool; - - @Autowired - public AccountService( - @Qualifier("Runelite SQL2O") Sql2o sql2o, - @Value("${oauth.client-id}") String oauthClientId, - @Value("${oauth.client-secret}") String oauthClientSecret, - @Value("${oauth.callback}") String oauthCallback, - @Value("${runelite.version}") String runeliteVersion, - AuthFilter auth, - RedisPool jedisPool - ) - { - this.sql2o = sql2o; - this.oauthClientId = oauthClientId; - this.oauthClientSecret = oauthClientSecret; - this.oauthCallback = oauthCallback; - this.runeliteVersion = runeliteVersion; - this.auth = auth; - this.jedisPool = jedisPool; - - try (Connection con = sql2o.open()) - { - con.createQuery(CREATE_SESSIONS) - .executeUpdate(); - - con.createQuery(CREATE_USERS) - .executeUpdate(); - - try - { - con.createQuery(SESSIONS_FK) - .executeUpdate(); - } - catch (Sql2oException ex) - { - // Ignore, happens when index already exists - } - } - } - - @GetMapping("/login") - public OAuthResponse login(@RequestParam UUID uuid) - { - State state = new State(); - state.setUuid(uuid); - state.setApiVersion(runeliteVersion); - - OAuth20Service service = new ServiceBuilder() - .apiKey(oauthClientId) - .apiSecret(oauthClientSecret) - .scope(SCOPE) - .callback(oauthCallback) - .state(gson.toJson(state)) - .build(GoogleApi20.instance()); - - final Map additionalParams = new HashMap<>(); - additionalParams.put("prompt", "select_account"); - - String authorizationUrl = service.getAuthorizationUrl(additionalParams); - - OAuthResponse lr = new OAuthResponse(); - lr.setOauthUrl(authorizationUrl); - lr.setUid(uuid); - - return lr; - } - - @GetMapping("/callback") - public Object callback( - HttpServletRequest request, - HttpServletResponse response, - @RequestParam(required = false) String error, - @RequestParam String code, - @RequestParam("state") String stateStr - ) throws InterruptedException, ExecutionException, IOException - { - if (error != null) - { - logger.info("Error in oauth callback: {}", error); - return null; - } - - State state = gson.fromJson(stateStr, State.class); - - logger.info("Got authorization code {} for uuid {}", code, state.getUuid()); - - OAuth20Service service = new ServiceBuilder() - .apiKey(oauthClientId) - .apiSecret(oauthClientSecret) - .scope(SCOPE) - .callback(oauthCallback) - .state(gson.toJson(state)) - .build(GoogleApi20.instance()); - - OAuth2AccessToken accessToken = service.getAccessToken(code); - - // Access user info - OAuthRequest orequest = new OAuthRequest(Verb.GET, USERINFO); - service.signRequest(accessToken, orequest); - - Response oresponse = service.execute(orequest); - - if (oresponse.getCode() / 100 != 2) - { - // Could be a forged result - return null; - } - - UserInfo userInfo = gson.fromJson(oresponse.getBody(), UserInfo.class); - - logger.info("Got user info: {}", userInfo); - - try (Connection con = sql2o.open()) - { - con.createQuery("insert ignore into users (username) values (:username)") - .addParameter("username", userInfo.getEmail()) - .executeUpdate(); - - UserEntry user = con.createQuery("select id from users where username = :username") - .addParameter("username", userInfo.getEmail()) - .executeAndFetchFirst(UserEntry.class); - - if (user == null) - { - logger.warn("Unable to find newly created user session"); - return null; // that's weird - } - - // insert session - con.createQuery("insert ignore into sessions (user, uuid) values (:user, :uuid)") - .addParameter("user", user.getId()) - .addParameter("uuid", state.getUuid().toString()) - .executeUpdate(); - - logger.info("Created session for user {}", userInfo.getEmail()); - } - - response.sendRedirect(RL_REDIR); - - notifySession(state.getUuid(), userInfo.getEmail()); - - return ""; - } - - private void notifySession(UUID uuid, String username) - { - LoginResponse response = new LoginResponse(); - response.setUsername(username); - - try (Jedis jedis = jedisPool.getResource()) - { - jedis.publish("session." + uuid, websocketGson.toJson(response, WebsocketMessage.class)); - } - } - - @GetMapping("/logout") - public void logout(HttpServletRequest request, HttpServletResponse response) throws IOException - { - SessionEntry session = auth.handle(request, response); - - if (session == null) - { - return; - } - - auth.invalidate(session.getUuid()); - - try (Connection con = sql2o.open()) - { - con.createQuery("delete from sessions where uuid = :uuid") - .addParameter("uuid", session.getUuid().toString()) - .executeUpdate(); - } - } - - @GetMapping("/session-check") - public void sessionCheck(HttpServletRequest request, HttpServletResponse response) throws IOException - { - auth.handle(request, response); - } -} diff --git a/http-service/src/main/java/net/runelite/http/service/account/AuthFilter.java b/http-service/src/main/java/net/runelite/http/service/account/AuthFilter.java deleted file mode 100644 index d283e71c5c..0000000000 --- a/http-service/src/main/java/net/runelite/http/service/account/AuthFilter.java +++ /dev/null @@ -1,116 +0,0 @@ -/* - * 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.account; - -import com.google.common.cache.Cache; -import com.google.common.cache.CacheBuilder; -import com.google.common.cache.RemovalNotification; -import java.io.IOException; -import java.sql.Timestamp; -import java.time.Instant; -import java.util.UUID; -import java.util.concurrent.TimeUnit; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import net.runelite.http.api.RuneLiteAPI; -import net.runelite.http.service.account.beans.SessionEntry; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Qualifier; -import org.springframework.stereotype.Service; -import org.sql2o.Connection; -import org.sql2o.Sql2o; - -@Service -public class AuthFilter -{ - private final Sql2o sql2o; - - private final Cache sessionCache = CacheBuilder.newBuilder() - .maximumSize(10000L) - .expireAfterAccess(30, TimeUnit.MINUTES) - .removalListener(this::removalListener) - .build(); - - @Autowired - public AuthFilter(@Qualifier("Runelite SQL2O") Sql2o sql2o) - { - this.sql2o = sql2o; - } - - public SessionEntry handle(HttpServletRequest request, HttpServletResponse response) throws IOException - { - String runeliteAuth = request.getHeader(RuneLiteAPI.RUNELITE_AUTH); - if (runeliteAuth == null) - { - response.sendError(401, "Access denied"); - return null; - } - - UUID uuid = UUID.fromString(runeliteAuth); - SessionEntry sessionEntry = sessionCache.getIfPresent(uuid); - if (sessionEntry != null) - { - return sessionEntry; - } - - try (Connection con = sql2o.open()) - { - sessionEntry = con.createQuery("select user, uuid, created, last_used as lastUsed from sessions where uuid = :uuid") - .addParameter("uuid", uuid.toString()) - .executeAndFetchFirst(SessionEntry.class); - } - - if (sessionEntry == null) - { - response.sendError(401, "Access denied"); - return null; - } - - sessionCache.put(uuid, sessionEntry); - - return sessionEntry; - } - - private void removalListener(RemovalNotification notification) - { - UUID uuid = notification.getKey(); - Instant now = Instant.now(); - - try (Connection con = sql2o.open()) - { - con.createQuery("update sessions set last_used = :last_used where uuid = :uuid") - .addParameter("last_used", Timestamp.from(now)) - .addParameter("uuid", uuid.toString()) - .executeUpdate(); - } - } - - public void invalidate(UUID uuid) - { - // If we ever run multiple services, may need to publish something here to invalidate... - sessionCache.invalidate(uuid); - } - -} diff --git a/http-service/src/main/java/net/runelite/http/service/account/State.java b/http-service/src/main/java/net/runelite/http/service/account/State.java deleted file mode 100644 index 1412efa11a..0000000000 --- a/http-service/src/main/java/net/runelite/http/service/account/State.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * 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.account; - -import java.util.UUID; -import lombok.Data; - -@Data -public class State -{ - private UUID uuid; - private String apiVersion; -} diff --git a/http-service/src/main/java/net/runelite/http/service/account/UserInfo.java b/http-service/src/main/java/net/runelite/http/service/account/UserInfo.java deleted file mode 100644 index a1cde03f79..0000000000 --- a/http-service/src/main/java/net/runelite/http/service/account/UserInfo.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * 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.account; - -public class UserInfo -{ - private String email; - - @Override - public String toString() - { - return "UserInfo{" + "email=" + email + '}'; - } - - public String getEmail() - { - return email; - } - - public void setEmail(String email) - { - this.email = email; - } -} diff --git a/http-service/src/main/java/net/runelite/http/service/account/beans/SessionEntry.java b/http-service/src/main/java/net/runelite/http/service/account/beans/SessionEntry.java deleted file mode 100644 index ded67c7a45..0000000000 --- a/http-service/src/main/java/net/runelite/http/service/account/beans/SessionEntry.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * 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.account.beans; - -import java.time.Instant; -import java.util.UUID; - -public class SessionEntry -{ - private int user; - private UUID uuid; - private Instant created; - private Instant lastUsed; - - public int getUser() - { - return user; - } - - public void setUser(int user) - { - this.user = user; - } - - public UUID getUuid() - { - return uuid; - } - - public void setUuid(UUID uuid) - { - this.uuid = uuid; - } - - public Instant getCreated() - { - return created; - } - - public void setCreated(Instant created) - { - this.created = created; - } - - public Instant getLastUsed() - { - return lastUsed; - } - - public void setLastUsed(Instant lastUsed) - { - this.lastUsed = lastUsed; - } -} diff --git a/http-service/src/main/java/net/runelite/http/service/account/beans/UserEntry.java b/http-service/src/main/java/net/runelite/http/service/account/beans/UserEntry.java deleted file mode 100644 index 83dd4152ac..0000000000 --- a/http-service/src/main/java/net/runelite/http/service/account/beans/UserEntry.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * 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.account.beans; - -public class UserEntry -{ - private int id; - private String username; - - @Override - public String toString() - { - return "UserEntry{" + "id=" + id + ", username=" + username + '}'; - } - - public int getId() - { - return id; - } - - public void setId(int id) - { - this.id = id; - } - - public String getUsername() - { - return username; - } - - public void setUsername(String username) - { - this.username = username; - } -} diff --git a/http-service/src/main/java/net/runelite/http/service/cache/CacheDAO.java b/http-service/src/main/java/net/runelite/http/service/cache/CacheDAO.java deleted file mode 100644 index 08282ca38e..0000000000 --- a/http-service/src/main/java/net/runelite/http/service/cache/CacheDAO.java +++ /dev/null @@ -1,123 +0,0 @@ -/* - * 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.cache; - -import java.util.List; -import net.runelite.cache.IndexType; -import net.runelite.http.service.cache.beans.ArchiveEntry; -import net.runelite.http.service.cache.beans.CacheEntry; -import net.runelite.http.service.cache.beans.FileEntry; -import net.runelite.http.service.cache.beans.IndexEntry; -import org.sql2o.Connection; -import org.sql2o.Query; -import org.sql2o.ResultSetIterable; - -class CacheDAO -{ - public List listCaches(Connection con) - { - return con.createQuery("select id, revision, date from cache") - .executeAndFetch(CacheEntry.class); - } - - public CacheEntry findMostRecent(Connection con) - { - return con.createQuery("select id, revision, date from cache order by revision desc, date desc limit 1") - .executeAndFetchFirst(CacheEntry.class); - } - - public List findIndexesForCache(Connection con, CacheEntry cache) - { - return con.createQuery("select id, indexId, crc, revision from `index` where cache = :cache") - .addParameter("cache", cache.getId()) - .executeAndFetch(IndexEntry.class); - } - - public IndexEntry findIndexForCache(Connection con, CacheEntry cache, int indexId) - { - return con.createQuery("select id, indexId, crc, revision from `index` " - + "where cache = :id " - + "and indexId = :indexId") - .addParameter("id", cache.getId()) - .addParameter("indexId", indexId) - .executeAndFetchFirst(IndexEntry.class); - } - - public ResultSetIterable findArchivesForIndex(Connection con, IndexEntry indexEntry) - { - return con.createQuery("select archive.id, archive.archiveId, archive.nameHash," - + " archive.crc, archive.revision, archive.hash from index_archive " - + "join archive on index_archive.archive = archive.id " - + "where index_archive.index = :id") - .addParameter("id", indexEntry.getId()) - .executeAndFetchLazy(ArchiveEntry.class); - } - - public ArchiveEntry findArchiveForIndex(Connection con, IndexEntry indexEntry, int archiveId) - { - return con.createQuery("select archive.id, archive.archiveId, archive.nameHash," - + " archive.crc, archive.revision, archive.hash from index_archive " - + "join archive on index_archive.archive = archive.id " - + "where index_archive.index = :id " - + "and archive.archiveId = :archiveId") - .addParameter("id", indexEntry.getId()) - .addParameter("archiveId", archiveId) - .executeAndFetchFirst(ArchiveEntry.class); - } - - public ArchiveEntry findArchiveByName(Connection con, CacheEntry cache, IndexType index, int nameHash) - { - return con.createQuery("select archive.id, archive.archiveId, archive.nameHash," - + " archive.crc, archive.revision, archive.hash from archive " - + "join index_archive on index_archive.archive = archive.id " - + "join `index` on index.id = index_archive.index " - + "where index.cache = :cacheId " - + "and index.indexId = :indexId " - + "and archive.nameHash = :nameHash " - + "limit 1") - .addParameter("cacheId", cache.getId()) - .addParameter("indexId", index.getNumber()) - .addParameter("nameHash", nameHash) - .executeAndFetchFirst(ArchiveEntry.class); - } - - public ResultSetIterable findFilesForArchive(Connection con, ArchiveEntry archiveEntry) - { - Query findFilesForArchive = con.createQuery("select id, fileId, nameHash from file " - + "where archive = :archive"); - - return findFilesForArchive - .addParameter("archive", archiveEntry.getId()) - .executeAndFetchLazy(FileEntry.class); - } - - public CacheEntry findCache(Connection con, int cacheId) - { - return con.createQuery("select id, revision, date from cache " - + "where id = :cacheId") - .addParameter("cacheId", cacheId) - .executeAndFetchFirst(CacheEntry.class); - } -} diff --git a/http-service/src/main/java/net/runelite/http/service/cache/CacheService.java b/http-service/src/main/java/net/runelite/http/service/cache/CacheService.java deleted file mode 100644 index c0b767a68c..0000000000 --- a/http-service/src/main/java/net/runelite/http/service/cache/CacheService.java +++ /dev/null @@ -1,254 +0,0 @@ -/* - * Copyright (c) 2017-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.service.cache; - -import com.google.common.collect.Iterables; -import com.google.common.io.BaseEncoding; -import com.google.common.io.ByteStreams; -import io.minio.MinioClient; -import io.minio.errors.ErrorResponseException; -import io.minio.errors.InsufficientDataException; -import io.minio.errors.InternalException; -import io.minio.errors.InvalidArgumentException; -import io.minio.errors.InvalidBucketNameException; -import io.minio.errors.InvalidEndpointException; -import io.minio.errors.InvalidPortException; -import io.minio.errors.NoResponseException; -import java.io.IOException; -import java.io.InputStream; -import java.security.InvalidKeyException; -import java.security.NoSuchAlgorithmException; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import lombok.extern.slf4j.Slf4j; -import net.runelite.cache.ConfigType; -import net.runelite.cache.IndexType; -import net.runelite.cache.definitions.ItemDefinition; -import net.runelite.cache.definitions.loaders.ItemLoader; -import net.runelite.cache.fs.ArchiveFiles; -import net.runelite.cache.fs.Container; -import net.runelite.cache.fs.FSFile; -import net.runelite.http.service.cache.beans.ArchiveEntry; -import net.runelite.http.service.cache.beans.CacheEntry; -import net.runelite.http.service.cache.beans.FileEntry; -import net.runelite.http.service.cache.beans.IndexEntry; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Qualifier; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.context.annotation.Bean; -import org.springframework.stereotype.Service; -import org.sql2o.Connection; -import org.sql2o.ResultSetIterable; -import org.sql2o.Sql2o; -import org.xmlpull.v1.XmlPullParserException; - -@Service -@Slf4j -public class CacheService -{ - @Autowired - @Qualifier("Runelite Cache SQL2O") - private Sql2o sql2o; - - @Value("${minio.bucket}") - private String minioBucket; - - private final MinioClient minioClient; - - @Autowired - public CacheService( - @Value("${minio.endpoint}") String minioEndpoint, - @Value("${minio.accesskey}") String accessKey, - @Value("${minio.secretkey}") String secretKey - ) throws InvalidEndpointException, InvalidPortException - { - this.minioClient = new MinioClient(minioEndpoint, accessKey, secretKey); - } - - @Bean - public MinioClient minioClient() - { - return minioClient; - } - - /** - * retrieve archive from storage - * - * @param archiveEntry - * @return - */ - public byte[] getArchive(ArchiveEntry archiveEntry) - { - String hashStr = BaseEncoding.base16().encode(archiveEntry.getHash()); - String path = new StringBuilder() - .append(hashStr, 0, 2) - .append('/') - .append(hashStr.substring(2)) - .toString(); - - try (InputStream in = minioClient.getObject(minioBucket, path)) - { - return ByteStreams.toByteArray(in); - } - catch (InvalidBucketNameException | NoSuchAlgorithmException | InsufficientDataException - | IOException | InvalidKeyException | NoResponseException | XmlPullParserException - | ErrorResponseException | InternalException | InvalidArgumentException ex) - { - log.warn(null, ex); - return null; - } - } - - public ArchiveFiles getArchiveFiles(ArchiveEntry archiveEntry) throws IOException - { - CacheDAO cacheDao = new CacheDAO(); - - try (Connection con = sql2o.open(); - ResultSetIterable files = cacheDao.findFilesForArchive(con, archiveEntry)) - { - byte[] archiveData = getArchive(archiveEntry); - - if (archiveData == null) - { - return null; - } - - Container result = Container.decompress(archiveData, null); - if (result == null) - { - return null; - } - - byte[] decompressedData = result.data; - - ArchiveFiles archiveFiles = new ArchiveFiles(); - for (FileEntry fileEntry : files) - { - FSFile file = new FSFile(fileEntry.getFileId()); - archiveFiles.addFile(file); - file.setNameHash(fileEntry.getNameHash()); - } - archiveFiles.loadContents(decompressedData); - return archiveFiles; - } - } - - public List listCaches() - { - try (Connection con = sql2o.open()) - { - CacheDAO cacheDao = new CacheDAO(); - return cacheDao.listCaches(con); - } - } - - public CacheEntry findCache(int cacheId) - { - try (Connection con = sql2o.open()) - { - CacheDAO cacheDao = new CacheDAO(); - return cacheDao.findCache(con, cacheId); - } - } - - public CacheEntry findMostRecent() - { - try (Connection con = sql2o.open()) - { - CacheDAO cacheDao = new CacheDAO(); - return cacheDao.findMostRecent(con); - } - } - - public List findIndexesForCache(CacheEntry cacheEntry) - { - try (Connection con = sql2o.open()) - { - CacheDAO cacheDao = new CacheDAO(); - return cacheDao.findIndexesForCache(con, cacheEntry); - } - } - - public IndexEntry findIndexForCache(CacheEntry cahceEntry, int indexId) - { - try (Connection con = sql2o.open()) - { - CacheDAO cacheDao = new CacheDAO(); - return cacheDao.findIndexForCache(con, cahceEntry, indexId); - } - } - - public List findArchivesForIndex(IndexEntry indexEntry) - { - try (Connection con = sql2o.open()) - { - CacheDAO cacheDao = new CacheDAO(); - ResultSetIterable archiveEntries = cacheDao.findArchivesForIndex(con, indexEntry); - List archives = new ArrayList<>(); - Iterables.addAll(archives, archiveEntries); - return archives; - } - } - - public ArchiveEntry findArchiveForIndex(IndexEntry indexEntry, int archiveId) - { - try (Connection con = sql2o.open()) - { - CacheDAO cacheDao = new CacheDAO(); - return cacheDao.findArchiveForIndex(con, indexEntry, archiveId); - } - } - - public ArchiveEntry findArchiveForTypeAndName(CacheEntry cache, IndexType index, int nameHash) - { - try (Connection con = sql2o.open()) - { - CacheDAO cacheDao = new CacheDAO(); - return cacheDao.findArchiveByName(con, cache, index, nameHash); - } - } - - public List getItems() throws IOException - { - CacheEntry cache = findMostRecent(); - if (cache == null) - { - return Collections.emptyList(); - } - - IndexEntry indexEntry = findIndexForCache(cache, IndexType.CONFIGS.getNumber()); - ArchiveEntry archiveEntry = findArchiveForIndex(indexEntry, ConfigType.ITEM.getId()); - ArchiveFiles archiveFiles = getArchiveFiles(archiveEntry); - final ItemLoader itemLoader = new ItemLoader(); - final List result = new ArrayList<>(archiveFiles.getFiles().size()); - for (FSFile file : archiveFiles.getFiles()) - { - ItemDefinition itemDef = itemLoader.load(file.getFileId(), file.getContents()); - result.add(itemDef); - } - return result; - } -} diff --git a/http-service/src/main/java/net/runelite/http/service/cache/beans/ArchiveEntry.java b/http-service/src/main/java/net/runelite/http/service/cache/beans/ArchiveEntry.java deleted file mode 100644 index acda96e77f..0000000000 --- a/http-service/src/main/java/net/runelite/http/service/cache/beans/ArchiveEntry.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * 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.cache.beans; - -import lombok.Data; - -@Data -public class ArchiveEntry -{ - private int id; - private int archiveId; - private int nameHash; - private int crc; - private int revision; - private byte[] hash; -} diff --git a/http-service/src/main/java/net/runelite/http/service/cache/beans/CacheEntry.java b/http-service/src/main/java/net/runelite/http/service/cache/beans/CacheEntry.java deleted file mode 100644 index 231ad7c655..0000000000 --- a/http-service/src/main/java/net/runelite/http/service/cache/beans/CacheEntry.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * 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.cache.beans; - -import java.time.Instant; -import lombok.Data; - -@Data -public class CacheEntry -{ - private int id; - private int revision; - private Instant date; -} diff --git a/http-service/src/main/java/net/runelite/http/service/cache/beans/FileEntry.java b/http-service/src/main/java/net/runelite/http/service/cache/beans/FileEntry.java deleted file mode 100644 index c5f35a4cc3..0000000000 --- a/http-service/src/main/java/net/runelite/http/service/cache/beans/FileEntry.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * 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.cache.beans; - -import lombok.Data; - -@Data -public class FileEntry -{ - private int id; - private int archiveId; - private int fileId; - private int nameHash; -} diff --git a/http-service/src/main/java/net/runelite/http/service/cache/beans/IndexEntry.java b/http-service/src/main/java/net/runelite/http/service/cache/beans/IndexEntry.java deleted file mode 100644 index 8d60927c71..0000000000 --- a/http-service/src/main/java/net/runelite/http/service/cache/beans/IndexEntry.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * 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.cache.beans; - -import lombok.Data; - -@Data -public class IndexEntry -{ - private int id; - private int indexId; - private int crc; - private int revision; -} diff --git a/http-service/src/main/java/net/runelite/http/service/chat/ChatController.java b/http-service/src/main/java/net/runelite/http/service/chat/ChatController.java deleted file mode 100644 index 954c90e94b..0000000000 --- a/http-service/src/main/java/net/runelite/http/service/chat/ChatController.java +++ /dev/null @@ -1,274 +0,0 @@ -/* - * 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.service.chat; - -import com.google.common.cache.Cache; -import com.google.common.cache.CacheBuilder; -import java.util.concurrent.TimeUnit; -import java.util.regex.Matcher; -import java.util.regex.Pattern; -import net.runelite.http.api.chat.Duels; -import net.runelite.http.api.chat.LayoutRoom; -import net.runelite.http.api.chat.Task; -import net.runelite.http.service.util.exception.NotFoundException; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.http.CacheControl; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.bind.annotation.RestController; - -@RestController -@RequestMapping("/chat") -public class ChatController -{ - private static final Pattern STRING_VALIDATION = Pattern.compile("[^a-zA-Z0-9' -]"); - private static final int STRING_MAX_LENGTH = 50; - private static final int MAX_LAYOUT_ROOMS = 16; - private static final int MAX_PETS = 256; - - private final Cache killCountCache = CacheBuilder.newBuilder() - .expireAfterWrite(2, TimeUnit.MINUTES) - .maximumSize(128L) - .build(); - - @Autowired - private ChatService chatService; - - @PostMapping("/kc") - public void submitKc(@RequestParam String name, @RequestParam String boss, @RequestParam int kc) - { - if (kc <= 0) - { - return; - } - - chatService.setKc(name, boss, kc); - killCountCache.put(new KillCountKey(name, boss), kc); - } - - @GetMapping("/kc") - public int getKc(@RequestParam String name, @RequestParam String boss) - { - Integer kc = killCountCache.getIfPresent(new KillCountKey(name, boss)); - if (kc == null) - { - kc = chatService.getKc(name, boss); - if (kc != null) - { - killCountCache.put(new KillCountKey(name, boss), kc); - } - } - - if (kc == null) - { - throw new NotFoundException(); - } - return kc; - } - - @PostMapping("/qp") - public void submitQp(@RequestParam String name, @RequestParam int qp) - { - if (qp < 0) - { - return; - } - - chatService.setQp(name, qp); - } - - @GetMapping("/qp") - public int getQp(@RequestParam String name) - { - Integer kc = chatService.getQp(name); - if (kc == null) - { - throw new NotFoundException(); - } - return kc; - } - - @PostMapping("/gc") - public void submitGc(@RequestParam String name, @RequestParam int gc) - { - if (gc < 0) - { - return; - } - - chatService.setGc(name, gc); - } - - @GetMapping("/gc") - public int getKc(@RequestParam String name) - { - Integer gc = chatService.getGc(name); - if (gc == null) - { - throw new NotFoundException(); - } - return gc; - } - - @PostMapping("/task") - public void submitTask(@RequestParam String name, @RequestParam("task") String taskName, @RequestParam int amount, - @RequestParam int initialAmount, @RequestParam String location) - { - Matcher mTask = STRING_VALIDATION.matcher(taskName); - Matcher mLocation = STRING_VALIDATION.matcher(location); - if (mTask.find() || taskName.length() > STRING_MAX_LENGTH || - mLocation.find() || location.length() > STRING_MAX_LENGTH) - { - return; - } - - Task task = new Task(); - task.setTask(taskName); - task.setAmount(amount); - task.setInitialAmount(initialAmount); - task.setLocation(location); - - chatService.setTask(name, task); - } - - @GetMapping("/task") - public ResponseEntity getTask(@RequestParam String name) - { - Task task = chatService.getTask(name); - if (task == null) - { - return ResponseEntity.status(HttpStatus.NOT_FOUND) - .build(); - } - - return ResponseEntity.ok() - .cacheControl(CacheControl.maxAge(2, TimeUnit.MINUTES).cachePublic()) - .body(task); - } - - @PostMapping("/pb") - public void submitPb(@RequestParam String name, @RequestParam String boss, @RequestParam double pb) - { - if (pb < 0) - { - return; - } - - chatService.setPb(name, boss, pb); - } - - @GetMapping("/pb") - public double getPb(@RequestParam String name, @RequestParam String boss) - { - Double pb = chatService.getPb(name, boss); - if (pb == null) - { - throw new NotFoundException(); - } - return pb; - } - - @PostMapping("/duels") - public void submitDuels(@RequestParam String name, @RequestParam int wins, - @RequestParam int losses, - @RequestParam int winningStreak, @RequestParam int losingStreak) - { - if (wins < 0 || losses < 0 || winningStreak < 0 || losingStreak < 0) - { - return; - } - - Duels duels = new Duels(); - duels.setWins(wins); - duels.setLosses(losses); - duels.setWinningStreak(winningStreak); - duels.setLosingStreak(losingStreak); - - chatService.setDuels(name, duels); - } - - @GetMapping("/duels") - public Duels getDuels(@RequestParam String name) - { - Duels duels = chatService.getDuels(name); - if (duels == null) - { - throw new NotFoundException(); - } - return duels; - } - - @PostMapping("/layout") - public void submitLayout(@RequestParam String name, @RequestBody LayoutRoom[] rooms) - { - if (rooms.length > MAX_LAYOUT_ROOMS) - { - return; - } - - chatService.setLayout(name, rooms); - } - - @GetMapping("/layout") - public LayoutRoom[] getLayout(@RequestParam String name) - { - LayoutRoom[] layout = chatService.getLayout(name); - - if (layout == null) - { - throw new NotFoundException(); - } - - return layout; - } - - @PostMapping("/pets") - public void submitPetList(@RequestParam String name, @RequestBody int[] petList) - { - if (petList.length == 0 || petList.length > MAX_PETS) - { - return; - } - - chatService.setPetList(name, petList); - } - - @GetMapping("/pets") - public int[] getPetList(@RequestParam String name) - { - int[] petList = chatService.getPetList(name); - if (petList == null) - { - throw new NotFoundException(); - } - - return petList; - } -} diff --git a/http-service/src/main/java/net/runelite/http/service/chat/ChatService.java b/http-service/src/main/java/net/runelite/http/service/chat/ChatService.java deleted file mode 100644 index 7748728aab..0000000000 --- a/http-service/src/main/java/net/runelite/http/service/chat/ChatService.java +++ /dev/null @@ -1,263 +0,0 @@ -/* - * 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.service.chat; - -import com.google.common.base.Joiner; -import com.google.common.base.Splitter; -import com.google.common.collect.ImmutableMap; -import java.time.Duration; -import java.util.Arrays; -import java.util.List; -import java.util.Map; -import java.util.Set; -import net.runelite.http.api.chat.Duels; -import net.runelite.http.api.chat.LayoutRoom; -import net.runelite.http.api.chat.Task; -import net.runelite.http.service.util.redis.RedisPool; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; -import redis.clients.jedis.Jedis; - -@Service -public class ChatService -{ - private static final Duration EXPIRE = Duration.ofMinutes(2); - - private final RedisPool jedisPool; - - @Autowired - public ChatService(RedisPool jedisPool) - { - this.jedisPool = jedisPool; - } - - public Integer getKc(String name, String boss) - { - String value; - try (Jedis jedis = jedisPool.getResource()) - { - value = jedis.get("kc." + name + "." + boss); - } - return value == null ? null : Integer.parseInt(value); - } - - public void setKc(String name, String boss, int kc) - { - try (Jedis jedis = jedisPool.getResource()) - { - jedis.setex("kc." + name + "." + boss, (int) EXPIRE.getSeconds(), Integer.toString(kc)); - } - } - - public Integer getQp(String name) - { - String value; - try (Jedis jedis = jedisPool.getResource()) - { - value = jedis.get("qp." + name); - } - return value == null ? null : Integer.parseInt(value); - } - - public void setQp(String name, int qp) - { - try (Jedis jedis = jedisPool.getResource()) - { - jedis.setex("qp." + name, (int) EXPIRE.getSeconds(), Integer.toString(qp)); - } - } - - public Task getTask(String name) - { - Map map; - - try (Jedis jedis = jedisPool.getResource()) - { - map = jedis.hgetAll("task." + name); - } - - if (map.isEmpty()) - { - return null; - } - - Task task = new Task(); - task.setTask(map.get("task")); - task.setAmount(Integer.parseInt(map.get("amount"))); - task.setInitialAmount(Integer.parseInt(map.get("initialAmount"))); - task.setLocation(map.get("location")); - return task; - } - - public void setTask(String name, Task task) - { - Map taskMap = ImmutableMap.builderWithExpectedSize(4) - .put("task", task.getTask()) - .put("amount", Integer.toString(task.getAmount())) - .put("initialAmount", Integer.toString(task.getInitialAmount())) - .put("location", task.getLocation()) - .build(); - - String key = "task." + name; - - try (Jedis jedis = jedisPool.getResource()) - { - jedis.hmset(key, taskMap); - jedis.expire(key, (int) EXPIRE.getSeconds()); - } - } - - public Double getPb(String name, String boss) - { - String value; - try (Jedis jedis = jedisPool.getResource()) - { - value = jedis.get("pb." + boss + "." + name); - } - return value == null ? null : Double.parseDouble(value); - } - - public void setPb(String name, String boss, double pb) - { - try (Jedis jedis = jedisPool.getResource()) - { - jedis.setex("pb." + boss + "." + name, (int) EXPIRE.getSeconds(), Double.toString(pb)); - } - } - - public Integer getGc(String name) - { - String value; - try (Jedis jedis = jedisPool.getResource()) - { - value = jedis.get("gc." + name); - } - return value == null ? null : Integer.parseInt(value); - } - - public void setGc(String name, int gc) - { - try (Jedis jedis = jedisPool.getResource()) - { - jedis.setex("gc." + name, (int) EXPIRE.getSeconds(), Integer.toString(gc)); - } - } - - public Duels getDuels(String name) - { - Map map; - - try (Jedis jedis = jedisPool.getResource()) - { - map = jedis.hgetAll("duels." + name); - } - - if (map.isEmpty()) - { - return null; - } - - Duels duels = new Duels(); - duels.setWins(Integer.parseInt(map.get("wins"))); - duels.setLosses(Integer.parseInt(map.get("losses"))); - duels.setWinningStreak(Integer.parseInt(map.get("winningStreak"))); - duels.setLosingStreak(Integer.parseInt(map.get("losingStreak"))); - return duels; - } - - public void setDuels(String name, Duels duels) - { - Map duelsMap = ImmutableMap.builderWithExpectedSize(4) - .put("wins", Integer.toString(duels.getWins())) - .put("losses", Integer.toString(duels.getLosses())) - .put("winningStreak", Integer.toString(duels.getWinningStreak())) - .put("losingStreak", Integer.toString(duels.getLosingStreak())) - .build(); - - String key = "duels." + name; - - try (Jedis jedis = jedisPool.getResource()) - { - jedis.hmset(key, duelsMap); - jedis.expire(key, (int) EXPIRE.getSeconds()); - } - } - - public LayoutRoom[] getLayout(String name) - { - String layout; - try (Jedis jedis = jedisPool.getResource()) - { - layout = jedis.get("layout." + name); - } - - if (layout == null) - { - return null; - } - - List roomList = Splitter.on(' ').splitToList(layout); - return roomList.stream() - .map(LayoutRoom::valueOf) - .toArray(LayoutRoom[]::new); - } - - public void setLayout(String name, LayoutRoom[] rooms) - { - try (Jedis jedis = jedisPool.getResource()) - { - jedis.setex("layout." + name, (int) EXPIRE.getSeconds(), Joiner.on(' ').join(rooms)); - } - } - - public int[] getPetList(String name) - { - Set pets; - try (Jedis jedis = jedisPool.getResource()) - { - pets = jedis.smembers("pets." + name); - } - - if (pets.isEmpty()) - { - return null; - } - - return pets.stream() - .mapToInt(Integer::parseInt) - .toArray(); - } - - public void setPetList(String name, int[] petList) - { - String[] pets = Arrays.stream(petList).mapToObj(Integer::toString).toArray(String[]::new); - String key = "pets." + name; - try (Jedis jedis = jedisPool.getResource()) - { - jedis.sadd(key, pets); - jedis.expire(key, (int) EXPIRE.getSeconds()); - } - } -} diff --git a/http-service/src/main/java/net/runelite/http/service/chat/KillCountKey.java b/http-service/src/main/java/net/runelite/http/service/chat/KillCountKey.java deleted file mode 100644 index 07ca775dad..0000000000 --- a/http-service/src/main/java/net/runelite/http/service/chat/KillCountKey.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * 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.service.chat; - -import lombok.Value; - -@Value -class KillCountKey -{ - private String username; - private String boss; -} diff --git a/http-service/src/main/java/net/runelite/http/service/config/ConfigController.java b/http-service/src/main/java/net/runelite/http/service/config/ConfigController.java deleted file mode 100644 index c247ecc0bc..0000000000 --- a/http-service/src/main/java/net/runelite/http/service/config/ConfigController.java +++ /dev/null @@ -1,134 +0,0 @@ -/* - * Copyright (c) 2019, Adam - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package net.runelite.http.service.config; - -import java.io.IOException; -import java.util.List; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import net.runelite.http.api.config.Configuration; -import net.runelite.http.service.account.AuthFilter; -import net.runelite.http.service.account.beans.SessionEntry; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PatchMapping; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import static org.springframework.web.bind.annotation.RequestMethod.DELETE; -import static org.springframework.web.bind.annotation.RequestMethod.PUT; -import org.springframework.web.bind.annotation.RestController; - -@RestController -@RequestMapping("/config") -public class ConfigController -{ - private final ConfigService configService; - private final AuthFilter authFilter; - - @Autowired - public ConfigController(ConfigService configService, AuthFilter authFilter) - { - this.configService = configService; - this.authFilter = authFilter; - } - - @GetMapping - public Configuration get(HttpServletRequest request, HttpServletResponse response) throws IOException - { - SessionEntry session = authFilter.handle(request, response); - - if (session == null) - { - return null; - } - - return configService.get(session.getUser()); - } - - @PatchMapping - public List patch( - HttpServletRequest request, - HttpServletResponse response, - @RequestBody Configuration changes - ) throws IOException - { - SessionEntry session = authFilter.handle(request, response); - if (session == null) - { - return null; - } - - List failures = configService.patch(session.getUser(), changes); - if (failures.size() != 0) - { - response.setStatus(HttpServletResponse.SC_BAD_REQUEST); - return failures; - } - - return null; - } - - @RequestMapping(path = "/{key:.+}", method = PUT) - public void setKey( - HttpServletRequest request, - HttpServletResponse response, - @PathVariable String key, - @RequestBody(required = false) String value - ) throws IOException - { - SessionEntry session = authFilter.handle(request, response); - - if (session == null) - { - return; - } - - if (!configService.setKey(session.getUser(), key, value)) - { - response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); - } - } - - @RequestMapping(path = "/{key:.+}", method = DELETE) - public void unsetKey( - HttpServletRequest request, - HttpServletResponse response, - @PathVariable String key - ) throws IOException - { - SessionEntry session = authFilter.handle(request, response); - - if (session == null) - { - return; - } - - if (!configService.unsetKey(session.getUser(), key)) - { - response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); - } - } -} diff --git a/http-service/src/main/java/net/runelite/http/service/config/ConfigService.java b/http-service/src/main/java/net/runelite/http/service/config/ConfigService.java deleted file mode 100644 index bb6050ad4b..0000000000 --- a/http-service/src/main/java/net/runelite/http/service/config/ConfigService.java +++ /dev/null @@ -1,367 +0,0 @@ -/* - * Copyright (c) 2017-2019, Adam - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package net.runelite.http.service.config; - -import com.google.common.annotations.VisibleForTesting; -import com.google.common.base.Strings; -import com.google.gson.Gson; -import com.google.gson.JsonArray; -import com.google.gson.JsonElement; -import com.google.gson.JsonObject; -import com.google.gson.JsonPrimitive; -import com.google.gson.JsonSyntaxException; -import com.mongodb.client.MongoClient; -import com.mongodb.client.MongoCollection; -import com.mongodb.client.MongoDatabase; -import static com.mongodb.client.model.Filters.eq; -import com.mongodb.client.model.IndexOptions; -import com.mongodb.client.model.Indexes; -import com.mongodb.client.model.UpdateOptions; -import static com.mongodb.client.model.Updates.combine; -import static com.mongodb.client.model.Updates.set; -import static com.mongodb.client.model.Updates.unset; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.regex.Pattern; -import javax.annotation.Nullable; -import net.runelite.http.api.RuneLiteAPI; -import net.runelite.http.api.config.ConfigEntry; -import net.runelite.http.api.config.Configuration; -import org.bson.Document; -import org.bson.conversions.Bson; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.stereotype.Service; - -@Service -public class ConfigService -{ - private static final Pattern MAYBE_JSON = Pattern.compile("^[\\-0-9{\\[\"]|true|false"); - private static final int MAX_DEPTH = 8; - private static final int MAX_VALUE_LENGTH = 262144; - - private final Gson GSON = RuneLiteAPI.GSON; - private final UpdateOptions upsertUpdateOptions = new UpdateOptions().upsert(true); - - private final MongoCollection mongoCollection; - - @Autowired - public ConfigService( - MongoClient mongoClient, - @Value("${mongo.database}") String databaseName - ) - { - - MongoDatabase database = mongoClient.getDatabase(databaseName); - MongoCollection collection = database.getCollection("config"); - this.mongoCollection = collection; - - // Create unique index on _userId - IndexOptions indexOptions = new IndexOptions().unique(true); - collection.createIndex(Indexes.ascending("_userId"), indexOptions); - } - - private Document getConfig(int userId) - { - return mongoCollection.find(eq("_userId", userId)).first(); - } - - public Configuration get(int userId) - { - Map configMap = getConfig(userId); - - if (configMap == null || configMap.isEmpty()) - { - return new Configuration(Collections.emptyList()); - } - - List config = new ArrayList<>(); - - for (String group : configMap.keySet()) - { - // Reserved keys - if (group.startsWith("_") || group.startsWith("$")) - { - continue; - } - - Map groupMap = (Map) configMap.get(group); - - for (Map.Entry entry : groupMap.entrySet()) - { - String key = entry.getKey(); - Object value = entry.getValue(); - - if (value instanceof Map || value instanceof Collection) - { - value = GSON.toJson(entry.getValue()); - } - else if (value == null) - { - continue; - } - - ConfigEntry configEntry = new ConfigEntry(); - configEntry.setKey(group + "." + key.replace(':', '.')); - configEntry.setValue(value.toString()); - config.add(configEntry); - } - } - - return new Configuration(config); - } - - public List patch(int userID, Configuration config) - { - List failures = new ArrayList<>(); - List sets = new ArrayList<>(config.getConfig().size()); - for (ConfigEntry entry : config.getConfig()) - { - Bson s = setForKV(entry.getKey(), entry.getValue()); - if (s == null) - { - failures.add(entry.getKey()); - } - else - { - sets.add(s); - } - } - - if (sets.size() > 0) - { - mongoCollection.updateOne( - eq("_userId", userID), - combine(sets), - upsertUpdateOptions - ); - } - - return failures; - } - - @Nullable - private Bson setForKV(String key, @Nullable String value) - { - if (key.startsWith("$") || key.startsWith("_")) - { - return null; - } - - String[] split = key.split("\\.", 2); - if (split.length != 2) - { - return null; - } - - String dbKey = split[0] + "." + split[1].replace('.', ':'); - - if (Strings.isNullOrEmpty(value)) - { - return unset(dbKey); - } - - Object jsonValue; - if (!isMaybeJson(value)) - { - if (!validateStr(value)) - { - return null; - } - - jsonValue = value; - } - else - { - if (!validateJson(value)) - { - return null; - } - - jsonValue = parseJsonString(value); - } - return set(dbKey, jsonValue); - } - - public boolean setKey( - int userId, - String key, - @Nullable String value - ) - { - Bson set = setForKV(key, value); - if (set == null) - { - return false; - } - - mongoCollection.updateOne(eq("_userId", userId), - set, - upsertUpdateOptions); - return true; - } - - public boolean unsetKey( - int userId, - String key - ) - { - Bson set = setForKV(key, null); - if (set == null) - { - return false; - } - - mongoCollection.updateOne(eq("_userId", userId), set); - return true; - } - - @VisibleForTesting - static Object parseJsonString(String value) - { - Object jsonValue; - try - { - jsonValue = RuneLiteAPI.GSON.fromJson(value, Object.class); - if (jsonValue == null) - { - return value; - } - else if (jsonValue instanceof Double || jsonValue instanceof Float) - { - Number number = (Number) jsonValue; - if (Math.floor(number.doubleValue()) == number.doubleValue() && !Double.isInfinite(number.doubleValue())) - { - // value is an int or long. 'number' might be truncated so parse it from 'value' - try - { - jsonValue = Integer.parseInt(value); - } - catch (NumberFormatException ex) - { - try - { - jsonValue = Long.parseLong(value); - } - catch (NumberFormatException ex2) - { - - } - } - } - } - } - catch (JsonSyntaxException ex) - { - jsonValue = value; - } - return jsonValue; - } - - @VisibleForTesting - static boolean isMaybeJson(String value) - { - return MAYBE_JSON.matcher(value).find(); - } - - private static boolean validateStr(String value) - { - return value.length() < MAX_VALUE_LENGTH; - } - - @VisibleForTesting - static boolean validateJson(String value) - { - try - { - // I couldn't figure out a better way to do this than a second json parse - JsonElement jsonElement = RuneLiteAPI.GSON.fromJson(value, JsonElement.class); - if (jsonElement == null) - { - return value.length() < MAX_VALUE_LENGTH; - } - return validateObject(jsonElement, 1); - } - catch (JsonSyntaxException ex) - { - // the client submits the string representation of objects which is not always valid json, - // eg. a value with a ':' in it. We just ignore it now. We can't json encode the values client - // side due to them already being strings, which prevents gson from being able to convert them - // to ints/floats/maps etc. - return value.length() < MAX_VALUE_LENGTH; - } - } - - private static boolean validateObject(JsonElement jsonElement, int depth) - { - if (depth >= MAX_DEPTH) - { - return false; - } - - if (jsonElement.isJsonObject()) - { - JsonObject jsonObject = jsonElement.getAsJsonObject(); - - for (Map.Entry entry : jsonObject.entrySet()) - { - JsonElement element = entry.getValue(); - - if (!validateObject(element, depth + 1)) - { - return false; - } - } - } - else if (jsonElement.isJsonArray()) - { - JsonArray jsonArray = jsonElement.getAsJsonArray(); - - for (int i = 0; i < jsonArray.size(); ++i) - { - JsonElement element = jsonArray.get(i); - - if (!validateObject(element, depth + 1)) - { - return false; - } - } - } - else if (jsonElement.isJsonPrimitive()) - { - JsonPrimitive jsonPrimitive = jsonElement.getAsJsonPrimitive(); - String value = jsonPrimitive.getAsString(); - if (value.length() >= MAX_VALUE_LENGTH) - { - return false; - } - } - - return true; - } -} diff --git a/http-service/src/main/java/net/runelite/http/service/feed/FeedController.java b/http-service/src/main/java/net/runelite/http/service/feed/FeedController.java deleted file mode 100644 index 9c799d9873..0000000000 --- a/http-service/src/main/java/net/runelite/http/service/feed/FeedController.java +++ /dev/null @@ -1,137 +0,0 @@ -/* - * Copyright (c) 2018, Lotto - * 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.feed; - -import com.google.common.hash.HashCode; -import com.google.common.hash.Hasher; -import com.google.common.hash.Hashing; -import java.nio.charset.StandardCharsets; -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import net.runelite.http.api.feed.FeedItem; -import net.runelite.http.api.feed.FeedResult; -import net.runelite.http.service.feed.blog.BlogService; -import net.runelite.http.service.feed.osrsnews.OSRSNewsService; -import net.runelite.http.service.feed.twitter.TwitterService; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.http.CacheControl; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; -import org.springframework.scheduling.annotation.Scheduled; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; - -@RestController -@RequestMapping("/feed") -@Slf4j -public class FeedController -{ - private final BlogService blogService; - private final TwitterService twitterService; - private final OSRSNewsService osrsNewsService; - - private static class MemoizedFeed - { - final FeedResult feedResult; - final String hash; - - MemoizedFeed(FeedResult feedResult) - { - this.feedResult = feedResult; - - Hasher hasher = Hashing.sha256().newHasher(); - for (FeedItem itemPrice : feedResult.getItems()) - { - hasher.putBytes(itemPrice.getTitle().getBytes(StandardCharsets.UTF_8)).putBytes(itemPrice.getContent().getBytes(StandardCharsets.UTF_8)); - } - HashCode code = hasher.hash(); - hash = code.toString(); - } - } - - private MemoizedFeed memoizedFeed; - - @Autowired - public FeedController(BlogService blogService, TwitterService twitterService, OSRSNewsService osrsNewsService) - { - this.blogService = blogService; - this.twitterService = twitterService; - this.osrsNewsService = osrsNewsService; - } - - @Scheduled(fixedDelay = 10 * 60 * 1000) - public void updateFeed() - { - List items = new ArrayList<>(); - - try - { - items.addAll(blogService.getBlogPosts()); - } - catch (Exception e) - { - log.warn("unable to fetch blogs", e); - } - - try - { - items.addAll(twitterService.getTweets()); - } - catch (Exception e) - { - log.warn("unable to fetch tweets", e); - } - - try - { - items.addAll(osrsNewsService.getNews()); - } - catch (Exception e) - { - log.warn("unable to fetch news", e); - } - - memoizedFeed = new MemoizedFeed(new FeedResult(items)); - } - - @GetMapping - public ResponseEntity getFeed() - { - if (memoizedFeed == null) - { - return ResponseEntity.status(HttpStatus.SERVICE_UNAVAILABLE) - .cacheControl(CacheControl.noCache()) - .build(); - } - - return ResponseEntity.ok() - .eTag(memoizedFeed.hash) - .cacheControl(CacheControl.maxAge(10, TimeUnit.MINUTES).cachePublic()) - .body(memoizedFeed.feedResult); - } -} diff --git a/http-service/src/main/java/net/runelite/http/service/feed/blog/BlogService.java b/http-service/src/main/java/net/runelite/http/service/feed/blog/BlogService.java deleted file mode 100644 index 72f7938910..0000000000 --- a/http-service/src/main/java/net/runelite/http/service/feed/blog/BlogService.java +++ /dev/null @@ -1,143 +0,0 @@ -/* - * Copyright (c) 2018, Lotto - * 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.feed.blog; - -import java.io.IOException; -import java.io.InputStream; -import java.text.ParseException; -import java.text.SimpleDateFormat; -import java.util.ArrayList; -import java.util.List; -import java.util.Locale; -import javax.xml.parsers.DocumentBuilderFactory; -import javax.xml.parsers.ParserConfigurationException; -import net.runelite.http.api.feed.FeedItem; -import net.runelite.http.api.feed.FeedItemType; -import net.runelite.http.service.util.exception.InternalServerErrorException; -import okhttp3.HttpUrl; -import okhttp3.OkHttpClient; -import okhttp3.Request; -import okhttp3.Response; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.stereotype.Service; -import org.w3c.dom.Document; -import org.w3c.dom.Element; -import org.w3c.dom.Node; -import org.w3c.dom.NodeList; -import org.xml.sax.SAXException; - -@Service -public class BlogService -{ - private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.US); - - private final OkHttpClient okHttpClient; - private final HttpUrl rssUrl; - - @Autowired - public BlogService( - OkHttpClient okHttpClient, - @Value("${runelite.feed.rssUrl}") String rssUrl - ) - { - this.okHttpClient = okHttpClient; - this.rssUrl = HttpUrl.get(rssUrl); - } - - public List getBlogPosts() throws IOException - { - Request request = new Request.Builder() - .url(rssUrl) - .build(); - - try (Response response = okHttpClient.newCall(request).execute()) - { - if (!response.isSuccessful()) - { - throw new IOException("Error getting blog posts: " + response); - } - - try - { - InputStream in = response.body().byteStream(); - Document document = DocumentBuilderFactory.newInstance() - .newDocumentBuilder() - .parse(in); - - Element documentElement = document.getDocumentElement(); - NodeList documentItems = documentElement.getElementsByTagName("entry"); - - List items = new ArrayList<>(); - - for (int i = 0; i < Math.min(documentItems.getLength(), 3); i++) - { - Node item = documentItems.item(i); - NodeList children = item.getChildNodes(); - - String title = null; - String summary = null; - String link = null; - long timestamp = -1; - - for (int j = 0; j < children.getLength(); j++) - { - Node childItem = children.item(j); - String nodeName = childItem.getNodeName(); - - switch (nodeName) - { - case "title": - title = childItem.getTextContent(); - break; - case "summary": - summary = childItem.getTextContent().replace("\n", "").trim(); - break; - case "link": - link = childItem.getAttributes().getNamedItem("href").getTextContent(); - break; - case "updated": - timestamp = DATE_FORMAT.parse(childItem.getTextContent()).getTime(); - break; - } - } - - if (title == null || summary == null || link == null || timestamp == -1) - { - throw new InternalServerErrorException("Failed to find title, summary, link and/or timestamp in the blog post feed"); - } - - items.add(new FeedItem(FeedItemType.BLOG_POST, title, summary, link, timestamp)); - } - - return items; - } - catch (ParserConfigurationException | SAXException | ParseException e) - { - throw new InternalServerErrorException("Failed to parse blog posts: " + e.getMessage()); - } - } - } -} diff --git a/http-service/src/main/java/net/runelite/http/service/feed/osrsnews/OSRSNewsService.java b/http-service/src/main/java/net/runelite/http/service/feed/osrsnews/OSRSNewsService.java deleted file mode 100644 index e53b2d8044..0000000000 --- a/http-service/src/main/java/net/runelite/http/service/feed/osrsnews/OSRSNewsService.java +++ /dev/null @@ -1,143 +0,0 @@ -/* - * Copyright (c) 2018, Lotto - * 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.feed.osrsnews; - -import java.io.IOException; -import java.io.InputStream; -import java.text.ParseException; -import java.text.SimpleDateFormat; -import java.util.ArrayList; -import java.util.List; -import java.util.Locale; -import javax.xml.parsers.DocumentBuilderFactory; -import javax.xml.parsers.ParserConfigurationException; -import net.runelite.http.api.feed.FeedItem; -import net.runelite.http.api.feed.FeedItemType; -import net.runelite.http.service.util.exception.InternalServerErrorException; -import okhttp3.HttpUrl; -import okhttp3.OkHttpClient; -import okhttp3.Request; -import okhttp3.Response; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.stereotype.Service; -import org.w3c.dom.Document; -import org.w3c.dom.Element; -import org.w3c.dom.Node; -import org.w3c.dom.NodeList; -import org.xml.sax.SAXException; - -@Service -public class OSRSNewsService -{ - private static final SimpleDateFormat PUB_DATE_FORMAT = new SimpleDateFormat("EEE, dd MMM yyyy '00:00:00 GMT'", Locale.US); - - private final OkHttpClient okHttpClient; - private final HttpUrl rssUrl; - - @Autowired - public OSRSNewsService( - OkHttpClient okHttpClient, - @Value("${runelite.osrsnews.rssUrl}") String rssUrl - ) - { - this.okHttpClient = okHttpClient; - this.rssUrl = HttpUrl.get(rssUrl); - } - - public List getNews() throws IOException - { - Request request = new Request.Builder() - .url(rssUrl) - .build(); - - try (Response response = okHttpClient.newCall(request).execute()) - { - if (!response.isSuccessful()) - { - throw new IOException("Error getting OSRS news: " + response); - } - - try - { - InputStream in = response.body().byteStream(); - Document document = DocumentBuilderFactory.newInstance() - .newDocumentBuilder() - .parse(in); - - Element documentElement = document.getDocumentElement(); - NodeList documentItems = documentElement.getElementsByTagName("item"); - - List items = new ArrayList<>(); - - for (int i = 0; i < documentItems.getLength(); i++) - { - Node item = documentItems.item(i); - NodeList children = item.getChildNodes(); - - String title = null; - String description = null; - String link = null; - long timestamp = -1; - - for (int j = 0; j < children.getLength(); j++) - { - Node childItem = children.item(j); - String nodeName = childItem.getNodeName(); - - switch (nodeName) - { - case "title": - title = childItem.getTextContent(); - break; - case "description": - description = childItem.getTextContent().replace("\n", "").trim(); - break; - case "link": - link = childItem.getTextContent(); - break; - case "pubDate": - timestamp = PUB_DATE_FORMAT.parse(childItem.getTextContent()).getTime(); - break; - } - } - - if (title == null || description == null || link == null || timestamp == -1) - { - throw new InternalServerErrorException("Failed to find title, description, link and/or timestamp in the OSRS RSS feed"); - } - - items.add(new FeedItem(FeedItemType.OSRS_NEWS, title, description, link, timestamp)); - } - - return items; - } - catch (ParserConfigurationException | SAXException | ParseException e) - { - throw new InternalServerErrorException("Failed to parse OSRS news: " + e.getMessage()); - } - } - } -} diff --git a/http-service/src/main/java/net/runelite/http/service/feed/twitter/TwitterOAuth2TokenResponse.java b/http-service/src/main/java/net/runelite/http/service/feed/twitter/TwitterOAuth2TokenResponse.java deleted file mode 100644 index 24df0b6cf6..0000000000 --- a/http-service/src/main/java/net/runelite/http/service/feed/twitter/TwitterOAuth2TokenResponse.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (c) 2018, Lotto - * 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.feed.twitter; - -import com.google.gson.annotations.SerializedName; -import lombok.Data; - -@Data -class TwitterOAuth2TokenResponse -{ - @SerializedName("token_type") - private String tokenType; - - @SerializedName("access_token") - private String token; -} diff --git a/http-service/src/main/java/net/runelite/http/service/feed/twitter/TwitterService.java b/http-service/src/main/java/net/runelite/http/service/feed/twitter/TwitterService.java deleted file mode 100644 index 4b7b026646..0000000000 --- a/http-service/src/main/java/net/runelite/http/service/feed/twitter/TwitterService.java +++ /dev/null @@ -1,183 +0,0 @@ -/* - * Copyright (c) 2018, Lotto - * 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.feed.twitter; - -import com.google.gson.reflect.TypeToken; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.lang.reflect.Type; -import java.nio.charset.StandardCharsets; -import java.util.ArrayList; -import java.util.Base64; -import java.util.List; -import net.runelite.http.api.RuneLiteAPI; -import net.runelite.http.api.feed.FeedItem; -import net.runelite.http.api.feed.FeedItemType; -import net.runelite.http.service.util.exception.InternalServerErrorException; -import okhttp3.FormBody; -import okhttp3.HttpUrl; -import okhttp3.OkHttpClient; -import okhttp3.Request; -import okhttp3.Response; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.http.HttpStatus; -import org.springframework.stereotype.Service; - -@Service -public class TwitterService -{ - private static final HttpUrl AUTH_URL = HttpUrl.parse("https://api.twitter.com/oauth2/token"); - private static final HttpUrl LIST_STATUSES_URL = HttpUrl.parse("https://api.twitter.com/1.1/lists/statuses.json"); - - private final String credentials; - private final String listId; - private final OkHttpClient okHttpClient; - - private String token; - - @Autowired - public TwitterService( - @Value("${runelite.twitter.consumerkey}") String consumerKey, - @Value("${runelite.twitter.secretkey}") String consumerSecret, - @Value("${runelite.twitter.listid}") String listId, - OkHttpClient okHttpClient - ) - { - this.credentials = consumerKey + ":" + consumerSecret; - this.listId = listId; - this.okHttpClient = okHttpClient; - } - - public List getTweets() throws IOException - { - return getTweets(false); - } - - private List getTweets(boolean hasRetried) throws IOException - { - if (token == null) - { - updateToken(); - } - - HttpUrl url = LIST_STATUSES_URL.newBuilder() - .addQueryParameter("list_id", listId) - .addQueryParameter("count", "15") - .addQueryParameter("include_entities", "false") - .build(); - - Request request = new Request.Builder() - .url(url) - .header("Authorization", "Bearer " + token) - .build(); - - try (Response response = okHttpClient.newCall(request).execute()) - { - if (!response.isSuccessful()) - { - switch (HttpStatus.valueOf(response.code())) - { - case BAD_REQUEST: - case UNAUTHORIZED: - updateToken(); - if (!hasRetried) - { - return getTweets(true); - } - throw new InternalServerErrorException("Could not auth to Twitter after trying once: " + response); - default: - throw new IOException("Error getting Twitter list: " + response); - } - } - - InputStream in = response.body().byteStream(); - Type listType = new TypeToken>() - { - }.getType(); - List statusesResponse = RuneLiteAPI.GSON - .fromJson(new InputStreamReader(in, StandardCharsets.UTF_8), listType); - - List items = new ArrayList<>(); - - for (TwitterStatusesResponseItem i : statusesResponse) - { - items.add(new FeedItem(FeedItemType.TWEET, - i.getUser().getProfileImageUrl(), - i.getUser().getScreenName(), - i.getText().replace("\n\n", " ").replaceAll("\n", " "), - "https://twitter.com/" + i.getUser().getScreenName() + "/status/" + i.getId(), - getTimestampFromSnowflake(i.getId()))); - } - - return items; - } - } - - private void updateToken() throws IOException - { - String encodedCredentials = Base64.getEncoder().encodeToString(credentials.getBytes(StandardCharsets.UTF_8)); - - Request request = new Request.Builder() - .url(AUTH_URL) - .header("Authorization", "Basic " + encodedCredentials) - .post(new FormBody.Builder().add("grant_type", "client_credentials").build()) - .build(); - - try (Response response = okHttpClient.newCall(request).execute()) - { - if (!response.isSuccessful()) - { - throw new IOException("Error authing to Twitter: " + response); - } - - InputStream in = response.body().byteStream(); - TwitterOAuth2TokenResponse tokenResponse = RuneLiteAPI.GSON - .fromJson(new InputStreamReader(in, StandardCharsets.UTF_8), TwitterOAuth2TokenResponse.class); - - if (!tokenResponse.getTokenType().equals("bearer")) - { - throw new InternalServerErrorException("Returned token was not a bearer token"); - } - - if (tokenResponse.getToken() == null) - { - throw new InternalServerErrorException("Returned token was null"); - } - - token = tokenResponse.getToken(); - } - } - - /** - * Extracts the UTC timestamp from a Twitter snowflake as per - * https://github.com/client9/snowflake2time/blob/master/python/snowflake.py#L24 - */ - private long getTimestampFromSnowflake(long snowflake) - { - return (snowflake >> 22) + 1288834974657L; - } -} diff --git a/http-service/src/main/java/net/runelite/http/service/feed/twitter/TwitterStatusesResponseItem.java b/http-service/src/main/java/net/runelite/http/service/feed/twitter/TwitterStatusesResponseItem.java deleted file mode 100644 index 90b37c5021..0000000000 --- a/http-service/src/main/java/net/runelite/http/service/feed/twitter/TwitterStatusesResponseItem.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (c) 2018, Lotto - * 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.feed.twitter; - -import lombok.Data; - -@Data -class TwitterStatusesResponseItem -{ - private long id; - private String text; - private TwitterStatusesResponseItemUser user; -} diff --git a/http-service/src/main/java/net/runelite/http/service/feed/twitter/TwitterStatusesResponseItemUser.java b/http-service/src/main/java/net/runelite/http/service/feed/twitter/TwitterStatusesResponseItemUser.java deleted file mode 100644 index 94fe9360f9..0000000000 --- a/http-service/src/main/java/net/runelite/http/service/feed/twitter/TwitterStatusesResponseItemUser.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (c) 2018, Lotto - * 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.feed.twitter; - -import com.google.gson.annotations.SerializedName; -import lombok.Data; - -@Data -class TwitterStatusesResponseItemUser -{ - @SerializedName("screen_name") - private String screenName; - - @SerializedName("profile_image_url_https") - private String profileImageUrl; -} diff --git a/http-service/src/main/java/net/runelite/http/service/ge/GrandExchangeController.java b/http-service/src/main/java/net/runelite/http/service/ge/GrandExchangeController.java deleted file mode 100644 index 509f2bdb70..0000000000 --- a/http-service/src/main/java/net/runelite/http/service/ge/GrandExchangeController.java +++ /dev/null @@ -1,158 +0,0 @@ -/* - * Copyright (c) 2019, Adam - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package net.runelite.http.service.ge; - -import com.google.gson.Gson; -import java.io.IOException; -import java.time.Instant; -import java.util.Collection; -import java.util.stream.Collectors; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import net.runelite.http.api.RuneLiteAPI; -import net.runelite.http.api.ge.GrandExchangeTrade; -import net.runelite.http.service.account.AuthFilter; -import net.runelite.http.service.account.beans.SessionEntry; -import net.runelite.http.service.util.redis.RedisPool; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.web.bind.annotation.DeleteMapping; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.bind.annotation.RestController; -import redis.clients.jedis.Jedis; - -@RestController -@RequestMapping("/ge") -public class GrandExchangeController -{ - private static final Gson GSON = RuneLiteAPI.GSON; - - private final GrandExchangeService grandExchangeService; - private final AuthFilter authFilter; - private final RedisPool redisPool; - - @Autowired - public GrandExchangeController(GrandExchangeService grandExchangeService, AuthFilter authFilter, RedisPool redisPool) - { - this.grandExchangeService = grandExchangeService; - this.authFilter = authFilter; - this.redisPool = redisPool; - } - - @PostMapping - public void submit(HttpServletRequest request, HttpServletResponse response, @RequestBody GrandExchangeTrade grandExchangeTrade) throws IOException - { - SessionEntry session = null; - if (request.getHeader(RuneLiteAPI.RUNELITE_AUTH) != null) - { - session = authFilter.handle(request, response); - if (session == null) - { - // error is set here on the response, so we shouldn't continue - return; - } - } - Integer userId = session == null ? null : session.getUser(); - - // We don't keep track of pending trades in the web UI, so only add cancelled or completed trades - if (userId != null && - grandExchangeTrade.getQty() > 0 && - (grandExchangeTrade.isCancel() || grandExchangeTrade.getQty() == grandExchangeTrade.getTotal())) - { - grandExchangeService.add(userId, grandExchangeTrade); - } - - Trade trade = new Trade(); - trade.setBuy(grandExchangeTrade.isBuy()); - trade.setCancel(grandExchangeTrade.isCancel()); - trade.setLogin(grandExchangeTrade.isLogin()); - trade.setItemId(grandExchangeTrade.getItemId()); - trade.setQty(grandExchangeTrade.getQty()); - trade.setDqty(grandExchangeTrade.getDqty()); - trade.setTotal(grandExchangeTrade.getTotal()); - trade.setSpent(grandExchangeTrade.getDspent()); - trade.setOffer(grandExchangeTrade.getOffer()); - trade.setSlot(grandExchangeTrade.getSlot()); - trade.setTime((int) (System.currentTimeMillis() / 1000L)); - trade.setMachineId(request.getHeader(RuneLiteAPI.RUNELITE_MACHINEID)); - trade.setUserId(userId); - trade.setIp(request.getHeader("X-Forwarded-For")); - trade.setUa(request.getHeader("User-Agent")); - trade.setWorldType(grandExchangeTrade.getWorldType()); - trade.setSeq(grandExchangeTrade.getSeq()); - Instant resetTime = grandExchangeTrade.getResetTime(); - trade.setResetTime(resetTime == null ? 0L : resetTime.getEpochSecond()); - - String json = GSON.toJson(trade); - try (Jedis jedis = redisPool.getResource()) - { - jedis.publish("ge", json); - } - } - - @GetMapping - public Collection get(HttpServletRequest request, HttpServletResponse response, - @RequestParam(required = false, defaultValue = "1024") int limit, - @RequestParam(required = false, defaultValue = "0") int offset) throws IOException - { - SessionEntry session = authFilter.handle(request, response); - - if (session == null) - { - return null; - } - - return grandExchangeService.get(session.getUser(), limit, offset).stream() - .map(GrandExchangeController::convert) - .collect(Collectors.toList()); - } - - private static GrandExchangeTradeHistory convert(TradeEntry tradeEntry) - { - GrandExchangeTradeHistory grandExchangeTrade = new GrandExchangeTradeHistory(); - grandExchangeTrade.setBuy(tradeEntry.getAction() == TradeAction.BUY); - grandExchangeTrade.setItemId(tradeEntry.getItem()); - grandExchangeTrade.setQuantity(tradeEntry.getQuantity()); - grandExchangeTrade.setPrice(tradeEntry.getPrice()); - grandExchangeTrade.setTime(tradeEntry.getTime()); - return grandExchangeTrade; - } - - @DeleteMapping - public void delete(HttpServletRequest request, HttpServletResponse response) throws IOException - { - SessionEntry session = authFilter.handle(request, response); - - if (session == null) - { - return; - } - - grandExchangeService.delete(session.getUser()); - } -} diff --git a/http-service/src/main/java/net/runelite/http/service/ge/GrandExchangeService.java b/http-service/src/main/java/net/runelite/http/service/ge/GrandExchangeService.java deleted file mode 100644 index 227d5e1159..0000000000 --- a/http-service/src/main/java/net/runelite/http/service/ge/GrandExchangeService.java +++ /dev/null @@ -1,119 +0,0 @@ -/* - * Copyright (c) 2019, Adam - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package net.runelite.http.service.ge; - -import java.util.Collection; -import net.runelite.http.api.ge.GrandExchangeTrade; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Qualifier; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.scheduling.annotation.Scheduled; -import org.springframework.stereotype.Service; -import org.sql2o.Connection; -import org.sql2o.Sql2o; - -@Service -public class GrandExchangeService -{ - private static final String CREATE_TABLE = "CREATE TABLE IF NOT EXISTS `ge_trades` (\n" + - " `id` int(11) NOT NULL AUTO_INCREMENT,\n" + - " `user` int(11) NOT NULL,\n" + - " `action` enum('BUY','SELL') NOT NULL,\n" + - " `item` int(11) NOT NULL,\n" + - " `quantity` int(11) NOT NULL,\n" + - " `price` int(11) NOT NULL,\n" + - " `time` timestamp NOT NULL DEFAULT current_timestamp(),\n" + - " PRIMARY KEY (`id`),\n" + - " KEY `user_time` (`user`, `time`),\n" + - " KEY `time` (`time`),\n" + - " CONSTRAINT `ge_trades_ibfk_1` FOREIGN KEY (`user`) REFERENCES `users` (`id`)\n" + - ") ENGINE=InnoDB;"; - - private final Sql2o sql2o; - private final int historyDays; - - @Autowired - public GrandExchangeService( - @Qualifier("Runelite SQL2O") Sql2o sql2o, - @Value("${runelite.ge.history}") int historyDays - ) - { - this.sql2o = sql2o; - this.historyDays = historyDays; - - // Ensure necessary tables exist - try (Connection con = sql2o.open()) - { - con.createQuery(CREATE_TABLE).executeUpdate(); - } - } - - public void add(int userId, GrandExchangeTrade grandExchangeTrade) - { - try (Connection con = sql2o.open()) - { - con.createQuery("insert into ge_trades (user, action, item, quantity, price) values (:user," + - " :action, :item, :quantity, :price)") - .addParameter("user", userId) - .addParameter("action", grandExchangeTrade.isBuy() ? "BUY" : "SELL") - .addParameter("item", grandExchangeTrade.getItemId()) - .addParameter("quantity", grandExchangeTrade.getQty()) - .addParameter("price", grandExchangeTrade.getSpent() / grandExchangeTrade.getQty()) - .executeUpdate(); - } - } - - public Collection get(int userId, int limit, int offset) - { - try (Connection con = sql2o.open()) - { - return con.createQuery("select id, user, action, item, quantity, price, time from ge_trades where user = :user limit :limit offset :offset") - .addParameter("user", userId) - .addParameter("limit", limit) - .addParameter("offset", offset) - .executeAndFetch(TradeEntry.class); - } - } - - public void delete(int userId) - { - try (Connection con = sql2o.open()) - { - con.createQuery("delete from ge_trades where user = :user") - .addParameter("user", userId) - .executeUpdate(); - } - } - - @Scheduled(fixedDelay = 60 * 60 * 1000) - public void expire() - { - try (Connection con = sql2o.open()) - { - con.createQuery("delete from ge_trades where time < current_timestamp - interval " + historyDays + " day") - .executeUpdate(); - } - } -} diff --git a/http-service/src/main/java/net/runelite/http/service/ge/GrandExchangeTradeHistory.java b/http-service/src/main/java/net/runelite/http/service/ge/GrandExchangeTradeHistory.java deleted file mode 100644 index c45f5acf4f..0000000000 --- a/http-service/src/main/java/net/runelite/http/service/ge/GrandExchangeTradeHistory.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (c) 2020, 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.ge; - -import java.time.Instant; -import lombok.Data; - -@Data -class GrandExchangeTradeHistory -{ - private boolean buy; - private int itemId; - private int quantity; - private int price; - private Instant time; -} diff --git a/http-service/src/main/java/net/runelite/http/service/ge/Trade.java b/http-service/src/main/java/net/runelite/http/service/ge/Trade.java deleted file mode 100644 index 7ad01f322a..0000000000 --- a/http-service/src/main/java/net/runelite/http/service/ge/Trade.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (c) 2020, 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.ge; - -import lombok.Data; -import net.runelite.http.api.worlds.WorldType; - -@Data -class Trade -{ - private boolean buy; - private boolean cancel; - private boolean login; - private int itemId; - private int qty; - private int dqty; - private int total; - private int spent; - private int offer; - private int slot; - private int time; - private String machineId; - private Integer userId; - private String ip; - private String ua; - private WorldType worldType; - private int seq; - private long resetTime; -} diff --git a/http-service/src/main/java/net/runelite/http/service/ge/TradeAction.java b/http-service/src/main/java/net/runelite/http/service/ge/TradeAction.java deleted file mode 100644 index fcc96d615f..0000000000 --- a/http-service/src/main/java/net/runelite/http/service/ge/TradeAction.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (c) 2019, Adam - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package net.runelite.http.service.ge; - -enum TradeAction -{ - BUY, - SELL; -} diff --git a/http-service/src/main/java/net/runelite/http/service/ge/TradeEntry.java b/http-service/src/main/java/net/runelite/http/service/ge/TradeEntry.java deleted file mode 100644 index bca3869811..0000000000 --- a/http-service/src/main/java/net/runelite/http/service/ge/TradeEntry.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (c) 2019, Adam - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package net.runelite.http.service.ge; - -import java.time.Instant; -import lombok.Data; - -@Data -class TradeEntry -{ - private int id; - private int user; - private TradeAction action; - private int item; - private int quantity; - private int price; - private Instant time; -} diff --git a/http-service/src/main/java/net/runelite/http/service/item/ItemController.java b/http-service/src/main/java/net/runelite/http/service/item/ItemController.java deleted file mode 100644 index e546344d4c..0000000000 --- a/http-service/src/main/java/net/runelite/http/service/item/ItemController.java +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Copyright (c) 2017-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.service.item; - -import com.google.common.base.Suppliers; -import com.google.common.hash.HashCode; -import com.google.common.hash.Hasher; -import com.google.common.hash.Hashing; -import java.util.concurrent.TimeUnit; -import java.util.function.Supplier; -import net.runelite.http.api.item.ItemPrice; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.http.CacheControl; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; - -@RestController -@RequestMapping("/item") -public class ItemController -{ - private static class MemoizedPrices - { - final ItemPrice[] prices; - final String hash; - - MemoizedPrices(ItemPrice[] prices) - { - this.prices = prices; - - Hasher hasher = Hashing.sha256().newHasher(); - for (ItemPrice itemPrice : prices) - { - hasher.putInt(itemPrice.getId()).putInt(itemPrice.getPrice()); - } - HashCode code = hasher.hash(); - hash = code.toString(); - } - } - - private final ItemService itemService; - private final int priceCache; - - private final Supplier memoizedPrices; - - @Autowired - public ItemController( - ItemService itemService, - @Value("${runelite.price.cache}") int priceCache - ) - { - this.itemService = itemService; - this.priceCache = priceCache; - - memoizedPrices = Suppliers.memoizeWithExpiration(() -> new MemoizedPrices(itemService.fetchPrices().stream() - .map(priceEntry -> - { - ItemPrice itemPrice = new ItemPrice(); - itemPrice.setId(priceEntry.getItem()); - itemPrice.setName(priceEntry.getName()); - itemPrice.setPrice(priceEntry.getPrice()); - itemPrice.setWikiPrice(computeWikiPrice(priceEntry)); - return itemPrice; - }) - .toArray(ItemPrice[]::new)), priceCache, TimeUnit.MINUTES); - } - - private static int computeWikiPrice(PriceEntry priceEntry) - { - if (priceEntry.getLow() > 0 && priceEntry.getHigh() > 0) - { - return (priceEntry.getLow() + priceEntry.getHigh()) / 2; - } - else - { - return Math.max(priceEntry.getLow(), priceEntry.getHigh()); - } - } - - @GetMapping("/prices") - public ResponseEntity prices() - { - MemoizedPrices memorizedPrices = this.memoizedPrices.get(); - return ResponseEntity.ok() - .eTag(memorizedPrices.hash) - .cacheControl(CacheControl.maxAge(priceCache, TimeUnit.MINUTES).cachePublic()) - .body(memorizedPrices.prices); - } -} diff --git a/http-service/src/main/java/net/runelite/http/service/item/ItemEntry.java b/http-service/src/main/java/net/runelite/http/service/item/ItemEntry.java deleted file mode 100644 index 41186b1608..0000000000 --- a/http-service/src/main/java/net/runelite/http/service/item/ItemEntry.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * 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.item; - -import java.time.Instant; -import lombok.Data; -import net.runelite.http.api.item.ItemType; - -@Data -public class ItemEntry -{ - private int id; - private String name; - private String description; - private ItemType type; - private Instant timestamp; -} diff --git a/http-service/src/main/java/net/runelite/http/service/item/ItemService.java b/http-service/src/main/java/net/runelite/http/service/item/ItemService.java deleted file mode 100644 index bc3f03e70c..0000000000 --- a/http-service/src/main/java/net/runelite/http/service/item/ItemService.java +++ /dev/null @@ -1,287 +0,0 @@ -/* - * Copyright (c) 2017-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.service.item; - -import com.google.gson.JsonParseException; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.nio.charset.StandardCharsets; -import java.time.Instant; -import java.util.List; -import java.util.Map; -import java.util.Random; -import lombok.extern.slf4j.Slf4j; -import net.runelite.cache.definitions.ItemDefinition; -import net.runelite.http.api.RuneLiteAPI; -import net.runelite.http.api.item.ItemType; -import net.runelite.http.service.cache.CacheService; -import okhttp3.HttpUrl; -import okhttp3.OkHttpClient; -import okhttp3.Request; -import okhttp3.Response; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Qualifier; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.scheduling.annotation.Scheduled; -import org.springframework.stereotype.Service; -import org.sql2o.Connection; -import org.sql2o.Query; -import org.sql2o.Sql2o; - -@Service -@Slf4j -public class ItemService -{ - private static final String CREATE_ITEMS = "CREATE TABLE IF NOT EXISTS `items` (\n" - + " `id` int(11) NOT NULL,\n" - + " `name` tinytext NOT NULL,\n" - + " `description` tinytext NOT NULL,\n" - + " `type` enum('DEFAULT') NOT NULL,\n" - + " `timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,\n" - + " PRIMARY KEY (`id`)\n" - + ") ENGINE=InnoDB"; - - private static final String CREATE_PRICES = "CREATE TABLE IF NOT EXISTS `prices` (\n" - + " `item` int(11) NOT NULL,\n" - + " `price` int(11) NOT NULL,\n" - + " `time` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',\n" - + " `fetched_time` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',\n" - + " UNIQUE KEY `item_time` (`item`,`time`),\n" - + " KEY `item_fetched_time` (`item`,`fetched_time`)\n" - + ") ENGINE=InnoDB"; - - private final Sql2o sql2o; - private final CacheService cacheService; - private final OkHttpClient okHttpClient; - private final HttpUrl itemUrl; - private final HttpUrl priceUrl; - - private int[] tradeableItems; - private final Random random = new Random(); - - @Autowired - public ItemService( - @Qualifier("Runelite SQL2O") Sql2o sql2o, - CacheService cacheService, - OkHttpClient okHttpClient, - @Value("${runelite.item.itemUrl}") String itemUrl, - @Value("${runelite.item.priceUrl}") String priceUrl - ) - { - this.sql2o = sql2o; - this.cacheService = cacheService; - this.okHttpClient = okHttpClient; - this.itemUrl = HttpUrl.get(itemUrl); - this.priceUrl = HttpUrl.get(priceUrl); - - try (Connection con = sql2o.open()) - { - con.createQuery(CREATE_ITEMS) - .executeUpdate(); - - con.createQuery(CREATE_PRICES) - .executeUpdate(); - } - } - - public ItemEntry getItem(int itemId) - { - try (Connection con = sql2o.open()) - { - return con.createQuery("select id, name, description, type from items where id = :id") - .addParameter("id", itemId) - .executeAndFetchFirst(ItemEntry.class); - } - } - - public ItemEntry fetchItem(int itemId) - { - try - { - RSItem rsItem = fetchRSItem(itemId); - - try (Connection con = sql2o.open()) - { - con.createQuery("insert into items (id, name, description, type) values (:id," - + " :name, :description, :type) ON DUPLICATE KEY UPDATE name = :name," - + " description = :description, type = :type") - .addParameter("id", rsItem.getId()) - .addParameter("name", rsItem.getName()) - .addParameter("description", rsItem.getDescription()) - .addParameter("type", rsItem.getType()) - .executeUpdate(); - } - - ItemEntry item = new ItemEntry(); - item.setId(itemId); - item.setName(rsItem.getName()); - item.setDescription(rsItem.getDescription()); - item.setType(ItemType.of(rsItem.getType())); - return item; - } - catch (IOException ex) - { - log.warn("unable to fetch item {}", itemId, ex); - return null; - } - } - - private void fetchPrice(int itemId) - { - RSPrices rsprice; - try - { - rsprice = fetchRSPrices(itemId); - } - catch (IOException ex) - { - log.warn("unable to fetch price for item {}", itemId, ex); - return; - } - - try (Connection con = sql2o.beginTransaction()) - { - Instant now = Instant.now(); - - Query query = con.createQuery("insert into prices (item, price, time, fetched_time) values (:item, :price, :time, :fetched_time) " - + "ON DUPLICATE KEY UPDATE price = VALUES(price), fetched_time = VALUES(fetched_time)"); - - for (Map.Entry entry : rsprice.getDaily().entrySet()) - { - long ts = entry.getKey(); // ms since epoch - int price = entry.getValue(); // gp - - Instant time = Instant.ofEpochMilli(ts); - - query - .addParameter("item", itemId) - .addParameter("price", price) - .addParameter("time", time) - .addParameter("fetched_time", now) - .addToBatch(); - } - - query.executeBatch(); - con.commit(false); - } - } - - public List fetchPrices() - { - try (Connection con = sql2o.beginTransaction()) - { - Query query = con.createQuery("select t2.item, t3.name, t2.time, prices.price, prices.fetched_time, t4.high, t4.low" + - " from (select t1.item as item, max(t1.time) as time from prices t1 group by item) t2" + - " join prices on t2.item=prices.item and t2.time=prices.time" + - " join items t3 on t2.item=t3.id" + - " join wiki_prices t4 on t2.item=t4.item_id"); - return query.executeAndFetch(PriceEntry.class); - } - } - - private RSItem fetchRSItem(int itemId) throws IOException - { - HttpUrl itemUrl = this.itemUrl - .newBuilder() - .addQueryParameter("item", "" + itemId) - .build(); - - Request request = new Request.Builder() - .url(itemUrl) - .build(); - - RSItemResponse itemResponse = fetchJson(request, RSItemResponse.class); - return itemResponse.getItem(); - - } - - private RSPrices fetchRSPrices(int itemId) throws IOException - { - HttpUrl priceUrl = this.priceUrl - .newBuilder() - .addPathSegment(itemId + ".json") - .build(); - - Request request = new Request.Builder() - .url(priceUrl) - .build(); - - return fetchJson(request, RSPrices.class); - } - - private T fetchJson(Request request, Class clazz) throws IOException - { - try (Response response = okHttpClient.newCall(request).execute()) - { - if (!response.isSuccessful()) - { - throw new IOException("Unsuccessful http response: " + response); - } - - InputStream in = response.body().byteStream(); - return RuneLiteAPI.GSON.fromJson(new InputStreamReader(in, StandardCharsets.UTF_8), clazz); - } - catch (JsonParseException ex) - { - throw new IOException(ex); - } - } - - @Scheduled(fixedDelay = 20_000) - public void crawlPrices() - { - if (tradeableItems == null || tradeableItems.length == 0) - { - return; - } - - int idx = random.nextInt(tradeableItems.length); - int id = tradeableItems[idx]; - - log.debug("Fetching price for {}", id); - - // check if the item name or description has changed - fetchItem(id); - fetchPrice(id); - } - - @Scheduled(fixedDelay = 1_800_000) // 30 minutes - public void reloadItems() throws IOException - { - List items = cacheService.getItems(); - if (items.isEmpty()) - { - log.warn("Failed to load any items from cache, item price updating will be disabled"); - } - - tradeableItems = items.stream() - .filter(ItemDefinition::isTradeable) - .mapToInt(ItemDefinition::getId) - .toArray(); - - log.debug("Loaded {} tradeable items", tradeableItems.length); - } -} diff --git a/http-service/src/main/java/net/runelite/http/service/item/PriceEntry.java b/http-service/src/main/java/net/runelite/http/service/item/PriceEntry.java deleted file mode 100644 index 4d29d7e98d..0000000000 --- a/http-service/src/main/java/net/runelite/http/service/item/PriceEntry.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * 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.item; - -import java.time.Instant; -import lombok.Data; - -@Data -class PriceEntry -{ - private int item; - private String name; - private int price; - private Instant time; - private Instant fetched_time; - private int high; - private int low; -} diff --git a/http-service/src/main/java/net/runelite/http/service/item/RSItem.java b/http-service/src/main/java/net/runelite/http/service/item/RSItem.java deleted file mode 100644 index 17e3352f6d..0000000000 --- a/http-service/src/main/java/net/runelite/http/service/item/RSItem.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * 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.item; - -import lombok.Data; - -@Data -class RSItem -{ - private int id; - private String name; - private String description; - private String type; -} diff --git a/http-service/src/main/java/net/runelite/http/service/item/RSItemResponse.java b/http-service/src/main/java/net/runelite/http/service/item/RSItemResponse.java deleted file mode 100644 index c0305cd552..0000000000 --- a/http-service/src/main/java/net/runelite/http/service/item/RSItemResponse.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * 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.item; - -import lombok.Data; - -@Data -class RSItemResponse -{ - private RSItem item; -} diff --git a/http-service/src/main/java/net/runelite/http/service/item/RSPrices.java b/http-service/src/main/java/net/runelite/http/service/item/RSPrices.java deleted file mode 100644 index 04331d753e..0000000000 --- a/http-service/src/main/java/net/runelite/http/service/item/RSPrices.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * 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.item; - -import java.util.Map; -import lombok.Data; - -@Data -public class RSPrices -{ - /** - * unix time in ms to price in gp - */ - private Map daily; -} diff --git a/http-service/src/main/java/net/runelite/http/service/loottracker/LootResult.java b/http-service/src/main/java/net/runelite/http/service/loottracker/LootResult.java deleted file mode 100644 index 4cb3375154..0000000000 --- a/http-service/src/main/java/net/runelite/http/service/loottracker/LootResult.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * 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.service.loottracker; - -import java.time.Instant; -import lombok.Data; -import net.runelite.http.api.loottracker.LootRecordType; - -@Data -class LootResult -{ - private int killId; - private Instant first_time; - private Instant last_time; - private LootRecordType type; - private String eventId; - private int amount; - private int itemId; - private int itemQuantity; -} diff --git a/http-service/src/main/java/net/runelite/http/service/loottracker/LootTrackerController.java b/http-service/src/main/java/net/runelite/http/service/loottracker/LootTrackerController.java deleted file mode 100644 index ef39ac0d50..0000000000 --- a/http-service/src/main/java/net/runelite/http/service/loottracker/LootTrackerController.java +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Copyright (c) 2018, TheStonedTurtle - * 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.service.loottracker; - -import com.google.api.client.http.HttpStatusCodes; -import com.google.gson.Gson; -import java.io.IOException; -import java.util.Collection; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import net.runelite.http.api.RuneLiteAPI; -import net.runelite.http.api.loottracker.LootAggregate; -import net.runelite.http.api.loottracker.LootRecord; -import net.runelite.http.service.account.AuthFilter; -import net.runelite.http.service.account.beans.SessionEntry; -import net.runelite.http.service.util.redis.RedisPool; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.web.bind.annotation.DeleteMapping; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestMethod; -import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.bind.annotation.RestController; -import redis.clients.jedis.Jedis; - -@RestController -@RequestMapping("/loottracker") -public class LootTrackerController -{ - private static final Gson GSON = RuneLiteAPI.GSON; - - @Autowired - private LootTrackerService service; - - @Autowired - private RedisPool redisPool; - - @Autowired - private AuthFilter auth; - - @RequestMapping(method = RequestMethod.POST) - public void storeLootRecord(HttpServletRequest request, HttpServletResponse response, @RequestBody Collection records) throws IOException - { - SessionEntry session = null; - if (request.getHeader(RuneLiteAPI.RUNELITE_AUTH) != null) - { - session = auth.handle(request, response); - if (session == null) - { - // error is set here on the response, so we shouldn't continue - return; - } - } - Integer userId = session == null ? null : session.getUser(); - - if (userId != null) - { - service.store(records, userId); - } - response.setStatus(HttpStatusCodes.STATUS_CODE_OK); - - try (Jedis jedis = redisPool.getResource()) - { - jedis.publish("drops", GSON.toJson(records)); - } - } - - @GetMapping - public Collection getLootAggregate(HttpServletRequest request, HttpServletResponse response, @RequestParam(value = "count", defaultValue = "1024") int count, @RequestParam(value = "start", defaultValue = "0") int start) throws IOException - { - SessionEntry e = auth.handle(request, response); - if (e == null) - { - response.setStatus(HttpStatusCodes.STATUS_CODE_UNAUTHORIZED); - return null; - } - - return service.get(e.getUser(), count, start); - } - - @DeleteMapping - public void deleteLoot(HttpServletRequest request, HttpServletResponse response, - @RequestParam(required = false) String eventId) throws IOException - { - SessionEntry e = auth.handle(request, response); - if (e == null) - { - response.setStatus(HttpStatusCodes.STATUS_CODE_UNAUTHORIZED); - return; - } - - service.delete(e.getUser(), eventId); - } -} \ No newline at end of file diff --git a/http-service/src/main/java/net/runelite/http/service/loottracker/LootTrackerService.java b/http-service/src/main/java/net/runelite/http/service/loottracker/LootTrackerService.java deleted file mode 100644 index 4836afd97d..0000000000 --- a/http-service/src/main/java/net/runelite/http/service/loottracker/LootTrackerService.java +++ /dev/null @@ -1,259 +0,0 @@ -/* - * Copyright (c) 2018, TheStonedTurtle - * 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.service.loottracker; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import lombok.EqualsAndHashCode; -import lombok.Getter; -import lombok.RequiredArgsConstructor; -import net.runelite.http.api.loottracker.GameItem; -import net.runelite.http.api.loottracker.LootAggregate; -import net.runelite.http.api.loottracker.LootRecord; -import net.runelite.http.api.loottracker.LootRecordType; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Qualifier; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.scheduling.annotation.Scheduled; -import org.springframework.stereotype.Service; -import org.sql2o.Connection; -import org.sql2o.Query; -import org.sql2o.Sql2o; - -@Service -public class LootTrackerService -{ - private static final String CREATE_KILLS = "CREATE TABLE IF NOT EXISTS `loottracker_kills` (\n" + - " `id` bigint NOT NULL AUTO_INCREMENT,\n" + - " `first_time` timestamp NOT NULL DEFAULT current_timestamp(),\n" + - " `last_time` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(),\n" + - " `accountId` int(11) NOT NULL,\n" + - " `type` enum('NPC','PLAYER','EVENT','PICKPOCKET','UNKNOWN') NOT NULL,\n" + - " `eventId` varchar(255) NOT NULL,\n" + - " `amount` int(11) NOT NULL,\n" + - " PRIMARY KEY (`id`),\n" + - " FOREIGN KEY (accountId) REFERENCES users(id) ON DELETE CASCADE ON UPDATE CASCADE,\n" + - " INDEX idx_acc_lasttime (`accountId` ,`last_time`),\n" + - " UNIQUE INDEX idx_acc_type_event (`accountId`, `type`, `eventId`),\n" + - " INDEX idx_time (last_time)" + - ") ENGINE=InnoDB;"; - - private static final String CREATE_DROPS = "CREATE TABLE IF NOT EXISTS `loottracker_drops` (\n" + - " `killId` bigint NOT NULL,\n" + - " `itemId` int(11) NOT NULL,\n" + - " `itemQuantity` int(11) NOT NULL,\n" + - " UNIQUE INDEX idx_kill_item (`killId`, `itemId`),\n" + - " FOREIGN KEY (killId) REFERENCES loottracker_kills(id) ON DELETE CASCADE\n" + - ") ENGINE=InnoDB;\n"; - - // Queries for inserting kills - private static final String INSERT_KILL_QUERY = "INSERT INTO loottracker_kills (accountId, type, eventId, amount) VALUES (:accountId, :type, :eventId, :kills) ON DUPLICATE KEY UPDATE amount = amount + :kills"; - private static final String INSERT_DROP_QUERY = "INSERT INTO loottracker_drops (killId, itemId, itemQuantity) VALUES (:killId, :itemId, :itemQuantity) ON DUPLICATE KEY UPDATE itemQuantity = itemQuantity + :itemQuantity"; - - private static final String SELECT_LOOT_QUERY = "SELECT killId,first_time,last_time,type,eventId,amount,itemId,itemQuantity FROM loottracker_kills JOIN loottracker_drops ON loottracker_drops.killId = loottracker_kills.id WHERE accountId = :accountId ORDER BY last_time DESC LIMIT :limit OFFSET :offset"; - - private static final String DELETE_LOOT_ACCOUNT = "DELETE FROM loottracker_kills WHERE accountId = :accountId"; - private static final String DELETE_LOOT_ACCOUNT_EVENTID = "DELETE FROM loottracker_kills WHERE accountId = :accountId AND eventId = :eventId"; - - private final Sql2o sql2o; - private final int historyDays; - - @Autowired - public LootTrackerService( - @Qualifier("Runelite SQL2O") Sql2o sql2o, - @Value("${runelite.loottracker.history}") int historyDays - ) - { - this.sql2o = sql2o; - this.historyDays = historyDays; - - // Ensure necessary tables exist - try (Connection con = sql2o.open()) - { - con.createQuery(CREATE_KILLS).executeUpdate(); - con.createQuery(CREATE_DROPS).executeUpdate(); - } - } - - @RequiredArgsConstructor - @EqualsAndHashCode(exclude = {"kills", "drops"}) - @Getter - private static class AggregateLootRecord - { - final LootRecordType type; - final String eventId; - int kills = 0; - Map drops = new HashMap<>(); - } - - @RequiredArgsConstructor - @EqualsAndHashCode(exclude = "qty") - @Getter - private static class AggregateDrop - { - final int id; - int qty = 0; - } - - private static Collection aggregate(Collection records) - { - Map combinedRecords = new HashMap<>(); - for (LootRecord record : records) - { - AggregateLootRecord r = new AggregateLootRecord(record.getType(), record.getEventId()); - r = combinedRecords.computeIfAbsent(r, (k) -> k); - ++r.kills; - - // Combine drops - for (GameItem gameItem : record.getDrops()) - { - AggregateDrop cd = new AggregateDrop(gameItem.getId()); - cd = r.drops.computeIfAbsent(cd, (k) -> k); - cd.qty += gameItem.getQty(); - } - } - return combinedRecords.values(); - } - - /** - * Store LootRecord - * - * @param records LootRecords to store - * @param accountId runelite account id to tie data too - */ - public void store(Collection records, int accountId) - { - Collection combinedRecords = aggregate(records); - - try (Connection con = sql2o.beginTransaction()) - { - Query killQuery = con.createQuery(INSERT_KILL_QUERY, true); - Query insertDrop = con.createQuery(INSERT_DROP_QUERY); - - for (AggregateLootRecord record : combinedRecords) - { - killQuery - .addParameter("accountId", accountId) - .addParameter("type", record.getType()) - .addParameter("eventId", record.getEventId()) - .addParameter("kills", record.getKills()) - .executeUpdate(); - Object[] keys = con.getKeys(); - - for (AggregateDrop drop : record.getDrops().values()) - { - insertDrop - .addParameter("killId", keys[0]) - .addParameter("itemId", drop.getId()) - .addParameter("itemQuantity", drop.getQty()) - .addToBatch(); - } - - insertDrop.executeBatch(); - } - - con.commit(false); - } - } - - public Collection get(int accountId, int limit, int offset) - { - List lootResults; - - try (Connection con = sql2o.open()) - { - lootResults = con.createQuery(SELECT_LOOT_QUERY) - .addParameter("accountId", accountId) - .addParameter("limit", limit) - .addParameter("offset", offset) - .executeAndFetch(LootResult.class); - } - - LootResult current = null; - List lootRecords = new ArrayList<>(); - List gameItems = new ArrayList<>(); - - for (LootResult lootResult : lootResults) - { - if (current == null || current.getKillId() != lootResult.getKillId()) - { - if (!gameItems.isEmpty()) - { - LootAggregate lootRecord = new LootAggregate(current.getEventId(), current.getType(), gameItems, current.getFirst_time(), current.getLast_time(), current.getAmount()); - lootRecords.add(lootRecord); - - gameItems = new ArrayList<>(); - } - - current = lootResult; - } - - GameItem gameItem = new GameItem(lootResult.getItemId(), lootResult.getItemQuantity()); - gameItems.add(gameItem); - } - - if (!gameItems.isEmpty()) - { - LootAggregate lootRecord = new LootAggregate(current.getEventId(), current.getType(), gameItems, current.getFirst_time(), current.getLast_time(), current.getAmount()); - lootRecords.add(lootRecord); - } - - return lootRecords; - } - - public void delete(int accountId, String eventId) - { - try (Connection con = sql2o.open()) - { - if (eventId == null) - { - con.createQuery(DELETE_LOOT_ACCOUNT) - .addParameter("accountId", accountId) - .executeUpdate(); - } - else - { - con.createQuery(DELETE_LOOT_ACCOUNT_EVENTID) - .addParameter("accountId", accountId) - .addParameter("eventId", eventId) - .executeUpdate(); - } - } - } - - @Scheduled(fixedDelay = 60 * 60 * 1000) - public void expire() - { - try (Connection con = sql2o.open()) - { - con.createQuery("delete from loottracker_kills where last_time < current_timestamp() - interval " + historyDays + " day") - .executeUpdate(); - } - } -} diff --git a/http-service/src/main/java/net/runelite/http/service/pluginhub/PluginHubController.java b/http-service/src/main/java/net/runelite/http/service/pluginhub/PluginHubController.java deleted file mode 100644 index f9f424dca7..0000000000 --- a/http-service/src/main/java/net/runelite/http/service/pluginhub/PluginHubController.java +++ /dev/null @@ -1,144 +0,0 @@ -/* - * Copyright (c) 2020, 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.pluginhub; - -import com.google.common.cache.Cache; -import com.google.common.cache.CacheBuilder; -import java.time.Duration; -import java.time.Instant; -import java.time.ZoneOffset; -import java.time.ZonedDateTime; -import java.time.format.DateTimeFormatter; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.TimeUnit; -import java.util.stream.IntStream; -import javax.servlet.http.HttpServletRequest; -import net.runelite.http.service.util.redis.RedisPool; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.http.CacheControl; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; -import org.springframework.scheduling.annotation.Scheduled; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; -import redis.clients.jedis.Jedis; - -@RestController -@RequestMapping("/pluginhub") -public class PluginHubController -{ - @Value("${pluginhub.stats.days:7}") - private int days; - - @Value("${pluginhub.stats.expire:90}") - private int expireDays; - - @Autowired - private RedisPool redisPool; - - private final Cache pluginCache = CacheBuilder.newBuilder() - .maximumSize(512L) - .build(); - - private Map pluginCounts = Collections.emptyMap(); - - @GetMapping - public ResponseEntity> get() - { - if (pluginCounts.isEmpty()) - { - return ResponseEntity.status(HttpStatus.SERVICE_UNAVAILABLE) - .cacheControl(CacheControl.noCache()) - .build(); - } - - return ResponseEntity.ok() - .cacheControl(CacheControl.maxAge(30, TimeUnit.MINUTES).cachePublic()) - .body(pluginCounts); - } - - @PostMapping - public void submit(HttpServletRequest request, @RequestBody String[] plugins) - { - final String date = Instant.now().atZone(ZoneOffset.UTC).format(DateTimeFormatter.ISO_LOCAL_DATE); - final String ip = request.getHeader("X-Forwarded-For"); - try (Jedis jedis = redisPool.getResource()) - { - for (String plugin : plugins) - { - if (!plugin.matches("[a-z0-9-]+")) - { - continue; - } - - jedis.pfadd("pluginhub." + plugin + "." + date, ip); - - if (pluginCache.getIfPresent(plugin) == null) - { - jedis.sadd("pluginhub.plugins", plugin); - // additionally set the ttl on the hyperloglog since it might be a new key - jedis.expire("pluginhub." + plugin + "." + date, (int) (Duration.ofDays(expireDays).toMillis() / 1000L)); - - pluginCache.put(plugin, plugin); - } - } - } - } - - @Scheduled(fixedDelay = 1_800_000, initialDelay = 30_000) // 30 minutes with 30 second initial delay - public void rebuildCounts() - { - Map counts = new HashMap<>(); - try (Jedis jedis = redisPool.getResource()) - { - Set plugins = jedis.smembers("pluginhub.plugins"); - ZonedDateTime time = Instant.now().atZone(ZoneOffset.UTC); - - for (String plugin : plugins) - { - // When called with multiple keys, pfcount returns the approximated - // cardinality of the union of the HyperLogLogs. We use this to determine - // the number of users in the last N days. - String[] keys = IntStream.range(0, days - 1) - .mapToObj(time::minusDays) - .map(zdt -> "pluginhub." + plugin + "." + zdt.format(DateTimeFormatter.ISO_LOCAL_DATE)) - .toArray(String[]::new); - long cnt = jedis.pfcount(keys); - if (cnt > 0) - { - counts.put(plugin, cnt); - } - } - } - pluginCounts = counts; - } -} diff --git a/http-service/src/main/java/net/runelite/http/service/util/InstantConverter.java b/http-service/src/main/java/net/runelite/http/service/util/InstantConverter.java deleted file mode 100644 index 785ad00266..0000000000 --- a/http-service/src/main/java/net/runelite/http/service/util/InstantConverter.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * 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: - * - * Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 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 HOLDER 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.util; - -import java.sql.Timestamp; -import java.time.Instant; -import org.sql2o.converters.Converter; -import org.sql2o.converters.ConverterException; - -public class InstantConverter implements Converter -{ - @Override - public Instant convert(Object val) throws ConverterException - { - Timestamp ts = (Timestamp) val; - return ts.toInstant(); - } - - @Override - public Object toDatabaseParam(Instant val) - { - return Timestamp.from(val); - } - -} diff --git a/http-service/src/main/java/net/runelite/http/service/util/exception/InternalServerErrorException.java b/http-service/src/main/java/net/runelite/http/service/util/exception/InternalServerErrorException.java deleted file mode 100644 index 62adc5b6fc..0000000000 --- a/http-service/src/main/java/net/runelite/http/service/util/exception/InternalServerErrorException.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * 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: - * - * Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 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 HOLDER 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.util.exception; - -import org.springframework.http.HttpStatus; -import org.springframework.web.bind.annotation.ResponseStatus; - -@ResponseStatus(code = HttpStatus.INTERNAL_SERVER_ERROR) -public class InternalServerErrorException extends RuntimeException -{ - public InternalServerErrorException(String message) - { - super(message); - } -} diff --git a/http-service/src/main/java/net/runelite/http/service/util/exception/NotFoundException.java b/http-service/src/main/java/net/runelite/http/service/util/exception/NotFoundException.java deleted file mode 100644 index 83e04ceca6..0000000000 --- a/http-service/src/main/java/net/runelite/http/service/util/exception/NotFoundException.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * 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: - * - * Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 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 HOLDER 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.util.exception; - -import org.springframework.http.HttpStatus; -import org.springframework.web.bind.annotation.ResponseStatus; - -@ResponseStatus(code = HttpStatus.NOT_FOUND, reason = "Not found") -public class NotFoundException extends RuntimeException -{ - -} diff --git a/http-service/src/main/java/net/runelite/http/service/wiki/PriceResult.java b/http-service/src/main/java/net/runelite/http/service/wiki/PriceResult.java deleted file mode 100644 index 0723063b02..0000000000 --- a/http-service/src/main/java/net/runelite/http/service/wiki/PriceResult.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (c) 2021, 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: - * - * Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 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 HOLDER 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.wiki; - -import java.util.Map; -import lombok.Data; - -@Data -class PriceResult -{ - @Data - static class Item - { - private int high; - private int highTime; - private int low; - private int lowTime; - } - - private Map data; -} diff --git a/http-service/src/main/java/net/runelite/http/service/wiki/WikiPriceService.java b/http-service/src/main/java/net/runelite/http/service/wiki/WikiPriceService.java deleted file mode 100644 index 2e32fc1808..0000000000 --- a/http-service/src/main/java/net/runelite/http/service/wiki/WikiPriceService.java +++ /dev/null @@ -1,140 +0,0 @@ -/* - * Copyright (c) 2021, 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: - * - * Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 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 HOLDER 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.wiki; - -import com.google.gson.JsonSyntaxException; -import java.io.IOException; -import java.util.Map; -import lombok.extern.slf4j.Slf4j; -import net.runelite.http.api.RuneLiteAPI; -import okhttp3.HttpUrl; -import okhttp3.OkHttpClient; -import okhttp3.Request; -import okhttp3.Response; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Qualifier; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.scheduling.annotation.Scheduled; -import org.springframework.stereotype.Service; -import org.sql2o.Connection; -import org.sql2o.Query; -import org.sql2o.Sql2o; - -@Service -@Slf4j -public class WikiPriceService -{ - private static final String CREATE = "CREATE TABLE IF NOT EXISTS `wiki_prices` (\n" + - " `item_id` int(11) NOT NULL,\n" + - " `high` int(11) NOT NULL,\n" + - " `highTime` int(11) NOT NULL,\n" + - " `low` int(11) NOT NULL,\n" + - " `lowTime` int(11) NOT NULL,\n" + - " `last_update` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,\n" + - " PRIMARY KEY (`item_id`)\n" + - ") ENGINE=InnoDB;"; - - private final Sql2o sql2o; - private final OkHttpClient okHttpClient; - private final HttpUrl wikiUrl; - - @Autowired - public WikiPriceService( - @Qualifier("Runelite SQL2O") Sql2o sql2o, - OkHttpClient okHttpClient, - @Value("${runelite.wiki.url}") String url - ) - { - this.sql2o = sql2o; - this.okHttpClient = okHttpClient; - this.wikiUrl = HttpUrl.get(url); - - try (Connection con = sql2o.open()) - { - con.createQuery(CREATE).executeUpdate(); - } - } - - @Scheduled(initialDelay = 1000 * 5, fixedDelayString = "${runelite.wiki.poll.ms}") - private void updateDatabase() - { - try - { - PriceResult summary = getPrices(); - - try (Connection con = sql2o.beginTransaction()) - { - Query query = con.createQuery("INSERT INTO wiki_prices (item_id, high, highTime, low, lowTime)" - + " VALUES (:itemId, :high, :highTime, :low, :lowTime)" - + " ON DUPLICATE KEY UPDATE high = VALUES(high), highTime = VALUES(highTime)," - + " low = VALUES(low), lowTime = VALUES(lowTime)"); - - for (Map.Entry entry : summary.getData().entrySet()) - { - Integer itemId = entry.getKey(); - PriceResult.Item item = entry.getValue(); - - query - .addParameter("itemId", itemId) - .addParameter("high", item.getHigh()) - .addParameter("highTime", item.getHighTime()) - .addParameter("low", item.getLow()) - .addParameter("lowTime", item.getLowTime()) - .addToBatch(); - } - - query.executeBatch(); - con.commit(false); - } - } - catch (IOException e) - { - log.warn("Error while updating wiki prices", e); - } - } - - private PriceResult getPrices() throws IOException - { - Request request = new Request.Builder() - .url(wikiUrl) - .header("User-Agent", "RuneLite") - .build(); - - try (Response responseOk = okHttpClient.newCall(request).execute()) - { - if (!responseOk.isSuccessful()) - { - throw new IOException("Error retrieving prices: " + responseOk.message()); - } - - return RuneLiteAPI.GSON.fromJson(responseOk.body().string(), PriceResult.class); - } - catch (JsonSyntaxException ex) - { - throw new IOException(ex); - } - } -} diff --git a/http-service/src/main/java/net/runelite/http/service/worlds/ServiceWorldType.java b/http-service/src/main/java/net/runelite/http/service/worlds/ServiceWorldType.java deleted file mode 100644 index 642cd0440a..0000000000 --- a/http-service/src/main/java/net/runelite/http/service/worlds/ServiceWorldType.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (c) 2018, Lotto - * 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 net.runelite.http.api.worlds.WorldType; - -enum ServiceWorldType -{ - MEMBERS(WorldType.MEMBERS, 1), - PVP(WorldType.PVP, 1 << 2), - BOUNTY(WorldType.BOUNTY, 1 << 5), - SKILL_TOTAL(WorldType.SKILL_TOTAL, 1 << 7), - HIGH_RISK(WorldType.HIGH_RISK, 1 << 10), - LAST_MAN_STANDING(WorldType.LAST_MAN_STANDING, 1 << 14), - NOSAVE_MODE(WorldType.NOSAVE_MODE, 1 << 25), - TOURNAMENT(WorldType.TOURNAMENT, 1 << 26), - DEADMAN(WorldType.DEADMAN, 1 << 29), - SEASONAL(WorldType.SEASONAL, 1 << 30); - - private final WorldType apiType; - private final int mask; - - ServiceWorldType(WorldType apiType, int mask) - { - this.apiType = apiType; - this.mask = mask; - } - - public WorldType getApiType() - { - return apiType; - } - - public int getMask() - { - return mask; - } -} diff --git a/http-service/src/main/java/net/runelite/http/service/worlds/WorldController.java b/http-service/src/main/java/net/runelite/http/service/worlds/WorldController.java deleted file mode 100644 index a0c71af52c..0000000000 --- a/http-service/src/main/java/net/runelite/http/service/worlds/WorldController.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * 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.service.worlds; - -import java.io.IOException; -import java.util.concurrent.TimeUnit; -import net.runelite.http.api.worlds.WorldResult; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.http.CacheControl; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; -import org.springframework.scheduling.annotation.Scheduled; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; - -@RestController -@RequestMapping("/worlds") -public class WorldController -{ - @Autowired - private WorldsService worldsService; - - private WorldResult worldResult; - - @GetMapping - public ResponseEntity listWorlds() - { - if (worldResult == null) - { - return ResponseEntity.status(HttpStatus.SERVICE_UNAVAILABLE) - .cacheControl(CacheControl.noCache()) - .build(); - } - - return ResponseEntity.ok() - .cacheControl(CacheControl.maxAge(10, TimeUnit.MINUTES).cachePublic()) - .body(worldResult); - } - - @Scheduled(fixedDelay = 60_000L) - public void refreshWorlds() throws IOException - { - worldResult = worldsService.getWorlds(); - } -} 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 deleted file mode 100644 index 1f8debe7eb..0000000000 --- a/http-service/src/main/java/net/runelite/http/service/worlds/WorldsService.java +++ /dev/null @@ -1,132 +0,0 @@ -/* - * 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.nio.ByteBuffer; -import java.util.ArrayList; -import java.util.EnumSet; -import java.util.List; -import net.runelite.http.api.worlds.World; -import net.runelite.http.api.worlds.WorldResult; -import net.runelite.http.api.worlds.WorldType; -import okhttp3.HttpUrl; -import okhttp3.OkHttpClient; -import okhttp3.Request; -import okhttp3.Response; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.stereotype.Service; - -@Service -public class WorldsService -{ - private final OkHttpClient okHttpClient; - private final HttpUrl url; - - @Autowired - public WorldsService( - OkHttpClient okHttpClient, - @Value("${runelite.worlds.url}") String url - ) - { - this.okHttpClient = okHttpClient; - this.url = HttpUrl.get(url); - } - - public WorldResult getWorlds() throws IOException - { - Request okrequest = new Request.Builder() - .url(url) - .build(); - - byte[] b; - - try (Response okresponse = okHttpClient.newCall(okrequest).execute()) - { - b = okresponse.body().bytes(); - } - - List worlds = new ArrayList<>(); - ByteBuffer buf = ByteBuffer.wrap(b); - - int length = buf.getInt(); - buf.limit(length + 4); - - int num = buf.getShort() & 0xFFFF; - - for (int i = 0; i < num; ++i) - { - final World.WorldBuilder worldBuilder = World.builder() - .id(buf.getShort() & 0xFFFF) - .types(getTypes(buf.getInt())) - .address(readString(buf)) - .activity(readString(buf)) - .location(buf.get() & 0xFF) - .players(buf.getShort()); - - worlds.add(worldBuilder.build()); - } - - WorldResult result = new WorldResult(); - result.setWorlds(worlds); - return result; - } - - private static EnumSet getTypes(int mask) - { - EnumSet types = EnumSet.noneOf(WorldType.class); - - for (ServiceWorldType type : ServiceWorldType.values()) - { - if ((mask & type.getMask()) != 0) - { - types.add(type.getApiType()); - } - } - - return types; - } - - 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(); - } -} diff --git a/http-service/src/main/java/net/runelite/http/service/xtea/XteaCache.java b/http-service/src/main/java/net/runelite/http/service/xtea/XteaCache.java deleted file mode 100644 index 7c5f2bb5b0..0000000000 --- a/http-service/src/main/java/net/runelite/http/service/xtea/XteaCache.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * 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.service.xtea; - -import lombok.AllArgsConstructor; -import lombok.Data; - -@Data -@AllArgsConstructor -class XteaCache -{ - private int region; - private int key1; - private int key2; - private int key3; - private int key4; -} diff --git a/http-service/src/main/java/net/runelite/http/service/xtea/XteaController.java b/http-service/src/main/java/net/runelite/http/service/xtea/XteaController.java deleted file mode 100644 index 3868acb8c6..0000000000 --- a/http-service/src/main/java/net/runelite/http/service/xtea/XteaController.java +++ /dev/null @@ -1,86 +0,0 @@ -/* - * 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.service.xtea; - -import java.util.List; -import java.util.stream.Collectors; -import net.runelite.http.api.xtea.XteaKey; -import net.runelite.http.api.xtea.XteaRequest; -import net.runelite.http.service.util.exception.NotFoundException; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import static org.springframework.web.bind.annotation.RequestMethod.POST; -import org.springframework.web.bind.annotation.RestController; - -@RestController -@RequestMapping("/xtea") -public class XteaController -{ - @Autowired - private XteaService xteaService; - - @RequestMapping(method = POST) - public void submit(@RequestBody XteaRequest xteaRequest) - { - xteaService.submit(xteaRequest); - } - - @GetMapping - public List get() - { - return xteaService.get().stream() - .map(XteaController::entryToKey) - .collect(Collectors.toList()); - } - - @GetMapping("/{region}") - public XteaKey getRegion(@PathVariable int region) - { - XteaEntry xteaRegion = xteaService.getRegion(region); - if (xteaRegion == null) - { - throw new NotFoundException(); - } - - return entryToKey(xteaRegion); - } - - private static XteaKey entryToKey(XteaEntry xe) - { - XteaKey xteaKey = new XteaKey(); - xteaKey.setRegion(xe.getRegion()); - xteaKey.setKeys(new int[] - { - xe.getKey1(), - xe.getKey2(), - xe.getKey3(), - xe.getKey4() - }); - return xteaKey; - } -} diff --git a/http-service/src/main/java/net/runelite/http/service/xtea/XteaEntry.java b/http-service/src/main/java/net/runelite/http/service/xtea/XteaEntry.java deleted file mode 100644 index c5e60b1119..0000000000 --- a/http-service/src/main/java/net/runelite/http/service/xtea/XteaEntry.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * 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.xtea; - -import java.time.Instant; -import lombok.Data; - -@Data -class XteaEntry -{ - private int region; - private Instant time; - private int rev; - private int key1; - private int key2; - private int key3; - private int key4; -} diff --git a/http-service/src/main/java/net/runelite/http/service/xtea/XteaService.java b/http-service/src/main/java/net/runelite/http/service/xtea/XteaService.java deleted file mode 100644 index 8a5d651b05..0000000000 --- a/http-service/src/main/java/net/runelite/http/service/xtea/XteaService.java +++ /dev/null @@ -1,250 +0,0 @@ -/* - * 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.xtea; - -import com.google.common.cache.Cache; -import com.google.common.cache.CacheBuilder; -import java.io.IOException; -import java.util.List; -import lombok.extern.slf4j.Slf4j; -import net.runelite.cache.IndexType; -import net.runelite.cache.fs.Container; -import net.runelite.cache.util.Djb2; -import net.runelite.http.api.xtea.XteaKey; -import net.runelite.http.api.xtea.XteaRequest; -import net.runelite.http.service.cache.CacheService; -import net.runelite.http.service.cache.beans.ArchiveEntry; -import net.runelite.http.service.cache.beans.CacheEntry; -import net.runelite.http.service.util.exception.InternalServerErrorException; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Qualifier; -import org.springframework.stereotype.Service; -import org.sql2o.Connection; -import org.sql2o.Query; -import org.sql2o.Sql2o; - -@Service -@Slf4j -public class XteaService -{ - private static final String CREATE_SQL = "CREATE TABLE IF NOT EXISTS `xtea` (\n" - + " `id` int(11) NOT NULL AUTO_INCREMENT,\n" - + " `region` int(11) NOT NULL,\n" - + " `time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,\n" - + " `rev` int(11) NOT NULL,\n" - + " `key1` int(11) NOT NULL,\n" - + " `key2` int(11) NOT NULL,\n" - + " `key3` int(11) NOT NULL,\n" - + " `key4` int(11) NOT NULL,\n" - + " PRIMARY KEY (`id`),\n" - + " KEY `region` (`region`,`time`)\n" - + ") ENGINE=InnoDB"; - - private final Sql2o sql2o; - private final CacheService cacheService; - - private final Cache keyCache = CacheBuilder.newBuilder() - .maximumSize(1024) - .build(); - - @Autowired - public XteaService( - @Qualifier("Runelite SQL2O") Sql2o sql2o, - CacheService cacheService - ) - { - this.sql2o = sql2o; - this.cacheService = cacheService; - - try (Connection con = sql2o.beginTransaction()) - { - con.createQuery(CREATE_SQL) - .executeUpdate(); - } - } - - private XteaEntry findLatestXtea(Connection con, int region) - { - return con.createQuery("select region, time, key1, key2, key3, key4 from xtea " - + "where region = :region " - + "order by time desc " - + "limit 1") - .addParameter("region", region) - .executeAndFetchFirst(XteaEntry.class); - } - - public void submit(XteaRequest xteaRequest) - { - boolean cached = true; - for (XteaKey key : xteaRequest.getKeys()) - { - int region = key.getRegion(); - int[] keys = key.getKeys(); - - if (keys.length != 4) - { - throw new IllegalArgumentException("Key length must be 4"); - } - - XteaCache xteaCache = keyCache.getIfPresent(region); - if (xteaCache == null - || xteaCache.getKey1() != keys[0] - || xteaCache.getKey2() != keys[1] - || xteaCache.getKey3() != keys[2] - || xteaCache.getKey4() != keys[3]) - { - cached = false; - keyCache.put(region, new XteaCache(region, keys[0], keys[1], keys[2], keys[3])); - } - } - - if (cached) - { - return; - } - - try (Connection con = sql2o.beginTransaction()) - { - CacheEntry cache = cacheService.findMostRecent(); - - if (cache == null) - { - throw new InternalServerErrorException("No most recent cache"); - } - - Query query = null; - - for (XteaKey key : xteaRequest.getKeys()) - { - int region = key.getRegion(); - int[] keys = key.getKeys(); - - XteaEntry xteaEntry = findLatestXtea(con, region); - - // already have these? - if (xteaEntry != null - && xteaEntry.getKey1() == keys[0] - && xteaEntry.getKey2() == keys[1] - && xteaEntry.getKey3() == keys[2] - && xteaEntry.getKey4() == keys[3]) - { - continue; - } - - ArchiveEntry archiveEntry = archiveForRegion(cache, region); - if (archiveEntry == null) - { - // the client sends 0,0,0,0 for non-existent regions, just ignore them - continue; - } - - if (!checkKeys(archiveEntry, keys)) - { - continue; - } - - if (query == null) - { - query = con.createQuery("insert into xtea (region, rev, key1, key2, key3, key4) " - + "values (:region, :rev, :key1, :key2, :key3, :key4)"); - } - - query.addParameter("region", region) - .addParameter("rev", xteaRequest.getRevision()) - .addParameter("key1", keys[0]) - .addParameter("key2", keys[1]) - .addParameter("key3", keys[2]) - .addParameter("key4", keys[3]) - .addToBatch(); - - log.debug("Inserted keys for {}: {}, {}, {}, {}", region, keys[0], keys[1], keys[2], keys[3]); - } - - if (query != null) - { - query.executeBatch(); - con.commit(false); - } - } - } - - public List get() - { - try (Connection con = sql2o.open()) - { - return con.createQuery( - "select t1.region, t2.time, t2.rev, t2.key1, t2.key2, t2.key3, t2.key4 from " + - "(select region,max(id) as id from xtea group by region) t1 " + - "join xtea t2 on t1.id = t2.id") - .executeAndFetch(XteaEntry.class); - } - } - - public XteaEntry getRegion(int region) - { - try (Connection con = sql2o.open()) - { - return con.createQuery("select region, time, rev, key1, key2, key3, key4 from xtea " - + "where region = :region order by time desc limit 1") - .addParameter("region", region) - .executeAndFetchFirst(XteaEntry.class); - } - } - - private ArchiveEntry archiveForRegion(CacheEntry cache, int regionId) - { - int x = regionId >>> 8; - int y = regionId & 0xFF; - - String archiveName = new StringBuilder() - .append('l') - .append(x) - .append('_') - .append(y) - .toString(); - int archiveNameHash = Djb2.hash(archiveName); - - return cacheService.findArchiveForTypeAndName(cache, IndexType.MAPS, archiveNameHash); - } - - private boolean checkKeys(ArchiveEntry archiveEntry, int[] keys) - { - byte[] data = cacheService.getArchive(archiveEntry); - if (data == null) - { - throw new InternalServerErrorException("Unable to get archive data for archive " + archiveEntry.getArchiveId()); - } - - try - { - Container.decompress(data, keys); - return true; - } - catch (IOException ex) - { - return false; - } - } -} diff --git a/http-service/src/main/resources/application-dev.yaml b/http-service/src/main/resources/application-dev.yaml deleted file mode 100644 index 2b24790c51..0000000000 --- a/http-service/src/main/resources/application-dev.yaml +++ /dev/null @@ -1,29 +0,0 @@ -# Enable debug logging -debug: true -logging.level.net.runelite: DEBUG - -# Development data sources -datasource: - runelite: - jndiName: - driverClassName: org.mariadb.jdbc.Driver - type: org.mariadb.jdbc.MariaDbDataSource - url: jdbc:mariadb://localhost:3306/runelite - username: runelite - password: runelite - runelite-cache: - jndiName: - driverClassName: org.mariadb.jdbc.Driver - type: org.mariadb.jdbc.MariaDbDataSource - url: jdbc:mariadb://localhost:3306/cache - username: runelite - password: runelite - -# Development mongo -mongo: - jndiName: - host: mongodb://localhost:27017 - -# Development oauth callback (without proxy) -oauth: - callback: http://localhost:8080/account/callback diff --git a/http-service/src/main/resources/application.yaml b/http-service/src/main/resources/application.yaml deleted file mode 100644 index 7431545cbb..0000000000 --- a/http-service/src/main/resources/application.yaml +++ /dev/null @@ -1,61 +0,0 @@ -datasource: - runelite: - jndiName: java:comp/env/jdbc/runelite - runelite-cache: - jndiName: java:comp/env/jdbc/runelite-cache2 - -# By default Spring tries to register the datasource as an MXBean, -# so if multiple apis are deployed on one web container with -# shared datasource it tries to register it multiples times and -# fails when starting the 2nd api -spring.jmx.enabled: false - -# Google OAuth client -oauth: - client-id: - client-secret: - callback: https://api.runelite.net/oauth/ - -# Minio client storage for cache -minio: - endpoint: http://localhost:9000 - accesskey: AM54M27O4WZK65N6F8IP - secretkey: /PZCxzmsJzwCHYlogcymuprniGCaaLUOET2n6yMP - bucket: runelite - -# Redis client -redis: - pool.size: 10 - host: tcp://localhost:6379 - -mongo: - jndiName: java:comp/env/mongodb/runelite - database: runelite - -runelite: - version: @project.version@ - commit: @git.commit.id.abbrev@ - dirty: @git.dirty@ - # Twitter client for feed - twitter: - consumerkey: - secretkey: - listid: 1185897074786742273 - ge: - history: 90 # days - loottracker: - history: 90 # days - wiki: - poll.ms: 300000 # 5 minutes - url: https://prices.runescape.wiki/api/v1/osrs/latest - price: - cache: 30 # minutes - feed: - rssUrl: https://runelite.net/atom.xml - worlds: - url: http://www.runescape.com/g=oldscape/slr.ws?order=LPWM - osrsnews: - rssUrl: https://services.runescape.com/m=news/latest_news.rss?oldschool=true - item: - itemUrl: https://services.runescape.com/m=itemdb_oldschool/api/catalogue/detail.json - priceUrl: https://services.runescape.com/m=itemdb_oldschool/api/graph \ No newline at end of file diff --git a/http-service/src/main/templates/markdown.hbs b/http-service/src/main/templates/markdown.hbs deleted file mode 100644 index 1beacd052a..0000000000 --- a/http-service/src/main/templates/markdown.hbs +++ /dev/null @@ -1,110 +0,0 @@ -{{#info}} -# {{title}} -{{join schemes " | "}}://{{host}}{{basePath}} - -{{description}} - -{{#contact}} -[**Contact the developer**](mailto:{{email}}) -{{/contact}} - -**Version** {{version}} - -{{#if termsOfService}} -[**Terms of Service**]({{termsOfService}}) -{{/if}} - -{{/info}} - -{{#if consumes}}__Consumes:__ {{join consumes ", "}}{{/if}} - -{{#if produces}}__Produces:__ {{join produces ", "}}{{/if}} - -{{#if securityDefinitions}} -# Security Definitions -{{> security}} -{{/if}} - -
-Table Of Contents -[toc] -
- -# APIs - -{{#each paths}} -## {{@key}} -{{#this}} -{{#get}} -### GET -{{> operation}} -{{/get}} - -{{#put}} -### PUT -{{> operation}} -{{/put}} - -{{#post}} -### POST - -{{> operation}} - -{{/post}} - -{{#delete}} -### DELETE -{{> operation}} -{{/delete}} - -{{#option}} -### OPTION -{{> operation}} -{{/option}} - -{{#patch}} -### PATCH -{{> operation}} -{{/patch}} - -{{#head}} -### HEAD -{{> operation}} -{{/head}} - -{{/this}} -{{/each}} - -# Definitions -{{#each definitions}} -## {{@key}} - - - - - - - - - - {{#each this.properties}} - - - - - - - - {{/each}} -
nametyperequireddescriptionexample
{{@key}} - {{#ifeq type "array"}} - {{#items.$ref}} - {{type}}[{{basename items.$ref}}] - {{/items.$ref}} - {{^items.$ref}}{{type}}[{{items.type}}]{{/items.$ref}} - {{else}} - {{#$ref}}{{basename $ref}}{{/$ref}} - {{^$ref}}{{type}}{{#format}} ({{format}}){{/format}}{{/$ref}} - {{/ifeq}} - {{#required}}required{{/required}}{{^required}}optional{{/required}}{{#description}}{{{description}}}{{/description}}{{^description}}-{{/description}}{{example}}
-{{/each}} diff --git a/http-service/src/main/templates/operation.hbs b/http-service/src/main/templates/operation.hbs deleted file mode 100644 index f7015850b8..0000000000 --- a/http-service/src/main/templates/operation.hbs +++ /dev/null @@ -1,71 +0,0 @@ -{{#deprecated}}-deprecated-{{/deprecated}} -{{summary}} - -{{description}} - -{{#if externalDocs.url}}{{externalDocs.description}}. [See external documents for more details]({{externalDocs.url}}) -{{/if}} - -{{#if security}} -#### Security -{{/if}} - -{{#security}} -{{#each this}} -* {{@key}} -{{#this}} * {{this}} -{{/this}} -{{/each}} -{{/security}} - -#### Request - -{{#if consumes}}__Content-Type:__ {{join consumes ", "}}{{/if}} - -##### Parameters -{{#if parameters}} - - - - - - - - - -{{/if}} - -{{#parameters}} - - - - - - -{{#ifeq in "body"}} - -{{else}} - {{#ifeq type "array"}} - - {{else}} - - {{/ifeq}} -{{/ifeq}} - -{{/parameters}} -{{#if parameters}} -
NameLocated inRequiredDescriptionDefaultSchema
{{name}}{{in}}{{#if required}}yes{{else}}no{{/if}}{{description}}{{#if pattern}} (**Pattern**: `{{pattern}}`){{/if}} - - {{#ifeq schema.type "array"}}Array[{{basename schema.items.$ref}}]{{/ifeq}} - {{#schema.$ref}}{{basename schema.$ref}} {{/schema.$ref}} - Array[{{items.type}}] ({{collectionFormat}}){{type}} {{#format}}({{format}}){{/format}}
-{{/if}} - - -#### Response - -{{#if produces}}__Content-Type:__ {{join produces ", "}}{{/if}} - -| Status Code | Reason | Response Model | -|-------------|-------------|----------------| -{{#each responses}}| {{@key}} | {{description}} | {{#schema.$ref}}{{basename schema.$ref}}{{/schema.$ref}}{{#ifeq schema.type "array"}}Array[{{basename schema.items.$ref}}]{{/ifeq}}{{^schema}} - {{/schema}}| -{{/each}} diff --git a/http-service/src/main/templates/security.hbs b/http-service/src/main/templates/security.hbs deleted file mode 100644 index 04f86e8380..0000000000 --- a/http-service/src/main/templates/security.hbs +++ /dev/null @@ -1,88 +0,0 @@ -{{#each securityDefinitions}} -### {{@key}} -{{#this}} -{{#ifeq type "oauth2"}} - - - - - -{{#if description}} - - - - -{{/if}} -{{#if authorizationUrl}} - - - - -{{/if}} -{{#if flow}} - - - - -{{/if}} -{{#if tokenUrl}} - - - - -{{/if}} -{{#if scopes}} - - -{{#each scopes}} - - - - -{{/each}} - -{{/if}} -
type{{type}}
description{{description}}
authorizationUrl{{authorizationUrl}}
flow{{flow}}
tokenUrl{{tokenUrl}}
scopes{{@key}}{{this}}
-{{/ifeq}} -{{#ifeq type "apiKey"}} - - - - - -{{#if description}} - - - - -{{/if}} -{{#if name}} - - - - -{{/if}} -{{#if in}} - - - - -{{/if}} -
type{{type}}
description{{description}}
name{{name}}
in{{in}}
-{{/ifeq}} -{{#ifeq type "basic"}} - - - - - -{{#if description}} - - - - -{{/if}} -
type{{type}}
description{{description}}
-{{/ifeq}} -{{/this}} -{{/each}} \ No newline at end of file diff --git a/http-service/src/main/templates/template.html.hbs b/http-service/src/main/templates/template.html.hbs deleted file mode 100644 index da587c2cc4..0000000000 --- a/http-service/src/main/templates/template.html.hbs +++ /dev/null @@ -1,49 +0,0 @@ - - - - - - - - - - - - - - - - - {{info.title}} {{info.version}} - - - - - \ No newline at end of file diff --git a/http-service/src/main/webapp/WEB-INF/web.xml b/http-service/src/main/webapp/WEB-INF/web.xml deleted file mode 100644 index 0b07dbb973..0000000000 --- a/http-service/src/main/webapp/WEB-INF/web.xml +++ /dev/null @@ -1,32 +0,0 @@ - - - - RuneLite API - \ No newline at end of file diff --git a/http-service/src/test/java/net/runelite/http/service/config/ConfigControllerTest.java b/http-service/src/test/java/net/runelite/http/service/config/ConfigControllerTest.java deleted file mode 100644 index 27320f3f72..0000000000 --- a/http-service/src/test/java/net/runelite/http/service/config/ConfigControllerTest.java +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright (c) 2019, Adam - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package net.runelite.http.service.config; - -import java.io.IOException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import net.runelite.http.service.account.AuthFilter; -import net.runelite.http.service.account.beans.SessionEntry; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import static org.mockito.Matchers.any; -import static org.mockito.Matchers.anyInt; -import static org.mockito.Matchers.anyString; -import static org.mockito.Matchers.eq; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; -import org.springframework.boot.test.mock.mockito.MockBean; -import org.springframework.http.MediaType; -import org.springframework.test.context.ActiveProfiles; -import org.springframework.test.context.junit4.SpringRunner; -import org.springframework.test.web.servlet.MockMvc; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; - -@RunWith(SpringRunner.class) -@WebMvcTest(ConfigController.class) -@ActiveProfiles("test") -public class ConfigControllerTest -{ - @Autowired - private MockMvc mockMvc; - - @MockBean - private ConfigService configService; - - @MockBean - private AuthFilter authFilter; - - @Before - public void before() throws IOException - { - when(authFilter.handle(any(HttpServletRequest.class), any(HttpServletResponse.class))) - .thenReturn(mock(SessionEntry.class)); - - when(configService.setKey(anyInt(), anyString(), anyString())).thenReturn(true); - } - - @Test - public void testSetKey() throws Exception - { - mockMvc.perform(put("/config/key") - .content("value") - .contentType(MediaType.TEXT_PLAIN)) - .andExpect(status().isOk()); - - verify(configService).setKey(anyInt(), eq("key"), eq("value")); - } -} \ No newline at end of file diff --git a/http-service/src/test/java/net/runelite/http/service/config/ConfigServiceTest.java b/http-service/src/test/java/net/runelite/http/service/config/ConfigServiceTest.java deleted file mode 100644 index a08a9a7160..0000000000 --- a/http-service/src/test/java/net/runelite/http/service/config/ConfigServiceTest.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright (c) 2019, Adam - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package net.runelite.http.service.config; - -import com.google.common.collect.ImmutableMap; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; -import org.junit.Test; - -public class ConfigServiceTest -{ - @Test - public void testParseJsonString() - { - assertEquals(1, ConfigService.parseJsonString("1")); - assertEquals(3.14, ConfigService.parseJsonString("3.14")); - assertEquals(1L << 32, ConfigService.parseJsonString("4294967296")); - assertEquals("test", ConfigService.parseJsonString("test")); - assertEquals("test", ConfigService.parseJsonString("\"test\"")); - assertEquals(ImmutableMap.of("key", "value"), ConfigService.parseJsonString("{\"key\": \"value\"}")); - } - - @Test - public void testValidateJson() - { - assertTrue(ConfigService.validateJson("1")); - assertTrue(ConfigService.validateJson("3.14")); - assertTrue(ConfigService.validateJson("test")); - assertTrue(ConfigService.validateJson("\"test\"")); - assertTrue(ConfigService.validateJson("key:value")); - assertTrue(ConfigService.validateJson("{\"key\": \"value\"}")); - assertTrue(ConfigService.validateJson("\n")); - } - - @Test - public void testMaybeJson() - { - assertFalse(ConfigService.isMaybeJson("string")); - assertFalse(ConfigService.isMaybeJson("string with spaces")); - - assertTrue(ConfigService.isMaybeJson("true")); - assertTrue(ConfigService.isMaybeJson("false")); - assertTrue(ConfigService.isMaybeJson("1")); - assertTrue(ConfigService.isMaybeJson("1.2")); - assertTrue(ConfigService.isMaybeJson("\"quote\"")); - assertTrue(ConfigService.isMaybeJson("{\"key\": \"value\"}")); - assertTrue(ConfigService.isMaybeJson("[42]")); - } -} \ No newline at end of file diff --git a/http-service/src/test/java/net/runelite/http/service/loottracker/LootTrackerControllerTest.java b/http-service/src/test/java/net/runelite/http/service/loottracker/LootTrackerControllerTest.java deleted file mode 100644 index 68e64270d6..0000000000 --- a/http-service/src/test/java/net/runelite/http/service/loottracker/LootTrackerControllerTest.java +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Copyright (c) 2019, Adam - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package net.runelite.http.service.loottracker; - -import java.io.IOException; -import java.time.Instant; -import java.time.temporal.ChronoField; -import java.util.Collections; -import java.util.UUID; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import net.runelite.http.api.RuneLiteAPI; -import net.runelite.http.api.loottracker.GameItem; -import net.runelite.http.api.loottracker.LootRecord; -import net.runelite.http.api.loottracker.LootRecordType; -import net.runelite.http.service.account.AuthFilter; -import net.runelite.http.service.account.beans.SessionEntry; -import net.runelite.http.service.util.redis.RedisPool; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import static org.mockito.Matchers.any; -import static org.mockito.Matchers.anyInt; -import static org.mockito.Matchers.eq; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; -import org.springframework.boot.test.mock.mockito.MockBean; -import org.springframework.http.MediaType; -import org.springframework.test.context.ActiveProfiles; -import org.springframework.test.context.junit4.SpringRunner; -import org.springframework.test.web.servlet.MockMvc; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; -import redis.clients.jedis.Jedis; - -@RunWith(SpringRunner.class) -@WebMvcTest(LootTrackerController.class) -@ActiveProfiles("test") -public class LootTrackerControllerTest -{ - @Autowired - private MockMvc mockMvc; - - @MockBean - private LootTrackerService lootTrackerService; - - @MockBean - private AuthFilter authFilter; - - @MockBean - private RedisPool redisPool; - - @Before - public void before() throws IOException - { - when(authFilter.handle(any(HttpServletRequest.class), any(HttpServletResponse.class))) - .thenReturn(mock(SessionEntry.class)); - - when(redisPool.getResource()).thenReturn(mock(Jedis.class)); - } - - @Test - public void storeLootRecord() throws Exception - { - LootRecord lootRecord = new LootRecord(); - lootRecord.setType(LootRecordType.NPC); - lootRecord.setTime(Instant.now().with(ChronoField.NANO_OF_SECOND, 0)); - lootRecord.setDrops(Collections.singletonList(new GameItem(4151, 1))); - - String data = RuneLiteAPI.GSON.toJson(Collections.singletonList(lootRecord)); - mockMvc.perform(post("/loottracker") - .header(RuneLiteAPI.RUNELITE_AUTH, UUID.nameUUIDFromBytes("test".getBytes())) - .content(data) - .contentType(MediaType.APPLICATION_JSON)) - .andExpect(status().isOk()); - - verify(lootTrackerService).store(eq(Collections.singletonList(lootRecord)), anyInt()); - } -} \ No newline at end of file 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 deleted file mode 100644 index b6275d7c48..0000000000 --- a/http-service/src/test/java/net/runelite/http/service/worlds/WorldsServiceTest.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * 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 net.runelite.http.api.worlds.World; -import net.runelite.http.api.worlds.WorldResult; -import net.runelite.http.api.worlds.WorldType; -import okhttp3.OkHttpClient; -import okhttp3.mockwebserver.MockResponse; -import okhttp3.mockwebserver.MockWebServer; -import okio.Buffer; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.sql2o.tools.IOUtils; - -public class WorldsServiceTest -{ - @Rule - public final MockWebServer server = new MockWebServer(); - - @Before - public void before() throws IOException - { - InputStream in = WorldsServiceTest.class.getResourceAsStream("worldlist"); - byte[] worldData = IOUtils.toByteArray(in); - - Buffer buffer = new Buffer(); - buffer.write(worldData); - - server.enqueue(new MockResponse().setBody(buffer)); - } - - @Test - public void testListWorlds() throws Exception - { - WorldsService worlds = new WorldsService(new OkHttpClient(), server.url("/").toString()); - - WorldResult worldResult = worlds.getWorlds(); - assertEquals(82, worldResult.getWorlds().size()); - - World world = worldResult.findWorld(385); - assertNotNull(world); - assertTrue(world.getTypes().contains(WorldType.SKILL_TOTAL)); - - for (World testWorld : worldResult.getWorlds()) - { - assertNotNull("Missing a region in WorldRegion enum", testWorld.getRegion()); - } - } - -} diff --git a/http-service/src/test/resources/application-test.yaml b/http-service/src/test/resources/application-test.yaml deleted file mode 100644 index 3a8e416a54..0000000000 --- a/http-service/src/test/resources/application-test.yaml +++ /dev/null @@ -1,21 +0,0 @@ -# Use in-memory database for tests -datasource: - runelite: - jndiName: - driverClassName: org.h2.Driver - type: org.h2.jdbcx.JdbcDataSource - url: jdbc:h2:mem:runelite - runelite-cache: - jndiName: - driverClassName: org.h2.Driver - type: org.h2.jdbcx.JdbcDataSource - url: jdbc:h2:mem:cache - runelite-tracker: - jndiName: - driverClassName: org.h2.Driver - type: org.h2.jdbcx.JdbcDataSource - url: jdbc:h2:mem:xptracker - -mongo: - jndiName: - host: mongodb://localhost:27017 \ No newline at end of file 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 deleted file mode 100644 index 1d1360e5795d066b068e095cf2a033a504405ad6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 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