mirror of
https://github.com/funkemunky/AntiVPN.git
synced 2026-05-31 17:31:55 +00:00
Compare commits
28 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| c2e6168037 | |||
| 74ae0a0d4d | |||
| c9b373a273 | |||
| a943700c9c | |||
| e4ab168315 | |||
| 7f6f475b21 | |||
| 1c3ab6005c | |||
| 7bfe6b19bb | |||
| ae14755205 | |||
| 3583b15815 | |||
| a825752b4b | |||
| a49291192c | |||
| 1e042a486f | |||
| 37d8511edd | |||
| eb57929bbd | |||
| 4b8d6caa08 | |||
| 3839c4b916 | |||
| 3e4d8be955 | |||
| 7088dad4eb | |||
| 2bff5c06c9 | |||
| 4c2ad35c96 | |||
| db3e137522 | |||
| 546c610a53 | |||
| 64adf72e23 | |||
| fcffb669d4 | |||
| 5878fc6e43 | |||
|
a483a90851
|
|||
|
c6d282e3cc
|
@@ -6,30 +6,25 @@ jobs:
|
||||
name: Build and Release
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Cache local Maven repository
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: ~/.m2/repository
|
||||
key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-maven-
|
||||
- uses: actions/checkout@v5
|
||||
- name: Set up JDK 21
|
||||
uses: actions/setup-java@v5
|
||||
with:
|
||||
java-version: '21'
|
||||
distribution: 'zulu'
|
||||
- name: Set up Maven
|
||||
uses: stCarolas/setup-maven@v5
|
||||
- name: Set up Gradle
|
||||
uses: gradle/actions/setup-gradle@v4
|
||||
with:
|
||||
maven-version: 3.9.6
|
||||
- name: Compile
|
||||
run: mvn -B package --file pom.xml
|
||||
gradle-version: 'wrapper'
|
||||
- name: Build
|
||||
run: ./gradlew build --no-daemon
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: Get Version Number from Pom
|
||||
- name: Get Version Number from Gradle
|
||||
id: get_version
|
||||
run: echo "VERSION=$(mvn help:evaluate -Dexpression=project.version -q -DforceStdout)" >> $GITHUB_ENV
|
||||
run: |
|
||||
VERSION=$(./gradlew properties -q | awk -F': ' '/^version:/ {print $2; exit}')
|
||||
echo "VERSION=$VERSION" >> "$GITHUB_ENV"
|
||||
- name: Extract latest CHANGELOG entry
|
||||
id: changelog
|
||||
run: |
|
||||
@@ -37,7 +32,7 @@ jobs:
|
||||
CHANGELOG_ESCAPED=$(echo "$CHANGELOG_CONTENT" | sed ':a;N;$!ba;s/\n/%0A/g')
|
||||
echo "Extracted latest release notes from CHANGELOG.md:"
|
||||
echo -e "$CHANGELOG_CONTENT"
|
||||
echo "::set-output name=content::$CHANGELOG_ESCAPED"
|
||||
echo "content=$CHANGELOG_ESCAPED" >> "$GITHUB_OUTPUT"
|
||||
- name: Create Release
|
||||
uses: actions/create-release@v1
|
||||
id: create_release
|
||||
@@ -54,14 +49,6 @@ jobs:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
upload_url: ${{ steps.create_release.outputs.upload_url }}
|
||||
asset_path: ./Universal/target/AntiVPN-${{ env.VERSION }}-universal.jar
|
||||
asset_name: AntiVPN-Universal-v${{ env.VERSION }}.jar
|
||||
asset_content_type: application/java-archive
|
||||
- uses: actions/upload-release-asset@v1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
upload_url: ${{ steps.create_release.outputs.upload_url }}
|
||||
asset_path: ./Sponge/target/Sponge-${{ env.VERSION }}.jar
|
||||
asset_name: AntiVPN-Sponge-v${{ env.VERSION }}.jar
|
||||
asset_path: ./build/libs/AntiVPN-${{ env.VERSION }}-universal.jar
|
||||
asset_name: AntiVPN-v${{ env.VERSION }}.jar
|
||||
asset_content_type: application/java-archive
|
||||
|
||||
@@ -11,34 +11,27 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Cache local Maven repository
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: ~/.m2/repository
|
||||
key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-maven-
|
||||
- uses: actions/checkout@v5
|
||||
- name: Set up JDK 21
|
||||
uses: actions/setup-java@v5
|
||||
with:
|
||||
java-version: '21'
|
||||
distribution: 'zulu'
|
||||
- name: Set up Maven
|
||||
uses: stCarolas/setup-maven@v5
|
||||
- name: Set up Gradle
|
||||
uses: gradle/actions/setup-gradle@v4
|
||||
with:
|
||||
maven-version: 3.9.6
|
||||
- name: Compile
|
||||
run: mvn -B package --file pom.xml
|
||||
gradle-version: 'wrapper'
|
||||
- name: Build
|
||||
run: ./gradlew build --no-daemon
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: Upload AntiVPN
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: AntiVPN-Universal
|
||||
path: Universal/target/AntiVPN-*.jar
|
||||
path: build/libs/AntiVPN-*-universal.jar
|
||||
- name: Upload Sponge plugin
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: AntiVPN-Sponge
|
||||
path: Sponge/target/Sponge-*.jar
|
||||
path: Sponge/SpongeLoader/build/libs/*.jar
|
||||
@@ -0,0 +1,22 @@
|
||||
on:
|
||||
push:
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- name: Set up JDK 21
|
||||
uses: actions/setup-java@v5
|
||||
with:
|
||||
java-version: '21'
|
||||
distribution: 'zulu'
|
||||
- name: Set up Gradle
|
||||
uses: gradle/actions/setup-gradle@v4
|
||||
with:
|
||||
gradle-version: 'wrapper'
|
||||
- name: Build
|
||||
run: ./gradlew build --no-daemon
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
@@ -1,19 +0,0 @@
|
||||
on:
|
||||
push:
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Set up JDK 21
|
||||
uses: actions/setup-java@v4
|
||||
with:
|
||||
java-version: 21.0
|
||||
distribution: 'zulu'
|
||||
cache: 'maven'
|
||||
- name: Compile
|
||||
run: mvn -B package --file pom.xml
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
@@ -188,6 +188,7 @@ fabric.properties
|
||||
|
||||
# Package Files #
|
||||
*.jar
|
||||
!gradle/wrapper/gradle-wrapper.jar
|
||||
*.war
|
||||
*.nar
|
||||
*.ear
|
||||
@@ -293,3 +294,4 @@ $RECYCLE.BIN/
|
||||
*.lnk
|
||||
|
||||
# End of https://www.toptal.com/developers/gitignore/api/windows,macos,linux,maven,java,intellij,eclipse,netbeans
|
||||
/.gradle/
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
plugins {
|
||||
id 'com.github.johnrengelman.shadow'
|
||||
}
|
||||
|
||||
evaluationDependsOn(':Bukkit:Plugin')
|
||||
|
||||
dependencies {
|
||||
compileOnly 'org.spigotmc:spigot-api:1.20.2-R0.1-SNAPSHOT'
|
||||
compileOnly project(':Bukkit:Plugin')
|
||||
implementation project(':Common:loader-utils')
|
||||
}
|
||||
|
||||
shadowJar {
|
||||
archiveClassifier.set('')
|
||||
|
||||
// Include the shaded plugin jar as a single resource file
|
||||
from(project(':Bukkit:Plugin').tasks.shadowJar) {
|
||||
rename { 'antivpn-bukkit.jarinjar' }
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure the plugin is built before packaging the loader
|
||||
tasks.named('shadowJar') {
|
||||
dependsOn(':Bukkit:Plugin:shadowJar')
|
||||
}
|
||||
|
||||
tasks.build.dependsOn shadowJar
|
||||
@@ -1,107 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
~ Copyright 2026 Dawson Hessler
|
||||
~
|
||||
~ Licensed 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.
|
||||
-->
|
||||
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>dev.brighten.antivpn</groupId>
|
||||
<artifactId>Bukkit</artifactId>
|
||||
<version>1.10.0</version>
|
||||
</parent>
|
||||
<groupId>dev.brighten.antivpn.bukkit</groupId>
|
||||
<artifactId>Loader</artifactId>
|
||||
|
||||
<properties>
|
||||
<maven.compiler.source>17</maven.compiler.source>
|
||||
<maven.compiler.target>17</maven.compiler.target>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>spigot-repo</id>
|
||||
<url>https://hub.spigotmc.org/nexus/content/repositories/snapshots/</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.13.0</version>
|
||||
<configuration>
|
||||
<source>17</source>
|
||||
<target>17</target>
|
||||
<compilerArgument>-XDignore.symbol.file</compilerArgument>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-shade-plugin</artifactId>
|
||||
<version>3.6.0</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>shade</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<minimizeJar>false</minimizeJar>
|
||||
<transformers>
|
||||
<transformer implementation="org.apache.maven.plugins.shade.resource.IncludeResourceTransformer">
|
||||
<resource>antivpn-bukkit.jarinjar</resource>
|
||||
<file>${project.parent.basedir}/Plugin/target/Plugin-${project.version}.jar</file>
|
||||
</transformer>
|
||||
</transformers>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
<resources>
|
||||
<resource>
|
||||
<directory>src/main/resources</directory>
|
||||
<filtering>true</filtering>
|
||||
</resource>
|
||||
</resources>
|
||||
</build>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.spigotmc</groupId>
|
||||
<artifactId>spigot-api</artifactId>
|
||||
<version>1.20.2-R0.1-SNAPSHOT</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>dev.brighten.antivpn</groupId>
|
||||
<artifactId>Plugin</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>dev.brighten.antivpn</groupId>
|
||||
<artifactId>loader-utils</artifactId>
|
||||
<version>1.10.0</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
@@ -0,0 +1,18 @@
|
||||
plugins {
|
||||
id 'com.github.johnrengelman.shadow'
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compileOnly 'org.spigotmc:spigot-api:1.20.2-R0.1-SNAPSHOT'
|
||||
compileOnly project(':Common:Source')
|
||||
compileOnly project(':Common:loader-utils')
|
||||
implementation 'org.bstats:bstats-bukkit:2.2.1'
|
||||
}
|
||||
|
||||
shadowJar {
|
||||
archiveClassifier.set('')
|
||||
relocate 'org.bstats', 'dev.brighten.antivpn.bukkit.org.bstats'
|
||||
relocate 'org.yaml.snakeyaml', 'dev.brighten.antivpn.shaded.org.yaml.snakeyaml'
|
||||
}
|
||||
|
||||
tasks.build.dependsOn shadowJar
|
||||
@@ -1,118 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
~ Copyright 2026 Dawson Hessler
|
||||
~
|
||||
~ Licensed 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.
|
||||
-->
|
||||
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>dev.brighten.antivpn</groupId>
|
||||
<artifactId>Bukkit</artifactId>
|
||||
<version>1.10.0</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>Plugin</artifactId>
|
||||
|
||||
<properties>
|
||||
<maven.compiler.source>17</maven.compiler.source>
|
||||
<maven.compiler.target>17</maven.compiler.target>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>spigot-repo</id>
|
||||
<url>https://hub.spigotmc.org/nexus/content/repositories/snapshots/</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.13.0</version>
|
||||
<configuration>
|
||||
<source>17</source>
|
||||
<target>17</target>
|
||||
<compilerArgument>-XDignore.symbol.file</compilerArgument>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-shade-plugin</artifactId>
|
||||
<version>3.6.0</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>shade</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<minimizeJar>false</minimizeJar>
|
||||
<relocations>
|
||||
<relocation>
|
||||
<pattern>org.bstats</pattern>
|
||||
<!-- Replace this with your package! -->
|
||||
<shadedPattern>dev.brighten.antivpn.bukkit.org.bstats</shadedPattern>
|
||||
</relocation>
|
||||
<relocation>
|
||||
<pattern>org.yaml.snakeyaml</pattern>
|
||||
<shadedPattern>dev.brighten.antivpn.shaded.org.yaml.snakeyaml</shadedPattern>
|
||||
</relocation>
|
||||
</relocations>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
<resources>
|
||||
<resource>
|
||||
<directory>src/main/resources</directory>
|
||||
<filtering>true</filtering>
|
||||
</resource>
|
||||
</resources>
|
||||
</build>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.spigotmc</groupId>
|
||||
<artifactId>spigot-api</artifactId>
|
||||
<version>1.20.2-R0.1-SNAPSHOT</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>dev.brighten.antivpn</groupId>
|
||||
<artifactId>Source</artifactId>
|
||||
<version>1.10.0</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.bstats</groupId>
|
||||
<artifactId>bstats-bukkit</artifactId>
|
||||
<version>2.2.1</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>dev.brighten.antivpn</groupId>
|
||||
<artifactId>loader-utils</artifactId>
|
||||
<version>1.10.0</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
@@ -0,0 +1,111 @@
|
||||
package dev.brighten.antivpn.bukkit;
|
||||
|
||||
import be.seeseemelk.mockbukkit.MockBukkit;
|
||||
import be.seeseemelk.mockbukkit.ServerMock;
|
||||
import be.seeseemelk.mockbukkit.entity.PlayerMock;
|
||||
import dev.brighten.antivpn.AntiVPN;
|
||||
import dev.brighten.antivpn.api.PlayerExecutor;
|
||||
import dev.brighten.antivpn.api.VPNConfig;
|
||||
import dev.brighten.antivpn.api.VPNExecutor;
|
||||
import dev.brighten.antivpn.message.MessageHandler;
|
||||
import dev.brighten.antivpn.message.VpnString;
|
||||
import dev.brighten.antivpn.web.objects.VPNResponse;
|
||||
import org.bukkit.event.player.PlayerLoginEvent;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.net.InetAddress;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
public class BukkitListenerTest {
|
||||
|
||||
private ServerMock server;
|
||||
private BukkitListener listener;
|
||||
private VPNExecutor vpnExecutor;
|
||||
|
||||
@BeforeEach
|
||||
public void setUp() throws Exception {
|
||||
server = MockBukkit.mock();
|
||||
|
||||
AntiVPN antiVPN = mock(AntiVPN.class);
|
||||
VPNConfig config = mock(VPNConfig.class);
|
||||
PlayerExecutor playerExecutor = mock(PlayerExecutor.class);
|
||||
vpnExecutor = mock(VPNExecutor.class);
|
||||
MessageHandler messageHandler = mock(MessageHandler.class);
|
||||
|
||||
when(antiVPN.getVpnConfig()).thenReturn(config);
|
||||
when(antiVPN.getPlayerExecutor()).thenReturn(playerExecutor);
|
||||
when(antiVPN.getExecutor()).thenReturn(vpnExecutor);
|
||||
when(antiVPN.getMessageHandler()).thenReturn(messageHandler);
|
||||
|
||||
when(playerExecutor.getPlayer(any(UUID.class))).thenReturn(Optional.empty());
|
||||
when(config.getPrefixWhitelists()).thenReturn(java.util.Collections.emptyList());
|
||||
when(config.getCountryList()).thenReturn(java.util.Collections.emptyList());
|
||||
when(config.isKickPlayers()).thenReturn(true);
|
||||
when(config.getKickMessage()).thenReturn("Blocked!");
|
||||
|
||||
VpnString mockVpnString = mock(VpnString.class);
|
||||
when(mockVpnString.getFormattedMessage(any())).thenReturn("Blocked!");
|
||||
when(messageHandler.getString(anyString())).thenReturn(mockVpnString);
|
||||
|
||||
when(vpnExecutor.checkIp(anyString())).thenReturn(CompletableFuture.completedFuture(
|
||||
VPNResponse.builder().success(true).proxy(false).ip("127.0.0.1")
|
||||
.method("N/A").countryName("N/A").city("N/A").build()
|
||||
));
|
||||
|
||||
// Use reflection to set the private static INSTANCE field
|
||||
Field instanceField = AntiVPN.class.getDeclaredField("INSTANCE");
|
||||
instanceField.setAccessible(true);
|
||||
instanceField.set(null, antiVPN);
|
||||
|
||||
listener = new BukkitListener();
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
public void tearDown() throws Exception {
|
||||
// Reset the singleton
|
||||
Field instanceField = AntiVPN.class.getDeclaredField("INSTANCE");
|
||||
instanceField.setAccessible(true);
|
||||
instanceField.set(null, null);
|
||||
|
||||
MockBukkit.unmock();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLoginEventAllowed() throws Exception {
|
||||
PlayerMock player = server.addPlayer("TestPlayer");
|
||||
InetAddress address = InetAddress.getByName("127.0.0.1");
|
||||
|
||||
PlayerLoginEvent event = new PlayerLoginEvent(player, "localhost", address);
|
||||
|
||||
listener.onLogin(event);
|
||||
|
||||
assertEquals(PlayerLoginEvent.Result.ALLOWED, event.getResult());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLoginEventBlocked() throws Exception {
|
||||
PlayerMock player = server.addPlayer("ProxyPlayer");
|
||||
InetAddress address = InetAddress.getByName("1.1.1.1");
|
||||
|
||||
// Mock proxy response
|
||||
when(vpnExecutor.checkIp("1.1.1.1")).thenReturn(CompletableFuture.completedFuture(
|
||||
VPNResponse.builder().success(true).proxy(true).ip("1.1.1.1")
|
||||
.method("N/A").countryName("N/A").countryCode("N/A").city("N/A").build()
|
||||
));
|
||||
|
||||
PlayerLoginEvent event = new PlayerLoginEvent(player, "localhost", address);
|
||||
|
||||
listener.onLogin(event);
|
||||
|
||||
assertEquals(PlayerLoginEvent.Result.KICK_BANNED, event.getResult());
|
||||
assertEquals("Blocked!", net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().serialize(event.kickMessage()));
|
||||
}
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
~ Copyright 2026 Dawson Hessler
|
||||
~
|
||||
~ Licensed 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.
|
||||
-->
|
||||
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<artifactId>AntiVPN</artifactId>
|
||||
<groupId>dev.brighten.antivpn</groupId>
|
||||
<version>1.10.0</version>
|
||||
</parent>
|
||||
<packaging>pom</packaging>
|
||||
<modules>
|
||||
<module>Plugin</module>
|
||||
<module>Loader</module>
|
||||
</modules>
|
||||
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>Bukkit</artifactId>
|
||||
|
||||
<properties>
|
||||
<maven.compiler.source>17</maven.compiler.source>
|
||||
<maven.compiler.target>17</maven.compiler.target>
|
||||
</properties>
|
||||
|
||||
</project>
|
||||
@@ -0,0 +1,26 @@
|
||||
plugins {
|
||||
id 'com.github.johnrengelman.shadow'
|
||||
}
|
||||
|
||||
evaluationDependsOn(':Bungee:BungeePlugin')
|
||||
|
||||
dependencies {
|
||||
compileOnly 'net.md-5:bungeecord-api:1.21-R0.2'
|
||||
compileOnly project(':Bungee:BungeePlugin')
|
||||
implementation project(':Common:loader-utils')
|
||||
}
|
||||
|
||||
shadowJar {
|
||||
archiveClassifier.set('')
|
||||
|
||||
// Include the shaded plugin jar as a single resource file
|
||||
from(project(':Bungee:BungeePlugin').tasks.shadowJar) {
|
||||
rename { 'antivpn-bungee.jarinjar' }
|
||||
}
|
||||
}
|
||||
|
||||
tasks.named('shadowJar') {
|
||||
dependsOn(':Bungee:BungeePlugin:shadowJar')
|
||||
}
|
||||
|
||||
tasks.build.dependsOn shadowJar
|
||||
@@ -1,103 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
~ Copyright 2026 Dawson Hessler
|
||||
~
|
||||
~ Licensed 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.
|
||||
-->
|
||||
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>dev.brighten.antivpn</groupId>
|
||||
<artifactId>Bungee</artifactId>
|
||||
<version>1.10.0</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
<groupId>dev.brighten.antivpn.bungee</groupId>
|
||||
<artifactId>BungeeLoader</artifactId>
|
||||
|
||||
<properties>
|
||||
<maven.compiler.source>17</maven.compiler.source>
|
||||
<maven.compiler.target>17</maven.compiler.target>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.13.0</version>
|
||||
<configuration>
|
||||
<source>17</source>
|
||||
<target>17</target>
|
||||
<compilerArgument>-XDignore.symbol.file</compilerArgument>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-shade-plugin</artifactId>
|
||||
<version>3.6.0</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>shade</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<minimizeJar>false</minimizeJar>
|
||||
<transformers>
|
||||
<transformer implementation="org.apache.maven.plugins.shade.resource.IncludeResourceTransformer">
|
||||
<resource>antivpn-bungee.jarinjar</resource>
|
||||
<file>${project.parent.basedir}/BungeePlugin/target/BungeePlugin-${project.version}.jar</file>
|
||||
</transformer>
|
||||
</transformers>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
<resources>
|
||||
<resource>
|
||||
<directory>src/main/resources</directory>
|
||||
<filtering>true</filtering>
|
||||
</resource>
|
||||
</resources>
|
||||
</build>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>net.md-5</groupId>
|
||||
<artifactId>bungeecord-api</artifactId>
|
||||
<version>1.21-R0.2</version>
|
||||
<type>jar</type>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>dev.brighten.antivpn</groupId>
|
||||
<artifactId>Plugin</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>dev.brighten.antivpn</groupId>
|
||||
<artifactId>loader-utils</artifactId>
|
||||
<version>1.10.0</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
@@ -0,0 +1,18 @@
|
||||
plugins {
|
||||
id 'com.github.johnrengelman.shadow'
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compileOnly 'net.md-5:bungeecord-api:1.21-R0.2'
|
||||
compileOnly project(':Common:Source')
|
||||
compileOnly project(':Common:loader-utils')
|
||||
implementation 'org.bstats:bstats-bungeecord:2.2.1'
|
||||
}
|
||||
|
||||
shadowJar {
|
||||
archiveClassifier.set('')
|
||||
relocate 'org.bstats', 'dev.brighten.antivpn.bungee.org.bstats'
|
||||
relocate 'org.yaml.snakeyaml', 'dev.brighten.antivpn.shaded.org.yaml.snakeyaml'
|
||||
}
|
||||
|
||||
tasks.build.dependsOn shadowJar
|
||||
@@ -1,112 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
~ Copyright 2026 Dawson Hessler
|
||||
~
|
||||
~ Licensed 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.
|
||||
-->
|
||||
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>dev.brighten.antivpn</groupId>
|
||||
<artifactId>Bungee</artifactId>
|
||||
<version>1.10.0</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
<artifactId>BungeePlugin</artifactId>
|
||||
|
||||
<properties>
|
||||
<maven.compiler.source>17</maven.compiler.source>
|
||||
<maven.compiler.target>17</maven.compiler.target>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.13.0</version>
|
||||
<configuration>
|
||||
<source>17</source>
|
||||
<target>17</target>
|
||||
<compilerArgument>-XDignore.symbol.file</compilerArgument>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-shade-plugin</artifactId>
|
||||
<version>3.6.0</version>
|
||||
<configuration>
|
||||
<relocations>
|
||||
<relocation>
|
||||
<pattern>org.bstats</pattern>
|
||||
<!-- Replace this with your package! -->
|
||||
<shadedPattern>dev.brighten.antivpn.bungee.org.bstats</shadedPattern>
|
||||
</relocation>
|
||||
<relocation>
|
||||
<pattern>org.yaml.snakeyaml</pattern>
|
||||
<shadedPattern>dev.brighten.antivpn.shaded.org.yaml.snakeyaml</shadedPattern>
|
||||
</relocation>
|
||||
</relocations>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>shade</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
<resources>
|
||||
<resource>
|
||||
<directory>src/main/resources</directory>
|
||||
<filtering>true</filtering>
|
||||
</resource>
|
||||
</resources>
|
||||
</build>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>dev.brighten.antivpn</groupId>
|
||||
<artifactId>Source</artifactId>
|
||||
<version>1.10.0</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>net.md-5</groupId>
|
||||
<artifactId>bungeecord-api</artifactId>
|
||||
<version>1.21-R0.2</version>
|
||||
<type>jar</type>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.bstats</groupId>
|
||||
<artifactId>bstats-bungeecord</artifactId>
|
||||
<version>2.2.1</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>dev.brighten.antivpn</groupId>
|
||||
<artifactId>loader-utils</artifactId>
|
||||
<version>1.10.0</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
+110
@@ -0,0 +1,110 @@
|
||||
package dev.brighten.antivpn.bungee;
|
||||
|
||||
import dev.brighten.antivpn.AntiVPN;
|
||||
import dev.brighten.antivpn.api.PlayerExecutor;
|
||||
import dev.brighten.antivpn.api.VPNConfig;
|
||||
import dev.brighten.antivpn.api.VPNExecutor;
|
||||
import dev.brighten.antivpn.message.MessageHandler;
|
||||
import dev.brighten.antivpn.message.VpnString;
|
||||
import dev.brighten.antivpn.web.objects.VPNResponse;
|
||||
import net.md_5.bungee.api.connection.PendingConnection;
|
||||
import net.md_5.bungee.api.event.PreLoginEvent;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
public class BungeeListenerTest {
|
||||
|
||||
private BungeeListener listener;
|
||||
private VPNExecutor vpnExecutor;
|
||||
|
||||
@BeforeEach
|
||||
public void setUp() throws Exception {
|
||||
AntiVPN antiVPN = mock(AntiVPN.class);
|
||||
VPNConfig config = mock(VPNConfig.class);
|
||||
PlayerExecutor playerExecutor = mock(PlayerExecutor.class);
|
||||
vpnExecutor = mock(VPNExecutor.class);
|
||||
MessageHandler messageHandler = mock(MessageHandler.class);
|
||||
|
||||
when(antiVPN.getVpnConfig()).thenReturn(config);
|
||||
when(antiVPN.getPlayerExecutor()).thenReturn(playerExecutor);
|
||||
when(antiVPN.getExecutor()).thenReturn(vpnExecutor);
|
||||
when(antiVPN.getMessageHandler()).thenReturn(messageHandler);
|
||||
|
||||
when(playerExecutor.getPlayer(any(UUID.class))).thenReturn(Optional.empty());
|
||||
when(config.getPrefixWhitelists()).thenReturn(java.util.Collections.emptyList());
|
||||
when(config.getCountryList()).thenReturn(java.util.Collections.emptyList());
|
||||
when(config.isKickPlayers()).thenReturn(true);
|
||||
when(config.getKickMessage()).thenReturn("Blocked!");
|
||||
|
||||
VpnString mockVpnString = mock(VpnString.class);
|
||||
when(mockVpnString.getFormattedMessage(any())).thenReturn("Blocked!");
|
||||
when(messageHandler.getString(anyString())).thenReturn(mockVpnString);
|
||||
|
||||
when(vpnExecutor.checkIp(anyString())).thenReturn(CompletableFuture.completedFuture(
|
||||
VPNResponse.builder().success(true).proxy(false).ip("127.0.0.1")
|
||||
.method("N/A").countryName("N/A").city("N/A").build()
|
||||
));
|
||||
|
||||
// Use reflection to set the private static INSTANCE field
|
||||
Field instanceField = AntiVPN.class.getDeclaredField("INSTANCE");
|
||||
instanceField.setAccessible(true);
|
||||
instanceField.set(null, antiVPN);
|
||||
|
||||
listener = new BungeeListener();
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
public void tearDown() throws Exception {
|
||||
// Reset the singleton
|
||||
Field instanceField = AntiVPN.class.getDeclaredField("INSTANCE");
|
||||
instanceField.setAccessible(true);
|
||||
instanceField.set(null, null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPreLoginEventAllowed() {
|
||||
PreLoginEvent event = mock(PreLoginEvent.class);
|
||||
PendingConnection connection = mock(PendingConnection.class);
|
||||
|
||||
when(event.getConnection()).thenReturn(connection);
|
||||
when(connection.getUniqueId()).thenReturn(UUID.randomUUID());
|
||||
when(connection.getName()).thenReturn("TestPlayer");
|
||||
when(connection.getSocketAddress()).thenReturn(new InetSocketAddress("127.0.0.1", 12345));
|
||||
|
||||
listener.onListener(event);
|
||||
|
||||
verify(event, never()).setCancelled(true);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPreLoginEventBlocked() {
|
||||
PreLoginEvent event = mock(PreLoginEvent.class);
|
||||
PendingConnection connection = mock(PendingConnection.class);
|
||||
|
||||
UUID uuid = UUID.randomUUID();
|
||||
when(event.getConnection()).thenReturn(connection);
|
||||
when(connection.getUniqueId()).thenReturn(uuid);
|
||||
when(connection.getName()).thenReturn("ProxyPlayer");
|
||||
when(connection.getSocketAddress()).thenReturn(new InetSocketAddress("1.1.1.1", 12345));
|
||||
|
||||
// Mock proxy response
|
||||
when(vpnExecutor.checkIp("1.1.1.1")).thenReturn(CompletableFuture.completedFuture(
|
||||
VPNResponse.builder().success(true).proxy(true).ip("1.1.1.1")
|
||||
.method("N/A").countryName("N/A").countryCode("N/A").city("N/A").build()
|
||||
));
|
||||
|
||||
listener.onListener(event);
|
||||
|
||||
verify(event).setCancelled(true);
|
||||
verify(event).setReason(any());
|
||||
}
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
~ Copyright 2026 Dawson Hessler
|
||||
~
|
||||
~ Licensed 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.
|
||||
-->
|
||||
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<artifactId>AntiVPN</artifactId>
|
||||
<groupId>dev.brighten.antivpn</groupId>
|
||||
<version>1.10.0</version>
|
||||
</parent>
|
||||
<packaging>pom</packaging>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>Bungee</artifactId>
|
||||
|
||||
</project>
|
||||
+33
-23
@@ -4,36 +4,46 @@ All notable changes to this project will be documented in this file.
|
||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
## [1.10.0] - 2026-04-07
|
||||
|
||||
### Added
|
||||
- CIDR allowlisting, including commands to add, remove, view, and search entries
|
||||
- MongoDB support for CIDR allowlist storage
|
||||
- VPN detection webhooks with Discord and Slack formatting options
|
||||
- Mojang API fallback support for player lookups
|
||||
- Folia support
|
||||
|
||||
### Changed
|
||||
- Improved player blocking so flagged users are removed more reliably across platforms
|
||||
- Updated allowlist handling to validate CIDR entries more consistently
|
||||
- Improved database cleanup for outdated cached responses
|
||||
|
||||
### Fixed
|
||||
- SQL startup and loading issues, including MySQL library injection problems
|
||||
- CIDR parsing issues and MongoDB CIDR lookup failures
|
||||
- Allowlist-related SQL errors
|
||||
- Repeated webhook spam from duplicate VPN detection events
|
||||
|
||||
### Documentation
|
||||
- Expanded webhook setup documentation for Discord and Slack
|
||||
|
||||
## [1.9.4] - 2025-09-30
|
||||
|
||||
### Added
|
||||
- New dependency management system with automatic library loading and relocation
|
||||
- Caffeine cache implementation to replace Guava
|
||||
- Sponge platform support with full event handling and command system
|
||||
- UUID lookup functionality for player validation
|
||||
- Enhanced kick checking system with scheduled task execution
|
||||
- Support for Java 17 and Java 21 runtime environments
|
||||
- New database metrics tracking for bStats
|
||||
- Sponge platform support
|
||||
- UUID lookup support for player validation
|
||||
- Better scheduled kick checking
|
||||
- Java 17 and Java 21 support
|
||||
- Database metrics tracking for bStats
|
||||
|
||||
### Changed
|
||||
- **BREAKING**: Minimum Java version upgraded from 8 to 17
|
||||
- Replaced Guava cache with Caffeine cache for better performance
|
||||
- Modernized player checking system with asynchronous processing
|
||||
- Improved database connection handling with proper resource management
|
||||
- Enhanced VPN/Proxy detection with new `CheckResult` and `ResultType` system
|
||||
- Updated Maven dependencies and build process
|
||||
- Reorganized project structure (Assembly → Universal module)
|
||||
- Improved error handling and exception logging throughout codebase
|
||||
- Replaced the old cache implementation with Caffeine for better performance
|
||||
- Improved asynchronous player checking and VPN detection handling
|
||||
- Improved database connection management and error handling
|
||||
|
||||
### Fixed
|
||||
- H2 database compatibility issues with automatic backup and recovery
|
||||
- Memory leaks in database result set handling with try-with-resources
|
||||
- Memory leaks and resource cleanup problems in database handling
|
||||
- Thread safety issues in player cache management
|
||||
- Command registration and unregistration during plugin lifecycle
|
||||
- Proper cleanup of database drivers on shutdown
|
||||
- Resource management in SQL connections and prepared statements
|
||||
|
||||
### Removed
|
||||
- Guava dependency (replaced with Caffeine and built-in utilities)
|
||||
- Legacy cached response handling system
|
||||
- Old table format compatibility code
|
||||
- Command registration issues during plugin startup and shutdown
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
plugins {
|
||||
id 'com.github.johnrengelman.shadow'
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation 'org.ow2.asm:asm:9.8'
|
||||
implementation 'org.ow2.asm:asm-commons:9.8'
|
||||
implementation 'org.yaml:snakeyaml:2.2'
|
||||
implementation 'org.jetbrains:annotations:26.0.2'
|
||||
|
||||
compileOnly 'com.mysql:mysql-connector-j:9.3.0'
|
||||
compileOnly 'com.h2database:h2:2.2.220'
|
||||
compileOnly 'com.github.ben-manes.caffeine:caffeine:3.1.8'
|
||||
compileOnly 'org.mongodb:mongo-java-driver:3.12.14'
|
||||
}
|
||||
|
||||
shadowJar {
|
||||
archiveClassifier.set('')
|
||||
relocate 'org.yaml.snakeyaml', 'dev.brighten.antivpn.shaded.org.yaml.snakeyaml'
|
||||
relocate 'com.github.benmanes.caffeine', 'dev.brighten.antivpn.shaded.com.github.benmanes.caffeine'
|
||||
relocate 'org.h2', 'dev.brighten.antivpn.shaded.org.h2'
|
||||
relocate 'org.bson', 'dev.brighten.antivpn.shaded.org.bson'
|
||||
relocate 'com.mongodb', 'dev.brighten.antivpn.shaded.com.mongodb'
|
||||
relocate 'com.mysql.cj', 'dev.brighten.antivpn.shaded.com.mysql.cj'
|
||||
relocate 'com.mysql.jdbc', 'dev.brighten.antivpn.shaded.com.mysql.jdbc'
|
||||
|
||||
dependencies {
|
||||
exclude 'dev/brighten/antivpn/depends/Relocate*'
|
||||
exclude 'dev/brighten/antivpn/depends/MavenLibraries*'
|
||||
}
|
||||
}
|
||||
|
||||
tasks.build.dependsOn shadowJar
|
||||
@@ -1,199 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
~ Copyright 2026 Dawson Hessler
|
||||
~
|
||||
~ Licensed 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.
|
||||
-->
|
||||
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>dev.brighten.antivpn</groupId>
|
||||
<artifactId>Common</artifactId>
|
||||
<version>1.10.0</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>Source</artifactId>
|
||||
|
||||
<properties>
|
||||
<maven.compiler.source>17</maven.compiler.source>
|
||||
<maven.compiler.target>17</maven.compiler.target>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.13.0</version>
|
||||
<configuration>
|
||||
<source>17</source>
|
||||
<target>17</target>
|
||||
<compilerArgument>-XDignore.symbol.file</compilerArgument>
|
||||
<annotationProcessorPaths>
|
||||
<path>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<version>1.18.44</version>
|
||||
</path>
|
||||
</annotationProcessorPaths>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-shade-plugin</artifactId>
|
||||
<version>3.6.0</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>shade</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<minimizeJar>false</minimizeJar>
|
||||
<relocations>
|
||||
<relocation>
|
||||
<pattern>org.yaml.snakeyaml</pattern>
|
||||
<shadedPattern>dev.brighten.antivpn.shaded.org.yaml.snakeyaml</shadedPattern>
|
||||
<excludes>
|
||||
<!-- Exclude annotation values from relocation -->
|
||||
<exclude>dev.brighten.antivpn.depends.Relocate</exclude>
|
||||
<exclude>dev.brighten.antivpn.depends.MavenLibraries</exclude>
|
||||
</excludes>
|
||||
</relocation>
|
||||
<relocation>
|
||||
<pattern>com.github.benmanes.caffeine</pattern>
|
||||
<shadedPattern>dev.brighten.antivpn.shaded.com.github.benmanes.caffeine</shadedPattern>
|
||||
</relocation>
|
||||
<relocation>
|
||||
<pattern>org.h2</pattern>
|
||||
<shadedPattern>dev.brighten.antivpn.shaded.org.h2</shadedPattern>
|
||||
<excludes>
|
||||
<!-- Exclude annotation values from relocation -->
|
||||
<exclude>dev.brighten.antivpn.depends.Relocate</exclude>
|
||||
<exclude>dev.brighten.antivpn.depends.MavenLibraries</exclude>
|
||||
</excludes>
|
||||
</relocation>
|
||||
<relocation>
|
||||
<pattern>org.bson</pattern>
|
||||
<shadedPattern>dev.brighten.antivpn.shaded.org.bson</shadedPattern>
|
||||
<excludes>
|
||||
<!-- Exclude annotation values from relocation -->
|
||||
<exclude>dev.brighten.antivpn.depends.Relocate</exclude>
|
||||
<exclude>dev.brighten.antivpn.depends.MavenLibraries</exclude>
|
||||
</excludes>
|
||||
</relocation>
|
||||
<relocation>
|
||||
<pattern>com.mongodb</pattern>
|
||||
<shadedPattern>dev.brighten.antivpn.shaded.com.mongodb</shadedPattern>
|
||||
<excludes>
|
||||
<!-- Exclude annotation values from relocation -->
|
||||
<exclude>dev.brighten.antivpn.depends.Relocate</exclude>
|
||||
<exclude>dev.brighten.antivpn.depends.MavenLibraries</exclude>
|
||||
</excludes>
|
||||
</relocation>
|
||||
<relocation>
|
||||
<pattern>com.mysql.cj</pattern>
|
||||
<shadedPattern>dev.brighten.antivpn.shaded.com.mysql.cj</shadedPattern>
|
||||
<excludes>
|
||||
<!-- Exclude annotation values from relocation -->
|
||||
<exclude>dev.brighten.antivpn.depends.Relocate</exclude>
|
||||
<exclude>dev.brighten.antivpn.depends.MavenLibraries</exclude>
|
||||
</excludes>
|
||||
</relocation>
|
||||
<relocation>
|
||||
<pattern>com.mysql.jdbc</pattern>
|
||||
<shadedPattern>dev.brighten.antivpn.shaded.com.mysql.jdbc</shadedPattern>
|
||||
<excludes>
|
||||
<!-- Exclude annotation values from relocation -->
|
||||
<exclude>dev.brighten.antivpn.depends.Relocate</exclude>
|
||||
<exclude>dev.brighten.antivpn.depends.MavenLibraries</exclude>
|
||||
</excludes>
|
||||
</relocation>
|
||||
</relocations>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
<resources>
|
||||
<resource>
|
||||
<directory>src/main/resources</directory>
|
||||
<filtering>true</filtering>
|
||||
</resource>
|
||||
</resources>
|
||||
</build>
|
||||
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>funkemunky-releases</id>
|
||||
<url>https://nexus.funkemunky.cc/content/repositories/releases/</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.mysql</groupId>
|
||||
<artifactId>mysql-connector-j</artifactId>
|
||||
<version>9.3.0</version>
|
||||
<type>jar</type>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.h2database</groupId>
|
||||
<artifactId>h2</artifactId>
|
||||
<version>2.2.220</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.ow2.asm</groupId>
|
||||
<artifactId>asm</artifactId>
|
||||
<version>9.8</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.ow2.asm</groupId>
|
||||
<artifactId>asm-commons</artifactId>
|
||||
<version>9.8</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.yaml</groupId>
|
||||
<artifactId>snakeyaml</artifactId>
|
||||
<version>2.2</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.github.ben-manes.caffeine</groupId>
|
||||
<artifactId>caffeine</artifactId>
|
||||
<version>3.1.8</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.mongodb</groupId>
|
||||
<artifactId>mongo-java-driver</artifactId>
|
||||
<version>3.12.14</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jetbrains</groupId>
|
||||
<artifactId>annotations</artifactId>
|
||||
<version>26.0.2</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
@@ -206,8 +206,12 @@ public class AntiVPN {
|
||||
executor.log("Failed to deregister H2 driver: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
AntiVPN.getInstance().getExecutor().getThreadExecutor().shutdown();
|
||||
if (executor != null && executor.getThreadExecutor() != null) {
|
||||
executor.getThreadExecutor().shutdown();
|
||||
}
|
||||
if(database != null) database.shutdown();
|
||||
|
||||
INSTANCE = null;
|
||||
}
|
||||
|
||||
public void reloadDatabase() {
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
|
||||
package dev.brighten.antivpn.api;
|
||||
|
||||
import com.github.benmanes.caffeine.cache.Cache;
|
||||
import com.github.benmanes.caffeine.cache.Caffeine;
|
||||
import dev.brighten.antivpn.AntiVPN;
|
||||
import dev.brighten.antivpn.utils.CIDRUtils;
|
||||
import dev.brighten.antivpn.utils.StringUtil;
|
||||
@@ -146,7 +148,18 @@ public abstract class VPNExecutor {
|
||||
}
|
||||
}
|
||||
|
||||
private final Cache<String, VPNResponse> cachedResponses = Caffeine.newBuilder()
|
||||
.expireAfterWrite(20, TimeUnit.MINUTES)
|
||||
.maximumSize(4000)
|
||||
.build();
|
||||
|
||||
public CompletableFuture<VPNResponse> checkIp(String ip) {
|
||||
VPNResponse cached = cachedResponses.getIfPresent(ip);
|
||||
|
||||
if(cached != null) {
|
||||
return CompletableFuture.completedFuture(cached);
|
||||
}
|
||||
|
||||
return CompletableFuture.supplyAsync(() -> {
|
||||
Optional<VPNResponse> cachedRes = AntiVPN.getInstance().getDatabase().getStoredResponse(ip);
|
||||
|
||||
|
||||
@@ -16,8 +16,6 @@
|
||||
|
||||
package dev.brighten.antivpn.database.local;
|
||||
|
||||
import com.github.benmanes.caffeine.cache.Cache;
|
||||
import com.github.benmanes.caffeine.cache.Caffeine;
|
||||
import dev.brighten.antivpn.AntiVPN;
|
||||
import dev.brighten.antivpn.database.VPNDatabase;
|
||||
import dev.brighten.antivpn.database.sql.utils.ExecutableStatement;
|
||||
@@ -40,11 +38,6 @@ import java.util.function.Consumer;
|
||||
|
||||
public class H2VPN implements VPNDatabase {
|
||||
|
||||
private final Cache<String, VPNResponse> cachedResponses = Caffeine.newBuilder()
|
||||
.expireAfterWrite(20, TimeUnit.MINUTES)
|
||||
.maximumSize(4000)
|
||||
.build();
|
||||
|
||||
|
||||
public H2VPN() {
|
||||
AntiVPN.getInstance().getExecutor().getThreadExecutor().scheduleAtFixedRate(() -> {
|
||||
@@ -67,29 +60,25 @@ public class H2VPN implements VPNDatabase {
|
||||
if (!AntiVPN.getInstance().getVpnConfig().isDatabaseEnabled()|| MySQL.isClosed())
|
||||
return Optional.empty();
|
||||
|
||||
VPNResponse response = cachedResponses.get(ip, ip2 -> {
|
||||
try(ExecutableStatement statement = Query.prepare("select * from `responses` where `ip` = ? limit 1").append(ip)) {
|
||||
try(ResultSet rs = statement.executeQuery()) {
|
||||
if (rs != null && rs.next()) {
|
||||
return new VPNResponse(rs.getString("asn"), rs.getString("ip"),
|
||||
rs.getString("countryName"), rs.getString("countryCode"),
|
||||
rs.getString("city"), rs.getString("timeZone"),
|
||||
rs.getString("method"), rs.getString("isp"), "N/A",
|
||||
rs.getBoolean("proxy"), rs.getBoolean("cached"), true,
|
||||
rs.getDouble("latitude"), rs.getDouble("longitude"),
|
||||
rs.getTimestamp("inserted").getTime(), -1);
|
||||
}
|
||||
try(ExecutableStatement statement = Query.prepare("select * from `responses` where `ip` = ? limit 1").append(ip)) {
|
||||
try(ResultSet rs = statement.executeQuery()) {
|
||||
if (rs != null && rs.next()) {
|
||||
return Optional.of(new VPNResponse(rs.getString("asn"), rs.getString("ip"),
|
||||
rs.getString("countryName"), rs.getString("countryCode"),
|
||||
rs.getString("city"), rs.getString("timeZone"),
|
||||
rs.getString("method"), rs.getString("isp"), "N/A",
|
||||
rs.getBoolean("proxy"), rs.getBoolean("cached"), true,
|
||||
rs.getDouble("latitude"), rs.getDouble("longitude"),
|
||||
rs.getTimestamp("inserted").getTime(), -1));
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
AntiVPN.getInstance().getExecutor().logException("There was a problem getting a response for "
|
||||
+ ip, e);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
return null;
|
||||
});
|
||||
|
||||
return Optional.ofNullable(response);
|
||||
} catch (SQLException e) {
|
||||
AntiVPN.getInstance().getExecutor().logException("There was a problem getting a response for "
|
||||
+ ip, e);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -106,20 +95,16 @@ public class H2VPN implements VPNDatabase {
|
||||
if (!AntiVPN.getInstance().getVpnConfig().isDatabaseEnabled() || MySQL.isClosed())
|
||||
return;
|
||||
|
||||
if(AntiVPN.getInstance().getVpnConfig().cachedResults()) {
|
||||
cachedResponses.put(toCache.getIp(), toCache);
|
||||
|
||||
try(var statement = Query.prepare("insert into `responses` (`ip`,`asn`,`countryName`,`countryCode`,`city`,`timeZone`,"
|
||||
+ "`method`,`isp`,`proxy`,`cached`,`inserted`,`latitude`,`longitude`) values (?,?,?,?,?,?,?,?,?,?,?,?,?)")
|
||||
.append(toCache.getIp()).append(toCache.getAsn()).append(toCache.getCountryName())
|
||||
.append(toCache.getCountryCode()).append(toCache.getCity()).append(toCache.getTimeZone())
|
||||
.append(toCache.getMethod()).append(toCache.getIsp()).append(toCache.isProxy())
|
||||
.append(toCache.isCached()).append(new Timestamp(System.currentTimeMillis()))
|
||||
.append(toCache.getLatitude()).append(toCache.getLongitude())) {
|
||||
statement.execute();
|
||||
} catch(SQLException e) {
|
||||
AntiVPN.getInstance().getExecutor().logException("Could not cache response for IP: " + toCache.getIp(), e);
|
||||
}
|
||||
try(var statement = Query.prepare("insert into `responses` (`ip`,`asn`,`countryName`,`countryCode`,`city`,`timeZone`,"
|
||||
+ "`method`,`isp`,`proxy`,`cached`,`inserted`,`latitude`,`longitude`) values (?,?,?,?,?,?,?,?,?,?,?,?,?)")
|
||||
.append(toCache.getIp()).append(toCache.getAsn()).append(toCache.getCountryName())
|
||||
.append(toCache.getCountryCode()).append(toCache.getCity()).append(toCache.getTimeZone())
|
||||
.append(toCache.getMethod()).append(toCache.getIsp()).append(toCache.isProxy())
|
||||
.append(toCache.isCached()).append(new Timestamp(System.currentTimeMillis()))
|
||||
.append(toCache.getLatitude()).append(toCache.getLongitude())) {
|
||||
statement.execute();
|
||||
} catch(SQLException e) {
|
||||
AntiVPN.getInstance().getExecutor().logException("Could not cache response for IP: " + toCache.getIp(), e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -139,6 +124,7 @@ public class H2VPN implements VPNDatabase {
|
||||
public boolean isWhitelisted(UUID uuid) {
|
||||
if (!AntiVPN.getInstance().getVpnConfig().isDatabaseEnabled() || MySQL.isClosed())
|
||||
return false;
|
||||
|
||||
try(var statement = Query.prepare("select uuid from `whitelisted` where `uuid` = ? limit 1")
|
||||
.append(uuid.toString())) {
|
||||
try(var set = statement.executeQuery()) {
|
||||
|
||||
@@ -52,11 +52,11 @@ public class First implements Version<VPNDatabase> {
|
||||
.append(versionNumber())).execute();
|
||||
|
||||
AntiVPN.getInstance().getExecutor().log("Creating indexes...");
|
||||
createIndexIfAbsent("whitelisted", "uuid_1", "`uuid`");
|
||||
createIndexIfAbsent("responses", "ip_1", "`ip`");
|
||||
createIndexIfAbsent("responses", "proxy_1", "`proxy`");
|
||||
createIndexIfAbsent("responses", "inserted_1", "`inserted`");
|
||||
createIndexIfAbsent("whitelisted-ips", "ip_1", "`ip`");
|
||||
createIndexIfAbsent("whitelisted", "whitelisted_uuid_1", "`uuid`");
|
||||
createIndexIfAbsent("responses", "responses_ip_1", "`ip`");
|
||||
createIndexIfAbsent("responses", "responses_proxy_1", "`proxy`");
|
||||
createIndexIfAbsent("responses", "responses_inserted_1", "`inserted`");
|
||||
createIndexIfAbsent("whitelisted-ips", "whitelisted_ips_ip_1", "`ip`");
|
||||
} catch (SQLException e) {
|
||||
throw new DatabaseException("Failed to update database", e);
|
||||
} finally {
|
||||
|
||||
@@ -86,6 +86,7 @@ public class Second extends First implements Version<VPNDatabase> {
|
||||
}
|
||||
|
||||
dropIndexIfPresent("whitelisted-ips", "ip_1");
|
||||
dropIndexIfPresent("whitelisted-ips", "whitelisted_ips_ip_1");
|
||||
closeOnEnd(Query.prepare("DROP TABLE `whitelisted-ips`")).execute();
|
||||
closeOnEnd(Query.prepare("INSERT INTO `database_version` (`version`) VALUES (?)").append(versionNumber())).execute();
|
||||
} catch (Throwable e) {
|
||||
@@ -123,7 +124,7 @@ public class Second extends First implements Version<VPNDatabase> {
|
||||
statement.execute();
|
||||
}
|
||||
|
||||
createIndexIfAbsent("whitelisted-ips", "ip_1", "`ip`");
|
||||
createIndexIfAbsent("whitelisted-ips", "whitelisted_ips_ip_1", "`ip`");
|
||||
|
||||
try(var statement = Query.prepare("DELETE FROM `whitelisted-ips`")) {
|
||||
statement.execute();
|
||||
|
||||
@@ -47,11 +47,6 @@ public class MongoVPN implements VPNDatabase {
|
||||
private MongoClient client;
|
||||
public MongoDatabase antivpnDatabase;
|
||||
|
||||
private final Cache<String, VPNResponse> cachedResponses = Caffeine.newBuilder()
|
||||
.expireAfterWrite(20, TimeUnit.MINUTES)
|
||||
.maximumSize(4000)
|
||||
.build();
|
||||
|
||||
public MongoVPN() {
|
||||
AntiVPN.getInstance().getExecutor().getThreadExecutor().scheduleAtFixedRate(() -> {
|
||||
if(!AntiVPN.getInstance().getVpnConfig().isDatabaseEnabled()) return;
|
||||
@@ -69,37 +64,32 @@ public class MongoVPN implements VPNDatabase {
|
||||
}
|
||||
@Override
|
||||
public Optional<VPNResponse> getStoredResponse(String ip) {
|
||||
VPNResponse response = cachedResponses.get(ip, ip2 -> {
|
||||
Document rdoc = cacheDocument.find(Filters.eq("ip", ip)).first();
|
||||
Document rdoc = cacheDocument.find(Filters.eq("ip", ip)).first();
|
||||
|
||||
if(rdoc != null) {
|
||||
long lastUpdate = rdoc.get("lastAccess", 0L);
|
||||
if(rdoc != null) {
|
||||
long lastUpdate = rdoc.get("lastAccess", 0L);
|
||||
|
||||
if(System.currentTimeMillis() - lastUpdate > TimeUnit.HOURS.toMillis(1)) {
|
||||
AntiVPN.getInstance().getExecutor().getThreadExecutor().execute(() -> deleteResponse(ip));
|
||||
return null;
|
||||
}
|
||||
|
||||
return VPNResponse.builder().asn(rdoc.getString("asn")).ip(ip)
|
||||
.countryName(rdoc.getString("countryName"))
|
||||
.countryCode(rdoc.getString("countryCode"))
|
||||
.city(rdoc.getString("city"))
|
||||
.isp(rdoc.getString("isp"))
|
||||
.method(rdoc.getString("method"))
|
||||
.timeZone(rdoc.getString("timeZone"))
|
||||
.proxy(rdoc.getBoolean("proxy"))
|
||||
.cached(rdoc.getBoolean("cached"))
|
||||
.success(true)
|
||||
.latitude(rdoc.getDouble("latitude"))
|
||||
.longitude(rdoc.getDouble("longitude"))
|
||||
.lastAccess(rdoc.get("lastAccess", 0L))
|
||||
.build();
|
||||
if(System.currentTimeMillis() - lastUpdate > TimeUnit.HOURS.toMillis(1)) {
|
||||
AntiVPN.getInstance().getExecutor().getThreadExecutor().execute(() -> deleteResponse(ip));
|
||||
return null;
|
||||
}
|
||||
return null;
|
||||
});
|
||||
|
||||
|
||||
return Optional.ofNullable(response);
|
||||
return Optional.of(VPNResponse.builder().asn(rdoc.getString("asn")).ip(ip)
|
||||
.countryName(rdoc.getString("countryName"))
|
||||
.countryCode(rdoc.getString("countryCode"))
|
||||
.city(rdoc.getString("city"))
|
||||
.isp(rdoc.getString("isp"))
|
||||
.method(rdoc.getString("method"))
|
||||
.timeZone(rdoc.getString("timeZone"))
|
||||
.proxy(rdoc.getBoolean("proxy"))
|
||||
.cached(rdoc.getBoolean("cached"))
|
||||
.success(true)
|
||||
.latitude(rdoc.getDouble("latitude"))
|
||||
.longitude(rdoc.getDouble("longitude"))
|
||||
.lastAccess(rdoc.get("lastAccess", 0L))
|
||||
.build());
|
||||
}
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -121,8 +111,6 @@ public class MongoVPN implements VPNDatabase {
|
||||
rdoc.put("longitude", toCache.getLongitude());
|
||||
rdoc.put("lastAccess", System.currentTimeMillis());
|
||||
|
||||
cachedResponses.put(toCache.getIp(), toCache);
|
||||
|
||||
AntiVPN.getInstance().getExecutor().getThreadExecutor().execute(() -> {
|
||||
Bson update = new Document("$set", rdoc);
|
||||
cacheDocument.updateOne(Filters.eq("ip", toCache.getIp()), update,
|
||||
|
||||
@@ -26,6 +26,7 @@ import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.sql.Connection;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.SQLSyntaxErrorException;
|
||||
import java.util.Properties;
|
||||
import java.util.logging.Level;
|
||||
|
||||
@@ -48,9 +49,21 @@ public class MySQL {
|
||||
}
|
||||
conn.setAutoCommit(true);
|
||||
Query.use(conn);
|
||||
Query.prepare("CREATE DATABASE IF NOT EXISTS `"
|
||||
+ AntiVPN.getInstance().getVpnConfig().getDatabaseName() + "`").execute();
|
||||
Query.prepare("USE `" + AntiVPN.getInstance().getVpnConfig().getDatabaseName() + "`").execute();
|
||||
String databaseName = AntiVPN.getInstance().getVpnConfig().getDatabaseName();
|
||||
|
||||
try {
|
||||
Query.prepare("CREATE DATABASE IF NOT EXISTS `" + databaseName + "`").execute();
|
||||
} catch (SQLException ex) {
|
||||
if (!isDatabaseCreationPermissionIssue(ex)) {
|
||||
throw ex;
|
||||
}
|
||||
|
||||
AntiVPN.getInstance().getExecutor().log(
|
||||
"No permission to create MySQL database `" + databaseName
|
||||
+ "`. Attempting to use the existing database instead.");
|
||||
}
|
||||
|
||||
Query.prepare("USE `" + databaseName + "`").execute();
|
||||
AntiVPN.getInstance().getExecutor().log("Connection to MySQL has been established.");
|
||||
}
|
||||
} catch (Exception e) {
|
||||
@@ -59,6 +72,12 @@ public class MySQL {
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isDatabaseCreationPermissionIssue(SQLException ex) {
|
||||
return ex instanceof SQLSyntaxErrorException
|
||||
&& ex.getMessage() != null
|
||||
&& ex.getMessage().contains("Access denied");
|
||||
}
|
||||
|
||||
public static void initH2() {
|
||||
initH2(true);
|
||||
}
|
||||
|
||||
+217
@@ -0,0 +1,217 @@
|
||||
package dev.brighten.antivpn.database;
|
||||
|
||||
import dev.brighten.antivpn.AntiVPN;
|
||||
import dev.brighten.antivpn.api.VPNConfig;
|
||||
import dev.brighten.antivpn.api.VPNExecutor;
|
||||
import dev.brighten.antivpn.database.sql.utils.MySQL;
|
||||
import dev.brighten.antivpn.utils.CIDRUtils;
|
||||
import dev.brighten.antivpn.web.objects.VPNResponse;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.io.TempDir;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Field;
|
||||
import java.nio.file.Path;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import java.util.logging.Level;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
import static org.mockito.Mockito.lenient;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
abstract class DatabaseIntegrationTestSupport {
|
||||
|
||||
@TempDir
|
||||
Path pluginFolder;
|
||||
|
||||
@Mock
|
||||
protected AntiVPN antiVPN;
|
||||
|
||||
@Mock
|
||||
protected VPNConfig vpnConfig;
|
||||
|
||||
protected TestVPNExecutor vpnExecutor;
|
||||
private AutoCloseable mocks;
|
||||
private final AtomicReference<VPNDatabase> activeDatabase = new AtomicReference<>();
|
||||
|
||||
@BeforeEach
|
||||
void setUpBase() throws Exception {
|
||||
mocks = MockitoAnnotations.openMocks(this);
|
||||
vpnExecutor = new TestVPNExecutor();
|
||||
|
||||
when(antiVPN.getVpnConfig()).thenReturn(vpnConfig);
|
||||
when(antiVPN.getExecutor()).thenReturn(vpnExecutor);
|
||||
when(antiVPN.getPluginFolder()).thenReturn(pluginFolder.toFile());
|
||||
when(antiVPN.getDatabase()).thenAnswer(invocation -> activeDatabase.get());
|
||||
|
||||
lenient().when(vpnConfig.isDatabaseEnabled()).thenReturn(true);
|
||||
lenient().when(vpnConfig.cachedResults()).thenReturn(true);
|
||||
lenient().when(vpnConfig.getUsername()).thenReturn("testuser");
|
||||
lenient().when(vpnConfig.getPassword()).thenReturn("testpass");
|
||||
lenient().when(vpnConfig.getDatabaseName()).thenReturn("antivpn");
|
||||
lenient().when(vpnConfig.getIp()).thenReturn("127.0.0.1");
|
||||
lenient().when(vpnConfig.getPort()).thenReturn(-1);
|
||||
lenient().when(vpnConfig.mongoDatabaseURL()).thenReturn("");
|
||||
lenient().when(vpnConfig.useDatabaseCreds()).thenReturn(false);
|
||||
|
||||
setAntiVpnInstance(antiVPN);
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
void tearDownBase() throws Exception {
|
||||
VPNDatabase database = activeDatabase.getAndSet(null);
|
||||
if (database != null) {
|
||||
database.shutdown();
|
||||
}
|
||||
|
||||
MySQL.shutdown();
|
||||
if (vpnExecutor != null) {
|
||||
vpnExecutor.getThreadExecutor().shutdownNow();
|
||||
vpnExecutor.getThreadExecutor().awaitTermination(5, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
setAntiVpnInstance(null);
|
||||
|
||||
if (mocks != null) {
|
||||
mocks.close();
|
||||
}
|
||||
}
|
||||
|
||||
protected void registerDatabase(VPNDatabase database) {
|
||||
activeDatabase.set(database);
|
||||
}
|
||||
|
||||
protected void assertDatabaseContract(VPNDatabase database) throws Exception {
|
||||
registerDatabase(database);
|
||||
database.init();
|
||||
|
||||
VPNResponse response = VPNResponse.builder()
|
||||
.ip("1.2.3.4")
|
||||
.asn("AS123")
|
||||
.countryName("United States")
|
||||
.countryCode("US")
|
||||
.city("New York")
|
||||
.proxy(true)
|
||||
.cached(true)
|
||||
.success(true)
|
||||
.build();
|
||||
|
||||
database.cacheResponse(response);
|
||||
|
||||
Optional<VPNResponse> storedResponse = awaitStoredResponse(database, response.getIp());
|
||||
assertTrue(storedResponse.isPresent(), "Expected cached response to be stored");
|
||||
assertEquals("AS123", storedResponse.get().getAsn());
|
||||
assertTrue(storedResponse.get().isProxy());
|
||||
|
||||
database.deleteResponse(response.getIp());
|
||||
awaitCondition(() -> database.getStoredResponse(response.getIp()).isEmpty(),
|
||||
"Expected cached response to be deleted");
|
||||
|
||||
database.cacheResponse(response);
|
||||
awaitCondition(() -> database.getStoredResponse(response.getIp()).isPresent(),
|
||||
"Expected cached response to be restored");
|
||||
|
||||
UUID uuid = UUID.randomUUID();
|
||||
assertFalse(database.isWhitelisted(uuid));
|
||||
database.addWhitelist(uuid);
|
||||
awaitCondition(() -> database.isWhitelisted(uuid), "Expected UUID whitelist entry to exist");
|
||||
List<UUID> whitelisted = database.getAllWhitelisted();
|
||||
assertTrue(whitelisted.contains(uuid));
|
||||
database.removeWhitelist(uuid);
|
||||
awaitCondition(() -> !database.isWhitelisted(uuid), "Expected UUID whitelist entry to be removed");
|
||||
|
||||
CIDRUtils cidr = new CIDRUtils("192.168.1.0/24");
|
||||
assertFalse(database.isWhitelisted(cidr));
|
||||
database.addWhitelist(cidr);
|
||||
awaitCondition(() -> database.isWhitelisted(cidr), "Expected CIDR whitelist entry to exist");
|
||||
List<CIDRUtils> whitelistedIps = database.getAllWhitelistedIps();
|
||||
assertTrue(whitelistedIps.stream().anyMatch(entry -> entry.getCidr().equals(cidr.getCidr())));
|
||||
database.removeWhitelist(cidr);
|
||||
awaitCondition(() -> !database.isWhitelisted(cidr), "Expected CIDR whitelist entry to be removed");
|
||||
|
||||
database.updateAlertsState(uuid, true);
|
||||
awaitCondition(() -> awaitAlertsState(database, uuid), "Expected alerts to be enabled");
|
||||
database.updateAlertsState(uuid, false);
|
||||
awaitCondition(() -> !awaitAlertsState(database, uuid), "Expected alerts to be disabled");
|
||||
|
||||
database.clearResponses();
|
||||
awaitCondition(() -> database.getStoredResponse(response.getIp()).isEmpty(),
|
||||
"Expected cached responses to be cleared");
|
||||
}
|
||||
|
||||
private Optional<VPNResponse> awaitStoredResponse(VPNDatabase database, String ip) throws InterruptedException {
|
||||
AtomicReference<Optional<VPNResponse>> result = new AtomicReference<>(Optional.empty());
|
||||
awaitCondition(() -> {
|
||||
Optional<VPNResponse> response = database.getStoredResponse(ip);
|
||||
result.set(response);
|
||||
return response.isPresent();
|
||||
}, "Timed out waiting for cached response");
|
||||
return result.get();
|
||||
}
|
||||
|
||||
private boolean awaitAlertsState(VPNDatabase database, UUID uuid) throws InterruptedException {
|
||||
CountDownLatch latch = new CountDownLatch(1);
|
||||
AtomicReference<Boolean> result = new AtomicReference<>(false);
|
||||
database.alertsState(uuid, enabled -> {
|
||||
result.set(enabled);
|
||||
latch.countDown();
|
||||
});
|
||||
assertTrue(latch.await(2, TimeUnit.SECONDS), "Timed out waiting for alerts state callback");
|
||||
return result.get();
|
||||
}
|
||||
|
||||
protected void awaitCondition(CheckedBooleanSupplier condition, String failureMessage) throws InterruptedException {
|
||||
long deadline = System.nanoTime() + TimeUnit.SECONDS.toNanos(10);
|
||||
while (System.nanoTime() < deadline) {
|
||||
try {
|
||||
if (condition.getAsBoolean()) {
|
||||
return;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
fail(e.getMessage(), e);
|
||||
return;
|
||||
}
|
||||
Thread.sleep(100);
|
||||
}
|
||||
fail(failureMessage);
|
||||
}
|
||||
|
||||
private static void setAntiVpnInstance(AntiVPN instance) throws Exception {
|
||||
Field instanceField = AntiVPN.class.getDeclaredField("INSTANCE");
|
||||
instanceField.setAccessible(true);
|
||||
instanceField.set(null, instance);
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
protected interface CheckedBooleanSupplier {
|
||||
boolean getAsBoolean() throws Exception;
|
||||
}
|
||||
|
||||
protected static final class TestVPNExecutor extends VPNExecutor {
|
||||
@Override
|
||||
public void registerListeners() {}
|
||||
|
||||
@Override
|
||||
public void log(Level level, String log, Object... objects) {}
|
||||
|
||||
@Override
|
||||
public void log(String log, Object... objects) {}
|
||||
|
||||
@Override
|
||||
public void logException(String message, Throwable ex) {}
|
||||
|
||||
@Override
|
||||
public void runCommand(String command) {}
|
||||
|
||||
@Override
|
||||
public void disablePlugin() {}
|
||||
}
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
package dev.brighten.antivpn.database;
|
||||
|
||||
import dev.brighten.antivpn.database.local.H2VPN;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
class H2DatabaseIntegrationTest extends DatabaseIntegrationTestSupport {
|
||||
|
||||
@Test
|
||||
void h2DatabaseImplementsTheVpnDatabaseContract() throws Exception {
|
||||
assertDatabaseContract(new H2VPN());
|
||||
}
|
||||
}
|
||||
+40
@@ -0,0 +1,40 @@
|
||||
package dev.brighten.antivpn.database;
|
||||
|
||||
import com.mongodb.client.MongoClients;
|
||||
import dev.brighten.antivpn.database.mongo.MongoVPN;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.bson.Document;
|
||||
import org.testcontainers.containers.MongoDBContainer;
|
||||
import org.testcontainers.junit.jupiter.Container;
|
||||
import org.testcontainers.junit.jupiter.Testcontainers;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
@Testcontainers
|
||||
class MongoDatabaseIntegrationTest extends DatabaseIntegrationTestSupport {
|
||||
|
||||
@Container
|
||||
private static final MongoDBContainer MONGO = new MongoDBContainer("mongo:6.0.14");
|
||||
|
||||
@Test
|
||||
void mongoDatabaseImplementsTheVpnDatabaseContract() throws Exception {
|
||||
assertTrue(MONGO.isRunning(), "Mongo Testcontainer should be running");
|
||||
|
||||
try (var client = MongoClients.create(MONGO.getConnectionString())) {
|
||||
var response = client.getDatabase("admin").runCommand(new Document("ping", 1));
|
||||
assertEquals(1.0d, response.getDouble("ok"), "Expected Mongo container to respond to ping");
|
||||
}
|
||||
|
||||
when(vpnConfig.getIp()).thenReturn(MONGO.getHost());
|
||||
when(vpnConfig.getPort()).thenReturn(MONGO.getMappedPort(27017));
|
||||
when(vpnConfig.getDatabaseName()).thenReturn("antivpn_" + UUID.randomUUID().toString().replace("-", ""));
|
||||
when(vpnConfig.mongoDatabaseURL()).thenReturn("");
|
||||
when(vpnConfig.useDatabaseCreds()).thenReturn(false);
|
||||
|
||||
assertDatabaseContract(new MongoVPN());
|
||||
}
|
||||
}
|
||||
+45
@@ -0,0 +1,45 @@
|
||||
package dev.brighten.antivpn.database;
|
||||
|
||||
import dev.brighten.antivpn.database.sql.MySqlVPN;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.testcontainers.containers.MySQLContainer;
|
||||
import org.testcontainers.junit.jupiter.Container;
|
||||
import org.testcontainers.junit.jupiter.Testcontainers;
|
||||
|
||||
import java.sql.DriverManager;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
@Testcontainers
|
||||
class MySqlDatabaseIntegrationTest extends DatabaseIntegrationTestSupport {
|
||||
|
||||
@Container
|
||||
private static final MySQLContainer<?> MYSQL = new MySQLContainer<>("mysql:8.0.36")
|
||||
.withDatabaseName("antivpn")
|
||||
.withUsername("testuser")
|
||||
.withPassword("testpass");
|
||||
|
||||
@Test
|
||||
void mysqlDatabaseImplementsTheVpnDatabaseContract() throws Exception {
|
||||
assertTrue(MYSQL.isRunning(), "MySQL Testcontainer should be running");
|
||||
|
||||
try (var connection = DriverManager.getConnection(MYSQL.getJdbcUrl(), MYSQL.getUsername(), MYSQL.getPassword());
|
||||
var statement = connection.createStatement();
|
||||
var resultSet = statement.executeQuery("SELECT 1")) {
|
||||
assertTrue(resultSet.next(), "Expected a row from the MySQL container");
|
||||
assertEquals(1, resultSet.getInt(1), "Expected MySQL container to respond to SELECT 1");
|
||||
}
|
||||
|
||||
var pingResult = MYSQL.execInContainer("mysqladmin", "ping", "-h", "127.0.0.1", "-ptestpass");
|
||||
assertEquals(0, pingResult.getExitCode(), "Expected mysqladmin ping to succeed inside the container");
|
||||
|
||||
when(vpnConfig.getIp()).thenReturn(MYSQL.getHost());
|
||||
when(vpnConfig.getPort()).thenReturn(MYSQL.getMappedPort(3306));
|
||||
when(vpnConfig.getDatabaseName()).thenReturn(MYSQL.getDatabaseName());
|
||||
when(vpnConfig.getUsername()).thenReturn(MYSQL.getUsername());
|
||||
when(vpnConfig.getPassword()).thenReturn(MYSQL.getPassword());
|
||||
|
||||
assertDatabaseContract(new MySqlVPN());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
dependencies {
|
||||
// No special dependencies for loader-utils other than lombok from root
|
||||
}
|
||||
@@ -1,64 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
~ Copyright 2026 Dawson Hessler
|
||||
~
|
||||
~ Licensed 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.
|
||||
-->
|
||||
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>dev.brighten.antivpn</groupId>
|
||||
<artifactId>Common</artifactId>
|
||||
<version>1.10.0</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>loader-utils</artifactId>
|
||||
|
||||
<properties>
|
||||
<maven.compiler.source>17</maven.compiler.source>
|
||||
<maven.compiler.target>17</maven.compiler.target>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.13.0</version>
|
||||
<configuration>
|
||||
<source>17</source>
|
||||
<target>17</target>
|
||||
<compilerArgument>-XDignore.symbol.file</compilerArgument>
|
||||
<annotationProcessorPaths>
|
||||
<path>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<version>1.18.44</version>
|
||||
</path>
|
||||
</annotationProcessorPaths>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
<resources>
|
||||
<resource>
|
||||
<directory>src/main/resources</directory>
|
||||
<filtering>true</filtering>
|
||||
</resource>
|
||||
</resources>
|
||||
</build>
|
||||
|
||||
</project>
|
||||
@@ -1,40 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
~ Copyright 2026 Dawson Hessler
|
||||
~
|
||||
~ Licensed 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.
|
||||
-->
|
||||
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<artifactId>AntiVPN</artifactId>
|
||||
<groupId>dev.brighten.antivpn</groupId>
|
||||
<version>1.10.0</version>
|
||||
</parent>
|
||||
<packaging>pom</packaging>
|
||||
<modules>
|
||||
<module>loader-utils</module>
|
||||
<module>Source</module>
|
||||
</modules>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>Common</artifactId>
|
||||
|
||||
<properties>
|
||||
<maven.compiler.source>17</maven.compiler.source>
|
||||
<maven.compiler.target>17</maven.compiler.target>
|
||||
</properties>
|
||||
|
||||
</project>
|
||||
@@ -0,0 +1,26 @@
|
||||
plugins {
|
||||
id 'com.github.johnrengelman.shadow'
|
||||
}
|
||||
|
||||
evaluationDependsOn(':Sponge:SpongePlugin')
|
||||
|
||||
dependencies {
|
||||
compileOnly 'org.spongepowered:spongeapi:11.0.0'
|
||||
compileOnly project(':Sponge:SpongePlugin')
|
||||
implementation project(':Common:loader-utils')
|
||||
}
|
||||
|
||||
shadowJar {
|
||||
archiveClassifier.set('')
|
||||
|
||||
// Include the shaded plugin jar as a single resource file
|
||||
from(project(':Sponge:SpongePlugin').tasks.shadowJar) {
|
||||
rename { 'antivpn-sponge.jarinjar' }
|
||||
}
|
||||
}
|
||||
|
||||
tasks.named('shadowJar') {
|
||||
dependsOn(':Sponge:SpongePlugin:shadowJar')
|
||||
}
|
||||
|
||||
tasks.build.dependsOn shadowJar
|
||||
@@ -1,113 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
~ Copyright 2026 Dawson Hessler
|
||||
~
|
||||
~ Licensed 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.
|
||||
-->
|
||||
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>dev.brighten.antivpn</groupId>
|
||||
<artifactId>Sponge</artifactId>
|
||||
<version>1.10.0</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
<artifactId>SpongeLoader</artifactId>
|
||||
|
||||
<properties>
|
||||
<maven.compiler.source>17</maven.compiler.source>
|
||||
<maven.compiler.target>17</maven.compiler.target>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>maven-repo</id>
|
||||
<url>https://nexus.funkemunky.cc/repository/maven-public/</url>
|
||||
</repository>
|
||||
<repository>
|
||||
<id>funkemunky-releases</id>
|
||||
<url>https://nexus.funkemunky.cc/content/repositories/releases/</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.13.0</version>
|
||||
<configuration>
|
||||
<source>17</source>
|
||||
<target>17</target>
|
||||
<compilerArgument>-XDignore.symbol.file</compilerArgument>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-shade-plugin</artifactId>
|
||||
<version>3.6.0</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>shade</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<minimizeJar>false</minimizeJar>
|
||||
<transformers>
|
||||
<transformer implementation="org.apache.maven.plugins.shade.resource.IncludeResourceTransformer">
|
||||
<resource>antivpn-sponge.jarinjar</resource>
|
||||
<file>${project.parent.basedir}/SpongePlugin/target/SpongePlugin-${project.version}.jar</file>
|
||||
</transformer>
|
||||
</transformers>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
<resources>
|
||||
<resource>
|
||||
<directory>src/main/resources</directory>
|
||||
<filtering>true</filtering>
|
||||
</resource>
|
||||
</resources>
|
||||
</build>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.spongepowered</groupId>
|
||||
<artifactId>spongeapi</artifactId>
|
||||
<version>11.0.0</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>dev.brighten.antivpn</groupId>
|
||||
<artifactId>SpongePlugin</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>dev.brighten.antivpn</groupId>
|
||||
<artifactId>loader-utils</artifactId>
|
||||
<version>1.10.0</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
|
||||
</project>
|
||||
@@ -0,0 +1,28 @@
|
||||
plugins {
|
||||
id 'com.github.johnrengelman.shadow'
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compileOnly 'org.spongepowered:spongeapi:11.0.0'
|
||||
compileOnly project(':Common:Source')
|
||||
compileOnly project(':Common:loader-utils')
|
||||
}
|
||||
|
||||
shadowJar {
|
||||
archiveClassifier.set('')
|
||||
|
||||
// SpongePlugin pom.xml had some excludes in shade plugin
|
||||
exclude 'com/google/**'
|
||||
exclude 'org/objectweb/**'
|
||||
exclude 'org/checkerframework/**'
|
||||
|
||||
relocate 'org.yaml.snakeyaml', 'dev.brighten.antivpn.shaded.org.yaml.snakeyaml'
|
||||
relocate 'com.github.benmanes.caffeine', 'dev.brighten.antivpn.shaded.com.github.benmanes.caffeine'
|
||||
relocate 'org.h2', 'dev.brighten.antivpn.shaded.org.h2'
|
||||
relocate 'org.bson', 'dev.brighten.antivpn.shaded.org.bson'
|
||||
relocate 'com.mongodb', 'dev.brighten.antivpn.shaded.com.mongodb'
|
||||
relocate 'com.mysql.cj', 'dev.brighten.antivpn.shaded.com.mysql.cj'
|
||||
relocate 'com.mysql.jdbc', 'dev.brighten.antivpn.shaded.com.mysql.jdbc'
|
||||
}
|
||||
|
||||
tasks.build.dependsOn shadowJar
|
||||
@@ -1,175 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
~ Copyright 2026 Dawson Hessler
|
||||
~
|
||||
~ Licensed 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.
|
||||
-->
|
||||
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>dev.brighten.antivpn</groupId>
|
||||
<artifactId>Sponge</artifactId>
|
||||
<version>1.10.0</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
<artifactId>SpongePlugin</artifactId>
|
||||
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>maven-repo</id>
|
||||
<url>https://nexus.funkemunky.cc/repository/maven-public/</url>
|
||||
</repository>
|
||||
<repository>
|
||||
<id>funkemunky-releases</id>
|
||||
<url>https://nexus.funkemunky.cc/content/repositories/releases/</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.spongepowered</groupId>
|
||||
<artifactId>spongeapi</artifactId>
|
||||
<version>11.0.0</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>dev.brighten.antivpn</groupId>
|
||||
<artifactId>loader-utils</artifactId>
|
||||
<version>1.10.0</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>dev.brighten.antivpn</groupId>
|
||||
<artifactId>Source</artifactId>
|
||||
<version>1.10.0</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<properties>
|
||||
<maven.compiler.source>17</maven.compiler.source>
|
||||
<maven.compiler.target>17</maven.compiler.target>
|
||||
</properties>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.13.0</version>
|
||||
<configuration>
|
||||
<source>17</source>
|
||||
<target>17</target>
|
||||
<compilerArgument>-XDignore.symbol.file</compilerArgument>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-shade-plugin</artifactId>
|
||||
<version>3.6.0</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>shade</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<filters>
|
||||
<filter>
|
||||
<artifact>*:*</artifact>
|
||||
<excludes>
|
||||
<exclude>com/google/**</exclude>
|
||||
<exclude>org/objectweb/**</exclude>
|
||||
<exclude>org/checkerframework/**</exclude>
|
||||
</excludes>
|
||||
</filter>
|
||||
|
||||
</filters>
|
||||
<relocations>
|
||||
<relocation>
|
||||
<pattern>org.yaml.snakeyaml</pattern>
|
||||
<shadedPattern>dev.brighten.antivpn.shaded.org.yaml.snakeyaml</shadedPattern>
|
||||
<excludes>
|
||||
<!-- Exclude annotation values from relocation -->
|
||||
<exclude>dev.brighten.antivpn.depends.Relocate</exclude>
|
||||
<exclude>dev.brighten.antivpn.depends.MavenLibraries</exclude>
|
||||
</excludes>
|
||||
</relocation>
|
||||
<relocation>
|
||||
<pattern>com.github.benmanes.caffeine</pattern>
|
||||
<shadedPattern>dev.brighten.antivpn.shaded.com.github.benmanes.caffeine</shadedPattern>
|
||||
</relocation>
|
||||
<relocation>
|
||||
<pattern>org.h2</pattern>
|
||||
<shadedPattern>dev.brighten.antivpn.shaded.org.h2</shadedPattern>
|
||||
<excludes>
|
||||
<!-- Exclude annotation values from relocation -->
|
||||
<exclude>dev.brighten.antivpn.depends.Relocate</exclude>
|
||||
<exclude>dev.brighten.antivpn.depends.MavenLibraries</exclude>
|
||||
</excludes>
|
||||
</relocation>
|
||||
<relocation>
|
||||
<pattern>org.bson</pattern>
|
||||
<shadedPattern>dev.brighten.antivpn.shaded.org.bson</shadedPattern>
|
||||
<excludes>
|
||||
<!-- Exclude annotation values from relocation -->
|
||||
<exclude>dev.brighten.antivpn.depends.Relocate</exclude>
|
||||
<exclude>dev.brighten.antivpn.depends.MavenLibraries</exclude>
|
||||
</excludes>
|
||||
</relocation>
|
||||
<relocation>
|
||||
<pattern>com.mongodb</pattern>
|
||||
<shadedPattern>dev.brighten.antivpn.shaded.com.mongodb</shadedPattern>
|
||||
<excludes>
|
||||
<!-- Exclude annotation values from relocation -->
|
||||
<exclude>dev.brighten.antivpn.depends.Relocate</exclude>
|
||||
<exclude>dev.brighten.antivpn.depends.MavenLibraries</exclude>
|
||||
</excludes>
|
||||
</relocation>
|
||||
<relocation>
|
||||
<pattern>com.mysql.cj</pattern>
|
||||
<shadedPattern>dev.brighten.antivpn.shaded.com.mysql.cj</shadedPattern>
|
||||
<excludes>
|
||||
<!-- Exclude annotation values from relocation -->
|
||||
<exclude>dev.brighten.antivpn.depends.Relocate</exclude>
|
||||
<exclude>dev.brighten.antivpn.depends.MavenLibraries</exclude>
|
||||
</excludes>
|
||||
</relocation>
|
||||
<relocation>
|
||||
<pattern>com.mysql.jdbc</pattern>
|
||||
<shadedPattern>dev.brighten.antivpn.shaded.com.mysql.jdbc</shadedPattern>
|
||||
<excludes>
|
||||
<!-- Exclude annotation values from relocation -->
|
||||
<exclude>dev.brighten.antivpn.depends.Relocate</exclude>
|
||||
<exclude>dev.brighten.antivpn.depends.MavenLibraries</exclude>
|
||||
</excludes>
|
||||
</relocation>
|
||||
</relocations>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
<resources>
|
||||
<resource>
|
||||
<directory>src/main/resources</directory>
|
||||
<filtering>true</filtering>
|
||||
</resource>
|
||||
</resources>
|
||||
</build>
|
||||
|
||||
</project>
|
||||
+114
@@ -0,0 +1,114 @@
|
||||
package dev.brighten.antivpn.sponge;
|
||||
|
||||
import dev.brighten.antivpn.AntiVPN;
|
||||
import dev.brighten.antivpn.api.PlayerExecutor;
|
||||
import dev.brighten.antivpn.api.VPNConfig;
|
||||
import dev.brighten.antivpn.api.VPNExecutor;
|
||||
import dev.brighten.antivpn.message.MessageHandler;
|
||||
import dev.brighten.antivpn.message.VpnString;
|
||||
import dev.brighten.antivpn.web.objects.VPNResponse;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.spongepowered.api.event.network.ServerSideConnectionEvent;
|
||||
import org.spongepowered.api.network.ServerSideConnection;
|
||||
import org.spongepowered.api.profile.GameProfile;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
public class SpongeListenerTest {
|
||||
|
||||
private SpongeListener listener;
|
||||
private VPNExecutor vpnExecutor;
|
||||
|
||||
@BeforeEach
|
||||
public void setUp() throws Exception {
|
||||
AntiVPN antiVPN = mock(AntiVPN.class);
|
||||
VPNConfig config = mock(VPNConfig.class);
|
||||
PlayerExecutor playerExecutor = mock(PlayerExecutor.class);
|
||||
vpnExecutor = mock(VPNExecutor.class);
|
||||
MessageHandler messageHandler = mock(MessageHandler.class);
|
||||
|
||||
when(antiVPN.getVpnConfig()).thenReturn(config);
|
||||
when(antiVPN.getPlayerExecutor()).thenReturn(playerExecutor);
|
||||
when(antiVPN.getExecutor()).thenReturn(vpnExecutor);
|
||||
when(antiVPN.getMessageHandler()).thenReturn(messageHandler);
|
||||
|
||||
when(playerExecutor.getPlayer(any(UUID.class))).thenReturn(Optional.empty());
|
||||
when(config.getPrefixWhitelists()).thenReturn(java.util.Collections.emptyList());
|
||||
when(config.getCountryList()).thenReturn(java.util.Collections.emptyList());
|
||||
when(config.isKickPlayers()).thenReturn(true);
|
||||
when(config.getKickMessage()).thenReturn("Blocked!");
|
||||
|
||||
VpnString mockVpnString = mock(VpnString.class);
|
||||
when(mockVpnString.getFormattedMessage(any())).thenReturn("Blocked!");
|
||||
when(messageHandler.getString(anyString())).thenReturn(mockVpnString);
|
||||
|
||||
when(vpnExecutor.checkIp(anyString())).thenReturn(CompletableFuture.completedFuture(
|
||||
VPNResponse.builder().success(true).proxy(false).ip("127.0.0.1")
|
||||
.method("N/A").countryName("N/A").city("N/A").build()
|
||||
));
|
||||
|
||||
// Use reflection to set the private static INSTANCE field
|
||||
Field instanceField = AntiVPN.class.getDeclaredField("INSTANCE");
|
||||
instanceField.setAccessible(true);
|
||||
instanceField.set(null, antiVPN);
|
||||
|
||||
listener = new SpongeListener();
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
public void tearDown() throws Exception {
|
||||
// Reset the singleton
|
||||
Field instanceField = AntiVPN.class.getDeclaredField("INSTANCE");
|
||||
instanceField.setAccessible(true);
|
||||
instanceField.set(null, null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLoginEventAllowed() {
|
||||
ServerSideConnectionEvent.Login event = mock(ServerSideConnectionEvent.Login.class);
|
||||
GameProfile profile = mock(GameProfile.class);
|
||||
ServerSideConnection connection = mock(ServerSideConnection.class);
|
||||
|
||||
when(event.profile()).thenReturn(profile);
|
||||
when(event.connection()).thenReturn(connection);
|
||||
when(profile.uuid()).thenReturn(UUID.randomUUID());
|
||||
when(profile.name()).thenReturn(Optional.of("TestPlayer"));
|
||||
when(connection.address()).thenReturn(new InetSocketAddress("127.0.0.1", 12345));
|
||||
|
||||
listener.onJoin(event);
|
||||
|
||||
verify(event, never()).setCancelled(true);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLoginEventBlocked() {
|
||||
ServerSideConnectionEvent.Login event = mock(ServerSideConnectionEvent.Login.class);
|
||||
GameProfile profile = mock(GameProfile.class);
|
||||
ServerSideConnection connection = mock(ServerSideConnection.class);
|
||||
|
||||
when(event.profile()).thenReturn(profile);
|
||||
when(event.connection()).thenReturn(connection);
|
||||
when(profile.uuid()).thenReturn(UUID.randomUUID());
|
||||
when(profile.name()).thenReturn(Optional.of("ProxyPlayer"));
|
||||
when(connection.address()).thenReturn(new InetSocketAddress("1.1.1.1", 12345));
|
||||
|
||||
// Mock proxy response
|
||||
when(vpnExecutor.checkIp("1.1.1.1")).thenReturn(CompletableFuture.completedFuture(
|
||||
VPNResponse.builder().success(true).proxy(true).ip("1.1.1.1")
|
||||
.method("N/A").countryName("N/A").countryCode("N/A").city("N/A").build()
|
||||
));
|
||||
|
||||
listener.onJoin(event);
|
||||
|
||||
verify(event).setCancelled(true);
|
||||
verify(event).setMessage(any());
|
||||
}
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
~ Copyright 2026 Dawson Hessler
|
||||
~
|
||||
~ Licensed 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.
|
||||
-->
|
||||
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>dev.brighten.antivpn</groupId>
|
||||
<artifactId>AntiVPN</artifactId>
|
||||
<version>1.10.0</version>
|
||||
</parent>
|
||||
<packaging>pom</packaging>
|
||||
<modules>
|
||||
<module>SpongePlugin</module>
|
||||
<module>SpongeLoader</module>
|
||||
</modules>
|
||||
|
||||
<artifactId>Sponge</artifactId>
|
||||
|
||||
<properties>
|
||||
<maven.compiler.source>17</maven.compiler.source>
|
||||
<maven.compiler.target>17</maven.compiler.target>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
|
||||
</project>
|
||||
@@ -0,0 +1,36 @@
|
||||
plugins {
|
||||
id 'com.github.johnrengelman.shadow'
|
||||
}
|
||||
|
||||
// Aggregate universal jar that embeds platform loaders and the common source jar
|
||||
|
||||
evaluationDependsOn(':Common:Source')
|
||||
|
||||
dependencies {
|
||||
implementation project(':Bukkit:Loader')
|
||||
implementation project(':Velocity:VelocityLoader')
|
||||
implementation project(':Bungee:BungeeLoader')
|
||||
}
|
||||
|
||||
shadowJar {
|
||||
archiveClassifier.set('')
|
||||
archiveBaseName.set("AntiVPN-${project.version}-universal")
|
||||
|
||||
// Include the shaded Common:Source jar as a single resource
|
||||
from(project(':Common:Source').tasks.shadowJar) {
|
||||
rename { 'antivpn-source.jarinjar' }
|
||||
}
|
||||
|
||||
relocate 'org.yaml.snakeyaml', 'dev.brighten.antivpn.shaded.org.yaml.snakeyaml'
|
||||
relocate 'org.bstats', 'dev.brighten.antivpn.shaded.org.bstats'
|
||||
relocate 'org.objectweb', 'dev.brighten.antivpn.shaded.org.objectweb'
|
||||
}
|
||||
|
||||
tasks.named('shadowJar') {
|
||||
dependsOn(':Common:Source:shadowJar')
|
||||
dependsOn(':Bukkit:Loader:shadowJar')
|
||||
dependsOn(':Velocity:VelocityLoader:shadowJar')
|
||||
dependsOn(':Bungee:BungeeLoader:shadowJar')
|
||||
}
|
||||
|
||||
tasks.build.dependsOn shadowJar
|
||||
@@ -1,101 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
~ Copyright 2026 Dawson Hessler
|
||||
~
|
||||
~ Licensed 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.
|
||||
-->
|
||||
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>dev.brighten.antivpn</groupId>
|
||||
<artifactId>AntiVPN</artifactId>
|
||||
<version>1.10.0</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>Universal</artifactId>
|
||||
|
||||
<properties>
|
||||
<maven.compiler.source>17</maven.compiler.source>
|
||||
<maven.compiler.target>17</maven.compiler.target>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>dev.brighten.antivpn.bukkit</groupId>
|
||||
<artifactId>Loader</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>dev.brighten.antivpn</groupId>
|
||||
<artifactId>VelocityLoader</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>dev.brighten.antivpn.bungee</groupId>
|
||||
<artifactId>BungeeLoader</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-shade-plugin</artifactId>
|
||||
<version>3.6.0</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>shade</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<finalName>AntiVPN-${project.version}-universal</finalName>
|
||||
<createDependencyReducedPom>false</createDependencyReducedPom>
|
||||
<transformers>
|
||||
<transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer"/>
|
||||
<transformer implementation="org.apache.maven.plugins.shade.resource.IncludeResourceTransformer">
|
||||
<resource>antivpn-source.jarinjar</resource>
|
||||
<file>${project.parent.basedir}/Common/Source/target/Source-${project.version}.jar</file>
|
||||
</transformer>
|
||||
</transformers>
|
||||
<relocations>
|
||||
<relocation>
|
||||
<pattern>org.yaml.snakeyaml</pattern>
|
||||
<shadedPattern>dev.brighten.antivpn.shaded.org.yaml.snakeyaml</shadedPattern>
|
||||
</relocation>
|
||||
<relocation>
|
||||
<pattern>org.bstats</pattern>
|
||||
<shadedPattern>dev.brighten.antivpn.shaded.org.bstats</shadedPattern>
|
||||
</relocation>
|
||||
<relocation>
|
||||
<pattern>org.objectweb</pattern>
|
||||
<shadedPattern>dev.brighten.antivpn.shaded.org.objectweb</shadedPattern>
|
||||
</relocation>
|
||||
<!-- Add other relocations from Common/pom.xml -->
|
||||
</relocations>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
</project>
|
||||
@@ -0,0 +1,29 @@
|
||||
plugins {
|
||||
id 'com.github.johnrengelman.shadow'
|
||||
}
|
||||
|
||||
evaluationDependsOn(':Velocity:VelocityPlugin')
|
||||
|
||||
dependencies {
|
||||
compileOnly 'com.velocitypowered:velocity-api:3.4.0-SNAPSHOT'
|
||||
compileOnly project(':Velocity:VelocityPlugin')
|
||||
implementation project(':Common:loader-utils')
|
||||
}
|
||||
|
||||
shadowJar {
|
||||
archiveClassifier.set('')
|
||||
|
||||
// Include the shaded plugin jar as a single resource file
|
||||
from(project(':Velocity:VelocityPlugin').tasks.shadowJar) {
|
||||
rename { 'antivpn-velocity.jarinjar' }
|
||||
}
|
||||
|
||||
relocate 'org.bstats', 'dev.brighten.antivpn.velocity.org.bstats'
|
||||
relocate 'org.yaml.snakeyaml', 'dev.brighten.antivpn.shaded.org.yaml.snakeyaml'
|
||||
}
|
||||
|
||||
tasks.named('shadowJar') {
|
||||
dependsOn(':Velocity:VelocityPlugin:shadowJar')
|
||||
}
|
||||
|
||||
tasks.build.dependsOn shadowJar
|
||||
@@ -1,125 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
~ Copyright 2026 Dawson Hessler
|
||||
~
|
||||
~ Licensed 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.
|
||||
-->
|
||||
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>dev.brighten.antivpn</groupId>
|
||||
<artifactId>Velocity</artifactId>
|
||||
<version>1.10.0</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
<artifactId>VelocityLoader</artifactId>
|
||||
|
||||
<properties>
|
||||
<maven.compiler.source>17</maven.compiler.source>
|
||||
<maven.compiler.target>17</maven.compiler.target>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>velocity</id>
|
||||
<url>https://nexus.funkemunky.cc/repository/papermc-public/</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.velocitypowered</groupId>
|
||||
<artifactId>velocity-api</artifactId>
|
||||
<version>3.4.0-SNAPSHOT</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.bstats</groupId>
|
||||
<artifactId>bstats-velocity</artifactId>
|
||||
<version>2.2.1</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>dev.brighten.antivpn</groupId>
|
||||
<artifactId>loader-utils</artifactId>
|
||||
<version>1.10.0</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>dev.brighten.antivpn</groupId>
|
||||
<artifactId>VelocityPlugin</artifactId>
|
||||
<version>1.10.0</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.13.0</version>
|
||||
<configuration>
|
||||
<source>17</source>
|
||||
<target>17</target>
|
||||
<compilerArgument>-XDignore.symbol.file</compilerArgument>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-shade-plugin</artifactId>
|
||||
<version>3.6.0</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>shade</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<minimizeJar>false</minimizeJar>
|
||||
<transformers>
|
||||
<transformer implementation="org.apache.maven.plugins.shade.resource.IncludeResourceTransformer">
|
||||
<resource>antivpn-velocity.jarinjar</resource>
|
||||
<file>${project.parent.basedir}/VelocityPlugin/target/VelocityPlugin-${project.version}.jar</file>
|
||||
</transformer>
|
||||
</transformers>
|
||||
<relocations>
|
||||
<relocation>
|
||||
<pattern>org.bstats</pattern>
|
||||
<!-- Replace this with your package! -->
|
||||
<shadedPattern>dev.brighten.antivpn.velocity.org.bstats</shadedPattern>
|
||||
</relocation>
|
||||
<relocation>
|
||||
<pattern>org.yaml.snakeyaml</pattern>
|
||||
<shadedPattern>dev.brighten.antivpn.shaded.org.yaml.snakeyaml</shadedPattern>
|
||||
</relocation>
|
||||
</relocations>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
<resources>
|
||||
<resource>
|
||||
<directory>src/main/resources</directory>
|
||||
<filtering>true</filtering>
|
||||
</resource>
|
||||
</resources>
|
||||
</build>
|
||||
|
||||
</project>
|
||||
@@ -0,0 +1,18 @@
|
||||
plugins {
|
||||
id 'com.github.johnrengelman.shadow'
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compileOnly 'com.velocitypowered:velocity-api:3.4.0-SNAPSHOT'
|
||||
compileOnly project(':Common:Source')
|
||||
compileOnly project(':Common:loader-utils')
|
||||
implementation 'org.bstats:bstats-velocity:2.2.1'
|
||||
}
|
||||
|
||||
shadowJar {
|
||||
archiveClassifier.set('')
|
||||
relocate 'org.bstats', 'dev.brighten.antivpn.velocity.org.bstats'
|
||||
relocate 'org.yaml.snakeyaml', 'dev.brighten.antivpn.shaded.org.yaml.snakeyaml'
|
||||
}
|
||||
|
||||
tasks.build.dependsOn shadowJar
|
||||
@@ -1,118 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
~ Copyright 2026 Dawson Hessler
|
||||
~
|
||||
~ Licensed 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.
|
||||
-->
|
||||
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>dev.brighten.antivpn</groupId>
|
||||
<artifactId>AntiVPN</artifactId>
|
||||
<version>1.10.0</version>
|
||||
<relativePath>../../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
<artifactId>VelocityPlugin</artifactId>
|
||||
|
||||
<properties>
|
||||
<maven.compiler.source>17</maven.compiler.source>
|
||||
<maven.compiler.target>17</maven.compiler.target>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>velocity</id>
|
||||
<url>https://nexus.funkemunky.cc/repository/papermc-public/</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.velocitypowered</groupId>
|
||||
<artifactId>velocity-api</artifactId>
|
||||
<version>3.4.0-SNAPSHOT</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>dev.brighten.antivpn</groupId>
|
||||
<artifactId>Source</artifactId>
|
||||
<version>1.10.0</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.bstats</groupId>
|
||||
<artifactId>bstats-velocity</artifactId>
|
||||
<version>2.2.1</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>dev.brighten.antivpn</groupId>
|
||||
<artifactId>loader-utils</artifactId>
|
||||
<version>1.10.0</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.13.0</version>
|
||||
<configuration>
|
||||
<source>17</source>
|
||||
<target>17</target>
|
||||
<compilerArgument>-XDignore.symbol.file</compilerArgument>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-shade-plugin</artifactId>
|
||||
<version>3.6.0</version>
|
||||
<configuration>
|
||||
<relocations>
|
||||
<relocation>
|
||||
<pattern>org.bstats</pattern>
|
||||
<!-- Replace this with your package! -->
|
||||
<shadedPattern>dev.brighten.antivpn.velocity.org.bstats</shadedPattern>
|
||||
</relocation>
|
||||
<relocation>
|
||||
<pattern>org.yaml.snakeyaml</pattern>
|
||||
<shadedPattern>dev.brighten.antivpn.shaded.org.yaml.snakeyaml</shadedPattern>
|
||||
</relocation>
|
||||
</relocations>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>shade</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
<resources>
|
||||
<resource>
|
||||
<directory>src/main/resources</directory>
|
||||
<filtering>true</filtering>
|
||||
</resource>
|
||||
</resources>
|
||||
</build>
|
||||
|
||||
</project>
|
||||
+30
-28
@@ -41,43 +41,45 @@ public class VelocityListener extends VPNExecutor {
|
||||
.unloadPlayer(event.getPlayer().getUniqueId()));
|
||||
|
||||
VelocityPlugin.INSTANCE.getServer().getEventManager().register(VelocityPlugin.INSTANCE.getPluginInstance(), LoginEvent.class,
|
||||
event -> {
|
||||
APIPlayer player = AntiVPN.getInstance().getPlayerExecutor().getPlayer(event.getPlayer().getUniqueId())
|
||||
.orElse(new OfflinePlayer(
|
||||
event.getPlayer().getUniqueId(),
|
||||
event.getPlayer().getUsername(),
|
||||
event.getPlayer().getRemoteAddress().getAddress()
|
||||
));
|
||||
this::onLogin);
|
||||
}
|
||||
|
||||
player.checkPlayer(result -> {
|
||||
if(!result.resultType().isShouldBlock()) return;
|
||||
public void onLogin(LoginEvent event) {
|
||||
APIPlayer player = AntiVPN.getInstance().getPlayerExecutor().getPlayer(event.getPlayer().getUniqueId())
|
||||
.orElse(new OfflinePlayer(
|
||||
event.getPlayer().getUniqueId(),
|
||||
event.getPlayer().getUsername(),
|
||||
event.getPlayer().getRemoteAddress().getAddress()
|
||||
));
|
||||
|
||||
if(!AntiVPN.getInstance().getVpnConfig().isKickPlayers()) {
|
||||
return;
|
||||
}
|
||||
player.checkPlayer(result -> {
|
||||
if(!result.resultType().isShouldBlock()) return;
|
||||
|
||||
switch (result.resultType()) {
|
||||
case DENIED_COUNTRY -> event.setResult(ResultedEvent.ComponentResult.denied(
|
||||
LegacyComponentSerializer.builder()
|
||||
.character('&')
|
||||
.build().deserialize(AntiVPN.getInstance().getVpnConfig()
|
||||
.getCountryVanillaKickReason()
|
||||
.replace("%player%", event.getPlayer().getUsername())
|
||||
.replace("%country%", result.response().getCountryName())
|
||||
.replace("%code%", result.response().getCountryCode()))));
|
||||
case DENIED_PROXY -> {
|
||||
VelocityPlugin.INSTANCE.getLogger().info(event.getPlayer().getUsername()
|
||||
+ " joined on a VPN/Proxy (" + result.response().getMethod() + ")");
|
||||
event.setResult(ResultedEvent.ComponentResult.denied(LegacyComponentSerializer.builder()
|
||||
if(!AntiVPN.getInstance().getVpnConfig().isKickPlayers()) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (result.resultType()) {
|
||||
case DENIED_COUNTRY -> event.setResult(ResultedEvent.ComponentResult.denied(
|
||||
LegacyComponentSerializer.builder()
|
||||
.character('&')
|
||||
.build().deserialize(AntiVPN.getInstance().getVpnConfig()
|
||||
.getKickMessage()
|
||||
.getCountryVanillaKickReason()
|
||||
.replace("%player%", event.getPlayer().getUsername())
|
||||
.replace("%country%", result.response().getCountryName())
|
||||
.replace("%code%", result.response().getCountryCode()))));
|
||||
}
|
||||
case DENIED_PROXY -> {
|
||||
VelocityPlugin.INSTANCE.getLogger().info(event.getPlayer().getUsername()
|
||||
+ " joined on a VPN/Proxy (" + result.response().getMethod() + ")");
|
||||
event.setResult(ResultedEvent.ComponentResult.denied(LegacyComponentSerializer.builder()
|
||||
.character('&')
|
||||
.build().deserialize(AntiVPN.getInstance().getVpnConfig()
|
||||
.getKickMessage()
|
||||
.replace("%player%", event.getPlayer().getUsername())
|
||||
.replace("%country%", result.response().getCountryName())
|
||||
.replace("%code%", result.response().getCountryCode()))));
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
+126
@@ -0,0 +1,126 @@
|
||||
package dev.brighten.antivpn.velocity;
|
||||
|
||||
import com.velocitypowered.api.event.connection.LoginEvent;
|
||||
import com.velocitypowered.api.proxy.Player;
|
||||
import dev.brighten.antivpn.AntiVPN;
|
||||
import dev.brighten.antivpn.api.PlayerExecutor;
|
||||
import dev.brighten.antivpn.api.VPNConfig;
|
||||
import dev.brighten.antivpn.api.VPNExecutor;
|
||||
import dev.brighten.antivpn.message.MessageHandler;
|
||||
import dev.brighten.antivpn.message.VpnString;
|
||||
import dev.brighten.antivpn.web.objects.VPNResponse;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
public class VelocityListenerTest {
|
||||
|
||||
private VelocityListener listener;
|
||||
private AntiVPN antiVPN;
|
||||
private VPNConfig config;
|
||||
private PlayerExecutor playerExecutor;
|
||||
private VPNExecutor vpnExecutor;
|
||||
private MessageHandler messageHandler;
|
||||
private VelocityPlugin velocityPlugin;
|
||||
|
||||
@BeforeEach
|
||||
public void setUp() throws Exception {
|
||||
antiVPN = mock(AntiVPN.class);
|
||||
config = mock(VPNConfig.class);
|
||||
playerExecutor = mock(PlayerExecutor.class);
|
||||
vpnExecutor = mock(VPNExecutor.class);
|
||||
messageHandler = mock(MessageHandler.class);
|
||||
velocityPlugin = mock(VelocityPlugin.class);
|
||||
|
||||
when(antiVPN.getVpnConfig()).thenReturn(config);
|
||||
when(antiVPN.getPlayerExecutor()).thenReturn(playerExecutor);
|
||||
when(antiVPN.getExecutor()).thenReturn(vpnExecutor);
|
||||
when(antiVPN.getMessageHandler()).thenReturn(messageHandler);
|
||||
|
||||
when(velocityPlugin.getLogger()).thenReturn(Logger.getLogger("AntiVPN"));
|
||||
|
||||
when(playerExecutor.getPlayer(any(UUID.class))).thenReturn(Optional.empty());
|
||||
when(config.getPrefixWhitelists()).thenReturn(java.util.Collections.emptyList());
|
||||
when(config.getCountryList()).thenReturn(java.util.Collections.emptyList());
|
||||
when(config.isKickPlayers()).thenReturn(true);
|
||||
when(config.getKickMessage()).thenReturn("Blocked!");
|
||||
|
||||
VpnString mockVpnString = mock(VpnString.class);
|
||||
when(mockVpnString.getFormattedMessage(any())).thenReturn("Blocked!");
|
||||
when(messageHandler.getString(anyString())).thenReturn(mockVpnString);
|
||||
|
||||
when(vpnExecutor.checkIp(anyString())).thenReturn(CompletableFuture.completedFuture(
|
||||
VPNResponse.builder().success(true).proxy(false).ip("127.0.0.1")
|
||||
.method("N/A").countryName("N/A").city("N/A").countryCode("N/A").build()
|
||||
));
|
||||
|
||||
// Use reflection to set the private static INSTANCE field
|
||||
Field instanceField = AntiVPN.class.getDeclaredField("INSTANCE");
|
||||
instanceField.setAccessible(true);
|
||||
instanceField.set(null, antiVPN);
|
||||
|
||||
Field pluginInstanceField = VelocityPlugin.class.getDeclaredField("INSTANCE");
|
||||
pluginInstanceField.setAccessible(true);
|
||||
pluginInstanceField.set(null, velocityPlugin);
|
||||
|
||||
listener = new VelocityListener();
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
public void tearDown() throws Exception {
|
||||
// Reset the singletons
|
||||
Field instanceField = AntiVPN.class.getDeclaredField("INSTANCE");
|
||||
instanceField.setAccessible(true);
|
||||
instanceField.set(null, null);
|
||||
|
||||
Field pluginInstanceField = VelocityPlugin.class.getDeclaredField("INSTANCE");
|
||||
pluginInstanceField.setAccessible(true);
|
||||
pluginInstanceField.set(null, null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLoginEventAllowed() throws Exception {
|
||||
LoginEvent event = mock(LoginEvent.class);
|
||||
Player player = mock(Player.class);
|
||||
|
||||
when(event.getPlayer()).thenReturn(player);
|
||||
when(player.getUniqueId()).thenReturn(UUID.randomUUID());
|
||||
when(player.getUsername()).thenReturn("TestPlayer");
|
||||
when(player.getRemoteAddress()).thenReturn(new InetSocketAddress("127.0.0.1", 12345));
|
||||
|
||||
listener.onLogin(event);
|
||||
|
||||
verify(event, never()).setResult(any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLoginEventBlocked() throws Exception {
|
||||
LoginEvent event = mock(LoginEvent.class);
|
||||
Player player = mock(Player.class);
|
||||
|
||||
when(event.getPlayer()).thenReturn(player);
|
||||
when(player.getUniqueId()).thenReturn(UUID.randomUUID());
|
||||
when(player.getUsername()).thenReturn("ProxyPlayer");
|
||||
when(player.getRemoteAddress()).thenReturn(new InetSocketAddress("1.1.1.1", 12345));
|
||||
|
||||
// Mock proxy response
|
||||
when(vpnExecutor.checkIp("1.1.1.1")).thenReturn(CompletableFuture.completedFuture(
|
||||
VPNResponse.builder().success(true).proxy(true).ip("1.1.1.1")
|
||||
.method("N/A").countryName("N/A").city("N/A").countryCode("N/A").build()
|
||||
));
|
||||
|
||||
listener.onLogin(event);
|
||||
|
||||
verify(event).setResult(any());
|
||||
}
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
~ Copyright 2026 Dawson Hessler
|
||||
~
|
||||
~ Licensed 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.
|
||||
-->
|
||||
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<artifactId>AntiVPN</artifactId>
|
||||
<groupId>dev.brighten.antivpn</groupId>
|
||||
<version>1.10.0</version>
|
||||
</parent>
|
||||
<packaging>pom</packaging>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>Velocity</artifactId>
|
||||
|
||||
<properties>
|
||||
<maven.compiler.source>17</maven.compiler.source>
|
||||
<maven.compiler.target>17</maven.compiler.target>
|
||||
</properties>
|
||||
</project>
|
||||
@@ -0,0 +1,37 @@
|
||||
plugins {
|
||||
id 'java'
|
||||
id 'com.github.johnrengelman.shadow' version '8.1.1' apply false
|
||||
}
|
||||
|
||||
allprojects {
|
||||
group = 'dev.brighten.antivpn'
|
||||
version = '1.10.0'
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
maven { url 'https://nexus.funkemunky.cc/content/repositories/releases/' }
|
||||
maven { url 'https://hub.spigotmc.org/nexus/content/repositories/snapshots/' }
|
||||
maven { url 'https://oss.sonatype.org/content/repositories/snapshots' }
|
||||
maven { url 'https://repo.spongepowered.org/repository/maven-public/' }
|
||||
maven { url 'https://repo.velocitypowered.com/releases/' }
|
||||
maven { url 'https://jitpack.io' }
|
||||
}
|
||||
|
||||
apply plugin: 'java'
|
||||
|
||||
java {
|
||||
toolchain {
|
||||
languageVersion = JavaLanguageVersion.of(17)
|
||||
}
|
||||
}
|
||||
|
||||
tasks.withType(JavaCompile).configureEach {
|
||||
options.encoding = 'UTF-8'
|
||||
options.compilerArgs << '-XDignore.symbol.file'
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compileOnly 'org.projectlombok:lombok:1.18.44'
|
||||
annotationProcessor 'org.projectlombok:lombok:1.18.44'
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
systemProp.javax.net.ssl.trustStore=NONE
|
||||
systemProp.javax.net.ssl.trustStoreType=Windows-ROOT
|
||||
Vendored
BIN
Binary file not shown.
+6
@@ -0,0 +1,6 @@
|
||||
#Wed Apr 08 09:36:41 EDT 2026
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-9.4.0-bin.zip
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
@@ -0,0 +1,234 @@
|
||||
#!/bin/sh
|
||||
|
||||
#
|
||||
# Copyright © 2015-2021 the original authors.
|
||||
#
|
||||
# Licensed 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
|
||||
#
|
||||
# https://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.
|
||||
#
|
||||
|
||||
##############################################################################
|
||||
#
|
||||
# Gradle start up script for POSIX generated by Gradle.
|
||||
#
|
||||
# Important for running:
|
||||
#
|
||||
# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
|
||||
# noncompliant, but you have some other compliant shell such as ksh or
|
||||
# bash, then to run this script, type that shell name before the whole
|
||||
# command line, like:
|
||||
#
|
||||
# ksh Gradle
|
||||
#
|
||||
# Busybox and similar reduced shells will NOT work, because this script
|
||||
# requires all of these POSIX shell features:
|
||||
# * functions;
|
||||
# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
|
||||
# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
|
||||
# * compound commands having a testable exit status, especially «case»;
|
||||
# * various built-in commands including «command», «set», and «ulimit».
|
||||
#
|
||||
# Important for patching:
|
||||
#
|
||||
# (2) This script targets any POSIX shell, so it avoids extensions provided
|
||||
# by Bash, Ksh, etc; in particular arrays are avoided.
|
||||
#
|
||||
# The "traditional" practice of packing multiple parameters into a
|
||||
# space-separated string is a well documented source of bugs and security
|
||||
# problems, so this is (mostly) avoided, by progressively accumulating
|
||||
# options in "$@", and eventually passing that to Java.
|
||||
#
|
||||
# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
|
||||
# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
|
||||
# see the in-line comments for details.
|
||||
#
|
||||
# There are tweaks for specific operating systems such as AIX, CygWin,
|
||||
# Darwin, MinGW, and NonStop.
|
||||
#
|
||||
# (3) This script is generated from the Groovy template
|
||||
# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
|
||||
# within the Gradle project.
|
||||
#
|
||||
# You can find Gradle at https://github.com/gradle/gradle/.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
# Attempt to set APP_HOME
|
||||
|
||||
# Resolve links: $0 may be a link
|
||||
app_path=$0
|
||||
|
||||
# Need this for daisy-chained symlinks.
|
||||
while
|
||||
APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
|
||||
[ -h "$app_path" ]
|
||||
do
|
||||
ls=$( ls -ld "$app_path" )
|
||||
link=${ls#*' -> '}
|
||||
case $link in #(
|
||||
/*) app_path=$link ;; #(
|
||||
*) app_path=$APP_HOME$link ;;
|
||||
esac
|
||||
done
|
||||
|
||||
APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
|
||||
|
||||
APP_NAME="Gradle"
|
||||
APP_BASE_NAME=${0##*/}
|
||||
|
||||
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
|
||||
|
||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||
MAX_FD=maximum
|
||||
|
||||
warn () {
|
||||
echo "$*"
|
||||
} >&2
|
||||
|
||||
die () {
|
||||
echo
|
||||
echo "$*"
|
||||
echo
|
||||
exit 1
|
||||
} >&2
|
||||
|
||||
# OS specific support (must be 'true' or 'false').
|
||||
cygwin=false
|
||||
msys=false
|
||||
darwin=false
|
||||
nonstop=false
|
||||
case "$( uname )" in #(
|
||||
CYGWIN* ) cygwin=true ;; #(
|
||||
Darwin* ) darwin=true ;; #(
|
||||
MSYS* | MINGW* ) msys=true ;; #(
|
||||
NONSTOP* ) nonstop=true ;;
|
||||
esac
|
||||
|
||||
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
||||
|
||||
|
||||
# Determine the Java command to use to start the JVM.
|
||||
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
|
||||
else
|
||||
JAVACMD=$JAVA_HOME/bin/java
|
||||
fi
|
||||
if [ ! -x "$JAVACMD" ] ; then
|
||||
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
|
||||
|
||||
Please set the JAVA_HOME variable in your environment to match the
|
||||
location of your Java installation."
|
||||
fi
|
||||
else
|
||||
JAVACMD=java
|
||||
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
|
||||
Please set the JAVA_HOME variable in your environment to match the
|
||||
location of your Java installation."
|
||||
fi
|
||||
|
||||
# Increase the maximum file descriptors if we can.
|
||||
if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
|
||||
case $MAX_FD in #(
|
||||
max*)
|
||||
MAX_FD=$( ulimit -H -n ) ||
|
||||
warn "Could not query maximum file descriptor limit"
|
||||
esac
|
||||
case $MAX_FD in #(
|
||||
'' | soft) :;; #(
|
||||
*)
|
||||
ulimit -n "$MAX_FD" ||
|
||||
warn "Could not set maximum file descriptor limit to $MAX_FD"
|
||||
esac
|
||||
fi
|
||||
|
||||
# Collect all arguments for the java command, stacking in reverse order:
|
||||
# * args from the command line
|
||||
# * the main class name
|
||||
# * -classpath
|
||||
# * -D...appname settings
|
||||
# * --module-path (only if needed)
|
||||
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
|
||||
|
||||
# For Cygwin or MSYS, switch paths to Windows format before running java
|
||||
if "$cygwin" || "$msys" ; then
|
||||
APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
|
||||
CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
|
||||
|
||||
JAVACMD=$( cygpath --unix "$JAVACMD" )
|
||||
|
||||
# Now convert the arguments - kludge to limit ourselves to /bin/sh
|
||||
for arg do
|
||||
if
|
||||
case $arg in #(
|
||||
-*) false ;; # don't mess with options #(
|
||||
/?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
|
||||
[ -e "$t" ] ;; #(
|
||||
*) false ;;
|
||||
esac
|
||||
then
|
||||
arg=$( cygpath --path --ignore --mixed "$arg" )
|
||||
fi
|
||||
# Roll the args list around exactly as many times as the number of
|
||||
# args, so each arg winds up back in the position where it started, but
|
||||
# possibly modified.
|
||||
#
|
||||
# NB: a `for` loop captures its iteration list before it begins, so
|
||||
# changing the positional parameters here affects neither the number of
|
||||
# iterations, nor the values presented in `arg`.
|
||||
shift # remove old arg
|
||||
set -- "$@" "$arg" # push replacement arg
|
||||
done
|
||||
fi
|
||||
|
||||
# Collect all arguments for the java command;
|
||||
# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
|
||||
# shell script including quotes and variable substitutions, so put them in
|
||||
# double quotes to make sure that they get re-expanded; and
|
||||
# * put everything else in single quotes, so that it's not re-expanded.
|
||||
|
||||
set -- \
|
||||
"-Dorg.gradle.appname=$APP_BASE_NAME" \
|
||||
-classpath "$CLASSPATH" \
|
||||
org.gradle.wrapper.GradleWrapperMain \
|
||||
"$@"
|
||||
|
||||
# Use "xargs" to parse quoted args.
|
||||
#
|
||||
# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
|
||||
#
|
||||
# In Bash we could simply go:
|
||||
#
|
||||
# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
|
||||
# set -- "${ARGS[@]}" "$@"
|
||||
#
|
||||
# but POSIX shell has neither arrays nor command substitution, so instead we
|
||||
# post-process each arg (as a line of input to sed) to backslash-escape any
|
||||
# character that might be a shell metacharacter, then use eval to reverse
|
||||
# that process (while maintaining the separation between arguments), and wrap
|
||||
# the whole thing up as a single "set" statement.
|
||||
#
|
||||
# This will of course break if any of these variables contains a newline or
|
||||
# an unmatched quote.
|
||||
#
|
||||
|
||||
eval "set -- $(
|
||||
printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
|
||||
xargs -n1 |
|
||||
sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
|
||||
tr '\n' ' '
|
||||
)" '"$@"'
|
||||
|
||||
exec "$JAVACMD" "$@"
|
||||
Vendored
+89
@@ -0,0 +1,89 @@
|
||||
@rem
|
||||
@rem Copyright 2015 the original author or authors.
|
||||
@rem
|
||||
@rem Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@rem you may not use this file except in compliance with the License.
|
||||
@rem You may obtain a copy of the License at
|
||||
@rem
|
||||
@rem https://www.apache.org/licenses/LICENSE-2.0
|
||||
@rem
|
||||
@rem Unless required by applicable law or agreed to in writing, software
|
||||
@rem distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
@rem See the License for the specific language governing permissions and
|
||||
@rem limitations under the License.
|
||||
@rem
|
||||
|
||||
@if "%DEBUG%" == "" @echo off
|
||||
@rem ##########################################################################
|
||||
@rem
|
||||
@rem Gradle startup script for Windows
|
||||
@rem
|
||||
@rem ##########################################################################
|
||||
|
||||
@rem Set local scope for the variables with windows NT shell
|
||||
if "%OS%"=="Windows_NT" setlocal
|
||||
|
||||
set DIRNAME=%~dp0
|
||||
if "%DIRNAME%" == "" set DIRNAME=.
|
||||
set APP_BASE_NAME=%~n0
|
||||
set APP_HOME=%DIRNAME%
|
||||
|
||||
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
|
||||
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
|
||||
|
||||
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
|
||||
|
||||
@rem Find java.exe
|
||||
if defined JAVA_HOME goto findJavaFromJavaHome
|
||||
|
||||
set JAVA_EXE=java.exe
|
||||
%JAVA_EXE% -version >NUL 2>&1
|
||||
if "%ERRORLEVEL%" == "0" goto execute
|
||||
|
||||
echo.
|
||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
echo.
|
||||
echo Please set the JAVA_HOME variable in your environment to match the
|
||||
echo location of your Java installation.
|
||||
|
||||
goto fail
|
||||
|
||||
:findJavaFromJavaHome
|
||||
set JAVA_HOME=%JAVA_HOME:"=%
|
||||
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
||||
|
||||
if exist "%JAVA_EXE%" goto execute
|
||||
|
||||
echo.
|
||||
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
|
||||
echo.
|
||||
echo Please set the JAVA_HOME variable in your environment to match the
|
||||
echo location of your Java installation.
|
||||
|
||||
goto fail
|
||||
|
||||
:execute
|
||||
@rem Setup the command line
|
||||
|
||||
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
||||
|
||||
|
||||
@rem Execute Gradle
|
||||
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
|
||||
|
||||
:end
|
||||
@rem End local scope for the variables with windows NT shell
|
||||
if "%ERRORLEVEL%"=="0" goto mainEnd
|
||||
|
||||
:fail
|
||||
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
||||
rem the _cmd.exe /c_ return code!
|
||||
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
|
||||
exit /b 1
|
||||
|
||||
:mainEnd
|
||||
if "%OS%"=="Windows_NT" endlocal
|
||||
|
||||
:omega
|
||||
@@ -1,91 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
~ Copyright 2026 Dawson Hessler
|
||||
~
|
||||
~ Licensed 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.
|
||||
-->
|
||||
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>dev.brighten.antivpn</groupId>
|
||||
<artifactId>AntiVPN</artifactId>
|
||||
<packaging>pom</packaging>
|
||||
<version>1.10.0</version>
|
||||
|
||||
<modules>
|
||||
<module>Common</module>
|
||||
<module>Bungee</module>
|
||||
<module>Bukkit</module>
|
||||
<module>Velocity</module>
|
||||
<module>Sponge</module>
|
||||
<module>Universal</module>
|
||||
<module>Velocity/VelocityLoader</module>
|
||||
<module>Velocity/VelocityPlugin</module>
|
||||
<module>Bungee/BungeeLoader</module>
|
||||
<module>Bungee/BungeePlugin</module>
|
||||
</modules>
|
||||
|
||||
<properties>
|
||||
<maven.compiler.source>17</maven.compiler.source>
|
||||
<maven.compiler.target>17</maven.compiler.target>
|
||||
</properties>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.7.0</version>
|
||||
<configuration>
|
||||
<source>17</source>
|
||||
<target>17</target>
|
||||
<compilerArgument>-XDignore.symbol.file</compilerArgument>
|
||||
<useIncrementalCompilation>false</useIncrementalCompilation>
|
||||
<annotationProcessorPaths>
|
||||
<path>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<version>1.18.44</version>
|
||||
</path>
|
||||
</annotationProcessorPaths>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
<resources>
|
||||
<resource>
|
||||
<directory>src/main/resources</directory>
|
||||
<filtering>true</filtering>
|
||||
</resource>
|
||||
</resources>
|
||||
</build>
|
||||
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>funkemunky-releases</id>
|
||||
<url>https://nexus.funkemunky.cc/content/repositories/releases/</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<version>1.18.44</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
@@ -0,0 +1,18 @@
|
||||
rootProject.name = 'AntiVPN'
|
||||
|
||||
include 'Common:Source'
|
||||
include 'Common:loader-utils'
|
||||
|
||||
include 'Bukkit:Plugin'
|
||||
include 'Bukkit:Loader'
|
||||
|
||||
include 'Bungee:BungeePlugin'
|
||||
include 'Bungee:BungeeLoader'
|
||||
|
||||
include 'Sponge:SpongePlugin'
|
||||
include 'Sponge:SpongeLoader'
|
||||
|
||||
include 'Velocity:VelocityPlugin'
|
||||
include 'Velocity:VelocityLoader'
|
||||
|
||||
include 'Universal'
|
||||
Reference in New Issue
Block a user