Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,10 @@
<pattern>org.bstats</pattern>
<shadedPattern>org.zeroBzeroT.bstats</shadedPattern>
</relocation>
<relocation>
<pattern>redis.clients</pattern>
<shadedPattern>org.zeroBzeroT.chatCo.shaded.redis</shadedPattern>
</relocation>
</relocations>
<filters>
<filter>
Expand All @@ -62,6 +66,12 @@
<exclude>META-INF/*.MF</exclude>
</excludes>
</filter>
<filter>
<artifact>redis.clients:*</artifact>
<excludes>
<exclude>META-INF/*.MF</exclude>
</excludes>
</filter>
<filter>
<excludes>
<exclude>META-INF/**</exclude>
Expand Down Expand Up @@ -100,6 +110,10 @@
<url>https://repo.codemc.org/repository/maven-public/</url>
<layout>default</layout>
</repository>
<repository>
<id>central</id>
<url>https://repo1.maven.org/maven2/</url>
</repository>
</repositories>

<dependencies>
Expand All @@ -121,5 +135,11 @@
<version>3.1.0</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>5.1.3</version>
<scope>compile</scope>
</dependency>
</dependencies>
</project>
5 changes: 4 additions & 1 deletion src/main/java/org/zeroBzeroT/chatCo/ChatPlayer.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ public class ChatPlayer {
private List<String> ignores;
private List<String> ignoredBy;

public boolean rulesNoticeSent;


public ChatPlayer(final Player p) throws IOException {
name = p.getName();
Expand All @@ -34,7 +36,8 @@ public ChatPlayer(final Player p) throws IOException {
LastMessenger = null;
LastReceiver = null;
ignoredBy = new ArrayList<>();

rulesNoticeSent = false;

// create the ignore-list
saveIgnoreList("");
}
Expand Down
83 changes: 83 additions & 0 deletions src/main/java/org/zeroBzeroT/chatCo/LinkBlocker.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
package org.zeroBzeroT.chatCo;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.HashSet;
import java.util.Locale;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class LinkBlocker {

public static final Pattern URL_PATTERN = Pattern.compile(
"https?://(?:www\\.)?[-a-zA-Z0-9@:%._+~#=]{1,256}\\.[a-zA-Z0-9()]{1,6}\\b[-a-zA-Z0-9()@:%_\\\\+.~#?&/=]*");

private Set<String> domainAllowlist = new HashSet<>();
private String replacement = "[link removed]";
private boolean loaded = false;

public synchronized void load(File whitelistFile, String replacement) {
this.replacement = replacement == null ? "[link removed]" : replacement;
this.domainAllowlist = new HashSet<>();
if (whitelistFile != null && whitelistFile.exists()) {
try (BufferedReader r = new BufferedReader(new FileReader(whitelistFile))) {
String line;
while ((line = r.readLine()) != null) {
String t = line.trim().toLowerCase(Locale.ROOT);
if (t.isEmpty() || t.startsWith("#")) continue;
if (t.startsWith("http://")) t = t.substring(7);
else if (t.startsWith("https://")) t = t.substring(8);
if (t.endsWith("/")) t = t.substring(0, t.length() - 1);
domainAllowlist.add(t);
}
} catch (IOException ignored) {}
}
this.loaded = true;
}

public synchronized String apply(String message) {
if (!loaded || message == null || message.isEmpty()) return message;
Matcher m = URL_PATTERN.matcher(message);
StringBuilder out = new StringBuilder(message.length());
int last = 0;
while (m.find()) {
String url = m.group();
if (isAllowed(url)) {
continue;
}
out.append(message, last, m.start());
if (!replacement.isEmpty()) {
out.append(replacement);
} else if (out.length() > 0 && out.charAt(out.length() - 1) == ' ') {
out.setLength(out.length() - 1);
}
last = m.end();
}
out.append(message, last, message.length());
return out.toString();
}

private boolean isAllowed(String url) {
String host = extractHost(url);
if (host == null) return false;
return domainAllowlist.contains(host);
}

private static String extractHost(String url) {
String s = url.toLowerCase(Locale.ROOT);
if (s.startsWith("https://")) s = s.substring(8);
else if (s.startsWith("http://")) s = s.substring(7);
int slash = s.indexOf('/');
if (slash >= 0) s = s.substring(0, slash);
int colon = s.indexOf(':');
if (colon >= 0) s = s.substring(0, colon);
return s.isEmpty() ? null : s;
}

public boolean isLoaded() {
return loaded;
}
}
75 changes: 73 additions & 2 deletions src/main/java/org/zeroBzeroT/chatCo/Main.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.UUID;

import org.bstats.bukkit.Metrics;
import org.bukkit.Bukkit;
Expand All @@ -26,16 +27,28 @@ public class Main extends JavaPlugin {
public static File WhisperLog;
public static File dataFolder;
private static File Help;
public static File WordListFile;
public static File WhiteListFile;
public Collection<ChatPlayer> playerList;
private Whispers whispers;

private WordFilter wordFilter;
private LinkBlocker linkBlocker;
private int thresholdHours;
private PublicChat publicChat;
private static Main instance;

public static Main getInstance() {
return instance;
}

@Override
public void onDisable() {
playerList.clear();
}

@Override
public void onEnable() {
instance = this;
playerList = Collections.synchronizedCollection(new ArrayList<>());

// Config defaults
Expand All @@ -44,10 +57,13 @@ public void onEnable() {

saveResourceFiles();
toggleConfigValue(0);
loadFilters();
reloadGateConfig();

final PluginManager pm = getServer().getPluginManager();

pm.registerEvents(new PublicChat(this), this);
publicChat = new PublicChat(this);
pm.registerEvents(publicChat, this);

if (getConfig().getBoolean("ChatCo.whisperChangesEnabled", true)) {
whispers = new Whispers(this);
Expand All @@ -63,6 +79,46 @@ public void onEnable() {
}
}

public void loadFilters() {
if (wordFilter == null) wordFilter = new WordFilter();
if (linkBlocker == null) linkBlocker = new LinkBlocker();
boolean fuzzy = getConfig().getBoolean("ChatCo.playtimeGate.wordFilter.fuzzy", false);
String replacement = getConfig().getString("ChatCo.playtimeGate.wordFilter.replacement", "bobba");
wordFilter.load(WordListFile, WhiteListFile, fuzzy, replacement);
String linkRepl = getConfig().getString("ChatCo.playtimeGate.linkBlock.replacement", "[link removed]");
linkBlocker.load(WhiteListFile, linkRepl);
}

public void reloadGateConfig() {
thresholdHours = getConfig().getInt("ChatCo.playtimeGate.thresholdHours", 10);
}

public WordFilter getWordFilter() {
return wordFilter;
}

public LinkBlocker getLinkBlocker() {
return linkBlocker;
}

public boolean isGated(org.bukkit.entity.Player player) {
if (thresholdHours == 0) return false;
if (thresholdHours < 0) return true;
int hours = getPlaytimeHours(player.getUniqueId());
return hours < thresholdHours;
}

private int getPlaytimeHours(UUID uuid) {
String key = "player." + uuid + ".playtime";
java.util.Optional<String> value = Redis.readSync(key);
if (value.isEmpty()) return 0;
try {
return Integer.parseInt(value.get());
} catch (NumberFormatException e) {
return 0;
}
}

private void toggleConfigValue(final int change) {
switch (change) {
case 3:
Expand Down Expand Up @@ -101,6 +157,8 @@ private void saveResourceFiles() {
Main.PermissionConfig = new File(Main.dataFolder, "permissionConfig.yml");
Main.WhisperLog = new File(Main.dataFolder, "whisperlog.txt");
Main.Help = new File(Main.dataFolder, "help.txt");
Main.WordListFile = new File(Main.dataFolder, "wordlist.txt");
Main.WhiteListFile = new File(Main.dataFolder, "whitelist.txt");

if (!Main.WhisperLog.exists()) {
Main.WhisperLog.getParentFile().mkdirs();
Expand All @@ -112,6 +170,16 @@ private void saveResourceFiles() {
saveStreamToFile(getResource("help.txt"), Main.Help);
}

if (!Main.WordListFile.exists()) {
Main.WordListFile.getParentFile().mkdirs();
saveStreamToFile(getResource("wordlist.txt"), Main.WordListFile);
}

if (!Main.WhiteListFile.exists()) {
Main.WhiteListFile.getParentFile().mkdirs();
saveStreamToFile(getResource("whitelist.txt"), Main.WhiteListFile);
}

// Save the default config file, if it does not exist
saveDefaultConfig();

Expand Down Expand Up @@ -203,6 +271,9 @@ public boolean onCommand(final @NotNull CommandSender sender, final @NotNull Com
if (args.length > 0 && args[0].equalsIgnoreCase("reload")) {
reloadConfig();
saveConfig();
loadFilters();
reloadGateConfig();
if (publicChat != null) publicChat.reload();
sender.sendMessage("Config reloaded");
return true;
}
Expand Down
Loading