-
Notifications
You must be signed in to change notification settings - Fork 23
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #308 from danthe1st/hugs
replace f*cks with hugs
- Loading branch information
Showing
4 changed files
with
198 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
100 changes: 100 additions & 0 deletions
100
src/main/java/net/javadiscord/javabot/listener/HugListener.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,100 @@ | ||
package net.javadiscord.javabot.listener; | ||
|
||
import javax.annotation.Nonnull; | ||
|
||
import lombok.extern.slf4j.Slf4j; | ||
import net.dv8tion.jda.api.entities.ChannelType; | ||
import net.dv8tion.jda.api.entities.GuildMessageChannel; | ||
import net.dv8tion.jda.api.entities.Message; | ||
import net.dv8tion.jda.api.entities.TextChannel; | ||
import net.dv8tion.jda.api.entities.Webhook; | ||
import net.dv8tion.jda.api.events.message.MessageReceivedEvent; | ||
import net.dv8tion.jda.api.hooks.ListenerAdapter; | ||
import net.javadiscord.javabot.Bot; | ||
import net.javadiscord.javabot.util.WebhookUtil; | ||
|
||
/** | ||
* Replaces all occurences of 'fuck' in incoming messages with 'hug'. | ||
*/ | ||
@Slf4j | ||
public class HugListener extends ListenerAdapter { | ||
@Override | ||
public void onMessageReceived(@Nonnull MessageReceivedEvent event) { | ||
if (!event.isFromGuild()) { | ||
return; | ||
} | ||
if (Bot.autoMod.hasSuspiciousLink(event.getMessage()) || Bot.autoMod.hasAdvertisingLink(event.getMessage())) { | ||
return; | ||
} | ||
if (!event.getMessage().getMentions().getUsers().isEmpty()) { | ||
return; | ||
} | ||
if (event.isWebhookMessage()) { | ||
return; | ||
} | ||
if (event.getChannel().getIdLong() == Bot.config.get(event.getGuild()).getModeration() | ||
.getSuggestionChannelId()) { | ||
return; | ||
} | ||
TextChannel tc = null; | ||
if (event.isFromType(ChannelType.TEXT)) { | ||
tc = event.getTextChannel(); | ||
} | ||
if (event.isFromThread()) { | ||
GuildMessageChannel parentChannel = event.getThreadChannel().getParentMessageChannel(); | ||
if (parentChannel instanceof TextChannel textChannel) { | ||
tc = textChannel; | ||
} | ||
} | ||
if (tc == null) { | ||
return; | ||
} | ||
final TextChannel textChannel = tc; | ||
String content = event.getMessage().getContentRaw(); | ||
String lowerCaseContent = content.toLowerCase(); | ||
if (lowerCaseContent.contains("fuck")) { | ||
long threadId = event.isFromThread() ? event.getThreadChannel().getIdLong() : 0; | ||
StringBuilder sb = new StringBuilder(content.length()); | ||
int index = 0; | ||
int indexBkp = index; | ||
while ((index = lowerCaseContent.indexOf("fuck", index)) != -1) { | ||
sb.append(content.substring(indexBkp, index)); | ||
sb.append(loadHug(content, index)); | ||
indexBkp = index++ + 4; | ||
if (content.length() >= indexBkp + 3 && "ing".equals(lowerCaseContent.substring(indexBkp, indexBkp + 3))) { | ||
sb.append(copyCase(content, indexBkp-1, 'g')); | ||
sb.append(content.substring(indexBkp, indexBkp + 3)); | ||
index+=3; | ||
indexBkp+=3; | ||
} | ||
} | ||
|
||
sb.append(content.substring(indexBkp, content.length())); | ||
WebhookUtil.ensureWebhookExists(textChannel, | ||
wh -> sendWebhookMessage(wh, event.getMessage(), sb.toString(), threadId), | ||
e -> log.error("Webhook lookup/creation failed", e)); | ||
} | ||
} | ||
|
||
private String loadHug(String originalText, int startIndex) { | ||
return copyCase(originalText, startIndex, 'h') + "" | ||
+ copyCase(originalText, startIndex + 1, 'u') + "" | ||
+ copyCase(originalText, startIndex + 3, 'g'); | ||
} | ||
|
||
private char copyCase(String original, int index, char newChar) { | ||
if (Character.isUpperCase(original.charAt(index))) { | ||
return Character.toUpperCase(newChar); | ||
} else { | ||
return newChar; | ||
} | ||
} | ||
|
||
private void sendWebhookMessage(Webhook webhook, Message originalMessage, String newMessageContent, long threadId) { | ||
WebhookUtil.mirrorMessageToWebhook(webhook, originalMessage, newMessageContent, threadId) | ||
.thenAccept(unused -> originalMessage.delete().queue()).exceptionally(e -> { | ||
log.error("replacing the content 'fuck' with 'hug' in an incoming message failed", e); | ||
return null; | ||
}); | ||
} | ||
} |
93 changes: 93 additions & 0 deletions
93
src/main/java/net/javadiscord/javabot/util/WebhookUtil.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
package net.javadiscord.javabot.util; | ||
|
||
import java.util.List; | ||
import java.util.Optional; | ||
import java.util.concurrent.CompletableFuture; | ||
import java.util.function.Consumer; | ||
|
||
import club.minnced.discord.webhook.WebhookClientBuilder; | ||
import club.minnced.discord.webhook.external.JDAWebhookClient; | ||
import club.minnced.discord.webhook.send.AllowedMentions; | ||
import club.minnced.discord.webhook.send.WebhookMessageBuilder; | ||
import net.dv8tion.jda.api.entities.Message; | ||
import net.dv8tion.jda.api.entities.TextChannel; | ||
import net.dv8tion.jda.api.entities.Webhook; | ||
import net.dv8tion.jda.api.entities.Message.Attachment; | ||
|
||
/** | ||
* Contains utility methods for dealing with Discord Webhooks. | ||
*/ | ||
public class WebhookUtil { | ||
private WebhookUtil() { | ||
} | ||
|
||
/** | ||
* Makes sure that a writable webhook exists in a specific channel. if no | ||
* suitable webhook is found, one is created. | ||
* | ||
* @param channel the {@link TextChannel} the webhook should exist in | ||
* @param callback an action that is executed once a webhook is | ||
* found/created | ||
*/ | ||
public static void ensureWebhookExists(TextChannel channel, Consumer<? super Webhook> callback) { | ||
ensureWebhookExists(channel, callback, err -> { | ||
}); | ||
} | ||
|
||
/** | ||
* Makes sure that a writable webhook exists in a specific channel. if no | ||
* suitable webhook is found, one is created. | ||
* | ||
* @param channel the {@link TextChannel} the webhook should exist in | ||
* @param callback an action that is executed once a webhook is | ||
* found/created | ||
* @param failureCallback an action that is executed if the webhook | ||
* lookup/creation failed | ||
*/ | ||
public static void ensureWebhookExists(TextChannel channel, Consumer<? super Webhook> callback, | ||
Consumer<? super Throwable> failureCallback) { | ||
|
||
channel.retrieveWebhooks().queue(webhooks -> { | ||
Optional<Webhook> hook = webhooks.stream() | ||
.filter(webhook -> webhook.getChannel().getIdLong() == channel.getIdLong()) | ||
.filter(wh -> wh.getToken() != null).findAny(); | ||
if (hook.isPresent()) { | ||
callback.accept(hook.get()); | ||
} else { | ||
channel.createWebhook("JavaBot-webhook").queue(callback, failureCallback); | ||
} | ||
}, failureCallback); | ||
} | ||
|
||
/** | ||
* Resends a specific message using a webhook with a custom content. | ||
* | ||
* @param webhook the webhook used for sending the message | ||
* @param originalMessage the message to copy | ||
* @param newMessageContent the new (custom) content | ||
* @param threadId the thread to send the message in or {@code 0} if the | ||
* message should be sent directly | ||
* @return a {@link CompletableFuture} representing the action of sending | ||
* the message | ||
*/ | ||
public static CompletableFuture<Void> mirrorMessageToWebhook(Webhook webhook, Message originalMessage, | ||
String newMessageContent, long threadId) { | ||
JDAWebhookClient client = new WebhookClientBuilder(webhook.getIdLong(), webhook.getToken()) | ||
.setThreadId(threadId).buildJDA(); | ||
WebhookMessageBuilder message = new WebhookMessageBuilder().setContent(newMessageContent) | ||
.setAllowedMentions(AllowedMentions.none()) | ||
.setAvatarUrl(originalMessage.getMember().getEffectiveAvatarUrl()) | ||
.setUsername(originalMessage.getMember().getEffectiveName()); | ||
|
||
List<Attachment> attachments = originalMessage.getAttachments(); | ||
@SuppressWarnings("unchecked") | ||
CompletableFuture<?>[] futures = new CompletableFuture<?>[attachments.size()]; | ||
for (int i = 0; i < attachments.size(); i++) { | ||
Attachment attachment = attachments.get(i); | ||
futures[i] = attachment.getProxy().download().thenAccept( | ||
is -> message.addFile((attachment.isSpoiler() ? "SPOILER_" : "") + attachment.getFileName(), is)); | ||
} | ||
return CompletableFuture.allOf(futures).thenAccept(unused -> client.send(message.build())) | ||
.whenComplete((result, err) -> client.close()); | ||
} | ||
} |