Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reimplemented commands using Cloud and initial Sponge support #110

Merged
merged 4 commits into from
Nov 4, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 20 additions & 12 deletions core/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
plugins {
alias(libs.plugins.idea.ext)
alias(libs.plugins.blossom)
`maven-publish`
signing
Expand All @@ -21,6 +22,7 @@ dependencies {

compileOnly(libs.annotations)
compileOnly(libs.fuzzywuzzy)
compileOnly(libs.cloud.core)
}

tasks {
Expand All @@ -41,18 +43,24 @@ java {
withJavadocJar()
}

blossom {
replaceTokenIn("src/main/java/me/xneox/epicguard/core/util/VersionUtils.java")
replaceToken("{version}", project.version)
replaceToken("{hikari}", libs.versions.hikaricp.get())
replaceToken("{configurate}", libs.versions.configurate.get())
replaceToken("{caffeine}", libs.versions.caffeine.get())
replaceToken("{common-compress}", libs.versions.commons.compress.get())
replaceToken("{common-text}", libs.versions.commons.text.get())
replaceToken("{geoip}", libs.versions.geoip.get())
replaceToken("{jackson}", libs.versions.jackson.get())
replaceToken("{maxmind-db}", libs.versions.maxmind.db.get())
replaceToken("{fuzzywuzzy}", libs.versions.fuzzywuzzy.get())
sourceSets {
main {
blossom {
javaSources {
property("version", project.version.toString())
property("hikari", libs.versions.hikaricp.get())
property("configurate", libs.versions.configurate.get())
property("caffeine", libs.versions.caffeine.get())
property("compress", libs.versions.commons.compress.get())
property("text", libs.versions.commons.text.get())
property("geoip", libs.versions.geoip.get())
property("jackson", libs.versions.jackson.get())
property("maxminddb", libs.versions.maxmind.db.get())
property("fuzzywuzzy", libs.versions.fuzzywuzzy.get())
property("cloud", libs.versions.cloud.get())
}
}
}
}

// Publish to Maven Central
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package me.xneox.epicguard.core.util;

public final class Constants {
private Constants() {}
// replaced by the blossom task.
public static final String CURRENT_VERSION = "{{ version }}";
public static final String HIKARI = "{{ hikari }}";
public static final String CONFIGURATE = "{{ configurate }}";
public static final String CAFFEINE = "{{ caffeine }}";
public static final String COMMONS_TEXT = "{{ text }}";
public static final String COMMANDS_COMPRESS = "{{ compress }}";
public static final String GEOIP = "{{ geoip }}";
public static final String JACKSON = "{{ jackson }}";
public static final String FUZZYWUZZY = "{{ fuzzywuzzy }}";
public static final String MAXMIND_DB = "{{ maxminddb }}";
public static final String CLOUD = "{{ cloud }}";
}
4 changes: 2 additions & 2 deletions core/src/main/java/me/xneox/epicguard/core/EpicGuard.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@
import me.xneox.epicguard.core.config.migration.MiniMessageMigration;
import me.xneox.epicguard.core.proxy.ProxyService;
import me.xneox.epicguard.core.proxy.ProxyServiceSerializer;
import me.xneox.epicguard.core.util.Constants;
import me.xneox.epicguard.core.util.LogUtils;
import me.xneox.epicguard.core.util.VersionUtils;
import me.xneox.epicguard.core.util.logging.LogFilter;
import me.xneox.epicguard.core.manager.AttackManager;
import me.xneox.epicguard.core.manager.GeoManager;
Expand Down Expand Up @@ -89,7 +89,7 @@ private void startup() {
this.platform.scheduleRepeatingTask(new AttackResetTask(this), this.config.misc().attackResetInterval());
this.platform.scheduleRepeatingTask(new DataSaveTask(this), TimeUnit.MINUTES.toSeconds(this.config.misc().autoSaveInterval()));

logger().info("Startup completed successfully. Welcome to EpicGuard v" + VersionUtils.CURRENT_VERSION);
logger().info("Startup completed successfully. Welcome to EpicGuard v" + Constants.CURRENT_VERSION);
}

public void loadConfigurations() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,78 +15,52 @@

package me.xneox.epicguard.core.command;

import java.util.Collection;
import java.util.Collections;
import java.util.Map;
import cloud.commandframework.Command;
import cloud.commandframework.CommandManager;
import me.xneox.epicguard.core.EpicGuard;
import me.xneox.epicguard.core.command.sub.AnalyzeCommand;
import me.xneox.epicguard.core.command.sub.BlacklistCommand;
import me.xneox.epicguard.core.command.sub.HelpCommand;
import me.xneox.epicguard.core.command.sub.ReloadCommand;
import me.xneox.epicguard.core.command.sub.SaveCommand;
import me.xneox.epicguard.core.command.sub.StatusCommand;
import me.xneox.epicguard.core.command.sub.WhitelistCommand;
import me.xneox.epicguard.core.command.sub.*;
import me.xneox.epicguard.core.util.Constants;
import me.xneox.epicguard.core.util.TextUtils;
import me.xneox.epicguard.core.util.VersionUtils;
import net.kyori.adventure.audience.Audience;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.TextColor;
import org.jetbrains.annotations.NotNull;


/**
* This class holds all registered subcommands, and handles the user command/tab suggestion input.
*/
public class CommandHandler {
private final Map<String, SubCommand> commandMap;
private final EpicGuard epicGuard;

public CommandHandler(EpicGuard epicGuard) {
this.epicGuard = epicGuard;

this.commandMap = Map.of(
"analyze", new AnalyzeCommand(),
"blacklist", new BlacklistCommand(),
"help", new HelpCommand(),
"reload", new ReloadCommand(),
"status", new StatusCommand(),
"whitelist", new WhitelistCommand(),
"save", new SaveCommand()
);
}
public final class CommandHandler<A extends Audience> {
private final EpicGuard epicGuard;
private final CommandManager<A> commandManager;

public void handleCommand(@NotNull String[] args, @NotNull Audience audience) {
// No arguments provided - send the version message.
if (args.length < 1) {
audience.sendMessage(Component.text("You are running EpicGuard v" + VersionUtils.CURRENT_VERSION +
" on " + this.epicGuard.platform().platformVersion(), TextColor.color(0x99ff00)));
audience.sendMessage(TextUtils.cachedComponent("<#99ff00> Run <bold><white>/guard help</bold> to see available commands and statistics"));
return;
public CommandHandler(final EpicGuard epicGuard, final CommandManager<A> commandManager) {
this.epicGuard = epicGuard;
this.commandManager = commandManager;
}

var subCommand = this.commandMap.get(args[0]);
if (subCommand == null) {
audience.sendMessage(TextUtils.cachedComponent(this.epicGuard.messages().command().prefix() + this.epicGuard.messages().command().unknownCommand()));
return;
}

subCommand.execute(audience, args, this.epicGuard);
}
public void register() {
commandManager.command(builder()
.handler(ctx -> {
ctx.getSender().sendMessage(Component.text("You are running EpicGuard v" + Constants.CURRENT_VERSION +
" on " + this.epicGuard.platform().platformVersion(), TextColor.color(0x99ff00)));
ctx.getSender().sendMessage(TextUtils.cachedComponent("<#99ff00> Run <bold><white>/guard help</bold> to see available commands and statistics"));
}));

@NotNull
public Collection<String> handleSuggestions(@NotNull String[] args) {
// If no argument is specified, send all available subcommands.
if (args.length <= 1) {
return this.commandMap.keySet();
final SubCommand[] subCommands = {
new AnalyzeCommand(),
new BlacklistCommand(),
new HelpCommand(),
new ReloadCommand(),
new StatusCommand(),
new WhitelistCommand(),
new SaveCommand()
};
for (final SubCommand subCommand : subCommands) {
subCommand.register(commandManager, epicGuard);
}
}

// Handle argument completions.
// "rel" will be completed to "reload"
for (var entry : this.commandMap.entrySet()) {
if (entry.getKey().startsWith(args[0])) {
return entry.getValue().suggest(args, this.epicGuard);
}
private Command.Builder<A> builder() {
return commandManager.commandBuilder("epicguard").permission("epicguard.admin");
}

return Collections.emptyList();
}
}
29 changes: 5 additions & 24 deletions core/src/main/java/me/xneox/epicguard/core/command/SubCommand.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,37 +15,18 @@

package me.xneox.epicguard.core.command;

import java.util.Collection;
import java.util.Collections;

import cloud.commandframework.Command;
import cloud.commandframework.CommandManager;
import me.xneox.epicguard.core.EpicGuard;
import net.kyori.adventure.audience.Audience;
import org.jetbrains.annotations.NotNull;

/**
* A subcommand of the /epicguard command.
*/
public interface SubCommand {
<A extends Audience> void register(CommandManager<A> commandManager, EpicGuard epicGuard);

/**
* Handles the execution of this subcommand
*
* @param audience the executor of this subcommand
* @param args arguments provided by the executor
* @param epicGuard instance of {@link EpicGuard}
*/
void execute(@NotNull Audience audience, @NotNull String[] args, @NotNull EpicGuard epicGuard);

/**
* Handles the tab-completion of this subcommand.
* Returns available suggestions if possible.
*
* @param args arguments provided by the executor
* @param epicGuard instance of {@link EpicGuard}
* @return available suggestions, or an empty ArrayList
*/
@NotNull
default Collection<String> suggest(@NotNull String[] args, @NotNull EpicGuard epicGuard) {
return Collections.emptyList();
default <A extends Audience> Command.Builder<A> builder(CommandManager<A> commandManager) {
return commandManager.commandBuilder("epicguard").permission("epicguard.admin");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,65 +15,78 @@

package me.xneox.epicguard.core.command.sub;

import cloud.commandframework.CommandManager;
import cloud.commandframework.arguments.standard.StringArgument;
import com.google.common.net.InetAddresses;
import java.util.Collection;
import java.util.Collections;

import me.xneox.epicguard.core.EpicGuard;
import me.xneox.epicguard.core.command.SubCommand;
import me.xneox.epicguard.core.util.TextUtils;
import net.kyori.adventure.audience.Audience;
import org.jetbrains.annotations.NotNull;

public class AnalyzeCommand implements SubCommand {
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

@Override
public void execute(@NotNull Audience audience, @NotNull String[] args, @NotNull EpicGuard epicGuard) {
var config = epicGuard.messages().command();
public final class AnalyzeCommand implements SubCommand {

if (args.length != 2) {
audience.sendMessage(TextUtils.component(config.prefix() +
config.usage().replace("{USAGE}", "/guard analyze <nickname/address>")));
return;
}
@Override
public <A extends Audience> void register(CommandManager<A> commandManager, EpicGuard epicGuard) {
final StringArgument<A> addressArgument = StringArgument.<A>builder("address")
.single()
.withSuggestionsProvider((ctx, a) -> {
if (epicGuard.config().misc().disableIPTabCompletion()) {
return Collections.emptyList();
}

var meta = epicGuard.storageManager().resolveAddressMeta(args[1]);
if (meta == null) {
audience.sendMessage(TextUtils.component(config.prefix() + config.invalidArgument()));
return;
}
final List<String> addresses = new ArrayList<>();
epicGuard.storageManager().addresses().asMap().forEach((k, v) -> addresses.add(k));
return addresses;
})
.build();
commandManager.command(
builder(commandManager)
.literal("analyze")
.argument(addressArgument)
.handler(ctx -> {
final var config = epicGuard.messages().command();
final var audience = ctx.getSender();
var optionalAddress = ctx.getOptional(addressArgument);
if (optionalAddress.isEmpty()) {
audience.sendMessage(TextUtils.component(config.prefix() +
config.usage().replace("{USAGE}", "/guard analyze <nickname/address>")));
return;
}
// Assume that executor provided an address as the argument.
var address = optionalAddress.get();

// Assume that executor provided an address as the argument.
String address = args[1];
var meta = epicGuard.storageManager().resolveAddressMeta(address);
if (meta == null) {
ctx.getSender().sendMessage(TextUtils.component(config.prefix() + config.invalidArgument()));
return;
}

// If executor provided nickname as the argument instead, we have to find their IP address.
if (!InetAddresses.isInetAddress(args[1])) {
for (var entry : epicGuard.storageManager().addresses().asMap().entrySet()) {
if (entry.getValue().equals(meta)) {
address = entry.getKey();
break;
}
}
}
// If executor provided nickname as the argument instead, we have to find their IP address.
if (!InetAddresses.isInetAddress(address)) {
for (var entry : epicGuard.storageManager().addresses().asMap().entrySet()) {
if (entry.getValue().equals(meta)) {
address = entry.getKey();
break;
}
}
}

for (String line : config.analyzeCommand()) {
audience.sendMessage(TextUtils.component(line
.replace("{ADDRESS}", address)
.replace("{COUNTRY}", epicGuard.geoManager().countryCode(address))
.replace("{CITY}", epicGuard.geoManager().city(address))
.replace("{WHITELISTED}", meta.whitelisted() ? "<green>✔" : "<red>✖")
.replace("{BLACKLISTED}", meta.blacklisted() ? "<green>✔" : "<red>✖")
.replace("{ACCOUNT-AMOUNT}", Integer.toString(meta.nicknames().size()))
.replace("{NICKNAMES}", String.join(", ", meta.nicknames()))));
}
}
for (final String line : config.analyzeCommand()) {
audience.sendMessage(TextUtils.component(line
.replace("{ADDRESS}", address)
.replace("{COUNTRY}", epicGuard.geoManager().countryCode(address))
.replace("{CITY}", epicGuard.geoManager().city(address))
.replace("{WHITELISTED}", meta.whitelisted() ? "<green>✔" : "<red>✖")
.replace("{BLACKLISTED}", meta.blacklisted() ? "<green>✔" : "<red>✖")
.replace("{ACCOUNT-AMOUNT}", Integer.toString(meta.nicknames().size()))
.replace("{NICKNAMES}", String.join(", ", meta.nicknames()))));
}
})
);

@Override
public @NotNull Collection<String> suggest(@NotNull String[] args, @NotNull EpicGuard epicGuard) {
if (epicGuard.config().misc().disableIPTabCompletion()) {
return Collections.emptyList();
}

return epicGuard.storageManager().addresses().asMap().keySet();
}
}
Loading