Add Discord commands like the old bot

This commit is contained in:
Allink 2022-05-25 19:44:45 +01:00
parent 47c30c3283
commit c9f5db0141
No known key found for this signature in database
GPG Key ID: 7F1F1B98F0FAAD13
11 changed files with 486 additions and 8 deletions

View File

@ -74,6 +74,7 @@ public enum ConfigEntry
SERVER_FULL_MOTD(String.class, "server.motds.full"),
//
DISCORD_TOKEN(String.class, "discord.token"),
DISCORD_PREFIX(String.class, "discord.prefix"),
DISCORD_REPORT_CHANNEL_ID(String.class, "discord.report_channel_id"),
DISCORD_CHAT_CHANNEL_ID(String.class, "discord.chat_channel_id"),
DISCORD_ADMINCHAT_CHANNEL_ID(String.class, "discord.adminchat_channel_id"),

View File

@ -18,6 +18,7 @@ import com.google.common.collect.ImmutableList;
import me.totalfreedom.totalfreedommod.FreedomService;
import me.totalfreedom.totalfreedommod.admin.Admin;
import me.totalfreedom.totalfreedommod.config.ConfigEntry;
import me.totalfreedom.totalfreedommod.discord.command.DiscordCommandManager;
import me.totalfreedom.totalfreedommod.player.PlayerData;
import me.totalfreedom.totalfreedommod.rank.Rank;
import me.totalfreedom.totalfreedommod.util.FLog;
@ -59,6 +60,7 @@ public class Discord extends FreedomService
public static HashMap<String, PlayerData> LINK_CODES = new HashMap<>();
public static JDA bot = null;
public static DiscordCommandManager DISCORD_COMMAND_MANAGER;
public ScheduledThreadPoolExecutor RATELIMIT_EXECUTOR;
public List<CompletableFuture<Message>> sentMessages = new ArrayList<>();
public Boolean enabled = false;
@ -153,6 +155,9 @@ public class Discord extends FreedomService
public void startBot()
{
DISCORD_COMMAND_MANAGER = new DiscordCommandManager();
DISCORD_COMMAND_MANAGER.init(this);
enabled = !Strings.isNullOrEmpty(ConfigEntry.DISCORD_TOKEN.getString());
if (!enabled)
{

View File

@ -2,13 +2,12 @@ package me.totalfreedom.totalfreedommod.discord;
import me.totalfreedom.totalfreedommod.TotalFreedomMod;
import me.totalfreedom.totalfreedommod.config.ConfigEntry;
import me.totalfreedom.totalfreedommod.discord.command.DiscordCommandManager;
import me.totalfreedom.totalfreedommod.rank.Rank;
import me.totalfreedom.totalfreedommod.rank.Title;
import me.totalfreedom.totalfreedommod.util.FLog;
import me.totalfreedom.totalfreedommod.util.FUtil;
import net.dv8tion.jda.api.entities.Guild;
import net.dv8tion.jda.api.entities.Member;
import net.dv8tion.jda.api.entities.Message;
import net.dv8tion.jda.api.entities.*;
import net.dv8tion.jda.api.events.message.MessageReceivedEvent;
import net.dv8tion.jda.api.hooks.ListenerAdapter;
import net.md_5.bungee.api.chat.BaseComponent;
@ -25,7 +24,9 @@ public class DiscordToMinecraftListener extends ListenerAdapter
{
public void onMessageReceived(MessageReceivedEvent event)
{
String chat_channel_id = ConfigEntry.DISCORD_CHAT_CHANNEL_ID.getString();
final String chat_channel_id = ConfigEntry.DISCORD_CHAT_CHANNEL_ID.getString();
final MessageChannel genericChannel = event.getChannel();
if (event.getMember() == null)
{
return;
@ -41,14 +42,28 @@ public class DiscordToMinecraftListener extends ListenerAdapter
return;
}
if (!event.getChannel().getId().equals(chat_channel_id))
if (!genericChannel.getId().equals(chat_channel_id))
{
return;
}
Member member = event.getMember();
String tag = getDisplay(member);
Message msg = event.getMessage();
if (!(genericChannel instanceof TextChannel))
{
return;
}
final TextChannel textChannel = (TextChannel) genericChannel;
final Member member = event.getMember();
final String tag = getDisplay(member);
final Message msg = event.getMessage();
final String content = msg.getContentStripped();
if (content.startsWith(ConfigEntry.DISCORD_PREFIX.getString()))
{
Discord.DISCORD_COMMAND_MANAGER.parse(content, member, textChannel);
return;
}
ComponentBuilder emsg = new ComponentBuilder();

View File

@ -0,0 +1,25 @@
package me.totalfreedom.totalfreedommod.discord.command;
import net.dv8tion.jda.api.MessageBuilder;
import net.dv8tion.jda.api.entities.Guild;
import net.dv8tion.jda.api.entities.Member;
import net.dv8tion.jda.api.entities.User;
import java.util.List;
public interface DiscordCommand
{
String getCommandName();
String getDescription();
String getCategory();
List<String> getAliases();
boolean isAdmin();
boolean canExecute(Member member);
MessageBuilder execute(Member member, List<String> args);
}

View File

@ -0,0 +1,15 @@
package me.totalfreedom.totalfreedommod.discord.command;
import net.dv8tion.jda.api.entities.Member;
import java.util.stream.Collectors;
public abstract class DiscordCommandImpl implements DiscordCommand
{
@Override
public boolean canExecute(Member member)
{
//return !isAdmin() || member.getRoles().stream().filter((role -> role.getName().toLowerCase().contains("admin") && !role.getName().toLowerCase().contains("discord"))).toList().size() > 0;
return !isAdmin();
}
}

View File

@ -0,0 +1,84 @@
package me.totalfreedom.totalfreedommod.discord.command;
import me.totalfreedom.totalfreedommod.config.ConfigEntry;
import me.totalfreedom.totalfreedommod.discord.Discord;
import me.totalfreedom.totalfreedommod.util.FLog;
import net.dv8tion.jda.api.EmbedBuilder;
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.TextChannel;
import org.reflections.Reflections;
import java.awt.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
public class DiscordCommandManager
{
public static final String PREFIX = ConfigEntry.DISCORD_PREFIX.getString();
private Discord discord;
public final List<DiscordCommand> commands = new ArrayList<>();
public void init(Discord discord)
{
this.discord = discord;
final Reflections discordCommandsDir = new Reflections("me.totalfreedom.totalfreedommod.discord.commands");
final Set<Class<? extends DiscordCommand>> commandClasses = discordCommandsDir.getSubTypesOf(DiscordCommand.class);
for (Class<? extends DiscordCommand> commandClass : commandClasses)
{
try
{
commands.add(commandClass.getDeclaredConstructor().newInstance());
}
catch (Exception e)
{
FLog.warning("Failed to load Discord command: " + commandClass.getName());
}
}
FLog.info("Loaded " + commands.size() + " Discord commands.");
}
public void parse(String content, Member member, TextChannel channel)
{
List<String> args = new ArrayList<>(Arrays.asList(content.split(" ")));
final String alias = args.remove(0).split(PREFIX)[1]; // The joys of command parsing
for (DiscordCommand command : commands)
{
if (command.getCommandName().equalsIgnoreCase(alias) || command.getAliases().contains(alias.toLowerCase()))
{
if (command.canExecute(member))
{
final MessageBuilder messageBuilder = command.execute(member, args);
final Message message = messageBuilder.build();
final CompletableFuture<Message> futureMessage = channel.sendMessage(message).submit(true);
this.discord.sentMessages.add(futureMessage);
}
else
{
final MessageBuilder messageBuilder = new MessageBuilder();
final EmbedBuilder embedBuilder = new EmbedBuilder();
embedBuilder.setTitle("Command error");
embedBuilder.setColor(Color.RED);
embedBuilder.setDescription("You don't have permission to execute this command.");
messageBuilder.setEmbed(embedBuilder.build());
final Message message = messageBuilder.build();
final CompletableFuture<Message> futureMessage = channel.sendMessage(message).submit(true);
this.discord.sentMessages.add(futureMessage);
}
}
}
}
}

View File

@ -0,0 +1,86 @@
package me.totalfreedom.totalfreedommod.discord.commands;
import me.totalfreedom.totalfreedommod.discord.Discord;
import me.totalfreedom.totalfreedommod.discord.command.DiscordCommand;
import me.totalfreedom.totalfreedommod.discord.command.DiscordCommandImpl;
import me.totalfreedom.totalfreedommod.discord.command.DiscordCommandManager;
import net.dv8tion.jda.api.EmbedBuilder;
import net.dv8tion.jda.api.MessageBuilder;
import net.dv8tion.jda.api.entities.Member;
import java.awt.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class HelpCommand extends DiscordCommandImpl
{
@Override
public String getCommandName()
{
return "help";
}
@Override
public String getDescription()
{
return "Displays the help command";
}
@Override
public String getCategory()
{
return "Help";
}
@Override
public List<String> getAliases()
{
return List.of("cmds", "commands", "elp");
}
@Override
public boolean isAdmin()
{
return false;
}
@Override
public MessageBuilder execute(Member member, List<String> args)
{
final EmbedBuilder embedBuilder = new EmbedBuilder();
embedBuilder.setColor(Color.GREEN);
embedBuilder.setTitle("Help Command");
final Map<String, List<DiscordCommand>> commandCategories = new HashMap<>();
for (DiscordCommand command : Discord.DISCORD_COMMAND_MANAGER.commands)
{
if (!commandCategories.containsKey(command.getCategory()))
{
commandCategories.put(command.getCategory(), new ArrayList<>(List.of(command)));
}
else
{
commandCategories.get(command.getCategory()).add(command);
}
}
for (Map.Entry<String, List<DiscordCommand>> entry : commandCategories.entrySet())
{
final String category = entry.getKey();
final List<DiscordCommand> commands = entry.getValue();
final StringBuilder fieldValue = new StringBuilder();
for (DiscordCommand command : commands)
{
fieldValue.append("**").append(DiscordCommandManager.PREFIX).append(command.getCommandName()).append("** - ").append(command.getDescription()).append("\n");
}
embedBuilder.addField(category, fieldValue.toString().trim(), false);
}
return new MessageBuilder().setEmbed(embedBuilder.build());
}
}

View File

@ -0,0 +1,106 @@
package me.totalfreedom.totalfreedommod.discord.commands;
import me.totalfreedom.totalfreedommod.TotalFreedomMod;
import me.totalfreedom.totalfreedommod.admin.AdminList;
import me.totalfreedom.totalfreedommod.config.ConfigEntry;
import me.totalfreedom.totalfreedommod.discord.command.DiscordCommand;
import me.totalfreedom.totalfreedommod.discord.command.DiscordCommandImpl;
import me.totalfreedom.totalfreedommod.rank.Displayable;
import me.totalfreedom.totalfreedommod.rank.RankManager;
import me.totalfreedom.totalfreedommod.util.FUtil;
import net.dv8tion.jda.api.EmbedBuilder;
import net.dv8tion.jda.api.MessageBuilder;
import net.dv8tion.jda.api.entities.Guild;
import net.dv8tion.jda.api.entities.Member;
import net.dv8tion.jda.api.entities.User;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class ListCommand extends DiscordCommandImpl
{
private static final TotalFreedomMod PLUGIN = TotalFreedomMod.plugin();
@Override
public String getCommandName()
{
return "list";
}
@Override
public String getDescription()
{
return "Gives a list of online players.";
}
@Override
public String getCategory()
{
return "Server Commands";
}
@Override
public List<String> getAliases()
{
return List.of("online", "who", "l", "lsit");
}
@Override
public boolean isAdmin()
{
return false;
}
@Override
public MessageBuilder execute(Member member, List<String> args)
{
if (PLUGIN == null)
{
throw new IllegalStateException("TotalFreedomMod somehow null while executing a command!");
}
final AdminList adminList = PLUGIN.al;
final RankManager rankManager = PLUGIN.rm;
EmbedBuilder embedBuilder = new EmbedBuilder()
.setTitle("Player List - " + ConfigEntry.SERVER_NAME.getString())
.setDescription("There are " + FUtil.getFakePlayerCount() + " / " + Bukkit.getMaxPlayers() + " online players");
Map<Displayable, List<String>> displayables = new HashMap<>();
for (Player onlinePlayer : Bukkit.getOnlinePlayers())
{
if (adminList.isVanished(onlinePlayer.getName()))
{
continue;
}
Displayable displayable = rankManager.getDisplay(onlinePlayer);
if (displayables.containsKey(displayable))
{
displayables.get(displayable).add(onlinePlayer.getName());
}
else
{
displayables.put(displayable, new ArrayList<>(List.of(onlinePlayer.getName())));
}
}
for (Map.Entry<Displayable, List<String>> entry : displayables.entrySet())
{
final Displayable displayable = entry.getKey();
final List<String> players = entry.getValue();
embedBuilder.addField(displayable.getPlural() + " (" + players.size() + ")",
String.join(", ", players), false);
}
return new MessageBuilder().setEmbed(embedBuilder.build());
}
}

View File

@ -0,0 +1,60 @@
package me.totalfreedom.totalfreedommod.discord.commands;
import me.totalfreedom.totalfreedommod.discord.command.DiscordCommand;
import me.totalfreedom.totalfreedommod.discord.command.DiscordCommandImpl;
import me.totalfreedom.totalfreedommod.util.FUtil;
import net.dv8tion.jda.api.EmbedBuilder;
import net.dv8tion.jda.api.MessageBuilder;
import net.dv8tion.jda.api.entities.Member;
import org.bukkit.Bukkit;
import org.bukkit.Server;
import java.util.Collections;
import java.util.List;
public class TPSCommand extends DiscordCommandImpl
{
@Override
public String getCommandName()
{
return "tps";
}
@Override
public String getDescription()
{
return "Lag information regarding the server.";
}
@Override
public String getCategory()
{
return "Server Commands";
}
@Override
public List<String> getAliases()
{
return Collections.singletonList("lag");
}
@Override
public boolean isAdmin()
{
return false;
}
@Override
public MessageBuilder execute(Member member, List<String> args)
{
final EmbedBuilder builder = new EmbedBuilder();
builder.setTitle("Server lag information");
builder.addField("TPS", String.valueOf(Math.round(FUtil.getMeanAverageDouble(Bukkit.getServer().getTPS()))), false);
builder.addField("Uptime", FUtil.getUptime(), false);
builder.addField("Maximum Memory", Math.ceil(FUtil.getMaxMem()) + " MB", false);
builder.addField("Allocated Memory", Math.ceil(FUtil.getTotalMem()) + " MB", false);
builder.addField("Free Memory", Math.ceil(FUtil.getFreeMem()) + " MB", false);
return new MessageBuilder().setEmbed(builder.build());
}
}

View File

@ -0,0 +1,79 @@
package me.totalfreedom.totalfreedommod.discord.commands;
import me.totalfreedom.totalfreedommod.discord.command.DiscordCommandImpl;
import me.totalfreedom.totalfreedommod.util.FLog;
import net.dv8tion.jda.api.EmbedBuilder;
import net.dv8tion.jda.api.MessageBuilder;
import net.dv8tion.jda.api.entities.Member;
import java.awt.*;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.Collections;
import java.util.List;
public class UptimeCommand extends DiscordCommandImpl
{
@Override
public String getCommandName()
{
return "uptime";
}
@Override
public String getDescription()
{
return "Returns the uptime of the VPS.";
}
@Override
public String getCategory()
{
return "Server Commands";
}
@Override
public List<String> getAliases()
{
return Collections.emptyList();
}
@Override
public boolean isAdmin()
{
return false;
}
@Override
public MessageBuilder execute(Member member, List<String> args)
{
final EmbedBuilder embedBuilder = new EmbedBuilder();
try
{
final Process uptimeProcess = Runtime.getRuntime().exec(new String[]{"uptime"});
BufferedReader input = new BufferedReader(new InputStreamReader(uptimeProcess.getInputStream()));
String line = input.readLine();
if (line != null)
{
embedBuilder.setTitle("VPS Uptime Information");
embedBuilder.setDescription(line.trim());
}
else
{
throw new IllegalStateException("No output from uptime command.");
}
}
catch (Exception e)
{
FLog.warning("Error while executing uptime Discord command");
e.printStackTrace();
embedBuilder.setTitle("Command error");
embedBuilder.setColor(Color.RED);
embedBuilder.setDescription("Something went wrong");
}
return new MessageBuilder().setEmbed(embedBuilder.build());
}
}

View File

@ -58,6 +58,8 @@ server:
discord:
# If you do not have a token, make a bot account and get one at https://discordapp.com/developers/applications/me
token: ''
# The prefix for the integrated bot commands
prefix: 'tf!'
# The official discord server's ID for this server
server_id: ''
# Channel to send /report messages to