Skip to content

Commit 7aabba7

Browse files
committed
create utility class for webhook logic
1 parent c657a68 commit 7aabba7

File tree

2 files changed

+122
-70
lines changed

2 files changed

+122
-70
lines changed
Lines changed: 29 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,17 @@
11
package net.javadiscord.javabot.listener;
22

3-
import java.util.List;
4-
import java.util.Optional;
5-
import java.util.concurrent.CompletableFuture;
6-
73
import javax.annotation.Nonnull;
84

9-
import club.minnced.discord.webhook.WebhookClientBuilder;
10-
import club.minnced.discord.webhook.external.JDAWebhookClient;
11-
import club.minnced.discord.webhook.send.AllowedMentions;
12-
import club.minnced.discord.webhook.send.WebhookMessageBuilder;
135
import lombok.extern.slf4j.Slf4j;
146
import net.dv8tion.jda.api.entities.ChannelType;
157
import net.dv8tion.jda.api.entities.GuildMessageChannel;
168
import net.dv8tion.jda.api.entities.Message;
17-
import net.dv8tion.jda.api.entities.Message.Attachment;
189
import net.dv8tion.jda.api.entities.TextChannel;
1910
import net.dv8tion.jda.api.entities.Webhook;
2011
import net.dv8tion.jda.api.events.message.MessageReceivedEvent;
2112
import net.dv8tion.jda.api.hooks.ListenerAdapter;
2213
import net.javadiscord.javabot.Bot;
14+
import net.javadiscord.javabot.util.WebhookUtil;
2315

2416
/**
2517
* Replaces all occurences of 'fuck' in incoming messages with 'hug'.
@@ -28,90 +20,57 @@
2820
public class HugListener extends ListenerAdapter {
2921
@Override
3022
public void onMessageReceived(@Nonnull MessageReceivedEvent event) {
31-
if(!event.isFromGuild()) {
23+
if (!event.isFromGuild()) {
3224
return;
3325
}
3426
if (Bot.autoMod.hasSuspiciousLink(event.getMessage()) || Bot.autoMod.hasAdvertisingLink(event.getMessage())) {
3527
return;
3628
}
29+
if (!event.getMessage().getMentions().getUsers().isEmpty()) {
30+
return;
31+
}
32+
if (event.isWebhookMessage()) {
33+
return;
34+
}
3735
TextChannel tc = null;
38-
if(event.isFromType(ChannelType.TEXT)) {
36+
if (event.isFromType(ChannelType.TEXT)) {
3937
tc = event.getTextChannel();
4038
}
41-
if(event.isFromThread()) {
39+
if (event.isFromThread()) {
4240
GuildMessageChannel parentChannel = event.getThreadChannel().getParentMessageChannel();
43-
if(parentChannel instanceof TextChannel textChannel) {
41+
if (parentChannel instanceof TextChannel textChannel) {
4442
tc = textChannel;
4543
}
4644
}
47-
if(tc == null) {
45+
if (tc == null) {
4846
return;
4947
}
5048
final TextChannel textChannel = tc;
5149
String content = event.getMessage().getContentRaw();
5250
String lowerCaseContent = content.toLowerCase();
53-
if(lowerCaseContent.contains("fuck")) {
54-
long threadId = event.isFromThread()?event.getThreadChannel().getIdLong():0;
51+
if (lowerCaseContent.contains("fuck")) {
52+
long threadId = event.isFromThread() ? event.getThreadChannel().getIdLong() : 0;
5553
StringBuilder sb = new StringBuilder(content.length());
5654
int index = 0;
5755
int indexBkp = index;
58-
while((index = lowerCaseContent.indexOf("fuck",index)) != -1) {
59-
sb.append(content.substring(indexBkp,index));
56+
while ((index = lowerCaseContent.indexOf("fuck", index)) != -1) {
57+
sb.append(content.substring(indexBkp, index));
6058
sb.append("hug");
61-
indexBkp=index++ +4;
59+
indexBkp = index++ + 4;
6260
}
63-
64-
sb.append(content.substring(indexBkp,content.length()));
65-
textChannel.retrieveWebhooks().queue(webhooks->{
66-
Optional<Webhook> hook = webhooks
67-
.stream()
68-
.filter(webhook->webhook.getChannel().getIdLong() == textChannel.getIdLong())
69-
.filter(wh->wh.getToken()!=null)
70-
.findAny();
71-
if(hook.isPresent()) {
72-
sendWebhookMessage(hook.get(), event.getMessage(), sb.toString(),threadId);
73-
}else {
74-
textChannel
75-
.createWebhook("JavaBot-hug")
76-
.queue(wh->
77-
sendWebhookMessage(wh, event.getMessage(), sb.toString(), threadId)
78-
);
79-
}
80-
});
61+
62+
sb.append(content.substring(indexBkp, content.length()));
63+
WebhookUtil.ensureWebhookExists(textChannel,
64+
wh -> sendWebhookMessage(wh, event.getMessage(), sb.toString(), threadId),
65+
e -> log.error("Webhook lookup/creation failed", e));
8166
}
8267
}
83-
84-
private void sendWebhookMessage(Webhook webhook, Message originalMessage, String newMessageContent, long threadId){
85-
JDAWebhookClient client = new WebhookClientBuilder(webhook.getIdLong(), webhook.getToken())
86-
.setThreadId(threadId)
87-
.buildJDA();
88-
WebhookMessageBuilder message = new WebhookMessageBuilder()
89-
.setContent(newMessageContent)
90-
.setAllowedMentions(AllowedMentions.none())
91-
.setAvatarUrl(originalMessage.getMember().getEffectiveAvatarUrl())
92-
.setUsername(originalMessage.getMember().getEffectiveName());
93-
94-
List<Attachment> attachments = originalMessage.getAttachments();
95-
@SuppressWarnings("unchecked")
96-
CompletableFuture<?>[] futures = new CompletableFuture<?>[attachments.size()];
97-
for(int i = 0; i < attachments.size(); i++){
98-
Attachment attachment = attachments.get(i);
99-
futures[i] = attachment
100-
.getProxy()
101-
.download()
102-
.thenAccept(is ->
103-
message.addFile(
104-
(attachment.isSpoiler()?"SPOILER_":"")+attachment.getFileName(),
105-
is
106-
)
107-
);
108-
}
109-
CompletableFuture.allOf(futures)
110-
.thenAccept(unused -> client.send(message.build()))
111-
.thenAccept(unused -> originalMessage.delete().queue())
112-
.exceptionally(e ->{
113-
log.error("replacing the content 'fuck' with 'hug' in an incoming message failed", e);
114-
return null;
115-
});
68+
69+
private void sendWebhookMessage(Webhook webhook, Message originalMessage, String newMessageContent, long threadId) {
70+
WebhookUtil.mirrorMessageToWebhook(webhook, originalMessage, newMessageContent, threadId)
71+
.thenAccept(unused -> originalMessage.delete().queue()).exceptionally(e -> {
72+
log.error("replacing the content 'fuck' with 'hug' in an incoming message failed", e);
73+
return null;
74+
});
11675
}
11776
}
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
package net.javadiscord.javabot.util;
2+
3+
import java.util.List;
4+
import java.util.Optional;
5+
import java.util.concurrent.CompletableFuture;
6+
import java.util.function.Consumer;
7+
8+
import club.minnced.discord.webhook.WebhookClientBuilder;
9+
import club.minnced.discord.webhook.external.JDAWebhookClient;
10+
import club.minnced.discord.webhook.send.AllowedMentions;
11+
import club.minnced.discord.webhook.send.WebhookMessageBuilder;
12+
import net.dv8tion.jda.api.entities.Message;
13+
import net.dv8tion.jda.api.entities.TextChannel;
14+
import net.dv8tion.jda.api.entities.Webhook;
15+
import net.dv8tion.jda.api.entities.Message.Attachment;
16+
17+
/**
18+
* Contains utility methods for dealing with Discord Webhooks.
19+
*/
20+
public class WebhookUtil {
21+
private WebhookUtil() {
22+
}
23+
24+
/**
25+
* Makes sure that a writable webhook exists in a specific channel. if no
26+
* suitable webhook is found, one is created.
27+
*
28+
* @param channel the {@link TextChannel} the webhook should exist in
29+
* @param callback an action that is executed once a webhook is
30+
* found/created
31+
*/
32+
public static void ensureWebhookExists(TextChannel channel, Consumer<? super Webhook> callback) {
33+
ensureWebhookExists(channel, callback, err -> {
34+
});
35+
}
36+
37+
/**
38+
* Makes sure that a writable webhook exists in a specific channel. if no
39+
* suitable webhook is found, one is created.
40+
*
41+
* @param channel the {@link TextChannel} the webhook should exist in
42+
* @param callback an action that is executed once a webhook is
43+
* found/created
44+
* @param failureCallback an action that is executed if the webhook
45+
* lookup/creation failed
46+
*/
47+
public static void ensureWebhookExists(TextChannel channel, Consumer<? super Webhook> callback,
48+
Consumer<? super Throwable> failureCallback) {
49+
50+
channel.retrieveWebhooks().queue(webhooks -> {
51+
Optional<Webhook> hook = webhooks.stream()
52+
.filter(webhook -> webhook.getChannel().getIdLong() == channel.getIdLong())
53+
.filter(wh -> wh.getToken() != null).findAny();
54+
if (hook.isPresent()) {
55+
callback.accept(hook.get());
56+
} else {
57+
channel.createWebhook("JavaBot-webhook").queue(callback, failureCallback);
58+
}
59+
}, failureCallback);
60+
}
61+
62+
/**
63+
* Resends a specific message using a webhook with a custom content.
64+
*
65+
* @param webhook the webhook used for sending the message
66+
* @param originalMessage the message to copy
67+
* @param newMessageContent the new (custom) content
68+
* @param threadId the thread to send the message in or {@code 0} if the
69+
* message should be sent directly
70+
* @return a {@link CompletableFuture} representing the action of sending
71+
* the message
72+
*/
73+
public static CompletableFuture<Void> mirrorMessageToWebhook(Webhook webhook, Message originalMessage,
74+
String newMessageContent, long threadId) {
75+
JDAWebhookClient client = new WebhookClientBuilder(webhook.getIdLong(), webhook.getToken())
76+
.setThreadId(threadId).buildJDA();
77+
WebhookMessageBuilder message = new WebhookMessageBuilder().setContent(newMessageContent)
78+
.setAllowedMentions(AllowedMentions.none())
79+
.setAvatarUrl(originalMessage.getMember().getEffectiveAvatarUrl())
80+
.setUsername(originalMessage.getMember().getEffectiveName());
81+
82+
List<Attachment> attachments = originalMessage.getAttachments();
83+
@SuppressWarnings("unchecked")
84+
CompletableFuture<?>[] futures = new CompletableFuture<?>[attachments.size()];
85+
for (int i = 0; i < attachments.size(); i++) {
86+
Attachment attachment = attachments.get(i);
87+
futures[i] = attachment.getProxy().download().thenAccept(
88+
is -> message.addFile((attachment.isSpoiler() ? "SPOILER_" : "") + attachment.getFileName(), is));
89+
}
90+
return CompletableFuture.allOf(futures).thenAccept(unused -> client.send(message.build()))
91+
.whenComplete((result, err) -> client.close());
92+
}
93+
}

0 commit comments

Comments
 (0)