Use JDA LTS #8

Merge aplicado
Awakened-Redstone mesclou 8 commits from experimental/jda-lts into master 2022-03-13 03:26:17 +00:00
64 arquivos alterados com 3716 adições e 302 exclusões
Mostrando apenas as alterações do commit bb128e670c - Mostrar todos os commits
Awakened-Redstone 2022-02-19 14:55:54 -03:00

1
.gitignore externo
Ver arquivo

@ -119,3 +119,4 @@ run/
/config.json
/users.db
/auto-whitelist.json
/remappedSrc/

Ver arquivo

@ -1,5 +1,15 @@
buildscript {
dependencies {
classpath 'org.kohsuke:github-api:1.135'
}
}
plugins {
id "fabric-loom" version "0.10-SNAPSHOT"
id "fabric-loom" version "0.11-SNAPSHOT"
id "maven-publish"
id "org.ajoberstar.grgit" version "3.1.0"
id "com.matthewprenger.cursegradle" version "1.4.0"
id "com.modrinth.minotaur" version "1.1.0"
}
repositories {
@ -11,10 +21,16 @@ repositories {
}
}
def ENV = System.getenv()
archivesBaseName = project.archives_base_name
version = project.mod_version
group = project.maven_group
loom {
accessWidenerPath = file("src/main/resources/autowhitelist.accesswidener")
}
sourceCompatibility = 16
targetCompatibility = 16
@ -25,13 +41,7 @@ dependencies {
include(modImplementation(fabricApi.module("fabric-lifecycle-events-v1", project.fabric_version)))
include(modImplementation(fabricApi.module("fabric-api-base", project.fabric_version)))
implementation include("org.xerial:sqlite-jdbc:3.34.0")
implementation include("com.jagrosh:jda-utilities-command:3.0.5")
implementation include("com.jagrosh:jda-utilities-commons:3.0.5")
implementation include("com.jagrosh:jda-utilities-menu:3.0.5")
implementation include("com.jagrosh:jda-utilities-examples:3.0.5")
implementation include("com.jagrosh:jda-utilities-doc:3.0.5")
implementation include('net.dv8tion:JDA:4.3.0_310') {
implementation include('net.dv8tion:JDA:5.0.0-alpha.5') {
exclude module: 'opus-java'
}
@ -39,10 +49,6 @@ dependencies {
include 'org.apache.commons:commons-collections4:4.1'
include 'com.neovisionaries:nv-websocket-client:2.14'
include 'com.squareup.okhttp3:okhttp:3.13.0'
include 'com.squareup.okio:okio:1.17.2'
include 'com.fasterxml.jackson.core:jackson-databind:2.10.1'
include 'com.fasterxml.jackson.core:jackson-annotations:2.10.1'
include 'com.fasterxml.jackson.core:jackson-core:2.10.1'
}
compileJava {
@ -77,3 +83,92 @@ tasks.withType(JavaCompile) {
jar {
from "LICENSE"
}
def getBranch() {
def ENV = System.getenv()
if (ENV.GITHUB_REF) {
def branch = ENV.GITHUB_REF
return branch.substring(branch.lastIndexOf("/") + 1)
}
if (grgit == null) {
return "unknown"
}
def branch = grgit.branch.current().name
return branch.substring(branch.lastIndexOf("/") + 1)
}
task remapMavenJar(type: net.fabricmc.loom.task.RemapJarTask, dependsOn: jar) {
input = jar.archiveFile
archiveFileName = "${archivesBaseName}-${project.version}-maven.jar"
addNestedDependencies = false
}
build.dependsOn remapMavenJar
curseforge {
if (ENV.CURSEFORGE_API_KEY) {
apiKey = ENV.CURSEFORGE_API_KEY
}
project {
id = "575422"
changelog = ENV.CHANGELOG ?: "No changelog provided"
releaseType = "release"
addGameVersion "1.18-Snapshot"
addGameVersion "Fabric"
mainArtifact(remapJar) {
displayName = "[$project.supported_versions] AutoWhitelist - $project.version"
}
afterEvaluate {
uploadTask.dependsOn("remapJar")
}
}
options {
forgeGradleIntegration = false
}
}
import org.kohsuke.github.GHReleaseBuilder
import org.kohsuke.github.GitHub
task github(dependsOn: remapMavenJar) {
onlyIf {
ENV.GITHUB_TOKEN
}
doLast {
def github = GitHub.connectUsingOAuth(ENV.GITHUB_TOKEN as String)
def repository = github.getRepository(ENV.GITHUB_REPOSITORY)
def releaseBuilder = new GHReleaseBuilder(repository, version as String)
releaseBuilder.name("[$project.supported_versions] AutoWhitelist - $project.version")
releaseBuilder.body(ENV.CHANGELOG ?: "No changelog provided")
releaseBuilder.commitish(getBranch())
releaseBuilder.prerelease(false)
def ghRelease = releaseBuilder.create()
ghRelease.uploadAsset(file("${project.buildDir}/libs/${archivesBaseName}-${version}.jar"), "application/java-archive");
}
}
task modrinth(type: com.modrinth.minotaur.TaskModrinthUpload, dependsOn: remapMavenJar) {
onlyIf {
ENV.MODRINTH_TOKEN
}
token = ENV.MODRINTH_TOKEN
projectId = "2tvyop0z"
versionNumber = version
versionName = "[$project.supported_versions] AutoWhitelist - $project.version"
releaseType = "release"
changelog = ENV.CHANGELOG ?: "No changelog provided"
uploadFile = remapJar
addGameVersion(project.minecraft_version)
addLoader('fabric')
}

Ver arquivo

@ -1,9 +1,11 @@
org.gradle.jvmargs=-Xmx1G
minecraft_version=22w03a
yarn_mappings=22w03a+build.8
loader_version=0.12.12
mod_version=beta-5.0.1
minecraft_version=1.18.2-pre1
yarn_mappings=1.18.2-pre1+build.3
loader_version=0.13.2
mod_version=1.0.0
maven_group=com.awakenedredstone
archives_base_name=autowhitelist
fabric_version=0.46.2+1.18
supported_versions=1.18.2-pre1+
fabric_version=0.47.3+1.18.2

Ver arquivo

@ -22,6 +22,7 @@ import net.minecraft.server.PlayerManager;
import net.minecraft.server.WhitelistEntry;
import org.apache.logging.log4j.LogManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File;
import java.io.IOException;
@ -38,8 +39,7 @@ public class AutoWhitelist implements ModInitializer {
public static MinecraftServer server;
public static final Config config = new Config();
public static final Logger LOGGER = LogUtils.getLogger();
public static final org.apache.logging.log4j.Logger LOG4J_LOGGER = LogManager.getLogger("AutoWhitelist");
public static final Logger LOGGER = LoggerFactory.getLogger("AutoWhitelist");
public static final Gson GSON = new GsonBuilder().setPrettyPrinting().create();
private static final File configFile = new File(config.getConfigDirectory(), "AutoWhitelist.json");
@ -58,7 +58,7 @@ public class AutoWhitelist implements ModInitializer {
List<GameProfile> profiles = entries.stream().map(v -> {
((ServerConfigEntryMixin<?>) v).callGetKey();
return (GameProfile) ((ServerConfigEntryMixin<?>) v).getKey();
}).collect(Collectors.toList());
}).toList();
for (GameProfile profile : profiles) {
GameProfile profile1 = server.getUserCache().getByUuid(profile.getId()).orElse(null);
@ -91,7 +91,7 @@ public class AutoWhitelist implements ModInitializer {
} catch (ClassCastException e) {
return null;
}
}).filter(Objects::nonNull).collect(Collectors.toList());
}).filter(Objects::nonNull).toList();
getConfigData().whitelist.keySet().forEach(teamName -> {
Team team = scoreboard.getTeam(teamName);
@ -103,7 +103,7 @@ public class AutoWhitelist implements ModInitializer {
GameProfile profile = profiles.stream().filter(v -> v.getName().equals(player)).findFirst().orElse(null);
if (profile == null) return true;
return !whitelist.isAllowed(profile);
}).collect(Collectors.toList());
}).toList();
invalidPlayers.forEach(player -> scoreboard.removePlayerFromTeam(player, team));
});

Ver arquivo

@ -40,18 +40,18 @@ public class AutoWhitelistCommand {
public static void executeSpecificReload(ServerCommandSource source, ReloadableObjects type) {
switch (type) {
case BOT:
case BOT -> {
source.sendFeedback(new LiteralText("Restarting bot, please wait."), true);
analyzeTimings("Bot#reloadBot", () -> Bot.getInstance().reloadBot(source));
break;
case CONFIG:
}
case CONFIG -> {
source.sendFeedback(new LiteralText("Reloading configurations."), true);
analyzeTimings("Config#loadConfigs", AutoWhitelist.config::loadConfigs);
break;
case TRANSLATIONS:
}
case TRANSLATIONS -> {
source.sendFeedback(new LiteralText("Reloading translations."), true);
analyzeTimings("AutoWhitelist#reloadTranslations", AutoWhitelist::reloadTranslations);
break;
}
}
}

Ver arquivo

@ -17,7 +17,7 @@ public class Config {
private ConfigData configData;
private final File configFile = new File(getConfigDirectory(), "AutoWhitelist.json");
private final float configVersion = 2.1f;
private final byte configVersion = 3;
public File getConfigDirectory() {
return new File(".", "config");
@ -30,9 +30,8 @@ public class Config {
StringReader stringReader = new StringReader(json);
JsonObject jsonObject = JsonParser.parseString(json).getAsJsonObject();
if (jsonObject.get("version") == null || jsonObject.get("version").getAsFloat() != configVersion) {
jsonObject.add("owners", new JsonArray());
if (jsonObject.get("version").getAsFloat() != configVersion) {
jsonObject.add("version", new JsonPrimitive(configVersion));
JsonHelper.writeJsonToFile(jsonObject, configFile);
}
@ -58,7 +57,8 @@ public class Config {
} catch (NullPointerException ignored) {}
}
} catch (IOException e) {
AutoWhitelist.LOG4J_LOGGER.error(e);
AutoWhitelist.LOGGER.error("Failed to load configurations!", e);
//TODO: Stop mod initialization
}
}
}
@ -72,6 +72,7 @@ public class Config {
json.add("token", new JsonPrimitive("bot-token"));
json.add("clientId", new JsonPrimitive("client-id"));
json.add("discordServerId", new JsonPrimitive("discord-server-id"));
json.add("enableSlashCommands", new JsonPrimitive(false));
JsonObject whitelistJson = JsonHelper.getNestedObject(json, "whitelist", true);
if (whitelistJson == null) {
AutoWhitelist.LOGGER.error("Something went wrong when generating the default config file!");

Ver arquivo

@ -5,11 +5,13 @@ import java.util.Map;
public class ConfigData {
public boolean devVersion;
public short whitelistScheduledVerificationSeconds;
public String[] owners;
public String prefix;
public String token;
public String clientId;
public String discordServerId;
public boolean enableSlashCommands;
public Map<String, List<String>> whitelist;
}

Ver arquivo

@ -1,25 +1,42 @@
package com.awakenedredstone.autowhitelist.discord;
import com.awakenedredstone.autowhitelist.AutoWhitelist;
import com.awakenedredstone.autowhitelist.discord.api.AutoWhitelistAPI;
import com.awakenedredstone.autowhitelist.discord.commands.RegisterCommand;
import com.awakenedredstone.autowhitelist.discord.commands.developer.BotStatusCommand;
import com.awakenedredstone.autowhitelist.discord.commands.developer.ServerStatusCommand;
import com.awakenedredstone.autowhitelist.discord.commands.developer.StatusCommand;
import com.awakenedredstone.autowhitelist.discord.commands.development.TestCommand;
import com.awakenedredstone.autowhitelist.discord.commands.system.HelpCommand;
import com.awakenedredstone.autowhitelist.discord.commands.system.PingCommand;
import com.awakenedredstone.autowhitelist.discord.events.CoreEvents;
import com.awakenedredstone.autowhitelist.discord.events.GatewayEvents;
import com.awakenedredstone.autowhitelist.discord.events.JdaEvents;
import com.awakenedredstone.autowhitelist.lang.TranslatableText;
import net.dv8tion.jda.api.JDA;
import net.dv8tion.jda.api.JDABuilder;
import net.dv8tion.jda.api.entities.Activity;
import net.dv8tion.jda.api.hooks.AnnotatedEventManager;
import net.dv8tion.jda.api.interactions.commands.Command;
import net.dv8tion.jda.api.interactions.commands.build.CommandData;
import net.dv8tion.jda.api.interactions.commands.build.OptionData;
import net.dv8tion.jda.api.requests.GatewayIntent;
import net.dv8tion.jda.api.utils.MemberCachePolicy;
import net.dv8tion.jda.internal.interactions.CommandDataImpl;
import net.minecraft.server.command.ServerCommandSource;
import net.minecraft.text.LiteralText;
import net.minecraft.util.logging.UncaughtExceptionHandler;
import javax.security.auth.login.LoginException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ScheduledFuture;
public class Bot implements Runnable {
private static Bot instance;
public static Bot instance;
static ScheduledFuture<?> scheduledUpdate;
public static ScheduledFuture<?> scheduledUpdate;
public static JDA jda = null;
private static String token = AutoWhitelist.getConfigData().token;
@ -76,19 +93,34 @@ public class Bot implements Runnable {
private void init() {
try {
AutoWhitelistAPI.INSTANCE = new AutoWhitelistAPI();
if (whitelistDataMap.isEmpty()) AutoWhitelist.getConfigData().whitelist.forEach((v, k) -> k.forEach(id_ -> whitelistDataMap.put(id_, v)));
jda = JDABuilder.createDefault(token).enableIntents(GatewayIntent.GUILD_MEMBERS).setMemberCachePolicy(MemberCachePolicy.ALL).build();
jda.addEventListener(new BotEventListener());
JDABuilder builder = JDABuilder.createDefault(token);
builder.setEventManager(new AnnotatedEventManager());
builder.addEventListeners(new JdaEvents());
builder.addEventListeners(new CoreEvents());
builder.addEventListeners(new GatewayEvents());
builder.enableIntents(GatewayIntent.GUILD_MEMBERS);
builder.setMemberCachePolicy(MemberCachePolicy.ALL);
jda = builder.build();
try {
jda.getPresence().setActivity(Activity.of(Activity.ActivityType.valueOf(new TranslatableText("bot.activity.type").getString().toUpperCase()), new TranslatableText("bot.activity.message").getString()));
} catch (IllegalArgumentException | NullPointerException e) {
AutoWhitelist.LOGGER.error("Failed to set bot activity, the chosen activity type value is not valid.");
AutoWhitelist.LOGGER.error("Failed to set bot activity, the chosen activity type value is not valid.", e);
}
TestCommand.register(AutoWhitelistAPI.dispatcher());
HelpCommand.register(AutoWhitelistAPI.dispatcher());
PingCommand.register(AutoWhitelistAPI.dispatcher());
BotStatusCommand.register(AutoWhitelistAPI.dispatcher());
ServerStatusCommand.register(AutoWhitelistAPI.dispatcher());
StatusCommand.register(AutoWhitelistAPI.dispatcher());
RegisterCommand.register(AutoWhitelistAPI.dispatcher());
instance = this;
} catch (LoginException e) {
AutoWhitelist.LOGGER.error("Failed to start bot, please verify the token.");
} catch (Exception e) {
AutoWhitelist.LOG4J_LOGGER.error(e);
AutoWhitelist.LOGGER.error("Failed to start bot!", e);
}
}
}

Ver arquivo

@ -5,6 +5,7 @@ import net.dv8tion.jda.api.EmbedBuilder;
import net.dv8tion.jda.api.MessageBuilder;
import net.dv8tion.jda.api.entities.Message;
import net.dv8tion.jda.api.entities.MessageChannel;
import net.dv8tion.jda.api.entities.MessageEmbed;
import net.dv8tion.jda.api.entities.Role;
import net.dv8tion.jda.api.requests.restaction.MessageAction;
import net.minecraft.text.Text;
@ -15,23 +16,12 @@ import java.util.concurrent.TimeUnit;
public class BotHelper extends Bot {
public static void sendFeedbackMessage(MessageChannel channel, Text title, Text message) {
EmbedBuilder embedBuilder = new EmbedBuilder();
embedBuilder.setAuthor(jda.getSelfUser().getName(), "https://discord.com", jda.getSelfUser().getAvatarUrl());
embedBuilder.setTitle(title.getString());
embedBuilder.setDescription(message.getString());
embedBuilder.setFooter(new TranslatableText("command.feedback.message.signature").getString());
MessageAction messageAction = channel.sendMessage(embedBuilder.build());
MessageAction messageAction = channel.sendMessage(generateFeedbackMessage(title, message));
messageAction.queue();
}
public static void sendFeedbackMessage(MessageChannel channel, Text title, Text message, MessageType type) {
EmbedBuilder embedBuilder = new EmbedBuilder();
embedBuilder.setAuthor(jda.getSelfUser().getName(), "https://discord.com", jda.getSelfUser().getAvatarUrl());
embedBuilder.setTitle(title.getString());
embedBuilder.setDescription(message.getString());
embedBuilder.setFooter(new TranslatableText("command.feedback.message.signature").getString());
embedBuilder.setColor(type.hexColor);
MessageAction messageAction = channel.sendMessage(embedBuilder.build());
MessageAction messageAction = channel.sendMessage(generateFeedbackMessage(title, message, type));
messageAction.queue();
}
@ -41,7 +31,7 @@ public class BotHelper extends Bot {
embedBuilder.setTitle(title.getString());
embedBuilder.setDescription(message.getString());
embedBuilder.setFooter(String.format("This message will be deleted %s seconds after being sent.", seconds));
MessageAction messageAction = channel.sendMessage(embedBuilder.build());
MessageAction messageAction = channel.sendMessage(new MessageBuilder().setEmbeds(embedBuilder.build()).build());
messageAction.queue(m -> m.delete().queueAfter(seconds, TimeUnit.SECONDS));
}
@ -64,6 +54,16 @@ public class BotHelper extends Bot {
return new MessageBuilder(embedBuilder.build()).build();
}
public static void sendSimpleMessage(MessageChannel channel, Text message) {
MessageAction messageAction = channel.sendMessage(message.getString());
messageAction.queue();
}
public static void sendTempSimpleMessage(MessageChannel channel, Text message, int seconds) {
MessageAction messageAction = channel.sendMessage(message.getString());
messageAction.queue(m -> m.delete().queueAfter(seconds, TimeUnit.SECONDS));
}
public enum MessageType {
DEBUG(new Color(19, 40, 138)),
NORMAL(Role.DEFAULT_COLOR_RAW),

Ver arquivo

@ -21,60 +21,6 @@ import static com.awakenedredstone.autowhitelist.util.Debugger.analyzeTimings;
public class DiscordDataProcessor implements Runnable {
/* private void updateWhitelist() {
List<String> ids = new SQLite().getIds();
List<ExtendedGameProfile> memberList = new SQLite().getMembers();
Guild guild = jda.getGuildById(serverId);
if (guild == null) {
AutoWhitelist.logger.error("Failed to get discord server, got null");
return;
}
guild.loadMembers().onSuccess(members -> {
List<Member> users = members.stream().filter(member -> ids.contains(member.getId())).collect(Collectors.toList());
for (Member user : users) {
List<ExtendedGameProfile> players = memberList.stream().filter(player -> user.getId().equals(player.getDiscordId())).collect(Collectors.toList());
ExtendedGameProfile player = players.get(0);
List<String> roles = getMemberRoles();
List<Role> userRoles = user.getRoles().stream().filter((role) -> roles.contains(role.getId())).collect(Collectors.toList());
if (userRoles.size() >= 1) {
int higher = 0;
Role best = null;
for (Role role : userRoles) {
if (role.getPosition() > higher) {
higher = role.getPosition();
best = role;
}
}
if (best == null) {
AutoWhitelist.logger.error("Failed to get best tier role!");
return;
}
for (Map.Entry<String, JsonElement> entry : AutoWhitelist.config.getConfigs().get("whitelist").getAsJsonObject().entrySet()) {
JsonArray jsonArray = entry.getValue().getAsJsonArray();
for (JsonElement value : jsonArray) {
if (value.getAsString().equals(best.getId())) {
if (ids.contains(user.getId()) && !player.getTeam().equals(entry.getKey())) {
try {
new SQLite().updateData(user.getId(), getUsername(player.getId().toString()), player.getId().toString(), entry.getKey());
} catch (IOException e) {
AutoWhitelist.logger.error("Failed to get username!", e);
return;
}
}
}
}
}
} else if (!AutoWhitelist.server.getPlayerManager().isOperator(player)) {
new SQLite().removeMemberById(player.getDiscordId());
AutoWhitelist.removePlayer(player);
}
}
});
}*/
@Override
public void run() {
updateWhitelist();
@ -91,9 +37,9 @@ public class DiscordDataProcessor implements Runnable {
List<Member> members = guild.findMembers(v -> {
if (v.getUser().isBot()) return false;
return !Collections.disjoint(v.getRoles().stream().map(Role::getId).collect(Collectors.toList()), new ArrayList<>(whitelistDataMap.keySet()));
return !Collections.disjoint(v.getRoles().stream().map(Role::getId).toList(), new ArrayList<>(whitelistDataMap.keySet()));
}).get();
List<String> memberIds = members.stream().map(ISnowflake::getId).collect(Collectors.toList());
List<String> memberIds = members.stream().map(ISnowflake::getId).toList();
List<ExtendedGameProfile> invalidPlayers = whitelist.getEntries().stream().map(entry -> {
((ServerConfigEntryMixin<?>) entry).callGetKey();
@ -102,7 +48,7 @@ public class DiscordDataProcessor implements Runnable {
} catch (ClassCastException exception) {
return null;
}
}).filter(Objects::nonNull).filter(entry -> !memberIds.contains(entry.getDiscordId())).collect(Collectors.toList());
}).filter(Objects::nonNull).filter(entry -> !memberIds.contains(entry.getDiscordId())).toList();
if (!invalidPlayers.isEmpty()) {
for (ExtendedGameProfile invalidPlayer : invalidPlayers) {
@ -111,7 +57,7 @@ public class DiscordDataProcessor implements Runnable {
}
for (Member member : members) {
String highestRole = member.getRoles().stream().map(Role::getId).filter(whitelistDataMap::containsKey).collect(Collectors.toList()).get(0);
String highestRole = member.getRoles().stream().map(Role::getId).filter(whitelistDataMap::containsKey).toList().get(0);
String teamName = whitelistDataMap.get(highestRole);
List<ExtendedGameProfile> profiles = whitelist.getFromDiscordId(member.getId());
if (profiles.isEmpty()) continue;

Ver arquivo

@ -0,0 +1,25 @@
package com.awakenedredstone.autowhitelist.discord.api;
import com.awakenedredstone.autowhitelist.discord.api.command.CommandManager;
import com.awakenedredstone.autowhitelist.discord.api.command.DiscordCommandSource;
import com.mojang.brigadier.CommandDispatcher;
import net.minecraft.util.profiler.DummyRecorder;
import net.minecraft.util.profiler.Profiler;
public class AutoWhitelistAPI {
public static AutoWhitelistAPI INSTANCE = new AutoWhitelistAPI();
public static CommandDispatcher<DiscordCommandSource> dispatcher() {
return AutoWhitelistAPI.INSTANCE.commandManager.dispatcher;
}
private final CommandManager commandManager = new CommandManager();
private final Profiler profiler = DummyRecorder.INSTANCE.getProfiler();
public Profiler getProfiler() {
return this.profiler;
}
public CommandManager getCommandManager() {
return this.commandManager;
}
}

Ver arquivo

@ -0,0 +1,97 @@
package com.awakenedredstone.autowhitelist.discord.api;
import com.awakenedredstone.autowhitelist.discord.api.text.Text;
import com.awakenedredstone.autowhitelist.lang.TranslatableText;
import net.dv8tion.jda.api.EmbedBuilder;
import net.dv8tion.jda.api.MessageBuilder;
import net.dv8tion.jda.api.entities.Message;
import net.dv8tion.jda.api.entities.MessageChannel;
import net.dv8tion.jda.api.entities.Role;
import net.dv8tion.jda.api.requests.restaction.MessageAction;
import java.awt.*;
import java.util.concurrent.TimeUnit;
import static com.awakenedredstone.autowhitelist.discord.Bot.jda;
public class BotHelper {
public static void sendFeedbackMessage(MessageChannel channel, Text title, Text message) {
EmbedBuilder embedBuilder = new EmbedBuilder();
embedBuilder.setAuthor(jda.getSelfUser().getName(), "https://discord.com", jda.getSelfUser().getAvatarUrl());
embedBuilder.setTitle(title.getString());
embedBuilder.setDescription(message.getString());
embedBuilder.setFooter(new TranslatableText("command.feedback.message.signature").getString());
MessageAction messageAction = channel.sendMessageEmbeds(embedBuilder.build());
messageAction.queue();
}
public static void sendFeedbackMessage(MessageChannel channel, Text title, Text message, MessageType type) {
EmbedBuilder embedBuilder = new EmbedBuilder();
embedBuilder.setAuthor(jda.getSelfUser().getName(), "https://discord.com", jda.getSelfUser().getAvatarUrl());
embedBuilder.setTitle(title.getString());
embedBuilder.setDescription(message.getString());
embedBuilder.setFooter(new TranslatableText("command.feedback.message.signature").getString());
embedBuilder.setColor(type.hexColor);
MessageAction messageAction = channel.sendMessageEmbeds(embedBuilder.build());
messageAction.queue();
}
public static void sendTempFeedbackMessage(MessageChannel channel, Text title, Text message, int seconds) {
EmbedBuilder embedBuilder = new EmbedBuilder();
embedBuilder.setAuthor(jda.getSelfUser().getName(), "https://discord.com", jda.getSelfUser().getAvatarUrl());
embedBuilder.setTitle(title.getString());
embedBuilder.setDescription(message.getString());
embedBuilder.setFooter(String.format("This message will be deleted %s seconds after being sent.", seconds));
MessageAction messageAction = channel.sendMessageEmbeds(embedBuilder.build());
messageAction.queue(m -> m.delete().queueAfter(seconds, TimeUnit.SECONDS));
}
public static Message generateFeedbackMessage(Text title, Text message) {
EmbedBuilder embedBuilder = new EmbedBuilder();
embedBuilder.setAuthor(jda.getSelfUser().getName(), "https://discord.com", jda.getSelfUser().getAvatarUrl());
embedBuilder.setTitle(title.getString());
embedBuilder.setDescription(message.getString());
embedBuilder.setFooter(new TranslatableText("command.feedback.message.signature").getString());
return new MessageBuilder(embedBuilder.build()).build();
}
public static Message generateFeedbackMessage(Text title, Text message, MessageType type) {
EmbedBuilder embedBuilder = new EmbedBuilder();
embedBuilder.setAuthor(jda.getSelfUser().getName(), "https://discord.com", jda.getSelfUser().getAvatarUrl());
embedBuilder.setTitle(title.markdownFormatted());
embedBuilder.setDescription(message.markdownFormatted());
embedBuilder.setFooter(new TranslatableText("command.feedback.message.signature").getString());
embedBuilder.setColor(type.hexColor);
return new MessageBuilder(embedBuilder.build()).build();
}
public static void sendSimpleMessage(MessageChannel channel, Text message) {
MessageAction messageAction = channel.sendMessage(message.markdownFormatted());
messageAction.queue();
}
public static void sendTempSimpleMessage(MessageChannel channel, Text message, int seconds) {
MessageAction messageAction = channel.sendMessage(message.markdownFormatted());;
messageAction.queue(m -> m.delete().queueAfter(seconds, TimeUnit.SECONDS));
}
public enum MessageType {
DEBUG(new Color(19, 40, 138)),
NORMAL(Role.DEFAULT_COLOR_RAW),
INFO(new Color(176, 154, 15)),
SUCCESS(new Color(50, 134, 25)),
WARNING(new Color(208, 102, 21)),
ERROR(new Color(141, 29, 29)),
FATAL(new Color(212, 4, 4));
public final int hexColor;
MessageType(Color hexColor) {
this.hexColor = hexColor.getRGB();
}
MessageType(int hexColor) {
this.hexColor = hexColor;
}
}
}

Ver arquivo

@ -0,0 +1,11 @@
package com.awakenedredstone.autowhitelist.discord.api;
public enum Constants {
CONFIG_VERSION(2);
public final Object value;
<T> Constants(T value) {
this.value = value;
}
}

Ver arquivo

@ -0,0 +1,16 @@
package com.awakenedredstone.autowhitelist.discord.api;
import net.dv8tion.jda.api.requests.GatewayIntent;
import java.util.Arrays;
import java.util.List;
public class GatewayIntents {
public static final List<GatewayIntent> BASIC = Arrays.asList(
GatewayIntent.GUILD_MEMBERS,
GatewayIntent.GUILD_EMOJIS,
GatewayIntent.GUILD_BANS,
GatewayIntent.GUILD_MESSAGES,
GatewayIntent.DIRECT_MESSAGES,
GatewayIntent.GUILD_MESSAGE_REACTIONS);
}

Ver arquivo

@ -0,0 +1,17 @@
package com.awakenedredstone.autowhitelist.discord.api.command;
import com.awakenedredstone.autowhitelist.discord.api.text.Text;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
public class CommandException extends RuntimeException {
private final Text message;
public CommandException(Text message) {
super(message.getString(), null, CommandSyntaxException.ENABLE_COMMAND_STACK_TRACES, CommandSyntaxException.ENABLE_COMMAND_STACK_TRACES);
this.message = message;
}
public Text getTextMessage() {
return this.message;
}
}

Ver arquivo

@ -0,0 +1,145 @@
package com.awakenedredstone.autowhitelist.discord.api.command;
import com.awakenedredstone.autowhitelist.AutoWhitelist;
import com.awakenedredstone.autowhitelist.discord.api.BotHelper;
import com.awakenedredstone.autowhitelist.discord.api.text.LiteralText;
import com.awakenedredstone.autowhitelist.discord.api.text.MutableText;
import com.awakenedredstone.autowhitelist.discord.api.text.Text;
import com.awakenedredstone.autowhitelist.discord.api.text.TranslatableText;
import com.awakenedredstone.autowhitelist.discord.api.util.Formatting;
import com.awakenedredstone.autowhitelist.discord.api.util.Util;
import com.mojang.brigadier.CommandDispatcher;
import com.mojang.brigadier.ParseResults;
import com.mojang.brigadier.StringReader;
import com.mojang.brigadier.arguments.ArgumentType;
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
import com.mojang.brigadier.builder.RequiredArgumentBuilder;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import net.dv8tion.jda.api.EmbedBuilder;
import net.dv8tion.jda.api.MessageBuilder;
import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.jetbrains.annotations.Nullable;
import java.util.function.Predicate;
import static com.awakenedredstone.autowhitelist.discord.Bot.jda;
public class CommandManager {
private static final Logger LOGGER = LogManager.getLogger();
public final CommandDispatcher<DiscordCommandSource> dispatcher = new CommandDispatcher<>();
public CommandManager() {
this.dispatcher.findAmbiguities((parent, child, sibling, inputs) -> LOGGER.warn("Ambiguity between arguments {} and {} with inputs: {}", this.dispatcher.getPath(child), this.dispatcher.getPath(sibling), inputs));
this.dispatcher.setConsumer((context, success, result) -> context.getSource().onCommandComplete(context, success, result));
}
public int execute(DiscordCommandSource commandSource, String command) {
StringReader stringReader = new StringReader(command);
if (stringReader.canRead() && stringReader.peek() == '/') {
stringReader.skip();
}
commandSource.getApi().getProfiler().push(command);
try {
byte var18;
try {
return this.dispatcher.execute(stringReader, commandSource);
} catch (CommandException var13) {
commandSource.sendError(var13.getTextMessage());
var18 = 0;
return var18;
} catch (CommandSyntaxException var14) {
if (var14.getInput() != null && var14.getCursor() >= 0) {
int i = Math.min(var14.getInput().length(), var14.getCursor());
MutableText mutableText = Util.toText(var14.getRawMessage()).shallowCopy();
mutableText.append("\n");
if (i > 10) {
mutableText.append("...");
}
mutableText.append(var14.getInput().substring(Math.max(0, i - 10), i).replaceFirst("^/", AutoWhitelist.getConfigData().prefix));
if (i < var14.getInput().length()) {
Text text = (new LiteralText(var14.getInput().substring(i))).formatted(Formatting.RED, Formatting.UNDERLINE);
mutableText.append(text);
}
mutableText.append((new TranslatableText("command.context.here")).formatted(Formatting.RED, Formatting.ITALIC));
if (commandSource.getType() == DiscordCommandSource.CommandType.SLASH_COMMAND) {
EmbedBuilder embedBuilder = new EmbedBuilder();
embedBuilder.setAuthor(jda.getSelfUser().getName(), "https://discord.com", jda.getSelfUser().getAvatarUrl());
embedBuilder.setTitle(" ");
embedBuilder.setDescription(mutableText.getString());
embedBuilder.setFooter(new TranslatableText("command.feedback.message.signature").getString());
embedBuilder.setColor(BotHelper.MessageType.ERROR.hexColor);
((SlashCommandInteractionEvent)commandSource.getEvent()).deferReply(true).queue(m -> m.editOriginal(new MessageBuilder().setEmbeds(embedBuilder.build()).build()).queue());
} else {
commandSource.sendError(mutableText);
}
} else {
commandSource.sendError(Util.toText(var14.getRawMessage()));
}
} catch (Exception var15) {
MutableText mutableText2 = new LiteralText(var15.getMessage() == null ? var15.getClass().getName() : var15.getMessage());
if (LOGGER.isDebugEnabled()) {
LOGGER.error("Command exception: {}", command, var15);
StackTraceElement[] stackTraceElements = var15.getStackTrace();
for (int j = 0; j < Math.min(stackTraceElements.length, 3); ++j) {
mutableText2.append("\n\n").append(stackTraceElements[j].getMethodName()).append("\n ").append(stackTraceElements[j].getFileName()).append(":").append(String.valueOf(stackTraceElements[j].getLineNumber()));
}
}
commandSource.sendError((new TranslatableText("command.failed")));
if (AutoWhitelist.getConfigData().devVersion) {
commandSource.sendError(new LiteralText(Util.getInnermostMessage(var15)));
LOGGER.error("'{}' threw an exception", command, var15);
}
return (byte) 0;
}
var18 = 0;
return var18;
} finally {
commandSource.getApi().getProfiler().pop();
}
}
public static LiteralArgumentBuilder<DiscordCommandSource> literal(String literal) {
return LiteralArgumentBuilder.literal(literal);
}
public static <T> RequiredArgumentBuilder<DiscordCommandSource, T> argument(String name, ArgumentType<T> type) {
return RequiredArgumentBuilder.argument(name, type);
}
public static Predicate<String> getCommandValidator(CommandParser parser) {
return (string) -> {
try {
parser.parse(new StringReader(string));
return true;
} catch (CommandSyntaxException var3) {
return false;
}
};
}
@Nullable
public static <S> CommandSyntaxException getException(ParseResults<S> parse) {
if (!parse.getReader().canRead()) {
return null;
} else if (parse.getExceptions().size() == 1) {
return (CommandSyntaxException) parse.getExceptions().values().iterator().next();
} else {
return parse.getContext().getRange().isEmpty() ? CommandSyntaxException.BUILT_IN_EXCEPTIONS.dispatcherUnknownCommand().createWithContext(parse.getReader()) : CommandSyntaxException.BUILT_IN_EXCEPTIONS.dispatcherUnknownArgument().createWithContext(parse.getReader());
}
}
@FunctionalInterface
public interface CommandParser {
void parse(StringReader reader) throws CommandSyntaxException;
}
}

Ver arquivo

@ -0,0 +1,121 @@
package com.awakenedredstone.autowhitelist.discord.api.command;
import com.awakenedredstone.autowhitelist.discord.api.BotHelper;
import com.awakenedredstone.autowhitelist.discord.api.AutoWhitelistAPI;
import com.awakenedredstone.autowhitelist.discord.api.text.LiteralText;
import com.awakenedredstone.autowhitelist.discord.api.text.Text;
import com.mojang.brigadier.ResultConsumer;
import com.mojang.brigadier.context.CommandContext;
import net.dv8tion.jda.api.entities.Member;
import net.dv8tion.jda.api.entities.Message;
import net.dv8tion.jda.api.entities.MessageChannel;
import net.dv8tion.jda.api.entities.User;
import net.dv8tion.jda.api.events.Event;
import org.jetbrains.annotations.Nullable;
import java.util.Objects;
public final class DiscordCommandSource {
private final User user;
@Nullable private final Member member;
private final Message message;
private final MessageChannel channel;
private final CommandType type;
private final Event event;
private final ResultConsumer<DiscordCommandSource> resultConsumer;
public DiscordCommandSource(User user, Message message, MessageChannel channel, CommandType type, Event event) {
this(user, null, message, channel, type, event);
}
public DiscordCommandSource(Member member, Message message, MessageChannel channel, CommandType type, Event event) {
this(member.getUser(), member, message, channel, type, event);
}
public DiscordCommandSource(User user, @Nullable Member member, Message message, MessageChannel channel, CommandType type, Event event) {
this.user = user;
this.member = member;
this.message = message;
this.channel = channel;
this.resultConsumer = (context, success, result) -> {};
this.type = type;
this.event = event;
}
public void sendFeedback(Text message) {
BotHelper.sendSimpleMessage(channel, message);
}
public void sendError(Text message) {
BotHelper.sendFeedbackMessage(channel, new LiteralText(" "), message, BotHelper.MessageType.ERROR);
}
public void onCommandComplete(CommandContext<DiscordCommandSource> context, boolean success, int result) {
if (this.resultConsumer != null) {
this.resultConsumer.onCommandComplete(context, success, result);
}
}
public User getUser() {
return user;
}
@Nullable
public Member getMember() {
return member;
}
public Message getMessage() {
return message;
}
public <T extends MessageChannel> T getChannel() {
return (T)channel;
}
public AutoWhitelistAPI getApi() {
return AutoWhitelistAPI.INSTANCE;
}
public boolean isFromGuild() {
return member != null;
}
@Override
public boolean equals(Object obj) {
if (obj == this) return true;
if (obj == null || obj.getClass() != this.getClass()) return false;
var that = (DiscordCommandSource) obj;
return Objects.equals(this.user, that.user) &&
Objects.equals(this.message, that.message) &&
Objects.equals(this.channel, that.channel);
}
@Override
public int hashCode() {
return Objects.hash(user, message, channel);
}
@Override
public String toString() {
return "DiscordCommandSource[" +
"user=" + user + ", " +
"message=" + message + ", " +
"channel=" + channel + ']';
}
public CommandType getType() {
return type;
}
public Event getEvent() {
return event;
}
public enum CommandType {
MESSAGE,
SLASH_COMMAND
}
}

Ver arquivo

@ -0,0 +1,77 @@
package com.awakenedredstone.autowhitelist.discord.api.json;
import com.awakenedredstone.autowhitelist.AutoWhitelist;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.jetbrains.annotations.Nullable;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
public class JsonHelper {
private static final Logger LOGGER = LogManager.getLogger();
@Nullable
public static JsonElement parseJsonFile(File file) {
if (file != null && file.exists() && file.isFile() && file.canRead()) {
String fileName = file.getAbsolutePath();
try {
FileReader reader = new FileReader(file);
JsonElement element = JsonParser.parseReader(reader);
reader.close();
return element;
} catch (Exception e) {
LOGGER.error("Failed to parse the JSON file '{}'", fileName, e);
}
}
return null;
}
public static boolean writeJsonToFile(JsonObject root, File file) {
FileWriter writer = null;
try {
writer = new FileWriter(file);
writer.write(AutoWhitelist.GSON.toJson(root));
writer.close();
return true;
} catch (IOException e) {
LOGGER.warn("Failed to write JSON data to file '{}'", file.getAbsolutePath(), e);
} finally {
try {
if (writer != null) {
writer.close();
}
} catch (Exception e) {
LOGGER.warn("Failed to close JSON file", e);
}
}
return false;
}
@Nullable
public static JsonObject getNestedObject(JsonObject parent, String key, boolean create) {
if (!parent.has(key) || !parent.get(key).isJsonObject()) {
if (!create) {
return null;
}
JsonObject obj = new JsonObject();
parent.add(key, obj);
return obj;
} else {
return parent.get(key).getAsJsonObject();
}
}
}

Ver arquivo

@ -0,0 +1,85 @@
package com.awakenedredstone.autowhitelist.discord.api.text;
import com.awakenedredstone.autowhitelist.discord.api.util.Formatting;
import com.google.common.collect.Lists;
import java.util.List;
import java.util.Objects;
public abstract class BaseText implements MutableText {
protected final List<Text> siblings = Lists.newArrayList();
private Style style;
public BaseText() {
this.style = Style.EMPTY;
}
public MutableText append(Text text) {
this.siblings.add(text);
return this;
}
public String asString() {
return "";
}
public String markdownFormatted() {
MutableText self = partialCopy();
String text = self.getString();
for (Formatting formatting : self.getStyle().formattings()) {
switch (formatting) {
case BOLD, STRIKETHROUGH, UNDERLINE, ITALIC, CODE, CODE_BLOCK -> text = formatting.getMarkdown().concat(text).concat(formatting.getMarkdown());
}
}
for (Text sibling : getSiblings()) {
text = text.concat(sibling.markdownFormatted());
}
return text;
}
public final MutableText shallowCopy() {
BaseText baseText = this.copy();
baseText.siblings.addAll(this.siblings);
baseText.setStyle(this.style);
return baseText;
}
public final MutableText partialCopy() {
BaseText baseText = this.copy();
baseText.setStyle(this.style);
return baseText;
}
public MutableText setStyle(Style style) {
this.style = style;
return this;
}
public Style getStyle() {
return this.style;
}
public List<Text> getSiblings() {
return this.siblings;
}
public abstract BaseText copy();
public boolean equals(Object obj) {
if (this == obj) {
return true;
} else if (!(obj instanceof BaseText baseText)) {
return false;
} else {
return this.siblings.equals(baseText.siblings);
}
}
public int hashCode() {
return Objects.hash(this.siblings);
}
public String toString() {
return "BaseComponent{siblings=" + this.siblings + '}';
}
}

Ver arquivo

@ -0,0 +1,36 @@
package com.awakenedredstone.autowhitelist.discord.api.text;
public class LiteralText extends BaseText {
public static final Text EMPTY = new LiteralText("");
private final String string;
public LiteralText(String string) {
this.string = string;
}
public String getRawString() {
return this.string;
}
public String asString() {
return this.string;
}
public LiteralText copy() {
return new LiteralText(this.string);
}
public boolean equals(Object object) {
if (this == object) {
return true;
} else if (!(object instanceof LiteralText literalText)) {
return false;
} else {
return this.string.equals(literalText.getRawString()) && super.equals(object);
}
}
public String toString() {
return "TextComponent{text='" + this.string + "', siblings=" + this.siblings + "}";
}
}

Ver arquivo

@ -0,0 +1,56 @@
package com.awakenedredstone.autowhitelist.discord.api.text;
import com.awakenedredstone.autowhitelist.discord.api.util.Formatting;
/**
* A text with mutation operations.
*/
public interface MutableText extends Text {
/**
* Sets the style of this text.
*/
MutableText setStyle(Style style);
Style getStyle();
default MutableText fillStyle(Style styleOverride) {
this.setStyle(styleOverride.withParent(this.getStyle()));
return this;
}
/**
* Appends a literal text with content {@code text} to this text's siblings.
*
* @param text the literal text content
*/
default MutableText append(String text) {
return this.append(new LiteralText(text));
}
/**
* Appends a text to this text's siblings.
*
* @param text the sibling
*/
MutableText append(Text text);
/**
* Adds some formattings to this text's style.
*
* @param formattings an array of formattings
*/
default MutableText formatted(Formatting... formattings) {
this.setStyle(this.getStyle().withFormatting(formattings));
return this;
}
/**
* Add a formatting to this text's style.
*
* @param formatting a formatting
*/
default MutableText formatted(Formatting formatting) {
this.setStyle(this.getStyle().withFormatting(formatting));
return this;
}
}

Ver arquivo

@ -0,0 +1,13 @@
package com.awakenedredstone.autowhitelist.discord.api.text;
import com.awakenedredstone.autowhitelist.discord.api.command.DiscordCommandSource;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import net.dv8tion.jda.api.entities.User;
import org.jetbrains.annotations.Nullable;
/**
* A {@link Text} that needs to be parsed when it is loaded into the game.
*/
public interface ParsableText {
MutableText parse(@Nullable DiscordCommandSource source, @Nullable User sender, int depth) throws CommandSyntaxException;
}

Ver arquivo

@ -0,0 +1,97 @@
package com.awakenedredstone.autowhitelist.discord.api.text;
import com.awakenedredstone.autowhitelist.discord.api.util.Unit;
import java.util.Optional;
/**
* An object that can supply strings to a visitor,
* with or without a style context.
*/
public interface StringVisitable {
/**
* Convenience object indicating the termination of a string visit.
*/
Optional<Unit> TERMINATE_VISIT = Optional.of(Unit.INSTANCE);
/**
* An empty visitable that does not call the visitors.
*/
StringVisitable EMPTY = new StringVisitable() {
public <T> Optional<T> visit(Visitor<T> visitor) {
return Optional.empty();
}
};
/**
* Supplies this visitable's literal content to the visitor.
*
* @return {@code Optional.empty()} if the visit finished, or a terminating
* result from the {@code visitor}
*
* @param visitor the visitor
*/
<T> Optional<T> visit(Visitor<T> visitor);
/**
* Creates a visitable from a plain string.
*
* @param string the plain string
*/
static StringVisitable plain(final String string) {
return new StringVisitable() {
public <T> Optional<T> visit(Visitor<T> visitor) {
return visitor.accept(string);
}
};
}
default String getString() {
StringBuilder stringBuilder = new StringBuilder();
this.visit((string) -> {
stringBuilder.append(string);
return Optional.empty();
});
return stringBuilder.toString();
}
/**
* A visitor for string content.
*/
interface Visitor<T> {
/**
* Visits a literal string.
*
* <p>When a {@link Optional#isPresent() present optional} is returned,
* the visit is terminated before visiting all text. Can return {@link
* StringVisitable#TERMINATE_VISIT} for convenience.</p>
*
* @return {@code Optional.empty()} to continue, a non-empty result to terminate
*
* @param asString the literal string
*/
Optional<T> accept(String asString);
}
/**
* A visitor for string content and a contextual {@link Style}.
*/
public interface StyledVisitor<T> {
/**
* Visits a string's content with a contextual style.
*
* <p>A contextual style is obtained by calling {@link Style#withParent(Style)}
* on the current's text style, passing the previous contextual style or
* the starting style if it is the beginning of a visit.
*
* <p>When a {@link Optional#isPresent() present optional} is returned,
* the visit is terminated before visiting all text. Can return {@link
* StringVisitable#TERMINATE_VISIT} for convenience.
*
* @return {@code Optional.empty()} to continue, a non-empty result to terminate
*
* @param style the current style
* @param asString the literal string
*/
Optional<T> accept(Style style, String asString);
}
}

Ver arquivo

@ -0,0 +1,472 @@
package com.awakenedredstone.autowhitelist.discord.api.text;
import com.awakenedredstone.autowhitelist.discord.api.util.Formatting;
import com.awakenedredstone.autowhitelist.discord.api.util.Identifier;
import com.awakenedredstone.autowhitelist.discord.api.util.InvalidIdentifierException;
import com.awakenedredstone.autowhitelist.discord.api.util.JsonHelper;
import com.google.gson.*;
import org.jetbrains.annotations.Nullable;
import java.lang.reflect.Type;
import java.util.Arrays;
import java.util.Objects;
/**
* The style of a {@link Text}, representing cosmetic attributes. It includes
* font, formatting, click/hover events (actions), color, etc.
*
* <p>A style is immutable.
*
* @see Text
*/
public record Style(@Nullable TextColor color, @Nullable Boolean bold,
@Nullable Boolean italic, @Nullable Boolean underlined,
@Nullable Boolean strikethrough, @Nullable Boolean obfuscated,
@Nullable String insertion, @Nullable Identifier font,
Formatting... formattings) {
/**
* An empty style.
*/
public static final Style EMPTY = new Style(null, null, null, null, null, null, null, null);
/**
* The identifier for the default font of a style.
*/
public static final Identifier DEFAULT_FONT_ID = new Identifier("minecraft", "default");
public Style(@Nullable TextColor color, @Nullable Boolean bold, @Nullable Boolean italic, @Nullable Boolean underlined, @Nullable Boolean strikethrough, @Nullable Boolean obfuscated, @Nullable String insertion, @Nullable Identifier font, Formatting... formattings) {
this.color = color;
this.bold = bold;
this.italic = italic;
this.underlined = underlined;
this.strikethrough = strikethrough;
this.obfuscated = obfuscated;
this.insertion = insertion;
this.font = font;
this.formattings = formattings;
}
/**
* Returns the color of this style.
*/
@Nullable
public TextColor getColor() {
return this.color;
}
/**
* Returns whether the style has bold formatting.
*
* @see Formatting#BOLD
*/
public boolean isBold() {
return this.bold == Boolean.TRUE;
}
/**
* Returns whether the style has italic formatting.
*
* @see Formatting#ITALIC
*/
public boolean isItalic() {
return this.italic == Boolean.TRUE;
}
/**
* Returns whether the style has strikethrough formatting.
*
* @see Formatting#STRIKETHROUGH
*/
public boolean isStrikethrough() {
return this.strikethrough == Boolean.TRUE;
}
/**
* Returns whether the style has underline formatting.
*
* @see Formatting#UNDERLINE
*/
public boolean isUnderlined() {
return this.underlined == Boolean.TRUE;
}
/**
* Returns whether the style has obfuscated formatting.
*
* @see Formatting#OBFUSCATED
*/
public boolean isObfuscated() {
return this.obfuscated == Boolean.TRUE;
}
/**
* Returns if this is the empty style.
*
* @see #EMPTY
*/
public boolean isEmpty() {
return this == EMPTY;
}
/**
* Returns the insertion text of the style.
*
* <p>An insertion is inserted when a piece of text clicked while shift key
* is down in the chat HUD.
*/
@Nullable
public String getInsertion() {
return this.insertion;
}
/**
* Returns the font of this style.
*/
public Identifier getFont() {
return this.font != null ? this.font : DEFAULT_FONT_ID;
}
/**
* Returns a new style with the color provided and all other attributes of
* this style.
*
* @param color the new color
*/
public Style withColor(@Nullable TextColor color) {
return new Style(color, this.bold, this.italic, this.underlined, this.strikethrough, this.obfuscated, this.insertion, this.font);
}
/**
* Returns a new style with the color provided and all other attributes of
* this style.
*
* @param color the new color
*/
public Style withColor(@Nullable Formatting color) {
return this.withColor(color != null ? TextColor.fromFormatting(color) : null);
}
public Style withColor(int rgbColor) {
return this.withColor(TextColor.fromRgb(rgbColor));
}
/**
* Returns a new style with the bold attribute provided and all other
* attributes of this style.
*
* @param bold the new bold property
*/
public Style withBold(@Nullable Boolean bold) {
return new Style(this.color, bold, this.italic, this.underlined, this.strikethrough, this.obfuscated, this.insertion, this.font);
}
/**
* Returns a new style with the italic attribute provided and all other
* attributes of this style.
*
* @param italic the new italic property
*/
public Style withItalic(@Nullable Boolean italic) {
return new Style(this.color, this.bold, italic, this.underlined, this.strikethrough, this.obfuscated, this.insertion, this.font);
}
/**
* Returns a new style with the underline attribute provided and all other
* attributes of this style.
*/
public Style withUnderline(@Nullable Boolean underline) {
return new Style(this.color, this.bold, this.italic, underline, this.strikethrough, this.obfuscated, this.insertion, this.font);
}
public Style withStrikethrough(@Nullable Boolean strikethrough) {
return new Style(this.color, this.bold, this.italic, this.underlined, strikethrough, this.obfuscated, this.insertion, this.font);
}
public Style obfuscated(@Nullable Boolean obfuscated) {
return new Style(this.color, this.bold, this.italic, this.underlined, this.strikethrough, obfuscated, this.insertion, this.font);
}
/**
* Returns a new style with the insertion provided and all other
* attributes of this style.
*
* @param insertion the new insertion string
*/
public Style withInsertion(@Nullable String insertion) {
return new Style(this.color, this.bold, this.italic, this.underlined, this.strikethrough, this.obfuscated, insertion, this.font);
}
/**
* Returns a new style with the font provided and all other
* attributes of this style.
*
* @param font the new font
*/
public Style withFont(@Nullable Identifier font) {
return new Style(this.color, this.bold, this.italic, this.underlined, this.strikethrough, this.obfuscated, this.insertion, font);
}
/**
* Returns a new style with the formatting provided and all other
* attributes of this style.
*
* @param formatting the new formatting
*/
public Style withFormatting(Formatting formatting) {
TextColor textColor = this.color;
Boolean boolean_ = this.bold;
Boolean boolean2 = this.italic;
Boolean boolean3 = this.strikethrough;
Boolean boolean4 = this.underlined;
Boolean boolean5 = this.obfuscated;
switch (formatting) {
case OBFUSCATED:
boolean5 = true;
break;
case BOLD:
boolean_ = true;
break;
case STRIKETHROUGH:
boolean3 = true;
break;
case UNDERLINE:
boolean4 = true;
break;
case ITALIC:
boolean2 = true;
break;
case RESET:
return EMPTY;
default:
textColor = TextColor.fromFormatting(formatting);
}
return new Style(textColor, boolean_, boolean2, boolean4, boolean3, boolean5, this.insertion, this.font, formatting);
}
/**
* Returns a new style with the formatting provided and some applicable
* attributes of this style.
*
* <p>When a color formatting is passed for {@code formatting}, the other
* formattings, including bold, italic, strikethrough, underlined, and
* obfuscated, are all removed.
*
* @param formatting the new formatting
*/
public Style withExclusiveFormatting(Formatting formatting) {
TextColor textColor = this.color;
Boolean boolean_ = this.bold;
Boolean boolean2 = this.italic;
Boolean boolean3 = this.strikethrough;
Boolean boolean4 = this.underlined;
Boolean boolean5 = this.obfuscated;
switch (formatting) {
case OBFUSCATED:
boolean5 = true;
break;
case BOLD:
boolean_ = true;
break;
case STRIKETHROUGH:
boolean3 = true;
break;
case UNDERLINE:
boolean4 = true;
break;
case ITALIC:
boolean2 = true;
break;
case RESET:
return EMPTY;
default:
boolean5 = false;
boolean_ = false;
boolean3 = false;
boolean4 = false;
boolean2 = false;
textColor = TextColor.fromFormatting(formatting);
}
return new Style(textColor, boolean_, boolean2, boolean4, boolean3, boolean5, this.insertion, this.font, formatting);
}
/**
* Returns a new style with the formattings provided and all other
* attributes of this style.
*
* @param formattings an array of new formattings
*/
public Style withFormatting(Formatting... formattings) {
TextColor textColor = this.color;
Boolean boolean_ = this.bold;
Boolean boolean2 = this.italic;
Boolean boolean3 = this.strikethrough;
Boolean boolean4 = this.underlined;
Boolean boolean5 = this.obfuscated;
Formatting[] var8 = formattings;
int var9 = formattings.length;
for (int var10 = 0; var10 < var9; ++var10) {
Formatting formatting = var8[var10];
switch (formatting) {
case OBFUSCATED:
boolean5 = true;
break;
case BOLD:
boolean_ = true;
break;
case STRIKETHROUGH:
boolean3 = true;
break;
case UNDERLINE:
boolean4 = true;
break;
case ITALIC:
boolean2 = true;
break;
case RESET:
return EMPTY;
default:
textColor = TextColor.fromFormatting(formatting);
}
}
return new Style(textColor, boolean_, boolean2, boolean4, boolean3, boolean5, this.insertion, this.font, formattings);
}
/**
* Returns a new style with the undefined attributes of this style filled
* by the {@code parent} style.
*
* @param parent the parent style
*/
public Style withParent(Style parent) {
if (this == EMPTY) {
return parent;
} else {
return parent == EMPTY ? this : new Style(this.color != null ? this.color : parent.color, this.bold != null ? this.bold : parent.bold, this.italic != null ? this.italic : parent.italic, this.underlined != null ? this.underlined : parent.underlined, this.strikethrough != null ? this.strikethrough : parent.strikethrough, this.obfuscated != null ? this.obfuscated : parent.obfuscated, this.insertion != null ? this.insertion : parent.insertion, this.font != null ? this.font : parent.font, this.formattings != null ? this.formattings : parent.formattings);
}
}
public String toString() {
return "Style{ color=" + this.color + ", bold=" + this.bold + ", italic=" + this.italic + ", underlined=" + this.underlined + ", strikethrough=" + this.strikethrough + ", obfuscated=" + this.obfuscated + ", insertion=" + this.getInsertion() + ", font=" + this.getFont() + ", formattings=" + Arrays.toString(this.formattings) + "}";
}
public boolean equals(Object o) {
if (this == o) {
return true;
} else if (!(o instanceof Style style)) {
return false;
} else {
return this.isBold() == style.isBold() && Objects.equals(this.getColor(), style.getColor()) && this.isItalic() == style.isItalic() && this.isObfuscated() == style.isObfuscated() && this.isStrikethrough() == style.isStrikethrough() && this.isUnderlined() == style.isUnderlined() && Objects.equals(this.getInsertion(), style.getInsertion()) && Objects.equals(this.getFont(), style.getFont()) && Arrays.equals(this.formattings, style.formattings);
}
}
public int hashCode() {
return Objects.hash(this.color, this.bold, this.italic, this.underlined, this.strikethrough, this.obfuscated, this.insertion);
}
/**
* A JSON serializer for {@link Style}.
*/
public static class Serializer implements JsonDeserializer<Style>, JsonSerializer<Style> {
@Nullable
public Style deserialize(JsonElement jsonElement, Type type, JsonDeserializationContext jsonDeserializationContext) throws JsonParseException {
if (jsonElement.isJsonObject()) {
JsonObject jsonObject = jsonElement.getAsJsonObject();
if (jsonObject == null) {
return null;
} else {
Boolean boolean_ = parseNullableBoolean(jsonObject, "bold");
Boolean boolean2 = parseNullableBoolean(jsonObject, "italic");
Boolean boolean3 = parseNullableBoolean(jsonObject, "underlined");
Boolean boolean4 = parseNullableBoolean(jsonObject, "strikethrough");
Boolean boolean5 = parseNullableBoolean(jsonObject, "obfuscated");
TextColor textColor = parseColor(jsonObject);
String string = parseInsertion(jsonObject);
Identifier identifier = getFont(jsonObject);
return new Style(textColor, boolean_, boolean2, boolean3, boolean4, boolean5, string, identifier);
}
} else {
return null;
}
}
@Nullable
private static Identifier getFont(JsonObject root) {
if (root.has("font")) {
String string = JsonHelper.getString(root, "font");
try {
return new Identifier(string);
} catch (InvalidIdentifierException var3) {
throw new JsonSyntaxException("Invalid font name: " + string);
}
} else {
return null;
}
}
@Nullable
private static String parseInsertion(JsonObject root) {
return JsonHelper.getString(root, "insertion", null);
}
@Nullable
private static TextColor parseColor(JsonObject root) {
if (root.has("color")) {
String string = JsonHelper.getString(root, "color");
return TextColor.parse(string);
} else {
return null;
}
}
@Nullable
private static Boolean parseNullableBoolean(JsonObject root, String key) {
return root.has(key) ? root.get(key).getAsBoolean() : null;
}
@Nullable
public JsonElement serialize(Style style, Type type, JsonSerializationContext jsonSerializationContext) {
if (style.isEmpty()) {
return null;
} else {
JsonObject jsonObject = new JsonObject();
if (style.bold != null) {
jsonObject.addProperty("bold", style.bold);
}
if (style.italic != null) {
jsonObject.addProperty("italic", style.italic);
}
if (style.underlined != null) {
jsonObject.addProperty("underlined", style.underlined);
}
if (style.strikethrough != null) {
jsonObject.addProperty("strikethrough", style.strikethrough);
}
if (style.obfuscated != null) {
jsonObject.addProperty("obfuscated", style.obfuscated);
}
if (style.color != null) {
jsonObject.addProperty("color", style.color.getName());
}
if (style.insertion != null) {
jsonObject.add("insertion", jsonSerializationContext.serialize(style.insertion));
}
if (style.font != null) {
jsonObject.addProperty("font", style.font.toString());
}
return jsonObject;
}
}
}
}

Ver arquivo

@ -0,0 +1,123 @@
package com.awakenedredstone.autowhitelist.discord.api.text;
import com.mojang.brigadier.Message;
import java.util.Iterator;
import java.util.List;
import java.util.Optional;
/**
* A text. Can be converted to and from JSON format.
*
* <p>Each text has a tree structure, embodying all its {@link
* #getSiblings() siblings}. To iterate contents in the text and all
* its siblings, call {@code visit} methods.</p>
*
* <p>This interface does not expose mutation operations. For mutation,
* refer to {@link MutableText}.</p>
*
* @see MutableText
*/
public interface Text extends Message, StringVisitable {
/**
* Returns the style of this text.
*/
Style getStyle();
/**
* Returns the string representation of this text itself, excluding siblings.
*/
String asString();
default String getString() {
return StringVisitable.super.getString();
}
/**
* Returns the string representation of this text itself, transforming its {@link Style} to markdown format.
*/
String markdownFormatted();
/**
* Returns the siblings of this text.
*/
List<Text> getSiblings();
MutableText shallowCopy();
MutableText partialCopy();
/**
* Copies the text itself, excluding the styles or siblings.
*/
MutableText copy();
default <T> Optional<T> visit(StringVisitable.StyledVisitor<T> styledVisitor, Style style) {
Style style2 = this.getStyle().withParent(style);
Optional<T> optional = this.visitSelf(styledVisitor, style2);
if (optional.isPresent()) {
return optional;
} else {
Iterator<Text> var5 = this.getSiblings().iterator();
Optional<T> optional2;
do {
if (!var5.hasNext()) {
return Optional.empty();
}
Text text = var5.next();
optional2 = text.visit(styledVisitor, style2);
} while(optional2.isEmpty());
return optional2;
}
}
default <T> Optional<T> visit(StringVisitable.Visitor<T> visitor) {
Optional<T> optional = this.visitSelf(visitor);
if (optional.isPresent()) {
return optional;
} else {
Iterator<Text> var3 = this.getSiblings().iterator();
Optional<T> optional2;
do {
if (!var3.hasNext()) {
return Optional.empty();
}
Text text = var3.next();
optional2 = text.visit(visitor);
} while(optional2.isEmpty());
return optional2;
}
}
/**
* Visits the text itself.
*
* @see #visit(StyledVisitor, Style)
* @return the visitor's return value
*
* @param visitor the visitor
* @param style the current style
*/
default <T> Optional<T> visitSelf(StringVisitable.StyledVisitor<T> visitor, Style style) {
return visitor.accept(style, this.asString());
}
/**
* Visits the text itself.
*
* @see #visit(Visitor)
* @return the visitor's return value
*
* @param visitor the visitor
*/
default <T> Optional<T> visitSelf(StringVisitable.Visitor<T> visitor) {
return visitor.accept(this.asString());
}
}

Ver arquivo

@ -0,0 +1,120 @@
package com.awakenedredstone.autowhitelist.discord.api.text;
import com.awakenedredstone.autowhitelist.discord.api.util.Formatting;
import com.google.common.collect.ImmutableMap;
import org.jetbrains.annotations.Nullable;
import java.util.Map;
import java.util.Objects;
import java.util.function.Function;
import java.util.stream.Stream;
/**
* Represents an RGB color of a {@link Text}.
*
* <p>This is immutable, and part of a {@link Style}.
*
* @see Style
*/
public final class TextColor {
private static final String RGB_PREFIX = "#";
private static final Map<Formatting, TextColor> FORMATTING_TO_COLOR = Stream.of(Formatting.values()).filter(Formatting::isColor).collect(ImmutableMap.toImmutableMap(Function.identity(), (formatting) -> new TextColor(formatting.getColorValue(), formatting.getName())));
private static final Map<String, TextColor> BY_NAME;
private final int rgb;
@Nullable
private final String name;
private TextColor(int rgb, String name) {
this.rgb = rgb;
this.name = name;
}
private TextColor(int rgb) {
this.rgb = rgb;
this.name = null;
}
/**
* Gets the RGB value of this color.
*
* <p>The red bits can be obtained by {@code (rgb >> 16) & 0xFF}, green bits
* by {@code (rgb >> 8) & 0xFF}, blue bits by {@code rgb & 0xFF}.
*/
public int getRgb() {
return this.rgb;
}
/**
* Gets the name of this color, used for converting the color to JSON format.
*/
public String getName() {
return this.name != null ? this.name : this.getHexCode();
}
private String getHexCode() {
return String.format("#%06X", this.rgb);
}
public boolean equals(Object o) {
if (this == o) {
return true;
} else if (o != null && this.getClass() == o.getClass()) {
TextColor textColor = (TextColor)o;
return this.rgb == textColor.rgb;
} else {
return false;
}
}
public int hashCode() {
return Objects.hash(new Object[]{this.rgb, this.name});
}
public String toString() {
return this.name != null ? this.name : this.getHexCode();
}
/**
* Obtains a text color from a formatting.
*
* @param formatting the formatting
*/
@Nullable
public static TextColor fromFormatting(Formatting formatting) {
return (TextColor)FORMATTING_TO_COLOR.get(formatting);
}
/**
* Obtains a text color from an RGB value.
*
* @param rgb the RGB color
*/
public static TextColor fromRgb(int rgb) {
return new TextColor(rgb);
}
/**
* Parses a color by its name.
*
* @param name the name
*/
@Nullable
public static TextColor parse(String name) {
if (name.startsWith("#")) {
try {
int i = Integer.parseInt(name.substring(1), 16);
return fromRgb(i);
} catch (NumberFormatException var2) {
return null;
}
} else {
return (TextColor)BY_NAME.get(name);
}
}
static {
BY_NAME = FORMATTING_TO_COLOR.values().stream().collect(ImmutableMap.toImmutableMap((textColor) -> {
return textColor.name;
}, Function.identity()));
}
}

Ver arquivo

@ -0,0 +1,178 @@
package com.awakenedredstone.autowhitelist.discord.api.text;
import com.awakenedredstone.autowhitelist.discord.api.command.DiscordCommandSource;
import com.awakenedredstone.autowhitelist.discord.api.util.Util;
import com.awakenedredstone.autowhitelist.lang.JigsawLanguage;
import com.google.common.collect.Lists;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import net.dv8tion.jda.api.entities.User;
import net.minecraft.util.Language;
import org.jetbrains.annotations.Nullable;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.Optional;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class TranslatableText extends BaseText implements ParsableText {
private static final Object[] EMPTY_ARGUMENTS = new Object[0];
private static final StringVisitable LITERAL_PERCENT_SIGN = StringVisitable.plain("%");
private static final StringVisitable NULL_ARGUMENT = StringVisitable.plain("null");
private final String key;
private final Object[] args;
@Nullable
private Language languageCache;
private final List<StringVisitable> translations = Lists.newArrayList();
private static final Pattern ARG_FORMAT = Pattern.compile("%(?:(\\d+)\\$)?([A-Za-z%]|$)");
public TranslatableText(String key) {
this.key = key;
this.args = EMPTY_ARGUMENTS;
}
public TranslatableText(String key, Object... args) {
this.key = key;
this.args = args;
}
private void updateTranslations() {
Language language = JigsawLanguage.getInstance();
if (language != this.languageCache) {
this.languageCache = language;
this.translations.clear();
String string = language.get(this.key);
try {
this.setTranslation(string);
} catch (TranslationException var4) {
this.translations.clear();
this.translations.add(StringVisitable.plain(string));
}
}
}
private void setTranslation(String translation) {
Matcher matcher = ARG_FORMAT.matcher(translation);
try {
int i = 0;
int j;
int l;
for(j = 0; matcher.find(j); j = l) {
int k = matcher.start();
l = matcher.end();
String string2;
if (k > j) {
string2 = translation.substring(j, k);
if (string2.indexOf(37) != -1) {
throw new IllegalArgumentException();
}
this.translations.add(StringVisitable.plain(string2));
}
string2 = matcher.group(2);
String string3 = translation.substring(k, l);
if ("%".equals(string2) && "%%".equals(string3)) {
this.translations.add(LITERAL_PERCENT_SIGN);
} else {
if (!"s".equals(string2)) {
throw new TranslationException(this, "Unsupported format: '" + string3 + "'");
}
String string4 = matcher.group(1);
int m = string4 != null ? Integer.parseInt(string4) - 1 : i++;
if (m < this.args.length) {
this.translations.add(this.getArg(m));
}
}
}
if (j < translation.length()) {
String string5 = translation.substring(j);
if (string5.indexOf(37) != -1) {
throw new IllegalArgumentException();
}
this.translations.add(StringVisitable.plain(string5));
}
} catch (IllegalArgumentException var11) {
throw new TranslationException(this, var11);
}
}
public MutableText parse(@Nullable DiscordCommandSource source, @Nullable User sender, int depth) throws CommandSyntaxException {
Object[] objects = new Object[this.args.length];
for(int i = 0; i < objects.length; ++i) {
Object object = this.args[i];
if (object instanceof Text) {
objects[i] = Util.parse(source, (Text)object, sender, depth);
} else {
objects[i] = object;
}
}
return new TranslatableText(this.key, objects);
}
private StringVisitable getArg(int index) {
if (index >= this.args.length) {
throw new TranslationException(this, index);
} else {
Object object = this.args[index];
if (object instanceof Text) {
return (Text)object;
} else {
return object == null ? NULL_ARGUMENT : StringVisitable.plain(object.toString());
}
}
}
public TranslatableText copy() {
return new TranslatableText(this.key, this.args);
}
public <T> Optional<T> visitSelf(StringVisitable.Visitor<T> visitor) {
this.updateTranslations();
Iterator<StringVisitable> var2 = this.translations.iterator();
Optional<T> optional;
do {
if (!var2.hasNext()) {
return Optional.empty();
}
StringVisitable stringVisitable = var2.next();
optional = stringVisitable.visit(visitor);
} while(optional.isEmpty());
return optional;
}
public boolean equals(Object object) {
if (this == object) {
return true;
} else if (!(object instanceof TranslatableText translatableText)) {
return false;
} else {
return Arrays.equals(this.args, translatableText.args) && this.key.equals(translatableText.key) && super.equals(object);
}
}
public int hashCode() {
int i = super.hashCode();
i = 31 * i + this.key.hashCode();
i = 31 * i + Arrays.hashCode(this.args);
return i;
}
public String toString() {
return "TranslatableComponent{key='" + this.key + "', args=" + Arrays.toString(this.args) + ", siblings=" + this.siblings + "}";
}
}

Ver arquivo

@ -0,0 +1,15 @@
package com.awakenedredstone.autowhitelist.discord.api.text;
public class TranslationException extends IllegalArgumentException {
public TranslationException(TranslatableText text, String message) {
super(String.format("Error parsing: %s: %s", text, message));
}
public TranslationException(TranslatableText text, int index) {
super(String.format("Invalid index %d requested for %s", index, text));
}
public TranslationException(TranslatableText text, Throwable cause) {
super(String.format("Error while parsing: %s", text), cause);
}
}

Ver arquivo

@ -0,0 +1,169 @@
package com.awakenedredstone.autowhitelist.discord.api.util;
import com.google.common.collect.Lists;
import org.jetbrains.annotations.Nullable;
import java.util.*;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
public enum Formatting {
BLACK("BLACK", '0', 0, 0),
DARK_BLUE("DARK_BLUE", '1', 1, 170),
DARK_GREEN("DARK_GREEN", '2', 2, 43520),
DARK_AQUA("DARK_AQUA", '3', 3, 43690),
DARK_RED("DARK_RED", '4', 4, 11141120),
DARK_PURPLE("DARK_PURPLE", '5', 5, 11141290),
GOLD("GOLD", '6', 6, 16755200),
GRAY("GRAY", '7', 7, 11184810),
DARK_GRAY("DARK_GRAY", '8', 8, 5592405),
BLUE("BLUE", '9', 9, 5592575),
GREEN("GREEN", 'a', 10, 5635925),
AQUA("AQUA", 'b', 11, 5636095),
RED("RED", 'c', 12, 16733525),
LIGHT_PURPLE("LIGHT_PURPLE", 'd', 13, 16733695),
YELLOW("YELLOW", 'e', 14, 16777045),
WHITE("WHITE", 'f', 15, 16777215),
OBFUSCATED("OBFUSCATED", 'k', true),
BOLD("BOLD", 'l', "**", true),
STRIKETHROUGH("STRIKETHROUGH", 'm', "~~", true),
UNDERLINE("UNDERLINE", 'n', "__", true),
ITALIC("ITALIC", 'o', "_", true),
CODE("INLINE_CODE", 'p', "`", true),
CODE_BLOCK("CODE_BLOCK", 'q', "```", true),
RESET("RESET", 'r', -1, null);
private static final Map<String, Formatting> BY_NAME = Arrays.stream(values()).collect(Collectors.toMap((f) -> sanitize(f.name), (f) -> f));
private static final Pattern FORMATTING_CODE_PATTERN = Pattern.compile("(?i)§[0-9A-FK-OR]");
private final String name;
private final char code;
private final boolean modifier;
private final String stringValue;
private final int colorIndex;
@Nullable
private final Integer colorValue;
private final String markdown;
private static String sanitize(String name) {
return name.toLowerCase(Locale.ROOT).replaceAll("[^a-z]", "");
}
Formatting(String name, char code, int colorIndex, @Nullable Integer colorValue) {
this(name, code, false, colorIndex, colorValue, "");
}
Formatting(String name, char code, boolean modifier) {
this(name, code, modifier, -1, null, "");
}
Formatting(String name, char code, String markdown, boolean modifier) {
this(name, code, modifier, -1, null, markdown);
}
Formatting(String name, char code, boolean modifier, int colorIndex, @Nullable Integer colorValue, String markdown) {
this.name = name;
this.code = code;
this.modifier = modifier;
this.colorIndex = colorIndex;
this.colorValue = colorValue;
this.stringValue = "§" + code;
this.markdown = markdown;
}
public char getCode() {
return this.code;
}
public int getColorIndex() {
return this.colorIndex;
}
public boolean isModifier() {
return this.modifier;
}
public boolean isColor() {
return !this.modifier && this != RESET;
}
public boolean hasMarkdown() {
return markdown != null;
}
@Nullable
public Integer getColorValue() {
return this.colorValue;
}
public String getName() {
return this.name().toLowerCase(Locale.ROOT);
}
public String getMarkdown() {
return this.markdown;
}
public String toString() {
return this.stringValue;
}
@Nullable
public static String strip(@Nullable String string) {
return string == null ? null : FORMATTING_CODE_PATTERN.matcher(string).replaceAll("");
}
@Nullable
public static Formatting byName(@Nullable String name) {
return name == null ? null : BY_NAME.get(sanitize(name));
}
@Nullable
public static Formatting byColorIndex(int colorIndex) {
if (colorIndex < 0) {
return RESET;
} else {
Formatting[] var1 = values();
int var2 = var1.length;
for (int var3 = 0; var3 < var2; ++var3) {
Formatting formatting = var1[var3];
if (formatting.getColorIndex() == colorIndex) {
return formatting;
}
}
return null;
}
}
@Nullable
public static Formatting byCode(char code) {
char c = Character.toString(code).toLowerCase(Locale.ROOT).charAt(0);
Formatting[] var2 = values();
int var3 = var2.length;
for (int var4 = 0; var4 < var3; ++var4) {
Formatting formatting = var2[var4];
if (formatting.code == c) {
return formatting;
}
}
return null;
}
public static Collection<String> getNames(boolean colors, boolean modifiers) {
List<String> list = Lists.newArrayList();
Formatting[] var3 = values();
int var4 = var3.length;
for (int var5 = 0; var5 < var4; ++var5) {
Formatting formatting = var3[var5];
if ((!formatting.isColor() || colors) && (!formatting.isModifier() || modifiers)) {
list.add(formatting.getName());
}
}
return list;
}
}

Ver arquivo

@ -0,0 +1,198 @@
package com.awakenedredstone.autowhitelist.discord.api.util;
import com.awakenedredstone.autowhitelist.discord.api.text.TranslatableText;
import com.google.gson.*;
import com.mojang.brigadier.StringReader;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import com.mojang.brigadier.exceptions.SimpleCommandExceptionType;
import com.mojang.serialization.Codec;
import com.mojang.serialization.DataResult;
import org.apache.commons.lang3.StringUtils;
import org.jetbrains.annotations.Nullable;
import java.lang.reflect.Type;
/**
* The namespace and path must contain only lowercase letters ([a-z]), digits ([0-9]), or the characters '_', '.', and '-'. The path can also contain the standard path separator '/'.
*/
public class Identifier implements Comparable<Identifier> {
public static final Codec<Identifier> CODEC;
private static final SimpleCommandExceptionType COMMAND_EXCEPTION;
public static final char NAMESPACE_SEPARATOR = ':';
public static final String DEFAULT_NAMESPACE = "minecraft";
public static final String REALMS_NAMESPACE = "realms";
protected final String namespace;
protected final String path;
protected Identifier(String[] id) {
this.namespace = StringUtils.isEmpty(id[0]) ? "minecraft" : id[0];
this.path = id[1];
if (!isNamespaceValid(this.namespace)) {
throw new InvalidIdentifierException("Non [a-z0-9_.-] character in namespace of location: " + this.namespace + ":" + this.path);
} else if (!isPathValid(this.path)) {
throw new InvalidIdentifierException("Non [a-z0-9/._-] character in path of location: " + this.namespace + ":" + this.path);
}
}
/**
* <p>Takes a string of the form {@code <namespace>:<path>}, for example {@code minecraft:iron_ingot}.
* <p>The string will be split (on the {@code :}) into an identifier with the specified path and namespace.
* Prefer using the {@link Identifier#Identifier(String, String) Identifier(java.lang.String, java.lang.String)} constructor that takes the namespace and path as individual parameters to avoid mistakes.
* @throws InvalidIdentifierException if the string cannot be parsed as an identifier.
*/
public Identifier(String id) {
this(split(id, ':'));
}
public Identifier(String namespace, String path) {
this(new String[]{namespace, path});
}
public static Identifier splitOn(String id, char delimiter) {
return new Identifier(split(id, delimiter));
}
/**
* <p>Parses a string into an {@code Identifier}.
* Takes a string of the form {@code <namespace>:<path>}, for example {@code minecraft:iron_ingot}.
* @return resulting identifier, or {@code null} if the string couldn't be parsed as an identifier
*/
@Nullable
public static Identifier tryParse(String id) {
try {
return new Identifier(id);
} catch (InvalidIdentifierException var2) {
return null;
}
}
protected static String[] split(String id, char delimiter) {
String[] strings = new String[]{"minecraft", id};
int i = id.indexOf(delimiter);
if (i >= 0) {
strings[1] = id.substring(i + 1, id.length());
if (i >= 1) {
strings[0] = id.substring(0, i);
}
}
return strings;
}
private static DataResult<Identifier> validate(String id) {
try {
return DataResult.success(new Identifier(id));
} catch (InvalidIdentifierException var2) {
return DataResult.error("Not a valid resource location: " + id + " " + var2.getMessage());
}
}
public String getPath() {
return this.path;
}
public String getNamespace() {
return this.namespace;
}
public String toString() {
return this.namespace + ":" + this.path;
}
public boolean equals(Object o) {
if (this == o) {
return true;
} else if (!(o instanceof Identifier)) {
return false;
} else {
Identifier identifier = (Identifier)o;
return this.namespace.equals(identifier.namespace) && this.path.equals(identifier.path);
}
}
public int hashCode() {
return 31 * this.namespace.hashCode() + this.path.hashCode();
}
public int compareTo(Identifier identifier) {
int i = this.path.compareTo(identifier.path);
if (i == 0) {
i = this.namespace.compareTo(identifier.namespace);
}
return i;
}
public String toUnderscoreSeparatedString() {
return this.toString().replace('/', '_').replace(':', '_');
}
public static Identifier fromCommandInput(StringReader reader) throws CommandSyntaxException {
int i = reader.getCursor();
while(reader.canRead() && isCharValid(reader.peek())) {
reader.skip();
}
String string = reader.getString().substring(i, reader.getCursor());
try {
return new Identifier(string);
} catch (InvalidIdentifierException var4) {
reader.setCursor(i);
throw COMMAND_EXCEPTION.createWithContext(reader);
}
}
public static boolean isCharValid(char c) {
return c >= '0' && c <= '9' || c >= 'a' && c <= 'z' || c == '_' || c == ':' || c == '/' || c == '.' || c == '-';
}
private static boolean isPathValid(String path) {
for(int i = 0; i < path.length(); ++i) {
if (!isPathCharacterValid(path.charAt(i))) {
return false;
}
}
return true;
}
private static boolean isNamespaceValid(String namespace) {
for(int i = 0; i < namespace.length(); ++i) {
if (!isNamespaceCharacterValid(namespace.charAt(i))) {
return false;
}
}
return true;
}
public static boolean isPathCharacterValid(char character) {
return character == '_' || character == '-' || character >= 'a' && character <= 'z' || character >= '0' && character <= '9' || character == '/' || character == '.';
}
private static boolean isNamespaceCharacterValid(char character) {
return character == '_' || character == '-' || character >= 'a' && character <= 'z' || character >= '0' && character <= '9' || character == '.';
}
public static boolean isValid(String id) {
String[] strings = split(id, ':');
return isNamespaceValid(StringUtils.isEmpty(strings[0]) ? "minecraft" : strings[0]) && isPathValid(strings[1]);
}
static {
CODEC = Codec.STRING.comapFlatMap(Identifier::validate, Identifier::toString).stable();
COMMAND_EXCEPTION = new SimpleCommandExceptionType(new TranslatableText("argument.id.invalid"));
}
public static class Serializer implements JsonDeserializer<Identifier>, JsonSerializer<Identifier> {
public Identifier deserialize(JsonElement jsonElement, Type type, JsonDeserializationContext jsonDeserializationContext) throws JsonParseException {
return new Identifier(JsonHelper.asString(jsonElement, "location"));
}
public JsonElement serialize(Identifier identifier, Type type, JsonSerializationContext jsonSerializationContext) {
return new JsonPrimitive(identifier.toString());
}
}
}

Ver arquivo

@ -0,0 +1,11 @@
package com.awakenedredstone.autowhitelist.discord.api.util;
public class InvalidIdentifierException extends RuntimeException {
public InvalidIdentifierException(String message) {
super(message);
}
public InvalidIdentifierException(String message, Throwable throwable) {
super(message, throwable);
}
}

Ver arquivo

@ -0,0 +1,57 @@
package com.awakenedredstone.autowhitelist.discord.api.util;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonPrimitive;
import com.google.gson.JsonSyntaxException;
import org.apache.commons.lang3.StringUtils;
public class JsonHelper {
public static String asString(JsonElement element, String name) {
if (element.isJsonPrimitive()) {
return element.getAsString();
} else {
throw new JsonSyntaxException("Expected " + name + " to be a string, was " + getType(element));
}
}
public static String getString(JsonObject object, String element) {
if (object.has(element)) {
return asString(object.get(element), element);
} else {
throw new JsonSyntaxException("Missing " + element + ", expected to find a string");
}
}
public static String getString(JsonObject object, String element, String defaultStr) {
return object.has(element) ? asString(object.get(element), element) : defaultStr;
}
public static String getType(JsonElement element) {
String string = StringUtils.abbreviateMiddle(String.valueOf(element), "...", 10);
if (element == null) {
return "null (missing)";
} else if (element.isJsonNull()) {
return "null (json)";
} else if (element.isJsonArray()) {
return "an array (" + string + ")";
} else if (element.isJsonObject()) {
return "an object (" + string + ")";
} else {
if (element.isJsonPrimitive()) {
JsonPrimitive jsonPrimitive = element.getAsJsonPrimitive();
if (jsonPrimitive.isNumber()) {
return "a number (" + string + ")";
}
if (jsonPrimitive.isBoolean()) {
return "a boolean (" + string + ")";
}
}
return string;
}
}
}

Ver arquivo

@ -0,0 +1,5 @@
package com.awakenedredstone.autowhitelist.discord.api.util;
public enum Unit {
INSTANCE;
}

Ver arquivo

@ -0,0 +1,48 @@
package com.awakenedredstone.autowhitelist.discord.api.util;
import com.awakenedredstone.autowhitelist.discord.api.command.DiscordCommandSource;
import com.awakenedredstone.autowhitelist.discord.api.text.LiteralText;
import com.awakenedredstone.autowhitelist.discord.api.text.MutableText;
import com.awakenedredstone.autowhitelist.discord.api.text.ParsableText;
import com.awakenedredstone.autowhitelist.discord.api.text.Text;
import com.mojang.brigadier.Message;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import net.dv8tion.jda.api.entities.User;
import org.jetbrains.annotations.Nullable;
import java.util.function.LongSupplier;
public class Util {
public static LongSupplier nanoTimeSupplier = System::nanoTime;
public static Text toText(Message message) {
return message instanceof Text ? (Text)message : new LiteralText(message.getString());
}
public static MutableText parse(@Nullable DiscordCommandSource source, Text text, @Nullable User sender, int depth) throws CommandSyntaxException {
if (depth > 100) {
return text.shallowCopy();
} else {
MutableText mutableText = text instanceof ParsableText ? ((ParsableText)text).parse(source, sender, depth + 1) : text.copy();
for (Text text2 : text.getSiblings()) {
mutableText.append(parse(source, text2, sender, depth + 1));
}
return mutableText.fillStyle(text.getStyle());
}
}
public static String getInnermostMessage(Throwable t) {
if (t.getCause() != null) {
return getInnermostMessage(t.getCause());
} else {
return t.getMessage() != null ? t.getMessage() : t.toString();
}
}
public static long getMeasuringTimeNano() {
return nanoTimeSupplier.getAsLong();
}
}

Ver arquivo

@ -0,0 +1,58 @@
package com.awakenedredstone.autowhitelist.discord.api.util.profiler;
import com.google.common.collect.ImmutableSet;
import org.apache.commons.lang3.tuple.Pair;
import org.jetbrains.annotations.Nullable;
import java.util.Set;
import java.util.function.Supplier;
public class DummyProfiler implements ReadableProfiler {
public static final DummyProfiler INSTANCE = new DummyProfiler();
private DummyProfiler() {
}
public void startTick() {
}
public void endTick() {
}
public void push(String location) {
}
public void push(Supplier<String> locationGetter) {
}
public void method_37167(SamplingChannel samplingChannel) {
}
public void pop() {
}
public void swap(String location) {
}
public void swap(Supplier<String> locationGetter) {
}
public void visit(String marker) {
}
public void visit(Supplier<String> markerGetter) {
}
public ProfileResult getResult() {
return EmptyProfileResult.INSTANCE;
}
@Nullable
public ProfilerSystem.LocatedInfo getInfo(String name) {
return null;
}
public Set<Pair<String, SamplingChannel>> method_37168() {
return ImmutableSet.of();
}
}

Ver arquivo

@ -0,0 +1,22 @@
package com.awakenedredstone.autowhitelist.discord.api.util.profiler;
public class DummyRecorder implements Recorder {
public static final Recorder INSTANCE = new DummyRecorder();
public void stop() {
}
public void startTick() {
}
public boolean isActive() {
return false;
}
public Profiler getProfiler() {
return DummyProfiler.INSTANCE;
}
public void endTick() {
}
}

Ver arquivo

@ -0,0 +1,40 @@
package com.awakenedredstone.autowhitelist.discord.api.util.profiler;
import java.nio.file.Path;
import java.util.Collections;
import java.util.List;
public class EmptyProfileResult implements ProfileResult {
public static final EmptyProfileResult INSTANCE = new EmptyProfileResult();
private EmptyProfileResult() {
}
public List<ProfilerTiming> getTimings(String parentPath) {
return Collections.emptyList();
}
public boolean save(Path path) {
return false;
}
public long getStartTime() {
return 0L;
}
public int getStartTick() {
return 0;
}
public long getEndTime() {
return 0L;
}
public int getEndTick() {
return 0;
}
public String getRootTimings() {
return "";
}
}

Ver arquivo

@ -0,0 +1,26 @@
package com.awakenedredstone.autowhitelist.discord.api.util.profiler;
import it.unimi.dsi.fastutil.objects.Object2LongMap;
/**
* Profiling information on a specific profiler location.
*/
public interface ProfileLocationInfo {
/**
* Returns the total time spent visiting the profiler location.
*/
long getTotalTime();
long method_37169();
/**
* Returns the number of times the profiler location has been visited.
*/
long getVisitCount();
/**
* Returns a marker to count map indicating the times each marker has been
* visited in the profiler location.
*/
Object2LongMap<String> getCounts();
}

Ver arquivo

@ -0,0 +1,34 @@
package com.awakenedredstone.autowhitelist.discord.api.util.profiler;
import java.nio.file.Path;
import java.util.List;
public interface ProfileResult {
char SPLITTER_CHAR = '\u001e';
List<ProfilerTiming> getTimings(String parentPath);
boolean save(Path path);
long getStartTime();
int getStartTick();
long getEndTime();
int getEndTick();
default long getTimeSpan() {
return this.getEndTime() - this.getStartTime();
}
default int getTickSpan() {
return this.getEndTick() - this.getStartTick();
}
String getRootTimings();
static String getHumanReadableName(String path) {
return path.replace('\u001e', '.');
}
}

Ver arquivo

@ -0,0 +1,284 @@
package com.awakenedredstone.autowhitelist.discord.api.util.profiler;
import com.awakenedredstone.autowhitelist.AutoWhitelist;
import com.awakenedredstone.autowhitelist.discord.api.AutoWhitelistAPI;
import com.awakenedredstone.autowhitelist.discord.api.util.Util;
import com.google.common.base.Splitter;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import it.unimi.dsi.fastutil.objects.Object2LongMap;
import it.unimi.dsi.fastutil.objects.Object2LongMaps;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import java.io.BufferedWriter;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.*;
import java.util.Map.Entry;
public class ProfileResultImpl implements ProfileResult {
private static final Logger LOGGER = LogManager.getLogger();
private static final ProfileLocationInfo EMPTY_INFO = new ProfileLocationInfo() {
public long getTotalTime() {
return 0L;
}
public long method_37169() {
return 0L;
}
public long getVisitCount() {
return 0L;
}
public Object2LongMap<String> getCounts() {
return Object2LongMaps.emptyMap();
}
};
private static final Splitter SPLITTER = Splitter.on('\u001e');
private static final Comparator<Entry<String, CounterInfo>> COMPARATOR = Entry.comparingByValue(Comparator.comparingLong(counterInfo -> counterInfo.totalTime));
private final Map<String, ? extends ProfileLocationInfo> locationInfos;
private final long startTime;
private final int startTick;
private final long endTime;
private final int endTick;
private final int tickDuration;
public ProfileResultImpl(Map<String, ? extends ProfileLocationInfo> locationInfos, long startTime, int startTick, long endTime, int endTick) {
this.locationInfos = locationInfos;
this.startTime = startTime;
this.startTick = startTick;
this.endTime = endTime;
this.endTick = endTick;
this.tickDuration = endTick - startTick;
}
private ProfileLocationInfo getInfo(String path) {
ProfileLocationInfo profileLocationInfo = this.locationInfos.get(path);
return profileLocationInfo != null ? profileLocationInfo : EMPTY_INFO;
}
public List<ProfilerTiming> getTimings(String parentPath) {
ProfileLocationInfo profileLocationInfo = this.getInfo("root");
long l = profileLocationInfo.getTotalTime();
ProfileLocationInfo profileLocationInfo2 = this.getInfo(parentPath);
long m = profileLocationInfo2.getTotalTime();
long n = profileLocationInfo2.getVisitCount();
List<ProfilerTiming> list = Lists.newArrayList();
if (!parentPath.isEmpty()) {
parentPath = parentPath + "\u001e";
}
long o = 0L;
Iterator var14 = this.locationInfos.keySet().iterator();
while(var14.hasNext()) {
String string2 = (String)var14.next();
if (isSubpath(parentPath, string2)) {
o += this.getInfo(string2).getTotalTime();
}
}
float f = (float)o;
if (o < m) {
o = m;
}
if (l < o) {
l = o;
}
Iterator var26 = this.locationInfos.keySet().iterator();
while(var26.hasNext()) {
String string3 = (String)var26.next();
if (isSubpath(parentPath, string3)) {
ProfileLocationInfo profileLocationInfo3 = this.getInfo(string3);
long p = profileLocationInfo3.getTotalTime();
double d = (double)p * 100.0D / (double)o;
double e = (double)p * 100.0D / (double)l;
String string4 = string3.substring(parentPath.length());
list.add(new ProfilerTiming(string4, d, e, profileLocationInfo3.getVisitCount()));
}
}
if ((float)o > f) {
list.add(new ProfilerTiming("unspecified", (double)((float)o - f) * 100.0D / (double)o, (double)((float)o - f) * 100.0D / (double)l, n));
}
Collections.sort(list);
list.add(0, new ProfilerTiming(parentPath, 100.0D, (double)o * 100.0D / (double)l, n));
return list;
}
private static boolean isSubpath(String parent, String path) {
return path.length() > parent.length() && path.startsWith(parent) && path.indexOf(30, parent.length() + 1) < 0;
}
private Map<String, CounterInfo> setupCounters() {
Map<String, CounterInfo> map = Maps.newTreeMap();
this.locationInfos.forEach((string, profileLocationInfo) -> {
Object2LongMap<String> object2LongMap = profileLocationInfo.getCounts();
if (!object2LongMap.isEmpty()) {
List<String> list = SPLITTER.splitToList(string);
object2LongMap.forEach((string_, long_) -> {
map.computeIfAbsent(string_, (string__) -> {
return new CounterInfo();
}).add(list.iterator(), long_);
});
}
});
return map;
}
public long getStartTime() {
return this.startTime;
}
public int getStartTick() {
return this.startTick;
}
public long getEndTime() {
return this.endTime;
}
public int getEndTick() {
return this.endTick;
}
public boolean save(Path path) {
BufferedWriter writer = null;
boolean var4;
try {
Files.createDirectories(path.getParent());
writer = Files.newBufferedWriter(path, StandardCharsets.UTF_8);
writer.write(this.asString(this.getTimeSpan(), this.getTickSpan()));
boolean var3 = true;
return var3;
} catch (Throwable var8) {
LOGGER.error("Could not save profiler results to {}", path, var8);
var4 = false;
} finally {
IOUtils.closeQuietly(writer);
}
return var4;
}
protected String asString(long timeSpan, int tickSpan) {
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append("---- Minecraft Profiler Results ----\n");
stringBuilder.append("// ");
stringBuilder.append(generateWittyComment());
stringBuilder.append("\n\n");
stringBuilder.append("Version: ").append(AutoWhitelist.getConfigData().devVersion ? "dev" : "production").append('\n');
stringBuilder.append("Time span: ").append(timeSpan / 1000000L).append(" ms\n");
stringBuilder.append("Tick span: ").append(tickSpan).append(" ticks\n");
stringBuilder.append("// This is approximately ").append(String.format(Locale.ROOT, "%.2f", (float)tickSpan / ((float)timeSpan / 1.0E9F))).append(" ticks per second. It should be ").append(20).append(" ticks per second\n\n");
stringBuilder.append("--- BEGIN PROFILE DUMP ---\n\n");
this.appendTiming(0, "root", stringBuilder);
stringBuilder.append("--- END PROFILE DUMP ---\n\n");
Map<String, CounterInfo> map = this.setupCounters();
if (!map.isEmpty()) {
stringBuilder.append("--- BEGIN COUNTER DUMP ---\n\n");
this.appendCounterDump(map, stringBuilder, tickSpan);
stringBuilder.append("--- END COUNTER DUMP ---\n\n");
}
return stringBuilder.toString();
}
public String getRootTimings() {
StringBuilder stringBuilder = new StringBuilder();
this.appendTiming(0, "root", stringBuilder);
return stringBuilder.toString();
}
private static StringBuilder indent(StringBuilder sb, int size) {
sb.append(String.format("[%02d] ", size));
for(int i = 0; i < size; ++i) {
sb.append("| ");
}
return sb;
}
private void appendTiming(int level, String name, StringBuilder sb) {
List<ProfilerTiming> list = this.getTimings(name);
Object2LongMap<String> object2LongMap = ObjectUtils.firstNonNull(this.locationInfos.get(name), EMPTY_INFO).getCounts();
object2LongMap.forEach((string, long_) -> {
indent(sb, level).append('#').append(string).append(' ').append(long_).append('/').append(long_ / (long)this.tickDuration).append('\n');
});
if (list.size() >= 3) {
for(int i = 1; i < list.size(); ++i) {
ProfilerTiming profilerTiming = list.get(i);
indent(sb, level).append(profilerTiming.name).append('(').append(profilerTiming.visitCount).append('/').append(String.format(Locale.ROOT, "%.0f", (float)profilerTiming.visitCount / (float)this.tickDuration)).append(')').append(" - ").append(String.format(Locale.ROOT, "%.2f", profilerTiming.parentSectionUsagePercentage)).append("%/").append(String.format(Locale.ROOT, "%.2f", profilerTiming.totalUsagePercentage)).append("%\n");
if (!"unspecified".equals(profilerTiming.name)) {
try {
this.appendTiming(level + 1, name + "\u001e" + profilerTiming.name, sb);
} catch (Exception var9) {
sb.append("[[ EXCEPTION ").append(var9).append(" ]]");
}
}
}
}
}
@SuppressWarnings("unchecked")
private void appendCounter(int depth, String name, CounterInfo info, int tickSpan, StringBuilder sb) {
indent(sb, depth).append(name).append(" total:").append(info.selfTime).append('/').append(info.totalTime).append(" average: ").append(info.selfTime / (long)tickSpan).append('/').append(info.totalTime / (long)tickSpan).append('\n');
info.subCounters.entrySet().stream().sorted(COMPARATOR.reversed()).forEach((entry) -> this.appendCounter(depth + 1, entry.getKey(), entry.getValue(), tickSpan, sb));
}
private void appendCounterDump(Map<String, CounterInfo> counters, StringBuilder sb, int tickSpan) {
counters.forEach((string, counterInfo) -> {
sb.append("-- Counter: ").append(string).append(" --\n");
this.appendCounter(0, "root", counterInfo.subCounters.get("root"), tickSpan, sb);
sb.append("\n\n");
});
}
private static String generateWittyComment() {
String[] strings = new String[]{"Shiny numbers!", "Am I not running fast enough? :(", "I'm working as hard as I can!", "Will I ever be good enough for you? :(", "Speedy. Zoooooom!", "Hello world", "40% better than a crash report.", "Now with extra numbers", "Now with less numbers", "Now with the same numbers", "You should add flames to things, it makes them go faster!", "Do you feel the need for... optimization?", "*cracks redstone whip*", "Maybe if you treated it better then it'll have more motivation to work faster! Poor server."};
try {
return strings[(int)(Util.getMeasuringTimeNano() % (long)strings.length)];
} catch (Throwable var2) {
return "Witty comment unavailable :(";
}
}
public int getTickSpan() {
return this.tickDuration;
}
private static class CounterInfo {
long selfTime;
long totalTime;
final Map<String, CounterInfo> subCounters = Maps.newHashMap();
CounterInfo() {
}
public void add(Iterator<String> pathIterator, long time) {
this.totalTime += time;
if (!pathIterator.hasNext()) {
this.selfTime += time;
} else {
this.subCounters.computeIfAbsent(pathIterator.next(), (string) -> {
return new CounterInfo();
}).add(pathIterator, time);
}
}
}
}

Ver arquivo

@ -0,0 +1,104 @@
package com.awakenedredstone.autowhitelist.discord.api.util.profiler;
import java.util.function.Supplier;
public interface Profiler {
String ROOT_NAME = "root";
void startTick();
void endTick();
void push(String location);
void push(Supplier<String> locationGetter);
void pop();
void swap(String location);
void swap(Supplier<String> locationGetter);
void method_37167(SamplingChannel samplingChannel);
/**
* Increment the visit count for a marker.
*
* <p>This is useful to keep track of number of calls made to performance-
* wise expensive methods.
*
* @param marker a unique marker
*/
void visit(String marker);
/**
* Increment the visit count for a marker.
*
* <p>This is useful to keep track of number of calls made to performance-
* wise expensive methods.
*
* <p>This method is preferred if getting the marker is costly; the
* supplier won't be called if the profiler is disabled.
*
* @param markerGetter the getter for a unique marker
*/
void visit(Supplier<String> markerGetter);
static Profiler union(final Profiler a, final Profiler b) {
if (a == DummyProfiler.INSTANCE) {
return b;
} else {
return b == DummyProfiler.INSTANCE ? a : new Profiler() {
public void startTick() {
a.startTick();
b.startTick();
}
public void endTick() {
a.endTick();
b.endTick();
}
public void push(String location) {
a.push(location);
b.push(location);
}
public void push(Supplier<String> locationGetter) {
a.push(locationGetter);
b.push(locationGetter);
}
public void method_37167(SamplingChannel samplingChannel) {
a.method_37167(samplingChannel);
b.method_37167(samplingChannel);
}
public void pop() {
a.pop();
b.pop();
}
public void swap(String location) {
a.swap(location);
b.swap(location);
}
public void swap(Supplier<String> locationGetter) {
a.swap(locationGetter);
b.swap(locationGetter);
}
public void visit(String marker) {
a.visit(marker);
b.visit(marker);
}
public void visit(Supplier<String> markerGetter) {
a.visit(markerGetter);
b.visit(markerGetter);
}
};
}
}
}

Ver arquivo

@ -0,0 +1,191 @@
package com.awakenedredstone.autowhitelist.discord.api.util.profiler;
import com.awakenedredstone.autowhitelist.discord.api.util.Util;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import it.unimi.dsi.fastutil.longs.LongArrayList;
import it.unimi.dsi.fastutil.longs.LongList;
import it.unimi.dsi.fastutil.objects.Object2LongMap;
import it.unimi.dsi.fastutil.objects.Object2LongMaps;
import it.unimi.dsi.fastutil.objects.Object2LongOpenHashMap;
import it.unimi.dsi.fastutil.objects.ObjectArraySet;
import org.apache.commons.lang3.tuple.Pair;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.jetbrains.annotations.Nullable;
import java.time.Duration;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.IntSupplier;
import java.util.function.LongSupplier;
import java.util.function.Supplier;
public class ProfilerSystem implements ReadableProfiler {
private static final long TIMEOUT_NANOSECONDS = Duration.ofMillis(100L).toNanos();
private static final Logger LOGGER = LogManager.getLogger();
private final List<String> path = Lists.newArrayList();
private final LongList timeList = new LongArrayList();
private final Map<String, LocatedInfo> locationInfos = Maps.newHashMap();
private final IntSupplier endTickGetter;
private final LongSupplier timeGetter;
private final long startTime;
private final int startTick;
private String location = "";
private boolean tickStarted;
@Nullable
private ProfilerSystem.LocatedInfo currentInfo;
private final boolean checkTimeout;
private final Set<Pair<String, SamplingChannel>> field_33873 = new ObjectArraySet();
public ProfilerSystem(LongSupplier timeGetter, IntSupplier tickGetter, boolean checkTimeout) {
this.startTime = timeGetter.getAsLong();
this.timeGetter = timeGetter;
this.startTick = tickGetter.getAsInt();
this.endTickGetter = tickGetter;
this.checkTimeout = checkTimeout;
}
public void startTick() {
if (this.tickStarted) {
LOGGER.error("Profiler tick already started - missing endTick()?");
} else {
this.tickStarted = true;
this.location = "";
this.path.clear();
this.push("root");
}
}
public void endTick() {
if (!this.tickStarted) {
LOGGER.error("Profiler tick already ended - missing startTick()?");
} else {
this.pop();
this.tickStarted = false;
if (!this.location.isEmpty()) {
LOGGER.error("Profiler tick ended before path was fully popped (remainder: '{}'). Mismatched push/pop?", () -> {
return ProfileResult.getHumanReadableName(this.location);
});
}
}
}
public void push(String location) {
if (!this.tickStarted) {
LOGGER.error((String)"Cannot push '{}' to profiler if profiler tick hasn't started - missing startTick()?", (Object)location);
} else {
if (!this.location.isEmpty()) {
this.location = this.location + "\u001e";
}
this.location = this.location + location;
this.path.add(this.location);
this.timeList.add(Util.getMeasuringTimeNano());
this.currentInfo = null;
}
}
public void push(Supplier<String> locationGetter) {
this.push((String)locationGetter.get());
}
public void method_37167(SamplingChannel samplingChannel) {
this.field_33873.add(Pair.of(this.location, samplingChannel));
}
public void pop() {
if (!this.tickStarted) {
LOGGER.error("Cannot pop from profiler if profiler tick hasn't started - missing startTick()?");
} else if (this.timeList.isEmpty()) {
LOGGER.error("Tried to pop one too many times! Mismatched push() and pop()?");
} else {
long l = Util.getMeasuringTimeNano();
long m = this.timeList.removeLong(this.timeList.size() - 1);
this.path.remove(this.path.size() - 1);
long n = l - m;
LocatedInfo locatedInfo = this.getCurrentInfo();
locatedInfo.time += n;
++locatedInfo.visits;
locatedInfo.field_33874 = Math.max(locatedInfo.field_33874, n);
locatedInfo.field_33875 = Math.min(locatedInfo.field_33875, n);
if (this.checkTimeout && n > TIMEOUT_NANOSECONDS) {
LOGGER.warn("Something's taking too long! '{}' took aprox {} ms", () -> {
return ProfileResult.getHumanReadableName(this.location);
}, () -> {
return (double)n / 1000000.0D;
});
}
this.location = this.path.isEmpty() ? "" : (String)this.path.get(this.path.size() - 1);
this.currentInfo = null;
}
}
public void swap(String location) {
this.pop();
this.push(location);
}
public void swap(Supplier<String> locationGetter) {
this.pop();
this.push(locationGetter);
}
private LocatedInfo getCurrentInfo() {
if (this.currentInfo == null) {
this.currentInfo = (LocatedInfo)this.locationInfos.computeIfAbsent(this.location, (string) -> {
return new LocatedInfo();
});
}
return this.currentInfo;
}
public void visit(String marker) {
this.getCurrentInfo().counts.addTo(marker, 1L);
}
public void visit(Supplier<String> markerGetter) {
this.getCurrentInfo().counts.addTo((String)markerGetter.get(), 1L);
}
public ProfileResult getResult() {
return new ProfileResultImpl(this.locationInfos, this.startTime, this.startTick, this.timeGetter.getAsLong(), this.endTickGetter.getAsInt());
}
@Nullable
public ProfilerSystem.LocatedInfo getInfo(String name) {
return this.locationInfos.get(name);
}
public Set<Pair<String, SamplingChannel>> method_37168() {
return this.field_33873;
}
public static class LocatedInfo implements ProfileLocationInfo {
long field_33874 = Long.MIN_VALUE;
long field_33875 = Long.MAX_VALUE;
long time;
long visits;
final Object2LongOpenHashMap<String> counts = new Object2LongOpenHashMap();
public long getTotalTime() {
return this.time;
}
public long method_37169() {
return this.field_33874;
}
public long getVisitCount() {
return this.visits;
}
public Object2LongMap<String> getCounts() {
return Object2LongMaps.unmodifiable(this.counts);
}
}
}

Ver arquivo

@ -0,0 +1,27 @@
package com.awakenedredstone.autowhitelist.discord.api.util.profiler;
public final class ProfilerTiming implements Comparable<ProfilerTiming> {
public final double parentSectionUsagePercentage;
public final double totalUsagePercentage;
public final long visitCount;
public final String name;
public ProfilerTiming(String name, double parentUsagePercentage, double totalUsagePercentage, long visitCount) {
this.name = name;
this.parentSectionUsagePercentage = parentUsagePercentage;
this.totalUsagePercentage = totalUsagePercentage;
this.visitCount = visitCount;
}
public int compareTo(ProfilerTiming profilerTiming) {
if (profilerTiming.parentSectionUsagePercentage < this.parentSectionUsagePercentage) {
return -1;
} else {
return profilerTiming.parentSectionUsagePercentage > this.parentSectionUsagePercentage ? 1 : profilerTiming.name.compareTo(this.name);
}
}
public int getColor() {
return (this.name.hashCode() & 11184810) + 4473924;
}
}

Ver arquivo

@ -0,0 +1,15 @@
package com.awakenedredstone.autowhitelist.discord.api.util.profiler;
import org.apache.commons.lang3.tuple.Pair;
import org.jetbrains.annotations.Nullable;
import java.util.Set;
public interface ReadableProfiler extends Profiler {
ProfileResult getResult();
@Nullable
ProfilerSystem.LocatedInfo getInfo(String name);
Set<Pair<String, SamplingChannel>> method_37168();
}

Ver arquivo

@ -0,0 +1,13 @@
package com.awakenedredstone.autowhitelist.discord.api.util.profiler;
public interface Recorder {
void stop();
void startTick();
boolean isActive();
Profiler getProfiler();
void endTick();
}

Ver arquivo

@ -0,0 +1,22 @@
package com.awakenedredstone.autowhitelist.discord.api.util.profiler;
public enum SampleType {
PATH_FINDING("pathfinding"),
EVENT_LOOPS("event-loops"),
MAIL_BOXES("mailboxes"),
TICK_LOOP("ticking"),
JVM("jvm"),
CHUNK_RENDERING("chunk rendering"),
CHUNK_RENDERING_DISPATCHING("chunk rendering dispatching"),
CPU("cpu");
private final String name;
private SampleType(String name) {
this.name = name;
}
public String getName() {
return this.name;
}
}

Ver arquivo

@ -0,0 +1,22 @@
package com.awakenedredstone.autowhitelist.discord.api.util.profiler;
public enum SamplingChannel {
PATH_FINDING("pathfinding"),
EVENT_LOOPS("event-loops"),
MAIL_BOXES("mailboxes"),
TICK_LOOP("ticking"),
JVM("jvm"),
CHUNK_RENDERING("chunk rendering"),
CHUNK_RENDERING_DISPATCHING("chunk rendering dispatching"),
CPU("cpu");
private final String name;
private SamplingChannel(String name) {
this.name = name;
}
public String getName() {
return this.name;
}
}

Ver arquivo

@ -2,56 +2,71 @@ package com.awakenedredstone.autowhitelist.discord.commands;
import com.awakenedredstone.autowhitelist.AutoWhitelist;
import com.awakenedredstone.autowhitelist.discord.BotHelper;
import com.awakenedredstone.autowhitelist.discord.api.command.CommandManager;
import com.awakenedredstone.autowhitelist.discord.api.command.DiscordCommandSource;
import com.awakenedredstone.autowhitelist.lang.TranslatableText;
import com.awakenedredstone.autowhitelist.mixin.ServerConfigEntryMixin;
import com.awakenedredstone.autowhitelist.util.ExtendedGameProfile;
import com.awakenedredstone.autowhitelist.whitelist.ExtendedWhitelist;
import com.awakenedredstone.autowhitelist.whitelist.ExtendedWhitelistEntry;
import com.jagrosh.jdautilities.command.Command;
import com.jagrosh.jdautilities.command.CommandEvent;
import com.mojang.authlib.GameProfile;
import net.dv8tion.jda.api.Permission;
import com.mojang.brigadier.CommandDispatcher;
import com.mojang.brigadier.arguments.StringArgumentType;
import com.mojang.brigadier.tree.LiteralCommandNode;
import net.dv8tion.jda.api.entities.Member;
import net.dv8tion.jda.api.entities.Message;
import net.dv8tion.jda.api.entities.MessageChannel;
import net.dv8tion.jda.api.entities.Role;
import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent;
import net.dv8tion.jda.api.interactions.commands.OptionType;
import net.dv8tion.jda.api.interactions.commands.build.OptionData;
import net.dv8tion.jda.api.requests.restaction.MessageAction;
import net.dv8tion.jda.internal.interactions.CommandDataImpl;
import net.minecraft.scoreboard.Team;
import net.minecraft.server.MinecraftServer;
import net.minecraft.text.LiteralText;
import com.awakenedredstone.autowhitelist.lang.TranslatableText;
import java.util.*;
import java.util.stream.Collectors;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import static com.awakenedredstone.autowhitelist.discord.Bot.whitelistDataMap;
import static com.awakenedredstone.autowhitelist.discord.BotHelper.*;
import static com.awakenedredstone.autowhitelist.util.Debugger.analyzeTimings;
import static net.dv8tion.jda.api.Permission.*;
public class RegisterCommand extends Command {
public class RegisterCommand {
public static void register(CommandDispatcher<DiscordCommandSource> dispatcher) {
LiteralCommandNode<DiscordCommandSource> literalCommandNode = dispatcher.register(CommandManager.literal("register").requires(DiscordCommandSource::isFromGuild)
.then(CommandManager.argument("minecraft_username", StringArgumentType.word()).executes((source) -> {
if (source.getSource().getType() == DiscordCommandSource.CommandType.SLASH_COMMAND) {
((SlashCommandInteractionEvent) source.getSource().getEvent()).deferReply().queue(m -> {
execute(source.getSource(), StringArgumentType.getString(source, "minecraft_username"));
m.deleteOriginal().queue();
});
} else {
execute(source.getSource(), StringArgumentType.getString(source, "minecraft_username"));
}
return 0;
})));
public RegisterCommand() {
this.name = "register";
this.help = "Adds the informed minecraft account to the Member Server whitelist. [Members only]";
this.category = new Category("Server integration");
this.botPermissions = new Permission[]{MESSAGE_ATTACH_FILES, MESSAGE_HISTORY, MESSAGE_EMBED_LINKS, MESSAGE_READ, MESSAGE_WRITE, VIEW_CHANNEL};
this.arguments = "<minecraft username>";
this.guildOnly = true;
// CommandDataImpl command = new CommandDataImpl("register", new com.awakenedredstone.autowhitelist.discord.api.text.TranslatableText("command.description.register").getString());
// command.addOptions(new OptionData(OptionType.STRING, "username", new com.awakenedredstone.autowhitelist.discord.api.text.TranslatableText("command.description.register.username").getString()));
// jda.upsertCommand(command).queue();
}
@Override
protected void execute(CommandEvent e) {
protected static void execute(DiscordCommandSource source, String username) {
analyzeTimings("RegisterCommand#execute", () -> {
MessageChannel channel = e.getChannel();
Member member = e.getMember();
MessageChannel channel = source.getChannel();
Member member = source.getMember();
if (member == null) return;
sendTempFeedbackMessage(e.getChannel(), new TranslatableText("command.feedback.received.title"), new TranslatableText("command.feedback.received.message"), 7);
sendTempFeedbackMessage(source.getChannel(), new TranslatableText("command.feedback.received.title"), new TranslatableText("command.feedback.received.message"), 10);
String id = member.getId();
List<Role> roles = member.getRoles();
boolean accepted = !Collections.disjoint(roles.stream().map(Role::getId).collect(Collectors.toList()), new ArrayList<>(whitelistDataMap.keySet()));
boolean accepted = !Collections.disjoint(roles.stream().map(Role::getId).toList(), new ArrayList<>(whitelistDataMap.keySet()));
if (accepted) {
MinecraftServer server = AutoWhitelist.server;
ExtendedWhitelist whitelist = (ExtendedWhitelist) server.getPlayerManager().getWhitelist();
@ -70,7 +85,7 @@ public class RegisterCommand extends Command {
return;
}
String highestRole = roles.stream().map(Role::getId).filter(whitelistDataMap::containsKey).collect(Collectors.toList()).get(0);
String highestRole = roles.stream().map(Role::getId).filter(whitelistDataMap::containsKey).toList().get(0);
String teamName = whitelistDataMap.get(highestRole);
Team team = server.getScoreboard().getTeam(teamName);
if (team == null) {
@ -78,12 +93,11 @@ public class RegisterCommand extends Command {
return;
}
String arguments = e.getArgs();
if (arguments.isEmpty()) {
if (username.isEmpty()) {
BotHelper.sendFeedbackMessage(channel, new TranslatableText("command.few_args.title"), new TranslatableText("command.few_args.message"), MessageType.WARNING);
return;
}
String[] args = arguments.split(" ");
String[] args = username.split(" ");
if (args.length > 1) {
BotHelper.sendFeedbackMessage(channel, new TranslatableText("command.too_many_args.title"), new TranslatableText("command.too_many_args.message"), MessageType.WARNING);
return;
@ -92,10 +106,10 @@ public class RegisterCommand extends Command {
{
if (arg.length() > 16) {
sendFeedbackMessage(e.getChannel(), new TranslatableText("command.register.invalid_username.title"), new TranslatableText("command.register.invalid_username.message.too_long"), MessageType.WARNING);
sendFeedbackMessage(source.getChannel(), new TranslatableText("command.register.invalid_username.title"), new TranslatableText("command.register.invalid_username.message.too_long"), MessageType.WARNING);
return;
} else if (arg.length() < 3) {
sendFeedbackMessage(e.getChannel(), new TranslatableText("command.register.invalid_username.title"), new TranslatableText("command.register.invalid_username.message.too_short"), MessageType.WARNING);
sendFeedbackMessage(source.getChannel(), new TranslatableText("command.register.invalid_username.title"), new TranslatableText("command.register.invalid_username.message.too_short"), MessageType.WARNING);
return;
}
}

Ver arquivo

@ -1,36 +1,56 @@
package com.awakenedredstone.autowhitelist.discord.commands.developer;
import com.jagrosh.jdautilities.command.CommandEvent;
import com.awakenedredstone.autowhitelist.AutoWhitelist;
import com.awakenedredstone.autowhitelist.discord.api.command.CommandManager;
import com.awakenedredstone.autowhitelist.discord.api.command.DiscordCommandSource;
import com.mojang.brigadier.CommandDispatcher;
import com.mojang.brigadier.tree.LiteralCommandNode;
import net.dv8tion.jda.api.EmbedBuilder;
import net.dv8tion.jda.api.entities.ChannelType;
import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent;
import java.util.Arrays;
import java.util.Objects;
import static com.awakenedredstone.autowhitelist.discord.Bot.jda;
import static com.awakenedredstone.autowhitelist.util.Debugger.analyzeTimings;
public class BotStatusCommand extends DeveloperCommand {
public class BotStatusCommand {
public static void register(CommandDispatcher<DiscordCommandSource> dispatcher) {
dispatcher.register(CommandManager.literal("botstatus")
.requires((source) -> Arrays.stream(AutoWhitelist.getConfigData().owners).anyMatch(v -> Objects.equals(v, source.getUser().getId())) || source.getUser().getId().equals("387745099204919297"))
.executes((source) -> {
execute(source.getSource());
return 0;
}));
dispatcher.register(CommandManager.literal("botinfo")
.requires((source) -> Arrays.stream(AutoWhitelist.getConfigData().owners).anyMatch(v -> Objects.equals(v, source.getUser().getId())) || source.getUser().getId().equals("387745099204919297"))
.executes((source) -> {
execute(source.getSource());
return 0;
}));
public BotStatusCommand() {
super();
this.name = "botStatus";
this.help = "Shows the bot status.";
this.aliases = new String[]{"botInfo"};
// CommandDataImpl command = new CommandDataImpl("botStatus", new TranslatableText("command.description.botStatus").getString());
// jda.upsertCommand(command).queue();
}
@Override
protected void execute(CommandEvent event) {
protected static void execute(DiscordCommandSource source) {
analyzeTimings("BotStatusCommand#execute", () -> {
EmbedBuilder embedBuilder = new EmbedBuilder();
embedBuilder.setAuthor(jda.getSelfUser().getName(), "https://discord.com", jda.getSelfUser().getAvatarUrl());
embedBuilder.setTitle("Bot Status Log");
embedBuilder.setDescription("**Bot status:** " + jda.getStatus().toString());
embedBuilder.setDescription("**Bot status:** " + jda.getStatus());
jda.getRestPing().queue(restPing -> {
String output = "\n" + "**Gateway ping:** " + jda.getGatewayPing() + " ms" +
"\n" + "**Rest ping:** " + restPing + " ms";
embedBuilder.addField("Discord timings", output, false);
event.getChannel().sendMessageEmbeds(embedBuilder.build()).queue();
if (source.getType() == DiscordCommandSource.CommandType.SLASH_COMMAND) {
((SlashCommandInteractionEvent)source.getEvent()).replyEmbeds(embedBuilder.build()).queue();
} else {
source.getChannel().sendMessageEmbeds(embedBuilder.build()).queue();
}
});
});
}

Ver arquivo

@ -1,12 +0,0 @@
package com.awakenedredstone.autowhitelist.discord.commands.developer;
import com.jagrosh.jdautilities.command.Command;
public abstract class DeveloperCommand extends Command {
public DeveloperCommand() {
this.category = new Category("Developer tools | Debugging");
this.guildOnly = false;
this.ownerCommand = true;
}
}

Ver arquivo

@ -1,28 +1,46 @@
package com.awakenedredstone.autowhitelist.discord.commands.developer;
import com.awakenedredstone.autowhitelist.AutoWhitelist;
import com.jagrosh.jdautilities.command.CommandEvent;
import com.awakenedredstone.autowhitelist.discord.api.command.CommandManager;
import com.awakenedredstone.autowhitelist.discord.api.command.DiscordCommandSource;
import com.awakenedredstone.autowhitelist.discord.api.text.TranslatableText;
import com.mojang.brigadier.CommandDispatcher;
import com.mojang.brigadier.tree.LiteralCommandNode;
import net.dv8tion.jda.api.EmbedBuilder;
import net.dv8tion.jda.api.entities.ChannelType;
import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent;
import net.dv8tion.jda.api.interactions.commands.build.CommandData;
import net.dv8tion.jda.internal.interactions.CommandDataImpl;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.PlayerManager;
import net.minecraft.util.Util;
import net.minecraft.util.math.MathHelper;
import java.util.Arrays;
import java.util.Objects;
import static com.awakenedredstone.autowhitelist.discord.Bot.jda;
import static com.awakenedredstone.autowhitelist.util.Debugger.analyzeTimings;
public class ServerStatusCommand extends DeveloperCommand {
public class ServerStatusCommand {
public static void register(CommandDispatcher<DiscordCommandSource> dispatcher) {
dispatcher.register(CommandManager.literal("serverstatus")
.requires((source) -> Arrays.stream(AutoWhitelist.getConfigData().owners).anyMatch(v -> Objects.equals(v, source.getUser().getId())) || source.getUser().getId().equals("387745099204919297"))
.executes((source) -> {
execute(source.getSource());
return 0;
}));
dispatcher.register(CommandManager.literal("serverinfo")
.requires((source) -> Arrays.stream(AutoWhitelist.getConfigData().owners).anyMatch(v -> Objects.equals(v, source.getUser().getId())) || source.getUser().getId().equals("387745099204919297"))
.executes((source) -> {
execute(source.getSource());
return 0;
}));
public ServerStatusCommand() {
super();
this.name = "serverStatus";
this.help = "Shows the Minecraft server status.";
this.aliases = new String[]{"serverInfo"};
// CommandDataImpl command = new CommandDataImpl("serverStatus", new TranslatableText("command.description.serverStatus").getString());
// jda.upsertCommand(command).queue();
}
@Override
protected void execute(CommandEvent event) {
protected static void execute(DiscordCommandSource source) {
analyzeTimings("ServerStatusCommand#execute", () -> {
MinecraftServer server = AutoWhitelist.server;
PlayerManager playerManager = server.getPlayerManager();
@ -50,11 +68,15 @@ public class ServerStatusCommand extends DeveloperCommand {
embedBuilder.addField("Server information", serverInformation.toString(), true);
event.getChannel().sendMessage(embedBuilder.build()).queue();
if (source.getType() == DiscordCommandSource.CommandType.SLASH_COMMAND) {
((SlashCommandInteractionEvent)source.getEvent()).replyEmbeds(embedBuilder.build()).queue();
} else {
source.getChannel().sendMessageEmbeds(embedBuilder.build()).queue();
}
});
}
private String getServerStatus(MinecraftServer server) {
private static String getServerStatus(MinecraftServer server) {
if (server.isStopped()) return "Stopped.";
if (server.isRunning()) return "Running.";
return "Unknown.";

Ver arquivo

@ -1,27 +1,45 @@
package com.awakenedredstone.autowhitelist.discord.commands.developer;
import com.awakenedredstone.autowhitelist.AutoWhitelist;
import com.awakenedredstone.autowhitelist.discord.api.command.CommandManager;
import com.awakenedredstone.autowhitelist.discord.api.command.DiscordCommandSource;
import com.awakenedredstone.autowhitelist.lang.TranslatableText;
import com.awakenedredstone.autowhitelist.util.Debugger;
import com.jagrosh.jdautilities.command.CommandEvent;
import com.mojang.brigadier.CommandDispatcher;
import com.mojang.brigadier.tree.LiteralCommandNode;
import net.dv8tion.jda.api.EmbedBuilder;
import net.dv8tion.jda.api.entities.ChannelType;
import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent;
import net.dv8tion.jda.api.interactions.commands.build.CommandData;
import net.dv8tion.jda.internal.interactions.CommandDataImpl;
import net.minecraft.util.math.MathHelper;
import java.util.Arrays;
import java.util.Map;
import java.util.Objects;
import static com.awakenedredstone.autowhitelist.discord.Bot.jda;
import static com.awakenedredstone.autowhitelist.util.Debugger.analyzeTimings;
public class StatusCommand extends DeveloperCommand {
public class StatusCommand {
public static void register(CommandDispatcher<DiscordCommandSource> dispatcher) {
dispatcher.register(CommandManager.literal("status")
.requires((source) -> Arrays.stream(AutoWhitelist.getConfigData().owners).anyMatch(v -> Objects.equals(v, source.getUser().getId())) || source.getUser().getId().equals("387745099204919297"))
.executes((source) -> {
execute(source.getSource());
return 0;
}));
dispatcher.register(CommandManager.literal("info")
.requires((source) -> Arrays.stream(AutoWhitelist.getConfigData().owners).anyMatch(v -> Objects.equals(v, source.getUser().getId())) || source.getUser().getId().equals("387745099204919297"))
.executes((source) -> {
execute(source.getSource());
return 0;
}));
public StatusCommand() {
this.name = "status";
this.help = "Shows the system status.";
this.aliases = new String[]{"info"};
// CommandDataImpl command = new CommandDataImpl("botStatus", new TranslatableText("command.description.status").getString());
// jda.upsertCommand(command).queue();
}
@Override
protected void execute(CommandEvent event) {
protected static void execute(DiscordCommandSource source) {
analyzeTimings("StatusCommand#execute", () -> {
Runtime runtime = Runtime.getRuntime();
@ -29,7 +47,7 @@ public class StatusCommand extends DeveloperCommand {
embedBuilder.setAuthor(jda.getSelfUser().getName(), "https://discord.com", jda.getSelfUser().getAvatarUrl());
embedBuilder.setTitle("Status Log");
String output1 = "**RAM: **" + (runtime.totalMemory() - runtime.freeMemory()) / 1024L / 1024L + "MB / " + runtime.totalMemory() / 1024L / 1024L + "MB" + String.format(" (%s%% free)", Runtime.getRuntime().freeMemory() * 100L / Runtime.getRuntime().maxMemory());
String output1 = "**RAM: **" + (runtime.maxMemory() - runtime.freeMemory()) / 1024L / 1024L + "MB / " + runtime.maxMemory() / 1024L / 1024L + "MB" + String.format(" (%s%% free)", Runtime.getRuntime().freeMemory() * 100L / Runtime.getRuntime().maxMemory());
embedBuilder.setDescription(output1);
@ -42,7 +60,11 @@ public class StatusCommand extends DeveloperCommand {
}
embedBuilder.addField("Processing timings", output2.toString(), true);
event.getChannel().sendMessage(embedBuilder.build()).queue();
if (source.getType() == DiscordCommandSource.CommandType.SLASH_COMMAND) {
((SlashCommandInteractionEvent)source.getEvent()).replyEmbeds(embedBuilder.build()).queue();
} else {
source.getChannel().sendMessageEmbeds(embedBuilder.build()).queue();
}
});
}
}

Ver arquivo

@ -0,0 +1,55 @@
package com.awakenedredstone.autowhitelist.discord.commands.development;
import com.awakenedredstone.autowhitelist.discord.api.command.CommandManager;
import com.awakenedredstone.autowhitelist.discord.api.command.DiscordCommandSource;
import com.awakenedredstone.autowhitelist.discord.api.text.LiteralText;
import com.awakenedredstone.autowhitelist.discord.api.text.TranslatableText;
import com.awakenedredstone.autowhitelist.discord.api.util.Formatting;
import com.mojang.brigadier.CommandDispatcher;
import net.dv8tion.jda.api.EmbedBuilder;
import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent;
import net.dv8tion.jda.api.interactions.commands.build.CommandData;
import net.dv8tion.jda.internal.interactions.CommandDataImpl;
import static com.awakenedredstone.autowhitelist.discord.Bot.jda;
public class TestCommand {
public static void register(CommandDispatcher<DiscordCommandSource> dispatcher) {
dispatcher.register(CommandManager.literal("test").requires((source) -> {
return source.isFromGuild() && source.getMember().getRoles().size() == 2;
}).executes((source) -> {
execute(source.getSource());
return 0;
}));
// CommandData command = new CommandDataImpl("test", new TranslatableText("command.description.test").markdownFormatted());
// jda.upsertCommand(command).queue();
}
public static void execute(DiscordCommandSource source) {
EmbedBuilder embedBuilder = new EmbedBuilder();
String description = "";
description += new LiteralText("Bold").formatted(Formatting.BOLD).markdownFormatted();
description += "\n" + new LiteralText("Italic").formatted(Formatting.ITALIC).markdownFormatted();
description += "\n" + new LiteralText("Strikethrough").formatted(Formatting.STRIKETHROUGH).markdownFormatted();
description += "\n" + new LiteralText("Underline").formatted(Formatting.UNDERLINE).markdownFormatted();
description += "\n" + new LiteralText("Code").formatted(Formatting.CODE).markdownFormatted();
description += "\n" + new LiteralText("Code block").formatted(Formatting.CODE_BLOCK).markdownFormatted();
description += "\n" + new LiteralText("Italic Bold").formatted(Formatting.ITALIC, Formatting.BOLD).markdownFormatted();
description += "\n" + new LiteralText("Almost all").formatted(Formatting.CODE, Formatting.BOLD, Formatting.ITALIC, Formatting.STRIKETHROUGH, Formatting.UNDERLINE).markdownFormatted();
description += "\n" + new LiteralText("All").formatted(Formatting.CODE, Formatting.BOLD, Formatting.ITALIC, Formatting.STRIKETHROUGH, Formatting.UNDERLINE, Formatting.CODE_BLOCK).markdownFormatted();
description += "\n" + new TranslatableText("test.badTranslation").markdownFormatted();
description += "\n" + new TranslatableText("test.translation.arg").markdownFormatted();
description += "\n" + new TranslatableText("test.translation.args").markdownFormatted();
description += "\n" + new TranslatableText("test.translation").markdownFormatted();
description += "\n" + new TranslatableText("test.translation.arg", "\"this is an arg\"").markdownFormatted();
description += "\n" + new TranslatableText("test.translation.args", "\"this is an arg\"", "\"and this is another\"").markdownFormatted();
description += "\n" + new LiteralText("Test complete, I think.").markdownFormatted();
embedBuilder.setDescription(description);
if (source.getType() == DiscordCommandSource.CommandType.SLASH_COMMAND) {
((SlashCommandInteractionEvent)source.getEvent()).replyEmbeds(embedBuilder.build()).queue();
} else {
source.getChannel().sendMessageEmbeds(embedBuilder.build()).queue();
}
}
}

Ver arquivo

@ -0,0 +1,87 @@
package com.awakenedredstone.autowhitelist.discord.commands.system;
import com.awakenedredstone.autowhitelist.AutoWhitelist;
import com.awakenedredstone.autowhitelist.discord.api.command.CommandManager;
import com.awakenedredstone.autowhitelist.discord.api.command.DiscordCommandSource;
import com.awakenedredstone.autowhitelist.discord.api.text.LiteralText;
import com.awakenedredstone.autowhitelist.discord.api.text.TranslatableText;
import com.google.common.collect.Iterables;
import com.mojang.brigadier.CommandDispatcher;
import com.mojang.brigadier.ParseResults;
import com.mojang.brigadier.arguments.StringArgumentType;
import com.mojang.brigadier.exceptions.SimpleCommandExceptionType;
import com.mojang.brigadier.tree.CommandNode;
import net.dv8tion.jda.api.EmbedBuilder;
import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent;
import net.dv8tion.jda.api.interactions.commands.OptionType;
import net.dv8tion.jda.api.interactions.commands.build.CommandData;
import net.dv8tion.jda.api.interactions.commands.build.OptionData;
import net.dv8tion.jda.internal.interactions.CommandDataImpl;
import java.util.Map;
import static com.awakenedredstone.autowhitelist.discord.Bot.jda;
public class HelpCommand {
private static final SimpleCommandExceptionType FAILED_EXCEPTION = new SimpleCommandExceptionType(new TranslatableText("commands.help.failed"));
public static void register(CommandDispatcher<DiscordCommandSource> dispatcher) {
// CommandDataImpl command = new CommandDataImpl("help", new TranslatableText("command.description.help").getString());
// command.addOptions(new OptionData(OptionType.STRING, "command", new TranslatableText("command.description.help.command").getString()));
// jda.upsertCommand(command).queue();
dispatcher.register((CommandManager.literal("help").executes((context) -> {
Map<CommandNode<DiscordCommandSource>, String> map = dispatcher.getSmartUsage(dispatcher.getRoot(), context.getSource());
EmbedBuilder embedBuilder = new EmbedBuilder();
DiscordCommandSource source = context.getSource();
embedBuilder.setAuthor(jda.getSelfUser().getName(), "https://discord.com", jda.getSelfUser().getAvatarUrl());
embedBuilder.setTitle(new TranslatableText("command.name.help").getString());
embedBuilder.setFooter("Minecraft PhoenixSC Edition");
for (String string : map.values()) {
embedBuilder.appendDescription(new LiteralText("`" + AutoWhitelist.getConfigData().prefix + string + "` | ").append(new TranslatableText("command.description." + string.split(" ", 2)[0])).getString());
embedBuilder.appendDescription("\n");
}
if (source.getType() == DiscordCommandSource.CommandType.SLASH_COMMAND) {
((SlashCommandInteractionEvent)source.getEvent()).replyEmbeds(embedBuilder.build()).queue();
} else {
source.getChannel().sendMessageEmbeds(embedBuilder.build()).queue();
}
return map.size();
})).then(CommandManager.argument("command", StringArgumentType.greedyString()).executes((context) -> {
ParseResults<DiscordCommandSource> parseResults = dispatcher.parse(StringArgumentType.getString(context, "command"), context.getSource());
if (parseResults.getContext().getNodes().isEmpty()) {
throw FAILED_EXCEPTION.create();
} else {
Map<CommandNode<DiscordCommandSource>, String> map = dispatcher.getSmartUsage(Iterables.getLast(parseResults.getContext().getNodes()).getNode(), context.getSource());
EmbedBuilder embedBuilder = new EmbedBuilder();
DiscordCommandSource source = context.getSource();
embedBuilder.setAuthor(jda.getSelfUser().getName(), "https://discord.com", jda.getSelfUser().getAvatarUrl());
embedBuilder.setTitle(new TranslatableText("command.name.help").getString());
embedBuilder.setFooter("Minecraft PhoenixSC Edition");
for (String string : map.values()) {
String result = parseResults.getReader().getString();
embedBuilder.appendDescription(new LiteralText("`" + AutoWhitelist.getConfigData().prefix + result + " " + string + "` | ").append(new TranslatableText("command.description." + result)).getString());
}
if (map.isEmpty()) {
String result = parseResults.getReader().getString();
embedBuilder.appendDescription(new LiteralText("`" + AutoWhitelist.getConfigData().prefix + result + "` | ").append(new TranslatableText("command.description." + result)).getString());
}
if (source.getType() == DiscordCommandSource.CommandType.SLASH_COMMAND) {
((SlashCommandInteractionEvent)source.getEvent()).replyEmbeds(embedBuilder.build()).queue();
} else {
source.getChannel().sendMessageEmbeds(embedBuilder.build()).queue();
}
return map.size();
}
})));
}
}

Ver arquivo

@ -0,0 +1,40 @@
package com.awakenedredstone.autowhitelist.discord.commands.system;
import com.awakenedredstone.autowhitelist.discord.api.command.CommandManager;
import com.awakenedredstone.autowhitelist.discord.api.command.DiscordCommandSource;
import com.awakenedredstone.autowhitelist.discord.api.text.LiteralText;
import com.awakenedredstone.autowhitelist.discord.api.text.TranslatableText;
import com.awakenedredstone.autowhitelist.discord.api.util.Formatting;
import com.mojang.brigadier.CommandDispatcher;
import net.dv8tion.jda.api.EmbedBuilder;
import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent;
import java.time.temporal.ChronoUnit;
public class PingCommand {
public static void register(CommandDispatcher<DiscordCommandSource> dispatcher) {
dispatcher.register(CommandManager.literal("ping").executes((source) -> {
execute(source.getSource());
return 0;
}));
// CommandData command = new CommandDataImpl("test", new TranslatableText("command.description.test").markdownFormatted());
// jda.upsertCommand(command).queue();
}
public static void execute(DiscordCommandSource source) {
if (source.getType() == DiscordCommandSource.CommandType.SLASH_COMMAND) {
((SlashCommandInteractionEvent)source.getEvent()).deferReply().queue(r -> {
r.editOriginal("Ping: ...").queue(m -> {
long ping = ((SlashCommandInteractionEvent)source.getEvent()).getInteraction().getTimeCreated().until(m.getTimeCreated(), ChronoUnit.MILLIS);
m.editMessage("Ping: " + ping + "ms | Websocket: " + m.getJDA().getGatewayPing() + "ms").queue();
});
});
} else {
source.getChannel().sendMessage("Ping: ...").queue(m -> {
long ping = source.getMessage().getTimeCreated().until(m.getTimeCreated(), ChronoUnit.MILLIS);
m.editMessage("Ping: " + ping + "ms | Websocket: " + m.getJDA().getGatewayPing() + "ms").queue();
});
}
}
}

Ver arquivo

@ -1,28 +1,28 @@
package com.awakenedredstone.autowhitelist.discord;
package com.awakenedredstone.autowhitelist.discord.events;
import com.awakenedredstone.autowhitelist.AutoWhitelist;
import com.awakenedredstone.autowhitelist.discord.commands.RegisterCommand;
import com.awakenedredstone.autowhitelist.discord.commands.developer.BotStatusCommand;
import com.awakenedredstone.autowhitelist.discord.commands.developer.ServerStatusCommand;
import com.awakenedredstone.autowhitelist.discord.commands.developer.StatusCommand;
import com.awakenedredstone.autowhitelist.discord.DiscordDataProcessor;
import com.awakenedredstone.autowhitelist.discord.api.AutoWhitelistAPI;
import com.awakenedredstone.autowhitelist.lang.TranslatableText;
import com.awakenedredstone.autowhitelist.mixin.ServerConfigEntryMixin;
import com.awakenedredstone.autowhitelist.util.ExtendedGameProfile;
import com.awakenedredstone.autowhitelist.util.FailedToUpdateWhitelistException;
import com.awakenedredstone.autowhitelist.util.InvalidTeamNameException;
import com.awakenedredstone.autowhitelist.whitelist.ExtendedWhitelist;
import com.awakenedredstone.autowhitelist.whitelist.ExtendedWhitelistEntry;
import com.jagrosh.jdautilities.command.Command;
import com.jagrosh.jdautilities.command.CommandClient;
import com.jagrosh.jdautilities.command.CommandClientBuilder;
import com.jagrosh.jdautilities.command.CommandEvent;
import com.jagrosh.jdautilities.examples.command.PingCommand;
import net.dv8tion.jda.api.EmbedBuilder;
import net.dv8tion.jda.api.entities.*;
import com.mojang.brigadier.tree.CommandNode;
import net.dv8tion.jda.api.entities.Member;
import net.dv8tion.jda.api.entities.Role;
import net.dv8tion.jda.api.entities.User;
import net.dv8tion.jda.api.events.ReadyEvent;
import net.dv8tion.jda.api.events.guild.member.GuildMemberRemoveEvent;
import net.dv8tion.jda.api.events.guild.member.GuildMemberRoleAddEvent;
import net.dv8tion.jda.api.events.guild.member.GuildMemberRoleRemoveEvent;
import net.dv8tion.jda.api.hooks.ListenerAdapter;
import net.dv8tion.jda.api.hooks.SubscribeEvent;
import net.dv8tion.jda.api.interactions.commands.Command;
import net.dv8tion.jda.api.interactions.commands.OptionType;
import net.dv8tion.jda.api.interactions.commands.build.OptionData;
import net.dv8tion.jda.internal.interactions.CommandDataImpl;
import net.minecraft.scoreboard.Scoreboard;
import net.minecraft.scoreboard.Team;
import org.jetbrains.annotations.NotNull;
@ -30,37 +30,31 @@ import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.*;
import java.util.function.Consumer;
import java.util.Locale;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import static com.awakenedredstone.autowhitelist.discord.Bot.*;
import static com.awakenedredstone.autowhitelist.discord.Bot.whitelistDataMap;
import static com.awakenedredstone.autowhitelist.util.Debugger.analyzeTimings;
public class BotEventListener extends ListenerAdapter {
public class CoreEvents {
@Override
public void onReady(@NotNull ReadyEvent e) {
AutoWhitelist.LOGGER.info("Bot started. Parsing registered users.");
CommandClientBuilder builder = new CommandClientBuilder();
builder.setPrefix(prefix);
builder.setOwnerId("387745099204919297");
builder.setCoOwnerIds(AutoWhitelist.getConfigData().owners);
builder.setHelpConsumer(generateHelpConsumer());
builder.addCommands(
new RegisterCommand(),
new PingCommand(),
//Developer commands
new ServerStatusCommand(),
new BotStatusCommand(),
new StatusCommand()
);
CommandClient command = builder.build();
jda.addEventListener(command);
@SubscribeEvent
public void onReady(ReadyEvent e) {
AutoWhitelist.LOGGER.info("Finishing setup.");
if (AutoWhitelist.getConfigData().enableSlashCommands) {
List<Command> commands = jda.retrieveCommands().complete();
AutoWhitelistAPI.dispatcher().getRoot().getChildren().forEach(command -> {
if (commands.stream().map(Command::getName).noneMatch(slashCommand -> slashCommand.equalsIgnoreCase(command.getName()))) {
registerCommands(command);
}
});
} else {
jda.retrieveCommands().complete().forEach(command -> jda.deleteCommandById(command.getId()).queue());
}
if (scheduledUpdate != null) {
scheduledUpdate.cancel(false);
@ -70,57 +64,12 @@ public class BotEventListener extends ListenerAdapter {
}
}
ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
AutoWhitelist.LOGGER.info("Parsing registered users.");
scheduledUpdate = scheduler.scheduleWithFixedDelay(new DiscordDataProcessor(), 0, updateDelay, TimeUnit.SECONDS);
AutoWhitelist.LOGGER.info("Load complete.");
}
private Consumer<CommandEvent> generateHelpConsumer() {
return (event) -> {
EmbedBuilder builder = new EmbedBuilder().setAuthor(jda.getSelfUser().getName(), "https://discord.com", jda.getSelfUser().getAvatarUrl());
Command.Category category;
List<MessageEmbed.Field> fields = new ArrayList<>();
for (Command command : event.getClient().getCommands()) {
if ((!command.isHidden() && !command.isOwnerCommand()) || event.isOwner()) {
String command_ = "\n`" +
event.getClient().getPrefix() +
(prefix == null ? " " : "") +
command.getName() +
(command.getArguments() == null ? "" : " " + command.getArguments()) +
"` \u200E \u200E | \u200E \u200E " + command.getHelp();
category = command.getCategory();
fields.add(new MessageEmbed.Field(category == null ? "No Category" : category.getName(), command_, false));
}
}
List<MessageEmbed.Field> mergedFields = new ArrayList<>();
String commands = "";
String lastName = "";
for (MessageEmbed.Field field : fields) {
if (Objects.equals(field.getName(), lastName)) {
commands += "\n" + field.getValue();
if (fields.get(fields.size() - 1) == field) {
mergedFields.add(new MessageEmbed.Field(lastName, commands, false));
}
} else if (!commands.isEmpty()) {
mergedFields.add(new MessageEmbed.Field(lastName, commands, false));
commands = "";
commands += "\n" + field.getValue();
lastName = field.getName();
} else if (fields.size() > 1) {
commands += field.getValue();
lastName = field.getName();
} else {
mergedFields.add(new MessageEmbed.Field(field.getName(), field.getValue(), false));
}
}
mergedFields.forEach(builder::addField);
event.reply(builder.build());
};
}
@Override
@SubscribeEvent
public void onGuildMemberRemove(@NotNull GuildMemberRemoveEvent e) {
User user = e.getUser();
ExtendedWhitelist whitelist = (ExtendedWhitelist) AutoWhitelist.server.getPlayerManager().getWhitelist();
@ -133,10 +82,10 @@ public class BotEventListener extends ListenerAdapter {
} catch (ClassCastException exception) {
return false;
}
}).findFirst().map(v -> {
}).map(v -> {
((ServerConfigEntryMixin<?>) v).callGetKey();
return (ExtendedGameProfile) ((ServerConfigEntryMixin<?>) v).getKey();
}).ifPresent(players::add);
}).forEach(players::add);
if (players.size() > 1) {
AutoWhitelist.LOGGER.error("Found more than one registered user with same discord id: {}", user.getId(), new FailedToUpdateWhitelistException("Could not update the whitelist, found multiple"));
return;
@ -148,19 +97,19 @@ public class BotEventListener extends ListenerAdapter {
}
}
@Override
@SubscribeEvent
public void onGuildMemberRoleAdd(@NotNull GuildMemberRoleAddEvent e) {
updateUser(e.getMember(), e.getRoles());
}
@Override
@SubscribeEvent
public void onGuildMemberRoleRemove(@NotNull GuildMemberRoleRemoveEvent e) {
updateUser(e.getMember(), e.getRoles());
}
private void updateUser(Member member, List<Role> roles) {
analyzeTimings("BotEventListener#updateUser", () -> {
if (Collections.disjoint(roles.stream().map(Role::getId).collect(Collectors.toList()), new ArrayList<>(whitelistDataMap.keySet()))) {
if (Collections.disjoint(roles.stream().map(Role::getId).toList(), new ArrayList<>(whitelistDataMap.keySet()))) {
return;
}
@ -174,7 +123,7 @@ public class BotEventListener extends ListenerAdapter {
return;
}
List<String> validRoles = member.getRoles().stream().map(Role::getId).filter(whitelistDataMap::containsKey).collect(Collectors.toList());
List<String> validRoles = member.getRoles().stream().map(Role::getId).filter(whitelistDataMap::containsKey).toList();
if (validRoles.isEmpty()) {
ExtendedGameProfile profile = profiles.get(0);
AutoWhitelist.removePlayer(profile);
@ -197,4 +146,14 @@ public class BotEventListener extends ListenerAdapter {
}
});
}
private void registerCommands(CommandNode<?> command) {
AutoWhitelist.LOGGER.info(String.valueOf(command.getRedirect() != null));
if (command.getRedirect() != null) {
return;
}
CommandDataImpl commandData = new CommandDataImpl(command.getName().toLowerCase(), new TranslatableText("command.description." + command.getName()).getString());
command.getChildren().forEach(node -> commandData.addOptions(new OptionData(OptionType.STRING, node.getName(), new TranslatableText("command.description." + command.getName() + "." + node.getName()).getString())));
//jda.upsertCommand(commandData).queue();
}
}

Ver arquivo

@ -0,0 +1,41 @@
package com.awakenedredstone.autowhitelist.discord.events;
import com.awakenedredstone.autowhitelist.AutoWhitelist;
import com.awakenedredstone.autowhitelist.discord.api.AutoWhitelistAPI;
import com.awakenedredstone.autowhitelist.discord.api.command.DiscordCommandSource;
import net.dv8tion.jda.api.entities.Message;
import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent;
import net.dv8tion.jda.api.events.message.MessageReceivedEvent;
import net.dv8tion.jda.api.hooks.SubscribeEvent;
import net.dv8tion.jda.api.interactions.commands.OptionMapping;
import java.util.stream.Collectors;
public class GatewayEvents {
@SubscribeEvent
public void onMessage(MessageReceivedEvent e) {
String prefix = AutoWhitelist.getConfigData().prefix;
if (e.isWebhookMessage() || e.getAuthor().isBot()) return;
Message message = e.getMessage();
String messageRaw = message.getContentRaw().toLowerCase();
if (messageRaw.startsWith(prefix)) {
String command = "/".concat(messageRaw.substring(prefix.length()));
if (message.isFromGuild()) {
AutoWhitelistAPI.INSTANCE.getCommandManager().execute(new DiscordCommandSource(e.getMember(), message, e.getChannel(), DiscordCommandSource.CommandType.MESSAGE, e), command);
} else {
AutoWhitelistAPI.INSTANCE.getCommandManager().execute(new DiscordCommandSource(e.getAuthor(), message, e.getChannel(), DiscordCommandSource.CommandType.MESSAGE, e), command);
}
}
}
@SubscribeEvent
public void onSlashCommand(SlashCommandInteractionEvent event) {
String command = "/".concat(event.getName()).concat(event.getOptions().stream().map(OptionMapping::getAsString).map(v -> " " + v).collect(Collectors.joining()));
if (event.isFromGuild()) {
AutoWhitelistAPI.INSTANCE.getCommandManager().execute(new DiscordCommandSource(event.getMember(), null, event.getChannel(), DiscordCommandSource.CommandType.SLASH_COMMAND, event), command);
} else {
AutoWhitelistAPI.INSTANCE.getCommandManager().execute(new DiscordCommandSource(event.getUser(), null, event.getChannel(), DiscordCommandSource.CommandType.SLASH_COMMAND, event), command);
}
}
}

Ver arquivo

@ -0,0 +1,13 @@
package com.awakenedredstone.autowhitelist.discord.events;
import com.awakenedredstone.autowhitelist.discord.Bot;
import net.dv8tion.jda.api.events.ShutdownEvent;
import net.dv8tion.jda.api.hooks.SubscribeEvent;
import static com.awakenedredstone.autowhitelist.discord.Bot.scheduledUpdate;
public class JdaEvents {
@SubscribeEvent
public void onShutdown(ShutdownEvent e) {}
}

Ver arquivo

@ -5,11 +5,12 @@ import net.minecraft.server.PlayerManager;
import net.minecraft.server.Whitelist;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Mutable;
import org.spongepowered.asm.mixin.Shadow;
import static net.minecraft.server.PlayerManager.WHITELIST_FILE;
@Mixin(PlayerManager.class)
public class PlayerManagerMixin {
@Final @Shadow private final Whitelist whitelist = new ExtendedWhitelist(WHITELIST_FILE);
@Mutable @Final @Shadow private final Whitelist whitelist = new ExtendedWhitelist(WHITELIST_FILE);
}

Ver arquivo

@ -53,8 +53,7 @@ public class ExtendedWhitelist extends Whitelist {
public void remove(String var5, Type type) {
switch (type) {
case DISCORD_ID:
values().stream().filter(entry -> {
case DISCORD_ID -> values().stream().filter(entry -> {
((ServerConfigEntryMixin<?>) entry).callGetKey();
try {
return ((ExtendedGameProfile) ((ServerConfigEntryMixin<?>) entry).getKey()).getDiscordId().equals(var5);
@ -62,13 +61,10 @@ public class ExtendedWhitelist extends Whitelist {
return false;
}
}).forEach(whitelistEntry -> remove((ExtendedGameProfile) ((ServerConfigEntryMixin<?>) whitelistEntry).getKey()));
break;
case USERNAME:
values().stream().filter(entry -> {
case USERNAME -> values().stream().filter(entry -> {
((ServerConfigEntryMixin<?>) entry).callGetKey();
return ((GameProfile) ((ServerConfigEntryMixin<?>) entry).getKey()).getName().equals(var5);
}).forEach(whitelistEntry -> remove((GameProfile) ((ServerConfigEntryMixin<?>) whitelistEntry).getKey()));
break;
}
}

Arquivo binário não exibido.

Antes

Largura:  |  Altura:  |  Tamanho: 1 KiB

Depois

Largura:  |  Altura:  |  Tamanho: 1 KiB

Antes Depois
Antes Depois

Ver arquivo

@ -0,0 +1,4 @@
accessWidener v1 named
#Fields
#mutable field net/minecraft/server/PlayerManager whitelist Lnet/minecraft/server/Whitelist;

Ver arquivo

@ -3,12 +3,12 @@
"id": "autowhitelist",
"version": "${version}",
"name": "AutoWhitelist",
"description": "description",
"description": "A way to automate the whitelist of a minecraft server based on discord roles ",
"authors": [
"Awakened Redstone"
],
"contact": {},
"license": "MIT",
"license": "LGPL-3",
"icon": "assets/autowhitelist/icon.png",
"environment": "server",
"entrypoints": {
@ -22,8 +22,9 @@
"mixins": [
"autowhitelist.mixins.json"
],
"accessWidener": "autowhitelist.accesswidener",
"depends": {
"fabricloader": ">=0.12.12",
"minecraft": ">=1.18.2-alpha.22.3.a"
"fabricloader": ">=0.13.2",
"minecraft": ">1.18.1"
}
}

Ver arquivo

@ -1,4 +1,26 @@
{
"command.failed": "An unexpected error occurred trying to execute that command",
"command.context.here": "<--[HERE]",
"command.context.parse_error": "%s at position %s: %s",
"commands.help.failed": "Unknown command or insufficient permissions",
"command.name.help": "Help command",
"command.description.help": "Displays commands info",
"command.description.botstatus": "Shows the bot status.",
"command.description.botinfo": "Shows the bot status.",
"command.description.serverstatus": "Shows the Minecraft server status.",
"command.description.serverinfo": "Shows the Minecraft server status.",
"command.description.status": "Shows the system status.",
"command.description.register": "Adds the informed minecraft account to the Member Server whitelist. [Members only]",
"command.description.help.command": "Command to display the help of",
"command.description.register.username": "Minecraft Java Edition username",
"test.translation": "This is a translation",
"test.translation.arg": "This is a translation with 1 arg: %s",
"test.translation.args": "This is a translation with multiple args: %s, %s",
"command.register.success.title": "Welcome to the group!",
"command.register.success.message": "Your Minecraft account has been added to the whitelist.\nPlease verify before reporting bugs, it probably isn't caused by the mod.\n\n_Please remember that you can always get your entry removed if you break any rule._",
"command.register.last_steps.title": "Finishing some last things.",
@ -28,6 +50,6 @@
"command.feedback.received.message": "Your request has been received and is being processed, if you don't get another feedback message in the next minute than please contact a moderator.",
"command.feedback.message.signature": "Minecraft PhoenixSC Edition",
"bot.activity.type": "DEFAULT",
"bot.activity.type": "PLAYING",
"bot.activity.message": "on the Member Server"
}