diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c65bcf4 --- /dev/null +++ b/.gitignore @@ -0,0 +1,115 @@ +# User-specific stuff +.idea/ + +*.iml +*.ipr +*.iws + +# IntelliJ +out/ + +# Compiled class file +*.class + +# Log file +*.log + +# BlueJ files +*.ctxt + +# Package Files # +*.jar +*.war +*.nar +*.ear +*.zip +*.tar.gz +*.rar + +# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml +hs_err_pid* + +*~ + +# temporary files which can be created if a process still has a handle open of a deleted file +.fuse_hidden* + +# KDE directory preferences +.directory + +# Linux trash folder which might appear on any partition or disk +.Trash-* + +# .nfs files are created when an open file is removed but is still being accessed +.nfs* + +# General +.DS_Store +.AppleDouble +.LSOverride + +# Icon must end with two \r +Icon + +# Thumbnails +._* + +# Files that might appear in the root of a volume +.DocumentRevisions-V100 +.fseventsd +.Spotlight-V100 +.TemporaryItems +.Trashes +.VolumeIcon.icns +.com.apple.timemachine.donotpresent + +# Directories potentially created on remote AFP share +.AppleDB +.AppleDesktop +Network Trash Folder +Temporary Items +.apdisk + +# Windows thumbnail cache files +Thumbs.db +Thumbs.db:encryptable +ehthumbs.db +ehthumbs_vista.db + +# Dump file +*.stackdump + +# Folder config file +[Dd]esktop.ini + +# Recycle Bin used on file shares +$RECYCLE.BIN/ + +# Windows Installer files +*.cab +*.msi +*.msix +*.msm +*.msp + +# Windows shortcuts +*.lnk + +target/ + +pom.xml.tag +pom.xml.releaseBackup +pom.xml.versionsBackup +pom.xml.next + +release.properties +dependency-reduced-pom.xml +buildNumber.properties +.mvn/timing.properties +.mvn/wrapper/maven-wrapper.jar +.flattened-pom.xml + +# Common working directory +run/ + +.junie diff --git a/.mvn/wrapper/maven-wrapper.properties b/.mvn/wrapper/maven-wrapper.properties new file mode 100644 index 0000000..7c6b218 --- /dev/null +++ b/.mvn/wrapper/maven-wrapper.properties @@ -0,0 +1,3 @@ +wrapperVersion=3.3.4 +distributionType=only-script +distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.6/apache-maven-3.9.6-bin.zip diff --git a/api/pom.xml b/api/pom.xml index 41f94d2..c314078 100644 --- a/api/pom.xml +++ b/api/pom.xml @@ -122,16 +122,6 @@ org.apache.maven.plugins maven-compiler-plugin - ${maven-compiler-plugin.version} - - - - org.projectlombok - lombok - ${lombok.version} - - - diff --git a/api/src/main/java/org/btuk/proxy/api/impl/BuildingsApiImpl.java b/api/src/main/java/org/btuk/proxy/api/impl/BuildingsApiImpl.java index df80fea..362f123 100644 --- a/api/src/main/java/org/btuk/proxy/api/impl/BuildingsApiImpl.java +++ b/api/src/main/java/org/btuk/proxy/api/impl/BuildingsApiImpl.java @@ -1,5 +1,7 @@ package org.btuk.proxy.api.impl; +import jakarta.inject.Inject; +import jakarta.ws.rs.Path; import jakarta.ws.rs.core.Response; import org.btuk.proxy.api.BuildingsApi; import org.btuk.proxy.api.model.Building; @@ -17,17 +19,16 @@ import java.util.UUID; import java.util.stream.Collectors; +@Path("/buildings") public class BuildingsApiImpl implements BuildingsApi { private final GlobalSQL globalSQL; + @Inject public BuildingsApiImpl(GlobalSQL globalSQL) { this.globalSQL = globalSQL; } - - - @Override public Response getBuildingsByArea(Double minLat, Double maxLat, Double minLon, Double maxLon, UUID playerUuid) { String playerUuidStr = playerUuid != null ? playerUuid.toString() : null; diff --git a/api/src/main/java/org/btuk/proxy/api/impl/PlayerApiImpl.java b/api/src/main/java/org/btuk/proxy/api/impl/PlayerApiImpl.java index a67946d..dcf0e2e 100644 --- a/api/src/main/java/org/btuk/proxy/api/impl/PlayerApiImpl.java +++ b/api/src/main/java/org/btuk/proxy/api/impl/PlayerApiImpl.java @@ -1,8 +1,10 @@ package org.btuk.proxy.api.impl; +import jakarta.inject.Inject; +import jakarta.ws.rs.Path; import jakarta.ws.rs.core.Response; -import net.bteuk.network.lib.dto.DirectMessage; -import net.bteuk.network.lib.utils.ChatUtils; +import org.btuk.network.lib.dto.DirectMessage; +import org.btuk.network.lib.utils.ChatUtils; import org.btuk.proxy.api.PlayerApi; import org.btuk.proxy.api.model.Message; import org.btuk.proxy.api.model.Player; @@ -14,14 +16,15 @@ import java.util.UUID; import java.util.stream.Collectors; -import static net.bteuk.network.lib.enums.ChatChannels.GLOBAL; +import static org.btuk.network.lib.enums.ChatChannels.GLOBAL; import static org.btuk.proxy.core.utils.Constants.SERVER_SENDER; - +@Path("/player") public class PlayerApiImpl implements PlayerApi { private final GlobalSQL globalSQL; private final ChatManager chatManager; + @Inject public PlayerApiImpl(GlobalSQL globalSQL, ChatManager chatManager) { this.globalSQL = globalSQL;this.chatManager = chatManager; } @@ -63,7 +66,7 @@ public Response sendPlayerMessage(String playerID, Message message){ try { String messagePlainText = message.getMessage(); - DirectMessage m = new DirectMessage(GLOBAL.getChannelName(), playerID.toString(), SERVER_SENDER, ChatUtils.success(messagePlainText), true); + DirectMessage m = new DirectMessage(GLOBAL.getChannelName(), playerID, SERVER_SENDER, ChatUtils.success(messagePlainText), true); chatManager.sendDirectMessage(m); return Response.status(Response.Status.CREATED).build(); }catch (Exception e) diff --git a/api/src/main/java/org/btuk/proxy/api/impl/StatusApiImpl.java b/api/src/main/java/org/btuk/proxy/api/impl/StatusApiImpl.java index 5433870..6326ba6 100644 --- a/api/src/main/java/org/btuk/proxy/api/impl/StatusApiImpl.java +++ b/api/src/main/java/org/btuk/proxy/api/impl/StatusApiImpl.java @@ -1,9 +1,11 @@ package org.btuk.proxy.api.impl; +import jakarta.ws.rs.Path; import jakarta.ws.rs.core.Response; import org.btuk.proxy.api.StatusApi; import org.btuk.proxy.api.model.Status; +@Path("/status") public class StatusApiImpl implements StatusApi { @Override diff --git a/api/src/main/java/org/btuk/proxy/api/server/ProxyApi.java b/api/src/main/java/org/btuk/proxy/api/server/ProxyApi.java index 6feadaa..5723b78 100644 --- a/api/src/main/java/org/btuk/proxy/api/server/ProxyApi.java +++ b/api/src/main/java/org/btuk/proxy/api/server/ProxyApi.java @@ -9,6 +9,7 @@ import org.glassfish.grizzly.http.server.HttpServer; import org.glassfish.jersey.grizzly2.httpserver.GrizzlyHttpServerFactory; +import org.glassfish.jersey.internal.inject.AbstractBinder; import org.glassfish.jersey.server.ResourceConfig; import java.net.URI; @@ -43,10 +44,34 @@ public void start() { String baseUri = "http://0.0.0.0:" + apiPort + "/api/"; - ResourceConfig rc = new ResourceConfig() - .register(new StatusApiImpl()) - .register(new PlayerApiImpl(globalSQL,chatManager)) - .register(new BuildingsApiImpl(globalSQL)); + + ResourceConfig rc = new ResourceConfig(); + + // 1. Disable WADL warning + rc.property("jersey.config.server.wadl.disableWadl", true); + + // 2. Bind SQL and ChatManager dependencies for injection + rc.register(new AbstractBinder() { + @Override + protected void configure() { + bind(globalSQL).to(GlobalSQL.class); + bind(chatManager).to(ChatManager.class); + } + }); + + // 3. Register the implementation CLASSES (or scan the package) + rc.register(StatusApiImpl.class); + rc.register(PlayerApiImpl.class); + rc.register(BuildingsApiImpl.class); + +// ResourceConfig rc = new ResourceConfig() +// .property("jersey.config.server.wadl.disableWadl", true) +// .packages("org.btuk.proxy.api.impl"); + +// ResourceConfig rc = new ResourceConfig() +// .register(new StatusApiImpl()) +// .register(new PlayerApiImpl(globalSQL,chatManager)) +// .register(new BuildingsApiImpl(globalSQL)); try { server = GrizzlyHttpServerFactory.createHttpServer(URI.create(baseUri), rc); diff --git a/api/src/main/resources/openapi.yaml b/api/src/main/resources/openapi.yaml index f3c2dbd..3eb16fe 100644 --- a/api/src/main/resources/openapi.yaml +++ b/api/src/main/resources/openapi.yaml @@ -84,7 +84,7 @@ paths: responses: "201": description: Message Added - /players/online: + /player/online: get: tags: - Player diff --git a/app/pom.xml b/app/pom.xml new file mode 100644 index 0000000..b24d3cf --- /dev/null +++ b/app/pom.xml @@ -0,0 +1,96 @@ + + + 4.0.0 + + org.btuk + Proxy + 1.13.0-SNAPSHOT + + + org.btuk.proxy + app + App + + + 21 + 21 + UTF-8 + + + + + org.btuk.proxy + api + + + org.btuk.proxy + core + + + org.btuk.proxy + database + + + + com.github.BuildtheUK + NetworkLib + + + + org.projectlombok + lombok + + + + org.apache.logging.log4j + log4j-core + provided + + + org.apache.logging.log4j + log4j-slf4j2-impl + provided + + + org.slf4j + jul-to-slf4j + + + + net.dv8tion + JDA + + + + net.kyori + adventure-text-serializer-plain + 4.16.0 + + + net.kyori + adventure-text-minimessage + 4.16.0 + + + + org.yaml + snakeyaml + + + + org.apache.commons + commons-lang3 + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + + + \ No newline at end of file diff --git a/plugin/src/main/java/org/btuk/proxy/ProxyController.java b/app/src/main/java/org.btuk.proxy.app/ProxyController.java similarity index 92% rename from plugin/src/main/java/org/btuk/proxy/ProxyController.java rename to app/src/main/java/org.btuk.proxy.app/ProxyController.java index 698fe0e..b7e9aab 100644 --- a/plugin/src/main/java/org/btuk/proxy/ProxyController.java +++ b/app/src/main/java/org.btuk.proxy.app/ProxyController.java @@ -1,29 +1,12 @@ -package org.btuk.proxy; +package org.btuk.proxy.app; import lombok.Getter; import lombok.extern.java.Log; -import net.bteuk.network.lib.dto.OnlineUserRemove; - -import org.btuk.proxy.core.chat.automod.AutoMod; -import org.btuk.proxy.database.DatabaseInit; -import org.btuk.proxy.database.sql.GlobalSQL; -import org.btuk.proxy.database.sql.PlotSQL; -import org.btuk.proxy.database.sql.RegionSQL; - -import org.slf4j.bridge.SLF4JBridgeHandler; - -import javax.sql.DataSource; -import java.io.File; -import java.io.IOException; -import java.sql.SQLException; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.function.Consumer; - +import org.btuk.network.lib.dto.OnlineUserRemove; import org.btuk.proxy.api.server.ProxyApi; import org.btuk.proxy.core.chat.ChatHandler; import org.btuk.proxy.core.chat.ChatManager; +import org.btuk.proxy.core.chat.automod.AutoMod; import org.btuk.proxy.core.config.Config; import org.btuk.proxy.core.discord.Discord; import org.btuk.proxy.core.discord.ReviewStatus; @@ -38,9 +21,22 @@ import org.btuk.proxy.core.utils.Analytics; import org.btuk.proxy.core.utils.Constants; import org.btuk.proxy.core.utils.Moderation; +import org.btuk.proxy.database.DatabaseInit; +import org.btuk.proxy.database.sql.GlobalSQL; +import org.btuk.proxy.database.sql.PlotSQL; +import org.btuk.proxy.database.sql.RegionSQL; +import org.slf4j.bridge.SLF4JBridgeHandler; + +import javax.sql.DataSource; +import java.io.File; +import java.io.IOException; +import java.sql.SQLException; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.function.Consumer; import static java.awt.Color.RED; -import static org.btuk.proxy.core.utils.Constants.LEAVE_MESSAGE; /** * Controller of the core proxy functionality; can be enabled by the proxy or external plugins that want to use the proxy functions. @@ -102,8 +98,8 @@ public ProxyController(File dataFolder) { this.enabled = true; } - - public void start(ChatHandler chatHandler, Scheduler scheduler, CoreServerManager coreServerManager, PlayerManager playerManager, TabManager tabManager, Consumer socketInitializer) throws IOException { + public void start(ChatHandler chatHandler, Scheduler scheduler, CoreServerManager coreServerManager, PlayerManager playerManager, TabManager tabManager, + Consumer socketInitializer) throws IOException { if (!enabled) { log.severe("Proxy is not enabled, see previous logs for errors."); @@ -119,9 +115,10 @@ public void start(ChatHandler chatHandler, Scheduler scheduler, CoreServerManage Moderation moderation = new Moderation(globalSQL); AutoMod automod = new AutoMod(coreUserManager, new Config(dataFolder, AUTOMOD_CONFIG_NAME), moderation, discord, chatHandler, tabManager); - ChatManager chatManager = new ChatManager(chatHandler, coreUserManager, analytics, globalSQL, moderation, automod); + ChatManager chatManager = new ChatManager(chatHandler, coreUserManager, analytics, globalSQL, moderation, automod, discord); - this.userManager = new UserManager(coreUserManager, chatHandler, tabManager, globalSQL, plotSQL, regionSQL, coreServerManager, scheduler, chatManager, playerManager, analytics, discord, automod); + this.userManager = new UserManager(coreUserManager, chatHandler, tabManager, globalSQL, plotSQL, regionSQL, coreServerManager, scheduler, chatManager, playerManager, + analytics, discord, automod); ServerManager serverManager = new ServerManager(coreServerManager, scheduler, globalSQL, chatHandler, tabManager, coreUserManager, userManager); @@ -129,10 +126,10 @@ public void start(ChatHandler chatHandler, Scheduler scheduler, CoreServerManage new ReviewStatus(config, globalSQL, plotSQL, regionSQL, discord, scheduler); this.discord.addJDAEventListeners(chatManager, coreUserManager, tabManager, plotSQL); - this.proxyApi = new ProxyApi(config.getBoolean("api.enabled"), config.getInt("api.port"), globalSQL,chatManager); + this.proxyApi = new ProxyApi(config.getBoolean("api.enabled"), config.getInt("api.port"), globalSQL, chatManager); serverManager.initOnlineServers(); - socketInitializer.accept(new ProxySocketHandler(chatManager, discord, userManager, serverManager, tabManager)); + socketInitializer.accept(new ProxySocketHandler(chatManager, discord, userManager, serverManager)); proxyApi.start(); @@ -151,7 +148,7 @@ public void stop() { coreUserManager.runForEachOnline(user -> { if (user.isOnline()) { - discord.sendConnectEmbed(LEAVE_MESSAGE, user.getName(), user.getUuid(), user.getPlayerSkin(), RED, (reply) -> { + discord.sendConnectEmbed(Constants.LEAVE_MESSAGE, user.getName(), user.getUuid(), user.getPlayerSkin(), RED, (reply) -> { users.decrementAndGet(); disconnectLatch.countDown(); }); @@ -172,7 +169,7 @@ public void stop() { // Clear JDA listeners if (discord.getJda() != null) { - //Unregister listeners. + // Unregister listeners. discord.getJda().getEventManager().getRegisteredListeners().forEach(listener -> discord.getJda().getEventManager().unregister(listener)); } diff --git a/core/pom.xml b/core/pom.xml index 9f00e77..76da412 100644 --- a/core/pom.xml +++ b/core/pom.xml @@ -26,7 +26,7 @@ - com.github.BTEUK + com.github.BuildtheUK NetworkLib @@ -75,6 +75,11 @@ org.apache.commons commons-lang3 + + org.junit.jupiter + junit-jupiter + test + @@ -82,16 +87,6 @@ org.apache.maven.plugins maven-compiler-plugin - ${maven-compiler-plugin.version} - - - - org.projectlombok - lombok - ${lombok.version} - - - diff --git a/core/src/main/java/org/btuk/proxy/core/chat/ChatHandler.java b/core/src/main/java/org/btuk/proxy/core/chat/ChatHandler.java index 8280fdf..434d042 100644 --- a/core/src/main/java/org/btuk/proxy/core/chat/ChatHandler.java +++ b/core/src/main/java/org/btuk/proxy/core/chat/ChatHandler.java @@ -1,6 +1,6 @@ package org.btuk.proxy.core.chat; -import net.bteuk.network.lib.dto.AbstractTransferObject; +import org.btuk.network.lib.dto.AbstractTransferObject; import org.btuk.proxy.core.exceptions.ServerNotFoundException; diff --git a/core/src/main/java/org/btuk/proxy/core/chat/ChatManager.java b/core/src/main/java/org/btuk/proxy/core/chat/ChatManager.java index 8e99beb..fa64c5f 100644 --- a/core/src/main/java/org/btuk/proxy/core/chat/ChatManager.java +++ b/core/src/main/java/org/btuk/proxy/core/chat/ChatManager.java @@ -1,26 +1,25 @@ package org.btuk.proxy.core.chat; -import net.bteuk.network.lib.dto.ChatMessage; -import net.bteuk.network.lib.dto.DirectMessage; -import net.bteuk.network.lib.dto.PrivateMessage; -import net.bteuk.network.lib.dto.ReplyMessage; -import net.bteuk.network.lib.utils.ChatUtils; - -import org.btuk.proxy.core.chat.automod.AutoMod; -import org.btuk.proxy.database.sql.GlobalSQL; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.format.NamedTextColor; import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer; - -import java.util.List; - +import org.btuk.network.lib.dto.ChatMessage; +import org.btuk.network.lib.dto.DirectMessage; +import org.btuk.network.lib.dto.PrivateMessage; +import org.btuk.network.lib.dto.ReplyMessage; +import org.btuk.network.lib.utils.ChatUtils; +import org.btuk.proxy.core.chat.automod.AutoMod; +import org.btuk.proxy.core.discord.Discord; import org.btuk.proxy.core.user.CoreUserManager; import org.btuk.proxy.core.user.User; import org.btuk.proxy.core.utils.Analytics; import org.btuk.proxy.core.utils.Moderation; import org.btuk.proxy.core.utils.Time; +import org.btuk.proxy.database.sql.GlobalSQL; + +import java.util.List; -import static net.bteuk.network.lib.enums.ChatChannels.GLOBAL; +import static org.btuk.network.lib.enums.ChatChannels.GLOBAL; import static org.btuk.proxy.core.utils.Constants.DISCORD_SENDER; import static org.btuk.proxy.core.utils.Constants.SERVER_SENDER; @@ -41,17 +40,20 @@ public class ChatManager { private final AutoMod autoMod; + private final Discord discord; + private static final List SERVER_USERS = List.of(new String[]{SERVER_SENDER, DISCORD_SENDER}); private static final String FOCUS_ENABLED_PRESET = "%s is in focus mode, unable to send message."; - public ChatManager(ChatHandler chatHandler, CoreUserManager userManager, Analytics analytics, GlobalSQL globalSQL, Moderation moderation, AutoMod autoMod) { + public ChatManager(ChatHandler chatHandler, CoreUserManager userManager, Analytics analytics, GlobalSQL globalSQL, Moderation moderation, AutoMod autoMod, Discord discord) { this.chatHandler = chatHandler; this.userManager = userManager; this.analytics = analytics; this.globalSQL = globalSQL; this.moderation = moderation; this.autoMod = autoMod; + this.discord = discord; } /** @@ -70,6 +72,10 @@ public void handle(ChatMessage chatMessage) { if (player) { analytics.addMessage(chatMessage.getSender(), Time.getDate(Time.currentTime())); } + // Send the message to discord. + if (player) { + discord.handle(chatMessage); + } } /** diff --git a/core/src/main/java/org/btuk/proxy/core/chat/automod/AutoMod.java b/core/src/main/java/org/btuk/proxy/core/chat/automod/AutoMod.java index 00c9d28..2cbd378 100644 --- a/core/src/main/java/org/btuk/proxy/core/chat/automod/AutoMod.java +++ b/core/src/main/java/org/btuk/proxy/core/chat/automod/AutoMod.java @@ -1,16 +1,10 @@ package org.btuk.proxy.core.chat.automod; import lombok.extern.java.Log; -import net.bteuk.network.lib.dto.DirectMessage; -import net.bteuk.network.lib.utils.ChatUtils; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer; - -import java.time.Duration; -import java.util.Collections; -import java.util.List; -import java.util.Map; - +import org.btuk.network.lib.dto.DirectMessage; +import org.btuk.network.lib.utils.ChatUtils; import org.btuk.proxy.core.chat.ChatHandler; import org.btuk.proxy.core.config.Config; import org.btuk.proxy.core.discord.Discord; @@ -20,7 +14,11 @@ import org.btuk.proxy.core.utils.Moderation; import org.btuk.proxy.core.utils.Time; -import static net.bteuk.network.lib.enums.ChatChannels.GLOBAL; +import java.time.Duration; +import java.util.Collections; +import java.util.List; + +import static org.btuk.network.lib.enums.ChatChannels.GLOBAL; import static org.btuk.proxy.core.utils.Constants.SERVER_SENDER; /** @@ -93,7 +91,7 @@ public boolean moderate(String sender, Component messageComponent) { * @return true if the message should be blocked */ private boolean checkMessage(User user, String message) { - Map candidateWords = AutoModRule.getCandidateWords(message); + List candidateWords = AutoModRule.getCandidateWords(message); boolean blockMessage = false; for (AutoModRule rule : autoModConfig.getRules()) { blockMessage |= checkRule(rule, candidateWords, user, message); @@ -123,7 +121,7 @@ private void checkUser(User user) { } } - private boolean checkRule(AutoModRule rule, Map candidateWords, User user, String message) { + private boolean checkRule(AutoModRule rule, List candidateWords, User user, String message) { List matches = rule.getMatches(candidateWords); if (matches.isEmpty()) { return false; diff --git a/core/src/main/java/org/btuk/proxy/core/chat/automod/AutoModRule.java b/core/src/main/java/org/btuk/proxy/core/chat/automod/AutoModRule.java index a69fcd5..3904f04 100644 --- a/core/src/main/java/org/btuk/proxy/core/chat/automod/AutoModRule.java +++ b/core/src/main/java/org/btuk/proxy/core/chat/automod/AutoModRule.java @@ -4,13 +4,13 @@ import java.text.Normalizer; import java.time.Duration; -import java.util.LinkedHashMap; +import java.util.ArrayList; import java.util.List; import java.util.Locale; -import java.util.Map; import java.util.Set; import java.util.regex.Matcher; import java.util.regex.Pattern; +import java.util.stream.Collectors; public abstract class AutoModRule { @@ -26,13 +26,29 @@ public abstract class AutoModRule { @Getter private final Duration duration; + private final int maxLength; + public AutoModRule(String id, List flaggedWords, Duration duration) { + int maxLength = 0; this.id = id; - this.flaggedWords = flaggedWords.stream() - .map(AutoModRule::normalize) - .filter(word -> !word.isBlank()) - .collect(java.util.stream.Collectors.toUnmodifiableSet()); + java.util.Set normalizedSet = new java.util.HashSet<>(); + for (String word : flaggedWords) { + String normalized = normalize(word); + List tokens = new ArrayList<>(); + Matcher matcher = TOKEN_PATTERN.matcher(normalized); + while (matcher.find()) { + tokens.add(matcher.group()); + } + if (tokens.isEmpty()) continue; + + normalizedSet.add(String.join(" ", tokens)); + String joined = String.join("", tokens); + maxLength = Math.max(maxLength, joined.length()); + normalizedSet.add(joined); + } + this.flaggedWords = java.util.Collections.unmodifiableSet(normalizedSet); this.duration = duration; + this.maxLength = maxLength; } public abstract boolean blockMessage(); @@ -40,58 +56,90 @@ public AutoModRule(String id, List flaggedWords, Duration duration) { /** * Matches words against flagged words. * - * @param candidateWords map of candidate words keyed by normalized value + * @param candidateWords list of candidate words in order * @return list of matches */ - public List getMatches(Map candidateWords) { - return candidateWords.values().stream() - .filter(candidateWord -> flaggedWords.contains(candidateWord.normalized())) - .flatMap(candidateWord -> candidateWord.originals().stream() - .map(original -> new AutoModMatch(original, candidateWord.normalized()))) - .toList(); + public List getMatches(List candidateWords) { + List matches = new ArrayList<>(); + int n = candidateWords.size(); + for (int i = 0; i < n; i++) { + // Check single word and phrases up to maxLength tokens. + for (int len = 1; len <= maxLength && i + len <= n; len++) { + List sub = candidateWords.subList(i, i + len); + + // Try joining with spaces + String normalizedPhrase = sub.stream() + .map(CandidateWord::normalized) + .collect(Collectors.joining(" ")); + + if (flaggedWords.contains(normalizedPhrase)) { + String originalPhrase = sub.stream() + .map(CandidateWord::original) + .collect(Collectors.joining(" ")); + matches.add(new AutoModMatch(originalPhrase, normalizedPhrase)); + continue; + } + + // Try joining without spaces to catch things like "b a d" if "bad" is flagged + String noSpacePhrase = sub.stream() + .map(CandidateWord::normalized) + .collect(Collectors.joining("")); + if (flaggedWords.contains(noSpacePhrase)) { + String originalPhrase = sub.stream() + .map(CandidateWord::original) + .collect(Collectors.joining("")); + matches.add(new AutoModMatch(originalPhrase, noSpacePhrase)); + } + } + } + return matches; } /** - * Gets a map of candidate words based on a message. + * Gets a list of candidate words based on a message. * * @param message the message to get candidates for - * @return map of candidate words keyed by normalized value + * @return list of candidate words in order */ - public static LinkedHashMap getCandidateWords(String message) { - LinkedHashMap candidates = new LinkedHashMap<>(); - - Matcher tokenMatcher = TOKEN_PATTERN.matcher(message); - while (tokenMatcher.find()) { - String originalToken = tokenMatcher.group(); - String normalizedToken = normalize(originalToken); - - addCandidate(candidates, normalizedToken, originalToken); - } + public static List getCandidateWords(String message) { + List candidates = new ArrayList<>(); Matcher chunkMatcher = NON_WHITESPACE_PATTERN.matcher(message); while (chunkMatcher.find()) { String originalChunk = chunkMatcher.group(); - - // Plain alphanumeric words are already handled by TOKEN_PATTERN, - // so only process chunks that contain punctuation/symbols. - if (originalChunk.chars().allMatch(Character::isLetterOrDigit)) { - continue; - } - String normalizedChunk = NON_ALPHANUMERIC.matcher(normalize(originalChunk)).replaceAll(""); - addCandidate(candidates, normalizedChunk, originalChunk); - } + if (normalizedChunk.isBlank()) continue; - return candidates; - } + // Try to see if this chunk contains multiple words + Matcher tokenMatcher = TOKEN_PATTERN.matcher(originalChunk); + List subTokens = new ArrayList<>(); + while (tokenMatcher.find()) { + subTokens.add(tokenMatcher.group()); + } - private static void addCandidate(LinkedHashMap candidates, String normalized, String original) { - if (normalized.isBlank() || original.isBlank()) { - return; + if (subTokens.size() > 1) { + // If it contains multi-character tokens, it's likely multiple words (e.g., "bad-word") + if (subTokens.stream().anyMatch(t -> t.length() > 1)) { + for (String sub : subTokens) { + candidates.add(new CandidateWord(normalize(sub), sub)); + } + // Also add the combined version if it's different from simple concatenation + String joinedSub = subTokens.stream().map(AutoModRule::normalize).collect(Collectors.joining("")); + if (!normalizedChunk.equals(joinedSub)) { + candidates.add(new CandidateWord(normalizedChunk, originalChunk)); + } + } else { + // All single letters, likely a single word broken up (e.g., "b.a.d") + candidates.add(new CandidateWord(normalizedChunk, originalChunk)); + } + } else { + // Single token or no sub-tokens (punctuation only) + candidates.add(new CandidateWord(normalizedChunk, originalChunk)); + } } - candidates.computeIfAbsent(normalized, CandidateWord::new).addOriginal(original); + return candidates; } private static String normalize(String input) { diff --git a/core/src/main/java/org/btuk/proxy/core/chat/automod/CandidateWord.java b/core/src/main/java/org/btuk/proxy/core/chat/automod/CandidateWord.java index b57d434..8bb43e3 100644 --- a/core/src/main/java/org/btuk/proxy/core/chat/automod/CandidateWord.java +++ b/core/src/main/java/org/btuk/proxy/core/chat/automod/CandidateWord.java @@ -1,17 +1,4 @@ package org.btuk.proxy.core.chat.automod; -import java.util.ArrayList; -import java.util.LinkedHashSet; -import java.util.List; -import java.util.Set; - -public record CandidateWord(String normalized, List originals) { - - public CandidateWord(String normalized) { - this(normalized, new ArrayList<>()); - } - - public void addOriginal(String original) { - originals.add(original); - } +public record CandidateWord(String normalized, String original) { } \ No newline at end of file diff --git a/core/src/main/java/org/btuk/proxy/core/discord/BotChatListener.java b/core/src/main/java/org/btuk/proxy/core/discord/BotChatListener.java index 87945af..03bbc68 100644 --- a/core/src/main/java/org/btuk/proxy/core/discord/BotChatListener.java +++ b/core/src/main/java/org/btuk/proxy/core/discord/BotChatListener.java @@ -1,16 +1,15 @@ package org.btuk.proxy.core.discord; import lombok.extern.java.Log; -import net.bteuk.network.lib.dto.DiscordLinking; import net.dv8tion.jda.api.entities.channel.ChannelType; import net.dv8tion.jda.api.events.message.MessageReceivedEvent; import net.dv8tion.jda.api.hooks.ListenerAdapter; import org.apache.commons.lang3.StringUtils; +import org.btuk.network.lib.dto.DiscordLinking; +import org.btuk.proxy.core.chat.ChatHandler; import java.util.List; -import org.btuk.proxy.core.chat.ChatHandler; - @Log public class BotChatListener extends ListenerAdapter { diff --git a/core/src/main/java/org/btuk/proxy/core/discord/Discord.java b/core/src/main/java/org/btuk/proxy/core/discord/Discord.java index a435367..afcda52 100644 --- a/core/src/main/java/org/btuk/proxy/core/discord/Discord.java +++ b/core/src/main/java/org/btuk/proxy/core/discord/Discord.java @@ -3,20 +3,15 @@ import lombok.Getter; import lombok.Setter; import lombok.extern.java.Log; -import net.bteuk.network.lib.dto.ChatMessage; -import net.bteuk.network.lib.dto.DiscordDirectMessage; -import net.bteuk.network.lib.dto.DiscordEmbed; -import net.bteuk.network.lib.dto.DiscordLinking; -import net.bteuk.network.lib.dto.DiscordRole; - -import org.btuk.proxy.core.chat.automod.AutoModMatch; -import org.btuk.proxy.core.user.User; -import org.btuk.proxy.database.sql.GlobalSQL; -import org.btuk.proxy.database.sql.PlotSQL; import net.dv8tion.jda.api.EmbedBuilder; import net.dv8tion.jda.api.JDA; import net.dv8tion.jda.api.JDABuilder; -import net.dv8tion.jda.api.entities.*; +import net.dv8tion.jda.api.entities.Activity; +import net.dv8tion.jda.api.entities.Member; +import net.dv8tion.jda.api.entities.Message; +import net.dv8tion.jda.api.entities.MessageEmbed; +import net.dv8tion.jda.api.entities.Role; +import net.dv8tion.jda.api.entities.UserSnowflake; import net.dv8tion.jda.api.entities.channel.concrete.TextChannel; import net.dv8tion.jda.api.requests.GatewayIntent; import net.dv8tion.jda.api.utils.ChunkingFilter; @@ -28,6 +23,22 @@ import net.kyori.adventure.text.format.TextDecoration; import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer; import org.apache.commons.lang3.time.DurationFormatUtils; +import org.btuk.network.lib.dto.ChatMessage; +import org.btuk.network.lib.dto.DiscordDirectMessage; +import org.btuk.network.lib.dto.DiscordEmbed; +import org.btuk.network.lib.dto.DiscordLinking; +import org.btuk.network.lib.dto.DiscordRole; +import org.btuk.proxy.core.chat.ChatHandler; +import org.btuk.proxy.core.chat.ChatManager; +import org.btuk.proxy.core.chat.automod.AutoModMatch; +import org.btuk.proxy.core.config.Config; +import org.btuk.proxy.core.discord.command.CommandManager; +import org.btuk.proxy.core.scheduler.Scheduler; +import org.btuk.proxy.core.tab.TabManager; +import org.btuk.proxy.core.user.CoreUserManager; +import org.btuk.proxy.core.user.User; +import org.btuk.proxy.database.sql.GlobalSQL; +import org.btuk.proxy.database.sql.PlotSQL; import java.awt.Color; import java.nio.charset.StandardCharsets; @@ -39,14 +50,6 @@ import java.util.concurrent.TimeUnit; import java.util.function.Consumer; -import org.btuk.proxy.core.chat.ChatHandler; -import org.btuk.proxy.core.chat.ChatManager; -import org.btuk.proxy.core.config.Config; -import org.btuk.proxy.core.discord.command.CommandManager; -import org.btuk.proxy.core.scheduler.Scheduler; -import org.btuk.proxy.core.tab.TabManager; -import org.btuk.proxy.core.user.CoreUserManager; - @Log public class Discord { @@ -116,7 +119,7 @@ public Discord(Config config, GlobalSQL globalSQL, ChatHandler chatHandler, Sche this.moderatorChat = jda.getTextChannelById(moderatorChannel); //Load all members into cache. - chat.getGuild().loadMembers().onSuccess(members -> { + chat.getGuild().loadMembers().onSuccess(_ -> { log.info("Loaded all discord members into cache"); //Enable role syncing. @@ -132,7 +135,7 @@ public void addJDAEventListeners(ChatManager chatManager, CoreUserManager coreUs jda.addEventListener(new DiscordChatListener(this, chatManager, chatChannelId, staffChannelId)); jda.addEventListener(new BotChatListener(chatHandler, linking)); - CommandManager commandManager = new CommandManager(coreUserManager, tabManager, globalSQL, plotSQL); + CommandManager commandManager = new CommandManager(coreUserManager, tabManager, globalSQL, plotSQL, config); jda.addEventListener(commandManager); jda.getGuilds().forEach(commandManager::registerCommands); } @@ -338,7 +341,7 @@ public void addRole(long userId, long role_id, boolean sync) { if (!member.getRoles().contains(role)) { // If successful, resync if enabled. chat.getGuild().addRoleToMember(member, role).queue( - (user) -> { + _ -> { if (sync && hasRoles != null && giveRoles != null) { syncRoles(); } @@ -368,7 +371,7 @@ public void removeRole(long userId, long role_id, boolean sync) { // If the member does not have the role, add it. if (member.getRoles().contains(role)) { chat.getGuild().removeRoleFromMember(member, role).queue( - (user) -> { + _ -> { if (sync && hasRoles != null && giveRoles != null) { syncRoles(); } diff --git a/core/src/main/java/org/btuk/proxy/core/discord/DiscordChatListener.java b/core/src/main/java/org/btuk/proxy/core/discord/DiscordChatListener.java index 8e075e1..c3673d2 100644 --- a/core/src/main/java/org/btuk/proxy/core/discord/DiscordChatListener.java +++ b/core/src/main/java/org/btuk/proxy/core/discord/DiscordChatListener.java @@ -1,9 +1,6 @@ package org.btuk.proxy.core.discord; import lombok.extern.java.Log; -import net.bteuk.network.lib.dto.ChatMessage; -import net.bteuk.network.lib.enums.ChatChannels; -import net.bteuk.network.lib.utils.ChatUtils; import net.dv8tion.jda.api.events.message.MessageReceivedEvent; import net.dv8tion.jda.api.hooks.ListenerAdapter; import net.kyori.adventure.text.Component; @@ -11,7 +8,9 @@ import net.kyori.adventure.text.format.TextColor; import net.kyori.adventure.text.format.TextDecoration; import org.apache.commons.lang3.StringUtils; - +import org.btuk.network.lib.dto.ChatMessage; +import org.btuk.network.lib.enums.ChatChannels; +import org.btuk.network.lib.utils.ChatUtils; import org.btuk.proxy.core.chat.ChatManager; import static org.btuk.proxy.core.utils.Constants.DISCORD_SENDER; diff --git a/core/src/main/java/org/btuk/proxy/core/discord/command/CommandManager.java b/core/src/main/java/org/btuk/proxy/core/discord/command/CommandManager.java index 54c1fb5..fccf6c1 100644 --- a/core/src/main/java/org/btuk/proxy/core/discord/command/CommandManager.java +++ b/core/src/main/java/org/btuk/proxy/core/discord/command/CommandManager.java @@ -1,8 +1,5 @@ package org.btuk.proxy.core.discord.command; -import org.btuk.proxy.database.sql.GlobalSQL; -import org.btuk.proxy.database.sql.PlotSQL; - import lombok.extern.java.Log; import net.dv8tion.jda.api.entities.Guild; import net.dv8tion.jda.api.events.guild.GuildJoinEvent; @@ -14,14 +11,16 @@ import net.dv8tion.jda.api.interactions.commands.build.CommandData; import net.dv8tion.jda.api.interactions.commands.build.Commands; import net.dv8tion.jda.api.interactions.commands.build.OptionData; +import org.btuk.proxy.core.config.Config; +import org.btuk.proxy.core.tab.TabManager; +import org.btuk.proxy.core.user.CoreUserManager; +import org.btuk.proxy.database.sql.GlobalSQL; +import org.btuk.proxy.database.sql.PlotSQL; import org.jetbrains.annotations.NotNull; import java.util.ArrayList; import java.util.List; -import org.btuk.proxy.core.tab.TabManager; -import org.btuk.proxy.core.user.CoreUserManager; - /** * Manages all Discord commands. * Each command is stored in a map so when a command interaction is run it can be routed accordingly. @@ -39,11 +38,14 @@ public class CommandManager extends ListenerAdapter { private final PlotSQL plotSQL; - public CommandManager(CoreUserManager userManager, TabManager tabManager, GlobalSQL globalSQL, PlotSQL plotSQL) { + private final Config config; + + public CommandManager(CoreUserManager userManager, TabManager tabManager, GlobalSQL globalSQL, PlotSQL plotSQL, Config config) { this.userManager = userManager; this.tabManager = tabManager; this.globalSQL = globalSQL; this.plotSQL = plotSQL; + this.config = config; commands = new ArrayList<>(); } @@ -97,7 +99,17 @@ public void registerCommands(Guild guild) { //Create commands. commands.add(new Playerlist(userManager, tabManager, "playerlist", "List all online players on the Minecraft server.")); - //commands.add(new Map("map", "Sends a link to the UK progress map.")); // The progress map is no longer available. + String progressMap = config.getString("progress_map"); + if (progressMap != null && !progressMap.isBlank()) { + commands.add(new Map("map", "Sends a link to the UK progress map.", progressMap)); + commands.add(new Map("progress", "Sends a link to the UK progress map.", progressMap)); + commands.add(new Map("progressmap", "Sends a link to the UK progress map.", progressMap)); + } + + String websiteLink = config.getString("website"); + if (websiteLink != null && !websiteLink.isBlank()) { + commands.add(new Website("website", "Sends a link of the website", websiteLink)); + } commands.add(new ClaimedPlots(globalSQL, plotSQL, "claimedplots", "List all plots that are currently claimed.", playerOption)); commands.add(new SubmittedPlots(globalSQL, plotSQL, "submittedplots", "List all plots that are currently submitted.", playerOption)); diff --git a/core/src/main/java/org/btuk/proxy/core/discord/command/Map.java b/core/src/main/java/org/btuk/proxy/core/discord/command/Map.java index 9d23928..7c0d58a 100644 --- a/core/src/main/java/org/btuk/proxy/core/discord/command/Map.java +++ b/core/src/main/java/org/btuk/proxy/core/discord/command/Map.java @@ -1,29 +1,27 @@ -//package org.btuk.proxy.core.discord.command; -// -//import org.btuk.proxy.Proxy; -//import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent; -//import net.dv8tion.jda.api.requests.restaction.interactions.ReplyCallbackAction; -// -//public class Map extends AbstractCommand { -// -// /** -// * Constructor, saved the name and description of the command. -// * Also registers the command in Discord. -// * @param name Name of the command -// * @param description Description of the command -// */ -// public Map(String name, String description) { -// super(name, description); -// } -// -// @Override -// public void onCommand(SlashCommandInteractionEvent event) { -// -// String playerListMessage = Proxy.getInstance().getConfig().getString("progress_map"); -// -// ReplyCallbackAction reply = event.reply(playerListMessage); -// reply = reply.setEphemeral(true); -// reply.queue(); -// -// } -//} \ No newline at end of file +package org.btuk.proxy.core.discord.command; + +import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent; +import net.dv8tion.jda.api.requests.restaction.interactions.ReplyCallbackAction; + +public class Map extends AbstractCommand { + + private final String link; + + /** + * Constructor, saved the name and description of the command. + * Also registers the command in Discord. + * @param name Name of the command + * @param description Description of the command + */ + public Map(String name, String description, String link) { + super(name, description); + this.link = link; + } + + @Override + public void onCommand(SlashCommandInteractionEvent event) { + ReplyCallbackAction reply = event.reply(link); + reply = reply.setEphemeral(true); + reply.queue(); + } +} \ No newline at end of file diff --git a/core/src/main/java/org/btuk/proxy/core/discord/command/Playerlist.java b/core/src/main/java/org/btuk/proxy/core/discord/command/Playerlist.java index e1eef47..2004a8f 100644 --- a/core/src/main/java/org/btuk/proxy/core/discord/command/Playerlist.java +++ b/core/src/main/java/org/btuk/proxy/core/discord/command/Playerlist.java @@ -1,20 +1,19 @@ package org.btuk.proxy.core.discord.command; -import net.bteuk.network.lib.dto.OnlineUser; -import net.bteuk.network.lib.dto.TabPlayer; import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent; import net.dv8tion.jda.api.requests.restaction.interactions.ReplyCallbackAction; import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer; +import org.btuk.network.lib.dto.OnlineUser; +import org.btuk.network.lib.dto.TabPlayer; +import org.btuk.proxy.core.tab.TabManager; +import org.btuk.proxy.core.user.CoreUserManager; +import org.btuk.proxy.core.user.User; import java.util.ArrayList; import java.util.Comparator; import java.util.Optional; import java.util.Set; -import org.btuk.proxy.core.tab.TabManager; -import org.btuk.proxy.core.user.CoreUserManager; -import org.btuk.proxy.core.user.User; - public class Playerlist extends AbstractCommand { private final CoreUserManager userManager; diff --git a/core/src/main/java/org/btuk/proxy/core/discord/command/Website.java b/core/src/main/java/org/btuk/proxy/core/discord/command/Website.java new file mode 100644 index 0000000..098552f --- /dev/null +++ b/core/src/main/java/org/btuk/proxy/core/discord/command/Website.java @@ -0,0 +1,27 @@ +package org.btuk.proxy.core.discord.command; + +import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent; +import net.dv8tion.jda.api.requests.restaction.interactions.ReplyCallbackAction; + +public class Website extends AbstractCommand { + + private final String link; + + /** + * Constructor, saved the name and description of the command. + * Also registers the command in Discord. + * @param name Name of the command + * @param description Description of the command + */ + public Website(String name, String description, String link) { + super(name, description); + this.link = link; + } + + @Override + public void onCommand(SlashCommandInteractionEvent event) { + ReplyCallbackAction reply = event.reply(link); + reply = reply.setEphemeral(true); + reply.queue(); + } +} \ No newline at end of file diff --git a/core/src/main/java/org/btuk/proxy/core/server/ServerManager.java b/core/src/main/java/org/btuk/proxy/core/server/ServerManager.java index e072d55..00986e6 100644 --- a/core/src/main/java/org/btuk/proxy/core/server/ServerManager.java +++ b/core/src/main/java/org/btuk/proxy/core/server/ServerManager.java @@ -1,18 +1,11 @@ package org.btuk.proxy.core.server; import lombok.extern.java.Log; -import net.bteuk.network.lib.dto.OnlineUserRemove; -import net.bteuk.network.lib.dto.OnlineUsersReply; -import net.bteuk.network.lib.dto.ServerShutdown; -import net.bteuk.network.lib.dto.ServerStartup; -import org.btuk.proxy.database.sql.GlobalSQL; - -import java.util.List; -import java.util.Optional; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.TimeUnit; +import org.btuk.network.lib.dto.OnlineUserRemove; +import org.btuk.network.lib.dto.OnlineUsersReply; +import org.btuk.network.lib.dto.ServerShutdown; +import org.btuk.network.lib.dto.ServerStartup; import org.btuk.proxy.core.chat.ChatHandler; import org.btuk.proxy.core.scheduler.Scheduler; import org.btuk.proxy.core.tab.TabManager; @@ -20,12 +13,18 @@ import org.btuk.proxy.core.user.User; import org.btuk.proxy.core.user.UserManager; import org.btuk.proxy.core.utils.Time; +import org.btuk.proxy.database.sql.GlobalSQL; + +import java.util.List; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.TimeUnit; @Log public class ServerManager { private final CoreServerManager coreServerManager; - + private final Scheduler scheduler; private final GlobalSQL globalSQL; private final ChatHandler chatHandler; @@ -40,6 +39,7 @@ public class ServerManager { public ServerManager(CoreServerManager coreServerManager, Scheduler scheduler, GlobalSQL globalSQL, ChatHandler chatHandler, TabManager tabManager, CoreUserManager coreUserManager, UserManager userManager) { this.coreServerManager = coreServerManager; + this.scheduler = scheduler; this.globalSQL = globalSQL; this.chatHandler = chatHandler; this.tabManager = tabManager; @@ -58,30 +58,30 @@ public void initOnlineServers() { } public void addServer(ServerStartup serverStartup) { - // It is possible the server is already set to online, this probably means it crashed, - // first clear all players that are 'connected' to this server and remove them. - Optional optionalServer = coreServerManager.getServers().stream().filter(server -> server.getName().equals(serverStartup.getServerName())).findFirst(); - optionalServer.ifPresent(this::removeServerDueToTimeout); + String serverName = serverStartup.getServerName(); + // It is possible the server was already set to online, this probably means it crashed. + // Even if the server is not currently tracked, there might be 'ghost' players. + cleanupServer(serverName); try { - Server server = coreServerManager.createServer(serverStartup.getServerName()); + Server server = coreServerManager.createServer(serverName); threadExecutor.submit(() -> addServerIfOnline(server)); } catch (RuntimeException e) { - log.warning("Unable to add server " + serverStartup.getServerName() + ", it can not be found."); + log.warning("Unable to add server " + serverName + ", it can not be found."); } } public void removeServer(ServerShutdown serverShutdown) { - Optional optionalServer = coreServerManager.getServers().stream().filter(server -> server.getName().equals(serverShutdown.getServerName())).findFirst(); - optionalServer.ifPresent(coreServerManager::removeServer); - - // Set the server offline in the database. - globalSQL.update("UPDATE server_data SET online=0 WHERE name='" + serverShutdown.getServerName() + "';"); + cleanupServer(serverShutdown.getServerName()); } private void addServerIfOnline(Server server) { + addServerIfOnline(server, 0); + } + + private void addServerIfOnline(Server server, int attempt) { // Skip if the server is already added. - if (coreServerManager.getServers().stream().anyMatch(server::equals)) { + if (coreServerManager.getServers().stream().anyMatch(s -> s.getName().equals(server.getName()))) { return; } if (server.canPing()) { @@ -95,34 +95,48 @@ private void addServerIfOnline(Server server) { tabManager.sendAddTeam(); } else { // The server is not online. - log.warning(String.format("Server " + server.getName() + " is not online.")); + if (attempt < 30) { + scheduler.createDelayedTask(() -> threadExecutor.submit(() -> addServerIfOnline(server, attempt + 1)), 1, TimeUnit.SECONDS); + } else { + log.warning(String.format("Server " + server.getName() + " is not online.")); + } } } private void pingServers() { coreServerManager.getServers().forEach(server -> threadExecutor.submit(() -> updatePing(server))); - // If any server has a ping of more than 120 seconds, set the server to offline and remove all online players that were connected to the server. + // If any server has a ping of more than 60 seconds, set the server to offline and remove all online players that were connected to the server. // This probably means the server crashed. - List offlineServers = coreServerManager.getServers().stream().filter(server -> server.getLastPing() < Time.currentTime() - 1000 * 120).toList(); + List offlineServers = coreServerManager.getServers().stream().filter(server -> server.getLastPing() < Time.currentTime() - 1000 * 60).toList(); offlineServers.forEach(this::removeServerDueToTimeout); } - private void removeServerDueToTimeout(Server server) { + private void cleanupServer(String serverName) { // Set the server offline in the database. - globalSQL.update("UPDATE server_data SET online=0 WHERE name='" + server.getName() + "';"); + globalSQL.update("UPDATE server_data SET online=0 WHERE name='" + serverName + "';"); - // Remove all users connected to this server, + // Remove all users connected to this server // and also send a message to all other online servers to remove these users from their list. - List offlineServerUsers = coreUserManager.getUsersOnServer(server.getName()); - offlineServerUsers.forEach(user -> { - OnlineUserRemove onlineUserRemove = new OnlineUserRemove(user.getUuid()); - chatHandler.handle(onlineUserRemove); - userManager.disconnectUser(user); - } - ); + // Delay this by a second so the switch server events have time to be processed. + scheduler.createDelayedTask(() -> { + List offlineServerUsers = coreUserManager.getUsersOnServer(serverName); + offlineServerUsers.forEach(user -> { + if (user.getSwitchServer() != null && user.getSwitchServer().getFromServer().equals(serverName)) { + log.info("User " + user.getName() + " is switching servers on shutdown."); + } else { + OnlineUserRemove onlineUserRemove = new OnlineUserRemove(user.getUuid()); + chatHandler.handle(onlineUserRemove); + userManager.disconnectUser(user); + } + }); + }, 1, TimeUnit.SECONDS); + + // Remove server from the list if it exists. + coreServerManager.getServer(serverName).ifPresent(coreServerManager::removeServer); + } - // Remove server from the list. - coreServerManager.removeServer(server); + private void removeServerDueToTimeout(Server server) { + cleanupServer(server.getName()); } private void updatePing(Server server) { diff --git a/core/src/main/java/org/btuk/proxy/core/socket/ProxySocketHandler.java b/core/src/main/java/org/btuk/proxy/core/socket/ProxySocketHandler.java index c59fe66..0324333 100644 --- a/core/src/main/java/org/btuk/proxy/core/socket/ProxySocketHandler.java +++ b/core/src/main/java/org/btuk/proxy/core/socket/ProxySocketHandler.java @@ -1,13 +1,30 @@ package org.btuk.proxy.core.socket; import lombok.extern.java.Log; -import net.bteuk.network.lib.dto.*; -import net.bteuk.network.lib.socket.SocketHandler; - +import org.btuk.network.lib.dto.AbstractTransferObject; +import org.btuk.network.lib.dto.ChatMessage; +import org.btuk.network.lib.dto.DirectMessage; +import org.btuk.network.lib.dto.DiscordDirectMessage; +import org.btuk.network.lib.dto.DiscordEmbed; +import org.btuk.network.lib.dto.DiscordLinking; +import org.btuk.network.lib.dto.DiscordRole; +import org.btuk.network.lib.dto.FocusEvent; +import org.btuk.network.lib.dto.ModerationEvent; +import org.btuk.network.lib.dto.MuteEvent; +import org.btuk.network.lib.dto.PlotMessage; +import org.btuk.network.lib.dto.PrivateMessage; +import org.btuk.network.lib.dto.ReplyMessage; +import org.btuk.network.lib.dto.ServerShutdown; +import org.btuk.network.lib.dto.ServerStartup; +import org.btuk.network.lib.dto.SwitchServerEvent; +import org.btuk.network.lib.dto.TeleportEvent; +import org.btuk.network.lib.dto.UserConnectRequest; +import org.btuk.network.lib.dto.UserDisconnect; +import org.btuk.network.lib.dto.UserUpdate; +import org.btuk.network.lib.socket.SocketHandler; import org.btuk.proxy.core.chat.ChatManager; import org.btuk.proxy.core.discord.Discord; import org.btuk.proxy.core.server.ServerManager; -import org.btuk.proxy.core.tab.TabManager; import org.btuk.proxy.core.user.UserManager; @Log @@ -17,14 +34,12 @@ public class ProxySocketHandler implements SocketHandler { private final Discord discord; private final UserManager userManager; private final ServerManager serverManager; - private final TabManager tabManager; - public ProxySocketHandler(ChatManager chatManager, Discord discord, UserManager userManager, ServerManager serverManager, TabManager tabManager) { + public ProxySocketHandler(ChatManager chatManager, Discord discord, UserManager userManager, ServerManager serverManager) { this.chatManager = chatManager; this.discord = discord; this.userManager = userManager; this.serverManager = serverManager; - this.tabManager = tabManager; } @Override @@ -33,7 +48,6 @@ public synchronized AbstractTransferObject handle(AbstractTransferObject abstrac switch (abstractTransferObject) { case ChatMessage chatMessage -> { chatManager.handle(chatMessage); - discord.handle(chatMessage); } case DirectMessage directMessage -> chatManager.handle(directMessage); case PrivateMessage privateMessage -> chatManager.handle(privateMessage); diff --git a/core/src/main/java/org/btuk/proxy/core/tab/AbstractTabManager.java b/core/src/main/java/org/btuk/proxy/core/tab/AbstractTabManager.java index 125ff8e..d1ab730 100644 --- a/core/src/main/java/org/btuk/proxy/core/tab/AbstractTabManager.java +++ b/core/src/main/java/org/btuk/proxy/core/tab/AbstractTabManager.java @@ -1,14 +1,20 @@ package org.btuk.proxy.core.tab; import lombok.Getter; -import net.bteuk.network.lib.dto.AddTeamEvent; -import net.bteuk.network.lib.dto.TabPlayer; -import net.bteuk.network.lib.utils.ChatUtils; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.format.NamedTextColor; import net.kyori.adventure.text.format.Style; import net.kyori.adventure.text.format.TextDecoration; import net.kyori.adventure.text.minimessage.MiniMessage; +import org.btuk.network.lib.dto.AddTeamEvent; +import org.btuk.network.lib.dto.TabPlayer; +import org.btuk.network.lib.utils.ChatUtils; +import org.btuk.proxy.core.chat.ChatHandler; +import org.btuk.proxy.core.config.Config; +import org.btuk.proxy.core.player.Player; +import org.btuk.proxy.core.scheduler.Scheduler; +import org.btuk.proxy.core.user.CoreUserManager; +import org.btuk.proxy.core.user.User; import org.jetbrains.annotations.Nullable; import java.util.HashSet; @@ -17,13 +23,6 @@ import java.util.Set; import java.util.concurrent.TimeUnit; -import org.btuk.proxy.core.chat.ChatHandler; -import org.btuk.proxy.core.config.Config; -import org.btuk.proxy.core.player.Player; -import org.btuk.proxy.core.scheduler.Scheduler; -import org.btuk.proxy.core.user.CoreUserManager; -import org.btuk.proxy.core.user.User; - public abstract class AbstractTabManager implements TabManager { private final Config config; diff --git a/core/src/main/java/org/btuk/proxy/core/tab/TabManager.java b/core/src/main/java/org/btuk/proxy/core/tab/TabManager.java index c50ef3a..b552bb6 100644 --- a/core/src/main/java/org/btuk/proxy/core/tab/TabManager.java +++ b/core/src/main/java/org/btuk/proxy/core/tab/TabManager.java @@ -1,11 +1,10 @@ package org.btuk.proxy.core.tab; -import net.bteuk.network.lib.dto.TabPlayer; +import org.btuk.network.lib.dto.TabPlayer; +import org.btuk.proxy.core.user.User; import java.util.Optional; -import org.btuk.proxy.core.user.User; - public interface TabManager { void updatePlayerInTablistOfPlayer(User user, User userToUpdate); diff --git a/core/src/main/java/org/btuk/proxy/core/user/CoreUserManager.java b/core/src/main/java/org/btuk/proxy/core/user/CoreUserManager.java index 1145525..b8b13c2 100644 --- a/core/src/main/java/org/btuk/proxy/core/user/CoreUserManager.java +++ b/core/src/main/java/org/btuk/proxy/core/user/CoreUserManager.java @@ -1,6 +1,6 @@ package org.btuk.proxy.core.user; -import net.bteuk.network.lib.dto.OnlineUser; +import org.btuk.network.lib.dto.OnlineUser; import java.util.ArrayList; import java.util.Collections; diff --git a/core/src/main/java/org/btuk/proxy/core/user/User.java b/core/src/main/java/org/btuk/proxy/core/user/User.java index 7b39b29..eb3fa63 100644 --- a/core/src/main/java/org/btuk/proxy/core/user/User.java +++ b/core/src/main/java/org/btuk/proxy/core/user/User.java @@ -5,30 +5,37 @@ import lombok.Getter; import lombok.Setter; import lombok.extern.java.Log; -import net.bteuk.network.lib.dto.DirectMessage; -import net.bteuk.network.lib.dto.TeleportEvent; -import net.bteuk.network.lib.dto.UserConnectReply; -import net.bteuk.network.lib.dto.UserConnectRequest; -import net.bteuk.network.lib.enums.ChatChannels; -import net.bteuk.network.lib.enums.TeleportRequestType; -import net.bteuk.network.lib.utils.ChatUtils; - -import org.btuk.proxy.core.exceptions.ServerNotFoundException; -import org.btuk.proxy.core.utils.TeleportRequest; - +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.format.NamedTextColor; +import net.kyori.adventure.text.format.Style; +import net.kyori.adventure.text.format.TextDecoration; +import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer; +import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer; +import org.btuk.network.lib.dto.DirectMessage; +import org.btuk.network.lib.dto.TeleportEvent; +import org.btuk.network.lib.dto.UserConnectReply; +import org.btuk.network.lib.dto.UserConnectRequest; +import org.btuk.network.lib.enums.ChatChannels; +import org.btuk.network.lib.enums.TeleportRequestType; +import org.btuk.network.lib.utils.ChatUtils; +import org.btuk.proxy.core.chat.ChatHandler; import org.btuk.proxy.core.chat.automod.AutoMod; import org.btuk.proxy.core.chat.automod.AutoModFlag; import org.btuk.proxy.core.chat.automod.AutoModFlagRule; import org.btuk.proxy.core.chat.automod.AutoModMatch; import org.btuk.proxy.core.chat.automod.AutoModRule; +import org.btuk.proxy.core.exceptions.ServerNotFoundException; +import org.btuk.proxy.core.player.Player; +import org.btuk.proxy.core.scheduler.ScheduledTask; +import org.btuk.proxy.core.scheduler.Scheduler; +import org.btuk.proxy.core.scheduler.TaskStatus; +import org.btuk.proxy.core.tab.TabManager; +import org.btuk.proxy.core.utils.Analytics; +import org.btuk.proxy.core.utils.SwitchServer; +import org.btuk.proxy.core.utils.TeleportRequest; +import org.btuk.proxy.core.utils.Time; import org.btuk.proxy.database.dto.AutoModFlagDTO; import org.btuk.proxy.database.sql.GlobalSQL; -import net.kyori.adventure.text.Component; -import net.kyori.adventure.text.format.NamedTextColor; -import net.kyori.adventure.text.format.Style; -import net.kyori.adventure.text.format.TextDecoration; -import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer; -import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer; import java.io.IOException; import java.net.HttpURLConnection; @@ -47,16 +54,6 @@ import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; -import org.btuk.proxy.core.chat.ChatHandler; -import org.btuk.proxy.core.player.Player; -import org.btuk.proxy.core.scheduler.ScheduledTask; -import org.btuk.proxy.core.scheduler.Scheduler; -import org.btuk.proxy.core.scheduler.TaskStatus; -import org.btuk.proxy.core.tab.TabManager; -import org.btuk.proxy.core.utils.Analytics; -import org.btuk.proxy.core.utils.SwitchServer; -import org.btuk.proxy.core.utils.Time; - import static org.btuk.proxy.core.utils.Constants.SERVER_SENDER; /** @@ -135,10 +132,6 @@ public class User { @Getter private boolean focusEnabled; - @Getter - @Setter - private boolean blockNextDisconnect = false; - @Getter @Setter private int previousPlotSubmissionCount = 0; @@ -243,6 +236,10 @@ public void reconnect() { online = true; // Can't be afk on reconnect. afk = false; + cancelDisconnectTask(); + } + + public void cancelDisconnectTask() { if (disconnectTask != null && disconnectTask.getStatus() == TaskStatus.SCHEDULED) { disconnectTask.cancel(); } @@ -253,10 +250,7 @@ public void reconnect() { * Delete the user instance. */ public void delete() { - // If the disconnectTask is running cancel. - if (disconnectTask != null && disconnectTask.getStatus() == TaskStatus.SCHEDULED) { - disconnectTask.cancel(); - } + cancelDisconnectTask(); } public void mute(User user) { diff --git a/core/src/main/java/org/btuk/proxy/core/user/UserManager.java b/core/src/main/java/org/btuk/proxy/core/user/UserManager.java index 4f8c9ae..a2ac078 100644 --- a/core/src/main/java/org/btuk/proxy/core/user/UserManager.java +++ b/core/src/main/java/org/btuk/proxy/core/user/UserManager.java @@ -2,37 +2,55 @@ import lombok.Getter; import lombok.extern.java.Log; -import net.bteuk.network.lib.dto.*; -import net.bteuk.network.lib.enums.ChatChannels; -import net.bteuk.network.lib.enums.ModerationAction; -import net.bteuk.network.lib.enums.TeleportRequestType; -import net.bteuk.network.lib.utils.ChatUtils; -import org.btuk.proxy.database.sql.GlobalSQL; -import org.btuk.proxy.database.sql.PlotSQL; -import org.btuk.proxy.database.sql.RegionSQL; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.format.NamedTextColor; - -import java.awt.Color; -import java.util.*; -import java.util.concurrent.TimeUnit; - -import org.btuk.proxy.core.chat.automod.AutoMod; -import org.btuk.proxy.core.discord.Discord; -import org.btuk.proxy.core.tab.TabManager; +import org.btuk.network.lib.dto.ChatMessage; +import org.btuk.network.lib.dto.DirectMessage; +import org.btuk.network.lib.dto.FocusEvent; +import org.btuk.network.lib.dto.ModerationEvent; +import org.btuk.network.lib.dto.MuteEvent; +import org.btuk.network.lib.dto.OnlineUser; +import org.btuk.network.lib.dto.OnlineUserAdd; +import org.btuk.network.lib.dto.OnlineUserRemove; +import org.btuk.network.lib.dto.PlotMessage; +import org.btuk.network.lib.dto.SwitchServerEvent; +import org.btuk.network.lib.dto.TeleportEvent; +import org.btuk.network.lib.dto.UserConnectReply; +import org.btuk.network.lib.dto.UserConnectRequest; +import org.btuk.network.lib.dto.UserDisconnect; +import org.btuk.network.lib.dto.UserRemove; +import org.btuk.network.lib.dto.UserUpdate; +import org.btuk.network.lib.enums.ChatChannels; +import org.btuk.network.lib.enums.ModerationAction; +import org.btuk.network.lib.enums.TeleportRequestType; +import org.btuk.network.lib.utils.ChatUtils; import org.btuk.proxy.core.chat.ChatHandler; import org.btuk.proxy.core.chat.ChatManager; +import org.btuk.proxy.core.chat.automod.AutoMod; +import org.btuk.proxy.core.discord.Discord; import org.btuk.proxy.core.exceptions.ErrorMessage; import org.btuk.proxy.core.exceptions.ServerNotFoundException; import org.btuk.proxy.core.player.PlayerManager; import org.btuk.proxy.core.scheduler.Scheduler; import org.btuk.proxy.core.server.CoreServerManager; +import org.btuk.proxy.core.tab.TabManager; import org.btuk.proxy.core.utils.Analytics; import org.btuk.proxy.core.utils.SwitchServer; import org.btuk.proxy.core.utils.Time; +import org.btuk.proxy.database.sql.GlobalSQL; +import org.btuk.proxy.database.sql.PlotSQL; +import org.btuk.proxy.database.sql.RegionSQL; -import static net.bteuk.network.lib.enums.ChatChannels.GLOBAL; -import static org.btuk.proxy.core.utils.Constants.*; +import java.awt.Color; +import java.util.Optional; +import java.util.concurrent.TimeUnit; + +import static org.btuk.network.lib.enums.ChatChannels.GLOBAL; +import static org.btuk.proxy.core.utils.Constants.JOIN_MESSAGE; +import static org.btuk.proxy.core.utils.Constants.LEAVE_MESSAGE; +import static org.btuk.proxy.core.utils.Constants.RECONNECT_MESSAGE; +import static org.btuk.proxy.core.utils.Constants.SERVER_SENDER; +import static org.btuk.proxy.core.utils.Constants.WELCOME_MESSAGE; /** * Class to manage the users on the network. @@ -113,9 +131,9 @@ public void handleUserDisconnect(UserDisconnect disconnect) { return; } - if (user.isBlockNextDisconnect()) { - log.warning("User has already reconnected, cancelling disconnect."); - user.setBlockNextDisconnect(false); + // If the player is not on the server they disconnected from, it implies they switched server. + if (!user.getServer().equals(disconnect.getServer())) { + log.warning("User disconnect received but they are on a different server, cancelling disconnect."); return; } @@ -271,11 +289,8 @@ public User addUser(UserConnectRequest request) { switchServer.cancelTimeout(); user.setSwitchServer(null); + user.cancelDisconnectTask(); } else { - // If the user is still online, quickly cancel the disconnect event. - if (user.isOnline()) { - user.setBlockNextDisconnect(true); - } // Cancel disconnect task. user.reconnect(); diff --git a/core/src/main/java/org/btuk/proxy/core/utils/SwitchServer.java b/core/src/main/java/org/btuk/proxy/core/utils/SwitchServer.java index 20049d3..176ba56 100644 --- a/core/src/main/java/org/btuk/proxy/core/utils/SwitchServer.java +++ b/core/src/main/java/org/btuk/proxy/core/utils/SwitchServer.java @@ -29,6 +29,7 @@ public class SwitchServer { private final User user; + @Getter private final String fromServer; @Getter diff --git a/core/src/main/resources/proxy-config.yml b/core/src/main/resources/proxy-config.yml index ad24a34..0350500 100644 --- a/core/src/main/resources/proxy-config.yml +++ b/core/src/main/resources/proxy-config.yml @@ -1,5 +1,5 @@ #Config version (do not update) -version: "1.12.0-SNAPSHOT" +version: "1.13.0-SNAPSHOT" #Bot token token: "insert token here" @@ -86,4 +86,7 @@ tab: footer: "\nServer Info: /help\nMore Info: /discord" #Discord user activity playing status (your server name or IP) -DiscordPlaying: "server.net" \ No newline at end of file +DiscordPlaying: "server.net" + +progress_map: "https://progress.buildtheuk.org" +website: "https://btuk.org" \ No newline at end of file diff --git a/core/src/test/java/org/btuk/proxy/core/chat/automod/AutoModRuleTest.java b/core/src/test/java/org/btuk/proxy/core/chat/automod/AutoModRuleTest.java new file mode 100644 index 0000000..beaa868 --- /dev/null +++ b/core/src/test/java/org/btuk/proxy/core/chat/automod/AutoModRuleTest.java @@ -0,0 +1,59 @@ +package org.btuk.proxy.core.chat.automod; + +import org.junit.jupiter.api.Test; + +import java.time.Duration; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + +class AutoModRuleTest { + + @Test + void testTooBadMatch() { + AutoModRule rule = new AutoModFlagRule("test", List.of("too bad"), 1, Duration.ZERO, true); + List candidates = AutoModRule.getCandidateWords("this is too bad"); + List matches = rule.getMatches(candidates); + assertFalse(matches.isEmpty(), "Should match 'too bad'"); + assertEquals("too bad", matches.getFirst().flaggedWord()); + assertEquals("too bad", matches.getFirst().messageWord()); + } + + @Test + void testTooBadLeetspeakMatch() { + AutoModRule rule = new AutoModFlagRule("test", List.of("too bad"), 1, Duration.ZERO, true); + List candidates = AutoModRule.getCandidateWords("this is t00 b.a.d"); + List matches = rule.getMatches(candidates); + assertFalse(matches.isEmpty(), "Should match 't00 b.a.d' against 'too bad'"); + assertEquals("too bad", matches.getFirst().flaggedWord()); + } + + @Test + void testPunctuationInFlaggedWord() { + // Test case where flagged word has punctuation + AutoModRule rule = new AutoModFlagRule("test", List.of("bad-word"), 1, Duration.ZERO, true); + List candidates = AutoModRule.getCandidateWords("you are a bad-word"); + List matches = rule.getMatches(candidates); + + assertFalse(matches.isEmpty(), "Should match 'bad-word' even if flagged as 'bad-word'"); + assertTrue(matches.stream().anyMatch(m -> m.flaggedWord().equals("badword") || m.flaggedWord().equals("bad word"))); + } + + @Test + void testDoubleSpaceInMessage() { + AutoModRule rule = new AutoModFlagRule("test", List.of("too bad"), 1, Duration.ZERO, true); + List candidates = AutoModRule.getCandidateWords("this is too bad"); + List matches = rule.getMatches(candidates); + assertFalse(matches.isEmpty(), "Should match 'too bad' (double space) against 'too bad'"); + } + + @Test + void testMixedPunctuationAndLeetspeak() { + AutoModRule rule = new AutoModFlagRule("test", List.of("bad word"), 1, Duration.ZERO, true); + List candidates = AutoModRule.getCandidateWords("you are b.a.d-w.0.r.d"); + List matches = rule.getMatches(candidates); + assertFalse(matches.isEmpty(), "Should match 'b.a.d-w.0.r.d' against 'bad word'"); + } +} diff --git a/database/pom.xml b/database/pom.xml index 7ef8e1d..e73de01 100644 --- a/database/pom.xml +++ b/database/pom.xml @@ -13,7 +13,7 @@ - com.github.BTEUK + com.github.BuildtheUK NetworkLib @@ -42,16 +42,6 @@ org.apache.maven.plugins maven-compiler-plugin - ${maven-compiler-plugin.version} - - - - org.projectlombok - lombok - ${lombok.version} - - - diff --git a/database/src/main/java/org/btuk/proxy/database/sql/PlotSQL.java b/database/src/main/java/org/btuk/proxy/database/sql/PlotSQL.java index 2274dbd..a277f92 100644 --- a/database/src/main/java/org/btuk/proxy/database/sql/PlotSQL.java +++ b/database/src/main/java/org/btuk/proxy/database/sql/PlotSQL.java @@ -1,8 +1,8 @@ package org.btuk.proxy.database.sql; import lombok.extern.java.Log; -import net.bteuk.network.lib.enums.PlotDifficulties; -import net.bteuk.network.lib.utils.Reviewing; +import org.btuk.network.lib.enums.PlotDifficulties; +import org.btuk.network.lib.utils.Reviewing; import org.btuk.proxy.database.sql.migration.AcceptData; import org.btuk.proxy.database.sql.migration.DenyData; import org.btuk.proxy.database.sql.migration.PlotSubmissions; diff --git a/jitpack.yml b/jitpack.yml index 13ceb6c..18cdc8e 100644 --- a/jitpack.yml +++ b/jitpack.yml @@ -1,4 +1,4 @@ jdk: - openjdk21 install: - - mvn install -Dmaven.javadoc.skip=true -DskipTests -pl :database,:core -am \ No newline at end of file + - ./mvnw install -Dmaven.javadoc.skip=true -DskipTests -pl :database,:core,:app -am \ No newline at end of file diff --git a/mvnw b/mvnw new file mode 100755 index 0000000..bd8896b --- /dev/null +++ b/mvnw @@ -0,0 +1,295 @@ +#!/bin/sh +# ---------------------------------------------------------------------------- +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# ---------------------------------------------------------------------------- + +# ---------------------------------------------------------------------------- +# Apache Maven Wrapper startup batch script, version 3.3.4 +# +# Optional ENV vars +# ----------------- +# JAVA_HOME - location of a JDK home dir, required when download maven via java source +# MVNW_REPOURL - repo url base for downloading maven distribution +# MVNW_USERNAME/MVNW_PASSWORD - user and password for downloading maven +# MVNW_VERBOSE - true: enable verbose log; debug: trace the mvnw script; others: silence the output +# ---------------------------------------------------------------------------- + +set -euf +[ "${MVNW_VERBOSE-}" != debug ] || set -x + +# OS specific support. +native_path() { printf %s\\n "$1"; } +case "$(uname)" in +CYGWIN* | MINGW*) + [ -z "${JAVA_HOME-}" ] || JAVA_HOME="$(cygpath --unix "$JAVA_HOME")" + native_path() { cygpath --path --windows "$1"; } + ;; +esac + +# set JAVACMD and JAVACCMD +set_java_home() { + # For Cygwin and MinGW, ensure paths are in Unix format before anything is touched + if [ -n "${JAVA_HOME-}" ]; then + if [ -x "$JAVA_HOME/jre/sh/java" ]; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + JAVACCMD="$JAVA_HOME/jre/sh/javac" + else + JAVACMD="$JAVA_HOME/bin/java" + JAVACCMD="$JAVA_HOME/bin/javac" + + if [ ! -x "$JAVACMD" ] || [ ! -x "$JAVACCMD" ]; then + echo "The JAVA_HOME environment variable is not defined correctly, so mvnw cannot run." >&2 + echo "JAVA_HOME is set to \"$JAVA_HOME\", but \"\$JAVA_HOME/bin/java\" or \"\$JAVA_HOME/bin/javac\" does not exist." >&2 + return 1 + fi + fi + else + JAVACMD="$( + 'set' +e + 'unset' -f command 2>/dev/null + 'command' -v java + )" || : + JAVACCMD="$( + 'set' +e + 'unset' -f command 2>/dev/null + 'command' -v javac + )" || : + + if [ ! -x "${JAVACMD-}" ] || [ ! -x "${JAVACCMD-}" ]; then + echo "The java/javac command does not exist in PATH nor is JAVA_HOME set, so mvnw cannot run." >&2 + return 1 + fi + fi +} + +# hash string like Java String::hashCode +hash_string() { + str="${1:-}" h=0 + while [ -n "$str" ]; do + char="${str%"${str#?}"}" + h=$(((h * 31 + $(LC_CTYPE=C printf %d "'$char")) % 4294967296)) + str="${str#?}" + done + printf %x\\n $h +} + +verbose() { :; } +[ "${MVNW_VERBOSE-}" != true ] || verbose() { printf %s\\n "${1-}"; } + +die() { + printf %s\\n "$1" >&2 + exit 1 +} + +trim() { + # MWRAPPER-139: + # Trims trailing and leading whitespace, carriage returns, tabs, and linefeeds. + # Needed for removing poorly interpreted newline sequences when running in more + # exotic environments such as mingw bash on Windows. + printf "%s" "${1}" | tr -d '[:space:]' +} + +scriptDir="$(dirname "$0")" +scriptName="$(basename "$0")" + +# parse distributionUrl and optional distributionSha256Sum, requires .mvn/wrapper/maven-wrapper.properties +while IFS="=" read -r key value; do + case "${key-}" in + distributionUrl) distributionUrl=$(trim "${value-}") ;; + distributionSha256Sum) distributionSha256Sum=$(trim "${value-}") ;; + esac +done <"$scriptDir/.mvn/wrapper/maven-wrapper.properties" +[ -n "${distributionUrl-}" ] || die "cannot read distributionUrl property in $scriptDir/.mvn/wrapper/maven-wrapper.properties" + +case "${distributionUrl##*/}" in +maven-mvnd-*bin.*) + MVN_CMD=mvnd.sh _MVNW_REPO_PATTERN=/maven/mvnd/ + case "${PROCESSOR_ARCHITECTURE-}${PROCESSOR_ARCHITEW6432-}:$(uname -a)" in + *AMD64:CYGWIN* | *AMD64:MINGW*) distributionPlatform=windows-amd64 ;; + :Darwin*x86_64) distributionPlatform=darwin-amd64 ;; + :Darwin*arm64) distributionPlatform=darwin-aarch64 ;; + :Linux*x86_64*) distributionPlatform=linux-amd64 ;; + *) + echo "Cannot detect native platform for mvnd on $(uname)-$(uname -m), use pure java version" >&2 + distributionPlatform=linux-amd64 + ;; + esac + distributionUrl="${distributionUrl%-bin.*}-$distributionPlatform.zip" + ;; +maven-mvnd-*) MVN_CMD=mvnd.sh _MVNW_REPO_PATTERN=/maven/mvnd/ ;; +*) MVN_CMD="mvn${scriptName#mvnw}" _MVNW_REPO_PATTERN=/org/apache/maven/ ;; +esac + +# apply MVNW_REPOURL and calculate MAVEN_HOME +# maven home pattern: ~/.m2/wrapper/dists/{apache-maven-,maven-mvnd--}/ +[ -z "${MVNW_REPOURL-}" ] || distributionUrl="$MVNW_REPOURL$_MVNW_REPO_PATTERN${distributionUrl#*"$_MVNW_REPO_PATTERN"}" +distributionUrlName="${distributionUrl##*/}" +distributionUrlNameMain="${distributionUrlName%.*}" +distributionUrlNameMain="${distributionUrlNameMain%-bin}" +MAVEN_USER_HOME="${MAVEN_USER_HOME:-${HOME}/.m2}" +MAVEN_HOME="${MAVEN_USER_HOME}/wrapper/dists/${distributionUrlNameMain-}/$(hash_string "$distributionUrl")" + +exec_maven() { + unset MVNW_VERBOSE MVNW_USERNAME MVNW_PASSWORD MVNW_REPOURL || : + exec "$MAVEN_HOME/bin/$MVN_CMD" "$@" || die "cannot exec $MAVEN_HOME/bin/$MVN_CMD" +} + +if [ -d "$MAVEN_HOME" ]; then + verbose "found existing MAVEN_HOME at $MAVEN_HOME" + exec_maven "$@" +fi + +case "${distributionUrl-}" in +*?-bin.zip | *?maven-mvnd-?*-?*.zip) ;; +*) die "distributionUrl is not valid, must match *-bin.zip or maven-mvnd-*.zip, but found '${distributionUrl-}'" ;; +esac + +# prepare tmp dir +if TMP_DOWNLOAD_DIR="$(mktemp -d)" && [ -d "$TMP_DOWNLOAD_DIR" ]; then + clean() { rm -rf -- "$TMP_DOWNLOAD_DIR"; } + trap clean HUP INT TERM EXIT +else + die "cannot create temp dir" +fi + +mkdir -p -- "${MAVEN_HOME%/*}" + +# Download and Install Apache Maven +verbose "Couldn't find MAVEN_HOME, downloading and installing it ..." +verbose "Downloading from: $distributionUrl" +verbose "Downloading to: $TMP_DOWNLOAD_DIR/$distributionUrlName" + +# select .zip or .tar.gz +if ! command -v unzip >/dev/null; then + distributionUrl="${distributionUrl%.zip}.tar.gz" + distributionUrlName="${distributionUrl##*/}" +fi + +# verbose opt +__MVNW_QUIET_WGET=--quiet __MVNW_QUIET_CURL=--silent __MVNW_QUIET_UNZIP=-q __MVNW_QUIET_TAR='' +[ "${MVNW_VERBOSE-}" != true ] || __MVNW_QUIET_WGET='' __MVNW_QUIET_CURL='' __MVNW_QUIET_UNZIP='' __MVNW_QUIET_TAR=v + +# normalize http auth +case "${MVNW_PASSWORD:+has-password}" in +'') MVNW_USERNAME='' MVNW_PASSWORD='' ;; +has-password) [ -n "${MVNW_USERNAME-}" ] || MVNW_USERNAME='' MVNW_PASSWORD='' ;; +esac + +if [ -z "${MVNW_USERNAME-}" ] && command -v wget >/dev/null; then + verbose "Found wget ... using wget" + wget ${__MVNW_QUIET_WGET:+"$__MVNW_QUIET_WGET"} "$distributionUrl" -O "$TMP_DOWNLOAD_DIR/$distributionUrlName" || die "wget: Failed to fetch $distributionUrl" +elif [ -z "${MVNW_USERNAME-}" ] && command -v curl >/dev/null; then + verbose "Found curl ... using curl" + curl ${__MVNW_QUIET_CURL:+"$__MVNW_QUIET_CURL"} -f -L -o "$TMP_DOWNLOAD_DIR/$distributionUrlName" "$distributionUrl" || die "curl: Failed to fetch $distributionUrl" +elif set_java_home; then + verbose "Falling back to use Java to download" + javaSource="$TMP_DOWNLOAD_DIR/Downloader.java" + targetZip="$TMP_DOWNLOAD_DIR/$distributionUrlName" + cat >"$javaSource" <<-END + public class Downloader extends java.net.Authenticator + { + protected java.net.PasswordAuthentication getPasswordAuthentication() + { + return new java.net.PasswordAuthentication( System.getenv( "MVNW_USERNAME" ), System.getenv( "MVNW_PASSWORD" ).toCharArray() ); + } + public static void main( String[] args ) throws Exception + { + setDefault( new Downloader() ); + java.nio.file.Files.copy( java.net.URI.create( args[0] ).toURL().openStream(), java.nio.file.Paths.get( args[1] ).toAbsolutePath().normalize() ); + } + } + END + # For Cygwin/MinGW, switch paths to Windows format before running javac and java + verbose " - Compiling Downloader.java ..." + "$(native_path "$JAVACCMD")" "$(native_path "$javaSource")" || die "Failed to compile Downloader.java" + verbose " - Running Downloader.java ..." + "$(native_path "$JAVACMD")" -cp "$(native_path "$TMP_DOWNLOAD_DIR")" Downloader "$distributionUrl" "$(native_path "$targetZip")" +fi + +# If specified, validate the SHA-256 sum of the Maven distribution zip file +if [ -n "${distributionSha256Sum-}" ]; then + distributionSha256Result=false + if [ "$MVN_CMD" = mvnd.sh ]; then + echo "Checksum validation is not supported for maven-mvnd." >&2 + echo "Please disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." >&2 + exit 1 + elif command -v sha256sum >/dev/null; then + if echo "$distributionSha256Sum $TMP_DOWNLOAD_DIR/$distributionUrlName" | sha256sum -c - >/dev/null 2>&1; then + distributionSha256Result=true + fi + elif command -v shasum >/dev/null; then + if echo "$distributionSha256Sum $TMP_DOWNLOAD_DIR/$distributionUrlName" | shasum -a 256 -c >/dev/null 2>&1; then + distributionSha256Result=true + fi + else + echo "Checksum validation was requested but neither 'sha256sum' or 'shasum' are available." >&2 + echo "Please install either command, or disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." >&2 + exit 1 + fi + if [ $distributionSha256Result = false ]; then + echo "Error: Failed to validate Maven distribution SHA-256, your Maven distribution might be compromised." >&2 + echo "If you updated your Maven version, you need to update the specified distributionSha256Sum property." >&2 + exit 1 + fi +fi + +# unzip and move +if command -v unzip >/dev/null; then + unzip ${__MVNW_QUIET_UNZIP:+"$__MVNW_QUIET_UNZIP"} "$TMP_DOWNLOAD_DIR/$distributionUrlName" -d "$TMP_DOWNLOAD_DIR" || die "failed to unzip" +else + tar xzf${__MVNW_QUIET_TAR:+"$__MVNW_QUIET_TAR"} "$TMP_DOWNLOAD_DIR/$distributionUrlName" -C "$TMP_DOWNLOAD_DIR" || die "failed to untar" +fi + +# Find the actual extracted directory name (handles snapshots where filename != directory name) +actualDistributionDir="" + +# First try the expected directory name (for regular distributions) +if [ -d "$TMP_DOWNLOAD_DIR/$distributionUrlNameMain" ]; then + if [ -f "$TMP_DOWNLOAD_DIR/$distributionUrlNameMain/bin/$MVN_CMD" ]; then + actualDistributionDir="$distributionUrlNameMain" + fi +fi + +# If not found, search for any directory with the Maven executable (for snapshots) +if [ -z "$actualDistributionDir" ]; then + # enable globbing to iterate over items + set +f + for dir in "$TMP_DOWNLOAD_DIR"/*; do + if [ -d "$dir" ]; then + if [ -f "$dir/bin/$MVN_CMD" ]; then + actualDistributionDir="$(basename "$dir")" + break + fi + fi + done + set -f +fi + +if [ -z "$actualDistributionDir" ]; then + verbose "Contents of $TMP_DOWNLOAD_DIR:" + verbose "$(ls -la "$TMP_DOWNLOAD_DIR")" + die "Could not find Maven distribution directory in extracted archive" +fi + +verbose "Found extracted Maven distribution directory: $actualDistributionDir" +printf %s\\n "$distributionUrl" >"$TMP_DOWNLOAD_DIR/$actualDistributionDir/mvnw.url" +mv -- "$TMP_DOWNLOAD_DIR/$actualDistributionDir" "$MAVEN_HOME" || [ -d "$MAVEN_HOME" ] || die "fail to move MAVEN_HOME" + +clean || : +exec_maven "$@" diff --git a/mvnw.cmd b/mvnw.cmd new file mode 100644 index 0000000..92450f9 --- /dev/null +++ b/mvnw.cmd @@ -0,0 +1,189 @@ +<# : batch portion +@REM ---------------------------------------------------------------------------- +@REM Licensed to the Apache Software Foundation (ASF) under one +@REM or more contributor license agreements. See the NOTICE file +@REM distributed with this work for additional information +@REM regarding copyright ownership. The ASF licenses this file +@REM to you under the Apache License, Version 2.0 (the +@REM "License"); you may not use this file except in compliance +@REM with the License. You may obtain a copy of the License at +@REM +@REM http://www.apache.org/licenses/LICENSE-2.0 +@REM +@REM Unless required by applicable law or agreed to in writing, +@REM software distributed under the License is distributed on an +@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +@REM KIND, either express or implied. See the License for the +@REM specific language governing permissions and limitations +@REM under the License. +@REM ---------------------------------------------------------------------------- + +@REM ---------------------------------------------------------------------------- +@REM Apache Maven Wrapper startup batch script, version 3.3.4 +@REM +@REM Optional ENV vars +@REM MVNW_REPOURL - repo url base for downloading maven distribution +@REM MVNW_USERNAME/MVNW_PASSWORD - user and password for downloading maven +@REM MVNW_VERBOSE - true: enable verbose log; others: silence the output +@REM ---------------------------------------------------------------------------- + +@IF "%__MVNW_ARG0_NAME__%"=="" (SET __MVNW_ARG0_NAME__=%~nx0) +@SET __MVNW_CMD__= +@SET __MVNW_ERROR__= +@SET __MVNW_PSMODULEP_SAVE=%PSModulePath% +@SET PSModulePath= +@FOR /F "usebackq tokens=1* delims==" %%A IN (`powershell -noprofile "& {$scriptDir='%~dp0'; $script='%__MVNW_ARG0_NAME__%'; icm -ScriptBlock ([Scriptblock]::Create((Get-Content -Raw '%~f0'))) -NoNewScope}"`) DO @( + IF "%%A"=="MVN_CMD" (set __MVNW_CMD__=%%B) ELSE IF "%%B"=="" (echo %%A) ELSE (echo %%A=%%B) +) +@SET PSModulePath=%__MVNW_PSMODULEP_SAVE% +@SET __MVNW_PSMODULEP_SAVE= +@SET __MVNW_ARG0_NAME__= +@SET MVNW_USERNAME= +@SET MVNW_PASSWORD= +@IF NOT "%__MVNW_CMD__%"=="" ("%__MVNW_CMD__%" %*) +@echo Cannot start maven from wrapper >&2 && exit /b 1 +@GOTO :EOF +: end batch / begin powershell #> + +$ErrorActionPreference = "Stop" +if ($env:MVNW_VERBOSE -eq "true") { + $VerbosePreference = "Continue" +} + +# calculate distributionUrl, requires .mvn/wrapper/maven-wrapper.properties +$distributionUrl = (Get-Content -Raw "$scriptDir/.mvn/wrapper/maven-wrapper.properties" | ConvertFrom-StringData).distributionUrl +if (!$distributionUrl) { + Write-Error "cannot read distributionUrl property in $scriptDir/.mvn/wrapper/maven-wrapper.properties" +} + +switch -wildcard -casesensitive ( $($distributionUrl -replace '^.*/','') ) { + "maven-mvnd-*" { + $USE_MVND = $true + $distributionUrl = $distributionUrl -replace '-bin\.[^.]*$',"-windows-amd64.zip" + $MVN_CMD = "mvnd.cmd" + break + } + default { + $USE_MVND = $false + $MVN_CMD = $script -replace '^mvnw','mvn' + break + } +} + +# apply MVNW_REPOURL and calculate MAVEN_HOME +# maven home pattern: ~/.m2/wrapper/dists/{apache-maven-,maven-mvnd--}/ +if ($env:MVNW_REPOURL) { + $MVNW_REPO_PATTERN = if ($USE_MVND -eq $False) { "/org/apache/maven/" } else { "/maven/mvnd/" } + $distributionUrl = "$env:MVNW_REPOURL$MVNW_REPO_PATTERN$($distributionUrl -replace "^.*$MVNW_REPO_PATTERN",'')" +} +$distributionUrlName = $distributionUrl -replace '^.*/','' +$distributionUrlNameMain = $distributionUrlName -replace '\.[^.]*$','' -replace '-bin$','' + +$MAVEN_M2_PATH = "$HOME/.m2" +if ($env:MAVEN_USER_HOME) { + $MAVEN_M2_PATH = "$env:MAVEN_USER_HOME" +} + +if (-not (Test-Path -Path $MAVEN_M2_PATH)) { + New-Item -Path $MAVEN_M2_PATH -ItemType Directory | Out-Null +} + +$MAVEN_WRAPPER_DISTS = $null +if ((Get-Item $MAVEN_M2_PATH).Target[0] -eq $null) { + $MAVEN_WRAPPER_DISTS = "$MAVEN_M2_PATH/wrapper/dists" +} else { + $MAVEN_WRAPPER_DISTS = (Get-Item $MAVEN_M2_PATH).Target[0] + "/wrapper/dists" +} + +$MAVEN_HOME_PARENT = "$MAVEN_WRAPPER_DISTS/$distributionUrlNameMain" +$MAVEN_HOME_NAME = ([System.Security.Cryptography.SHA256]::Create().ComputeHash([byte[]][char[]]$distributionUrl) | ForEach-Object {$_.ToString("x2")}) -join '' +$MAVEN_HOME = "$MAVEN_HOME_PARENT/$MAVEN_HOME_NAME" + +if (Test-Path -Path "$MAVEN_HOME" -PathType Container) { + Write-Verbose "found existing MAVEN_HOME at $MAVEN_HOME" + Write-Output "MVN_CMD=$MAVEN_HOME/bin/$MVN_CMD" + exit $? +} + +if (! $distributionUrlNameMain -or ($distributionUrlName -eq $distributionUrlNameMain)) { + Write-Error "distributionUrl is not valid, must end with *-bin.zip, but found $distributionUrl" +} + +# prepare tmp dir +$TMP_DOWNLOAD_DIR_HOLDER = New-TemporaryFile +$TMP_DOWNLOAD_DIR = New-Item -Itemtype Directory -Path "$TMP_DOWNLOAD_DIR_HOLDER.dir" +$TMP_DOWNLOAD_DIR_HOLDER.Delete() | Out-Null +trap { + if ($TMP_DOWNLOAD_DIR.Exists) { + try { Remove-Item $TMP_DOWNLOAD_DIR -Recurse -Force | Out-Null } + catch { Write-Warning "Cannot remove $TMP_DOWNLOAD_DIR" } + } +} + +New-Item -Itemtype Directory -Path "$MAVEN_HOME_PARENT" -Force | Out-Null + +# Download and Install Apache Maven +Write-Verbose "Couldn't find MAVEN_HOME, downloading and installing it ..." +Write-Verbose "Downloading from: $distributionUrl" +Write-Verbose "Downloading to: $TMP_DOWNLOAD_DIR/$distributionUrlName" + +$webclient = New-Object System.Net.WebClient +if ($env:MVNW_USERNAME -and $env:MVNW_PASSWORD) { + $webclient.Credentials = New-Object System.Net.NetworkCredential($env:MVNW_USERNAME, $env:MVNW_PASSWORD) +} +[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 +$webclient.DownloadFile($distributionUrl, "$TMP_DOWNLOAD_DIR/$distributionUrlName") | Out-Null + +# If specified, validate the SHA-256 sum of the Maven distribution zip file +$distributionSha256Sum = (Get-Content -Raw "$scriptDir/.mvn/wrapper/maven-wrapper.properties" | ConvertFrom-StringData).distributionSha256Sum +if ($distributionSha256Sum) { + if ($USE_MVND) { + Write-Error "Checksum validation is not supported for maven-mvnd. `nPlease disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." + } + Import-Module $PSHOME\Modules\Microsoft.PowerShell.Utility -Function Get-FileHash + if ((Get-FileHash "$TMP_DOWNLOAD_DIR/$distributionUrlName" -Algorithm SHA256).Hash.ToLower() -ne $distributionSha256Sum) { + Write-Error "Error: Failed to validate Maven distribution SHA-256, your Maven distribution might be compromised. If you updated your Maven version, you need to update the specified distributionSha256Sum property." + } +} + +# unzip and move +Expand-Archive "$TMP_DOWNLOAD_DIR/$distributionUrlName" -DestinationPath "$TMP_DOWNLOAD_DIR" | Out-Null + +# Find the actual extracted directory name (handles snapshots where filename != directory name) +$actualDistributionDir = "" + +# First try the expected directory name (for regular distributions) +$expectedPath = Join-Path "$TMP_DOWNLOAD_DIR" "$distributionUrlNameMain" +$expectedMvnPath = Join-Path "$expectedPath" "bin/$MVN_CMD" +if ((Test-Path -Path $expectedPath -PathType Container) -and (Test-Path -Path $expectedMvnPath -PathType Leaf)) { + $actualDistributionDir = $distributionUrlNameMain +} + +# If not found, search for any directory with the Maven executable (for snapshots) +if (!$actualDistributionDir) { + Get-ChildItem -Path "$TMP_DOWNLOAD_DIR" -Directory | ForEach-Object { + $testPath = Join-Path $_.FullName "bin/$MVN_CMD" + if (Test-Path -Path $testPath -PathType Leaf) { + $actualDistributionDir = $_.Name + } + } +} + +if (!$actualDistributionDir) { + Write-Error "Could not find Maven distribution directory in extracted archive" +} + +Write-Verbose "Found extracted Maven distribution directory: $actualDistributionDir" +Rename-Item -Path "$TMP_DOWNLOAD_DIR/$actualDistributionDir" -NewName $MAVEN_HOME_NAME | Out-Null +try { + Move-Item -Path "$TMP_DOWNLOAD_DIR/$MAVEN_HOME_NAME" -Destination $MAVEN_HOME_PARENT | Out-Null +} catch { + if (! (Test-Path -Path "$MAVEN_HOME" -PathType Container)) { + Write-Error "fail to move MAVEN_HOME" + } +} finally { + try { Remove-Item $TMP_DOWNLOAD_DIR -Recurse -Force | Out-Null } + catch { Write-Warning "Cannot remove $TMP_DOWNLOAD_DIR" } +} + +Write-Output "MVN_CMD=$MAVEN_HOME/bin/$MVN_CMD" diff --git a/plugin/pom.xml b/plugin/pom.xml index b76825c..9df8608 100644 --- a/plugin/pom.xml +++ b/plugin/pom.xml @@ -30,7 +30,11 @@ false Proxy-${project.version} true - + + + io.netty:* + + *:* @@ -57,20 +61,24 @@ - com.github.BTEUK:NetworkLib + com.github.BuildtheUK:NetworkLib com/fasterxml/** com/google/gson/** net/kyori/** org/jetbrains/** org/intellij/** - META-INF/** + META-INF/MANIFEST.MF + META-INF/*.SF + META-INF/*.DSA + META-INF/*.RSA - + @@ -79,7 +87,6 @@ org.apache.maven.plugins maven-compiler-plugin - ${maven-compiler-plugin.version} @@ -105,6 +112,10 @@ + + org.btuk.proxy + app + org.btuk.proxy core diff --git a/plugin/src/main/java/org/btuk/proxy/Proxy.java b/plugin/src/main/java/org/btuk/proxy/Proxy.java index 2250eac..9ca99d9 100644 --- a/plugin/src/main/java/org/btuk/proxy/Proxy.java +++ b/plugin/src/main/java/org/btuk/proxy/Proxy.java @@ -10,21 +10,18 @@ import com.velocitypowered.api.proxy.ProxyServer; import com.velocitypowered.api.proxy.server.RegisteredServer; import lombok.Getter; -import net.bteuk.network.lib.socket.InputSocket; - +import org.btuk.network.lib.socket.InputSocket; +import org.btuk.proxy.app.ProxyController; import org.btuk.proxy.chat.ProxyChatHandler; - +import org.btuk.proxy.core.socket.ProxySocketHandler; import org.btuk.proxy.listener.CommandListener; import org.btuk.proxy.listener.ServerConnectListener; import org.btuk.proxy.player.ProxyPlayerManager; import org.btuk.proxy.scheduler.ProxyScheduler; import org.btuk.proxy.server.ProxyCoreServerManager; -import org.btuk.proxy.core.socket.ProxySocketHandler; - import org.btuk.proxy.tab.ProxyTabManager; import org.slf4j.Logger; - import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; @@ -38,7 +35,7 @@ import java.util.UUID; import java.util.function.Consumer; -@Plugin(id = "proxy", name = "Proxy", version = "1.12.0-SNAPSHOT", +@Plugin(id = "proxy", name = "Proxy", version = "1.13.0-SNAPSHOT", url = "https://github.com/BTEUK/Proxy", description = "Proxy plugin, managed chat, discord and server related actions.", authors = {"ELgamer"}) public class Proxy { @@ -69,7 +66,6 @@ public Proxy(ProxyServer server, Logger logger) { @Subscribe public void onProxyInitialization(ProxyInitializeEvent event) throws IOException { - this.proxyController = new ProxyController(getDataFolder()); this.defaultServer = proxyController.getConfig().getString("default_server"); diff --git a/plugin/src/main/java/org/btuk/proxy/chat/ProxyChatHandler.java b/plugin/src/main/java/org/btuk/proxy/chat/ProxyChatHandler.java index 38baaf6..25e6f27 100644 --- a/plugin/src/main/java/org/btuk/proxy/chat/ProxyChatHandler.java +++ b/plugin/src/main/java/org/btuk/proxy/chat/ProxyChatHandler.java @@ -1,21 +1,20 @@ package org.btuk.proxy.chat; import lombok.extern.java.Log; -import net.bteuk.network.lib.dto.AbstractTransferObject; -import net.bteuk.network.lib.socket.OutputSocket; +import org.btuk.network.lib.dto.AbstractTransferObject; +import org.btuk.network.lib.socket.OutputSocket; +import org.btuk.proxy.core.chat.ChatHandler; +import org.btuk.proxy.core.config.Config; +import org.btuk.proxy.core.config.ConfigSocket; import org.btuk.proxy.core.exceptions.ServerNotFoundException; +import org.btuk.proxy.core.server.CoreServerManager; +import org.btuk.proxy.core.server.Server; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Optional; -import org.btuk.proxy.core.chat.ChatHandler; -import org.btuk.proxy.core.config.Config; -import org.btuk.proxy.core.config.ConfigSocket; -import org.btuk.proxy.core.server.Server; -import org.btuk.proxy.core.server.CoreServerManager; - @Log public class ProxyChatHandler implements ChatHandler { diff --git a/plugin/src/main/java/org/btuk/proxy/tab/ProxyTabManager.java b/plugin/src/main/java/org/btuk/proxy/tab/ProxyTabManager.java index 6534f61..e8c03d7 100644 --- a/plugin/src/main/java/org/btuk/proxy/tab/ProxyTabManager.java +++ b/plugin/src/main/java/org/btuk/proxy/tab/ProxyTabManager.java @@ -3,13 +3,16 @@ import com.velocitypowered.api.proxy.ProxyServer; import com.velocitypowered.api.proxy.player.TabListEntry; import com.velocitypowered.api.util.GameProfile; -import net.bteuk.network.lib.dto.TabPlayer; - +import net.kyori.adventure.text.Component; +import org.btuk.network.lib.dto.TabPlayer; +import org.btuk.proxy.core.chat.ChatHandler; +import org.btuk.proxy.core.config.Config; +import org.btuk.proxy.core.player.Player; import org.btuk.proxy.core.scheduler.Scheduler; import org.btuk.proxy.core.tab.AbstractTabManager; +import org.btuk.proxy.core.user.CoreUserManager; +import org.btuk.proxy.core.user.User; import org.btuk.proxy.player.ProxyPlayer; - -import net.kyori.adventure.text.Component; import org.jetbrains.annotations.Nullable; import java.util.ArrayList; @@ -17,12 +20,6 @@ import java.util.List; import java.util.Optional; -import org.btuk.proxy.core.chat.ChatHandler; -import org.btuk.proxy.core.config.Config; -import org.btuk.proxy.core.player.Player; -import org.btuk.proxy.core.user.CoreUserManager; -import org.btuk.proxy.core.user.User; - /** * Keeps track of all users and their tab information. * Sends updates to the servers when things change. diff --git a/pom.xml b/pom.xml index dff10c7..813c04a 100644 --- a/pom.xml +++ b/pom.xml @@ -15,21 +15,22 @@ api core plugin + app - 21 + 25 UTF-8 ${java-version} - 3.11.0 - 3.6.1 + 3.15.0 + 3.6.2 - 955372d721 + 5dee061bcb - 3.5.0-SNAPSHOT + 4.1.0-SNAPSHOT - 1.18.34 + 1.18.46 2.25.2 2.0.17 @@ -71,12 +72,12 @@ org.btuk.proxy - database + api ${project.version} org.btuk.proxy - api + app ${project.version} @@ -84,9 +85,14 @@ core ${project.version} + + org.btuk.proxy + database + ${project.version} + - com.github.BTEUK + com.github.BuildtheUK NetworkLib ${networklib.version} @@ -160,4 +166,25 @@ + + + + + + org.apache.maven.plugins + maven-compiler-plugin + ${maven-compiler-plugin.version} + + + + org.projectlombok + lombok + ${lombok.version} + + + + + + + \ No newline at end of file