Skip to content

Commit fdf4847

Browse files
committed
cool
0 parents  commit fdf4847

19 files changed

+630
-0
lines changed

.gitignore

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
**/.DS_Store
2+
.idea
3+
.gradle
4+
build
5+
run
6+
gradlew
7+
gradlew.bat

README.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
# OriginBlacklist
2+
3+
basically just a reimplementation of originblacklist but for eaglerxserver
4+
5+
> [!WARNING]
6+
> **Velocity is the main platform I'm developing this for, bungee & bukkit will still work but will probably have some bugs and will receive less support!**
7+
8+
### Download
9+
**[https://github.com/colbster937/originblacklist/releases](https://github.com/colbster937/originblacklist/releases)**
10+
11+
### Building
12+
```
13+
$ gradle wrapper
14+
$ ./gradle.<bat|sh> shadowJar
15+
```

build.gradle

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
plugins {
2+
id 'java'
3+
id 'eclipse'
4+
id 'org.jetbrains.gradle.plugin.idea-ext' version '1.1.8'
5+
id 'com.github.johnrengelman.shadow' version '8.1.1'
6+
id("xyz.jpenilla.run-velocity") version "2.3.1"
7+
}
8+
9+
10+
group = 'dev.colbster937'
11+
version = '1.0.0'
12+
13+
repositories {
14+
mavenCentral()
15+
maven {
16+
name = "papermc-repo"
17+
url = "https://repo.papermc.io/repository/maven-public/"
18+
}
19+
maven {
20+
name = "sonatype"
21+
url = "https://oss.sonatype.org/content/groups/public/"
22+
}
23+
maven {
24+
name = "spigotmc-repo"
25+
url = "https://hub.spigotmc.org/nexus/content/repositories/public/"
26+
}
27+
maven {
28+
name = "md_5"
29+
url = "https://repo.md-5.net/content/repositories/releases/"
30+
}
31+
maven {
32+
name = "aikar"
33+
url = "https://repo.aikar.co/nexus/content/groups/aikar/"
34+
}
35+
maven {
36+
name = "lax1dude"
37+
url = "https://repo.lax1dude.net/repository/releases/"
38+
}
39+
}
40+
41+
dependencies {
42+
compileOnly("com.velocitypowered:velocity-api:3.3.0-SNAPSHOT")
43+
annotationProcessor("com.velocitypowered:velocity-api:3.3.0-SNAPSHOT")
44+
compileOnly("org.bukkit:bukkit:1.8-R0.1-SNAPSHOT")
45+
compileOnly("net.md-5:bungeecord-api:1.8-SNAPSHOT")
46+
compileOnly("net.lax1dude.eaglercraft.backend:api-velocity:1.0.0")
47+
compileOnly("net.lax1dude.eaglercraft.backend:api-bungee:1.0.0")
48+
compileOnly("net.lax1dude.eaglercraft.backend:api-bukkit:1.0.0")
49+
implementation("org.yaml:snakeyaml:2.2")
50+
implementation("net.kyori:adventure-api:4.20.0")
51+
implementation("net.kyori:adventure-text-serializer-legacy:4.20.0")
52+
implementation("net.kyori:adventure-text-minimessage:4.20.0")
53+
}
54+
55+
tasks {
56+
runVelocity {
57+
// Configure the Velocity version for our task.
58+
// This is the only required configuration besides applying the plugin.
59+
// Your plugin's jar (or shadowJar if present) will be used automatically.
60+
velocityVersion("3.3.0-SNAPSHOT")
61+
}
62+
}
63+
64+
def targetJavaVersion = 17
65+
java {
66+
toolchain.languageVersion = JavaLanguageVersion.of(targetJavaVersion)
67+
}
68+
69+
shadowJar {
70+
relocate 'org.yaml.snakeyaml', 'dev.colbster937.shaded.snakeyaml'
71+
archiveClassifier.set('all')
72+
}
73+
74+
tasks.withType(JavaCompile).configureEach {
75+
options.encoding = 'UTF-8'
76+
options.release.set(targetJavaVersion)
77+
}
78+
79+
/*def templateSource = file('src/main/templates')
80+
def templateDest = layout.buildDirectory.dir('generated/sources/templates')
81+
def generateTemplates = tasks.register('generateTemplates', Copy) { task ->
82+
def props = ['version': project.version]
83+
task.inputs.properties props
84+
85+
task.from templateSource
86+
task.into templateDest
87+
task.expand props
88+
}
89+
90+
sourceSets.main.java.srcDir(generateTemplates.map { it.outputs })
91+
92+
project.idea.project.settings.taskTriggers.afterSync generateTemplates
93+
project.eclipse.synchronizationTasks(generateTemplates)*/

gradle.properties

Whitespace-only changes.

gradle/wrapper/gradle-wrapper.jar

42.4 KB
Binary file not shown.
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
distributionBase=GRADLE_USER_HOME
2+
distributionPath=wrapper/dists
3+
distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-bin.zip
4+
networkTimeout=10000
5+
validateDistributionUrl=true
6+
zipStoreBase=GRADLE_USER_HOME
7+
zipStorePath=wrapper/dists

settings.gradle

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
rootProject.name = 'OriginBlacklist'
Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
package dev.colbster937.originblacklist.base;
2+
3+
import net.kyori.adventure.text.minimessage.MiniMessage;
4+
import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
5+
import net.lax1dude.eaglercraft.backend.server.api.IEaglerXServerAPI;
6+
import net.lax1dude.eaglercraft.backend.server.api.IEaglerPlayer;
7+
import net.lax1dude.eaglercraft.backend.server.api.EnumWebSocketHeader;
8+
import net.lax1dude.eaglercraft.backend.server.api.event.IEaglercraftInitializePlayerEvent;
9+
import java.io.OutputStream;
10+
import java.net.HttpURLConnection;
11+
import java.net.URL;
12+
13+
public class Base {
14+
private static LoggerAdapter adapter;
15+
private static IEaglerXServerAPI api;
16+
private static ConfigManager config;
17+
18+
public static void setLogger(LoggerAdapter log) {
19+
adapter = log;
20+
}
21+
22+
public static void setApi(IEaglerXServerAPI api1) {
23+
api = api1;
24+
}
25+
26+
public static LoggerAdapter getLogger() {
27+
if (adapter == null) throw new IllegalStateException("Logger not initialized!");
28+
return adapter;
29+
}
30+
31+
public interface LoggerAdapter {
32+
void info(String msg);
33+
void warn(String msg);
34+
void error(String msg);
35+
}
36+
37+
public static void handleConnection(IEaglercraftInitializePlayerEvent e) {
38+
IEaglerPlayer plr = e.getPlayer();
39+
String origin = plr.getWebSocketHeader(EnumWebSocketHeader.HEADER_ORIGIN);
40+
String brand = plr.getEaglerBrandString();
41+
if ((origin != "null" || origin != null) && !config.blacklist.missing_origin) {
42+
for (String origin1 : config.blacklist.origins) {
43+
if (matches(origin, origin1)) {
44+
plr.disconnect(kick("origin", "website", origin));
45+
webhook(plr, origin, brand, "origin");
46+
return;
47+
}
48+
}
49+
} else {
50+
plr.disconnect(kick("origin", "website", origin));
51+
webhook(plr, "null", brand, "origin");
52+
}
53+
if (brand != "null" && brand != null) {
54+
for (String brand1 : config.blacklist.brands) {
55+
if (matches(brand, brand1)) {
56+
plr.disconnect(kick("brand", "client", brand));
57+
webhook(plr, origin, brand, "brand");
58+
return;
59+
}
60+
}
61+
}
62+
}
63+
64+
public static boolean matches(String text1, String text2) {
65+
return text1.toLowerCase().matches(text2.replace(".", "\\.").replaceAll("\\*", ".*").toLowerCase());
66+
}
67+
68+
public static String kick(String type, String easytype, String value) {
69+
return LegacyComponentSerializer.legacySection().serialize(
70+
MiniMessage.miniMessage().deserialize(
71+
config.messages.kick
72+
.replace("%blocktype%", type)
73+
.replace("%easyblocktype%", easytype)
74+
.replace("%blocked%", value)
75+
)
76+
);
77+
}
78+
79+
80+
public static void webhook(IEaglerPlayer plr, String origin, String brand, String type) {
81+
String webhook = config.discord.webhook;
82+
if (webhook == null || webhook.isBlank()) return;
83+
84+
String addr = plr.getPlayerAddress() != null ? plr.getPlayerAddress().toString().substring(1) : "undefined";
85+
String protocol = plr.isEaglerXRewindPlayer()
86+
? (String.valueOf(plr.getRewindProtocolVersion()) != null ? String.valueOf(plr.getRewindProtocolVersion()) : "undefined")
87+
: (String.valueOf(plr.getMinecraftProtocol()) != null ? String.valueOf(plr.getMinecraftProtocol()) : "undefined");
88+
String rewind = plr.isEaglerXRewindPlayer() ? "Yes" : "No";
89+
String userAgent = plr.getWebSocketHeader(EnumWebSocketHeader.HEADER_USER_AGENT);
90+
if (userAgent == null || userAgent.isEmpty()) userAgent = "undefined";
91+
92+
String payload = String.format("""
93+
{
94+
"content": "Blocked a blacklisted %s from joining",
95+
"embeds": [
96+
{
97+
"title": "Player Information",
98+
"description": "🎮 **Name:** %s\\n🏠 **Address:** %s\\n🌄 **PVN:** %s\\n🌐 **Origin:** %s\\n🔋 **Brand:** %s\\n🧊 **User Agent:** %s\\n⏪ **Rewind:** %s"
99+
}
100+
]
101+
}
102+
""", type, plr.getUsername(), addr, protocol, origin, brand, userAgent, rewind);
103+
104+
try {
105+
HttpURLConnection conn = (HttpURLConnection) new URL(webhook).openConnection();
106+
conn.setRequestMethod("POST");
107+
conn.setRequestProperty("Content-Type", "application/json");
108+
conn.setDoOutput(true);
109+
conn.setConnectTimeout(5000);
110+
conn.setReadTimeout(5000);
111+
112+
try (OutputStream os = conn.getOutputStream()) {
113+
os.write(payload.getBytes());
114+
}
115+
116+
conn.getInputStream().close();
117+
} catch (Exception e) {
118+
getLogger().warn("Failed to send webhook: " + e);
119+
}
120+
}
121+
122+
public static void reloadConfig() {
123+
config = ConfigManager.loadConfig(adapter);
124+
}
125+
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
package dev.colbster937.originblacklist.base;
2+
3+
public class Command {
4+
5+
public interface CommandContext {
6+
String getName();
7+
void reply(String message);
8+
boolean hasPermission(String permission);
9+
String[] getArgs();
10+
}
11+
12+
13+
public static void usage(CommandContext ctx) {
14+
ctx.reply("<aqua>Commands:</aqua>");
15+
ctx.reply("<gray> - /originblacklist reload</gray>");
16+
}
17+
18+
public static void handle(CommandContext ctx) {
19+
String[] args = ctx.getArgs();
20+
if (!ctx.hasPermission("originblacklist.reload")) {
21+
ctx.reply("<red>You do not have permission to use this command.</red>");
22+
return;
23+
} else if (args.length == 0) {
24+
usage(ctx);
25+
return;
26+
}
27+
28+
String sub = args[0].toLowerCase();
29+
30+
switch (sub) {
31+
case "reload" -> {
32+
Base.reloadConfig();
33+
ctx.reply("<green>Reloaded.</green>");
34+
}
35+
36+
default -> usage(ctx);
37+
}
38+
}
39+
}
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
package dev.colbster937.originblacklist.base;
2+
3+
import org.yaml.snakeyaml.Yaml;
4+
import org.yaml.snakeyaml.LoaderOptions;
5+
import org.yaml.snakeyaml.constructor.Constructor;
6+
import java.io.File;
7+
import java.io.InputStream;
8+
import java.io.FileInputStream;
9+
import java.io.IOException;
10+
import java.nio.file.Files;
11+
import java.nio.file.StandardCopyOption;
12+
import java.util.List;
13+
14+
public class ConfigManager {
15+
public Messages messages = new Messages();
16+
public List<String> subscriptions;
17+
public Blacklist blacklist = new Blacklist();
18+
public Discord discord = new Discord();
19+
20+
public static ConfigManager loadConfig(Base.LoggerAdapter logger) {
21+
File conf = new File("plugins/originblacklist/config.yml");
22+
23+
try {
24+
if (!conf.exists()) {
25+
conf.getParentFile().mkdirs();
26+
try (InputStream in = ConfigManager.class.getResourceAsStream("/config.yml")) {
27+
if (in != null) {
28+
Files.copy(in, conf.toPath(), StandardCopyOption.REPLACE_EXISTING);
29+
}
30+
}
31+
}
32+
33+
LoaderOptions options = new LoaderOptions();
34+
Constructor constructor = new Constructor(ConfigManager.class, options);
35+
Yaml yaml = new Yaml(constructor);
36+
return yaml.load(new FileInputStream(conf));
37+
} catch (IOException e) {
38+
return new ConfigManager();
39+
}
40+
}
41+
42+
public static class Blacklist {
43+
public List<String> origins;
44+
public List<String> brands;
45+
public List<String> players;
46+
public boolean missing_origin;
47+
48+
public Blacklist() {}
49+
}
50+
51+
public static class Discord {
52+
public String webhook;
53+
}
54+
55+
public static class Messages {
56+
public String kick;
57+
}
58+
}

0 commit comments

Comments
 (0)