Compare commits

..

72 Commits

Author SHA1 Message Date
Dawson 9cbeed1df3 58-bug-plugin-fails-to-load-after-upgrading-to-193-on-velocity (#60)
* Moving to previous H2 version that was in 1.9.2 that somehow got downgraded

* Reverting back to Java 8 compile target

* removing minimize on shade for Common

* Clearly something here changed something, cause reverting it this way seems to have fixed it

* Cleaning up code here

---------

Co-authored-by: Dawson <dawson@funkemunky.cc>
2025-03-27 10:44:34 -04:00
Dawson 353b7dad78 bugfix/velocity-kick (#56)
* Updating velocity API

* Added exception logging and fixed NullPointerException with antivpn plan command in velocity from tab-complete being null. Replaced MySQL with MariaDB driver

* Added exception logging and fixed NullPointerException with antivpn plan command in velocity from tab-complete being null. Replaced MySQL with MariaDB driver.

* Added exception logging and fixed NullPointerException with antivpn plan command in velocity from tab-complete being null. Replaced MySQL with MariaDB driver.

* Fixing kick reason

* Corrected MySQL ssl errors and fixed visual bug with velocity users kicking

* Reverted to mysql driver

---------

Co-authored-by: Dawson <dawson@funkemunky.cc>
2025-01-26 14:56:12 -05:00
dependabot[bot] 0291aca052 Merge pull request #52
* Bump com.h2database:h2 from 2.1.210 to 2.2.220 in /Common

* Merge branch 'master' into dependabot/maven/Common/com.h2database-h2-…

* Merge branch 'master' into dependabot/maven/Common/com.h2database-h2-…

* Updating mysql depends to non-vulnerable
2024-11-24 14:38:27 -05:00
funkemunky ae5893be89 Worflow now uses setup-java for caching as well. 2024-11-18 09:23:52 -05:00
funkemunky f9ed53bfec Updating action to latest versions 2024-11-18 09:19:23 -05:00
Dawson cb32dfc370 Allowing manual dispatch 2024-11-18 09:14:37 -05:00
Dawson 4c7ff3d061 Merge pull request #48 from funkemunky/bugfix-bukkit-login
Fixing bukkit and antivirus problems - Release v1.9.3
2024-03-17 14:23:42 -04:00
funkemunky aec0bb2738 Corrected error on bukkit servers when vanilla kicking players 2024-03-15 11:17:25 -04:00
funkemunky 3f5ab39877 - Correct command concurrency issues on Bukkit servers
- Removed dynamic class loading of libraries to fix antivirus flags of the plugin.
2024-03-15 11:06:49 -04:00
Dawson f2e59c0075 Merge pull request #47 from Michielo1/patch-1
Correct ISO codes link in config
2024-03-08 22:37:00 -05:00
Michielo a01b595953 Correct ISO codes link 2024-02-18 20:51:25 +01:00
funkemunky b2fcc4ff26 Changing event priority on bungee so KauriVPN checks run before anything else. 2024-01-25 13:24:51 -05:00
funkemunky 5363b7c469 In process of correcting kick issues 2024-01-06 19:56:14 -05:00
Dawson df48e3dfd4 Update issue templates 2023-12-31 13:39:31 -05:00
Dawson 0686c5fd3e Update issue templates 2023-12-31 13:38:17 -05:00
funkemunky 5b6d214e6f Patches bug on Bukkit/Spigot servers may result in some players not being kicked on VPN detection.
I believe this occurs when the API response is below 50ms, and we attempt to Player#kickPlayer() or run commands on console that attempt to kick the player. The problem is that if this is running before the tick PlayerLoginEvent runs on ends, the player wouldn't be considered "online". Therefore, the player would never be removed from the server even if desired.

I assumed wrongly that the async processing of the query would always end up on the next tick. So now I update the PlayerLoginEvent result to KICK_BANNED no matter if the processing is async or in the same thread stack as the event.
2023-12-30 14:06:44 -05:00
funkemunky 2bdd7d2c34 Cleaned up files 2023-12-04 08:55:01 -05:00
funkemunky 31a9412c0a Updated libraries, and cleaned up code for performance purposes. 2023-12-04 08:54:48 -05:00
Dawson Hessler 7f96c49ce8 Delete nightly.yml 2023-10-30 10:41:45 -04:00
Dawson Hessler 7b3f9fc6ae Update nightly.yml 2023-10-30 10:38:01 -04:00
Dawson Hessler edd08b27ce Update maven.yml 2023-10-30 10:37:36 -04:00
Dawson Hessler 158045217e Create nightly.yml 2023-10-30 10:37:01 -04:00
Dawson 63bdb0a4da Merge pull request #45 from funkemunky/dependabot/maven/Common/com.google.guava-guava-32.0.0-jre
Bump com.google.guava:guava from 31.1-jre to 32.0.0-jre in /Common
2023-10-30 10:27:05 -04:00
Dawson b9e23ba34e Updating to only run on commits and pull requests to main 2023-10-30 10:26:26 -04:00
dependabot[bot] 9f6b0f8b27 Bump com.google.guava:guava from 31.1-jre to 32.0.0-jre in /Common
Bumps [com.google.guava:guava](https://github.com/google/guava) from 31.1-jre to 32.0.0-jre.
- [Release notes](https://github.com/google/guava/releases)
- [Commits](https://github.com/google/guava/commits)

---
updated-dependencies:
- dependency-name: com.google.guava:guava
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-10-30 14:24:01 +00:00
Dawson fec1dcdef1 Merge pull request #29 from funkemunky/dependabot/maven/Common/org.yaml-snakeyaml-2.0
Bump snakeyaml from 1.30 to 2.0 in /Common
2023-10-30 10:23:21 -04:00
Dawson Hessler c062e3d910 Tested and correcting dependency issues 2023-10-30 10:20:49 -04:00
Dawson Hessler a79fb1fe9a Updating more vulnerable depends 2023-10-30 10:14:15 -04:00
Dawson Hessler d224efce3c Updating depends to make it work 2023-10-30 10:12:14 -04:00
Dawson Hessler a2554c2bba Merge branch 'master' into dependabot/maven/Common/org.yaml-snakeyaml-2.0 2023-10-30 10:06:28 -04:00
Dawson 70bfb4e83d Merge pull request #42 from C0D3-M4513R/master
Fix PR #35
2023-10-30 10:06:07 -04:00
Dawson bc666447c5 Merge pull request #43 from C0D3-M4513R/patch-bukkit-banned-whitelist
Add null checks to ip check on login
2023-10-30 10:05:51 -04:00
Dawson Hessler 26cfc3e3f8 Update maven.yml 2023-10-30 10:03:04 -04:00
Dawson Hessler 7974b24271 Revert "Revert "Revert "Update maven.yml"""
This reverts commit 87cdd57383.
2023-10-30 10:02:30 -04:00
Dawson Hessler 87cdd57383 Revert "Revert "Update maven.yml""
This reverts commit 6fe928ca14.
2023-10-30 10:02:17 -04:00
Dawson Hessler 6fe928ca14 Revert "Update maven.yml"
This reverts commit d461b5945b.
2023-10-30 10:02:02 -04:00
Dawson Hessler dae9111a34 Revert "Merge branch 'master' of https://github.com/funkemunky/AntiVPN"
This reverts commit f4d6fc2b4b, reversing
changes made to d461b5945b.
2023-10-30 10:01:50 -04:00
Dawson Hessler f4d6fc2b4b Merge branch 'master' of https://github.com/funkemunky/AntiVPN 2023-10-30 10:00:12 -04:00
Dawson Hessler d461b5945b Update maven.yml 2023-10-30 09:59:50 -04:00
Dawson c6303ec1b2 Merge pull request #44 from funkemunky/funkemunky-patch-1
Updating build action to run on pull request
2023-10-30 09:57:55 -04:00
Dawson Hessler ca8fb24134 Caching maven repos properly 2023-10-30 09:54:58 -04:00
Dawson 5e37d2c371 Updating to run on pull request 2023-10-30 09:50:47 -04:00
Dawson Hessler 48c6dd63ee Revert "Merge pull request #35 from C0D3-M4513R/patch-1"
This reverts commit db1cdad4e1, reversing
changes made to 9f66570088.
2023-10-30 09:48:04 -04:00
C0D3 M4513R 50e7059597 Add null checks to ip check on login
Supersedes: #41
Fixes: #39
2023-10-18 05:57:22 +02:00
C0D3 M4513R 464b02f416 Fix PR #35 2023-10-18 05:45:27 +02:00
Dawson db1cdad4e1 Merge pull request #35 from C0D3-M4513R/patch-1 2023-10-17 18:58:31 -04:00
Dawson 9f66570088 Merge pull request #37 from C0D3-M4513R/command-suggestion 2023-10-17 18:57:47 -04:00
Dawson 5f0b2796b3 Merge pull request #40 from alexkarezin/master 2023-10-17 18:56:42 -04:00
Alex Karezin be5eb4e953 Update README.md by adding a link to repository map
Adding a link to the high-level diagrams including module, library dependency and others (https://sourcespy.com/github/funkemunkyantivpn/). Built directly from source and updated on schedule. Intended to simplify developer's introduction to the project.

In the spirit of transparency - I am the author of the diagrams. Hope contributors find it useful.
2023-07-31 14:43:20 -04:00
C0D3 M4513R dde81b0495 Bump version 2023-07-14 13:35:50 +02:00
C0D3 M4513R cbc00b79e2 Add command suggestion for empty args 2023-07-14 13:31:36 +02:00
C0D3 M4513R 3b2a463e58 Update PlanCommand.java 2023-07-14 13:17:47 +02:00
Dawson Hessler 96e48594d8 Fixing velocity loading issues 2023-07-12 08:45:39 -04:00
Dawson Hessler c1ab71c7ed Merge branch 'master' of https://github.com/funkemunky/AntiVPN 2023-07-06 20:26:07 -04:00
Dawson Hessler 4bda24f10c Bump to 1.9.0 2023-07-06 20:26:02 -04:00
Dawson 259cff4402 Merge pull request #32 from AlexProgrammerDE/patch-1
Remove unused import
2023-07-06 20:15:51 -04:00
Dawson Hessler c54e90dca1 Removing usages of System.out.print 2023-07-06 20:13:47 -04:00
Alex 4f1e3848de Remove unused import 2023-07-04 17:30:39 +02:00
Dawson 1606ad192e Working on spongepowered version of plugin 2023-05-25 10:24:42 -04:00
Dawson Hessler 40308869c0 1.8.4 Added cache for logins for faster response 2023-05-23 08:09:41 -04:00
Dawson Hessler 6959f35d0c Fixing whitelist issues in bukkit and bungee 2023-04-18 06:45:28 -04:00
Dawson Hessler 21b6924cce Fixing error with inserted type mismatch in H2 and MySQL 2023-04-18 06:42:07 -04:00
Dawson Hessler 9c843cd061 Updating to 1.8.3.1
Turns out we accidentally already used the 1.8.3 version
2023-03-13 15:08:04 -04:00
Dawson Hessler 91a09f6940 Updating version to 1.8.3 2023-03-13 15:04:14 -04:00
Dawson Hessler 36b44200c4 Adding response expiry since I just realized it never expires 2023-03-13 15:00:39 -04:00
dependabot[bot] 903dd8e73e Bump snakeyaml from 1.30 to 2.0 in /Common
Bumps [snakeyaml](https://bitbucket.org/snakeyaml/snakeyaml) from 1.30 to 2.0.
- [Commits](https://bitbucket.org/snakeyaml/snakeyaml/branches/compare/snakeyaml-2.0..snakeyaml-1.30)

---
updated-dependencies:
- dependency-name: org.yaml:snakeyaml
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-02-28 19:31:59 +00:00
Dawson e6bc601372 Fixing compile bug 2023-02-28 14:31:40 -05:00
Dawson 9dbf0e8635 Merge branch 'master' of https://github.com/funkemunky/AntiVPN 2022-11-02 10:39:50 -04:00
Dawson dd1b6afbb7 Working on adding sponge support 2022-11-02 10:39:48 -04:00
Dawson Hessler 14e266b978 Fixing load issue with snakeyaml on 1.12+ servers 2022-09-02 09:34:47 -04:00
Dawson Hessler cc289f41ff Instead of deleting old files, make new one 2022-08-29 07:34:53 -04:00
Dawson Hessler bf5b81b750 1.8.2.1, fixed H2 and removed debug 2022-08-29 07:19:42 -04:00
54 changed files with 898 additions and 2262 deletions
+34
View File
@@ -0,0 +1,34 @@
---
name: Bug report
about: Create a bug report that will allow us to fix any unexpected behavior
title: "[BUG]"
labels: ''
assignees: ''
---
**Describe the bug**
A clear and concise description of what the bug is.
**To Reproduce**
Steps to reproduce the behavior:
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error
**Expected behavior**
A clear and concise description of what you expected to happen.
**Screenshots**
If applicable, add screenshots to help explain your problem.
**What instance are you running KauriVPN on?**
*Put an 'x' in the brackets to check it*
- [ ] Velocity
- [ ] Bukkit/Spigot
- [ ] Bungeecord
**Additional context**
Add any other context about the problem here.
+20
View File
@@ -0,0 +1,20 @@
---
name: Feature request
about: Suggest an idea you would like added
title: "[FEATURE] "
labels: enhancement
assignees: ''
---
**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
**Describe the solution you'd like**
A clear and concise description of what you want to happen.
**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.
**Additional context**
Add any other context or screenshots about the feature request here.
+11 -12
View File
@@ -1,29 +1,28 @@
on:
push:
branches: ["**"]
branches: [master]
pull_request:
branches: [master]
workflow_dispatch:
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4
- name: Set up JDK 17.0.2
uses: actions/setup-java@v1
uses: actions/setup-java@v4
with:
java-version: 17.0
- name: Cache Maven packages
uses: actions/cache@v2
with:
path: ~/.m2
key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }}
distribution: 'zulu'
cache: 'maven'
- name: Compile
run: mvn -B -Pclean install
run: mvn -B package --file pom.xml
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Upload AntiVPN
uses: actions/upload-artifact@v2
uses: actions/upload-artifact@v4
with:
name: AntiVPN
path: Assembly/target/Assembly-*.jar
path: Assembly/target/Assembly-*.jar
-38
View File
@@ -1,38 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<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/maven-v4_0_0.xsd">
<parent>
<artifactId>AntiVPN</artifactId>
<groupId>dev.brighten.antivpn</groupId>
<version>1.8.2</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>Assembly</artifactId>
<build>
<plugins>
<plugin>
<artifactId>maven-shade-plugin</artifactId>
<version>3.2.4</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>cc.funkemunky.utils</groupId>
<artifactId>lombok</artifactId>
<version>1.18.0</version>
<scope>provided</scope>
</dependency>
</dependencies>
<properties>
<maven.compiler.target>8</maven.compiler.target>
<maven.compiler.source>8</maven.compiler.source>
</properties>
</project>
+14 -2
View File
@@ -5,7 +5,7 @@
<parent>
<artifactId>AntiVPN</artifactId>
<groupId>dev.brighten.antivpn</groupId>
<version>1.8.2</version>
<version>1.9.3.1</version>
</parent>
<modelVersion>4.0.0</modelVersion>
@@ -21,13 +21,25 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.2.4</version>
<version>3.5.2</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<relocations>
<relocation>
<pattern>org.yaml.snakeyaml</pattern>
<shadedPattern>dev.brighten.antivpn.shaded.org.yaml.snakeyaml</shadedPattern>
</relocation>
<relocation>
<pattern>com.google.common</pattern>
<shadedPattern>dev.brighten.antivpn.shaded.com.google.common</shadedPattern>
</relocation>
</relocations>
</configuration>
</execution>
</executions>
</plugin>
-74
View File
@@ -1,74 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<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/maven-v4_0_0.xsd">
<parent>
<artifactId>AntiVPN</artifactId>
<groupId>dev.brighten.antivpn</groupId>
<version>1.8.2</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>Bukkit</artifactId>
<build>
<resources>
<resource>
<filtering>true</filtering>
<directory>src/main/resources</directory>
</resource>
</resources>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.7.0</version>
<configuration>
<source>8</source>
<target>8</target>
<compilerArgument>-XDignore.symbol.file</compilerArgument>
</configuration>
</plugin>
<plugin>
<artifactId>maven-shade-plugin</artifactId>
<version>3.1.0</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
</execution>
</executions>
<configuration>
<relocations>
<relocation>
<pattern>org.bstats</pattern>
<shadedPattern>dev.brighten.antivpn.bukkit.org.bstats</shadedPattern>
</relocation>
</relocations>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>org.github.spigot</groupId>
<artifactId>1.13.2</artifactId>
<version>1.13.2</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>dev.brighten.antivpn</groupId>
<artifactId>Common</artifactId>
<version>1.8.2</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>cc.funkemunky.utils</groupId>
<artifactId>lombok</artifactId>
<version>1.18.0</version>
<scope>provided</scope>
</dependency>
</dependencies>
<properties>
<maven.compiler.target>8</maven.compiler.target>
<maven.compiler.source>8</maven.compiler.source>
</properties>
</project>
+24 -16
View File
@@ -5,7 +5,7 @@
<parent>
<artifactId>AntiVPN</artifactId>
<groupId>dev.brighten.antivpn</groupId>
<version>1.8.2</version>
<version>1.9.3.1</version>
</parent>
<modelVersion>4.0.0</modelVersion>
@@ -16,7 +16,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.7.0</version>
<version>3.13.0</version>
<configuration>
<source>8</source>
<target>8</target>
@@ -26,22 +26,30 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.1.0</version>
<configuration>
<relocations>
<relocation>
<pattern>org.bstats</pattern>
<!-- Replace this with your package! -->
<shadedPattern>dev.brighten.antivpn.bukkit.org.bstats</shadedPattern>
</relocation>
</relocations>
</configuration>
<version>3.5.2</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<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>
<relocation>
<pattern>com.google.common</pattern>
<shadedPattern>dev.brighten.antivpn.shaded.com.google.common</shadedPattern>
</relocation>
</relocations>
</configuration>
</execution>
</executions>
</plugin>
@@ -61,15 +69,15 @@
<dependencies>
<dependency>
<groupId>org.github.spigot</groupId>
<artifactId>1.13.2</artifactId>
<version>1.13.2</version>
<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>Common</artifactId>
<version>1.8.2</version>
<version>1.9.3.1</version>
<scope>provided</scope>
</dependency>
<dependency>
@@ -1,26 +1,35 @@
package dev.brighten.antivpn.bukkit;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import dev.brighten.antivpn.AntiVPN;
import dev.brighten.antivpn.api.APIPlayer;
import dev.brighten.antivpn.api.VPNExecutor;
import dev.brighten.antivpn.message.VpnString;
import dev.brighten.antivpn.web.objects.VPNResponse;
import net.md_5.bungee.api.ChatColor;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.HandlerList;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.event.player.PlayerLoginEvent;
import org.bukkit.event.player.PlayerQuitEvent;
import org.bukkit.scheduler.BukkitRunnable;
import org.bukkit.scheduler.BukkitTask;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
@SuppressWarnings("unchecked")
public class BukkitListener extends VPNExecutor implements Listener {
private final Cache<UUID, VPNResponse> responseCache = CacheBuilder.newBuilder()
.expireAfterWrite(5, TimeUnit.MINUTES)
.maximumSize(2000)
.build();
private BukkitTask cacheResetTask;
@Override
public void registerListeners() {
BukkitPlugin.pluginInstance.getServer().getPluginManager()
@@ -28,47 +37,41 @@ public class BukkitListener extends VPNExecutor implements Listener {
}
@Override
public void runCacheReset() {
cacheResetTask = new BukkitRunnable() {
public void run() {
resetCache();
}
}.runTaskTimerAsynchronously(BukkitPlugin.pluginInstance, 24000, 24000); //Reset cache every 20 minutes
public void shutdown() {
HandlerList.unregisterAll(this);
threadExecutor.shutdown();
}
@Override
public void shutdown() {
if(cacheResetTask != null && !cacheResetTask.isCancelled()) cacheResetTask.cancel();
public void log(Level level, String log, Object... objects) {
Bukkit.getLogger().log(level, String.format(log, objects));
}
@Override
public void log(String log, Object... objects) {
Bukkit.getLogger().log(Level.INFO, String.format(log, objects));
log(Level.INFO, String.format(log, objects));
}
@Override
public void logException(String message, Exception ex) {
Bukkit.getLogger().log(Level.SEVERE, message, ex);
}
@EventHandler
public void onJoin(final PlayerJoinEvent event) {
AntiVPN.getInstance().getPlayerExecutor().getPlayer(event.getPlayer().getUniqueId())
.ifPresent(player -> {
AntiVPN.getInstance().getDatabase().alertsState(player.getUuid(), enabled -> {
if(enabled) {
AntiVPN.getInstance().getExecutor().log("Enabled");
player.setAlertsEnabled(true);
player.sendMessage(AntiVPN.getInstance().getMessageHandler()
.getString("command-alerts-toggled")
.getFormattedMessage(new VpnString.Var<>("state", true)));
} else AntiVPN.getInstance().getExecutor().log("Not enabled");
});
});
.ifPresent(player -> AntiVPN.getInstance().getDatabase().alertsState(player.getUuid(), enabled -> {
if(enabled) {
player.setAlertsEnabled(true);
player.sendMessage(AntiVPN.getInstance().getMessageHandler()
.getString("command-alerts-toggled")
.getFormattedMessage(new VpnString.Var<>("state", true)));
}
}));
}
@EventHandler
public void onListener(final PlayerLoginEvent event) {
//If they're exempt, don't check.
System.out.println(event.getAddress().getHostAddress() + ";" + event.getPlayer().getUniqueId() + ";" + event.getPlayer().getName());
if(event.getPlayer().hasPermission("antivpn.bypass") //Has bypass permission
|| AntiVPN.getInstance().getExecutor().isWhitelisted(event.getPlayer().getUniqueId()) //Is exempt
//Or has a name that starts with a certain prefix. This is for Bedrock exempting.
@@ -76,83 +79,144 @@ public class BukkitListener extends VPNExecutor implements Listener {
|| AntiVPN.getInstance().getVpnConfig().getPrefixWhitelists().stream()
.anyMatch(prefix -> event.getPlayer().getName().startsWith(prefix))) return;
if(responseCache.asMap().containsKey(event.getPlayer().getUniqueId())) {
VPNResponse cached = responseCache.getIfPresent(event.getPlayer().getUniqueId());
if (cached != null && cached.isProxy()) {
event.setResult(PlayerLoginEvent.Result.KICK_BANNED);
event.setKickMessage(org.bukkit.ChatColor.translateAlternateColorCodes('&',
AntiVPN.getInstance().getVpnConfig().getKickString()));
return;
}
}
final Player player = event.getPlayer();
checkIp(event.getAddress().getHostAddress(),
AntiVPN.getInstance().getVpnConfig().cachedResults(), result -> {
if(result.isSuccess()) {
//We need to run on main thread or kicking and running commands will cause errors
new BukkitRunnable() {
public void run() {
// If the countryList() size is zero, no need to check.
// Running country check first
if(AntiVPN.getInstance().getVpnConfig().countryList().size() > 0
&& !(AntiVPN.getInstance().getExecutor()
.isWhitelisted(event.getPlayer().getUniqueId()) //Is exempt
//Or has a name that starts with a certain prefix. This is for Bedrock exempting.
|| AntiVPN.getInstance().getExecutor().isWhitelisted(event.getPlayer()
.getAddress().getAddress()
.getHostAddress()))
// This bit of code will decide whether or not to kick the player
// If it contains the code and it is set to whitelist, it will not kick as they are equal
// and vise versa. However, if the contains does not match the state, it will kick.
&& AntiVPN.getInstance().getVpnConfig().countryList()
.contains(result.getCountryCode())
!= AntiVPN.getInstance().getVpnConfig().whitelistCountries()) {
//Using our built in kicking system if no commands are configured
if(AntiVPN.getInstance().getVpnConfig().countryKickCommands().size() == 0) {
final String kickReason = AntiVPN.getInstance().getVpnConfig()
.countryVanillaKickReason();
// Kicking our player
//If the player is whitelisted, we don't want to kick them
if(AntiVPN.getInstance().getExecutor().isWhitelisted(event.getPlayer().getUniqueId())) {
log("UUID is whitelisted: %s",
event.getPlayer().getUniqueId().toString());
return;
}
//If the IP is whitelisted, we don't want to kick them
InetSocketAddress address = event.getPlayer().getAddress();
if (address != null){
InetAddress address1 = address.getAddress();
if (address1 != null && AntiVPN.getInstance().getExecutor()
.isWhitelisted(address1.getHostAddress())) {
log("IP is whitelisted: %s",
address1.getHostAddress());
return;
}
}
// If the countryList() size is zero, no need to check.
// Running country check first
if(!AntiVPN.getInstance().getVpnConfig().countryList().isEmpty()
// This bit of code will decide whether or not to kick the player
// If it contains the code and it is set to whitelist, it will not kick as they are equal
// and vise versa. However, if the contains does not match the state, it will kick.
&& AntiVPN.getInstance().getVpnConfig().countryList()
.contains(result.getCountryCode())
!= AntiVPN.getInstance().getVpnConfig().whitelistCountries()) {
final String kickReason = AntiVPN.getInstance().getVpnConfig()
.countryVanillaKickReason();
// Start "online" fix
// In case the response was so fast from API the player wouldn't be "online".
event.setResult(PlayerLoginEvent.Result.KICK_BANNED);
event.setKickMessage(ChatColor
.translateAlternateColorCodes('&',
kickReason
.replace("%player%", event.getPlayer().getName())
.replace("%country%", result.getCountryName())
.replace("%code%", result.getCountryCode())));
// End "online" fix
//Using our built in kicking system if no commands are configured
if(AntiVPN.getInstance().getVpnConfig().countryKickCommands().isEmpty()) {
// Kicking our player
new BukkitRunnable() {
public void run() {
event.getPlayer().kickPlayer(ChatColor
.translateAlternateColorCodes('&',
kickReason
.replace("%player%", event.getPlayer().getName())
.replace("%country%", result.getCountryName())
.replace("%code%", result.getCountryCode())));
} else {
for (String cmd : AntiVPN.getInstance().getVpnConfig().countryKickCommands()) {
final String formattedCommand = ChatColor.translateAlternateColorCodes('&',
cmd.replace("%player%", event.getPlayer().getName())
.replace("%country%", result.getCountryName())
.replace("%code%", result.getCountryCode()));
// Runs our command from console
Bukkit.dispatchCommand(Bukkit.getConsoleSender(), formattedCommand);
}
}
} else if(result.isProxy()) {
if(AntiVPN.getInstance().getVpnConfig().kickPlayersOnDetect())
}.runTask(BukkitPlugin.pluginInstance);
} else {
final String playerName = event.getPlayer().getName();
BukkitPlugin.pluginInstance.getPlayerCommandRunner()
.addAction(event.getPlayer().getUniqueId(), () -> {
for (String cmd : AntiVPN.getInstance().getVpnConfig().countryKickCommands()) {
final String formattedCommand = ChatColor.translateAlternateColorCodes('&',
cmd.replace("%player%", playerName)
.replace("%country%", result.getCountryName())
.replace("%code%", result.getCountryCode()));
// Runs our command from console
Bukkit.dispatchCommand(Bukkit.getConsoleSender(), formattedCommand);
}
});
}
} else if(result.isProxy()) {
// Start "online" fix
// In case the response was so fast from API the player wouldn't be "online".
event.setResult(PlayerLoginEvent.Result.KICK_BANNED);
event.setKickMessage(ChatColor
.translateAlternateColorCodes('&',
AntiVPN.getInstance().getVpnConfig().getKickString()
.replace("%player%", event.getPlayer().getName())
.replace("%country%", result.getCountryName())
.replace("%code%", result.getCountryCode())));
// End "online" fix
if(AntiVPN.getInstance().getVpnConfig().kickPlayersOnDetect()) {
new BukkitRunnable() {
public void run() {
player.kickPlayer(org.bukkit.ChatColor.translateAlternateColorCodes('&',
AntiVPN.getInstance().getVpnConfig().getKickString()));
Bukkit.getLogger().info(event.getPlayer().getName()
+ " joined on a VPN/Proxy (" + result.getMethod() + ")");
//Ensuring the user wishes to alert to staff
if(AntiVPN.getInstance().getVpnConfig().alertToStaff())
AntiVPN.getInstance().getPlayerExecutor().getOnlinePlayers().stream()
.filter(APIPlayer::isAlertsEnabled)
.forEach(pl -> pl.sendMessage(AntiVPN.getInstance().getVpnConfig().alertMessage()
.replace("%player%", event.getPlayer().getName())
.replace("%reason%", result.getMethod())
.replace("%country%", result.getCountryName())
.replace("%city%", result.getCity())));
//In case the user wants to run their own commands instead of using the built in kicking
if(AntiVPN.getInstance().getVpnConfig().runCommands()) {
for (String command : AntiVPN.getInstance().getVpnConfig().commands()) {
Bukkit.dispatchCommand(Bukkit.getConsoleSender(),
ChatColor.translateAlternateColorCodes('&',
command.replace("%player%",
event.getPlayer().getName())));
}
}
AntiVPN.getInstance().detections++;
}
}.runTask(BukkitPlugin.pluginInstance);
}
}.runTask(BukkitPlugin.pluginInstance);
log(Level.INFO, event.getPlayer().getName()
+ " joined on a VPN/Proxy (" + result.getMethod() + ")");
//Ensuring the user wishes to alert to staff
if(AntiVPN.getInstance().getVpnConfig().alertToStaff())
AntiVPN.getInstance().getPlayerExecutor().getOnlinePlayers().stream()
.filter(APIPlayer::isAlertsEnabled)
.forEach(pl -> pl.sendMessage(AntiVPN.getInstance().getVpnConfig().alertMessage()
.replace("%player%", event.getPlayer().getName())
.replace("%reason%", result.getMethod())
.replace("%country%", result.getCountryName())
.replace("%city%", result.getCity())));
//In case the user wants to run their own commands instead of using the built in kicking
if(AntiVPN.getInstance().getVpnConfig().runCommands()) {
String playerName = event.getPlayer().getName();
BukkitPlugin.pluginInstance.getPlayerCommandRunner()
.addAction(event.getPlayer().getUniqueId(), () -> {
for (String command : AntiVPN.getInstance().getVpnConfig().commands()) {
Bukkit.dispatchCommand(Bukkit.getConsoleSender(),
ChatColor.translateAlternateColorCodes('&',
command.replace("%player%",
playerName)));
}
});
}
AntiVPN.getInstance().detections++;
}
} else {
Bukkit.getLogger()
.log(Level.WARNING,
log(Level.WARNING,
"The API query was not a success! " +
"You may need to upgrade your license on https://funkemunky.cc/shop");
}
@@ -3,6 +3,7 @@ package dev.brighten.antivpn.bukkit;
import dev.brighten.antivpn.AntiVPN;
import dev.brighten.antivpn.bukkit.command.BukkitCommand;
import dev.brighten.antivpn.command.Command;
import lombok.Getter;
import org.bstats.bukkit.Metrics;
import org.bstats.charts.SingleLineChart;
import org.bukkit.Bukkit;
@@ -21,8 +22,12 @@ public class BukkitPlugin extends JavaPlugin {
public static BukkitPlugin pluginInstance;
private SimpleCommandMap commandMap;
private List<org.bukkit.command.Command> registeredCommands = new ArrayList<>();
private final List<org.bukkit.command.Command> registeredCommands = new ArrayList<>();
@Getter
private SingleLineChart vpnDetections, ipsChecked;
@Getter
private PlayerCommandRunner playerCommandRunner;
public void onEnable() {
pluginInstance = this;
@@ -30,6 +35,9 @@ public class BukkitPlugin extends JavaPlugin {
Bukkit.getLogger().info("Starting AntiVPN services...");
AntiVPN.start(new BukkitListener(), new BukkitPlayerExecutor(), getDataFolder());
playerCommandRunner = new PlayerCommandRunner();
playerCommandRunner.start();
// Loading our bStats metrics to be pushed to https://bstats.org
if(AntiVPN.getInstance().getVpnConfig().metrics()) {
Bukkit.getLogger().info("Starting bStats metrics...");
@@ -84,6 +92,7 @@ public class BukkitPlugin extends JavaPlugin {
public void onDisable() {
Bukkit.getLogger().info("Stopping plugin services...");
AntiVPN.getInstance().stop();
playerCommandRunner.stop();
Bukkit.getLogger().info("Unregistering commands...");
try {
@@ -0,0 +1,61 @@
package dev.brighten.antivpn.bukkit;
import dev.brighten.antivpn.utils.MiscUtils;
import lombok.Data;
import org.bukkit.Bukkit;
import org.bukkit.scheduler.BukkitRunnable;
import java.util.Queue;
import java.util.UUID;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
public class PlayerCommandRunner {
private final ScheduledExecutorService executorService;
private final Queue<PlayerAction> playerActions = new ArrayBlockingQueue<>(10000);
public PlayerCommandRunner() {
executorService = Executors.newSingleThreadScheduledExecutor(
MiscUtils.createThreadFactory("AntiVPN:PlayerCommandRunner")
);
}
void start() {
executorService.scheduleAtFixedRate(() -> {
long currentTime = System.currentTimeMillis();
while(!playerActions.isEmpty()) {
PlayerAction action = playerActions.peek();
if(action == null) continue;
if(currentTime - action.start > 2000L || Bukkit.getPlayer(action.getUuid()) != null) {
new BukkitRunnable() {
public void run() {
action.getAction().run();
}
}.runTask(BukkitPlugin.pluginInstance);
playerActions.poll();
}
}
}, 1000, 100, TimeUnit.MILLISECONDS);
}
void stop() {
executorService.shutdown();
playerActions.clear();
}
void addAction(UUID uuid, Runnable action) {
playerActions.add(new PlayerAction(uuid, System.currentTimeMillis(), action));
}
@Data
static class PlayerAction {
private final UUID uuid;
private final long start;
private final Runnable action;
}
}
-74
View File
@@ -1,74 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<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/maven-v4_0_0.xsd">
<parent>
<artifactId>AntiVPN</artifactId>
<groupId>dev.brighten.antivpn</groupId>
<version>1.8.2</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>Bungee</artifactId>
<build>
<resources>
<resource>
<filtering>true</filtering>
<directory>src/main/resources</directory>
</resource>
</resources>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.7.0</version>
<configuration>
<source>8</source>
<target>8</target>
<compilerArgument>-XDignore.symbol.file</compilerArgument>
</configuration>
</plugin>
<plugin>
<artifactId>maven-shade-plugin</artifactId>
<version>3.1.0</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
</execution>
</executions>
<configuration>
<relocations>
<relocation>
<pattern>org.bstats</pattern>
<shadedPattern>dev.brighten.antivpn.bungee.org.bstats</shadedPattern>
</relocation>
</relocations>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>dev.brighten.antivpn</groupId>
<artifactId>Common</artifactId>
<version>1.8.2</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.github.bungee</groupId>
<artifactId>BungeeCord-1.8</artifactId>
<version>1.8</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>cc.funkemunky.utils</groupId>
<artifactId>lombok</artifactId>
<version>1.18.0</version>
<scope>provided</scope>
</dependency>
</dependencies>
<properties>
<maven.compiler.target>8</maven.compiler.target>
<maven.compiler.source>8</maven.compiler.source>
</properties>
</project>
+12 -4
View File
@@ -5,7 +5,7 @@
<parent>
<artifactId>AntiVPN</artifactId>
<groupId>dev.brighten.antivpn</groupId>
<version>1.8.2</version>
<version>1.9.3.1</version>
</parent>
<modelVersion>4.0.0</modelVersion>
@@ -16,7 +16,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.7.0</version>
<version>3.13.0</version>
<configuration>
<source>8</source>
<target>8</target>
@@ -26,7 +26,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.1.0</version>
<version>3.5.2</version>
<configuration>
<relocations>
<relocation>
@@ -34,6 +34,14 @@
<!-- 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>
<relocation>
<pattern>com.google</pattern>
<shadedPattern>dev.brighten.antivpn.shaded.com.google</shadedPattern>
</relocation>
</relocations>
</configuration>
<executions>
@@ -63,7 +71,7 @@
<dependency>
<groupId>dev.brighten.antivpn</groupId>
<artifactId>Common</artifactId>
<version>1.8.2</version>
<version>1.9.3.1</version>
<scope>provided</scope>
</dependency>
<dependency>
@@ -1,17 +1,23 @@
package dev.brighten.antivpn.bungee;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import dev.brighten.antivpn.AntiVPN;
import dev.brighten.antivpn.api.APIPlayer;
import dev.brighten.antivpn.api.VPNExecutor;
import dev.brighten.antivpn.web.objects.VPNResponse;
import net.md_5.bungee.BungeeCord;
import net.md_5.bungee.api.ChatColor;
import net.md_5.bungee.api.chat.TextComponent;
import net.md_5.bungee.api.event.PlayerDisconnectEvent;
import net.md_5.bungee.api.event.PostLoginEvent;
import net.md_5.bungee.api.event.PreLoginEvent;
import net.md_5.bungee.api.plugin.Listener;
import net.md_5.bungee.api.scheduler.ScheduledTask;
import net.md_5.bungee.event.EventHandler;
import net.md_5.bungee.event.EventPriority;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
@@ -19,18 +25,17 @@ public class BungeeListener extends VPNExecutor implements Listener {
private ScheduledTask cacheResetTask;
private final Cache<UUID, VPNResponse> responseCache = CacheBuilder.newBuilder()
.expireAfterWrite(5, TimeUnit.MINUTES)
.maximumSize(2000)
.build();
@Override
public void registerListeners() {
BungeePlugin.pluginInstance.getProxy().getPluginManager()
.registerListener(BungeePlugin.pluginInstance, this);
}
@Override
public void runCacheReset() {
cacheResetTask = BungeePlugin.pluginInstance.getProxy().getScheduler().schedule(BungeePlugin.pluginInstance,
this::resetCache, 20, 20, TimeUnit.MINUTES);
}
@Override
public void shutdown() {
if(cacheResetTask != null) {
@@ -42,11 +47,38 @@ public class BungeeListener extends VPNExecutor implements Listener {
}
@Override
public void log(String log, Object... objects) {
public void log(Level level, String log, Object... objects) {
BungeeCord.getInstance().getLogger().log(Level.INFO, String.format(log, objects));
}
@EventHandler
@Override
public void log(String log, Object... objects) {
log(Level.INFO, String.format(log, objects));
}
@Override
public void logException(String message, Exception ex) {
BungeeCord.getInstance().getLogger().log(Level.SEVERE, message, ex);
}
@EventHandler(priority = EventPriority.LOWEST)
public void onListener(final PreLoginEvent event) {
if(!responseCache.asMap().containsKey(event.getConnection().getUniqueId())) return;
VPNResponse cached = responseCache.getIfPresent(event.getConnection().getUniqueId());
if(cached != null && cached.isProxy()) {
event.setCancelled(true);
event.setCancelReason(TextComponent.fromLegacyText(ChatColor
.translateAlternateColorCodes('&',
AntiVPN.getInstance().getVpnConfig().getKickString())));
AntiVPN.getInstance().getExecutor().log(Level.INFO,
"%s was kicked from pre-login proxy cache.",
event.getConnection().getName());
}
}
@EventHandler(priority = EventPriority.LOWEST)
public void onListener(final PostLoginEvent event) {
if(event.getPlayer().hasPermission("antivpn.bypass") //Has bypass permission
|| AntiVPN.getInstance().getVpnConfig().getPrefixWhitelists().stream()
@@ -55,20 +87,31 @@ public class BungeeListener extends VPNExecutor implements Listener {
checkIp(event.getPlayer().getAddress().getAddress().getHostAddress(),
AntiVPN.getInstance().getVpnConfig().cachedResults(), result -> {
if(result.isSuccess()) {
// If the countryList() size is zero, no need to check.
// Running country check first
if(AntiVPN.getInstance().getVpnConfig().countryList().size() > 0
&& !(AntiVPN.getInstance().getExecutor().isWhitelisted(event.getPlayer().getUniqueId()) //Is exempt
//Or has a name that starts with a certain prefix. This is for Bedrock exempting.
|| AntiVPN.getInstance().getExecutor().isWhitelisted(event.getPlayer().getAddress().getAddress()
.getHostAddress()))
//If the player is whitelisted, we don't want to kick them
if(AntiVPN.getInstance().getExecutor().isWhitelisted(event.getPlayer().getUniqueId())) {
AntiVPN.getInstance().getExecutor().log("UUID is whitelisted: %s",
event.getPlayer().getUniqueId().toString());
return;
}
//If the IP is whitelisted, we don't want to kick them
if(AntiVPN.getInstance().getExecutor().isWhitelisted(event.getPlayer().getAddress().getAddress()
.getHostAddress())) {
AntiVPN.getInstance().getExecutor().log("IP is whitelisted: %s",
event.getPlayer().getAddress().getAddress().getHostAddress());
return;
}
responseCache.put(event.getPlayer().getUniqueId(), result);
if(!AntiVPN.getInstance().getVpnConfig().countryList().isEmpty()
// This bit of code will decide whether or not to kick the player
// If it contains the code and it is set to whitelist, it will not kick as they are equal
// and vise versa. However, if the contains does not match the state, it will kick.
&& AntiVPN.getInstance().getVpnConfig().countryList()
.contains(result.getCountryCode()) != AntiVPN.getInstance().getVpnConfig().whitelistCountries()) {
//Using our built in kicking system if no commands are configured
if(AntiVPN.getInstance().getVpnConfig().countryKickCommands().size() == 0) {
if(AntiVPN.getInstance().getVpnConfig().countryKickCommands().isEmpty()) {
final String kickReason = AntiVPN.getInstance().getVpnConfig()
.countryVanillaKickReason();
// Kicking our player
@@ -4,8 +4,6 @@ import dev.brighten.antivpn.AntiVPN;
import lombok.val;
import net.md_5.bungee.api.ChatColor;
import net.md_5.bungee.api.CommandSender;
import net.md_5.bungee.api.chat.BaseComponent;
import net.md_5.bungee.api.chat.ComponentBuilder;
import net.md_5.bungee.api.chat.TextComponent;
import net.md_5.bungee.api.plugin.Command;
import net.md_5.bungee.api.plugin.TabExecutor;
+53 -13
View File
@@ -5,7 +5,7 @@
<parent>
<artifactId>AntiVPN</artifactId>
<groupId>dev.brighten.antivpn</groupId>
<version>1.8.2</version>
<version>1.9.3.1</version>
</parent>
<modelVersion>4.0.0</modelVersion>
@@ -21,13 +21,50 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<version>3.13.0</version>
<configuration>
<source>8</source>
<target>8</target>
<compilerArgument>-XDignore.symbol.file</compilerArgument>
<annotationProcessorPaths>
<path>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.30</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.5.2</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>
</relocation>
<relocation>
<pattern>com.google.common</pattern>
<shadedPattern>dev.brighten.antivpn.shaded.com.google.common</shadedPattern>
</relocation>
<relocation>
<pattern>org.h2</pattern>
<shadedPattern>dev.brighten.antivpn.shaded.org.h2</shadedPattern>
</relocation>
</relocations>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
<resources>
<resource>
@@ -46,29 +83,32 @@
<dependencies>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.30</version>
<type>jar</type>
<scope>provided</scope>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<version>9.1.0</version>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>2.1.214</version>
<scope>provided</scope>
<version>2.2.224</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.yaml</groupId>
<artifactId>snakeyaml</artifactId>
<version>1.30</version>
<scope>provided</scope>
<version>2.2</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>32.1.3-jre</version>
</dependency>
<dependency>
<groupId>org.mongodb</groupId>
<artifactId>mongo-java-driver</artifactId>
<version>3.12.11</version>
<scope>provided</scope>
<version>3.12.14</version>
<scope>compile</scope>
</dependency>
</dependencies>
@@ -9,8 +9,6 @@ import dev.brighten.antivpn.database.VPNDatabase;
import dev.brighten.antivpn.database.local.H2VPN;
import dev.brighten.antivpn.database.mongo.MongoVPN;
import dev.brighten.antivpn.database.sql.MySqlVPN;
import dev.brighten.antivpn.depends.LibraryLoader;
import dev.brighten.antivpn.depends.MavenLibrary;
import dev.brighten.antivpn.message.MessageHandler;
import dev.brighten.antivpn.utils.ConfigDefault;
import dev.brighten.antivpn.utils.MiscUtils;
@@ -31,10 +29,6 @@ import java.util.List;
@Getter
@Setter(AccessLevel.PRIVATE)
@MavenLibrary(groupId = "com.h2database", artifactId ="h2", version = "2.1.214")
@MavenLibrary(groupId = "org.yaml", artifactId = "snakeyaml", version = "1.30")
@MavenLibrary(groupId = "org.mongodb", artifactId = "mongo-java-driver", version = "3.12.11")
@MavenLibrary(groupId = "mysql", artifactId = "mysql-connector-java", version = "8.0.30")
public class AntiVPN {
private static AntiVPN INSTANCE;
@@ -57,8 +51,6 @@ public class AntiVPN {
INSTANCE.executor = executor;
INSTANCE.playerExecutor = playerExecutor;
LibraryLoader.loadAll(INSTANCE);
try {
File configFile = new File(pluginFolder, "config.yml");
if(!configFile.exists()){
@@ -1,39 +1,49 @@
package dev.brighten.antivpn.api;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import dev.brighten.antivpn.AntiVPN;
import dev.brighten.antivpn.utils.EvictingMap;
import dev.brighten.antivpn.web.objects.VPNResponse;
import dev.brighten.antivpn.utils.json.JSONException;
import dev.brighten.antivpn.web.FunkemunkyAPI;
import dev.brighten.antivpn.web.objects.VPNResponse;
import lombok.Getter;
import java.io.IOException;
import java.util.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;
import java.util.logging.Level;
public abstract class VPNExecutor {
public static ExecutorService threadExecutor = Executors.newSingleThreadExecutor();
public static ScheduledExecutorService threadExecutor = Executors.newScheduledThreadPool(2);
public static final Map<String, VPNResponse> responseCache = new EvictingMap<>(5000);
@Getter
private final Set<UUID> whitelisted = Collections.synchronizedSet(new HashSet<>());
@Getter
private final Set<String> whitelistedIps = Collections.synchronizedSet(new HashSet<>());
private final Cache<String, VPNResponse> responseCache = CacheBuilder.newBuilder()
.expireAfterWrite(20, TimeUnit.MINUTES)
.maximumSize(4000)
.build();
public abstract void registerListeners();
public abstract void runCacheReset();
public void resetCache() {
responseCache.clear();
}
public abstract void shutdown();
public abstract void log(Level level, String log, Object... objects);
public abstract void log(String log, Object... objects);
public abstract void logException(String message, Exception ex);
public void logException(Exception ex) {
logException("An exception occurred: " + ex.getMessage(), ex);
}
public boolean isWhitelisted(UUID uuid) {
if(AntiVPN.getInstance().getVpnConfig().isDatabaseEnabled()) {
return AntiVPN.getInstance().getDatabase().isWhitelisted(uuid);
@@ -49,60 +59,42 @@ public abstract class VPNExecutor {
}
public void checkIp(String ip, boolean cachedResults, Consumer<VPNResponse> result) {
threadExecutor.execute(() -> result.accept(responseCache.compute(ip, (key, val) -> {
if(val == null) {
Optional<VPNResponse> cachedRes = AntiVPN.getInstance().getDatabase().getStoredResponse(ip);
if(cachedRes.isPresent()) return cachedRes.get();
else {
try {
VPNResponse response = FunkemunkyAPI
.getVPNResponse(ip, AntiVPN.getInstance().getVpnConfig().getLicense(), cachedResults);
if(response.isSuccess()) {
AntiVPN.getInstance().getDatabase().cacheResponse(response);
} else {
log("Query to VPN API failed! Reason: " + response.getFailureReason());
}
return response;
} catch (JSONException | IOException e) {
log("Query to VPN API failed! Reason: Java Exception");
e.printStackTrace();
}
threadExecutor.execute(() -> {
if(cachedResults) {
try {
result.accept(responseCache.get(ip, () -> checkIp(ip)));
} catch (ExecutionException e) {
log("Failed to process checkIp() method! Reason: " + e.getMessage());
result.accept(VPNResponse.FAILED_RESPONSE);
}
} else {
result.accept(checkIp(ip));
}
return val;
})));
}
public VPNResponse checkIp(String ip, boolean cachedResults) {
return responseCache.compute(ip, (key, val) -> {
if(val == null) {
Optional<VPNResponse> cachedRes = AntiVPN.getInstance().getDatabase().getStoredResponse(ip);
if(cachedRes.isPresent()) return cachedRes.get();
else {
try {
VPNResponse response = FunkemunkyAPI
.getVPNResponse(ip, AntiVPN.getInstance().getVpnConfig().getLicense(), cachedResults);
if(response.isSuccess()) {
threadExecutor.execute(() -> AntiVPN.getInstance().getDatabase().cacheResponse(response));
} else {
log("Query to VPN API failed! Reason: " + response.getFailureReason());
}
return response;
} catch (JSONException | IOException e) {
log("Query to VPN API failed! Reason: Java Exception");
e.printStackTrace();
}
}
}
return val;
});
}
public VPNResponse checkIp(String ip) {
Optional<VPNResponse> cachedRes = AntiVPN.getInstance().getDatabase().getStoredResponse(ip);
if(cachedRes.isPresent()) {
return cachedRes.get();
}
else {
try {
VPNResponse response = FunkemunkyAPI
.getVPNResponse(ip, AntiVPN.getInstance().getVpnConfig().getLicense(), true);
if (response.isSuccess()) {
AntiVPN.getInstance().getDatabase().cacheResponse(response);
} else {
log("Query to VPN API failed! Reason: " + response.getFailureReason());
}
return response;
} catch (JSONException | IOException e) {
log("Query to VPN API failed! Reason: " + e.getMessage());
return VPNResponse.FAILED_RESPONSE;
}
}
}
}
@@ -2,7 +2,6 @@ package dev.brighten.antivpn.command;
import dev.brighten.antivpn.api.APIPlayer;
import java.util.Objects;
import java.util.Optional;
public interface CommandExecutor {
@@ -1,7 +1,6 @@
package dev.brighten.antivpn.command.impl;
import dev.brighten.antivpn.AntiVPN;
import dev.brighten.antivpn.api.VPNExecutor;
import dev.brighten.antivpn.command.Command;
import dev.brighten.antivpn.command.CommandExecutor;
@@ -47,7 +46,6 @@ public class ClearCacheCommand extends Command {
@Override
public String execute(CommandExecutor executor, String[] args) {
AntiVPN.getInstance().getDatabase().clearResponses();
VPNExecutor.responseCache.clear();
return "&aCleared all cached API response information!";
}
@@ -10,6 +10,7 @@ import dev.brighten.antivpn.web.FunkemunkyAPI;
import dev.brighten.antivpn.web.objects.QueryResponse;
import java.io.IOException;
import java.util.Collections;
import java.util.List;
public class PlanCommand extends Command {
@@ -53,7 +54,7 @@ public class PlanCommand extends Command {
VPNExecutor.threadExecutor.execute(() -> {
QueryResponse result;
try {
if(AntiVPN.getInstance().getVpnConfig().getLicense().equals("")) {
if(AntiVPN.getInstance().getVpnConfig().getLicense().isEmpty()) {
result = FunkemunkyAPI.getQueryResponse();
} else {
result = FunkemunkyAPI.getQueryResponse(AntiVPN.getInstance().getVpnConfig().getLicense());
@@ -81,11 +82,11 @@ public class PlanCommand extends Command {
result.getQueries(), queryMax);
executor.sendMessage(StringUtil.line("&8"));
} catch(JSONException e) {
e.printStackTrace();
AntiVPN.getInstance().getExecutor().logException(e);
executor.sendMessage("&cThere was a JSONException thrown while looking up your query " +
"information. Check console for more details.");
} catch (IOException e) {
e.printStackTrace();
AntiVPN.getInstance().getExecutor().logException(e);
executor.sendMessage("&cThere was a IOException thrown while looking up your query " +
"information. Check console for more details.");
}
@@ -95,6 +96,6 @@ public class PlanCommand extends Command {
@Override
public List<String> tabComplete(CommandExecutor executor, String alias, String[] args) {
return null;
return Collections.emptyList();
}
}
@@ -1,13 +1,8 @@
package dev.brighten.antivpn.command.impl;
import dev.brighten.antivpn.AntiVPN;
import dev.brighten.antivpn.api.VPNExecutor;
import dev.brighten.antivpn.command.Command;
import dev.brighten.antivpn.command.CommandExecutor;
import dev.brighten.antivpn.database.local.H2VPN;
import dev.brighten.antivpn.database.mongo.MongoVPN;
import dev.brighten.antivpn.database.sql.MySqlVPN;
import dev.brighten.antivpn.message.VpnString;
import java.util.Collections;
import java.util.List;
@@ -58,9 +53,6 @@ public class ReloadCommand extends Command {
AntiVPN.getInstance().getMessageHandler().reloadStrings();
// Clearing the local response cache
VPNExecutor.responseCache.clear();
AntiVPN.getInstance().reloadDatabase();
return AntiVPN.getInstance().getMessageHandler().getString("command-reload-complete").getMessage();
@@ -12,6 +12,8 @@ public interface VPNDatabase {
void cacheResponse(VPNResponse toCache);
void deleteResponse(String ip);
boolean isWhitelisted(UUID uuid);
boolean isWhitelisted(String ip);
@@ -20,34 +20,20 @@ import java.util.function.Consumer;
public class H2VPN implements VPNDatabase {
private Thread whitelistedThread;
public H2VPN() {
whitelistedThread = new Thread(() -> {
try {
Thread.sleep(TimeUnit.SECONDS.toMillis(2));
} catch (InterruptedException e) {
e.printStackTrace();
}
while (true) {
// Updating from database
if (AntiVPN.getInstance().getVpnConfig().isDatabaseEnabled()) {
AntiVPN.getInstance().getExecutor().getWhitelisted().clear();
AntiVPN.getInstance().getExecutor().getWhitelisted()
.addAll(AntiVPN.getInstance().getDatabase().getAllWhitelisted());
AntiVPN.getInstance().getExecutor().getWhitelistedIps().clear();
AntiVPN.getInstance().getExecutor().getWhitelistedIps()
.addAll(AntiVPN.getInstance().getDatabase().getAllWhitelistedIps());
}
try {
Thread.sleep(TimeUnit.SECONDS.toMillis(4));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
VPNExecutor.threadExecutor.scheduleAtFixedRate(() -> {
if(!AntiVPN.getInstance().getVpnConfig().isDatabaseEnabled() || MySQL.isClosed()) return;
whitelistedThread.start();
//Refreshing whitelisted players
AntiVPN.getInstance().getExecutor().getWhitelisted().clear();
AntiVPN.getInstance().getExecutor().getWhitelisted()
.addAll(AntiVPN.getInstance().getDatabase().getAllWhitelisted());
//Refreshing whitlisted IPs
AntiVPN.getInstance().getExecutor().getWhitelistedIps().clear();
AntiVPN.getInstance().getExecutor().getWhitelistedIps()
.addAll(AntiVPN.getInstance().getDatabase().getAllWhitelistedIps());
}, 2, 30, TimeUnit.SECONDS);
}
@Override
@@ -65,7 +51,12 @@ public class H2VPN implements VPNDatabase {
rs.getString("method"), rs.getString("isp"), "N/A",
rs.getBoolean("proxy"), rs.getBoolean("cached"), true,
rs.getDouble("latitude"), rs.getDouble("longitude"),
System.currentTimeMillis(), -1);
rs.getTimestamp("inserted").getTime(), -1);
if(System.currentTimeMillis() - response.getLastAccess() > TimeUnit.HOURS.toMillis(1)) {
VPNExecutor.threadExecutor.execute(() -> deleteResponse(ip));
return Optional.empty();
}
return Optional.of(response);
}
} catch (SQLException throwables) {
@@ -98,6 +89,14 @@ public class H2VPN implements VPNDatabase {
.append(toCache.getLatitude()).append(toCache.getLongitude()).execute();
}
@Override
public void deleteResponse(String ip) {
if(!AntiVPN.getInstance().getVpnConfig().isDatabaseEnabled() || MySQL.isClosed())
return;
Query.prepare("delete from `responses` where `ip` = ?").append(ip).execute();
}
@SneakyThrows
@Override
public boolean isWhitelisted(UUID uuid) {
@@ -7,26 +7,50 @@ import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoDatabase;
import com.mongodb.client.model.Filters;
import com.mongodb.client.model.Indexes;
import com.mongodb.client.model.UpdateOptions;
import dev.brighten.antivpn.AntiVPN;
import dev.brighten.antivpn.api.VPNExecutor;
import dev.brighten.antivpn.database.VPNDatabase;
import dev.brighten.antivpn.web.objects.VPNResponse;
import org.bson.Document;
import org.bson.conversions.Bson;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;
public class MongoVPN implements VPNDatabase {
private MongoCollection<Document> settingsDocument, cacheDocument;
private MongoClient client;
private MongoDatabase antivpnDatabase;
public MongoVPN() {
VPNExecutor.threadExecutor.scheduleAtFixedRate(() -> {
if(!AntiVPN.getInstance().getVpnConfig().isDatabaseEnabled()) return;
//Refreshing whitelisted players
AntiVPN.getInstance().getExecutor().getWhitelisted().clear();
AntiVPN.getInstance().getExecutor().getWhitelisted()
.addAll(AntiVPN.getInstance().getDatabase().getAllWhitelisted());
//Refreshing whitlisted IPs
AntiVPN.getInstance().getExecutor().getWhitelistedIps().clear();
AntiVPN.getInstance().getExecutor().getWhitelistedIps()
.addAll(AntiVPN.getInstance().getDatabase().getAllWhitelistedIps());
}, 2, 30, TimeUnit.SECONDS);
}
@Override
public Optional<VPNResponse> getStoredResponse(String ip) {
Document rdoc = cacheDocument.find(Filters.eq("ip", ip)).first();
if(rdoc != null) {
long lastUpdate = rdoc.get("lastAccess", 0L);
if(System.currentTimeMillis() - lastUpdate > TimeUnit.HOURS.toMillis(1)) {
VPNExecutor.threadExecutor.execute(() -> deleteResponse(ip));
return Optional.empty();
}
return Optional.of(VPNResponse.builder().asn(rdoc.getString("asn")).ip(ip)
.countryName(rdoc.getString("countryName"))
.countryCode(rdoc.getString("countryCode"))
@@ -39,6 +63,7 @@ public class MongoVPN implements VPNDatabase {
.success(true)
.latitude(rdoc.getDouble("latitude"))
.longitude(rdoc.getDouble("longitude"))
.lastAccess(rdoc.get("lastAccess", 0L))
.build());
}
return Optional.empty();
@@ -60,13 +85,20 @@ public class MongoVPN implements VPNDatabase {
rdoc.put("success", toCache.isSuccess());
rdoc.put("latitude", toCache.getLatitude());
rdoc.put("longitude", toCache.getLongitude());
rdoc.put("lastAccess", System.currentTimeMillis());
VPNExecutor.threadExecutor.execute(() -> {
cacheDocument.deleteMany(Filters.eq("ip", toCache.getIp()));
cacheDocument.insertOne(rdoc);
Bson update = new Document("$set", rdoc);
cacheDocument.updateOne(Filters.eq("ip", toCache.getIp()), update,
new UpdateOptions().upsert(true));
});
}
@Override
public void deleteResponse(String ip) {
cacheDocument.deleteMany(Filters.eq("ip", ip));
}
@Override
public boolean isWhitelisted(UUID uuid) {
return settingsDocument
@@ -100,8 +132,8 @@ public class MongoVPN implements VPNDatabase {
@Override
public void setWhitelisted(String ip, boolean whitelisted) {
if(whitelisted) {
Document wdoc = new Document("setting", "whitelist");
wdoc.put("ip", ip);
Document wdoc = new Document("setting", "whitelist").append("ip", ip);
AntiVPN.getInstance().getExecutor().getWhitelistedIps().add(ip);
VPNExecutor.threadExecutor.execute(() -> settingsDocument.insertOne(wdoc));
} else {
@@ -174,18 +206,20 @@ public class MongoVPN implements VPNDatabase {
@Override
public void init() {
if(AntiVPN.getInstance().getVpnConfig().mongoDatabaseURL().length() > 0) { //URL
if(!AntiVPN.getInstance().getVpnConfig().mongoDatabaseURL().isEmpty()) { //URL
ConnectionString cs = new ConnectionString(AntiVPN.getInstance().getVpnConfig().mongoDatabaseURL());
MongoClientSettings settings = MongoClientSettings.builder().applyConnectionString(cs).build();
client = MongoClients.create(settings);
} else {
MongoClientSettings.Builder settingsBld = MongoClientSettings.builder().readPreference(ReadPreference.nearest())
.applyToClusterSettings(builder -> {
builder.hosts(Collections.singletonList(new ServerAddress(AntiVPN.getInstance().getVpnConfig().getIp(),
AntiVPN.getInstance().getVpnConfig().getPort())));
});
.applyToClusterSettings(builder -> builder.
hosts(Collections.singletonList(
new ServerAddress(
AntiVPN.getInstance().getVpnConfig().getIp(),
AntiVPN.getInstance().getVpnConfig().getPort())
)));
if(AntiVPN.getInstance().getVpnConfig().useDatabaseCreds()) {
settingsBld = settingsBld.credential(MongoCredential
settingsBld.credential(MongoCredential
.createCredential(AntiVPN.getInstance().getVpnConfig().getUsername(),
AntiVPN.getInstance().getVpnConfig().getDatabaseName(),
AntiVPN.getInstance().getVpnConfig().getPassword().toCharArray()));
@@ -193,7 +227,7 @@ public class MongoVPN implements VPNDatabase {
client = MongoClients.create(settingsBld.build());
}
antivpnDatabase = client.getDatabase(AntiVPN.getInstance().getVpnConfig().getDatabaseName());
MongoDatabase antivpnDatabase = client.getDatabase(AntiVPN.getInstance().getVpnConfig().getDatabaseName());
settingsDocument = antivpnDatabase.getCollection("settings");
if(settingsDocument.listIndexes().first() == null) {
@@ -20,39 +20,25 @@ import java.util.function.Consumer;
public class MySqlVPN implements VPNDatabase {
private Thread whitelistedThread;
public MySqlVPN() {
whitelistedThread = new Thread(() -> {
try {
Thread.sleep(TimeUnit.SECONDS.toMillis(2));
} catch (InterruptedException e) {
e.printStackTrace();
}
while (true) {
// Updating from database
if (AntiVPN.getInstance().getVpnConfig().isDatabaseEnabled()) {
AntiVPN.getInstance().getExecutor().getWhitelisted().clear();
AntiVPN.getInstance().getExecutor().getWhitelisted()
.addAll(AntiVPN.getInstance().getDatabase().getAllWhitelisted());
AntiVPN.getInstance().getExecutor().getWhitelistedIps().clear();
AntiVPN.getInstance().getExecutor().getWhitelistedIps()
.addAll(AntiVPN.getInstance().getDatabase().getAllWhitelistedIps());
}
try {
Thread.sleep(TimeUnit.SECONDS.toMillis(4));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
VPNExecutor.threadExecutor.scheduleAtFixedRate(() -> {
if(!AntiVPN.getInstance().getVpnConfig().isDatabaseEnabled() || MySQL.isClosed()) return;
whitelistedThread.start();
//Refreshing whitelisted players
AntiVPN.getInstance().getExecutor().getWhitelisted().clear();
AntiVPN.getInstance().getExecutor().getWhitelisted()
.addAll(AntiVPN.getInstance().getDatabase().getAllWhitelisted());
//Refreshing whitlisted IPs
AntiVPN.getInstance().getExecutor().getWhitelistedIps().clear();
AntiVPN.getInstance().getExecutor().getWhitelistedIps()
.addAll(AntiVPN.getInstance().getDatabase().getAllWhitelistedIps());
}, 2, 30, TimeUnit.SECONDS);
}
@Override
public Optional<VPNResponse> getStoredResponse(String ip) {
if (!AntiVPN.getInstance().getVpnConfig().isDatabaseEnabled()|| MySQL.isClosed())
if (isDisabled())
return Optional.empty();
ResultSet rs = Query.prepare("select * from `responses` where `ip` = ? limit 1").append(ip).executeQuery();
@@ -65,7 +51,13 @@ public class MySqlVPN implements VPNDatabase {
rs.getString("method"), rs.getString("isp"), "N/A",
rs.getBoolean("proxy"), rs.getBoolean("cached"), true,
rs.getDouble("latitude"), rs.getDouble("longitude"),
System.currentTimeMillis(), -1);
rs.getTimestamp("inserted").getTime(), -1);
if(System.currentTimeMillis() - response.getLastAccess() > TimeUnit.HOURS.toMillis(1)) {
VPNExecutor.threadExecutor.execute(() -> deleteResponse(ip));
return Optional.empty();
}
return Optional.of(response);
}
} catch (SQLException throwables) {
@@ -86,7 +78,7 @@ public class MySqlVPN implements VPNDatabase {
*/
@Override
public void cacheResponse(VPNResponse toCache) {
if (!AntiVPN.getInstance().getVpnConfig().isDatabaseEnabled() || MySQL.isClosed())
if (isDisabled())
return;
Query.prepare("insert into `responses` (`ip`,`asn`,`countryName`,`countryCode`,`city`,`timeZone`,"
@@ -98,10 +90,18 @@ public class MySqlVPN implements VPNDatabase {
.append(toCache.getLatitude()).append(toCache.getLongitude()).execute();
}
@Override
public void deleteResponse(String ip) {
if(!isDisabled())
return;
Query.prepare("delete from `responses` where `ip` = ?").append(ip).execute();
}
@SneakyThrows
@Override
public boolean isWhitelisted(UUID uuid) {
if (!AntiVPN.getInstance().getVpnConfig().isDatabaseEnabled() || MySQL.isClosed())
if (isDisabled())
return false;
ResultSet set = Query.prepare("select uuid from `whitelisted` where `uuid` = ? limit 1")
.append(uuid.toString()).executeQuery();
@@ -112,7 +112,7 @@ public class MySqlVPN implements VPNDatabase {
@SneakyThrows
@Override
public boolean isWhitelisted(String ip) {
if (!AntiVPN.getInstance().getVpnConfig().isDatabaseEnabled() || MySQL.isClosed())
if (isDisabled())
return false;
ResultSet set = Query.prepare("select `ip` from `whitelisted-ips` where `ip` = ? limit 1")
.append(ip).executeQuery();
@@ -123,7 +123,7 @@ public class MySqlVPN implements VPNDatabase {
@Override
public void setWhitelisted(UUID uuid, boolean whitelisted) {
if (!AntiVPN.getInstance().getVpnConfig().isDatabaseEnabled() || MySQL.isClosed())
if (isDisabled())
return;
if (whitelisted) {
@@ -139,7 +139,7 @@ public class MySqlVPN implements VPNDatabase {
@Override
public void setWhitelisted(String ip, boolean whitelisted) {
if (!AntiVPN.getInstance().getVpnConfig().isDatabaseEnabled() || MySQL.isClosed())
if (isDisabled())
return;
if(whitelisted) {
@@ -333,6 +333,10 @@ public class MySqlVPN implements VPNDatabase {
System.err.println("MySQL Excepton created" + e.getMessage());
}
}
private boolean isDisabled() {
return !AntiVPN.getInstance().getVpnConfig().isDatabaseEnabled()|| MySQL.isClosed();
}
@Override
public void shutdown() {
@@ -1,11 +1,13 @@
package dev.brighten.antivpn.database.sql.utils;
import com.mysql.cj.jdbc.Driver;
import dev.brighten.antivpn.AntiVPN;
import java.io.File;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Properties;
public class MySQL {
private static Connection conn;
@@ -13,11 +15,7 @@ public class MySQL {
public static void init() {
try {
if (conn == null || conn.isClosed()) {
try {
Class.forName("com.mysql.cj.jdbc.Driver");
} catch (ClassNotFoundException e) {
Class.forName("com.mysql.jdbc.Driver");
}
DriverManager.registerDriver(new Driver());
conn = DriverManager.getConnection("jdbc:mysql://" + AntiVPN.getInstance().getVpnConfig().getIp()
+ ":" + AntiVPN.getInstance().getVpnConfig().getPort()
+ "/?useSSL=true&autoReconnect=true",
@@ -31,26 +29,23 @@ public class MySQL {
AntiVPN.getInstance().getExecutor().log("Connection to MySQL has been established.");
}
} catch (Exception e) {
AntiVPN.getInstance().getExecutor().log("Failed to load mysql: " + e.getMessage());
e.printStackTrace();
AntiVPN.getInstance().getExecutor().logException("Failed to load mysql: " + e.getMessage(), e);
}
}
public static void initH2() {
File dataFolder = new File(AntiVPN.getInstance().getPluginFolder(), "databases" + File.separator + "database");
File dataFolder = new File(AntiVPN.getInstance().getPluginFolder(), "databases");
File databaseFile = new File(dataFolder, "database");
try {
Class.forName("org.h2.Driver");
conn = new NonClosableConnection(DriverManager.getConnection ("jdbc:h2:file:" +
dataFolder.getAbsolutePath(),
AntiVPN.getInstance().getVpnConfig().getUsername(),AntiVPN.getInstance().getVpnConfig().getPassword()));
conn = new NonClosableConnection(new org.h2.jdbc.JdbcConnection("jdbc:h2:file:" +
databaseFile.getAbsolutePath(),
new Properties(), AntiVPN.getInstance().getVpnConfig().getUsername(),
AntiVPN.getInstance().getVpnConfig().getPassword(), false));
conn.setAutoCommit(true);
Query.use(conn);
AntiVPN.getInstance().getExecutor().log("Connection to H2 has been established.");
} catch (SQLException ex) {
AntiVPN.getInstance().getExecutor().log("H2 exception on initialize");
ex.printStackTrace();
} catch (ClassNotFoundException ex) {
AntiVPN.getInstance().getExecutor().log("No H2 library found!");
AntiVPN.getInstance().getExecutor().logException("H2 exception on initialize", ex);
}
}
@@ -58,7 +53,7 @@ public class MySQL {
try {
init();
} catch (Exception e) {
e.printStackTrace();
AntiVPN.getInstance().getExecutor().logException(e);
}
}
@@ -71,7 +66,7 @@ public class MySQL {
conn = null;
}
} catch (Exception e) {
e.printStackTrace();
AntiVPN.getInstance().getExecutor().logException(e);
}
}
@@ -82,7 +77,7 @@ public class MySQL {
try {
return conn.isClosed();
} catch (SQLException e) {
e.printStackTrace();
AntiVPN.getInstance().getExecutor().logException(e);
return true;
}
}
@@ -1,200 +0,0 @@
/*
* This file is part of helper, licensed under the MIT License.
*
* Copyright (c) lucko (Luck) <luck@lucko.me>
* Copyright (c) contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package dev.brighten.antivpn.depends;
import dev.brighten.antivpn.AntiVPN;
import dev.brighten.antivpn.utils.NonnullByDefault;
import dev.brighten.antivpn.utils.Supplier;
import dev.brighten.antivpn.utils.Suppliers;
import java.io.File;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.nio.file.Files;
import java.util.Objects;
/**
* Resolves {@link MavenLibrary} annotations for a class, and loads the dependency
* into the classloader.
*/
@NonnullByDefault
public final class LibraryLoader {
@SuppressWarnings("Guava")
private static final Supplier<URLClassLoaderAccess> URL_INJECTOR = Suppliers.memoize(() -> URLClassLoaderAccess.create((URLClassLoader) AntiVPN.getInstance().getClass().getClassLoader()));
/**
* Resolves all {@link MavenLibrary} annotations on the given object.
*
* @param object the object to load libraries for.
*/
public static void loadAll(Object object) {
loadAll(object.getClass());
}
/**
* Resolves all {@link MavenLibrary} annotations on the given class.
*
* @param clazz the class to load libraries for.
*/
public static void loadAll(Class<?> clazz) {
MavenLibrary[] libs = clazz.getDeclaredAnnotationsByType(MavenLibrary.class);
if (libs == null) {
return;
}
for (MavenLibrary lib : libs) {
load(lib.groupId(), lib.artifactId(), lib.version(), lib.repo().url());
}
}
public static void load(String groupId, String artifactId, String version) {
load(groupId, artifactId, version, "https://repo1.maven.org/maven2");
}
public static void load(String groupId, String artifactId, String version, String repoUrl) {
load(new Dependency(groupId, artifactId, version, repoUrl));
}
public static void load(Dependency d) {
AntiVPN.getInstance().getExecutor().log(String.format("Loading dependency %s:%s:%s from %s", d.getGroupId(), d.getArtifactId(), d.getVersion(), d.getRepoUrl()));
String name = d.getArtifactId() + "-" + d.getVersion();
File saveLocation = new File(getLibFolder(), name + ".jar");
if (!saveLocation.exists()) {
try {
AntiVPN.getInstance().getExecutor().log("Dependency '" + name + "' is not already in the libraries folder. Attempting to download...");
URL url = d.getUrl();
try (InputStream is = url.openStream()) {
Files.copy(is, saveLocation.toPath());
}
} catch (Exception e) {
e.printStackTrace();
}
AntiVPN.getInstance().getExecutor().log("Dependency '" + name + "' successfully downloaded.");
}
if (!saveLocation.exists()) {
throw new RuntimeException("Unable to download dependency: " + d.toString());
}
try {
URL_INJECTOR.get().addURL(saveLocation.toURI().toURL());
} catch (Exception e) {
throw new RuntimeException("Unable to load dependency: " + saveLocation.toString(), e);
}
AntiVPN.getInstance().getExecutor().log("Loaded dependency '" + name + "' successfully.");
}
private static File getLibFolder() {
File pluginDataFolder = AntiVPN.getInstance().getPluginFolder();
File libs = new File(pluginDataFolder, "libraries");
libs.mkdirs();
return libs;
}
@NonnullByDefault
public static final class Dependency {
private final String groupId;
private final String artifactId;
private final String version;
private final String repoUrl;
public Dependency(String groupId, String artifactId, String version, String repoUrl) {
this.groupId = Objects.requireNonNull(groupId, "groupId");
this.artifactId = Objects.requireNonNull(artifactId, "artifactId");
this.version = Objects.requireNonNull(version, "version");
this.repoUrl = Objects.requireNonNull(repoUrl, "repoUrl");
}
public String getGroupId() {
return this.groupId;
}
public String getArtifactId() {
return this.artifactId;
}
public String getVersion() {
return this.version;
}
public String getRepoUrl() {
return this.repoUrl;
}
public URL getUrl() throws MalformedURLException {
String repo = this.repoUrl;
if (!repo.endsWith("/")) {
repo += "/";
}
repo += "%s/%s/%s/%s-%s.jar";
String url = String.format(repo, this.groupId.replace(".", "/"), this.artifactId, this.version, this.artifactId, this.version);
return new URL(url);
}
@Override
public boolean equals(Object o) {
if (o == this) return true;
if (!(o instanceof Dependency)) return false;
final Dependency other = (Dependency) o;
return this.getGroupId().equals(other.getGroupId()) &&
this.getArtifactId().equals(other.getArtifactId()) &&
this.getVersion().equals(other.getVersion()) &&
this.getRepoUrl().equals(other.getRepoUrl());
}
@Override
public int hashCode() {
final int PRIME = 59;
int result = 1;
result = result * PRIME + this.getGroupId().hashCode();
result = result * PRIME + this.getArtifactId().hashCode();
result = result * PRIME + this.getVersion().hashCode();
result = result * PRIME + this.getRepoUrl().hashCode();
return result;
}
@Override
public String toString() {
return "LibraryLoader.Dependency(" +
"groupId=" + this.getGroupId() + ", " +
"artifactId=" + this.getArtifactId() + ", " +
"version=" + this.getVersion() + ", " +
"repoUrl=" + this.getRepoUrl() + ")";
}
}
}
@@ -1,40 +0,0 @@
/*
* This file is part of helper, licensed under the MIT License.
*
* Copyright (c) lucko (Luck) <luck@lucko.me>
* Copyright (c) contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package dev.brighten.antivpn.depends;
import java.lang.annotation.*;
/**
* Annotation to indicate the required libraries for a class.
*/
@Documented
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface MavenLibraries {
MavenLibrary[] value() default {};
}
@@ -1,67 +0,0 @@
/*
* This file is part of helper, licensed under the MIT License.
*
* Copyright (c) lucko (Luck) <luck@lucko.me>
* Copyright (c) contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package dev.brighten.antivpn.depends;
import java.lang.annotation.*;
/**
* Annotation to indicate a required library for a class.
*/
@Documented
@Repeatable(MavenLibraries.class)
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface MavenLibrary {
/**
* The group id of the library
*
* @return the group id of the library
*/
String groupId();
/**
* The artifact id of the library
*
* @return the artifact id of the library
*/
String artifactId();
/**
* The version of the library
*
* @return the version of the library
*/
String version();
/**
* The repo where the library can be obtained from
*
* @return the repo where the library can be obtained from
*/
Repository repo() default @Repository(url = "https://repo1.maven.org/maven2");
}
@@ -1,45 +0,0 @@
/*
* This file is part of helper, licensed under the MIT License.
*
* Copyright (c) lucko (Luck) <luck@lucko.me>
* Copyright (c) contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package dev.brighten.antivpn.depends;
import java.lang.annotation.*;
/**
* Represents a maven repository.
*/
@Documented
@Target(ElementType.LOCAL_VARIABLE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Repository {
/**
* Gets the base url of the repository.
*
* @return the base url of the repository
*/
String url();
}
@@ -1,175 +0,0 @@
/*
* This file is part of helper, licensed under the MIT License.
*
* Copyright (c) lucko (Luck) <luck@lucko.me>
* Copyright (c) contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package dev.brighten.antivpn.depends;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.Collection;
/**
* Provides access to {@link URLClassLoader}#addURL.
*/
public abstract class URLClassLoaderAccess {
/**
* Creates a {@link URLClassLoaderAccess} for the given class loader.
*
* @param classLoader the class loader
* @return the access object
*/
static URLClassLoaderAccess create(URLClassLoader classLoader) {
if (Reflection.isSupported()) {
return new Reflection(classLoader);
} else if (Unsafe.isSupported()) {
return new Unsafe(classLoader);
} else {
return Noop.INSTANCE;
}
}
private final URLClassLoader classLoader;
protected URLClassLoaderAccess(URLClassLoader classLoader) {
this.classLoader = classLoader;
}
/**
* Adds the given URL to the class loader.
*
* @param url the URL to add
*/
public abstract void addURL(URL url);
/**
* Accesses using reflection, not supported on Java 9+.
*/
private static class Reflection extends URLClassLoaderAccess {
private static final Method ADD_URL_METHOD;
static {
Method addUrlMethod;
try {
addUrlMethod = URLClassLoader.class.getDeclaredMethod("addURL", URL.class);
addUrlMethod.setAccessible(true);
} catch (Exception e) {
addUrlMethod = null;
}
ADD_URL_METHOD = addUrlMethod;
}
private static boolean isSupported() {
return ADD_URL_METHOD != null;
}
Reflection(URLClassLoader classLoader) {
super(classLoader);
}
@Override
public void addURL(URL url) {
try {
ADD_URL_METHOD.invoke(super.classLoader, url);
} catch (ReflectiveOperationException e) {
throw new RuntimeException(e);
}
}
}
/**
* Accesses using sun.misc.Unsafe, supported on Java 9+.
*
* @author Vaishnav Anil (https://github.com/slimjar/slimjar)
*/
private static class Unsafe extends URLClassLoaderAccess {
private static final sun.misc.Unsafe UNSAFE;
static {
sun.misc.Unsafe unsafe;
try {
Field unsafeField = sun.misc.Unsafe.class.getDeclaredField("theUnsafe");
unsafeField.setAccessible(true);
unsafe = (sun.misc.Unsafe) unsafeField.get(null);
} catch (Throwable t) {
unsafe = null;
}
UNSAFE = unsafe;
}
private static boolean isSupported() {
return UNSAFE != null;
}
private final Collection<URL> unopenedURLs;
private final Collection<URL> pathURLs;
@SuppressWarnings("unchecked")
Unsafe(URLClassLoader classLoader) {
super(classLoader);
Collection<URL> unopenedURLs;
Collection<URL> pathURLs;
try {
Object ucp = fetchField(URLClassLoader.class, classLoader, "ucp");
unopenedURLs = (Collection<URL>) fetchField(ucp.getClass(), ucp, "unopenedUrls");
pathURLs = (Collection<URL>) fetchField(ucp.getClass(), ucp, "path");
} catch (Throwable e) {
unopenedURLs = null;
pathURLs = null;
}
this.unopenedURLs = unopenedURLs;
this.pathURLs = pathURLs;
}
private static Object fetchField(final Class<?> clazz, final Object object, final String name) throws NoSuchFieldException {
Field field = clazz.getDeclaredField(name);
long offset = UNSAFE.objectFieldOffset(field);
return UNSAFE.getObject(object, offset);
}
@Override
public void addURL(URL url) {
this.unopenedURLs.add(url);
this.pathURLs.add(url);
}
}
private static class Noop extends URLClassLoaderAccess {
private static final Noop INSTANCE = new Noop();
private Noop() {
super(null);
}
@Override
public void addURL(URL url) {
throw new UnsupportedOperationException();
}
}
}
@@ -30,7 +30,7 @@ public class MessageHandler {
public void addString(VpnString string, Function<VpnString, String> getter) {
string.setConfigStringGetter(getter);
getter.apply(string);
System.out.println("Added string " + string.getKey());
AntiVPN.getInstance().getExecutor().log("Added string " + string.getKey());
messages.put(string.getKey(), string);
}
@@ -1,21 +0,0 @@
/*
* Copyright (C) 2016 The Guava 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
*
* 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.
*/
package dev.brighten.antivpn.utils;
/**
* Holder for extra methods of {@code Objects} only in web. Intended to be empty for regular
* version.
*/
abstract class ExtraObjectsMethodsForWeb {}
@@ -1,6 +1,7 @@
package dev.brighten.antivpn.utils;
import java.io.*;
import java.util.concurrent.ThreadFactory;
import java.util.regex.Pattern;
public class MiscUtils {
@@ -41,6 +42,14 @@ public class MiscUtils {
}
}
public static ThreadFactory createThreadFactory(String threadName) {
return r -> {
Thread thread = new Thread(r);
thread.setName(threadName);
return thread;
};
}
public static boolean isIpv4(String ip)
{
return ipv4.matcher(ip).matches();
@@ -1,36 +0,0 @@
/*
* This file is part of helper, licensed under the MIT License.
*
* Copyright (c) lucko (Luck) <luck@lucko.me>
* Copyright (c) contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package dev.brighten.antivpn.utils;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@Documented
@Retention(RetentionPolicy.RUNTIME)
public @interface NonnullByDefault {
}
@@ -1,53 +0,0 @@
/*
* Copyright (C) 2021 The Guava 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
*
* 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.
*/
package dev.brighten.antivpn.utils;
/** A utility method to perform unchecked casts to suppress errors produced by nullness analyses. */
final class NullnessCasts {
/**
* Accepts a {@code @Nullable T} and returns a plain {@code T}, without performing any check that
* that conversion is safe.
*
* <p>This method is intended to help with usages of type parameters that have {
* ParametricNullness parametric nullness}. If a type parameter instead ranges over only non-null
* types (or if the type is a non-variable type, like {@code String}), then code should almost
* never use this method, preferring instead to call {@code requireNonNull} so as to benefit from
* its runtime check.
*
* <p>An example use case for this method is in implementing an {@code Iterator<T>} whose {@code
* next} field is lazily initialized. The type of that field would be {@code @Nullable T}, and the
* code would be responsible for populating a "real" {@code T} (which might still be the value
* {@code null}!) before returning it to callers. Depending on how the code is structured, a
* nullness analysis might not understand that the field has been populated. To avoid that problem
* without having to add {@code @SuppressWarnings}, the code can call this method.
*
* <p>Why <i>not</i> just add {@code SuppressWarnings}? The problem is that this method is
* typically useful for {@code return} statements. That leaves the code with two options: Either
* add the suppression to the whole method (which turns off checking for a large section of code),
* or extract a variable, and put the suppression on that. However, a local variable typically
* doesn't work: Because nullness analyses typically infer the nullness of local variables,
* there's no way to assign a {@code @Nullable T} to a field {@code T foo;} and instruct the
* analysis that that means "plain {@code T}" rather than the inferred type {@code @Nullable T}.
* (Even if supported added {@code @NonNull}, that would not help, since the problem case
* addressed by this method is the case in which {@code T} has parametric nullness -- and thus its
* value may be legitimately {@code null}.)
*/
@SuppressWarnings("nullness")
static <T extends Object> T uncheckedCastNullableTToT(T t) {
return t;
}
private NullnessCasts() {}
}
@@ -1,78 +0,0 @@
/*
* Copyright (C) 2007 The Guava 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
*
* 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.
*/
package dev.brighten.antivpn.utils;
import com.mongodb.lang.Nullable;
import java.util.Arrays;
/**
* Helper functions that can operate on any {@code Object}.
*
* <p>See the Guava User Guide on <a
* href="https://github.com/google/guava/wiki/CommonObjectUtilitiesExplained">writing {@code Object}
* methods with {@code Objects}</a>.
*
* @author Laurence Gonsalves
* @since 2.0
*/
public final class Objects extends ExtraObjectsMethodsForWeb {
private Objects() {}
/**
* Determines whether two possibly-null objects are equal. Returns:
*
* <ul>
* <li>{@code true} if {@code a} and {@code b} are both null.
* <li>{@code true} if {@code a} and {@code b} are both non-null and they are equal according to
* {@link Object#equals(Object)}.
* <li>{@code false} in all other situations.
* </ul>
*
* <p>This assumes that any non-null objects passed to this function conform to the {@code
* equals()} contract.
*
* <p><b>Note for Java 7 and later:</b> This method should be treated as deprecated; use {@link
* java.util.Objects#equals} instead.
*/
public static boolean equal(Object a, Object b) {
return a == b || (a != null && a.equals(b));
}
/**
* Generates a hash code for multiple values. The hash code is generated by calling {@link
* Arrays#hashCode(Object[])}. Note that array arguments to this method, with the exception of a
* single Object array, do not get any special handling; their hash codes are based on identity
* and not contents.
*
* <p>This is useful for implementing {@link Object#hashCode()}. For example, in an object that
* has three properties, {@code x}, {@code y}, and {@code z}, one could write:
*
* <pre>{@code
* public int hashCode() {
* return Objects.hashCode(getX(), getY(), getZ());
* }
* }</pre>
*
* <p><b>Warning:</b> When a single object is supplied, the returned hash code does not equal the
* hash code of that object.
*
* <p><b>Note for Java 7 and later:</b> This method should be treated as deprecated; use {@link
* java.util.Objects#hash} instead.
*/
public static int hashCode(@Nullable Object... objects) {
return Arrays.hashCode(objects);
}
}
@@ -1,602 +0,0 @@
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//
package dev.brighten.antivpn.utils;
public final class Preconditions {
private Preconditions() {
}
public static void checkArgument(boolean expression) {
if (!expression) {
throw new IllegalArgumentException();
}
}
public static void checkArgument(boolean expression, Object errorMessage) {
if (!expression) {
throw new IllegalArgumentException(String.valueOf(errorMessage));
}
}
public static void checkArgument(boolean expression, String errorMessageTemplate, Object... errorMessageArgs) {
if (!expression) {
throw new IllegalArgumentException(format(errorMessageTemplate, errorMessageArgs));
}
}
public static void checkArgument(boolean b, String errorMessageTemplate, char p1) {
if (!b) {
throw new IllegalArgumentException(format(errorMessageTemplate, p1));
}
}
public static void checkArgument(boolean b, String errorMessageTemplate, int p1) {
if (!b) {
throw new IllegalArgumentException(format(errorMessageTemplate, p1));
}
}
public static void checkArgument(boolean b, String errorMessageTemplate, long p1) {
if (!b) {
throw new IllegalArgumentException(format(errorMessageTemplate, p1));
}
}
public static void checkArgument(boolean b, String errorMessageTemplate, Object p1) {
if (!b) {
throw new IllegalArgumentException(format(errorMessageTemplate, p1));
}
}
public static void checkArgument(boolean b, String errorMessageTemplate, char p1, char p2) {
if (!b) {
throw new IllegalArgumentException(format(errorMessageTemplate, p1, p2));
}
}
public static void checkArgument(boolean b, String errorMessageTemplate, char p1, int p2) {
if (!b) {
throw new IllegalArgumentException(format(errorMessageTemplate, p1, p2));
}
}
public static void checkArgument(boolean b, String errorMessageTemplate, char p1, long p2) {
if (!b) {
throw new IllegalArgumentException(format(errorMessageTemplate, p1, p2));
}
}
public static void checkArgument(boolean b, String errorMessageTemplate, char p1, Object p2) {
if (!b) {
throw new IllegalArgumentException(format(errorMessageTemplate, p1, p2));
}
}
public static void checkArgument(boolean b, String errorMessageTemplate, int p1, char p2) {
if (!b) {
throw new IllegalArgumentException(format(errorMessageTemplate, p1, p2));
}
}
public static void checkArgument(boolean b, String errorMessageTemplate, int p1, int p2) {
if (!b) {
throw new IllegalArgumentException(format(errorMessageTemplate, p1, p2));
}
}
public static void checkArgument(boolean b, String errorMessageTemplate, int p1, long p2) {
if (!b) {
throw new IllegalArgumentException(format(errorMessageTemplate, p1, p2));
}
}
public static void checkArgument(boolean b, String errorMessageTemplate, int p1, Object p2) {
if (!b) {
throw new IllegalArgumentException(format(errorMessageTemplate, p1, p2));
}
}
public static void checkArgument(boolean b, String errorMessageTemplate, long p1, char p2) {
if (!b) {
throw new IllegalArgumentException(format(errorMessageTemplate, p1, p2));
}
}
public static void checkArgument(boolean b, String errorMessageTemplate, long p1, int p2) {
if (!b) {
throw new IllegalArgumentException(format(errorMessageTemplate, p1, p2));
}
}
public static void checkArgument(boolean b, String errorMessageTemplate, long p1, long p2) {
if (!b) {
throw new IllegalArgumentException(format(errorMessageTemplate, p1, p2));
}
}
public static void checkArgument(boolean b, String errorMessageTemplate, long p1, Object p2) {
if (!b) {
throw new IllegalArgumentException(format(errorMessageTemplate, p1, p2));
}
}
public static void checkArgument(boolean b, String errorMessageTemplate, Object p1, char p2) {
if (!b) {
throw new IllegalArgumentException(format(errorMessageTemplate, p1, p2));
}
}
public static void checkArgument(boolean b, String errorMessageTemplate, Object p1, int p2) {
if (!b) {
throw new IllegalArgumentException(format(errorMessageTemplate, p1, p2));
}
}
public static void checkArgument(boolean b, String errorMessageTemplate, Object p1, long p2) {
if (!b) {
throw new IllegalArgumentException(format(errorMessageTemplate, p1, p2));
}
}
public static void checkArgument(boolean b, String errorMessageTemplate, Object p1, Object p2) {
if (!b) {
throw new IllegalArgumentException(format(errorMessageTemplate, p1, p2));
}
}
public static void checkArgument(boolean b, String errorMessageTemplate, Object p1, Object p2, Object p3) {
if (!b) {
throw new IllegalArgumentException(format(errorMessageTemplate, p1, p2, p3));
}
}
public static void checkArgument(boolean b, String errorMessageTemplate, Object p1, Object p2, Object p3, Object p4) {
if (!b) {
throw new IllegalArgumentException(format(errorMessageTemplate, p1, p2, p3, p4));
}
}
public static void checkState(boolean expression) {
if (!expression) {
throw new IllegalStateException();
}
}
public static void checkState(boolean expression, Object errorMessage) {
if (!expression) {
throw new IllegalStateException(String.valueOf(errorMessage));
}
}
public static void checkState(boolean expression, String errorMessageTemplate, Object... errorMessageArgs) {
if (!expression) {
throw new IllegalStateException(format(errorMessageTemplate, errorMessageArgs));
}
}
public static void checkState(boolean b, String errorMessageTemplate, char p1) {
if (!b) {
throw new IllegalStateException(format(errorMessageTemplate, p1));
}
}
public static void checkState(boolean b, String errorMessageTemplate, int p1) {
if (!b) {
throw new IllegalStateException(format(errorMessageTemplate, p1));
}
}
public static void checkState(boolean b, String errorMessageTemplate, long p1) {
if (!b) {
throw new IllegalStateException(format(errorMessageTemplate, p1));
}
}
public static void checkState(boolean b, String errorMessageTemplate, Object p1) {
if (!b) {
throw new IllegalStateException(format(errorMessageTemplate, p1));
}
}
public static void checkState(boolean b, String errorMessageTemplate, char p1, char p2) {
if (!b) {
throw new IllegalStateException(format(errorMessageTemplate, p1, p2));
}
}
public static void checkState(boolean b, String errorMessageTemplate, char p1, int p2) {
if (!b) {
throw new IllegalStateException(format(errorMessageTemplate, p1, p2));
}
}
public static void checkState(boolean b, String errorMessageTemplate, char p1, long p2) {
if (!b) {
throw new IllegalStateException(format(errorMessageTemplate, p1, p2));
}
}
public static void checkState(boolean b, String errorMessageTemplate, char p1, Object p2) {
if (!b) {
throw new IllegalStateException(format(errorMessageTemplate, p1, p2));
}
}
public static void checkState(boolean b, String errorMessageTemplate, int p1, char p2) {
if (!b) {
throw new IllegalStateException(format(errorMessageTemplate, p1, p2));
}
}
public static void checkState(boolean b, String errorMessageTemplate, int p1, int p2) {
if (!b) {
throw new IllegalStateException(format(errorMessageTemplate, p1, p2));
}
}
public static void checkState(boolean b, String errorMessageTemplate, int p1, long p2) {
if (!b) {
throw new IllegalStateException(format(errorMessageTemplate, p1, p2));
}
}
public static void checkState(boolean b, String errorMessageTemplate, int p1, Object p2) {
if (!b) {
throw new IllegalStateException(format(errorMessageTemplate, p1, p2));
}
}
public static void checkState(boolean b, String errorMessageTemplate, long p1, char p2) {
if (!b) {
throw new IllegalStateException(format(errorMessageTemplate, p1, p2));
}
}
public static void checkState(boolean b, String errorMessageTemplate, long p1, int p2) {
if (!b) {
throw new IllegalStateException(format(errorMessageTemplate, p1, p2));
}
}
public static void checkState(boolean b, String errorMessageTemplate, long p1, long p2) {
if (!b) {
throw new IllegalStateException(format(errorMessageTemplate, p1, p2));
}
}
public static void checkState(boolean b, String errorMessageTemplate, long p1, Object p2) {
if (!b) {
throw new IllegalStateException(format(errorMessageTemplate, p1, p2));
}
}
public static void checkState(boolean b, String errorMessageTemplate, Object p1, char p2) {
if (!b) {
throw new IllegalStateException(format(errorMessageTemplate, p1, p2));
}
}
public static void checkState(boolean b, String errorMessageTemplate, Object p1, int p2) {
if (!b) {
throw new IllegalStateException(format(errorMessageTemplate, p1, p2));
}
}
public static void checkState(boolean b, String errorMessageTemplate, Object p1, long p2) {
if (!b) {
throw new IllegalStateException(format(errorMessageTemplate, p1, p2));
}
}
public static void checkState(boolean b, String errorMessageTemplate, Object p1, Object p2) {
if (!b) {
throw new IllegalStateException(format(errorMessageTemplate, p1, p2));
}
}
public static void checkState(boolean b, String errorMessageTemplate, Object p1, Object p2, Object p3) {
if (!b) {
throw new IllegalStateException(format(errorMessageTemplate, p1, p2, p3));
}
}
public static void checkState(boolean b, String errorMessageTemplate, Object p1, Object p2, Object p3, Object p4) {
if (!b) {
throw new IllegalStateException(format(errorMessageTemplate, p1, p2, p3, p4));
}
}
public static <T> T checkNotNull(T reference) {
if (reference == null) {
throw new NullPointerException();
} else {
return reference;
}
}
public static <T> T checkNotNull(T reference, Object errorMessage) {
if (reference == null) {
throw new NullPointerException(String.valueOf(errorMessage));
} else {
return reference;
}
}
public static <T> T checkNotNull(T reference, String errorMessageTemplate, Object... errorMessageArgs) {
if (reference == null) {
throw new NullPointerException(format(errorMessageTemplate, errorMessageArgs));
} else {
return reference;
}
}
public static <T> T checkNotNull(T obj, String errorMessageTemplate, char p1) {
if (obj == null) {
throw new NullPointerException(format(errorMessageTemplate, p1));
} else {
return obj;
}
}
public static <T> T checkNotNull(T obj, String errorMessageTemplate, int p1) {
if (obj == null) {
throw new NullPointerException(format(errorMessageTemplate, p1));
} else {
return obj;
}
}
public static <T> T checkNotNull(T obj, String errorMessageTemplate, long p1) {
if (obj == null) {
throw new NullPointerException(format(errorMessageTemplate, p1));
} else {
return obj;
}
}
public static <T> T checkNotNull(T obj, String errorMessageTemplate, Object p1) {
if (obj == null) {
throw new NullPointerException(format(errorMessageTemplate, p1));
} else {
return obj;
}
}
public static <T> T checkNotNull(T obj, String errorMessageTemplate, char p1, char p2) {
if (obj == null) {
throw new NullPointerException(format(errorMessageTemplate, p1, p2));
} else {
return obj;
}
}
public static <T> T checkNotNull(T obj, String errorMessageTemplate, char p1, int p2) {
if (obj == null) {
throw new NullPointerException(format(errorMessageTemplate, p1, p2));
} else {
return obj;
}
}
public static <T> T checkNotNull(T obj, String errorMessageTemplate, char p1, long p2) {
if (obj == null) {
throw new NullPointerException(format(errorMessageTemplate, p1, p2));
} else {
return obj;
}
}
public static <T> T checkNotNull(T obj, String errorMessageTemplate, char p1, Object p2) {
if (obj == null) {
throw new NullPointerException(format(errorMessageTemplate, p1, p2));
} else {
return obj;
}
}
public static <T> T checkNotNull(T obj, String errorMessageTemplate, int p1, char p2) {
if (obj == null) {
throw new NullPointerException(format(errorMessageTemplate, p1, p2));
} else {
return obj;
}
}
public static <T> T checkNotNull(T obj, String errorMessageTemplate, int p1, int p2) {
if (obj == null) {
throw new NullPointerException(format(errorMessageTemplate, p1, p2));
} else {
return obj;
}
}
public static <T> T checkNotNull(T obj, String errorMessageTemplate, int p1, long p2) {
if (obj == null) {
throw new NullPointerException(format(errorMessageTemplate, p1, p2));
} else {
return obj;
}
}
public static <T> T checkNotNull(T obj, String errorMessageTemplate, int p1, Object p2) {
if (obj == null) {
throw new NullPointerException(format(errorMessageTemplate, p1, p2));
} else {
return obj;
}
}
public static <T> T checkNotNull(T obj, String errorMessageTemplate, long p1, char p2) {
if (obj == null) {
throw new NullPointerException(format(errorMessageTemplate, p1, p2));
} else {
return obj;
}
}
public static <T> T checkNotNull(T obj, String errorMessageTemplate, long p1, int p2) {
if (obj == null) {
throw new NullPointerException(format(errorMessageTemplate, p1, p2));
} else {
return obj;
}
}
public static <T> T checkNotNull(T obj, String errorMessageTemplate, long p1, long p2) {
if (obj == null) {
throw new NullPointerException(format(errorMessageTemplate, p1, p2));
} else {
return obj;
}
}
public static <T> T checkNotNull(T obj, String errorMessageTemplate, long p1, Object p2) {
if (obj == null) {
throw new NullPointerException(format(errorMessageTemplate, p1, p2));
} else {
return obj;
}
}
public static <T> T checkNotNull(T obj, String errorMessageTemplate, Object p1, char p2) {
if (obj == null) {
throw new NullPointerException(format(errorMessageTemplate, p1, p2));
} else {
return obj;
}
}
public static <T> T checkNotNull(T obj, String errorMessageTemplate, Object p1, int p2) {
if (obj == null) {
throw new NullPointerException(format(errorMessageTemplate, p1, p2));
} else {
return obj;
}
}
public static <T> T checkNotNull(T obj, String errorMessageTemplate, Object p1, long p2) {
if (obj == null) {
throw new NullPointerException(format(errorMessageTemplate, p1, p2));
} else {
return obj;
}
}
public static <T> T checkNotNull(T obj, String errorMessageTemplate, Object p1, Object p2) {
if (obj == null) {
throw new NullPointerException(format(errorMessageTemplate, p1, p2));
} else {
return obj;
}
}
public static <T> T checkNotNull(T obj, String errorMessageTemplate, Object p1, Object p2, Object p3) {
if (obj == null) {
throw new NullPointerException(format(errorMessageTemplate, p1, p2, p3));
} else {
return obj;
}
}
public static <T> T checkNotNull(T obj, String errorMessageTemplate, Object p1, Object p2, Object p3, Object p4) {
if (obj == null) {
throw new NullPointerException(format(errorMessageTemplate, p1, p2, p3, p4));
} else {
return obj;
}
}
public static int checkElementIndex(int index, int size) {
return checkElementIndex(index, size, "index");
}
public static int checkElementIndex(int index, int size, String desc) {
if (index >= 0 && index < size) {
return index;
} else {
throw new IndexOutOfBoundsException(badElementIndex(index, size, desc));
}
}
private static String badElementIndex(int index, int size, String desc) {
if (index < 0) {
return format("%s (%s) must not be negative", desc, index);
} else if (size < 0) {
throw new IllegalArgumentException("negative size: " + size);
} else {
return format("%s (%s) must be less than size (%s)", desc, index, size);
}
}
public static int checkPositionIndex(int index, int size) {
return checkPositionIndex(index, size, "index");
}
public static int checkPositionIndex(int index, int size, String desc) {
if (index >= 0 && index <= size) {
return index;
} else {
throw new IndexOutOfBoundsException(badPositionIndex(index, size, desc));
}
}
private static String badPositionIndex(int index, int size, String desc) {
if (index < 0) {
return format("%s (%s) must not be negative", desc, index);
} else if (size < 0) {
throw new IllegalArgumentException("negative size: " + size);
} else {
return format("%s (%s) must not be greater than size (%s)", desc, index, size);
}
}
public static void checkPositionIndexes(int start, int end, int size) {
if (start < 0 || end < start || end > size) {
throw new IndexOutOfBoundsException(badPositionIndexes(start, end, size));
}
}
private static String badPositionIndexes(int start, int end, int size) {
if (start >= 0 && start <= size) {
return end >= 0 && end <= size ? format("end index (%s) must not be less than start index (%s)", end, start) : badPositionIndex(end, size, "end index");
} else {
return badPositionIndex(start, size, "start index");
}
}
static String format(String template, Object... args) {
template = String.valueOf(template);
StringBuilder builder = new StringBuilder(template.length() + 16 * args.length);
int templateStart = 0;
int i;
int placeholderStart;
for(i = 0; i < args.length; templateStart = placeholderStart + 2) {
placeholderStart = template.indexOf("%s", templateStart);
if (placeholderStart == -1) {
break;
}
builder.append(template, templateStart, placeholderStart);
builder.append(args[i++]);
}
builder.append(template, templateStart, template.length());
if (i < args.length) {
builder.append(" [");
builder.append(args[i++]);
while(i < args.length) {
builder.append(", ");
builder.append(args[i++]);
}
builder.append(']');
}
return builder.toString();
}
}
@@ -1,11 +0,0 @@
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//
package dev.brighten.antivpn.utils;
@FunctionalInterface
public interface Supplier<T> extends java.util.function.Supplier<T> {
T get();
}
@@ -1,380 +0,0 @@
/*
* Copyright (C) 2007 The Guava 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
*
* 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.
*/
package dev.brighten.antivpn.utils;
import static java.util.Objects.requireNonNull;
import java.io.Serializable;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;
import static dev.brighten.antivpn.utils.Preconditions.checkArgument;
import static dev.brighten.antivpn.utils.Preconditions.checkNotNull;
import static dev.brighten.antivpn.utils.NullnessCasts.uncheckedCastNullableTToT;
import static java.util.Objects.requireNonNull;
import jdk.tools.jlink.internal.Platform;
/**
* Useful suppliers.
*
* <p>All methods return serializable suppliers as long as they're given serializable parameters.
*
* @author Laurence Gonsalves
* @author Harry Heymann
* @since 2.0
*/
public final class Suppliers {
private Suppliers() {}
/**
* Returns a new supplier which is the composition of the provided function and supplier. In other
* words, the new supplier's value will be computed by retrieving the value from {@code supplier},
* and then applying {@code function} to that value. Note that the resulting supplier will not
* call {@code supplier} or invoke {@code function} until it is called.
*/
public static <F extends Object, T extends Object> Supplier<T> compose(
Function<? super F, T> function, Supplier<F> supplier) {
return new SupplierComposition<>(function, supplier);
}
private static class SupplierComposition<F extends Object, T extends Object>
implements Supplier<T>, Serializable {
final Function<? super F, T> function;
final Supplier<F> supplier;
SupplierComposition(Function<? super F, T> function, Supplier<F> supplier) {
this.function = checkNotNull(function);
this.supplier = checkNotNull(supplier);
}
@Override
public T get() {
return function.apply(supplier.get());
}
@Override
public boolean equals(Object obj) {
if (obj instanceof SupplierComposition) {
SupplierComposition<?, ?> that = (SupplierComposition<?, ?>) obj;
return function.equals(that.function) && supplier.equals(that.supplier);
}
return false;
}
@Override
public int hashCode() {
return Objects.hashCode(function, supplier);
}
@Override
public String toString() {
return "Suppliers.compose(" + function + ", " + supplier + ")";
}
private static final long serialVersionUID = 0;
}
/**
* Returns a supplier which caches the instance retrieved during the first call to {@code get()}
* and returns that value on subsequent calls to {@code get()}. See: <a
* href="http://en.wikipedia.org/wiki/Memoization">memoization</a>
*
* <p>The returned supplier is thread-safe. The delegate's {@code get()} method will be invoked at
* most once unless the underlying {@code get()} throws an exception. The supplier's serialized
* form does not contain the cached value, which will be recalculated when {@code get()} is called
* on the reserialized instance.
*
* <p>When the underlying delegate throws an exception then this memoizing supplier will keep
* delegating calls until it returns valid data.
*
* <p>If {@code delegate} is an instance created by an earlier call to {@code memoize}, it is
* returned directly.
*/
public static <T extends Object> Supplier<T> memoize(Supplier<T> delegate) {
if (delegate instanceof NonSerializableMemoizingSupplier
|| delegate instanceof MemoizingSupplier) {
return delegate;
}
return delegate instanceof Serializable
? new MemoizingSupplier<T>(delegate)
: new NonSerializableMemoizingSupplier<T>(delegate);
}
static class MemoizingSupplier<T extends Object> implements Supplier<T>, Serializable {
final Supplier<T> delegate;
transient volatile boolean initialized;
// "value" does not need to be volatile; visibility piggy-backs
// on volatile read of "initialized".
transient T value;
MemoizingSupplier(Supplier<T> delegate) {
this.delegate = checkNotNull(delegate);
}
@Override
public T get() {
// A 2-field variant of Double Checked Locking.
if (!initialized) {
synchronized (this) {
if (!initialized) {
T t = delegate.get();
value = t;
initialized = true;
return t;
}
}
}
// This is safe because we checked `initialized.`
return uncheckedCastNullableTToT(value);
}
@Override
public String toString() {
return "Suppliers.memoize("
+ (initialized ? "<supplier that returned " + value + ">" : delegate)
+ ")";
}
private static final long serialVersionUID = 0;
}
static class NonSerializableMemoizingSupplier<T extends Object> implements Supplier<T> {
volatile Supplier<T> delegate;
volatile boolean initialized;
// "value" does not need to be volatile; visibility piggy-backs
// on volatile read of "initialized".
T value;
NonSerializableMemoizingSupplier(Supplier<T> delegate) {
this.delegate = checkNotNull(delegate);
}
@Override
public T get() {
// A 2-field variant of Double Checked Locking.
if (!initialized) {
synchronized (this) {
if (!initialized) {
/*
* requireNonNull is safe because we read and write `delegate` under synchronization.
*
* TODO(cpovirk): To avoid having to check for null, replace `delegate` with a singleton
* `Supplier` that always throws an exception.
*/
T t = requireNonNull(delegate).get();
value = t;
initialized = true;
// Release the delegate to GC.
delegate = null;
return t;
}
}
}
// This is safe because we checked `initialized.`
return uncheckedCastNullableTToT(value);
}
@Override
public String toString() {
Supplier<T> delegate = this.delegate;
return "Suppliers.memoize("
+ (delegate == null ? "<supplier that returned " + value + ">" : delegate)
+ ")";
}
}
/**
* Returns a supplier that caches the instance supplied by the delegate and removes the cached
* value after the specified time has passed. Subsequent calls to {@code get()} return the cached
* value if the expiration time has not passed. After the expiration time, a new value is
* retrieved, cached, and returned. See: <a
* href="http://en.wikipedia.org/wiki/Memoization">memoization</a>
*
* <p>The returned supplier is thread-safe. The supplier's serialized form does not contain the
* cached value, which will be recalculated when {@code get()} is called on the reserialized
* instance. The actual memoization does not happen when the underlying delegate throws an
* exception.
*
* <p>When the underlying delegate throws an exception then this memoizing supplier will keep
* delegating calls until it returns valid data.
*
* @param duration the length of time after a value is created that it should stop being returned
* by subsequent {@code get()} calls
* @param unit the unit that {@code duration} is expressed in
* @throws IllegalArgumentException if {@code duration} is not positive
* @since 2.0
*/
@SuppressWarnings("GoodTime") // should accept a java.time.Duration
public static <T extends Object> Supplier<T> memoizeWithExpiration(
Supplier<T> delegate, long duration, TimeUnit unit) {
return new ExpiringMemoizingSupplier<>(delegate, duration, unit);
}
@SuppressWarnings("GoodTime") // lots of violations
static class ExpiringMemoizingSupplier<T extends Object>
implements Supplier<T>, Serializable {
final Supplier<T> delegate;
final long durationNanos;
transient volatile T value;
// The special value 0 means "not yet initialized".
transient volatile long expirationNanos;
ExpiringMemoizingSupplier(Supplier<T> delegate, long duration, TimeUnit unit) {
this.delegate = checkNotNull(delegate);
this.durationNanos = unit.toNanos(duration);
checkArgument(duration > 0, "duration (%s %s) must be > 0", duration, unit);
}
@Override
public T get() {
// Another variant of Double Checked Locking.
//
// We use two volatile reads. We could reduce this to one by
// putting our fields into a holder class, but (at least on x86)
// the extra memory consumption and indirection are more
// expensive than the extra volatile reads.
long nanos = expirationNanos;
long now = System.nanoTime();
if (nanos == 0 || now - nanos >= 0) {
synchronized (this) {
if (nanos == expirationNanos) { // recheck for lost race
T t = delegate.get();
value = t;
nanos = now + durationNanos;
// In the very unlikely event that nanos is 0, set it to 1;
// no one will notice 1 ns of tardiness.
expirationNanos = (nanos == 0) ? 1 : nanos;
return t;
}
}
}
// This is safe because we checked `expirationNanos.`
return uncheckedCastNullableTToT(value);
}
@Override
public String toString() {
// This is a little strange if the unit the user provided was not NANOS,
// but we don't want to store the unit just for toString
return "Suppliers.memoizeWithExpiration(" + delegate + ", " + durationNanos + ", NANOS)";
}
private static final long serialVersionUID = 0;
}
/** Returns a supplier that always supplies {@code instance}. */
public static <T extends Object> Supplier<T> ofInstance(
T instance) {
return new SupplierOfInstance<>(instance);
}
private static class SupplierOfInstance<T extends Object>
implements Supplier<T>, Serializable {
final T instance;
SupplierOfInstance(T instance) {
this.instance = instance;
}
@Override
public T get() {
return instance;
}
@Override
public boolean equals(Object obj) {
if (obj instanceof SupplierOfInstance) {
SupplierOfInstance<?> that = (SupplierOfInstance<?>) obj;
return Objects.equal(instance, that.instance);
}
return false;
}
@Override
public int hashCode() {
return Objects.hashCode(instance);
}
@Override
public String toString() {
return "Suppliers.ofInstance(" + instance + ")";
}
private static final long serialVersionUID = 0;
}
/**
* Returns a supplier whose {@code get()} method synchronizes on {@code delegate} before calling
* it, making it thread-safe.
*/
public static <T extends Object> Supplier<T> synchronizedSupplier(
Supplier<T> delegate) {
return new ThreadSafeSupplier<>(delegate);
}
private static class ThreadSafeSupplier<T extends Object>
implements Supplier<T>, Serializable {
final Supplier<T> delegate;
ThreadSafeSupplier(Supplier<T> delegate) {
this.delegate = checkNotNull(delegate);
}
@Override
public T get() {
synchronized (delegate) {
return delegate.get();
}
}
@Override
public String toString() {
return "Suppliers.synchronizedSupplier(" + delegate + ")";
}
private static final long serialVersionUID = 0;
}
/**
* Returns a function that accepts a supplier and returns the result of invoking {@link
* Supplier#get} on that supplier.
*
* <p><b>Java 8 users:</b> use the method reference {@code Supplier::get} instead.
*
* @since 8.0
*/
public static <T extends Object> Function<Supplier<T>, T> supplierFunction() {
@SuppressWarnings("unchecked") // implementation is "fully variant"
SupplierFunction<T> sf = (SupplierFunction<T>) SupplierFunctionImpl.INSTANCE;
return sf;
}
private interface SupplierFunction<T extends Object> extends Function<Supplier<T>, T> {}
private enum SupplierFunctionImpl implements SupplierFunction<Object> {
INSTANCE;
// Note: This makes T a "pass-through type"
@Override
public Object apply(Supplier<Object> input) {
return input.get();
}
@Override
public String toString() {
return "Suppliers.supplierFunction()";
}
}
}
@@ -23,17 +23,17 @@ public class YamlConfiguration extends ConfigurationProvider
@Override
protected Yaml initialValue()
{
Representer representer = new Representer()
DumperOptions options = new DumperOptions();
options.setDefaultFlowStyle( DumperOptions.FlowStyle.BLOCK );
Representer representer = new Representer(options)
{
{
representers.put( Configuration.class, data -> represent( ( (Configuration) data ).self ));
}
};
DumperOptions options = new DumperOptions();
options.setDefaultFlowStyle( DumperOptions.FlowStyle.BLOCK );
representer.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK);
return new Yaml( new Constructor(), representer, options );
return new Yaml( new Constructor(new LoaderOptions()), representer, options );
}
};
@@ -1,10 +1,10 @@
package dev.brighten.antivpn.web;
import dev.brighten.antivpn.web.objects.QueryResponse;
import dev.brighten.antivpn.web.objects.VPNResponse;
import dev.brighten.antivpn.utils.json.JSONException;
import dev.brighten.antivpn.utils.json.JSONObject;
import dev.brighten.antivpn.utils.json.JsonReader;
import dev.brighten.antivpn.web.objects.QueryResponse;
import dev.brighten.antivpn.web.objects.VPNResponse;
import java.io.IOException;
@@ -2,7 +2,9 @@ package dev.brighten.antivpn.web.objects;
import dev.brighten.antivpn.utils.json.JSONException;
import dev.brighten.antivpn.utils.json.JSONObject;
import lombok.*;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
@Data
@AllArgsConstructor
@@ -39,14 +41,18 @@ public class VPNResponse {
*
* @param json String
* @return VPNResponse
* @throws JSONException
*/
public static VPNResponse fromJson(String json) throws JSONException {
return fromJson(new JSONObject(json));
}
public static final VPNResponse FAILED_RESPONSE = VPNResponse.builder()
.success(false)
.failureReason("Internal plugin API error.")
.build();
/**
* Formats response from https://funkemunky.cc/vpn into {@link VPNResponse} for project use.
* Formats response from <a href="https://funkemunky.cc/vpn">...</a> into {@link VPNResponse} for project use.
*
* @param jsonObject JSONObject
* @return VPNResponse
+3 -3
View File
@@ -15,8 +15,8 @@ prefixWhitelists: []
# Configure your database here.
database:
# Enable to cache queries and save alerts state beyond restarts
enabled: false
useCredentials: true
enabled: true
useCredentials: false
#Options Mongo, MySQL, or H2
type: H2
# The database name you would like to use
@@ -50,7 +50,7 @@ alerts:
&7in location &8(&f%city%&7, &f%country%&8)'
# Configuration for country gatekeepings
countries:
# You must use ISO codes for country configuration: https://www.iban.com/country-code
# You must use ISO codes for country configuration: https://www.iban.com/country-codes
# Leave empty to disable this configuration
list: []
# Set whitelist to true to only allow listed country codes, and false to deny listed country codes.
+2
View File
@@ -1,3 +1,5 @@
[![Project Map](https://sourcespy.com/shield.svg)](https://sourcespy.com/github/funkemunkyantivpn/)
# AntiVPN
An antivpn plugin utilizing the KauriVPN API
+41
View File
@@ -0,0 +1,41 @@
<?xml version="1.0" encoding="UTF-8"?>
<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.9.3.1</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>Sponge</artifactId>
<repositories>
<repository>
<id>sponge</id>
<url>https://repo.spongepowered.org/repository/maven-public/</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>org.spongepowered</groupId>
<artifactId>spongeapi</artifactId>
<version>8.1.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>dev.brighten.antivpn</groupId>
<artifactId>Common</artifactId>
<version>1.9.3.1</version>
<scope>provided</scope>
</dependency>
</dependencies>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
</project>
@@ -0,0 +1,31 @@
package dev.brighten.antivpn.sponge;
import dev.brighten.antivpn.api.APIPlayer;
import dev.brighten.antivpn.sponge.util.StringUtil;
import net.kyori.adventure.text.Component;
import org.spongepowered.api.entity.living.player.server.ServerPlayer;
public class SpongePlayer extends APIPlayer {
private final ServerPlayer player;
public SpongePlayer(ServerPlayer player) {
super(player.uniqueId(), player.name(), player.connection().address().getAddress());
this.player = player;
}
@Override
public void sendMessage(String message) {
//player.sendMessage(StringUtil.translateColorCodes('&', message));
}
@Override
public void kickPlayer(String reason) {
player.kick(Component.text(StringUtil.translateColorCodes('&', reason)));
}
@Override
public boolean hasPermission(String permission) {
return player.hasPermission(permission);
}
}
@@ -0,0 +1,31 @@
package dev.brighten.antivpn.sponge;
import dev.brighten.antivpn.api.APIPlayer;
import dev.brighten.antivpn.api.PlayerExecutor;
import java.util.List;
import java.util.Optional;
import java.util.UUID;
public class SpongePlayerExecutor implements PlayerExecutor {
@Override
public Optional<APIPlayer> getPlayer(String name) {
return Optional.empty();
}
@Override
public Optional<APIPlayer> getPlayer(UUID uuid) {
return Optional.empty();
}
@Override
public void unloadPlayer(UUID uuid) {
}
@Override
public List<APIPlayer> getOnlinePlayers() {
return null;
}
}
@@ -0,0 +1,28 @@
package dev.brighten.antivpn.sponge;
import com.google.inject.Inject;
import org.spongepowered.api.Server;
import org.spongepowered.api.event.Listener;
import org.spongepowered.api.event.lifecycle.StartedEngineEvent;
import org.spongepowered.plugin.builtin.jvm.Plugin;
import java.util.logging.Logger;
@Plugin("kaurivpn")
public class SpongePlugin {
public static SpongePlugin INSTANCE;
//Plugin init
@Inject
private Logger logger;
@Listener
public void onServerStart(final StartedEngineEvent<Server> event) {
INSTANCE = this;
logger.info("Starting AntiVPN services...");
//Start AntiVPN
}
}
@@ -0,0 +1,17 @@
package dev.brighten.antivpn.sponge.util;
public class StringUtil {
public static String translateColorCodes(char altColorChar, String textToTranslate) {
char[] b = textToTranslate.toCharArray();
for(int i = 0; i < b.length - 1; ++i) {
if (b[i] == altColorChar && "0123456789AaBbCcDdEeFfKkLlMmNnOoRr".indexOf(b[i + 1]) > -1) {
b[i] = 167;
b[i + 1] = Character.toLowerCase(b[i + 1]);
}
}
return new String(b);
}
}
+9 -5
View File
@@ -5,7 +5,7 @@
<parent>
<artifactId>AntiVPN</artifactId>
<groupId>dev.brighten.antivpn</groupId>
<version>1.8.2</version>
<version>1.9.3.1</version>
</parent>
<modelVersion>4.0.0</modelVersion>
@@ -27,13 +27,13 @@
<dependency>
<groupId>com.velocitypowered</groupId>
<artifactId>velocity-api</artifactId>
<version>3.0.1</version>
<version>3.1.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>dev.brighten.antivpn</groupId>
<artifactId>Common</artifactId>
<version>1.8.2</version>
<version>1.9.3.1</version>
<scope>provided</scope>
</dependency>
<dependency>
@@ -49,7 +49,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.7.0</version>
<version>3.13.0</version>
<configuration>
<source>8</source>
<target>8</target>
@@ -59,7 +59,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.1.0</version>
<version>3.5.2</version>
<configuration>
<relocations>
<relocation>
@@ -67,6 +67,10 @@
<!-- 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>
@@ -1,5 +1,8 @@
package dev.brighten.antivpn.velocity;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import com.velocitypowered.api.event.ResultedEvent;
import com.velocitypowered.api.event.connection.DisconnectEvent;
import com.velocitypowered.api.event.connection.LoginEvent;
import com.velocitypowered.api.scheduler.ScheduledTask;
@@ -7,14 +10,22 @@ import dev.brighten.antivpn.AntiVPN;
import dev.brighten.antivpn.api.APIPlayer;
import dev.brighten.antivpn.api.VPNExecutor;
import dev.brighten.antivpn.velocity.util.StringUtils;
import dev.brighten.antivpn.web.objects.VPNResponse;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
public class VelocityListener extends VPNExecutor {
private ScheduledTask cacheResetTask;
private final Cache<UUID, VPNResponse> responseCache = CacheBuilder.newBuilder()
.expireAfterWrite(5, TimeUnit.MINUTES)
.maximumSize(2000)
.build();
@Override
public void registerListeners() {
@@ -36,12 +47,21 @@ public class VelocityListener extends VPNExecutor {
|| AntiVPN.getInstance().getVpnConfig().getPrefixWhitelists().stream()
.anyMatch(prefix -> event.getPlayer().getUsername().startsWith(prefix))) return;
if(responseCache.asMap().containsKey(event.getPlayer().getUniqueId())) {
VPNResponse cached = responseCache.getIfPresent(event.getPlayer().getUniqueId());
if (cached != null && cached.isProxy()) {
event.setResult(ResultedEvent.ComponentResult.denied(Component.text("No")));
return;
}
}
checkIp(event.getPlayer().getRemoteAddress().getAddress().getHostAddress(),
AntiVPN.getInstance().getVpnConfig().cachedResults(), result -> {
if (result.isSuccess()) {
// If the countryList() size is zero, no need to check.
// Running country check first
if (AntiVPN.getInstance().getVpnConfig().countryList().size() > 0
if (!AntiVPN.getInstance().getVpnConfig().countryList().isEmpty()
&& !(AntiVPN.getInstance().getExecutor()
.isWhitelisted(event.getPlayer().getUniqueId()) //Is exempt
//Or has a name that starts with a certain prefix. This is for Bedrock exempting.
@@ -55,15 +75,24 @@ public class VelocityListener extends VPNExecutor {
.contains(result.getCountryCode())
!= AntiVPN.getInstance().getVpnConfig().whitelistCountries()) {
//Using our built in kicking system if no commands are configured
if (AntiVPN.getInstance().getVpnConfig().countryKickCommands().size() == 0) {
if (AntiVPN.getInstance().getVpnConfig().countryKickCommands().isEmpty()) {
final String kickReason = AntiVPN.getInstance().getVpnConfig()
.countryVanillaKickReason();
// Kicking our player
event.getPlayer().disconnect(LegacyComponentSerializer.builder().character('&')
event.setResult(ResultedEvent.ComponentResult.denied(LegacyComponentSerializer.builder()
.character('&')
.build().deserialize(kickReason
.replace("%player%", event.getPlayer().getUsername())
.replace("%country%", result.getCountryName())
.replace("%code%", result.getCountryCode())));
.replace("%code%", result.getCountryCode()))));
VelocityPlugin.INSTANCE.getServer().getScheduler()
.buildTask(VelocityPlugin.INSTANCE, () ->
event.getPlayer().disconnect(LegacyComponentSerializer.builder()
.character('&')
.build().deserialize(kickReason
.replace("%player%", event.getPlayer().getUsername())
.replace("%country%", result.getCountryName())
.replace("%code%", result.getCountryCode()))));
} else {
for (String cmd : AntiVPN.getInstance().getVpnConfig().countryKickCommands()) {
final String formattedCommand = StringUtils
@@ -81,10 +110,27 @@ public class VelocityListener extends VPNExecutor {
}
}
} else if (result.isProxy()) {
if (AntiVPN.getInstance().getVpnConfig().kickPlayersOnDetect())
event.getPlayer().disconnect(LegacyComponentSerializer.builder().character('&')
if (AntiVPN.getInstance().getVpnConfig().kickPlayersOnDetect()) {
// Delay code execution
event.setResult(ResultedEvent.ComponentResult.denied(LegacyComponentSerializer.builder()
.character('&')
.build().deserialize(AntiVPN.getInstance().getVpnConfig()
.getKickString()));
.getKickString()
.replace("%player%", event.getPlayer().getUsername())
.replace("%country%", result.getCountryName())
.replace("%code%", result.getCountryCode()))));
VelocityPlugin.INSTANCE.getServer().getScheduler()
.buildTask(VelocityPlugin.INSTANCE, () ->
event.getPlayer().disconnect(LegacyComponentSerializer.builder()
.character('&')
.build().deserialize(AntiVPN.getInstance().getVpnConfig()
.getKickString()
.replace("%player%", event.getPlayer().getUsername())
.replace("%country%", result.getCountryName())
.replace("%code%", result.getCountryCode()))))
.delay(1, TimeUnit.SECONDS).schedule();
}
VelocityPlugin.INSTANCE.getLogger().info(event.getPlayer().getUsername()
+ " joined on a VPN/Proxy (" + result.getMethod() + ")");
//Ensuring the user wishes to alert to staff
@@ -130,14 +176,6 @@ public class VelocityListener extends VPNExecutor {
});
}
@Override
public void runCacheReset() {
cacheResetTask = VelocityPlugin.INSTANCE.getServer().getScheduler()
.buildTask(VelocityPlugin.INSTANCE, this::resetCache)
.repeat(20, TimeUnit.MINUTES)
.schedule();
}
@Override
public void shutdown() {
if (cacheResetTask != null) {
@@ -148,8 +186,18 @@ public class VelocityListener extends VPNExecutor {
VelocityPlugin.INSTANCE.getServer().getEventManager().unregisterListener(VelocityPlugin.INSTANCE, this);
}
@Override
public void log(Level level, String log, Object... objects) {
VelocityPlugin.INSTANCE.getLogger().log(level, String.format(log, objects));
}
@Override
public void log(String log, Object... objects) {
VelocityPlugin.INSTANCE.getLogger().log(Level.INFO, String.format(log, objects));
log(Level.INFO, String.format(log, objects));
}
@Override
public void logException(String message, Exception ex) {
VelocityPlugin.INSTANCE.getLogger().log(Level.SEVERE, message, ex);
}
}
@@ -12,6 +12,7 @@ import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
public class VelocityCommand implements SimpleCommand {
@@ -78,7 +79,10 @@ public class VelocityCommand implements SimpleCommand {
.mapToObj(i -> args[i + 1]).toArray(String[]::new));
}
}
}else if (children.length > 0){ // && args.length == 0 is always true here
return Arrays.stream(children).map(Command::name).collect(Collectors.toList());
}
return command.tabComplete(new VelocityCommandExecutor(sender), "alias", args);
}
+10 -5
View File
@@ -7,7 +7,7 @@
<groupId>dev.brighten.antivpn</groupId>
<artifactId>AntiVPN</artifactId>
<packaging>pom</packaging>
<version>1.8.2</version>
<version>1.9.3.1</version>
<modules>
<module>Common</module>
@@ -15,6 +15,7 @@
<module>Bukkit</module>
<module>Assembly</module>
<module>Velocity</module>
<module>Sponge</module>
</modules>
<properties>
@@ -27,7 +28,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.7.0</version>
<version>3.13.0</version>
<configuration>
<source>8</source>
<target>8</target>
@@ -37,7 +38,7 @@
<path>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.20</version>
<version>1.18.30</version>
</path>
</annotationProcessorPaths>
</configuration>
@@ -52,6 +53,10 @@
</build>
<repositories>
<repository>
<id>spigot-repo</id>
<url>https://hub.spigotmc.org/nexus/content/repositories/snapshots/</url>
</repository>
<repository>
<id>funkemunky-releases</id>
<url>https://nexus.funkemunky.cc/content/repositories/releases/</url>
@@ -60,9 +65,9 @@
<dependencies>
<dependency>
<groupId>cc.funkemunky.utils</groupId>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.0</version>
<version>1.18.30</version>
<scope>provided</scope>
</dependency>
</dependencies>