Skip to content

Commit cf93f9e

Browse files
authored
Merge pull request #520 from ayyhimself/ayys-crazy-attachment-remover
delete blacklisted attachments from message and replace with webhook
2 parents badfb49 + 45611d2 commit cf93f9e

File tree

9 files changed

+336
-130
lines changed

9 files changed

+336
-130
lines changed

src/main/java/net/discordjug/javabot/data/config/GuildConfig.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
import java.lang.reflect.Field;
1919
import java.nio.file.Files;
2020
import java.nio.file.Path;
21+
import java.util.List;
2122
import java.util.Optional;
2223

2324
/**
@@ -37,6 +38,7 @@ public class GuildConfig {
3738
private StarboardConfig starboardConfig;
3839
private MessageCacheConfig messageCacheConfig;
3940
private ServerLockConfig serverLockConfig;
41+
private List<String> blacklistedMessageExtensions = List.of("jar", "exe", "zip");
4042

4143
/**
4244
* Constructor that initializes all Config classes.

src/main/java/net/discordjug/javabot/listener/HugListener.java

Lines changed: 0 additions & 120 deletions
This file was deleted.
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
package net.discordjug.javabot.listener.filter;
2+
3+
import lombok.RequiredArgsConstructor;
4+
import net.discordjug.javabot.data.config.BotConfig;
5+
import net.discordjug.javabot.data.config.GuildConfig;
6+
import net.dv8tion.jda.api.EmbedBuilder;
7+
import net.dv8tion.jda.api.entities.Message;
8+
import net.dv8tion.jda.api.entities.MessageEmbed;
9+
import net.dv8tion.jda.api.events.message.MessageReceivedEvent;
10+
import org.springframework.stereotype.Component;
11+
12+
import java.util.List;
13+
14+
/**
15+
* This {@link MessageFilter} blocks attachments blacklisted using {@link GuildConfig}.
16+
*/
17+
@Component
18+
@RequiredArgsConstructor
19+
public class BlacklistedMessageAttachmentFilter implements MessageFilter {
20+
21+
private final BotConfig botConfig;
22+
23+
@Override
24+
public MessageModificationStatus processMessage(MessageContent content) {
25+
MessageReceivedEvent event = content.event();
26+
List<Message.Attachment> attachments = content.attachments();
27+
List<MessageEmbed> embeds = content.embeds();
28+
GuildConfig guildConfig = botConfig.get(event.getGuild());
29+
List<String> blacklistedMessageExtensions = guildConfig.getBlacklistedMessageExtensions();
30+
boolean removed = attachments.removeIf(attachment -> blacklistedMessageExtensions.contains(attachment.getFileExtension()));
31+
if (removed) {
32+
MessageEmbed attachmentRemovedInfo = new EmbedBuilder()
33+
.setDescription("Disallowed attachments have been removed from this message.")
34+
.build();
35+
embeds.add(attachmentRemovedInfo);
36+
return MessageModificationStatus.MODIFIED;
37+
} else {
38+
return MessageModificationStatus.NOT_MODIFIED;
39+
}
40+
}
41+
}
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
package net.discordjug.javabot.listener.filter;
2+
3+
import lombok.RequiredArgsConstructor;
4+
import org.springframework.stereotype.Component;
5+
6+
import java.util.Objects;
7+
import java.util.regex.Pattern;
8+
9+
/**
10+
* This {@link MessageFilter} replaces all occurrences of 'fuck' in incoming messages with 'hug'.
11+
*/
12+
@Component
13+
@RequiredArgsConstructor
14+
public class HugFilter implements MessageFilter {
15+
16+
private static final Pattern FUCKER = Pattern.compile(
17+
"(fuck)(ing|er|ed|k+)?",
18+
Pattern.CASE_INSENSITIVE
19+
);
20+
21+
@Override
22+
public MessageModificationStatus processMessage(MessageContent content) {
23+
if (!content.event().getMessage().getMentions().getUsers().isEmpty()) {
24+
return MessageModificationStatus.NOT_MODIFIED;
25+
}
26+
String before = content.messageText().toString();
27+
String processed = replaceFucks(content.messageText().toString());
28+
if (!before.equals(processed)) {
29+
content.messageText().setLength(0);
30+
content.messageText().append(processed);
31+
return MessageModificationStatus.MODIFIED;
32+
} else {
33+
return MessageModificationStatus.NOT_MODIFIED;
34+
}
35+
}
36+
37+
private static String processHug(String originalText) {
38+
// FucK -> HuG, FuCk -> Hug
39+
return String.valueOf(copyCase(originalText, 0, 'h')) + copyCase(originalText, 1, 'u') +
40+
copyCase(originalText, 3, 'g');
41+
}
42+
43+
private static String replaceFucks(String str) {
44+
return FUCKER.matcher(str).replaceAll(matchResult -> {
45+
String theFuck = matchResult.group(1);
46+
String suffix = Objects.requireNonNullElse(matchResult.group(2), "");
47+
String processedSuffix = switch (suffix.toLowerCase()) {
48+
case "er", "ed", "ing" -> copyCase(suffix, 0, 'g') + suffix; // fucking, fucker, fucked
49+
case "" -> ""; // just fuck
50+
default -> copyCase(suffix, "g".repeat(suffix.length())); // fuckkkkk...
51+
};
52+
return processHug(theFuck) + processedSuffix;
53+
});
54+
}
55+
56+
private static String copyCase(String source, String toChange) {
57+
if (source.length() != toChange.length()) {
58+
throw new IllegalArgumentException("lengths differ");
59+
}
60+
StringBuilder sb = new StringBuilder();
61+
for (int i = 0; i < source.length(); i++) {
62+
sb.append(copyCase(source, i, toChange.charAt(i)));
63+
}
64+
return sb.toString();
65+
}
66+
67+
private static char copyCase(String original, int index, char newChar) {
68+
if (Character.isUpperCase(original.charAt(index))) {
69+
return Character.toUpperCase(newChar);
70+
} else {
71+
return newChar;
72+
}
73+
}
74+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package net.discordjug.javabot.listener.filter;
2+
3+
import net.dv8tion.jda.api.entities.Message;
4+
import net.dv8tion.jda.api.entities.MessageEmbed;
5+
import net.dv8tion.jda.api.events.message.MessageReceivedEvent;
6+
7+
import java.util.List;
8+
9+
/**
10+
* A class containing modifiable content of a message that has been received.
11+
* @param event The event associated with receiving the message
12+
* @param messageText The text associated with the message
13+
* @param attachments The attachments associated with the message
14+
* @param embeds The embeds associated with the message
15+
*/
16+
public record MessageContent(MessageReceivedEvent event,
17+
StringBuilder messageText,
18+
List<Message.Attachment> attachments,
19+
List<MessageEmbed> embeds) {
20+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
package net.discordjug.javabot.listener.filter;
2+
3+
/**
4+
* This interface is implemented by all message filters.
5+
*
6+
* The {@link MessageContent} is processed by every class implementing {@link MessageFilter}
7+
* unless one of the filters returns {@link MessageModificationStatus#STOP_PROCESSING} which stops further filters from executing.
8+
*/
9+
public interface MessageFilter {
10+
11+
/**
12+
* When a message is received, it is processed by the registered filters.
13+
*
14+
* @param content The content of the new message that will be reposted instead of the received message
15+
* if at least one filter returns {@link MessageModificationStatus#MODIFIED}
16+
* and no filter returns {@link MessageModificationStatus#STOP_PROCESSING}.
17+
* This {@link MessageContent} is built up incrementally by the filters.
18+
* @return the appropriate {@link MessageModificationStatus} based on the filter's processing.
19+
* @see MessageFilterHandler
20+
*/
21+
MessageModificationStatus processMessage(MessageContent content);
22+
23+
}

0 commit comments

Comments
 (0)