ProjectAres/Commons/bukkit/src/main/java/tc/oc/commons/bukkit/report/ReportCommands.java

193 lines
8.3 KiB
Java

package tc.oc.commons.bukkit.report;
import java.util.Map;
import java.util.WeakHashMap;
import javax.inject.Inject;
import javax.inject.Singleton;
import com.sk89q.minecraft.util.commands.Command;
import com.sk89q.minecraft.util.commands.CommandContext;
import com.sk89q.minecraft.util.commands.CommandException;
import com.sk89q.minecraft.util.commands.CommandPermissions;
import net.md_5.bungee.api.ChatColor;
import net.md_5.bungee.api.chat.TranslatableComponent;
import org.bukkit.command.CommandSender;
import org.bukkit.command.ConsoleCommandSender;
import org.bukkit.entity.Player;
import java.time.Duration;
import java.time.Instant;
import org.bukkit.event.EventHandler;
import org.bukkit.event.player.PlayerQuitEvent;
import tc.oc.api.bukkit.users.BukkitUserStore;
import tc.oc.api.docs.Report;
import tc.oc.api.docs.Server;
import tc.oc.minecraft.scheduler.SyncExecutor;
import tc.oc.api.model.QueryService;
import tc.oc.api.reports.ReportSearchRequest;
import tc.oc.commons.bukkit.chat.Audiences;
import tc.oc.commons.bukkit.chat.HeaderComponent;
import tc.oc.commons.bukkit.chat.NameStyle;
import tc.oc.commons.bukkit.chat.PlayerComponent;
import tc.oc.commons.bukkit.commands.UserFinder;
import tc.oc.commons.bukkit.nick.IdentityProvider;
import tc.oc.commons.core.chat.Audience;
import tc.oc.commons.core.chat.Component;
import tc.oc.commons.core.commands.CommandFutureCallback;
import tc.oc.commons.core.commands.Commands;
import tc.oc.commons.core.commands.TranslatableCommandException;
import tc.oc.commons.core.formatting.PeriodFormats;
import tc.oc.commons.core.util.Comparables;
import tc.oc.minecraft.api.event.Listener;
@Singleton
public class ReportCommands implements Commands, Listener {
private static final int PER_PAGE = 8;
private final ReportFormatter reportFormatter;
private final QueryService<Report> reportService;
private final ReportCreator reportCreator;
private final ReportConfiguration reportConfiguration;
private final UserFinder userFinder;
private final SyncExecutor syncExecutor;
private final Server localServer;
private final BukkitUserStore userStore;
private final Audiences audiences;
private final IdentityProvider identities;
private final Map<CommandSender, Instant> senderLastReport = new WeakHashMap<>();
@Inject ReportCommands(ReportFormatter reportFormatter,
QueryService<Report> reportService,
ReportCreator reportCreator,
ReportConfiguration reportConfiguration,
UserFinder userFinder,
SyncExecutor syncExecutor,
Server localServer,
BukkitUserStore userStore,
Audiences audiences,
IdentityProvider identities) {
this.reportFormatter = reportFormatter;
this.reportService = reportService;
this.reportCreator = reportCreator;
this.reportConfiguration = reportConfiguration;
this.userFinder = userFinder;
this.syncExecutor = syncExecutor;
this.localServer = localServer;
this.userStore = userStore;
this.audiences = audiences;
this.identities = identities;
}
@EventHandler
private void onQuit(PlayerQuitEvent event) {
senderLastReport.remove(event.getPlayer());
}
private void assertEnabled() throws CommandException {
if(!reportConfiguration.enabled()) {
throw new TranslatableCommandException("command.reports.notEnabled");
}
}
@Command(
aliases = { "report" },
usage = "<player> <reason>",
desc = "Report a player who is breaking the rules",
min = 2,
max = -1
)
@CommandPermissions(ReportPermissions.CREATE)
public void report(final CommandContext args, final CommandSender sender) throws CommandException {
assertEnabled();
if(!sender.hasPermission(ReportPermissions.COOLDOWN_EXEMPT)) {
final Instant lastReportTime = senderLastReport.get(sender);
if(lastReportTime != null) {
final Duration timeLeft = reportConfiguration.cooldown().minus(Duration.between(lastReportTime, Instant.now()));
if(Comparables.greaterThan(timeLeft, Duration.ZERO)) {
throw new TranslatableCommandException("command.report.cooldown", PeriodFormats.briefNaturalApproximate(timeLeft));
}
}
}
syncExecutor.callback(
userFinder.findLocalPlayer(sender, args, 0),
CommandFutureCallback.onSuccess(sender, args, response -> {
if(response.player().hasPermission(ReportPermissions.EXEMPT) && !sender.hasPermission(ReportPermissions.OVERRIDE)) {
throw new TranslatableCommandException("command.report.exempt", new PlayerComponent(identities.createIdentity(response)));
}
senderLastReport.put(sender, Instant.now());
syncExecutor.callback(
reportCreator.createReport(
response.user,
sender instanceof Player ? userStore.getUser((Player) sender) : null,
args.getJoinedStrings(1),
sender instanceof ConsoleCommandSender
),
CommandFutureCallback.onSuccess(sender, args, report -> {
audiences.get(sender).sendMessage(
new Component(
new Component(new TranslatableComponent("misc.thankYou"), ChatColor.GREEN),
new Component(" "),
new Component(new TranslatableComponent("command.report.successful.dealtWithMessage"), ChatColor.GOLD)
)
);
})
);
})
);
}
@Command(
aliases = { "reports", "reps" },
usage = "[-a] [-p page] [player]",
flags = "ap:",
desc = "List recent reports on this server, or all servers, optionally filtering by player.",
min = 0,
max = 1
)
@CommandPermissions(ReportPermissions.VIEW)
public void reports(final CommandContext args, final CommandSender sender) throws CommandException {
assertEnabled();
syncExecutor.callback(
userFinder.findUser(sender, args.getString(0, null), UserFinder.Scope.ALL, UserFinder.Default.NULL),
CommandFutureCallback.onSuccess(sender, args, userResult -> {
final int page = args.getFlagInteger('p', 1);
final boolean crossServer = args.hasFlag('a');
ReportSearchRequest request = ReportSearchRequest.create(page, PER_PAGE);
request = userResult != null ? request.forPlayer(userResult.user)
: request.forServer(localServer, crossServer);
syncExecutor.callback(
reportService.find(request),
CommandFutureCallback.onSuccess(sender, args, reportResult -> {
final Component title = new Component(new TranslatableComponent(crossServer ? "command.reports.networkTitle" : "command.reports.serverTitle"),
ChatColor.YELLOW);
if(userResult != null) {
title.extra(" (")
.extra(new PlayerComponent(identities.createIdentity(userResult), NameStyle.VERBOSE))
.extra(")");
}
title.extra(" ")
.extra(new TranslatableComponent("currentPage", String.valueOf(page)), ChatColor.DARK_AQUA);
final Audience audience = audiences.get(sender);
audience.sendMessage(new HeaderComponent(title));
for(Report report : reportResult.documents()) {
if(report.reported() != null) {
audience.sendMessages(reportFormatter.format(report, crossServer, true));
}
}
})
);
})
);
}
}