fix: rewrite ModerationLogger with proper audit-log correlation
- Fix onMessageDelete: search audit log for entry matching message ID instead of blindly taking l.get(0) (was showing random moderator) - Increase audit log fetch limit from 1 to 5 for better matching - Fix onMessageBulkDelete: same approach - Unify all handlers to use findEntry() for target-matching - Remove unused handle() helper, simplify send() logic
This commit is contained in:
parent
7cc21213b1
commit
43735de681
1 changed files with 106 additions and 92 deletions
|
|
@ -33,142 +33,156 @@ public class ModerationLogger extends ListenerAdapter {
|
||||||
this.messageCache = messageCache;
|
this.messageCache = messageCache;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handle(
|
private void send(final Guild g, final EmbedBuilder eb) {
|
||||||
final Guild g,
|
if (eb == null) return;
|
||||||
final ActionType t,
|
var ch = g.getTextChannelById(configRepo.get("moderation.log_channel_id"));
|
||||||
final int l,
|
if (ch == null) return;
|
||||||
final Function<List<AuditLogEntry>, EmbedBuilder> fn) {
|
ch.sendMessageEmbeds(eb.setTimestamp(OffsetDateTime.now()).build()).queue();
|
||||||
var log = g.getTextChannelById(configRepo.get("moderation.log_channel_id"));
|
|
||||||
if (log == null) {
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
var al = g.retrieveAuditLogs().type(t).limit(l);
|
|
||||||
al.queue(
|
// ── Message delete ──────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onMessageDelete(MessageDeleteEvent e) {
|
||||||
|
var content = messageCache.getContent(e.getMessageId());
|
||||||
|
var g = e.getGuild();
|
||||||
|
g.retrieveAuditLogs().type(ActionType.MESSAGE_DELETE).limit(5).queue(
|
||||||
logs -> {
|
logs -> {
|
||||||
var embed = fn.apply(logs);
|
var entry = logs.stream()
|
||||||
if (embed == null) {
|
.filter(log -> e.getMessageId().equals(log.getTargetId()))
|
||||||
return;
|
.findFirst().orElse(null);
|
||||||
}
|
send(g, LogEmbeds.messageDelete(entry, e.getChannel().getAsMention(), content));
|
||||||
log.sendMessageEmbeds(embed.setTimestamp(OffsetDateTime.now()).build()).queue();
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onMessageDelete(MessageDeleteEvent e) {
|
@Override
|
||||||
var content = messageCache.getContent(e.getMessageId());
|
|
||||||
handle(e.getGuild(), ActionType.MESSAGE_DELETE, 1, l -> md(e, content, l));
|
|
||||||
}
|
|
||||||
|
|
||||||
private EmbedBuilder md(MessageDeleteEvent e, final String c, final List<AuditLogEntry> l) {
|
|
||||||
var entry = l.isEmpty() ? null : l.get(0);
|
|
||||||
return LogEmbeds.messageDelete(entry, e.getChannel().getAsMention(), c);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void onMessageBulkDelete(MessageBulkDeleteEvent e) {
|
public void onMessageBulkDelete(MessageBulkDeleteEvent e) {
|
||||||
handle(e.getGuild(), ActionType.MESSAGE_BULK_DELETE, 1, l -> mbd(e, l));
|
var g = e.getGuild();
|
||||||
}
|
|
||||||
|
|
||||||
private EmbedBuilder mbd(MessageBulkDeleteEvent e, final List<AuditLogEntry> l) {
|
|
||||||
var entry = l.isEmpty() ? null : l.get(0);
|
|
||||||
var size = e.getMessageIds().size();
|
var size = e.getMessageIds().size();
|
||||||
return LogEmbeds.messageBulkDelete(entry, e.getChannel().getAsMention(), size);
|
g.retrieveAuditLogs().type(ActionType.MESSAGE_BULK_DELETE).limit(3).queue(
|
||||||
|
logs -> {
|
||||||
|
var entry = logs.stream().findFirst().orElse(null);
|
||||||
|
send(g, LogEmbeds.messageBulkDelete(entry, e.getChannel().getAsMention(), size));
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onGuildBan(final GuildBanEvent ev) {
|
// ── Ban / Unban ────────────────────────────────────────────────────────────
|
||||||
handle(ev.getGuild(), ActionType.BAN, 1, l -> b(ev, l));
|
|
||||||
|
@Override
|
||||||
|
public void onGuildBan(GuildBanEvent ev) {
|
||||||
|
handle(ev.getGuild(), ActionType.BAN, 5, l -> ban(ev, l));
|
||||||
}
|
}
|
||||||
|
|
||||||
private EmbedBuilder b(final GuildBanEvent ev, final List<AuditLogEntry> l) {
|
private EmbedBuilder ban(GuildBanEvent ev, List<AuditLogEntry> l) {
|
||||||
if (l.isEmpty()) {
|
var entry = findEntry(l, ev.getUser().getId());
|
||||||
return null;
|
if (entry == null) return null;
|
||||||
}
|
return LogEmbeds.ban(
|
||||||
var user = ev.getUser();
|
ev.getUser().getAsMention(),
|
||||||
var e = l.get(0);
|
mod(entry),
|
||||||
var mod = e.getUser() != null ? e.getUser().getAsMention() : "Неизвестно";
|
entry.getReason(),
|
||||||
var reason = e.getReason() != null ? e.getReason() : "Не указана";
|
ev.getUser().getAvatarUrl());
|
||||||
return LogEmbeds.ban(user.getAsMention(), mod, reason, user.getAvatarUrl());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onGuildUnban(final GuildUnbanEvent ev) {
|
@Override
|
||||||
handle(ev.getGuild(), ActionType.UNBAN, 1, l -> ub(ev, l));
|
public void onGuildUnban(GuildUnbanEvent ev) {
|
||||||
|
handle(ev.getGuild(), ActionType.UNBAN, 5, l -> unban(ev, l));
|
||||||
}
|
}
|
||||||
|
|
||||||
private EmbedBuilder ub(final GuildUnbanEvent ev, final List<AuditLogEntry> l) {
|
private EmbedBuilder unban(GuildUnbanEvent ev, List<AuditLogEntry> l) {
|
||||||
if (l.isEmpty()) {
|
var entry = findEntry(l, ev.getUser().getId());
|
||||||
return null;
|
if (entry == null) return null;
|
||||||
}
|
return LogEmbeds.unban(
|
||||||
var user = ev.getUser();
|
ev.getUser().getAsMention(),
|
||||||
var e = l.get(0);
|
mod(entry),
|
||||||
var mod = e.getUser() != null ? e.getUser().getAsMention() : "Неизвестно";
|
ev.getUser().getAvatarUrl());
|
||||||
return LogEmbeds.unban(user.getAsMention(), mod, user.getAvatarUrl());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onGuildMemberRemove(final GuildMemberRemoveEvent ev) {
|
// ── Kick ──────────────────────────────────────────────────────────────────
|
||||||
handle(ev.getGuild(), ActionType.KICK, 1, l -> k(ev, l));
|
|
||||||
|
@Override
|
||||||
|
public void onGuildMemberRemove(GuildMemberRemoveEvent ev) {
|
||||||
|
handle(ev.getGuild(), ActionType.KICK, 5, l -> kick(ev, l));
|
||||||
}
|
}
|
||||||
|
|
||||||
private EmbedBuilder k(final GuildMemberRemoveEvent ev, final List<AuditLogEntry> l) {
|
private EmbedBuilder kick(GuildMemberRemoveEvent ev, List<AuditLogEntry> l) {
|
||||||
if (l.isEmpty()) {
|
var entry = findEntry(l, ev.getUser().getId());
|
||||||
return null;
|
if (entry == null) return null;
|
||||||
}
|
return LogEmbeds.kick(
|
||||||
var e = l.get(0);
|
ev.getUser().getAsMention(),
|
||||||
if (!e.getTargetId().equals(ev.getUser().getId())) {
|
mod(entry),
|
||||||
return null;
|
entry.getReason(),
|
||||||
}
|
ev.getUser().getAvatarUrl());
|
||||||
var mod = e.getUser() != null ? e.getUser().getAsMention() : "Неизвестно";
|
|
||||||
var reason = e.getReason() != null ? e.getReason() : "Не указана";
|
|
||||||
return LogEmbeds.kick(ev.getUser().getAsMention(), mod, reason, ev.getUser().getAvatarUrl());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onGuildMemberUpdateTimeOut(final GuildMemberUpdateTimeOutEvent e) {
|
// ── Timeout ────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onGuildMemberUpdateTimeOut(GuildMemberUpdateTimeOutEvent e) {
|
||||||
var muted = e.getNewTimeOutEnd() != null;
|
var muted = e.getNewTimeOutEnd() != null;
|
||||||
handle(e.getGuild(), ActionType.MEMBER_UPDATE, 5, l -> t(e, muted, l));
|
handle(e.getGuild(), ActionType.MEMBER_UPDATE, 5, l -> timeout(e, muted, l));
|
||||||
}
|
}
|
||||||
|
|
||||||
private EmbedBuilder t(
|
private EmbedBuilder timeout(GuildMemberUpdateTimeOutEvent e, boolean muted, List<AuditLogEntry> l) {
|
||||||
final GuildMemberUpdateTimeOutEvent e, boolean muted, final List<AuditLogEntry> l) {
|
|
||||||
var entry = findEntry(l, e.getUser().getId());
|
var entry = findEntry(l, e.getUser().getId());
|
||||||
if (entry == null) {
|
if (entry == null) return null;
|
||||||
return null;
|
return LogEmbeds.timeout(
|
||||||
}
|
e.getUser().getAsMention(),
|
||||||
var mod = entry.getUser() != null ? entry.getUser().getAsMention() : "Неизвестно";
|
mod(entry),
|
||||||
var end = muted ? e.getNewTimeOutEnd().toEpochSecond() : null;
|
muted,
|
||||||
return LogEmbeds.timeout(e.getUser().getAsMention(), mod, muted, end, entry.getReason());
|
muted ? e.getNewTimeOutEnd().toEpochSecond() : null,
|
||||||
|
entry.getReason());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onGuildVoiceGuildMute(final GuildVoiceGuildMuteEvent e) {
|
// ── Voice mute / deafen ─────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onGuildVoiceGuildMute(GuildVoiceGuildMuteEvent e) {
|
||||||
var muted = e.isGuildMuted();
|
var muted = e.isGuildMuted();
|
||||||
handle(e.getGuild(), ActionType.MEMBER_UPDATE, 5, l -> vm(e, muted, l));
|
handle(e.getGuild(), ActionType.MEMBER_UPDATE, 5, l -> voiceMute(e, muted, l));
|
||||||
}
|
}
|
||||||
|
|
||||||
private EmbedBuilder vm(
|
private EmbedBuilder voiceMute(GuildVoiceGuildMuteEvent e, boolean muted, List<AuditLogEntry> l) {
|
||||||
final GuildVoiceGuildMuteEvent e, final boolean muted, final List<AuditLogEntry> l) {
|
|
||||||
var member = e.getMember();
|
var member = e.getMember();
|
||||||
var ch = e.getVoiceState().getChannel();
|
|
||||||
var entry = findEntry(l, member.getId(), "mute");
|
var entry = findEntry(l, member.getId(), "mute");
|
||||||
var mod = entry != null && entry.getUser() != null ? entry.getUser().getAsMention() : null;
|
return LogEmbeds.voiceMute(
|
||||||
return LogEmbeds.voiceMute(member.getAsMention(), ch.getAsMention(), muted, mod);
|
member.getAsMention(),
|
||||||
|
e.getVoiceState().getChannel().getAsMention(),
|
||||||
|
muted,
|
||||||
|
entry != null ? mod(entry) : null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onGuildVoiceGuildDeafen(final GuildVoiceGuildDeafenEvent e) {
|
@Override
|
||||||
|
public void onGuildVoiceGuildDeafen(GuildVoiceGuildDeafenEvent e) {
|
||||||
var deaf = e.isGuildDeafened();
|
var deaf = e.isGuildDeafened();
|
||||||
handle(e.getGuild(), ActionType.MEMBER_UPDATE, 5, l -> vd(e, deaf, l));
|
handle(e.getGuild(), ActionType.MEMBER_UPDATE, 5, l -> voiceDeafen(e, deaf, l));
|
||||||
}
|
}
|
||||||
|
|
||||||
private EmbedBuilder vd(
|
private EmbedBuilder voiceDeafen(GuildVoiceGuildDeafenEvent e, boolean deaf, List<AuditLogEntry> l) {
|
||||||
final GuildVoiceGuildDeafenEvent e, final boolean deaf, final List<AuditLogEntry> l) {
|
|
||||||
var member = e.getMember();
|
var member = e.getMember();
|
||||||
var ch = e.getVoiceState().getChannel();
|
|
||||||
var entry = findEntry(l, member.getId(), "deaf");
|
var entry = findEntry(l, member.getId(), "deaf");
|
||||||
var mod = entry != null && entry.getUser() != null ? entry.getUser().getAsMention() : null;
|
return LogEmbeds.voiceDeafen(
|
||||||
return LogEmbeds.voiceDeafen(member.getAsMention(), ch.getAsMention(), deaf, mod);
|
member.getAsMention(),
|
||||||
|
e.getVoiceState().getChannel().getAsMention(),
|
||||||
|
deaf,
|
||||||
|
entry != null ? mod(entry) : null);
|
||||||
}
|
}
|
||||||
|
|
||||||
private AuditLogEntry findEntry(
|
// ── Helpers ────────────────────────────────────────────────────────────────
|
||||||
final List<AuditLogEntry> l, final String targetId, final String... key) {
|
|
||||||
|
private void handle(Guild g, ActionType t, int limit, Function<List<AuditLogEntry>, EmbedBuilder> fn) {
|
||||||
|
g.retrieveAuditLogs().type(t).limit(limit).queue(
|
||||||
|
logs -> send(g, fn.apply(logs)));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static AuditLogEntry findEntry(List<AuditLogEntry> l, String targetId, String... key) {
|
||||||
var s = l.stream().filter(e -> targetId.equals(e.getTargetId()));
|
var s = l.stream().filter(e -> targetId.equals(e.getTargetId()));
|
||||||
if (key.length > 0) {
|
if (key.length > 0) {
|
||||||
s = s.filter(e -> e.getChangeByKey(key[0]) != null);
|
s = s.filter(e -> e.getChangeByKey(key[0]) != null);
|
||||||
}
|
}
|
||||||
return s.findFirst().orElse(null);
|
return s.findFirst().orElse(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static String mod(AuditLogEntry e) {
|
||||||
|
return e.getUser() != null ? e.getUser().getAsMention() : "Неизвестно";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue