add discord after hours of work?

This commit is contained in:
ChomeNS 2023-03-26 17:34:35 +07:00
parent ed34bcd63f
commit 0d38dbec49
14 changed files with 380 additions and 25 deletions

View file

@ -6,6 +6,11 @@
<option name="name" value="Minecraft Libraries" />
<option name="url" value="https://libraries.minecraft.net" />
</remote-repository>
<remote-repository>
<option name="id" value="dv8tion" />
<option name="name" value="m2-dv8tion" />
<option name="url" value="https://m2.dv8tion.net/releases" />
</remote-repository>
<remote-repository>
<option name="id" value="central" />
<option name="name" value="Central Repository" />

View file

@ -1,5 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="EntryPointsManager">
<writeAnnotations>
<writeAnnotation name="lombok.Getter" />
</writeAnnotations>
</component>
<component name="ExternalStorageConfigurationManager" enabled="true" />
<component name="MavenProjectsManager">
<option name="originalFiles">

View file

@ -46,6 +46,11 @@
<name>Minecraft Libraries</name>
<url>https://libraries.minecraft.net</url>
</repository>
<repository>
<id>dv8tion</id>
<name>m2-dv8tion</name>
<url>https://m2.dv8tion.net/releases</url>
</repository>
</repositories>
<properties>
<maven.compiler.target>17</maven.compiler.target>

12
pom.xml
View file

@ -26,6 +26,12 @@
<name>Minecraft Libraries</name>
<url>https://libraries.minecraft.net</url>
</repository>
<repository>
<id>dv8tion</id>
<name>m2-dv8tion</name>
<url>https://m2.dv8tion.net/releases</url>
</repository>
</repositories>
<dependencies>
@ -96,6 +102,12 @@
<artifactId>luaj-jse</artifactId>
<version>3.0.1</version>
</dependency>
<dependency>
<groupId>net.dv8tion</groupId>
<artifactId>JDA</artifactId>
<version>4.4.0_350</version>
</dependency>
</dependencies>
<build>

View file

@ -53,6 +53,10 @@ public class Bot {
this.allBots = allBots;
this.config = config;
try {
DiscordPlugin.readyLatch().await();
} catch (InterruptedException ignored) { System.exit(1); }
this.chat = new ChatPlugin(this);
this.selfCare = new SelfCarePlugin(this);
this.position = new PositionPlugin(this);

View file

@ -2,6 +2,7 @@ package me.chayapak1.chomens_bot;
import lombok.Getter;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@ -16,6 +17,7 @@ public class Configuration {
@Getter public Map<String, String> keys;
@Getter public Core core = new Core();
@Getter public Discord discord = new Discord();
@Getter public SelfCare selfCare = new SelfCare();
@Getter public Bots[] bots = new Bots[]{};
@ -25,6 +27,18 @@ public class Configuration {
@Getter public String customName = "[{\"text\":\"ChomeNS \",\"color\":\"yellow\"},{\"text\":\"Core\",\"color\":\"green\"},{\"text\":\"\",\"color\":\"gold\"}]";
}
public static class Discord {
@Getter public String prefix = "default!";
@Getter public String token;
@Getter public Map<String, String> servers = new HashMap<>();
@Getter public EmbedColors embedColors = new EmbedColors();
}
public static class EmbedColors {
@Getter public String normal = "#FFFF00";
@Getter public String error = "#FF0000";
}
public static class SelfCare {
@Getter public int checkInterval;

View file

@ -1,7 +1,7 @@
package me.chayapak1.chomens_bot;
import me.chayapak1.chomens_bot.plugins.ConsolePlugin;
import org.yaml.snakeyaml.LoaderOptions;
import me.chayapak1.chomens_bot.plugins.DiscordPlugin;
import org.yaml.snakeyaml.Yaml;
import org.yaml.snakeyaml.constructor.Constructor;
@ -11,6 +11,10 @@ import java.util.List;
import java.util.concurrent.CountDownLatch;
public class Main {
public static final List<Bot> allBots = new ArrayList<>();
public static CountDownLatch latch = null;
public static void main(String[] args) throws IOException, InterruptedException {
final File file = new File("config.yml");
final Constructor constructor = new Constructor(Configuration.class);
@ -47,9 +51,7 @@ public class Main {
Configuration.Bots[] botsOptions = config.bots();
final List<Bot> allBots = new ArrayList<>();
final CountDownLatch latch = new CountDownLatch(botsOptions.length);
latch = new CountDownLatch(botsOptions.length);
for (Configuration.Bots botOption : botsOptions) {
final String host = botOption.host();
@ -65,6 +67,8 @@ public class Main {
}).start();
}
new DiscordPlugin(config);
latch.await();
new ConsolePlugin(allBots);
}

View file

@ -0,0 +1,74 @@
package me.chayapak1.chomens_bot.command;
import com.github.steveice10.mc.auth.data.GameProfile;
import com.github.steveice10.mc.protocol.data.game.entity.player.GameMode;
import me.chayapak1.chomens_bot.Bot;
import me.chayapak1.chomens_bot.chatParsers.data.MutablePlayerListEntry;
import me.chayapak1.chomens_bot.util.ComponentUtilities;
import me.chayapak1.chomens_bot.util.EscapeCodeBlock;
import net.dv8tion.jda.api.EmbedBuilder;
import net.dv8tion.jda.api.entities.MessageEmbed;
import net.dv8tion.jda.api.events.message.MessageReceivedEvent;
import net.kyori.adventure.text.Component;
import java.awt.*;
import java.util.UUID;
public class DiscordCommandContext extends CommandContext {
private final MessageReceivedEvent event;
private final Bot bot;
public DiscordCommandContext(Bot bot, String prefix, MessageReceivedEvent event, String hash, String ownerHash) {
super(
bot,
prefix,
new MutablePlayerListEntry(
new GameProfile(
new UUID(0L, 0L),
null
),
GameMode.SURVIVAL,
0,
Component.text(event.getAuthor().getName()),
0L,
null,
new byte[0]
),
hash,
ownerHash
);
this.bot = bot;
this.event = event;
}
@Override
public void sendOutput (Component component) {
final String output = ComponentUtilities.stringifyAnsi(component);
final EmbedBuilder builder = new EmbedBuilder();
builder.setTitle("Output");
builder.setColor(Color.decode(bot.config().discord().embedColors().normal()));
builder.setDescription("```ansi\n" + EscapeCodeBlock.escape(output.replace("\u001b[9", "\u001b[3")) + "\n```");
final MessageEmbed embed = builder.build();
event.getMessage().replyEmbeds(embed).queue();
}
public void sendError (Component component) {
final String output = ComponentUtilities.stringifyAnsi(component);
final EmbedBuilder builder = new EmbedBuilder();
builder.setTitle("Error");
builder.setColor(Color.decode(bot.config().discord().embedColors().error()));
builder.setDescription("```ansi\n" + output + "\n```");
final MessageEmbed embed = builder.build();
event.getMessage().replyEmbeds(embed).queue();
}
@Override
public Component displayName () {
return Component.text(event.getAuthor().getName());
}
}

View file

@ -55,7 +55,7 @@ public class ChatCommandHandlerPlugin extends ChatPlugin.ChatListener {
final PlayerCommandContext context = new PlayerCommandContext(bot, displayName, prefix, selector, message.sender(), bot.hashing().hash(), bot.hashing().ownerHash());
final Component output = bot.commandHandler().executeCommand(commandString, context, bot.hashing().hash(), bot.hashing().ownerHash());
final Component output = bot.commandHandler().executeCommand(commandString, context, false, bot.hashing().hash(), bot.hashing().ownerHash(), null);
final String textOutput = ((TextComponent) output).content();
if (!textOutput.equals("success")) {

View file

@ -5,6 +5,8 @@ import me.chayapak1.chomens_bot.command.Command;
import me.chayapak1.chomens_bot.command.CommandContext;
import me.chayapak1.chomens_bot.commands.*;
import me.chayapak1.chomens_bot.util.ElementUtilities;
import net.dv8tion.jda.api.entities.Role;
import net.dv8tion.jda.api.events.message.MessageReceivedEvent;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.event.HoverEvent;
import net.kyori.adventure.text.format.NamedTextColor;
@ -44,7 +46,7 @@ public class CommandHandlerPlugin {
commands.add(command);
}
public Component executeCommand (String input, CommandContext context, String hash, String ownerHash) {
public Component executeCommand (String input, CommandContext context, boolean discord, String hash, String ownerHash, MessageReceivedEvent event) {
final String[] splitInput = input.split("\\s+");
final String commandName = splitInput[0];
@ -68,17 +70,33 @@ public class CommandHandlerPlugin {
final String[] args = Arrays.copyOfRange(splitInput, (trustLevel > 0) ? 2 : 1, splitInput.length);
// fix shit random messy code
if (command.trustLevel() > 0) {
if (
command.trustLevel() == 1 &&
!userHash.equals(hash) &&
!userHash.equals(ownerHash)
) return Component.text("Invalid hash").color(NamedTextColor.RED);
if (!discord) {
final List<Role> roles = event.getMember().getRoles();
if (
command.trustLevel() == 2 &&
!userHash.equals(ownerHash)
) return Component.text("Invalid OwnerHash").color(NamedTextColor.RED);
if (
command.trustLevel() == 1 &&
roles.stream().noneMatch(role -> role.getName().equalsIgnoreCase("Trusted")) &&
roles.stream().noneMatch(role -> role.getName().equalsIgnoreCase("Host"))
) return Component.text("You're not in the trusted role!").color(NamedTextColor.RED);
if (
command.trustLevel() == 2 &&
roles.stream().noneMatch(role -> role.getName().equalsIgnoreCase("Host"))
) return Component.text("You're not in the host role!").color(NamedTextColor.RED);
} else {
if (
command.trustLevel() == 1 &&
!userHash.equals(hash) &&
!userHash.equals(ownerHash)
) return Component.text("Invalid hash").color(NamedTextColor.RED);
if (
command.trustLevel() == 2 &&
!userHash.equals(ownerHash)
) return Component.text("Invalid OwnerHash").color(NamedTextColor.RED);
}
}
try {
@ -87,15 +105,19 @@ public class CommandHandlerPlugin {
exception.printStackTrace();
final String stackTrace = ExceptionUtils.getStackTrace(exception);
return Component
.text("An error occurred while trying to execute the command, hover here for more details", NamedTextColor.RED)
.hoverEvent(
HoverEvent.showText(
Component
.text(stackTrace)
.color(NamedTextColor.RED)
)
);
if (!discord) {
return Component
.text("An error occurred while trying to execute the command, hover here for more details", NamedTextColor.RED)
.hoverEvent(
HoverEvent.showText(
Component
.text(stackTrace)
.color(NamedTextColor.RED)
)
);
} else {
return Component.text(stackTrace).color(NamedTextColor.RED);
}
}
}

View file

@ -84,7 +84,7 @@ public class ConsolePlugin {
if (line.startsWith(prefix)) {
final ConsoleCommandContext context = new ConsoleCommandContext(bot, prefix, "h", "o"); // ? should the hashes be hardcoded?
final Component output = bot.commandHandler().executeCommand(line.substring(prefix.length()), context, "h", "o");
final Component output = bot.commandHandler().executeCommand(line.substring(prefix.length()), context, false, "h", "o", null);
final String textOutput = ((TextComponent) output).content();
if (!textOutput.equals("success")) {

View file

@ -0,0 +1,197 @@
package me.chayapak1.chomens_bot.plugins;
import com.github.steveice10.packetlib.event.session.ConnectedEvent;
import com.github.steveice10.packetlib.event.session.DisconnectedEvent;
import com.github.steveice10.packetlib.event.session.SessionAdapter;
import lombok.Getter;
import me.chayapak1.chomens_bot.Bot;
import me.chayapak1.chomens_bot.Configuration;
import me.chayapak1.chomens_bot.Main;
import me.chayapak1.chomens_bot.command.DiscordCommandContext;
import me.chayapak1.chomens_bot.util.ComponentUtilities;
import me.chayapak1.chomens_bot.util.EscapeCodeBlock;
import net.dv8tion.jda.api.JDA;
import net.dv8tion.jda.api.JDABuilder;
import net.dv8tion.jda.api.entities.TextChannel;
import net.dv8tion.jda.api.events.message.MessageReceivedEvent;
import net.dv8tion.jda.api.hooks.ListenerAdapter;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.TextComponent;
import net.kyori.adventure.text.format.NamedTextColor;
import org.jetbrains.annotations.NotNull;
import javax.security.auth.login.LoginException;
import java.util.HashMap;
import java.util.Map;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.CountDownLatch;
public class DiscordPlugin {
@Getter private JDA jda;
public final Map<String, String> servers;
public final String prefix;
@Getter private static CountDownLatch readyLatch = new CountDownLatch(1);
private final Map<String, Boolean> alreadyAddedListeners = new HashMap<>();
public DiscordPlugin (Configuration config) {
final Configuration.Discord options = config.discord();
this.prefix = options.prefix();
this.servers = options.servers();
JDABuilder builder = JDABuilder.createDefault(options.token());
new Thread(() -> {
try {
jda = builder.build();
jda.awaitReady();
} catch (LoginException e) {
System.err.println("Failed to login to Discord, stacktrace:");
e.printStackTrace();
System.exit(1);
} catch (InterruptedException ignored) {
System.exit(1);
}
readyLatch.countDown();
}).start();
try {
Main.latch.await();
} catch (InterruptedException ignored) { System.exit(1); }
for (Bot bot : Main.allBots) {
String channelId = servers.get(bot.host() + ":" + bot.port());
boolean channelAlreadyAddedListeners = alreadyAddedListeners.getOrDefault(channelId, false);
bot.addListener(new SessionAdapter() {
@Override
public void connected(ConnectedEvent event) {
boolean channelAlreadyAddedListeners = alreadyAddedListeners.getOrDefault(channelId, false);
if (channelAlreadyAddedListeners) return;
sendMessageInstantly("Successfully connected to: " + "`" + bot.host() + ":" + bot.port() + "`", channelId);
jda.addEventListener(new ListenerAdapter() {
@Override
public void onMessageReceived(@NotNull MessageReceivedEvent event) {
if (
!event.getChannel().getId().equals(channelId) ||
event.getAuthor().getId().equals(jda.getSelfUser().getId())
) return;
final String tag = event.getAuthor().getAsTag();
final String message = event.getMessage().getContentRaw();
if (message.startsWith(prefix)) {
final DiscordCommandContext context = new DiscordCommandContext(bot, prefix, event, null, null);
final Component output = bot.commandHandler().executeCommand(message.substring(prefix.length()), context, true, null, null, event);
final String textOutput = ((TextComponent) output).content();
if (!textOutput.equals("success")) {
context.sendError(output);
}
return;
}
final Component component = Component.translatable(
"[%s %s] %s %s",
Component.text("ChomeNS").color(NamedTextColor.YELLOW),
Component.text("Discord").color(NamedTextColor.BLUE),
Component.text(tag).color(NamedTextColor.RED),
Component.text(message).color(NamedTextColor.GRAY)
).color(NamedTextColor.DARK_GRAY);
bot.chat().tellraw(component);
}
});
alreadyAddedListeners.put(channelId, true);
bot.chat().addListener(new ChatPlugin.ChatListener() {
@Override
public void systemMessageReceived (String ignoredMessage, Component component) {
final String content = ComponentUtilities.stringifyAnsi(component);
sendMessage(EscapeCodeBlock.escape(content.replace("\u001b[9", "\u001b[3")), channelId);
}
});
final TimerTask task = new TimerTask() {
@Override
public void run() {
onDiscordTick(channelId);
}
};
final Timer timer = new Timer();
timer.schedule(task, 50, 50);
}
@Override
public void disconnected(DisconnectedEvent event) {
sendMessageInstantly("Disconnected: " + "`" + event.getReason().replace("`", "\\`") + "`", channelId);
}
});
}
}
// totallynotskidded from HBot (and changed a bit)
final Map<String, StringBuilder> logMessages = new HashMap<>();
final Map<String, Long> nextLogTimes = new HashMap<>();
final Map<String, Boolean> doneSendingInLogs = new HashMap<>();
public void sendMessage(String message, String channelId) {
synchronized (logMessages) {
if (!logMessages.containsKey(channelId)) {
logMessages.put(channelId, new StringBuilder());
}
StringBuilder logMessage = logMessages.get(channelId);
if (logMessage.length() < 2000) {
if (logMessage.length() > 0) {
logMessage.append('\n');
}
logMessage.append(message);
}
}
}
public void sendMessageInstantly (String message, String channelId) {
final TextChannel logChannel = jda.getTextChannelById(channelId);
logChannel.sendMessage(message).queue(
(msg) -> doneSendingInLogs.put(channelId, true),
(err) -> doneSendingInLogs.put(channelId, false)
);
}
public void onDiscordTick(String channelId) {
synchronized (logMessages) {
if (!logMessages.containsKey(channelId) || logMessages.get(channelId).length() == 0) {
return;
}
}
long currentTime = System.currentTimeMillis();
if (!nextLogTimes.containsKey(channelId) || (currentTime >= nextLogTimes.get(channelId) && doneSendingInLogs.get(channelId))
|| currentTime - nextLogTimes.get(channelId) > 5000) {
long logDelay = 2000; // mabe don't hardcode this
nextLogTimes.put(channelId, currentTime + logDelay);
String message;
synchronized (logMessages) {
StringBuilder logMessage = logMessages.get(channelId);
message = logMessage.toString();
if (message.length() >= 2000) {
message = message.substring(0, 2000);
}
logMessage.setLength(0);
}
sendMessageInstantly("```ansi\n" + message + "\n```", channelId);
}
}
}

View file

@ -0,0 +1,7 @@
package me.chayapak1.chomens_bot.util;
public class EscapeCodeBlock {
public static String escape (String message) {
return message.replace("`", "\\`");
}
}

View file

@ -11,6 +11,12 @@ consolePrefixes:
reconnectDelay: 7000
discord:
prefix: 'default!'
token: 'token here'
servers:
localhost:25565: 'channel id'
keys:
normalKey: 'normal hash key here'
ownerKey: 'OwnerHash™ key here'