From 9cb646608e7913a31501c6bf904aa3b6c784e09c Mon Sep 17 00:00:00 2001
From: Andre601 <11576465+Andre601@users.noreply.github.com>
Date: Thu, 16 Jul 2020 00:28:58 +0200
Subject: [PATCH 001/232] First major work on 6.0.0
---
build.gradle | 22 ++
core/build.gradle | 3 +
.../javabotblockapi/core}/BotBlockAPI.java | 55 ++--
.../botblock/javabotblockapi/core}/Site.java | 33 +-
.../core}/annotations/DeprecatedSince.java | 4 +-
.../core}/annotations/PlannedRemoval.java | 4 +-
.../core}/annotations/package-info.java | 2 +-
.../exceptions/RatelimitedException.java | 2 +-
.../core}/exceptions/package-info.java | 2 +-
.../core}/requests/CheckUtil.java | 3 +-
jda-module/build.gradle | 14 +
.../javabotblockapi/jda/PostAction.java | 211 +++++++++++++
request-module/build.gradle | 7 +
.../requests/GetBotAction.java | 22 +-
.../requests/GetListAction.java | 120 +++----
.../javabotblockapi/requests/PostAction.java | 173 +++++++++++
.../requests/handler}/RequestHandler.java | 47 +--
settings.gradle | 3 +
.../javabotblockapi/package-info.java | 23 --
.../javabotblockapi/requests/PostAction.java | 292 ------------------
.../requests/package-info.java | 26 --
src/main/resources/JavaBotBlockAPI.png | Bin 56517 -> 0 bytes
src/main/resources/Jbba.png | Bin 72918 -> 0 bytes
23 files changed, 578 insertions(+), 490 deletions(-)
create mode 100644 core/build.gradle
rename {src/main/java/org/botblock/javabotblockapi => core/src/main/java/org/botblock/javabotblockapi/core}/BotBlockAPI.java (90%)
rename {src/main/java/org/botblock/javabotblockapi => core/src/main/java/org/botblock/javabotblockapi/core}/Site.java (89%)
rename {src/main/java/org/botblock/javabotblockapi => core/src/main/java/org/botblock/javabotblockapi/core}/annotations/DeprecatedSince.java (93%)
rename {src/main/java/org/botblock/javabotblockapi => core/src/main/java/org/botblock/javabotblockapi/core}/annotations/PlannedRemoval.java (89%)
rename {src/main/java/org/botblock/javabotblockapi => core/src/main/java/org/botblock/javabotblockapi/core}/annotations/package-info.java (95%)
rename {src/main/java/org/botblock/javabotblockapi => core/src/main/java/org/botblock/javabotblockapi/core}/exceptions/RatelimitedException.java (98%)
rename {src/main/java/org/botblock/javabotblockapi => core/src/main/java/org/botblock/javabotblockapi/core}/exceptions/package-info.java (95%)
rename {src/main/java/org/botblock/javabotblockapi => core/src/main/java/org/botblock/javabotblockapi/core}/requests/CheckUtil.java (96%)
create mode 100644 jda-module/build.gradle
create mode 100644 jda-module/src/main/java/org/botblock/javabotblockapi/jda/PostAction.java
create mode 100644 request-module/build.gradle
rename {src => request-module/src}/main/java/org/botblock/javabotblockapi/requests/GetBotAction.java (97%)
rename {src => request-module/src}/main/java/org/botblock/javabotblockapi/requests/GetListAction.java (87%)
create mode 100644 request-module/src/main/java/org/botblock/javabotblockapi/requests/PostAction.java
rename {src/main/java/org/botblock/javabotblockapi/requests => request-module/src/main/java/org/botblock/javabotblockapi/requests/handler}/RequestHandler.java (85%)
delete mode 100644 src/main/java/org/botblock/javabotblockapi/package-info.java
delete mode 100644 src/main/java/org/botblock/javabotblockapi/requests/PostAction.java
delete mode 100644 src/main/java/org/botblock/javabotblockapi/requests/package-info.java
delete mode 100644 src/main/resources/JavaBotBlockAPI.png
delete mode 100644 src/main/resources/Jbba.png
diff --git a/build.gradle b/build.gradle
index 126b0788..b425fbff 100644
--- a/build.gradle
+++ b/build.gradle
@@ -11,6 +11,28 @@ plugins{
def ver = new Version(major: 5, minor: 2, revision: 3)
+allprojects {
+ apply plugin: 'com.jfrog.bintray'
+ apply plugin: 'maven-publish'
+ apply plugin: 'java-library'
+ apply plugin: 'com.github.johnrengelman.shadow'
+
+ group = "org.botblock"
+ version = "$ver"
+
+ repositories {
+ mavenCentral()
+ jcenter()
+ }
+
+ dependencies {
+ api group: 'com.squareup.okhttp3', name: 'okhttp', version: '4.7.2'
+ api group: 'org.json', name: 'json', version: '20200518'
+ api group: 'com.github.ben-manes.caffeine', name: 'caffeine', version: '2.8.0'
+ api group: 'com.google.code.findbugs', name: 'jsr305', version: '3.0.2'
+ }
+}
+
group = "org.botblock"
version = "$ver"
diff --git a/core/build.gradle b/core/build.gradle
new file mode 100644
index 00000000..075ba3d5
--- /dev/null
+++ b/core/build.gradle
@@ -0,0 +1,3 @@
+plugins {
+ id 'java'
+}
diff --git a/src/main/java/org/botblock/javabotblockapi/BotBlockAPI.java b/core/src/main/java/org/botblock/javabotblockapi/core/BotBlockAPI.java
similarity index 90%
rename from src/main/java/org/botblock/javabotblockapi/BotBlockAPI.java
rename to core/src/main/java/org/botblock/javabotblockapi/core/BotBlockAPI.java
index 84999e39..fd9f344c 100644
--- a/src/main/java/org/botblock/javabotblockapi/BotBlockAPI.java
+++ b/core/src/main/java/org/botblock/javabotblockapi/core/BotBlockAPI.java
@@ -15,10 +15,10 @@
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
-package org.botblock.javabotblockapi;
-import org.botblock.javabotblockapi.requests.CheckUtil;
-import org.botblock.javabotblockapi.requests.PostAction;
+package org.botblock.javabotblockapi.core;
+
+import org.botblock.javabotblockapi.core.requests.CheckUtil;
import javax.annotation.Nonnull;
import java.util.HashMap;
@@ -26,13 +26,12 @@
/**
* Class used to define the auth-tokens used for the different sites.
- *
The instance of this class will be used in the {@link PostAction PostAction} class.
- *
- *
Use the {@link org.botblock.javabotblockapi.BotBlockAPI.Builder BotBlockAPI.Builder} class for easy creation. + * + *
Use the {@link org.botblock.javabotblockapi.core.BotBlockAPI.Builder BotBlockAPI.Builder} class for easy creation.
*/
public class BotBlockAPI{
public static final int DEFAULT_DELAY = 30;
-
+
private final Map The fields can be used in:
- * A replacement may be mentioned with the {@link #replacements() replacements String array} but is not guaranteed.
* This annotation will always contain {@link #version() the version} in which the annotated Object will be removed.
diff --git a/src/main/java/org/botblock/javabotblockapi/annotations/package-info.java b/core/src/main/java/org/botblock/javabotblockapi/core/annotations/package-info.java
similarity index 95%
rename from src/main/java/org/botblock/javabotblockapi/annotations/package-info.java
rename to core/src/main/java/org/botblock/javabotblockapi/core/annotations/package-info.java
index fc438ccf..0f34e24c 100644
--- a/src/main/java/org/botblock/javabotblockapi/annotations/package-info.java
+++ b/core/src/main/java/org/botblock/javabotblockapi/core/annotations/package-info.java
@@ -19,4 +19,4 @@
/**
* The different annotations used to mark various Objects with it.
*/
-package org.botblock.javabotblockapi.annotations;
\ No newline at end of file
+package org.botblock.javabotblockapi.core.annotations;
\ No newline at end of file
diff --git a/src/main/java/org/botblock/javabotblockapi/exceptions/RatelimitedException.java b/core/src/main/java/org/botblock/javabotblockapi/core/exceptions/RatelimitedException.java
similarity index 98%
rename from src/main/java/org/botblock/javabotblockapi/exceptions/RatelimitedException.java
rename to core/src/main/java/org/botblock/javabotblockapi/core/exceptions/RatelimitedException.java
index 8e2914b0..0e11728f 100644
--- a/src/main/java/org/botblock/javabotblockapi/exceptions/RatelimitedException.java
+++ b/core/src/main/java/org/botblock/javabotblockapi/core/exceptions/RatelimitedException.java
@@ -15,7 +15,7 @@
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
-package org.botblock.javabotblockapi.exceptions;
+package org.botblock.javabotblockapi.core.exceptions;
import org.json.JSONObject;
diff --git a/src/main/java/org/botblock/javabotblockapi/exceptions/package-info.java b/core/src/main/java/org/botblock/javabotblockapi/core/exceptions/package-info.java
similarity index 95%
rename from src/main/java/org/botblock/javabotblockapi/exceptions/package-info.java
rename to core/src/main/java/org/botblock/javabotblockapi/core/exceptions/package-info.java
index caf915c5..baf12441 100644
--- a/src/main/java/org/botblock/javabotblockapi/exceptions/package-info.java
+++ b/core/src/main/java/org/botblock/javabotblockapi/core/exceptions/package-info.java
@@ -19,4 +19,4 @@
/**
* Contsins custom exceptions this API may throw.
*/
-package org.botblock.javabotblockapi.exceptions;
\ No newline at end of file
+package org.botblock.javabotblockapi.core.exceptions;
\ No newline at end of file
diff --git a/src/main/java/org/botblock/javabotblockapi/requests/CheckUtil.java b/core/src/main/java/org/botblock/javabotblockapi/core/requests/CheckUtil.java
similarity index 96%
rename from src/main/java/org/botblock/javabotblockapi/requests/CheckUtil.java
rename to core/src/main/java/org/botblock/javabotblockapi/core/requests/CheckUtil.java
index 898252f3..d0fd87c8 100644
--- a/src/main/java/org/botblock/javabotblockapi/requests/CheckUtil.java
+++ b/core/src/main/java/org/botblock/javabotblockapi/core/requests/CheckUtil.java
@@ -16,7 +16,7 @@
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
-package org.botblock.javabotblockapi.requests;
+package org.botblock.javabotblockapi.core.requests;
import java.util.Map;
@@ -36,5 +36,4 @@ public static void condition(boolean check, String message){
if(check)
throw new IllegalStateException(message);
}
-
}
diff --git a/jda-module/build.gradle b/jda-module/build.gradle
new file mode 100644
index 00000000..01135e00
--- /dev/null
+++ b/jda-module/build.gradle
@@ -0,0 +1,14 @@
+plugins {
+ id 'java'
+}
+
+group 'org.botblock'
+version '5.2.3'
+
+dependencies {
+ api(group: 'net.dv8tion', name: 'JDA', version: '4.2.0_172'){
+ exclude(module: 'opus-java')
+ }
+ implementation project(":core")
+ implementation project(":request-module")
+}
diff --git a/jda-module/src/main/java/org/botblock/javabotblockapi/jda/PostAction.java b/jda-module/src/main/java/org/botblock/javabotblockapi/jda/PostAction.java
new file mode 100644
index 00000000..35825491
--- /dev/null
+++ b/jda-module/src/main/java/org/botblock/javabotblockapi/jda/PostAction.java
@@ -0,0 +1,211 @@
+/*
+ * Copyright 2019 - 2020 Andre601
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
+ * documentation files (the "Software"), to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all copies or substantial
+ * portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+ * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
+ * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+package org.botblock.javabotblockapi.jda;
+
+import net.dv8tion.jda.api.JDA;
+import net.dv8tion.jda.api.sharding.ShardManager;
+import org.botblock.javabotblockapi.core.BotBlockAPI;
+import org.botblock.javabotblockapi.core.exceptions.RatelimitedException;
+import org.botblock.javabotblockapi.core.requests.CheckUtil;
+import org.botblock.javabotblockapi.requests.handler.RequestHandler;
+import org.json.JSONArray;
+import org.json.JSONObject;
+
+import javax.annotation.Nonnull;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Objects;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * This class is used to perform POST requests towards the BotBlock API using the Java Discord Library (JDA).
+ * If the post can't be performed - either by getting a {@link org.botblock.javabotblockapi.core.exceptions.RatelimitedException RatelimitedException}
+ * or by getting an {@link java.io.IOException IOException} - will the exception be catched and the stacktrace printed.
+ *
+ * The scheduler will wait an initial delay of 1 minute and then performs a task every n minutes, where n is the
+ * time set in {@link org.botblock.javabotblockapi.core.BotBlockAPI.Builder#setUpdateDelay(Integer) BotBlockAPI.Builder.setUpdateDelay(Integer)}
+ * (default is 30 minutes).
+ *
+ * If you have a sharded bot is it recommendet to use {@link #enableAutoPost(ShardManager, BotBlockAPI) enableAutoPost(ShardManager, BotBlockAPI)} instead.
+ *
+ * @param jda
+ * The {@link net.dv8tion.jda.api.JDA JDA instance} to post stats from.
+ * @param botBlockAPI
+ * The {@link org.botblock.javabotblockapi.core.BotBlockAPI BotBlockAPI instance} to use.
+ */
+ public void enableAutoPost(@Nonnull JDA jda, @Nonnull BotBlockAPI botBlockAPI){
+ scheduler.scheduleAtFixedRate(() -> {
+ try{
+ postGuilds(jda, botBlockAPI);
+ }catch(IOException | RatelimitedException ex){
+ ex.printStackTrace();
+ }
+ }, 1, botBlockAPI.getUpdateDelay(), TimeUnit.MINUTES);
+ }
+
+ /**
+ * Starts a {@link java.util.concurrent.ScheduledExecutorService#scheduleAtFixedRate(Runnable, long, long, TimeUnit) scheduleAtFixedRate}
+ * task, which will post the statistics of the provided {@link net.dv8tion.jda.api.sharding.ShardManager ShardManager instance} every n minutes.
+ *
+ * If the post can't be performed - either by getting a {@link org.botblock.javabotblockapi.core.exceptions.RatelimitedException RatelimitedException}
+ * or by getting an {@link java.io.IOException IOException} - will the exception be catched and the stacktrace printed.
+ *
+ * The scheduler will wait an initial delay of 1 minute and then performs a task every n minutes, where n is the
+ * time set in {@link org.botblock.javabotblockapi.core.BotBlockAPI.Builder#setUpdateDelay(Integer) BotBlockAPI.Builder.setUpdateDelay(Integer)}
+ * (default is 30 minutes).
+ *
+ * @param shardManager
+ * The {@link net.dv8tion.jda.api.sharding.ShardManager ShardManager instance} to post stats from.
+ * @param botBlockAPI
+ * The {@link org.botblock.javabotblockapi.core.BotBlockAPI BotBlockAPI instance} to use.
+ */
+ public void enableAutoPost(@Nonnull ShardManager shardManager, @Nonnull BotBlockAPI botBlockAPI){
+ scheduler.scheduleAtFixedRate(() -> {
+ try{
+ postGuilds(shardManager, botBlockAPI);
+ }catch(IOException | RatelimitedException ex){
+ ex.printStackTrace();
+ }
+ }, botBlockAPI.getUpdateDelay(), botBlockAPI.getUpdateDelay(), TimeUnit.MINUTES);
+ }
+
+ /**
+ * Performs a POST request towards the BotBlock API using the information from the provided
+ * {@link net.dv8tion.jda.api.JDA JDA} and {@link org.botblock.javabotblockapi.core.BotBlockAPI BotBlockAPI} instances.
+ *
+ * If the provided JDA instance also is part of a sharded Bot (Amount of shards is larger than 1) will the request
+ * also include {@code shard_id} and {@code shard_count}
+ *
+ * @param jda
+ * The {@link net.dv8tion.jda.api.JDA JDA instance} to post stats from.
+ * @param botBlockAPI
+ * The {@link org.botblock.javabotblockapi.core.BotBlockAPI BotBlockAPI instance} to use.
+ *
+ * @throws java.io.IOException
+ * When the POST request wasn't successfull.
+ * @throws org.botblock.javabotblockapi.core.exceptions.RatelimitedException
+ * When we get rate limited by the BotBlock API (returns error code 429).
+ */
+ public void postGuilds(@Nonnull JDA jda, @Nonnull BotBlockAPI botBlockAPI) throws IOException, RatelimitedException{
+ JSONObject json = new JSONObject()
+ .put("server_count", jda.getGuildCache().size())
+ .put("bot_id", jda.getSelfUser().getId());
+
+ if(jda.getShardInfo().getShardTotal() > 1)
+ json.put("shard_id", jda.getShardInfo().getShardId())
+ .put("shard_count", jda.getShardInfo().getShardTotal());
+
+ botBlockAPI.getTokens().forEach(json::put);
+
+ requestHandler.performPOST(json, botBlockAPI.getTokens().size());
+ }
+
+ /**
+ * Performs a POST request towards the BotBlock API using the information from the provided
+ * {@link net.dv8tion.jda.api.JDA JDA} and {@link org.botblock.javabotblockapi.core.BotBlockAPI BotBlockAPI} instances.
+ *
+ * If the provided JDA instance also is part of a sharded Bot (Amount of shards is larger than 1) will the request
+ * also include {@code shard_id} and {@code shard_count}
+ *
+ * @param shardManager
+ * The {@link net.dv8tion.jda.api.sharding.ShardManager ShardManager instance} to post stats from.
+ * @param botBlockAPI
+ * The {@link org.botblock.javabotblockapi.core.BotBlockAPI BotBlockAPI instance} to use.
+ *
+ * @throws java.lang.IllegalStateException
+ * When the first shard (id 0) of the provided ShardManager is null.
+ * @throws java.io.IOException
+ * When the POST request wasn't successfull.
+ * @throws org.botblock.javabotblockapi.core.exceptions.RatelimitedException
+ * When we get rate limited by the BotBlock API (returns error code 429).
+ */
+ public void postGuilds(@Nonnull ShardManager shardManager, @Nonnull BotBlockAPI botBlockAPI) throws IOException, RatelimitedException{
+ JDA shard = shardManager.getShardById(0);
+ CheckUtil.condition(shard == null, "Received invalid/null Shard (Shard ID: 0)");
+
+ JSONObject json = new JSONObject()
+ .put("server_count", shardManager.getGuildCache().size())
+ .put("bot_id", shard.getSelfUser().getId())
+ .put("shard_count", shardManager.getShardCache().size());
+
+ List GET requests are cached for 2 minutes unless disabled through {@link #GetListAction(boolean, String) GetListAction(true, String)}
* or {@link #GetListAction(boolean, String, String) GetListAction(true, String, String)}.
- *
+ *
* @since 5.0.0
*/
public class GetListAction{
@@ -41,13 +43,13 @@ public class GetListAction{
/**
* Constructor to get an instance of GetListAction.
- *
+ *
* Using this constructor will set the following default values:
* Using this constructor will set the following default values:
* Note that you can provide {@code {id}} inside the userAgent to get it replaced with the provided id.
*
* @param disableCache
@@ -108,14 +110,14 @@ public GetListAction(boolean disableCache, @Nonnull String userAgent, @Nonnull S
/**
* Gets the name of the specified field. The returned String can either be a URL or a field name.
- *
+ *
* @param id
* The id used for the cache.
* @param site
- * The {@link org.botblock.javabotblockapi.Site site} to get information from.
+ * The {@link org.botblock.javabotblockapi.core.Site site} to get information from.
* @param field
* The {@link org.botblock.javabotblockapi.requests.GetListAction.ApiField API field} to get the value from.
- *
+ *
* @return Possibly-null String containing either a URL or API field name.
*/
@Nullable
@@ -132,10 +134,10 @@ public String getApiField(@Nonnull String id, @Nonnull Site site, @Nonnull ApiFi
* @param id
* The id used for the cache.
* @param site
- * The {@link org.botblock.javabotblockapi.Site site} to get information from.
+ * The {@link org.botblock.javabotblockapi.core.Site site} to get information from.
* @param field
* The {@link org.botblock.javabotblockapi.requests.GetListAction.ApiField API field} to get the value from.
- *
+ *
* @return Possibly-null String containing either a URL or API field name.
*/
@Nullable
@@ -153,8 +155,8 @@ public String getApiField(@Nonnull String id, @Nonnull String site, @Nonnull Api
* @param id
* The id used for the cache.
* @param site
- * The {@link org.botblock.javabotblockapi.Site site} to get information from.
- *
+ * The {@link org.botblock.javabotblockapi.core.Site site} to get information from.
+ *
* @return Possibly-null String containing the URL used to display a widget.
*/
@Nullable
@@ -171,7 +173,7 @@ public String getBotWidgetUrl(@Nonnull String id, @Nonnull Site site){
* @param id
* The id used for the cache.
* @param site
- * The {@link org.botblock.javabotblockapi.Site site} to get information from.
+ * The {@link org.botblock.javabotblockapi.core.Site site} to get information from.
*
* @return Possibly-null String containing the URL used to display a widget.
*/
@@ -186,12 +188,12 @@ public String getBotWidgetUrl(@Nonnull String id, @Nonnull String site){
/**
* Gets the description of the bot list.
- *
+ *
* @param id
* The id used for the cache.
* @param site
- * The {@link org.botblock.javabotblockapi.Site site} to get information from.
- *
+ * The {@link org.botblock.javabotblockapi.core.Site site} to get information from.
+ *
* @return Possibly-null String containing the description/tag line of the bot list.
*/
@Nullable
@@ -208,7 +210,7 @@ public String getDescription(@Nonnull String id, @Nonnull Site site){
* @param id
* The id used for the cache.
* @param site
- * The {@link org.botblock.javabotblockapi.Site site} to get information from.
+ * The {@link org.botblock.javabotblockapi.core.Site site} to get information from.
*
* @return Possibly-null String containing the description/tag line of the bot list.
*/
@@ -227,7 +229,7 @@ public String getDescription(@Nonnull String id, @Nonnull String site){
* @param id
* The id used for the cache.
* @param site
- * The {@link org.botblock.javabotblockapi.Site site} to get information from.
+ * The {@link org.botblock.javabotblockapi.core.Site site} to get information from.
*
* @return Possibly-null String containing the invite to the Discord of the bot list.
*/
@@ -245,7 +247,7 @@ public String getDiscordInvite(@Nonnull String id, @Nonnull Site site){
* @param id
* The id used for the cache.
* @param site
- * The {@link org.botblock.javabotblockapi.Site site} to get information from.
+ * The {@link org.botblock.javabotblockapi.core.Site site} to get information from.
*
* @return Possibly-null String containing the invite to the Discord of the bot list.
*/
@@ -265,7 +267,7 @@ public String getDiscordInvite(@Nonnull String id, @Nonnull String site){
* @param id
* The id used for the cache.
* @param site
- * The {@link org.botblock.javabotblockapi.Site site} to get information from.
+ * The {@link org.botblock.javabotblockapi.core.Site site} to get information from.
*
* @return Possibly-empty {@link org.json.JSONArray JSONArray} containing the features of the bot list.
*/
@@ -283,7 +285,7 @@ public JSONArray getFeatures(@Nonnull String id, @Nonnull Site site){
* @param id
* The id used for the cache.
* @param site
- * The {@link org.botblock.javabotblockapi.Site site} to get information from.
+ * The {@link org.botblock.javabotblockapi.core.Site site} to get information from.
*
* @return Possibly-empty {@link org.json.JSONArray JSONArray} containing the features of the bot list.
*/
@@ -316,7 +318,7 @@ public JSONObject getFilteredLists(@Nonnull String id){
* @param id
* The id used for the cache.
* @param site
- * The {@link org.botblock.javabotblockapi.Site site} to get information from.
+ * The {@link org.botblock.javabotblockapi.core.Site site} to get information from.
*
* @return Possibly-null String containing the Icon-URL of the bot list.
*/
@@ -324,7 +326,7 @@ public JSONObject getFilteredLists(@Nonnull String id){
public String getIcon(@Nonnull String id, @Nonnull Site site){
CheckUtil.notEmpty(id, "id");
JSONObject json = getList(id, site);
-
+
return json.getString("icon");
}
@@ -334,7 +336,7 @@ public String getIcon(@Nonnull String id, @Nonnull Site site){
* @param id
* The id used for the cache.
* @param site
- * The {@link org.botblock.javabotblockapi.Site site} to get information from.
+ * The {@link org.botblock.javabotblockapi.core.Site site} to get information from.
*
* @return Possibly-null String containing the Icon-URL of the bot list.
*/
@@ -354,7 +356,7 @@ public String getIcon(@Nonnull String id, @Nonnull String site){
* @param id
* The id used for the cache.
* @param site
- * The {@link org.botblock.javabotblockapi.Site site} to get information from.
+ * The {@link org.botblock.javabotblockapi.core.Site site} to get information from.
*
* @return String containing the id of the bot list.
*/
@@ -368,12 +370,12 @@ public String getId(@Nonnull String id, @Nonnull Site site){
/**
* Gets the id of the bot list.
* Using this constructor will set the following default values:
+ * Note that you can provide {@code {id}} inside the userAgent to get it replaced with the provided id.
+ *
+ * @param userAgent
+ * The Name to use as User-Agent.
+ * @param id
+ * The id of the bot. This is required for the internal User-Agent.
+ *
+ * @throws NullPointerException
+ * When the provided userAgent or id is empty.
+ */
+ public PostAction(@Nonnull String userAgent, @Nonnull String id){
+ CheckUtil.notEmpty(userAgent, "UserAgent");
+ CheckUtil.notEmpty(id, "ID");
+
+ this.REQUEST_HANDLER = new RequestHandler(userAgent.replace("{id}", id));
+ }
+
+ /**
+ * Shuts down the scheduler, to stop the automatic posting.
+ */
+ public void disableAutoPost(){
+ scheduler.shutdown();
+ }
+
+ /**
+ * Starts posting of the guild count each n minutes.
+ * The scheduler will stop (cancel) the task, when an Exception appears!
+ *
+ * @param botId
+ * The ID of the bot as Long.
+ * @param guilds
+ * The guild count.
+ * @param botBlockAPI
+ * The {@link org.botblock.javabotblockapi.core.BotBlockAPI BotBlockAPI instance} to use.
+ */
+ public void enableAutoPost(@Nonnull Long botId, int guilds, @Nonnull BotBlockAPI botBlockAPI){
+ scheduler.scheduleAtFixedRate(() -> {
+ try{
+ postGuilds(botId, guilds, botBlockAPI);
+ }catch(IOException | RatelimitedException ex){
+ ex.printStackTrace();
+ }
+ }, botBlockAPI.getUpdateDelay(), botBlockAPI.getUpdateDelay(), TimeUnit.MINUTES);
+ }
+
+ /**
+ * Starts posting of the guild count each n minutes.
+ * The scheduler will stop (cancel) the task, when an Exception appears!
+ *
+ * @param botId
+ * The ID of the bot as String.
+ * @param guilds
+ * The guild count.
+ * @param botBlockAPI
+ * The {@link org.botblock.javabotblockapi.core.BotBlockAPI BotBlockAPI instance} to use.
+ */
+ public void enableAutoPost(@Nonnull String botId, int guilds, @Nonnull BotBlockAPI botBlockAPI){
+ scheduler.scheduleAtFixedRate(() -> {
+ try{
+ postGuilds(botId, guilds, botBlockAPI);
+ }catch(IOException | RatelimitedException ex){
+ ex.printStackTrace();
+ }
+ }, botBlockAPI.getUpdateDelay(), botBlockAPI.getUpdateDelay(), TimeUnit.MINUTES);
+ }
+
+ /**
+ * Posts the guild count with the provided bot id.
+ *
+ * @param botId
+ * The ID of the bot.
+ * @param guilds
+ * The guild count.
+ * @param botBlockAPI
+ * The {@link org.botblock.javabotblockapi.core.BotBlockAPI BotBlockAPI instance}.
+ *
+ * @throws IOException
+ * When the post request couldn't be performed.
+ * @throws org.botblock.javabotblockapi.core.exceptions.RatelimitedException
+ * When we exceed the rate-limit of the BotBlock API.
+ */
+ public void postGuilds(@Nonnull Long botId, @Nonnull Integer guilds, @Nonnull BotBlockAPI botBlockAPI) throws IOException, RatelimitedException{
+ postGuilds(Long.toString(botId), guilds, botBlockAPI);
+ }
+
+ /**
+ * Posts the guild count with the provided bot id.
+ *
+ * @param botId
+ * The ID of the bot.
+ * @param guilds
+ * The guild count.
+ * @param botBlockAPI
+ * The {@link org.botblock.javabotblockapi.core.BotBlockAPI BotBlockAPI instance}.
+ *
+ * @throws IOException
+ * When the post request couldn't be performed.
+ * @throws org.botblock.javabotblockapi.core.exceptions.RatelimitedException
+ * When we exceed the rate-limit of the BotBlock API.
+ */
+ public void postGuilds(@Nonnull String botId, @Nonnull Integer guilds, @Nonnull BotBlockAPI botBlockAPI) throws IOException, RatelimitedException{
+ JSONObject json = new JSONObject()
+ .put("server_count", guilds)
+ .put("bot_id", botId);
+
+ botBlockAPI.getTokens().forEach(json::put);
+
+ REQUEST_HANDLER.performPOST(json, botBlockAPI.getTokens().size());
+ }
+}
diff --git a/src/main/java/org/botblock/javabotblockapi/requests/RequestHandler.java b/request-module/src/main/java/org/botblock/javabotblockapi/requests/handler/RequestHandler.java
similarity index 85%
rename from src/main/java/org/botblock/javabotblockapi/requests/RequestHandler.java
rename to request-module/src/main/java/org/botblock/javabotblockapi/requests/handler/RequestHandler.java
index d1087000..8da8a321 100644
--- a/src/main/java/org/botblock/javabotblockapi/requests/RequestHandler.java
+++ b/request-module/src/main/java/org/botblock/javabotblockapi/requests/handler/RequestHandler.java
@@ -16,12 +16,13 @@
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
-package org.botblock.javabotblockapi.requests;
+package org.botblock.javabotblockapi.requests.handler;
-import org.botblock.javabotblockapi.exceptions.RatelimitedException;
import com.github.benmanes.caffeine.cache.Cache;
import com.github.benmanes.caffeine.cache.Caffeine;
import okhttp3.*;
+import org.botblock.javabotblockapi.core.exceptions.RatelimitedException;
+import org.botblock.javabotblockapi.core.requests.CheckUtil;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
@@ -31,7 +32,7 @@
import java.io.IOException;
import java.util.concurrent.TimeUnit;
-class RequestHandler{
+public class RequestHandler{
private final String BASE_URL = "https://botblock.org/api/";
private final OkHttpClient CLIENT = new OkHttpClient();
@@ -44,22 +45,22 @@ class RequestHandler{
.expireAfterWrite(2, TimeUnit.MINUTES)
.build();
- RequestHandler(String userAgent){
+ public RequestHandler(String userAgent){
this.userAgent = userAgent;
}
- JSONObject performGetBot(@Nonnull String id, boolean disableCache){
+ public JSONObject performGetBot(@Nonnull String id, boolean disableCache){
String url = BASE_URL + "bots/" + id;
if(!disableCache)
- return botCache.get(id, k -> {
- try{
- return performGET(url, userAgent);
- }catch(IOException | RatelimitedException ex){
- ex.printStackTrace();
- return null;
- }
- });
+ return botCache.get(id, k -> {
+ try{
+ return performGET(url, userAgent);
+ }catch(IOException | RatelimitedException ex){
+ ex.printStackTrace();
+ return null;
+ }
+ });
try{
return performGET(url, userAgent);
@@ -69,15 +70,15 @@ JSONObject performGetBot(@Nonnull String id, boolean disableCache){
}
}
- JSONObject performGetList(@Nonnull String id, boolean disableCache, boolean filtered){
+ public JSONObject performGetList(@Nonnull String id, boolean disableCache, boolean filtered){
return performGetList(id, null, disableCache, filtered);
}
- JSONObject performGetList(@Nonnull String id, @Nullable String site, boolean disableCache){
+ public JSONObject performGetList(@Nonnull String id, @Nullable String site, boolean disableCache){
return performGetList(id, site, disableCache, false);
}
- JSONObject performGetList(@Nonnull String id, @Nullable String site, boolean disableCache, boolean filtered){
+ public JSONObject performGetList(@Nonnull String id, @Nullable String site, boolean disableCache, boolean filtered){
String url = BASE_URL + (site == null ? "lists" : "lists/" + site);
if(filtered)
url += "?filter=true";
@@ -108,32 +109,32 @@ private JSONObject performGET(@Nonnull String url, String header) throws IOExcep
.url(url)
.addHeader("User-Agent", header)
.build();
-
+
try(Response response = CLIENT.newCall(request).execute()){
ResponseBody body = response.body();
if(body == null)
throw new NullPointerException("Received empty response body.");
-
+
String bodyString = body.string();
if(bodyString.isEmpty())
throw new NullPointerException("Received empty response body.");
-
+
if(!response.isSuccessful()){
if(response.code() == 429)
throw new RatelimitedException(bodyString);
-
+
throw new IOException(String.format(
"Could not retrieve information. The server responded with error code %d (%s).",
response.code(),
response.message()
));
}
-
+
return new JSONObject(bodyString);
}
}
- void performPOST(@Nonnull JSONObject json, int sites) throws IOException{
+ public void performPOST(@Nonnull JSONObject json, int sites) throws IOException{
CheckUtil.condition(sites < 1, "The POST action requires at least 1 site!");
String url = BASE_URL + "count";
@@ -195,7 +196,7 @@ void performPOST(@Nonnull JSONObject json, int sites) throws IOException{
}
}
- private JSONObject getJson(String key, JSONArray array){
+ JSONObject getJson(String key, JSONArray array){
JSONObject json = new JSONObject()
.put("code", array == null ? "?" : array.get(0))
.put("message", array == null ? "?" : array.get(1));
diff --git a/settings.gradle b/settings.gradle
index cf373446..d6f536d8 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -1,2 +1,5 @@
rootProject.name = 'JavaBotBlockAPI'
+include 'core'
+include 'jda-module'
+include 'request-module'
diff --git a/src/main/java/org/botblock/javabotblockapi/package-info.java b/src/main/java/org/botblock/javabotblockapi/package-info.java
deleted file mode 100644
index cacca15a..00000000
--- a/src/main/java/org/botblock/javabotblockapi/package-info.java
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * Copyright 2019 - 2020 Andre601
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
- * documentation files (the "Software"), to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
- * and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all copies or substantial
- * portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
- * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
- * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
- * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-/**
- * Contains the {@link org.botblock.javabotblockapi.BotBlockAPI BotBlockAPI} class for setting up bot tokens and sites.
- * You can {@link #enableAutoPost(JDA, BotBlockAPI) post automatically} or {@link #postGuilds(JDA, BotBlockAPI) post manually}.
- *
- * @since 3.0.0
- */
-public class PostAction{
-
- private final RequestHandler REQUEST_HANDLER;
- private final ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();
-
- /**
- * Constructor to get an instance of PostAction.
- *
- * Using this constructor will set the following default values:
- * Note that you can provide {@code {id}} inside the userAgent to get it replaced with the provided id.
- *
- * @param userAgent
- * The Name to use as User-Agent.
- * @param id
- * The id of the bot. This is required for the internal User-Agent.
- *
- * @throws java.lang.NullPointerException
- * When the provided userAgent or id is empty.
- */
- public PostAction(@Nonnull String userAgent, @Nonnull String id){
- CheckUtil.notEmpty(userAgent, "UserAgent");
- CheckUtil.notEmpty(id, "ID");
-
- this.REQUEST_HANDLER = new RequestHandler(userAgent.replace("{id}", id));
- }
-
- /**
- * Shuts down the scheduler, to stop the automatic posting.
- */
- public void disableAutoPost(){
- scheduler.shutdown();
- }
-
- /**
- * Starts posting of the guild count each n minutes.
- * The scheduler will stop (cancel) the task, when an Exception appears!
- *
- * @param jda
- * The {@link net.dv8tion.jda.api.JDA JDA instance} to use.
- * @param botBlockAPI
- * The {@link org.botblock.javabotblockapi.BotBlockAPI BotBlockAPI instance} to use.
- */
- public void enableAutoPost(@Nonnull JDA jda, @Nonnull BotBlockAPI botBlockAPI){
- scheduler.scheduleAtFixedRate(() -> {
- try{
- postGuilds(jda, botBlockAPI);
- }catch(IOException | RatelimitedException ex){
- ex.printStackTrace();
- }
- }, botBlockAPI.getUpdateDelay(), botBlockAPI.getUpdateDelay(), TimeUnit.MINUTES);
- }
-
- /**
- * Starts posting of the guild count each n minutes.
- * The scheduler will stop (cancel) the task, when an Exception appears!
- *
- * @param botId
- * The ID of the bot as Long.
- * @param guilds
- * The guild count.
- * @param botBlockAPI
- * The {@link org.botblock.javabotblockapi.BotBlockAPI BotBlockAPI instance} to use.
- */
- public void enableAutoPost(@Nonnull Long botId, int guilds, @Nonnull BotBlockAPI botBlockAPI){
- scheduler.scheduleAtFixedRate(() -> {
- try{
- postGuilds(botId, guilds, botBlockAPI);
- }catch(IOException | RatelimitedException ex){
- ex.printStackTrace();
- }
- }, botBlockAPI.getUpdateDelay(), botBlockAPI.getUpdateDelay(), TimeUnit.MINUTES);
- }
-
- /**
- * Starts posting of the guild count each n minutes.
- * The scheduler will stop (cancel) the task, when an Exception appears!
- *
- * @param shardManager
- * The {@link net.dv8tion.jda.api.sharding.ShardManager ShardManager instance} to use.
- * @param botBlockAPI
- * The {@link org.botblock.javabotblockapi.BotBlockAPI BotBlockAPI instance} to use.
- */
- public void enableAutoPost(@Nonnull ShardManager shardManager, @Nonnull BotBlockAPI botBlockAPI){
- scheduler.scheduleAtFixedRate(() -> {
- try{
- postGuilds(shardManager, botBlockAPI);
- }catch(IOException | RatelimitedException ex){
- ex.printStackTrace();
- }
- }, botBlockAPI.getUpdateDelay(), botBlockAPI.getUpdateDelay(), TimeUnit.MINUTES);
- }
-
- /**
- * Starts posting of the guild count each n minutes.
- * The scheduler will stop (cancel) the task, when an Exception appears!
- *
- * @param botId
- * The ID of the bot as String.
- * @param guilds
- * The guild count.
- * @param botBlockAPI
- * The {@link org.botblock.javabotblockapi.BotBlockAPI BotBlockAPI instance} to use.
- */
- public void enableAutoPost(@Nonnull String botId, int guilds, @Nonnull BotBlockAPI botBlockAPI){
- scheduler.scheduleAtFixedRate(() -> {
- try{
- postGuilds(botId, guilds, botBlockAPI);
- }catch(IOException | RatelimitedException ex){
- ex.printStackTrace();
- }
- }, botBlockAPI.getUpdateDelay(), botBlockAPI.getUpdateDelay(), TimeUnit.MINUTES);
- }
-
- /**
- * Posts the guild count provided through the {@link net.dv8tion.jda.api.JDA JDA instance}.
- * When the amount of shards a bot has is bigger than one will {@code shard_id} and {@code shard_count} be added.
- *
- * @param jda
- * The {@link net.dv8tion.jda.api.JDA JDA instance}.
- * @param botBlockAPI
- * The {@link org.botblock.javabotblockapi.BotBlockAPI BotBlockAPI instance}.
- *
- * @throws java.io.IOException
- * When the post request couldn't be performed.
- * @throws org.botblock.javabotblockapi.exceptions.RatelimitedException
- * When we exceed the rate-limit of the BotBlock API.
- */
- public void postGuilds(@Nonnull JDA jda, @Nonnull BotBlockAPI botBlockAPI) throws IOException, RatelimitedException{
- JSONObject json = new JSONObject()
- .put("server_count", jda.getGuilds().size())
- .put("bot_id", jda.getSelfUser().getId());
-
- if(jda.getShardInfo().getShardTotal() > 1)
- json.put("shard_id", jda.getShardInfo().getShardId())
- .put("shard_count", jda.getShardInfo().getShardTotal());
-
- botBlockAPI.getTokens().forEach(json::put);
-
- REQUEST_HANDLER.performPOST(json, botBlockAPI.getTokens().size());
- }
-
- /**
- * Posts the guild count with the provided bot id.
- *
- * @param botId
- * The ID of the bot.
- * @param guilds
- * The guild count.
- * @param botBlockAPI
- * The {@link org.botblock.javabotblockapi.BotBlockAPI BotBlockAPI instance}.
- *
- * @throws java.io.IOException
- * When the post request couldn't be performed.
- * @throws org.botblock.javabotblockapi.exceptions.RatelimitedException
- * When we exceed the rate-limit of the BotBlock API.
- */
- public void postGuilds(@Nonnull Long botId, @Nonnull Integer guilds, @Nonnull BotBlockAPI botBlockAPI) throws IOException, RatelimitedException{
- postGuilds(Long.toString(botId), guilds, botBlockAPI);
- }
-
- /**
- * Posts the guild count from the provided {@link net.dv8tion.jda.api.sharding.ShardManager ShardManager instance}.
- * Use {@link org.botblock.javabotblockapi.requests.GetBotAction GetBotAction} for retrieving bot information,
- * {@link org.botblock.javabotblockapi.requests.GetListAction GetListAction} for retrieving List information and
- * {@link org.botblock.javabotblockapi.requests.PostAction PostAction} for POST requests.
- */
-package org.botblock.javabotblockapi.requests;
\ No newline at end of file
diff --git a/src/main/resources/JavaBotBlockAPI.png b/src/main/resources/JavaBotBlockAPI.png
deleted file mode 100644
index b9515724797332b5a934fd853160c4d5e3e0f42e..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001
literal 56517
zcmeFX1y>wF*DXA_yE{R`;1b+jgS$g;C%C&i1P|_R!QI{6-2%bghC9#u-sk%h->p@%
zx~F?pS9NurbN1e+B9#=RP!I_b0RRAsjI_840009%g$#g)1s?|Pmhu4r>|!r9Ef*DI
zcXCH32XiZ1GjbPCM>BFW4=Zy3z+=5S(<14x)h+bX1V;yQGgKSZHpDIO=$y~Ax$-h6
z!c%4G``73(=s=q|h>h&em#cG7G#OHUn{88yLDUJ&)8@f$-pkX8FPflG?T+6+=f||W
zIGY1!Y@QSk#Vfd@&MRZbZ9kv< xY-shwZ3v39mkz1Y1)?=vr=iP%K$d!qiS7C%4F~73Mi-+Lt9JA9Se?@w-
z%i@-Topo_+IrWkJww+)v2&sGiGnr{4NX=%u@exF{vU|sEbZ(uxh{OU8%tz1Ne?KP~
zEeP=}ydl2c-lU^Q$T5kSZ@-{Kk4lwhNJC@%hkId)a1-->lPd5=Zl0Emd2B&yKDo5|
zMY?F&xZq^pi1t|UaGH~Wp!gMD714T`g0fcJr9N`)^21#)d~h%AuEAhRX)6QCRrA#x
z%&O1D-|D;I!{7fj*v!BNF3%5*GU~%WFf1danc&OAfe2StEcu+w`+~K+Ai~7H+;fs(
zB^x@A`OcmfJt$leSxTDgd{M)+m#$PN)a$;)dLBYTi>D{E u8U|3DV
zS~RDts`shd`;jWMK90|<#Sq
Entries with the same key will be overwritten.
*
* @param site
- * The {@link org.botblock.javabotblockapi.Site Site} to get the name from.
+ * The {@link org.botblock.javabotblockapi.core.Site Site} to get the name from.
* @param token
* The API token from the corresponding bot list. May not be null or empty.
*
You may receive the API token from the bot list.
@@ -86,12 +85,12 @@ public Builder(){}
*/
public Builder addAuthToken(@Nonnull Site site, @Nonnull String token){
CheckUtil.notEmpty(token, "Token");
-
+
tokens.put(site.getSite(), token);
-
+
return this;
}
-
+
/**
* Adds the provided Site name and token to the Map.
*
Entries with the same key will be overwritten.
@@ -113,10 +112,10 @@ public Builder addAuthToken(@Nonnull String site, @Nonnull String token){
CheckUtil.notEmpty(token, "Token");
tokens.put(site, token);
-
+
return this;
}
-
+
/**
* Sets the provided Map as the new Map.
*
This will overwrite every previously set entry!
@@ -131,9 +130,9 @@ public Builder addAuthToken(@Nonnull String site, @Nonnull String token){
*/
public Builder setAuthTokens(@Nonnull Map
- *
- *
+ *
* @since 2.1.0
*/
public enum Site {
@@ -81,7 +74,7 @@ public enum Site {
/**
* discordbots.co
- *
+ *
* @since 5.2.3
*/
DISCORDBOTS_CO("discordbots.co"),
@@ -98,7 +91,7 @@ public enum Site {
/**
* discordextremelist.xyz
- *
+ *
* @since 2.3.3
*/
DISCORDEXTREMELIST_XYZ("discordextremelist.xyz"),
@@ -110,7 +103,7 @@ public enum Site {
/**
* discordlistology.com
- *
+ *
* @since 5.2.1
*/
DISCORDLISTOLOGY_COM("discordlistology.com"),
@@ -132,9 +125,9 @@ public enum Site {
/**
* vultrex.io
- *
+ *
* @since 5.2.1
- *
+ *
* @deprecated Renamed to {@link #DISCORDBOTS_CO DISCORDBOTS_CO}
*
Planned removal in v5.2.5
*/
@@ -150,17 +143,17 @@ public enum Site {
/**
* yabl.xyz
- *
+ *
* @since 2.1.1
*/
YABL_XYZ("yabl.xyz");
-
+
private final String site;
-
+
Site(String site){
this.site = site;
}
-
+
/**
* Gives the ID of the selected site, which is used as ID in the BotBlock.org API.
*
diff --git a/src/main/java/org/botblock/javabotblockapi/annotations/DeprecatedSince.java b/core/src/main/java/org/botblock/javabotblockapi/core/annotations/DeprecatedSince.java
similarity index 93%
rename from src/main/java/org/botblock/javabotblockapi/annotations/DeprecatedSince.java
rename to core/src/main/java/org/botblock/javabotblockapi/core/annotations/DeprecatedSince.java
index c67bdc5d..57d35fa4 100644
--- a/src/main/java/org/botblock/javabotblockapi/annotations/DeprecatedSince.java
+++ b/core/src/main/java/org/botblock/javabotblockapi/core/annotations/DeprecatedSince.java
@@ -16,13 +16,13 @@
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
-package org.botblock.javabotblockapi.annotations;
+package org.botblock.javabotblockapi.core.annotations;
import java.lang.annotation.*;
/**
* Annotation used to indicate since when an Object is deprecated.
- *
This is always paired with the {@link java.lang.Deprecated @Deprecated} annotation.
+ *
This is always paired with the {@link Deprecated @Deprecated} annotation.
*
*
Anything annotated with this should be avoided as it may be removed in a future release.
diff --git a/src/main/java/org/botblock/javabotblockapi/annotations/PlannedRemoval.java b/core/src/main/java/org/botblock/javabotblockapi/core/annotations/PlannedRemoval.java
similarity index 89%
rename from src/main/java/org/botblock/javabotblockapi/annotations/PlannedRemoval.java
rename to core/src/main/java/org/botblock/javabotblockapi/core/annotations/PlannedRemoval.java
index a6c0d7bd..d6a39f53 100644
--- a/src/main/java/org/botblock/javabotblockapi/annotations/PlannedRemoval.java
+++ b/core/src/main/java/org/botblock/javabotblockapi/core/annotations/PlannedRemoval.java
@@ -16,13 +16,13 @@
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
-package org.botblock.javabotblockapi.annotations;
+package org.botblock.javabotblockapi.core.annotations;
import java.lang.annotation.*;
/**
* Annotation to mark an Object to be planned for removal.
- *
This is often paired with the {@link java.lang.Deprecated Deprecated} and {@link org.botblock.javabotblockapi.annotations.DeprecatedSince DeprecatedSince}
+ *
This is often paired with the {@link Deprecated Deprecated} and {@link DeprecatedSince DeprecatedSince}
* annotations.
*
*
It allows you to just provide either an {@link net.dv8tion.jda.api.JDA JDA} or a
+ * {@link net.dv8tion.jda.api.sharding.ShardManager ShardManager} instance and all other stuff such as providing
+ * the amount of shards, the Guild count, etc. are handled automatically.
+ */
+public class PostAction{
+ private final RequestHandler requestHandler;
+ private final ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();
+
+ /**
+ * Creates a new instance of this class.
+ *
This will set the UserAgent used for POST requests to {@code
This will set the UserAgent used for POST requests to {@code
This essentially just performs a {@link java.util.concurrent.ScheduledExecutorService#shutdown() ScheduledExecutorService.shutdown()}.
+ *
+ * @see java.util.concurrent.ScheduledExecutorService#shutdown()
+ */
+ public void disableAutoPost(){
+ scheduler.shutdown();
+ }
+
+ /**
+ * Starts a {@link java.util.concurrent.ScheduledExecutorService#scheduleAtFixedRate(Runnable, long, long, TimeUnit) scheduleAtFixedRate}
+ * task, which will post the statistics of the provided {@link net.dv8tion.jda.api.JDA JDA instance} every n minutes.
+ *
+ *
The OAuth invite is used to add a bot to a Discord server.
- *
+ *
* @param id
* The id of the bot to get the OAuth link from.
- *
+ *
* @return Possibly-empty String containing the OAuth link for the bot.
- *
+ *
* @since 5.1.13
*/
public String getOAuthInvite(@Nonnull Long id){
@@ -461,7 +463,7 @@ public String getOAuthInvite(@Nonnull Long id){
* The id of the bot to get the OAuth link from.
*
* @return Possibly-empty String containing the OAuth link for the bot.
- *
+ *
* @since 5.1.13
*/
public String getOAuthInvite(@Nonnull String id){
diff --git a/src/main/java/org/botblock/javabotblockapi/requests/GetListAction.java b/request-module/src/main/java/org/botblock/javabotblockapi/requests/GetListAction.java
similarity index 87%
rename from src/main/java/org/botblock/javabotblockapi/requests/GetListAction.java
rename to request-module/src/main/java/org/botblock/javabotblockapi/requests/GetListAction.java
index 5f91bef7..5a3ae568 100644
--- a/src/main/java/org/botblock/javabotblockapi/requests/GetListAction.java
+++ b/request-module/src/main/java/org/botblock/javabotblockapi/requests/GetListAction.java
@@ -18,20 +18,22 @@
package org.botblock.javabotblockapi.requests;
-import org.botblock.javabotblockapi.Site;
-import org.jetbrains.annotations.Nullable;
+import org.botblock.javabotblockapi.core.Site;
+import org.botblock.javabotblockapi.core.requests.CheckUtil;
+import org.botblock.javabotblockapi.requests.handler.RequestHandler;
import org.json.JSONArray;
import org.json.JSONObject;
import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
/**
* Class used to perform GET actions on the {@code /api/lists}
* and {@code /api/lists/:id} endpoints.
- *
+ *
*
*
- *
+ *
* @param id
* The id of the bot. This is required for the internal User-Agent.
*
@@ -61,12 +63,12 @@ public GetListAction(@Nonnull String id){
/**
* Constructor to get an instance of GetListAction.
*
This constructor allows you to disable the internal caching, by providing {@code true} as the first argument.
- *
+ *
*
*
- *
+ *
* @param disableCache
* If the cache should be disabled.
*
{@code true} means the cache is disabled.
@@ -84,7 +86,7 @@ public GetListAction(boolean disableCache, @Nonnull String id){
* Constructor to get the instance of GetListAction.
*
This constructor allows you to disable the internal caching, by providing {@code true} as the first argument
* and also set a own User-Agent for the requests by providing any String as the second argument.
- *
+ *
*
The id is used for the {@code /api/count} endpoint.
- *
+ *
* @param id
* The id used for the cache.
* @param site
- * The {@link org.botblock.javabotblockapi.Site site} to get information from.
- *
+ * The {@link org.botblock.javabotblockapi.core.Site site} to get information from.
+ *
* @return String containing the id of the bot list.
*/
public String getId(@Nonnull String id, @Nonnull String site){
@@ -390,7 +392,7 @@ public String getId(@Nonnull String id, @Nonnull String site){
* @param id
* The id used for the cache.
* @param site
- * The {@link org.botblock.javabotblockapi.Site site} to get information from.
+ * The {@link org.botblock.javabotblockapi.core.Site site} to get information from.
*
* @return String containing the primarily used language of the bot list.
*/
@@ -407,7 +409,7 @@ public String getLanguage(@Nonnull String id, @Nonnull Site site){
* @param id
* The id used for the cache.
* @param site
- * The {@link org.botblock.javabotblockapi.Site site} to get information from.
+ * The {@link org.botblock.javabotblockapi.core.Site site} to get information from.
*
* @return String containing the primarily used language of the bot list.
*/
@@ -425,7 +427,7 @@ public String getLanguage(@Nonnull String id, @Nonnull String site){
* @param id
* The id used for the cache.
* @param site
- * The {@link org.botblock.javabotblockapi.Site site} to get information from.
+ * The {@link org.botblock.javabotblockapi.core.Site site} to get information from.
*
* @return {@link org.json.JSONObject JSONObject} containing information about the specified bot list.
*/
@@ -441,7 +443,7 @@ public JSONObject getList(@Nonnull String id, @Nonnull Site site){
* @param id
* The id used for the cache.
* @param site
- * The {@link org.botblock.javabotblockapi.Site site} to get information from.
+ * The {@link org.botblock.javabotblockapi.core.Site site} to get information from.
*
* @return {@link org.json.JSONObject JSONObject} containing information about the specified bot list.
*/
@@ -472,7 +474,7 @@ public JSONObject getLists(@Nonnull String id){
* @param id
* The id used for the cache.
* @param site
- * The {@link org.botblock.javabotblockapi.Site site} to get information from.
+ * The {@link org.botblock.javabotblockapi.core.Site site} to get information from.
*
* @return String containing the name of the bot list.
*/
@@ -489,7 +491,7 @@ public String getName(@Nonnull String id, @Nonnull Site site){
* @param id
* The id used for the cache.
* @param site
- * The {@link org.botblock.javabotblockapi.Site site} to get information from.
+ * The {@link org.botblock.javabotblockapi.core.Site site} to get information from.
*
* @return String containing the name of the bot list.
*/
@@ -508,7 +510,7 @@ public String getName(@Nonnull String id, @Nonnull String site){
* @param id
* The id used for the cache.
* @param site
- * The {@link org.botblock.javabotblockapi.Site site} to get information from.
+ * The {@link org.botblock.javabotblockapi.core.Site site} to get information from.
*
* @return Possibly-null String containing the owners of the bot list.
*/
@@ -527,7 +529,7 @@ public String getOwners(@Nonnull String id, @Nonnull Site site){
* @param id
* The id used for the cache.
* @param site
- * The {@link org.botblock.javabotblockapi.Site site} to get information from.
+ * The {@link org.botblock.javabotblockapi.core.Site site} to get information from.
*
* @return Possibly-null String containing the owners of the bot list,
*/
@@ -546,7 +548,7 @@ public String getOwners(@Nonnull String id, @Nonnull String site){
* @param id
* The id used for the cache.
* @param site
- * The {@link org.botblock.javabotblockapi.Site site} to get information from.
+ * The {@link org.botblock.javabotblockapi.core.Site site} to get information from.
*
* @return Integer displaying the UNIX time at which the bot list was added to BotBlock.
*/
@@ -563,7 +565,7 @@ public Integer getTimeAdded(@Nonnull String id, @Nonnull Site site){
* @param id
* The id used for the cache.
* @param site
- * The {@link org.botblock.javabotblockapi.Site site} to get information from.
+ * The {@link org.botblock.javabotblockapi.core.Site site} to get information from.
*
* @return Integer displaying the UNIX time at which the bot list was added to BotBlock.
*/
@@ -581,7 +583,7 @@ public Integer getTimeAdded(@Nonnull String id, @Nonnull String site){
* @param id
* The id used for the cache.
* @param site
- * The {@link org.botblock.javabotblockapi.Site site} to get information from.
+ * The {@link org.botblock.javabotblockapi.core.Site site} to get information from.
*
* @return String containing the URL to the bot list website.
*/
@@ -598,7 +600,7 @@ public String getUrl(@Nonnull String id, @Nonnull Site site){
* @param id
* The id used for the cache.
* @param site
- * The {@link org.botblock.javabotblockapi.Site site} to get information from.
+ * The {@link org.botblock.javabotblockapi.core.Site site} to get information from.
*
* @return String containing the URL to the bot list website.
*/
@@ -617,7 +619,7 @@ public String getUrl(@Nonnull String id, @Nonnull String site){
* @param id
* The id used for the cache.
* @param site
- * The {@link org.botblock.javabotblockapi.Site site} to get information from.
+ * The {@link org.botblock.javabotblockapi.core.Site site} to get information from.
*
* @return {@code true} if the bot list is defunct, {@code false} otherwise.
*/
@@ -635,7 +637,7 @@ public boolean isDefunct(@Nonnull String id, @Nonnull Site site){
* @param id
* The id used for the cache.
* @param site
- * The {@link org.botblock.javabotblockapi.Site site} to get information from.
+ * The {@link org.botblock.javabotblockapi.core.Site site} to get information from.
*
* @return {@code true} if the bot list is defunct, {@code false} otherwise.
*/
@@ -653,7 +655,7 @@ public boolean isDefunct(@Nonnull String id, @Nonnull String site){
* @param id
* The id used for the cache.
* @param site
- * The {@link org.botblock.javabotblockapi.Site site} to get information from.
+ * The {@link org.botblock.javabotblockapi.core.Site site} to get information from.
*
* @return {@code true} if the list is only for Discord bots, {@code false} otherwise.
*/
@@ -670,7 +672,7 @@ public boolean isDiscordOnly(@Nonnull String id, @Nonnull Site site){
* @param id
* The id used for the cache.
* @param site
- * The {@link org.botblock.javabotblockapi.Site site} to get information from.
+ * The {@link org.botblock.javabotblockapi.core.Site site} to get information from.
*
* @return {@code true} if the list is only for Discord bots, {@code false} otherwise.
*/
@@ -678,14 +680,14 @@ public boolean isDiscordOnly(@Nonnull String id, @Nonnull String site){
CheckUtil.notEmpty(id, "id");
CheckUtil.notEmpty(site, "site");
JSONObject json = getList(id, site);
-
+
return json.getInt("discord_only") == 1;
}
/**
* Enum containing the different API fields a bot list may have.
*
This is used for {@link org.botblock.javabotblockapi.requests.GetListAction#getApiField(String, Site, ApiField) GetListAction#getApiField(String, Site|String, ApiField)}
- *
+ *
* @since 5.0.0
*/
public enum ApiField{
@@ -693,25 +695,25 @@ public enum ApiField{
/**
* Name of the field for the server count. Example: {@code server_count}
- *
+ *
* @since 5.2.0
*/
STRING_SERVER_COUNT("api_field"),
-
+
/**
* Name of the field for the shard id. Example: {@code shard_id}
*
* @since 5.2.0
*/
STRING_SHARD_ID("api_shard_id"),
-
+
/**
* Name of the field for the shard count. Example: {@code shard_count}
*
* @since 5.2.0
*/
STRING_SHARD_COUNT("api_shard_count"),
-
+
/**
* Name of the field for the shards. Example: {@code shards}
*
@@ -727,21 +729,21 @@ public enum ApiField{
* @since 5.2.0
*/
URL_ALL("api_all"),
-
+
/**
* URL to view the API documentation of the bot list
*
* @since 5.2.0
*/
URL_DOCS("api_docs"),
-
+
/**
* URL to GET information about a single bot listed on the bot list.
*
* @since 5.2.0
*/
URL_GET("api_get"),
-
+
/**
* URL to POST the server count to a bot list.
*
@@ -758,8 +760,8 @@ public enum ApiField{
public String getApiField(){
return apiField;
}
-
-
+
+
@Override
public String toString(){
return apiField;
diff --git a/request-module/src/main/java/org/botblock/javabotblockapi/requests/PostAction.java b/request-module/src/main/java/org/botblock/javabotblockapi/requests/PostAction.java
new file mode 100644
index 00000000..07adc94e
--- /dev/null
+++ b/request-module/src/main/java/org/botblock/javabotblockapi/requests/PostAction.java
@@ -0,0 +1,173 @@
+/*
+ * Copyright 2019 - 2020 Andre601
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
+ * documentation files (the "Software"), to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all copies or substantial
+ * portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+ * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
+ * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+package org.botblock.javabotblockapi.requests;
+
+import org.botblock.javabotblockapi.core.BotBlockAPI;
+import org.botblock.javabotblockapi.core.exceptions.RatelimitedException;
+import org.botblock.javabotblockapi.core.requests.CheckUtil;
+import org.botblock.javabotblockapi.requests.handler.RequestHandler;
+import org.json.JSONObject;
+
+import javax.annotation.Nonnull;
+import java.io.IOException;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
+
+public class PostAction{
+
+ private final RequestHandler REQUEST_HANDLER;
+ private final ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();
+
+ /**
+ * Constructor to get an instance of PostAction.
+ *
+ *
+ *
+ *
+ * @param id
+ * The id of the bot. This is required for the internal User-Agent.
+ *
+ * @throws NullPointerException
+ * When the provided id is empty.
+ */
+ public PostAction(@Nonnull String id){
+ this("JavaBotBlockAPI-0000/API_VERSION (Unknown; +https://jbba.dev) DBots/{id}", id);
+ }
+
+ /**
+ * Constructor to get an instance of PostAction.
+ *
This constructor allows you to set a own User-Agent by providing any String as the first argument.
+ *
+ *
The delay in which this happens is set using {@link org.botblock.javabotblockapi.core.BotBlockAPI.Builder#setUpdateDelay(Integer)} BotBlockAPI.Builder#setUpdateInterval(Integer)}
+ *
+ *
The delay in which this happens is set using {@link org.botblock.javabotblockapi.core.BotBlockAPI.Builder#setUpdateDelay(Integer)} BotBlockAPI.Builder#setUpdateInterval(Integer)}
+ *
+ *
Also contains the {@link org.botblock.javabotblockapi.Site Site} enum used in various GET requests and the BotBlockAPI.
- */
-package org.botblock.javabotblockapi;
\ No newline at end of file
diff --git a/src/main/java/org/botblock/javabotblockapi/requests/PostAction.java b/src/main/java/org/botblock/javabotblockapi/requests/PostAction.java
deleted file mode 100644
index ddc34db4..00000000
--- a/src/main/java/org/botblock/javabotblockapi/requests/PostAction.java
+++ /dev/null
@@ -1,292 +0,0 @@
-/*
- * Copyright 2019 - 2020 Andre601
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
- * documentation files (the "Software"), to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
- * and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all copies or substantial
- * portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
- * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
- * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
- * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-package org.botblock.javabotblockapi.requests;
-
-import org.botblock.javabotblockapi.BotBlockAPI;
-import org.botblock.javabotblockapi.exceptions.RatelimitedException;
-import net.dv8tion.jda.api.JDA;
-import net.dv8tion.jda.api.sharding.ShardManager;
-import org.json.JSONArray;
-import org.json.JSONObject;
-
-import javax.annotation.Nonnull;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-import java.util.concurrent.Executors;
-import java.util.concurrent.ScheduledExecutorService;
-import java.util.concurrent.TimeUnit;
-
-/**
- * Class used to perform POST requests towards the {@code /api/count} endpoint.
- *
- *
- *
- *
- * @param id
- * The id of the bot. This is required for the internal User-Agent.
- *
- * @throws java.lang.NullPointerException
- * When the provided id is empty.
- */
- public PostAction(@Nonnull String id){
- this("JavaBotBlockAPI-0000/API_VERSION (Unknown; +https://jbba.dev) DBots/{id}", id);
- }
-
- /**
- * Constructor to get an instance of PostAction.
- *
This constructor allows you to set a own User-Agent by providing any String as the first argument.
- *
- *
The delay in which this happens is set using {@link org.botblock.javabotblockapi.BotBlockAPI.Builder#setUpdateDelay(Integer) BotBlockAPI.Builder#setUpdateInterval(Integer)}
- *
- *
The delay in which this happens is set using {@link org.botblock.javabotblockapi.BotBlockAPI.Builder#setUpdateDelay(Integer)} BotBlockAPI.Builder#setUpdateInterval(Integer)}
- *
- *
The delay in which this happens is set using {@link org.botblock.javabotblockapi.BotBlockAPI.Builder#setUpdateDelay(Integer)} BotBlockAPI.Builder#setUpdateInterval(Integer)}
- *
- *
The delay in which this happens is set using {@link org.botblock.javabotblockapi.BotBlockAPI.Builder#setUpdateDelay(Integer)} BotBlockAPI.Builder#setUpdateInterval(Integer)}
- *
- *
It's recommended to use {@link #postGuilds(ShardManager, BotBlockAPI) postGuilds(ShardManager, BotBlockAPI)}
- * if you're using a sharded bot.
- *
- *
The guild count of each shard will be added as an JSONArray.
- *
- * @param shardManager
- * The {@link net.dv8tion.jda.api.sharding.ShardManager ShardManager instance}.
- * @param botBlockAPI
- * The {@link org.botblock.javabotblockapi.BotBlockAPI BotBlockAPI instance}.
- *
- * @throws java.io.IOException
- * When the post request couldn't be performed.
- * @throws org.botblock.javabotblockapi.exceptions.RatelimitedException
- * When we exceed the rate-limit of the BotBlock API.
- */
- public void postGuilds(@Nonnull ShardManager shardManager, @Nonnull BotBlockAPI botBlockAPI) throws IOException, RatelimitedException{
- JDA jda = shardManager.getShardById(0);
- if(jda == null)
- throw new NullPointerException("Received shard was null!");
-
- JSONObject json = new JSONObject()
- .put("server_count", shardManager.getGuilds().size())
- .put("bot_id", jda.getSelfUser().getId())
- .put("shard_count", shardManager.getShardCache().size());
-
- ListE`TYNBZeQF-od-{?_KyYhmdN3*5qh3Q^66|J7
zBMGPS;i1JurJWZ;>Ko8zBDGj1k6$i50M<>oL}@!gGg~0+NtS5A(vSOmPqK6cd|}H*
zVAstrrQ>9H(sO&>$334|aqP4!GIt2&cW&6wfp3erNDWMFQGDSMn5oN2Q4QXtI4Cw0
z`Q*0Q@^@aJS?h0zVSMK_K5izH_nL5i1y5{M4eIkP#8Lp?>w?}P8e!23DGkX9RTiT
zbYGS(7J|?h(*+g_xy1Ao`Ri${`RT7oB^%fGhB|{O{I=z-fE~Ep4FoVx5o|#+NP{wH
zK@!O&$`6pb_OVNX(dojlu13|#hJgJA(@up2#-0Bm0fYFcvz~@ii4f$N7|EJAL(F;=
z4A_QRgRHCJlkf9`I~I
g8LWnkTH6dy(;0M6te!s*pj>OH1xA`x*Sx8XU)lqQ(z?o(l6a2jA&tU~olD{+VC
zEhmRXnGxkLpMe8vz8WnA5dU4iFmDG=SMx3gTD~Aq><;6ei%djAo3R0rK7VP%o!i=Q
zLPqOuf@){zsa>*^`u*T0o#bN%1g(AUE}CYZa__#tLv?5CG4Hnz74m+W!A)D(vWM
$UCg$^zaAi>%yqz@ERRs=wjC)t^icyDR&Q{HXL`&}
zn=9Ta9m?g%TE>K
z!
FHJ-EpbOL9ug$nH_
zuJMiyXb2)hnlLas{WnbkGZjC+BtNDoD^YOv50QoKqH5E9;(xu_>z7IM4}?%sC85Qk
zQRh=FhsMbu#L2+=J1YTmQwB6t1RkcI3lQ4>UJg9HXU2j27ubITk@oBV=P$s#{J-=3
zkp2qj{`UnN3Hg5y4a|oE$g%%jObOEX|2+b*#2;Wi|MxGd-9YgFi}nAXzYP@tnZKKo
z{E7!hCL*+5LnE&AeeEc?LfhTwzoAg?`P$knDXCYAV}pa!?rtXy1kYcfG^GNro=XMLhic7K$(_lTeT}=xLG-(?B
zlRo_L{i#HJOfsUQk|M0LN}QtmRwjYpPfqA{re;Yq?K1j+JvaZ7^)duf*HF}X)tK8?
zlY5FMMh=@5%JZydb-X2_)tsJ4u16Eps(()UZMJZ%H{beErW6diNana`?9P6@)