Created
October 15, 2023 14:07
-
-
Save 4drian3d/b6e1641d23572f5778be71c3e128a47e to your computer and use it in GitHub Desktop.
ChatRegulator Platform Implementation
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
private static final Check[] CHECKS = { | |
RegexCheck.builder() | |
.blockedPatterns( | |
Stream.of( | |
"f[uv4@]ck", | |
"sh[i@lj1y]t", | |
"d[i@lj1y]c(k)?", | |
"b[i@lj1y]tch", | |
"[a@4x]w[3@ex]b[o@0x8]n[a@4x]d[o@0x8]", | |
"p[u@v]ssy", | |
"[i@lj1y]mb[3@ex]c[i@lj1y]l", | |
"m[o@0x8]th[3@ex]rf[u@v]ck[3@ex]r" | |
).map(pattern -> Pattern.compile(pattern, Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CASE)).toList() | |
).controlType(ControlType.BLOCK).build(), | |
FloodCheck.builder().limit(10).controlType(ControlType.BLOCK).build(), | |
SpamCheck.builder().similarLimit(5).source(SourceType.CHAT).build(), | |
CooldownCheck.builder().limit(350).timeUnit(TimeUnit.MILLISECONDS).source(SourceType.CHAT).build(), | |
CapsCheck.builder().limit(25).controlType(ControlType.BLOCK).algorithm(CapsAlgorithm.AMOUNT).build() | |
}; | |
private final ServerDBot plugin; | |
public ChatListener(ServerDBot plugin) { | |
this.plugin = plugin; | |
} | |
@Override | |
public Mono<Void> handle(final MessageCreateEvent event) { | |
return Mono.justOrEmpty(event.getMember()) | |
.map(plugin.infractionManager()::get) | |
.flatMap(player -> { | |
final Message message = event.getMessage(); | |
final String messageString = message.getContent(); | |
final CheckResult result = detect(player, messageString); | |
if (result.isDenied()) { | |
logDetection(result, player, messageString); | |
return event.getMessage().delete(); | |
} | |
player.getChain(SourceType.CHAT).executed(messageString); | |
return Mono.empty(); | |
}); | |
} | |
@Override | |
public Class<MessageCreateEvent> eventClass() { | |
return MessageCreateEvent.class; | |
} | |
private CheckResult detect(InfractionPlayerImpl player, String string) { | |
for (final Check check : CHECKS) { | |
final CheckResult result = check.check(player, string); | |
if (result.isDenied()) { | |
return result; | |
} | |
} | |
return CheckResult.allowed(); | |
} | |
private void logDetection(CheckResult result, InfractionPlayer player, String string) { | |
CheckResult.DeniedCheckResult deniedResult = (CheckResult.DeniedCheckResult) result; | |
plugin.logger().info("Infraction Detected | Player {} | Infraction {} | String {}", player.username(), deniedResult.infractionType(), string); | |
} |
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
public class InfractionPlayerImpl implements InfractionPlayer { | |
private final StringChainImpl stringChain = new StringChainImpl(); | |
private final InfractionCount count = new InfractionCount(); | |
private final Member member; | |
public InfractionPlayerImpl(Member member) { | |
this.member = member; | |
} | |
@Override | |
public @NotNull String username() { | |
return member.getUsername(); | |
} | |
@Override | |
public boolean isOnline() { | |
return true; | |
} | |
@Override | |
public @NotNull StringChainImpl getChain(@NotNull SourceType sourceType) { | |
return stringChain; | |
} | |
@Override | |
public @NotNull InfractionCount getInfractions() { | |
return count; | |
} | |
@Override | |
public @NotNull Audience audience() { | |
return Audience.empty(); | |
} | |
@Override | |
public void sendMessage(@NotNull Component message) { | |
} | |
} |
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
public final class StringChainImpl implements StringChain { | |
private final LinkedList<String> queue = new LinkedList<>(); | |
private final AtomicReference<Instant> lastExecuted = new AtomicReference<>(Instant.now().minusMillis(1_000)); | |
@Override | |
public @NotNull String index(int index) { | |
return queue.get(index); | |
} | |
@Override | |
public @NotNull String first() { | |
return queue.getFirst(); | |
} | |
@Override | |
public @NotNull String last() { | |
return queue.getLast(); | |
} | |
@Override | |
public @NotNull Instant lastExecuted() { | |
return lastExecuted.get(); | |
} | |
@Override | |
public int size() { | |
return queue.size(); | |
} | |
@NotNull | |
@Override | |
public Iterator<String> iterator() { | |
return queue.iterator(); | |
} | |
public void executed(final String string) { | |
final int similarCount = 5; | |
final int size = queue.size(); | |
if (similarCount < size) { | |
while (similarCount < queue.size() + 1) { | |
queue.removeFirst(); | |
} | |
} else if (similarCount == size) { | |
queue.removeFirst(); | |
} | |
queue.add(string); | |
lastExecuted.set(Instant.now()); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment