added discord webhook support
This commit is contained in:
parent
2a7da78acb
commit
848748c4b9
111
src/dev/asdf00/general/utils/discord/DiscordHook.java
Normal file
111
src/dev/asdf00/general/utils/discord/DiscordHook.java
Normal file
|
|
@ -0,0 +1,111 @@
|
||||||
|
package dev.asdf00.general.utils.discord;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.URI;
|
||||||
|
import java.net.http.HttpClient;
|
||||||
|
import java.net.http.HttpRequest;
|
||||||
|
import java.net.http.HttpResponse;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Queue;
|
||||||
|
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||||
|
import java.util.concurrent.Executor;
|
||||||
|
import java.util.concurrent.Executors;
|
||||||
|
|
||||||
|
public final class DiscordHook {
|
||||||
|
private static final HttpClient httpClient = HttpClient.newBuilder()
|
||||||
|
.version(HttpClient.Version.HTTP_2)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
private static final Map<String, DiscordHook> currentHooks = new HashMap<>();
|
||||||
|
|
||||||
|
private final String webhook;
|
||||||
|
|
||||||
|
private final Queue<String> msgQueue = new ConcurrentLinkedQueue<>();
|
||||||
|
|
||||||
|
private final Executor thread = Executors.newSingleThreadExecutor();
|
||||||
|
|
||||||
|
private final Object lockObject = new Object();
|
||||||
|
|
||||||
|
private int timeoutInMillis = 5000;
|
||||||
|
|
||||||
|
private DiscordHook(String webhook) {
|
||||||
|
this.webhook = webhook;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send a message to the associated discord webhook.
|
||||||
|
*
|
||||||
|
* @param splitMessage determines if the message should be pruned or split into
|
||||||
|
* multiple messages if it is lager than 2000 characters
|
||||||
|
* @param msg the message to be sent
|
||||||
|
* @param args arguments to be formatted into the message
|
||||||
|
*/
|
||||||
|
public void sendMsg(boolean splitMessage, String msg, Object... args) {
|
||||||
|
var pmsg = String.format(msg, args);
|
||||||
|
int cnt = 1;
|
||||||
|
if (!splitMessage && pmsg.length() > 1994) {
|
||||||
|
// large message with pruning
|
||||||
|
msgQueue.add(pmsg.substring(0, 1995) + " [...]");
|
||||||
|
} else if (pmsg.length() > 2000) {
|
||||||
|
// large message with splitting
|
||||||
|
var ms = new ArrayList<String>(pmsg.length() / 2000 + 1);
|
||||||
|
for (int i = 0; i < ms.size(); i++) {
|
||||||
|
ms.add(pmsg.substring(i * 2000, Math.min(pmsg.length(), (i + 1) * 2000 + 1)));
|
||||||
|
}
|
||||||
|
msgQueue.addAll(ms);
|
||||||
|
cnt = ms.size();
|
||||||
|
} else {
|
||||||
|
// small message
|
||||||
|
msgQueue.add(pmsg);
|
||||||
|
}
|
||||||
|
|
||||||
|
// schedule all messages inserted into the queue
|
||||||
|
for (; cnt > 0; cnt--) {
|
||||||
|
thread.execute(this::scheduleMsg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String wrapIntoJson(String msg) {
|
||||||
|
return String.format("{\"content\": \"%s\"}", msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void scheduleMsg() {
|
||||||
|
try {
|
||||||
|
var json = msgQueue.remove();
|
||||||
|
synchronized (lockObject) {
|
||||||
|
var postRequest = HttpRequest.newBuilder()
|
||||||
|
.POST(HttpRequest.BodyPublishers.ofString(json))
|
||||||
|
.uri(URI.create(webhook))
|
||||||
|
.setHeader("User-Agent", "JavaCrawler")
|
||||||
|
.header("Content-Type", "application/json")
|
||||||
|
.build();
|
||||||
|
httpClient.send(postRequest, HttpResponse.BodyHandlers.ofString());
|
||||||
|
Thread.sleep(timeoutInMillis);
|
||||||
|
}
|
||||||
|
} catch (InterruptedException | IOException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the timeout for rate limiting. Default is 5 seconds.
|
||||||
|
*/
|
||||||
|
public void setTimeout(int timeout) {
|
||||||
|
timeoutInMillis = timeout;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the instance associated with this webhook or creates a new one if no instance was found.
|
||||||
|
*
|
||||||
|
* @param webhook the URI of the discord webhook
|
||||||
|
* @return instance associated with the given webhook
|
||||||
|
*/
|
||||||
|
public static synchronized DiscordHook getInstance(String webhook) {
|
||||||
|
if (!currentHooks.containsKey(webhook)) {
|
||||||
|
currentHooks.put(webhook, new DiscordHook(webhook));
|
||||||
|
}
|
||||||
|
return currentHooks.get(webhook);
|
||||||
|
}
|
||||||
|
}
|
||||||
11
src/dev/asdf00/general/utils/extras/Tuple.java
Normal file
11
src/dev/asdf00/general/utils/extras/Tuple.java
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
package dev.asdf00.general.utils.extras;
|
||||||
|
|
||||||
|
public class Tuple<A, B> {
|
||||||
|
public A a;
|
||||||
|
public B b;
|
||||||
|
public Tuple() { }
|
||||||
|
public Tuple(A a, B b) {
|
||||||
|
this.a = a;
|
||||||
|
this.b = b;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,4 +1,7 @@
|
||||||
module GeneralUtils {
|
module GeneralUtils {
|
||||||
requires jdk.unsupported;
|
requires jdk.unsupported;
|
||||||
|
requires java.net.http;
|
||||||
|
exports dev.asdf00.general.utils.discord;
|
||||||
|
exports dev.asdf00.general.utils.extras;
|
||||||
exports dev.asdf00.general.utils.list;
|
exports dev.asdf00.general.utils.list;
|
||||||
}
|
}
|
||||||
Loading…
Reference in New Issue
Block a user