Skip to content

Commit

Permalink
Add a sign logger to admin chat
Browse files Browse the repository at this point in the history
Signed-off-by: applenick <[email protected]>
  • Loading branch information
applenick committed Aug 28, 2024
1 parent 7e1126c commit 4317335
Show file tree
Hide file tree
Showing 4 changed files with 128 additions and 88 deletions.
3 changes: 3 additions & 0 deletions src/main/java/dev/pgm/community/CommunityPermissions.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ public interface CommunityPermissions {
String PUNISHMENT_BROADCASTS =
ROOT + ".view-punishments"; // Access to view when punishments are broadcast silently

// Sign Logger
String SIGN_LOG_BROADCASTS = ROOT + ".view-sign-logs"; // Access to view when signs are placed

// Reports
String REPORTS = ROOT + ".reports"; // Access to view report broadcast & report history
String REPORT_BROADCASTS = REPORTS + ".view-broadcasts"; // Access to view report broadcasts
Expand Down
12 changes: 12 additions & 0 deletions src/main/java/dev/pgm/community/moderation/ModerationConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ public class ModerationConfig extends FeatureConfigImpl {
private static final String PLAYER_HOOK_KEY = TOOLS_KEY + ".player-hook";
private static final String LOOKUP_SIGN_KEY = TOOLS_KEY + ".lookup-sign";

private static final String SIGN_LOGGER_KEY = KEY + ".sign-logger";

// General options
private boolean persist;
private boolean broadcast;
Expand Down Expand Up @@ -88,6 +90,9 @@ public class ModerationConfig extends FeatureConfigImpl {
private int playerHookSlot;
private int lookupSignSlot;

// Sign Logger
private boolean signLoggerEnabled;

/**
* Config options related to {@link ModerationFeature}
*
Expand Down Expand Up @@ -251,6 +256,10 @@ public String getStaffBroadcastFormat() {
return staffBroadcastFormat;
}

public boolean isSignLoggerEnabled() {
return signLoggerEnabled;
}

@Override
public void reload(Configuration config) {
super.reload(config);
Expand Down Expand Up @@ -299,5 +308,8 @@ public void reload(Configuration config) {
this.modMenuSlot = config.getInt(getItemSlotKey(MOD_MENU_KEY));
this.playerHookSlot = config.getInt(getItemSlotKey(PLAYER_HOOK_KEY));
this.lookupSignSlot = config.getInt(getItemSlotKey(LOOKUP_SIGN_KEY));

// Sign Logger
this.signLoggerEnabled = config.getBoolean(getEnabledKey(SIGN_LOGGER_KEY));
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package dev.pgm.community.moderation.feature;

import static net.kyori.adventure.text.Component.text;
import static tc.oc.pgm.util.player.PlayerComponent.player;

import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
Expand All @@ -27,6 +28,7 @@
import dev.pgm.community.utils.Sounds;
import java.time.Duration;
import java.time.Instant;
import java.util.Arrays;
import java.util.List;
import java.util.Map.Entry;
import java.util.Optional;
Expand All @@ -37,9 +39,12 @@
import java.util.stream.Collectors;
import javax.annotation.Nullable;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.event.ClickEvent;
import net.kyori.adventure.text.event.HoverEvent;
import net.kyori.adventure.text.format.NamedTextColor;
import net.kyori.adventure.text.format.TextDecoration;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
Expand All @@ -50,7 +55,6 @@
import org.bukkit.event.player.PlayerJoinEvent;
import tc.oc.pgm.util.Audience;
import tc.oc.pgm.util.named.NameStyle;
import tc.oc.pgm.util.player.PlayerComponent;

public abstract class ModerationFeatureBase extends FeatureBase implements ModerationFeature {

Expand All @@ -77,18 +81,16 @@ public ModerationFeatureBase(
this.network = network;
this.recents = Sets.newHashSet();
this.muteCache = CacheBuilder.newBuilder().build();
this.banEvasionCache =
CacheBuilder.newBuilder()
.expireAfterWrite(config.getEvasionExpireMins(), TimeUnit.MINUTES)
.build();
this.banEvasionCache = CacheBuilder.newBuilder()
.expireAfterWrite(config.getEvasionExpireMins(), TimeUnit.MINUTES)
.build();
this.observerBanCache = CacheBuilder.newBuilder().build();
this.pardonedPlayers = CacheBuilder.newBuilder().build();

if (config.getMatchBanDuration() != null) {
this.matchBan =
CacheBuilder.newBuilder()
.expireAfterWrite(config.getMatchBanDuration().getSeconds(), TimeUnit.SECONDS)
.build();
this.matchBan = CacheBuilder.newBuilder()
.expireAfterWrite(config.getMatchBanDuration().getSeconds(), TimeUnit.SECONDS)
.build();
}

if (config.isEnabled()) {
Expand Down Expand Up @@ -132,19 +134,18 @@ public Punishment punish(
boolean active,
boolean silent) {
Instant time = Instant.now();
Punishment punishment =
Punishment.of(
UUID.randomUUID(),
target,
getSenderId(issuer.getSender()),
reason,
time.toEpochMilli(),
duration,
type,
active,
time.toEpochMilli(),
getSenderId(issuer.getSender()),
getModerationConfig().getService());
Punishment punishment = Punishment.of(
UUID.randomUUID(),
target,
getSenderId(issuer.getSender()),
reason,
time.toEpochMilli(),
duration,
type,
active,
time.toEpochMilli(),
getSenderId(issuer.getSender()),
getModerationConfig().getService());
Bukkit.getPluginManager().callEvent(new PlayerPunishmentEvent(issuer, punishment, silent));
return punishment;
}
Expand Down Expand Up @@ -213,11 +214,10 @@ public void onPunishmentEvent(PlayerPunishmentEvent event) {
&& onlineTarget.get().hasPermission(CommunityPermissions.ADMIN)) {
event
.getSender()
.sendWarning(
text()
.append(PlayerComponent.player(onlineTarget.get(), NameStyle.FANCY))
.append(text(" is exempt from punishment"))
.build());
.sendWarning(text()
.append(player(onlineTarget.get(), NameStyle.FANCY))
.append(text(" is exempt from punishment"))
.build());
return;
}
} else if (PunishmentType.WARN.equals(punishment.getType())
Expand All @@ -232,9 +232,8 @@ public void onPunishmentEvent(PlayerPunishmentEvent event) {

punishment.punish(event.isSilent()); // Perform the actual punishment

sendUpdate(
new NetworkPunishment(
punishment, network.getNetworkId())); // Send out network punishment update
sendUpdate(new NetworkPunishment(
punishment, network.getNetworkId())); // Send out network punishment update

switch (punishment.getType()) {
// Cache known IPS of a recently banned player, so if they rejoin on an alt we can find them
Expand Down Expand Up @@ -272,44 +271,43 @@ public void onPlayerJoinEvasionCheck(PlayerJoinEvent event) {
boolean exclude = hasRecentPardon(event.getPlayer().getUniqueId());

if (banEvasion.isPresent() && !exclude) {
users
.renderUsername(banEvasion, NameStyle.FANCY)
.thenAcceptAsync(
bannedName -> {
if (!banEvasion.get().equals(event.getPlayer().getUniqueId())) {
BroadcastUtils.sendAdminChatMessage(
PunishmentFormats.formatBanEvasion(
event.getPlayer(), banEvasion.get(), bannedName),
Sounds.BAN_EVASION,
CommunityPermissions.UNBAN);
}
});
users.renderUsername(banEvasion, NameStyle.FANCY).thenAcceptAsync(bannedName -> {
if (!banEvasion.get().equals(event.getPlayer().getUniqueId())) {
BroadcastUtils.sendAdminChatMessage(
PunishmentFormats.formatBanEvasion(event.getPlayer(), banEvasion.get(), bannedName),
Sounds.BAN_EVASION,
CommunityPermissions.UNBAN);
}
});
}
}

// Cancel chat for muted/banned players
@EventHandler(priority = EventPriority.HIGHEST)
public void onAsyncPlayerChatEvent(AsyncPlayerChatEvent event) {
// MUTES
getCachedMute(event.getPlayer().getUniqueId())
.ifPresent(
mute -> {
event.setCancelled(true);
Audience.get(event.getPlayer()).sendWarning(mute.getChatMuteMessage());
});
getCachedMute(event.getPlayer().getUniqueId()).ifPresent(mute -> {
event.setCancelled(true);
Audience.get(event.getPlayer()).sendWarning(mute.getChatMuteMessage());
});
}

// Clear sign text for muted players
@EventHandler(priority = EventPriority.HIGHEST)
public void onPlaceSign(SignChangeEvent event) {
getCachedMute(event.getPlayer().getUniqueId())
.ifPresent(
mute -> {
for (int i = 0; i < 4; i++) {
event.setLine(i, " ");
}
Audience.get(event.getPlayer()).sendWarning(mute.getSignMuteMessage());
});
// Prevent muted players from using signs
Optional<MutePunishment> mute = getCachedMute(event.getPlayer().getUniqueId());

if (mute.isPresent()) {
for (int i = 0; i < 4; i++) {
event.setLine(i, " ");
}
Audience.get(event.getPlayer()).sendWarning(mute.get().getSignMuteMessage());

return;
}

// Log sign text to file & chat when enabled
logSign(event.getPlayer(), event.getLines(), event.getBlock().getLocation());
}

// BANS
Expand Down Expand Up @@ -352,10 +350,9 @@ private UUID getSenderId(CommandSender sender) {
}

private Optional<UUID> isBanEvasion(String address) {
Optional<Entry<UUID, Set<String>>> cached =
banEvasionCache.asMap().entrySet().stream()
.filter(s -> s.getValue().contains(address))
.findAny();
Optional<Entry<UUID, Set<String>>> cached = banEvasionCache.asMap().entrySet().stream()
.filter(s -> s.getValue().contains(address))
.findAny();
return Optional.ofNullable(cached.isPresent() ? cached.get().getKey() : null);
}

Expand All @@ -367,36 +364,32 @@ private void banHover() {
color = !color;
NamedTextColor alertColor = color ? NamedTextColor.YELLOW : NamedTextColor.DARK_RED;
Component warning = text(" \u26a0 ", alertColor);
Component banned =
text()
.append(warning)
.append(text("You have been banned", NamedTextColor.RED, TextDecoration.BOLD))
.append(warning)
.build();
Component banned = text()
.append(warning)
.append(text("You have been banned", NamedTextColor.RED, TextDecoration.BOLD))
.append(warning)
.build();

this.observerBanCache.asMap().keySet().stream()
.filter(id -> Bukkit.getPlayer(id) != null)
.map(Bukkit::getPlayer)
.map(Audience::get)
.forEach(
viewer -> {
viewer.sendActionBar(banned);
});
.forEach(viewer -> {
viewer.sendActionBar(banned);
});
}

private Audience getStaffAudience() {
List<Player> staff =
Bukkit.getOnlinePlayers().stream()
.filter(p -> p.hasPermission(CommunityPermissions.PUNISHMENT_BROADCASTS))
.collect(Collectors.toList());
List<Player> staff = Bukkit.getOnlinePlayers().stream()
.filter(p -> p.hasPermission(CommunityPermissions.PUNISHMENT_BROADCASTS))
.collect(Collectors.toList());
return Audience.get(staff);
}

private Audience getGlobalAudience() {
List<Player> normal =
Bukkit.getOnlinePlayers().stream()
.filter(p -> !p.hasPermission(CommunityPermissions.PUNISHMENT_BROADCASTS))
.collect(Collectors.toList());
List<Player> normal = Bukkit.getOnlinePlayers().stream()
.filter(p -> !p.hasPermission(CommunityPermissions.PUNISHMENT_BROADCASTS))
.collect(Collectors.toList());
return Audience.get(normal);
}

Expand All @@ -412,17 +405,45 @@ private void broadcastPunishment(

if (global) {
PunishmentFormats.formatBroadcast(punishment, server, getGlobalFormat(), users)
.thenAcceptAsync(
broadcast -> {
getGlobalAudience().sendMessage(broadcast);
});
.thenAcceptAsync(broadcast -> {
getGlobalAudience().sendMessage(broadcast);
});
}

PunishmentFormats.formatBroadcast(punishment, server, getStaffFormat(), users)
.thenAcceptAsync(
broadcast -> {
BroadcastUtils.sendAdminChatMessage(
broadcast, CommunityPermissions.PUNISHMENT_BROADCASTS);
});
.thenAcceptAsync(broadcast -> {
BroadcastUtils.sendAdminChatMessage(
broadcast, CommunityPermissions.PUNISHMENT_BROADCASTS);
});
}

private void logSign(Player player, String[] lines, Location location) {
if (!getModerationConfig().isSignLoggerEnabled()) return;

int totalChars = 0;
for (String line : lines) {
totalChars += line.length();
}

if (totalChars < 4) return; // Don't track signs with barely any text

String locString =
String.format("%d %d %d", location.getBlockX(), location.getBlockY(), location.getBlockZ());

String oneLineSign = Arrays.stream(lines)
.map(line -> line.trim())
.filter(line -> !line.isBlank() && !line.isEmpty())
.collect(Collectors.joining(" "));

Component alert = text()
.append(player(player, NameStyle.FANCY))
.append(text(" placed a sign: \"", NamedTextColor.GRAY))
.append(text(oneLineSign, NamedTextColor.YELLOW))
.append(text("\"", NamedTextColor.GRAY))
.clickEvent(ClickEvent.runCommand("/tploc " + locString))
.hoverEvent(HoverEvent.showText(text("Click to teleport to sign", NamedTextColor.GRAY)))
.build();

BroadcastUtils.sendAdminChatMessage(alert, CommunityPermissions.SIGN_LOG_BROADCASTS);
}
}
4 changes: 4 additions & 0 deletions src/main/resources/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,10 @@ moderation:
enabled: true
public: true

# Sign Logging
sign-logger:
enabled: true

#Logins
login-timeout: 30

Expand Down

0 comments on commit 4317335

Please sign in to comment.