initial commit
This commit is contained in:
commit
574098a06a
21 changed files with 1924 additions and 0 deletions
|
|
@ -0,0 +1,80 @@
|
|||
package com.uravgcode.globalwhitelist;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import com.uravgcode.globalwhitelist.command.WhitelistCommand;
|
||||
import com.uravgcode.globalwhitelist.config.MessagesConfig;
|
||||
import com.uravgcode.globalwhitelist.config.WhitelistConfig;
|
||||
import com.uravgcode.globalwhitelist.service.MinecraftProfileService;
|
||||
import com.uravgcode.globalwhitelist.whitelist.PlayerProfile;
|
||||
import com.uravgcode.globalwhitelist.whitelist.Whitelist;
|
||||
import com.velocitypowered.api.event.ResultedEvent;
|
||||
import com.velocitypowered.api.event.Subscribe;
|
||||
import com.velocitypowered.api.event.connection.LoginEvent;
|
||||
import com.velocitypowered.api.event.proxy.ProxyInitializeEvent;
|
||||
import com.velocitypowered.api.plugin.Plugin;
|
||||
import com.velocitypowered.api.plugin.annotation.DataDirectory;
|
||||
import com.velocitypowered.api.proxy.ProxyServer;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
|
||||
@Plugin(
|
||||
id = "global-whitelist",
|
||||
name = "global-whitelist",
|
||||
version = BuildConstants.VERSION,
|
||||
url = "https://github.com/uravgcode/global-whitelist",
|
||||
description = "velocity whitelist plugin",
|
||||
authors = {"UrAvgCode"}
|
||||
)
|
||||
public class GlobalWhitelistPlugin {
|
||||
private final ProxyServer proxy;
|
||||
private final MinecraftProfileService profileService;
|
||||
|
||||
private final Whitelist whitelist;
|
||||
private final WhitelistConfig config;
|
||||
private final MessagesConfig messages;
|
||||
|
||||
@Inject
|
||||
public GlobalWhitelistPlugin(ProxyServer server, Logger logger, @DataDirectory Path dataDirectory) {
|
||||
this.proxy = server;
|
||||
this.profileService = new MinecraftProfileService(logger);
|
||||
|
||||
this.whitelist = new Whitelist(dataDirectory.resolve("whitelist.json"), logger);
|
||||
this.config = new WhitelistConfig(dataDirectory.resolve("config.properties"), logger);
|
||||
this.messages = new MessagesConfig(dataDirectory.resolve("messages.properties"), logger);
|
||||
|
||||
try {
|
||||
Files.createDirectories(dataDirectory);
|
||||
} catch (IOException e) {
|
||||
logger.error("failed to create plugin directory: {}", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onProxyInitialization(ProxyInitializeEvent event) {
|
||||
config.reload();
|
||||
whitelist.reload();
|
||||
messages.reload();
|
||||
|
||||
proxy.getEventManager().register(this, LoginEvent.class, loginEvent -> {
|
||||
if (!config.whitelistEnabled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
var player = loginEvent.getPlayer();
|
||||
if (!whitelist.contains(new PlayerProfile(player.getUniqueId(), player.getUsername()))) {
|
||||
loginEvent.setResult(ResultedEvent.ComponentResult.denied(messages.getMessage(MessagesConfig.WHITELIST_REJECTED)));
|
||||
}
|
||||
});
|
||||
|
||||
var commandManager = proxy.getCommandManager();
|
||||
var commandMeta = commandManager.metaBuilder("gwl")
|
||||
.plugin(this)
|
||||
.build();
|
||||
|
||||
var command = WhitelistCommand.createBrigadierCommand(proxy, profileService, whitelist, config, messages);
|
||||
commandManager.register(commandMeta, command);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,94 @@
|
|||
package com.uravgcode.globalwhitelist.command;
|
||||
|
||||
import com.mojang.brigadier.arguments.StringArgumentType;
|
||||
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
||||
import com.mojang.brigadier.tree.LiteralCommandNode;
|
||||
import com.uravgcode.globalwhitelist.config.MessagesConfig;
|
||||
import com.uravgcode.globalwhitelist.config.WhitelistConfig;
|
||||
import com.uravgcode.globalwhitelist.service.MinecraftProfileService;
|
||||
import com.uravgcode.globalwhitelist.whitelist.Whitelist;
|
||||
import com.velocitypowered.api.command.BrigadierCommand;
|
||||
import com.velocitypowered.api.command.CommandSource;
|
||||
import com.velocitypowered.api.proxy.ProxyServer;
|
||||
|
||||
public final class WhitelistCommand {
|
||||
private static final String PERMISSION_BASE = "globalwhitelist";
|
||||
private static final String PERMISSION_ADMIN = "globalwhitelist.admin";
|
||||
|
||||
public static BrigadierCommand createBrigadierCommand(
|
||||
final ProxyServer proxy,
|
||||
final MinecraftProfileService profileService,
|
||||
final Whitelist whitelist,
|
||||
final WhitelistConfig config,
|
||||
final MessagesConfig messages
|
||||
) {
|
||||
var commandHandler = new WhitelistCommandHandler(proxy, profileService, whitelist, config, messages);
|
||||
|
||||
LiteralCommandNode<CommandSource> helloNode = BrigadierCommand.literalArgumentBuilder("globalwhitelist")
|
||||
.requires(source -> source.hasPermission(PERMISSION_BASE) || source.hasPermission(PERMISSION_ADMIN))
|
||||
.executes(commandHandler::help)
|
||||
.then(buildAddCommand(commandHandler))
|
||||
.then(buildRemoveCommand(commandHandler))
|
||||
.then(buildListCommand(commandHandler))
|
||||
.then(buildReloadCommand(commandHandler))
|
||||
.then(buildOnCommand(commandHandler))
|
||||
.then(buildOffCommand(commandHandler))
|
||||
.then(buildEnforcedCommand(commandHandler))
|
||||
.then(buildUnenforcedCommand(commandHandler))
|
||||
.build();
|
||||
|
||||
return new BrigadierCommand(helloNode);
|
||||
}
|
||||
|
||||
private static LiteralArgumentBuilder<CommandSource> buildAddCommand(WhitelistCommandHandler handler) {
|
||||
return BrigadierCommand.literalArgumentBuilder("add")
|
||||
.requires(source -> source.hasPermission(PERMISSION_BASE))
|
||||
.then(BrigadierCommand.requiredArgumentBuilder("player", StringArgumentType.word())
|
||||
.suggests(handler::suggestOnlinePlayers)
|
||||
.executes(handler::add));
|
||||
}
|
||||
|
||||
private static LiteralArgumentBuilder<CommandSource> buildRemoveCommand(WhitelistCommandHandler handler) {
|
||||
return BrigadierCommand.literalArgumentBuilder("remove")
|
||||
.requires(source -> source.hasPermission(PERMISSION_BASE))
|
||||
.then(BrigadierCommand.requiredArgumentBuilder("player", StringArgumentType.word())
|
||||
.suggests(handler::suggestWhitelistedPlayers)
|
||||
.executes(handler::remove));
|
||||
}
|
||||
|
||||
private static LiteralArgumentBuilder<CommandSource> buildListCommand(WhitelistCommandHandler handler) {
|
||||
return BrigadierCommand.literalArgumentBuilder("list")
|
||||
.requires(source -> source.hasPermission(PERMISSION_BASE))
|
||||
.executes(handler::list);
|
||||
}
|
||||
|
||||
private static LiteralArgumentBuilder<CommandSource> buildOnCommand(WhitelistCommandHandler handler) {
|
||||
return BrigadierCommand.literalArgumentBuilder("on")
|
||||
.requires(source -> source.hasPermission(PERMISSION_ADMIN))
|
||||
.executes(handler::on);
|
||||
}
|
||||
|
||||
private static LiteralArgumentBuilder<CommandSource> buildOffCommand(WhitelistCommandHandler handler) {
|
||||
return BrigadierCommand.literalArgumentBuilder("off")
|
||||
.requires(source -> source.hasPermission(PERMISSION_ADMIN))
|
||||
.executes(handler::off);
|
||||
}
|
||||
|
||||
private static LiteralArgumentBuilder<CommandSource> buildEnforcedCommand(WhitelistCommandHandler handler) {
|
||||
return BrigadierCommand.literalArgumentBuilder("enforced")
|
||||
.requires(source -> source.hasPermission(PERMISSION_ADMIN))
|
||||
.executes(handler::enforced);
|
||||
}
|
||||
|
||||
private static LiteralArgumentBuilder<CommandSource> buildUnenforcedCommand(WhitelistCommandHandler handler) {
|
||||
return BrigadierCommand.literalArgumentBuilder("unenforced")
|
||||
.requires(source -> source.hasPermission(PERMISSION_ADMIN))
|
||||
.executes(handler::unenforced);
|
||||
}
|
||||
|
||||
private static LiteralArgumentBuilder<CommandSource> buildReloadCommand(WhitelistCommandHandler handler) {
|
||||
return BrigadierCommand.literalArgumentBuilder("reload")
|
||||
.requires(source -> source.hasPermission(PERMISSION_ADMIN))
|
||||
.executes(handler::reload);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,174 @@
|
|||
package com.uravgcode.globalwhitelist.command;
|
||||
|
||||
import com.mojang.brigadier.Command;
|
||||
import com.mojang.brigadier.context.CommandContext;
|
||||
import com.mojang.brigadier.suggestion.Suggestions;
|
||||
import com.mojang.brigadier.suggestion.SuggestionsBuilder;
|
||||
import com.uravgcode.globalwhitelist.config.MessagesConfig;
|
||||
import com.uravgcode.globalwhitelist.config.WhitelistConfig;
|
||||
import com.uravgcode.globalwhitelist.service.MinecraftProfileService;
|
||||
import com.uravgcode.globalwhitelist.whitelist.PlayerProfile;
|
||||
import com.uravgcode.globalwhitelist.whitelist.Whitelist;
|
||||
import com.velocitypowered.api.command.CommandSource;
|
||||
import com.velocitypowered.api.proxy.ProxyServer;
|
||||
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
public class WhitelistCommandHandler {
|
||||
private final ProxyServer proxy;
|
||||
private final MinecraftProfileService profileService;
|
||||
|
||||
private final Whitelist whitelist;
|
||||
private final WhitelistConfig config;
|
||||
private final MessagesConfig messages;
|
||||
|
||||
public WhitelistCommandHandler(
|
||||
final ProxyServer proxy,
|
||||
final MinecraftProfileService profileService,
|
||||
final Whitelist whitelist,
|
||||
final WhitelistConfig config,
|
||||
final MessagesConfig messages
|
||||
) {
|
||||
this.proxy = proxy;
|
||||
this.profileService = profileService;
|
||||
this.whitelist = whitelist;
|
||||
this.config = config;
|
||||
this.messages = messages;
|
||||
}
|
||||
|
||||
public CompletableFuture<Suggestions> suggestOnlinePlayers(CommandContext<CommandSource> ignored, SuggestionsBuilder builder) {
|
||||
proxy.getAllPlayers().forEach(player -> builder.suggest(player.getUsername()));
|
||||
return builder.buildFuture();
|
||||
}
|
||||
|
||||
public CompletableFuture<Suggestions> suggestWhitelistedPlayers(CommandContext<CommandSource> ignored, SuggestionsBuilder builder) {
|
||||
whitelist.list().forEach(builder::suggest);
|
||||
return builder.buildFuture();
|
||||
}
|
||||
|
||||
public int help(CommandContext<CommandSource> context) {
|
||||
context.getSource().sendMessage(messages.getMessage(MessagesConfig.WHITELIST_HELP));
|
||||
return Command.SINGLE_SUCCESS;
|
||||
}
|
||||
|
||||
public int add(CommandContext<CommandSource> context) {
|
||||
var source = context.getSource();
|
||||
var playerName = context.getArgument("player", String.class);
|
||||
|
||||
profileService.getProfile(playerName).ifPresentOrElse(player -> {
|
||||
if (whitelist.add(player)) {
|
||||
source.sendMessage(messages.getMessage(MessagesConfig.WHITELIST_ADD_SUCCESS, playerName));
|
||||
} else {
|
||||
source.sendMessage(messages.getMessage(MessagesConfig.WHITELIST_ADD_ALREADY_WHITELISTED, playerName));
|
||||
}
|
||||
}, () -> source.sendMessage(messages.getMessage(MessagesConfig.WHITELIST_PLAYER_DOES_NOT_EXIST, playerName)));
|
||||
|
||||
return Command.SINGLE_SUCCESS;
|
||||
}
|
||||
|
||||
public int remove(CommandContext<CommandSource> context) {
|
||||
var source = context.getSource();
|
||||
var playerName = context.getArgument("player", String.class);
|
||||
|
||||
profileService.getProfile(playerName).ifPresentOrElse(player -> {
|
||||
if (whitelist.remove(player)) {
|
||||
source.sendMessage(messages.getMessage(MessagesConfig.WHITELIST_REMOVE_SUCCESS, playerName));
|
||||
if (config.whitelistEnabled() && config.enforceWhitelistEnabled()) {
|
||||
proxy.getPlayer(playerName).ifPresent(p -> p.disconnect(messages.getMessage(MessagesConfig.WHITELIST_REJECTED)));
|
||||
}
|
||||
} else {
|
||||
source.sendMessage(messages.getMessage(MessagesConfig.WHITELIST_REMOVE_NOT_WHITELISTED, playerName));
|
||||
}
|
||||
}, () -> source.sendMessage(messages.getMessage(MessagesConfig.WHITELIST_PLAYER_DOES_NOT_EXIST, playerName)));
|
||||
|
||||
return Command.SINGLE_SUCCESS;
|
||||
}
|
||||
|
||||
public int list(CommandContext<CommandSource> context) {
|
||||
var source = context.getSource();
|
||||
var playerList = whitelist.list();
|
||||
|
||||
if (playerList.isEmpty()) {
|
||||
source.sendMessage(messages.getMessage(MessagesConfig.WHITELIST_LIST_EMPTY));
|
||||
} else {
|
||||
source.sendMessage(messages.getMessage(MessagesConfig.WHITELIST_LIST, playerList));
|
||||
}
|
||||
|
||||
return Command.SINGLE_SUCCESS;
|
||||
}
|
||||
|
||||
public int on(CommandContext<CommandSource> context) {
|
||||
CommandSource source = context.getSource();
|
||||
|
||||
if (config.whitelistEnabled()) {
|
||||
source.sendMessage(messages.getMessage(MessagesConfig.WHITELIST_ON_ALREADY));
|
||||
} else {
|
||||
config.setWhitelistEnabled(true);
|
||||
source.sendMessage(messages.getMessage(MessagesConfig.WHITELIST_ON));
|
||||
if (config.enforceWhitelistEnabled()) {
|
||||
for (var player : proxy.getAllPlayers()) {
|
||||
if (!whitelist.contains(new PlayerProfile(player.getUniqueId(), player.getUsername()))) {
|
||||
player.disconnect(messages.getMessage(MessagesConfig.WHITELIST_REJECTED));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Command.SINGLE_SUCCESS;
|
||||
}
|
||||
|
||||
public int off(CommandContext<CommandSource> context) {
|
||||
CommandSource source = context.getSource();
|
||||
|
||||
if (config.whitelistEnabled()) {
|
||||
config.setWhitelistEnabled(false);
|
||||
source.sendMessage(messages.getMessage(MessagesConfig.WHITELIST_OFF));
|
||||
} else {
|
||||
source.sendMessage(messages.getMessage(MessagesConfig.WHITELIST_OFF_ALREADY));
|
||||
}
|
||||
|
||||
return Command.SINGLE_SUCCESS;
|
||||
}
|
||||
|
||||
public int enforced(CommandContext<CommandSource> context) {
|
||||
CommandSource source = context.getSource();
|
||||
|
||||
if (config.enforceWhitelistEnabled()) {
|
||||
source.sendMessage(messages.getMessage(MessagesConfig.WHITELIST_ENFORCED_ALREADY));
|
||||
} else {
|
||||
config.setEnforceWhitelistEnabled(true);
|
||||
source.sendMessage(messages.getMessage(MessagesConfig.WHITELIST_ENFORCED));
|
||||
if (config.whitelistEnabled()) {
|
||||
for (var player : proxy.getAllPlayers()) {
|
||||
if (!whitelist.contains(new PlayerProfile(player.getUniqueId(), player.getUsername()))) {
|
||||
player.disconnect(messages.getMessage(MessagesConfig.WHITELIST_REJECTED));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Command.SINGLE_SUCCESS;
|
||||
}
|
||||
|
||||
public int unenforced(CommandContext<CommandSource> context) {
|
||||
CommandSource source = context.getSource();
|
||||
|
||||
if (config.enforceWhitelistEnabled()) {
|
||||
config.setEnforceWhitelistEnabled(false);
|
||||
source.sendMessage(messages.getMessage(MessagesConfig.WHITELIST_UNENFORCED));
|
||||
} else {
|
||||
source.sendMessage(messages.getMessage(MessagesConfig.WHITELIST_UNENFORCED_ALREADY));
|
||||
}
|
||||
|
||||
return Command.SINGLE_SUCCESS;
|
||||
}
|
||||
|
||||
public int reload(CommandContext<CommandSource> context) {
|
||||
whitelist.reload();
|
||||
config.reload();
|
||||
messages.reload();
|
||||
CommandSource source = context.getSource();
|
||||
source.sendMessage(messages.getMessage(MessagesConfig.WHITELIST_RELOAD));
|
||||
return Command.SINGLE_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,129 @@
|
|||
package com.uravgcode.globalwhitelist.config;
|
||||
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.minimessage.MiniMessage;
|
||||
import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Path;
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
|
||||
public class MessagesConfig {
|
||||
public static final String WHITELIST_HELP = "whitelist.help";
|
||||
|
||||
public static final String WHITELIST_ADD_SUCCESS = "whitelist.add.success";
|
||||
public static final String WHITELIST_ADD_ALREADY_WHITELISTED = "whitelist.add.already_whitelisted";
|
||||
|
||||
public static final String WHITELIST_REMOVE_SUCCESS = "whitelist.remove.success";
|
||||
public static final String WHITELIST_REMOVE_NOT_WHITELISTED = "whitelist.remove.not_whitelisted";
|
||||
|
||||
public static final String WHITELIST_PLAYER_DOES_NOT_EXIST = "whitelist.player_does_not_exist";
|
||||
|
||||
public static final String WHITELIST_LIST = "whitelist.list";
|
||||
public static final String WHITELIST_LIST_EMPTY = "whitelist.list.empty";
|
||||
|
||||
public static final String WHITELIST_ON = "whitelist.on";
|
||||
public static final String WHITELIST_ON_ALREADY = "whitelist.on.already";
|
||||
public static final String WHITELIST_OFF = "whitelist.off";
|
||||
public static final String WHITELIST_OFF_ALREADY = "whitelist.off.already";
|
||||
|
||||
public static final String WHITELIST_ENFORCED = "whitelist.enforced";
|
||||
public static final String WHITELIST_ENFORCED_ALREADY = "whitelist.enforced.already";
|
||||
public static final String WHITELIST_UNENFORCED = "whitelist.unenforced";
|
||||
public static final String WHITELIST_UNENFORCED_ALREADY = "whitelist.unenforced.already";
|
||||
|
||||
public static final String WHITELIST_RELOAD = "whitelist.reload";
|
||||
|
||||
public static final String WHITELIST_REJECTED = "whitelist.rejected";
|
||||
|
||||
private final Logger logger;
|
||||
private final Properties messages;
|
||||
private final File messagesFile;
|
||||
private final MiniMessage miniMessage;
|
||||
|
||||
public MessagesConfig(
|
||||
final Path messagesPath,
|
||||
final Logger logger
|
||||
) {
|
||||
this.messagesFile = messagesPath.toFile();
|
||||
this.logger = logger;
|
||||
this.messages = new Properties();
|
||||
this.miniMessage = MiniMessage.miniMessage();
|
||||
}
|
||||
|
||||
public void reload() {
|
||||
if (!messagesFile.exists()) {
|
||||
loadDefaults();
|
||||
save();
|
||||
return;
|
||||
}
|
||||
|
||||
try (FileInputStream in = new FileInputStream(messagesFile)) {
|
||||
messages.load(in);
|
||||
} catch (IOException e) {
|
||||
logger.error("failed to load messages config: {}", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public void save() {
|
||||
try (FileOutputStream out = new FileOutputStream(messagesFile)) {
|
||||
messages.store(out, "messages config");
|
||||
} catch (IOException e) {
|
||||
logger.error("failed to save messages config: {}", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private void loadDefaults() {
|
||||
messages.setProperty(WHITELIST_HELP, "<red>/globalwhitelist <add|remove|list|on|off|enforce|unenforce|reload>");
|
||||
|
||||
messages.setProperty(WHITELIST_ADD_SUCCESS, "Added <player> to the whitelist");
|
||||
messages.setProperty(WHITELIST_ADD_ALREADY_WHITELISTED, "<red>Player is already whitelisted");
|
||||
|
||||
messages.setProperty(WHITELIST_REMOVE_SUCCESS, "Removed <player> from the whitelist");
|
||||
messages.setProperty(WHITELIST_REMOVE_NOT_WHITELISTED, "<red>Player is not whitelisted");
|
||||
|
||||
messages.setProperty(WHITELIST_PLAYER_DOES_NOT_EXIST, "<red>That player does not exist");
|
||||
|
||||
messages.setProperty(WHITELIST_LIST, "There are <count> whitelisted player(s): <players>");
|
||||
messages.setProperty(WHITELIST_LIST_EMPTY, "There are no whitelisted players");
|
||||
|
||||
messages.setProperty(WHITELIST_ON, "Whitelist is now turned on");
|
||||
messages.setProperty(WHITELIST_ON_ALREADY, "<red>Whitelist is already turned on");
|
||||
messages.setProperty(WHITELIST_OFF, "Whitelist is now turned off");
|
||||
messages.setProperty(WHITELIST_OFF_ALREADY, "<red>Whitelist is already turned off");
|
||||
|
||||
messages.setProperty(WHITELIST_ENFORCED, "Enforce whitelist is now turned on");
|
||||
messages.setProperty(WHITELIST_ENFORCED_ALREADY, "<red>Enforce whitelist is already turned on");
|
||||
messages.setProperty(WHITELIST_UNENFORCED, "Enforce whitelist is now turned off");
|
||||
messages.setProperty(WHITELIST_UNENFORCED_ALREADY, "<red>Enforce whitelist is already turned off");
|
||||
|
||||
messages.setProperty(WHITELIST_RELOAD, "Reloaded the whitelist");
|
||||
|
||||
messages.setProperty(WHITELIST_REJECTED, "<red>You are not whitelisted on this server!");
|
||||
}
|
||||
|
||||
public String get(String key) {
|
||||
return messages.getProperty(key, "");
|
||||
}
|
||||
|
||||
public Component getMessage(String key) {
|
||||
return miniMessage.deserialize(get(key));
|
||||
}
|
||||
|
||||
public Component getMessage(String key, String player) {
|
||||
return miniMessage.deserialize(get(key), Placeholder.component("player", Component.text(player)));
|
||||
}
|
||||
|
||||
public Component getMessage(String key, List<String> players) {
|
||||
return miniMessage.deserialize(
|
||||
get(key),
|
||||
Placeholder.component("count", Component.text(players.size())),
|
||||
Placeholder.component("players", Component.text(String.join(", ", players)))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,66 @@
|
|||
package com.uravgcode.globalwhitelist.config;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Properties;
|
||||
|
||||
public class WhitelistConfig {
|
||||
private static final String WHITE_LIST = "white-list";
|
||||
private static final String ENFORCE_WHITELIST = "enforce-whitelist";
|
||||
|
||||
private final File configFile;
|
||||
private final Logger logger;
|
||||
private final Properties config;
|
||||
|
||||
public WhitelistConfig(Path configPath, Logger logger) {
|
||||
this.configFile = configPath.toFile();
|
||||
this.logger = logger;
|
||||
this.config = new Properties();
|
||||
}
|
||||
|
||||
public void reload() {
|
||||
if (!configFile.exists()) {
|
||||
config.setProperty(WHITE_LIST, "false");
|
||||
config.setProperty(ENFORCE_WHITELIST, "false");
|
||||
save();
|
||||
return;
|
||||
}
|
||||
|
||||
try (FileInputStream in = new FileInputStream(configFile)) {
|
||||
config.load(in);
|
||||
} catch (IOException e) {
|
||||
logger.error("failed to load whitelist config: {}", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public void save() {
|
||||
try (FileOutputStream out = new FileOutputStream(configFile)) {
|
||||
config.store(out, "whitelist config");
|
||||
} catch (IOException e) {
|
||||
logger.error("failed to save whitelist config: {}", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public boolean whitelistEnabled() {
|
||||
return Boolean.parseBoolean(config.getProperty(WHITE_LIST));
|
||||
}
|
||||
|
||||
public void setWhitelistEnabled(boolean enabled) {
|
||||
config.setProperty(WHITE_LIST, Boolean.toString(enabled));
|
||||
save();
|
||||
}
|
||||
|
||||
public boolean enforceWhitelistEnabled() {
|
||||
return Boolean.parseBoolean(config.getProperty(ENFORCE_WHITELIST));
|
||||
}
|
||||
|
||||
public void setEnforceWhitelistEnabled(boolean enabled) {
|
||||
config.setProperty(ENFORCE_WHITELIST, Boolean.toString(enabled));
|
||||
save();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,96 @@
|
|||
package com.uravgcode.globalwhitelist.service;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParser;
|
||||
import com.uravgcode.globalwhitelist.whitelist.PlayerProfile;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.net.http.HttpClient;
|
||||
import java.net.http.HttpRequest;
|
||||
import java.net.http.HttpResponse;
|
||||
import java.time.Duration;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public class MinecraftProfileService {
|
||||
private static final URI API_BASE_URL = URI.create("https://api.minecraftservices.com/minecraft/profile/lookup/name/");
|
||||
private static final Pattern UUID_PATTERN = Pattern.compile("(\\p{XDigit}{8})(\\p{XDigit}{4})(\\p{XDigit}{4})(\\p{XDigit}{4})(\\p{XDigit}{12})");
|
||||
private static final Duration TIMEOUT = Duration.ofSeconds(5);
|
||||
|
||||
private final Logger logger;
|
||||
private final HttpClient httpClient;
|
||||
|
||||
public MinecraftProfileService(Logger logger) {
|
||||
this.logger = logger;
|
||||
this.httpClient = HttpClient.newBuilder()
|
||||
.connectTimeout(TIMEOUT)
|
||||
.build();
|
||||
}
|
||||
|
||||
public Optional<PlayerProfile> getProfile(String playerName) {
|
||||
if (playerName == null || playerName.isBlank()) {
|
||||
logger.warn("player name cannot be null or empty");
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
try {
|
||||
var request = HttpRequest.newBuilder()
|
||||
.uri(API_BASE_URL.resolve(playerName))
|
||||
.timeout(TIMEOUT)
|
||||
.GET()
|
||||
.build();
|
||||
|
||||
var response = httpClient.send(request, HttpResponse.BodyHandlers.ofString());
|
||||
|
||||
return switch (response.statusCode()) {
|
||||
case 200 -> parseProfile(response.body());
|
||||
case 404 -> {
|
||||
logger.warn("player with name {} not found", playerName);
|
||||
yield Optional.empty();
|
||||
}
|
||||
default -> {
|
||||
logger.warn("api request failed with status {}: {}", response.statusCode(), response.body());
|
||||
yield Optional.empty();
|
||||
}
|
||||
};
|
||||
|
||||
} catch (IOException e) {
|
||||
logger.error("network error while fetching profile for '{}': {}", playerName, e.getMessage());
|
||||
return Optional.empty();
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
logger.error("request interrupted while fetching profile for '{}': {}", playerName, e.getMessage());
|
||||
return Optional.empty();
|
||||
}
|
||||
}
|
||||
|
||||
private Optional<PlayerProfile> parseProfile(String jsonString) {
|
||||
try {
|
||||
JsonObject jsonObject = JsonParser.parseString(jsonString).getAsJsonObject();
|
||||
|
||||
if (!jsonObject.has("id") || !jsonObject.has("name")) {
|
||||
logger.warn("missing 'id' or 'name' in json:\n{}", jsonString);
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
String uuidString = jsonObject.get("id").getAsString();
|
||||
String name = jsonObject.get("name").getAsString();
|
||||
|
||||
var matcher = UUID_PATTERN.matcher(uuidString);
|
||||
if (!matcher.matches()) {
|
||||
logger.warn("invalid uuid format in json:\n{}", jsonString);
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
var uuid = UUID.fromString(matcher.replaceFirst("$1-$2-$3-$4-$5"));
|
||||
return Optional.of(new PlayerProfile(uuid, name));
|
||||
|
||||
} catch (Exception e) {
|
||||
logger.error("failed to parse json:\n{}\nerror: {}", jsonString, e.getMessage());
|
||||
return Optional.empty();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
package com.uravgcode.globalwhitelist.whitelist;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public record PlayerProfile(UUID uuid, String name) {
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) return true;
|
||||
if (!(obj instanceof PlayerProfile other)) return false;
|
||||
return uuid.equals(other.uuid);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return uuid.hashCode();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,84 @@
|
|||
package com.uravgcode.globalwhitelist.whitelist;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileReader;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Type;
|
||||
import java.nio.file.Path;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
public class Whitelist {
|
||||
private final Logger logger;
|
||||
private final File whitelistFile;
|
||||
private final Set<PlayerProfile> whitelistPlayers;
|
||||
|
||||
private final Gson gson = new GsonBuilder().setPrettyPrinting().create();
|
||||
|
||||
public Whitelist(Path whitelistPath, Logger logger) {
|
||||
this.logger = logger;
|
||||
this.whitelistFile = whitelistPath.toFile();
|
||||
this.whitelistPlayers = new HashSet<>();
|
||||
}
|
||||
|
||||
public boolean contains(PlayerProfile player) {
|
||||
return whitelistPlayers.contains(player);
|
||||
}
|
||||
|
||||
public boolean add(PlayerProfile player) {
|
||||
if (whitelistPlayers.add(player)) {
|
||||
save();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean remove(PlayerProfile player) {
|
||||
if (whitelistPlayers.remove(player)) {
|
||||
save();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public List<String> list() {
|
||||
return whitelistPlayers.stream().map(PlayerProfile::name).toList();
|
||||
}
|
||||
|
||||
public void reload() {
|
||||
try {
|
||||
if (whitelistFile.createNewFile()) {
|
||||
whitelistPlayers.clear();
|
||||
return;
|
||||
}
|
||||
|
||||
try (FileReader reader = new FileReader(whitelistFile)) {
|
||||
Type listType = new TypeToken<List<PlayerProfile>>() {
|
||||
}.getType();
|
||||
List<PlayerProfile> players = gson.fromJson(reader, listType);
|
||||
|
||||
if (players != null) {
|
||||
whitelistPlayers.clear();
|
||||
whitelistPlayers.addAll(players);
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private void save() {
|
||||
try (FileWriter writer = new FileWriter(whitelistFile)) {
|
||||
gson.toJson(List.copyOf(whitelistPlayers), writer);
|
||||
} catch (IOException e) {
|
||||
logger.error("failed to save whitelist: {}", e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
package com.uravgcode.globalwhitelist;
|
||||
|
||||
public class BuildConstants {
|
||||
public static final String VERSION = "${version}";
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue