forked from ChomeNS/chomens-bot-java
add discord after hours of work?
This commit is contained in:
parent
ed34bcd63f
commit
0d38dbec49
14 changed files with 380 additions and 25 deletions
|
@ -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" />
|
||||
|
|
|
@ -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">
|
||||
|
|
|
@ -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
12
pom.xml
|
@ -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>
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
}
|
|
@ -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")) {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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")) {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
package me.chayapak1.chomens_bot.util;
|
||||
|
||||
public class EscapeCodeBlock {
|
||||
public static String escape (String message) {
|
||||
return message.replace("`", "\\`");
|
||||
}
|
||||
}
|
|
@ -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'
|
||||
|
|
Loading…
Reference in a new issue