Allow players to report offline players & allow admins to mark reports as completed, deleting them and sending them to an archive channel

This commit is contained in:
Allink 2022-05-26 16:10:00 +01:00
parent 09a220e0a2
commit 9c91166319
No known key found for this signature in database
GPG Key ID: 7F1F1B98F0FAAD13
7 changed files with 167 additions and 28 deletions

View File

@ -175,15 +175,15 @@ public class ChatManager extends FreedomService
}); });
} }
public void reportAction(Player reporter, Player reported, String report) public void reportAction(Player reporter, String reportedName, String report)
{ {
for (Player player : server.getOnlinePlayers()) for (Player player : server.getOnlinePlayers())
{ {
if (plugin.al.isAdmin(player)) if (plugin.al.isAdmin(player))
{ {
playerMsg(player, ChatColor.RED + "[REPORTS] " + ChatColor.GOLD + reporter.getName() + " has reported " + reported.getName() + " for " + report); playerMsg(player, ChatColor.RED + "[REPORTS] " + ChatColor.GOLD + reporter.getName() + " has reported " + reportedName + " for " + report);
} }
} }
FLog.info("[REPORTS] " + reporter.getName() + " has reported " + reported.getName() + " for " + report); FLog.info("[REPORTS] " + reporter.getName() + " has reported " + reportedName + " for " + report);
} }
} }

View File

@ -4,6 +4,7 @@ import me.totalfreedom.totalfreedommod.rank.Rank;
import org.apache.commons.lang.ArrayUtils; import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.StringUtils;
import org.bukkit.ChatColor; import org.bukkit.ChatColor;
import org.bukkit.OfflinePlayer;
import org.bukkit.command.Command; import org.bukkit.command.Command;
import org.bukkit.command.CommandSender; import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
@ -22,13 +23,15 @@ public class Command_report extends FreedomCommand
} }
Player player = getPlayer(args[0], true); Player player = getPlayer(args[0], true);
OfflinePlayer offlinePlayer = getOfflinePlayer(args[0]);
if (player == null) if (player == null && offlinePlayer == null)
{ {
msg(PLAYER_NOT_FOUND); msg(PLAYER_NOT_FOUND);
return true; return true;
} }
else if (player != null)
{
if (sender instanceof Player) if (sender instanceof Player)
{ {
if (player.equals(playerSender)) if (player.equals(playerSender))
@ -44,14 +47,16 @@ public class Command_report extends FreedomCommand
return true; return true;
} }
}
String report = StringUtils.join(ArrayUtils.subarray(args, 1, args.length), " "); String report = StringUtils.join(ArrayUtils.subarray(args, 1, args.length), " ");
plugin.cm.reportAction(playerSender, player, report); plugin.cm.reportAction(playerSender, (player == null) ? offlinePlayer.getName() : player.getName(), report);
boolean logged = false; boolean logged = false;
if (plugin.dc.enabled) if (plugin.dc.enabled)
{ {
logged = plugin.dc.sendReport(playerSender, player, report); logged = (player == null) ? plugin.dc.sendReportOffline(playerSender, offlinePlayer, report) : plugin.dc.sendReport(playerSender, player, report);
} }
msg(ChatColor.GREEN + "Thank you, your report has been successfully logged." msg(ChatColor.GREEN + "Thank you, your report has been successfully logged."

View File

@ -1,14 +1,10 @@
package me.totalfreedom.totalfreedommod.command; package me.totalfreedom.totalfreedommod.command;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.util.ArrayList; import java.util.*;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Timer;
import java.util.TimerTask;
import me.totalfreedom.totalfreedommod.TotalFreedomMod; import me.totalfreedom.totalfreedommod.TotalFreedomMod;
import me.totalfreedom.totalfreedommod.admin.Admin; import me.totalfreedom.totalfreedommod.admin.Admin;
import me.totalfreedom.totalfreedommod.player.PlayerData; import me.totalfreedom.totalfreedommod.player.PlayerData;
@ -18,12 +14,14 @@ import me.totalfreedom.totalfreedommod.util.FUtil;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.StringUtils;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.ChatColor; import org.bukkit.ChatColor;
import org.bukkit.OfflinePlayer;
import org.bukkit.Server; import org.bukkit.Server;
import org.bukkit.command.*; import org.bukkit.command.*;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.plugin.Plugin; import org.bukkit.plugin.Plugin;
import org.bukkit.util.StringUtil; import org.bukkit.util.StringUtil;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public abstract class FreedomCommand implements CommandExecutor, TabCompleter public abstract class FreedomCommand implements CommandExecutor, TabCompleter
{ {
@ -229,6 +227,16 @@ public abstract class FreedomCommand implements CommandExecutor, TabCompleter
return player; return player;
} }
@Nullable
protected OfflinePlayer getOfflinePlayer(String name)
{
return Arrays.stream(Bukkit.getOfflinePlayers())
.filter(player -> player.getName() != null)
.filter(player -> player.getName().equalsIgnoreCase(name))
.findFirst()
.orElse(null);
}
protected Admin getAdmin(CommandSender sender) protected Admin getAdmin(CommandSender sender)
{ {
return plugin.al.getAdmin(sender); return plugin.al.getAdmin(sender);

View File

@ -76,6 +76,7 @@ public enum ConfigEntry
DISCORD_TOKEN(String.class, "discord.token"), DISCORD_TOKEN(String.class, "discord.token"),
DISCORD_PREFIX(String.class, "discord.prefix"), DISCORD_PREFIX(String.class, "discord.prefix"),
DISCORD_REPORT_CHANNEL_ID(String.class, "discord.report_channel_id"), DISCORD_REPORT_CHANNEL_ID(String.class, "discord.report_channel_id"),
DISCORD_REPORT_ARCHIVE_CHANNEL_ID(String.class, "discord.report_archive_channel_id"),
DISCORD_CHAT_CHANNEL_ID(String.class, "discord.chat_channel_id"), DISCORD_CHAT_CHANNEL_ID(String.class, "discord.chat_channel_id"),
DISCORD_ADMINCHAT_CHANNEL_ID(String.class, "discord.adminchat_channel_id"), DISCORD_ADMINCHAT_CHANNEL_ID(String.class, "discord.adminchat_channel_id"),

View File

@ -47,6 +47,7 @@ import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.WordUtils; import org.apache.commons.lang.WordUtils;
import org.apache.commons.lang3.RandomStringUtils; import org.apache.commons.lang3.RandomStringUtils;
import org.bukkit.GameRule; import org.bukkit.GameRule;
import org.bukkit.OfflinePlayer;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler; import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority; import org.bukkit.event.EventPriority;
@ -64,7 +65,7 @@ public class Discord extends FreedomService
public ScheduledThreadPoolExecutor RATELIMIT_EXECUTOR; public ScheduledThreadPoolExecutor RATELIMIT_EXECUTOR;
public List<CompletableFuture<Message>> sentMessages = new ArrayList<>(); public List<CompletableFuture<Message>> sentMessages = new ArrayList<>();
public Boolean enabled = false; public Boolean enabled = false;
private final ImmutableList<String> DISCORD_SUBDOMAINS = ImmutableList.of("discordapp.com", "discord.com", "discord.gg"); private static final ImmutableList<String> DISCORD_SUBDOMAINS = ImmutableList.of("discordapp.com", "discord.com", "discord.gg");
private final Pattern DISCORD_MENTION_PATTERN = Pattern.compile("(<@!?([0-9]{16,20})>)"); private final Pattern DISCORD_MENTION_PATTERN = Pattern.compile("(<@!?([0-9]{16,20})>)");
public static String getCode(PlayerData playerData) public static String getCode(PlayerData playerData)
@ -180,6 +181,7 @@ public class Discord extends FreedomService
.addEventListeners(new PrivateMessageListener(), .addEventListeners(new PrivateMessageListener(),
new DiscordToMinecraftListener(), new DiscordToMinecraftListener(),
new DiscordToAdminChatListener(), new DiscordToAdminChatListener(),
new MessageReactionListener(),
new ListenerAdapter() new ListenerAdapter()
{ {
@Override @Override
@ -303,7 +305,7 @@ public class Discord extends FreedomService
} }
} }
public String sanitizeChatMessage(String message) public static String sanitizeChatMessage(String message)
{ {
String newMessage = message; String newMessage = message;
@ -397,12 +399,12 @@ public class Discord extends FreedomService
FLog.info("Discord integration has successfully shutdown."); FLog.info("Discord integration has successfully shutdown.");
} }
public String deformat(String input) public static String deformat(String input)
{ {
return input.replaceAll("([_\\\\`*>|])", "\\\\$1"); return input.replaceAll("([_\\\\`*>|])", "\\\\$1");
} }
public boolean sendReport(Player reporter, Player reported, String reason) public boolean shouldISendReport()
{ {
if (ConfigEntry.DISCORD_REPORT_CHANNEL_ID.getString().isEmpty()) if (ConfigEntry.DISCORD_REPORT_CHANNEL_ID.getString().isEmpty())
{ {
@ -430,7 +432,54 @@ public class Discord extends FreedomService
return false; return false;
} }
EmbedBuilder embedBuilder = new EmbedBuilder(); return true;
}
public boolean sendReportOffline(Player reporter, OfflinePlayer reported, String reason)
{
if (!shouldISendReport())
{
return false;
}
final Guild server = bot.getGuildById(ConfigEntry.DISCORD_SERVER_ID.getString());
final TextChannel channel = server.getTextChannelById(ConfigEntry.DISCORD_REPORT_CHANNEL_ID.getString());
final EmbedBuilder embedBuilder = new EmbedBuilder();
embedBuilder.setTitle("Report for " + reported.getName() + " (offline)");
embedBuilder.setDescription(reason);
embedBuilder.setFooter("Reported by " + reporter.getName(), "https://minotar.net/helm/" + reporter.getName() + ".png");
embedBuilder.setTimestamp(Instant.from(ZonedDateTime.now()));
com.earth2me.essentials.User user = plugin.esb.getEssentialsUser(reported.getName());
String location = "World: " + Objects.requireNonNull(user.getLastLocation().getWorld()).getName() + ", X: " + user.getLastLocation().getBlockX() + ", Y: " + user.getLastLocation().getBlockY() + ", Z: " + user.getLastLocation().getBlockZ();
embedBuilder.addField("Location", location, true);
embedBuilder.addField("God Mode", WordUtils.capitalizeFully(String.valueOf(user.isGodModeEnabled())), true);
if (user.getNickname() != null)
{
embedBuilder.addField("Nickname", user.getNickname(), true);
}
MessageEmbed embed = embedBuilder.build();
Message message = channel.sendMessage(embed).complete();
if (!ConfigEntry.DISCORD_REPORT_ARCHIVE_CHANNEL_ID.getString().isEmpty())
{
message.addReaction("\uD83D\uDCCB").complete();
}
return true;
}
public boolean sendReport(Player reporter, Player reported, String reason)
{
if (!shouldISendReport())
{
return false;
}
final Guild server = bot.getGuildById(ConfigEntry.DISCORD_SERVER_ID.getString());
final TextChannel channel = server.getTextChannelById(ConfigEntry.DISCORD_REPORT_CHANNEL_ID.getString());
final EmbedBuilder embedBuilder = new EmbedBuilder();
embedBuilder.setTitle("Report for " + reported.getName()); embedBuilder.setTitle("Report for " + reported.getName());
embedBuilder.setDescription(reason); embedBuilder.setDescription(reason);
embedBuilder.setFooter("Reported by " + reporter.getName(), "https://minotar.net/helm/" + reporter.getName() + ".png"); embedBuilder.setFooter("Reported by " + reporter.getName(), "https://minotar.net/helm/" + reporter.getName() + ".png");
@ -445,7 +494,13 @@ public class Discord extends FreedomService
embedBuilder.addField("Nickname", user.getNickname(), true); embedBuilder.addField("Nickname", user.getNickname(), true);
} }
MessageEmbed embed = embedBuilder.build(); MessageEmbed embed = embedBuilder.build();
channel.sendMessage(embed).complete(); Message message = channel.sendMessage(embed).complete();
if (!ConfigEntry.DISCORD_REPORT_ARCHIVE_CHANNEL_ID.getString().isEmpty())
{
message.addReaction("\uD83D\uDCCB").complete();
}
return true; return true;
} }

View File

@ -0,0 +1,68 @@
package me.totalfreedom.totalfreedommod.discord;
import me.totalfreedom.totalfreedommod.config.ConfigEntry;
import me.totalfreedom.totalfreedommod.util.FLog;
import net.dv8tion.jda.api.MessageBuilder;
import net.dv8tion.jda.api.entities.Member;
import net.dv8tion.jda.api.entities.Message;
import net.dv8tion.jda.api.entities.MessageEmbed;
import net.dv8tion.jda.api.entities.TextChannel;
import net.dv8tion.jda.api.events.message.react.MessageReactionAddEvent;
import net.dv8tion.jda.api.hooks.ListenerAdapter;
public class MessageReactionListener extends ListenerAdapter
{
public void onMessageReactionAdd(MessageReactionAddEvent messageReactionAddEvent)
{
if (!messageReactionAddEvent.isFromGuild())
{
return;
}
if (messageReactionAddEvent.getMember() == null)
{
return;
}
if (messageReactionAddEvent.getMember().getUser().getId().equals(Discord.bot.getSelfUser().getId()))
{
return;
}
if (!messageReactionAddEvent.getChannel().getId().equals(ConfigEntry.DISCORD_REPORT_CHANNEL_ID.getString()))
{
return;
}
if (!messageReactionAddEvent.getReactionEmote().getEmoji().equals("\uD83D\uDCCB"))
{
return;
}
final TextChannel archiveChannel = Discord.bot.getTextChannelById(ConfigEntry.DISCORD_REPORT_ARCHIVE_CHANNEL_ID.getString());
if (archiveChannel == null)
{
FLog.warning("Report archive channel is defined in the config, yet doesn't actually exist!");
return;
}
final Message message = messageReactionAddEvent.retrieveMessage().complete();
final Member completer = messageReactionAddEvent.getMember();
if (!message.getAuthor().getId().equals(Discord.bot.getSelfUser().getId()))
{
return;
}
// We don't need other embeds... yet?
final MessageEmbed embed = message.getEmbeds().get(0);
final MessageBuilder archiveMessageBuilder = new MessageBuilder();
archiveMessageBuilder.setContent("Report completed by " + Discord.deformat(completer.getUser().getAsTag()));
archiveMessageBuilder.setEmbed(embed);
final Message archiveMessage = archiveMessageBuilder.build();
archiveChannel.sendMessage(archiveMessage).complete();
message.delete().complete();
}
}

View File

@ -64,6 +64,8 @@ discord:
server_id: '' server_id: ''
# Channel to send /report messages to # Channel to send /report messages to
report_channel_id: '' report_channel_id: ''
# Channel to send archived reports to
report_archive_channel_id: ''
# Channel for Discord to Minecraft and vice-versa # Channel for Discord to Minecraft and vice-versa
chat_channel_id: '' chat_channel_id: ''
# Channel for Discord to AdminChat and vice-versa # Channel for Discord to AdminChat and vice-versa