[17.8k Lines] Started working on the chat filter
This commit is contained in:
parent
4d2a8369d9
commit
6803133935
@ -11,6 +11,7 @@ import zone.themcgamer.api.model.ModelSerializer;
|
|||||||
import zone.themcgamer.api.model.impl.*;
|
import zone.themcgamer.api.model.impl.*;
|
||||||
import zone.themcgamer.api.repository.AccountRepository;
|
import zone.themcgamer.api.repository.AccountRepository;
|
||||||
import zone.themcgamer.api.route.AccountRoute;
|
import zone.themcgamer.api.route.AccountRoute;
|
||||||
|
import zone.themcgamer.api.route.ChatRoute;
|
||||||
import zone.themcgamer.api.route.PlayerStatusRoute;
|
import zone.themcgamer.api.route.PlayerStatusRoute;
|
||||||
import zone.themcgamer.api.route.ServersRoute;
|
import zone.themcgamer.api.route.ServersRoute;
|
||||||
import zone.themcgamer.data.APIAccessLevel;
|
import zone.themcgamer.data.APIAccessLevel;
|
||||||
@ -63,6 +64,7 @@ public class API {
|
|||||||
addRoute(new ServersRoute());
|
addRoute(new ServersRoute());
|
||||||
addRoute(new AccountRoute(accountRepository));
|
addRoute(new AccountRoute(accountRepository));
|
||||||
addRoute(new PlayerStatusRoute());
|
addRoute(new PlayerStatusRoute());
|
||||||
|
addRoute(new ChatRoute());
|
||||||
|
|
||||||
// 404 Handling
|
// 404 Handling
|
||||||
Spark.notFound((request, response) -> {
|
Spark.notFound((request, response) -> {
|
||||||
|
70
api/src/main/java/zone/themcgamer/api/route/ChatRoute.java
Normal file
70
api/src/main/java/zone/themcgamer/api/route/ChatRoute.java
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
package zone.themcgamer.api.route;
|
||||||
|
|
||||||
|
import com.google.common.base.Strings;
|
||||||
|
import spark.Request;
|
||||||
|
import spark.Response;
|
||||||
|
import zone.themcgamer.api.APIException;
|
||||||
|
import zone.themcgamer.api.APIVersion;
|
||||||
|
import zone.themcgamer.api.RestPath;
|
||||||
|
import zone.themcgamer.common.EnumUtils;
|
||||||
|
import zone.themcgamer.data.APIAccessLevel;
|
||||||
|
import zone.themcgamer.data.ChatFilterLevel;
|
||||||
|
import zone.themcgamer.data.jedis.data.APIKey;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This route handles everything associated with the chat
|
||||||
|
*
|
||||||
|
* @author Braydon
|
||||||
|
*/
|
||||||
|
public class ChatRoute {
|
||||||
|
private static final Map<ChatFilterLevel, List<String>> filteredWords = new HashMap<>() {{
|
||||||
|
put(ChatFilterLevel.LOW, Arrays.asList(
|
||||||
|
"ass"
|
||||||
|
));
|
||||||
|
put(ChatFilterLevel.MEDIUM, Arrays.asList(
|
||||||
|
"fuck", "shit"
|
||||||
|
));
|
||||||
|
put(ChatFilterLevel.HIGH, Arrays.asList(
|
||||||
|
"nigger"
|
||||||
|
));
|
||||||
|
}};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This path handles filtering the provided text with the provided {@link ChatFilterLevel}
|
||||||
|
*/
|
||||||
|
@RestPath(path = "/filter/:text/:level", version = APIVersion.V1, accessLevel = APIAccessLevel.DEV)
|
||||||
|
public String filterText(Request request, Response response, APIKey apiKey) throws APIException {
|
||||||
|
String text = request.params(":text");
|
||||||
|
ChatFilterLevel chatFilterLevel = EnumUtils.fromString(ChatFilterLevel.class, request.params(":level").toUpperCase());
|
||||||
|
if (chatFilterLevel == null)
|
||||||
|
throw new APIException("Invalid filter level, valid options: " + Arrays.stream(ChatFilterLevel.values()).map(ChatFilterLevel::name).collect(Collectors.joining(", ")));
|
||||||
|
String filteredMessage = text;
|
||||||
|
text = text.replace("{dot}", ".");
|
||||||
|
if (chatFilterLevel.isUrls()) {
|
||||||
|
// TODO: 2/20/21 filter urls with regex patterns
|
||||||
|
}
|
||||||
|
if (chatFilterLevel.isIps()) {
|
||||||
|
// TODO: 2/20/21 filter ips with regex patterns
|
||||||
|
}
|
||||||
|
List<String> filteredWords = new ArrayList<>();
|
||||||
|
for (ChatFilterLevel filterLevel : ChatFilterLevel.values()) {
|
||||||
|
if (chatFilterLevel.ordinal() >= filterLevel.ordinal()) {
|
||||||
|
List<String> list = ChatRoute.filteredWords.getOrDefault(filterLevel, new ArrayList<>());
|
||||||
|
if (list.isEmpty())
|
||||||
|
continue;
|
||||||
|
filteredWords.addAll(list);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (String word : text.split(" ")) {
|
||||||
|
for (String filteredWord : filteredWords) {
|
||||||
|
if (word.toLowerCase().contains(filteredWord.toLowerCase())) {
|
||||||
|
filteredMessage = filteredMessage.replace(word, Strings.repeat("*", word.length()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return filteredMessage;
|
||||||
|
}
|
||||||
|
}
|
@ -41,7 +41,7 @@ subprojects {
|
|||||||
|
|
||||||
compileOnly("org.slf4j:slf4j-simple:1.7.30")
|
compileOnly("org.slf4j:slf4j-simple:1.7.30")
|
||||||
|
|
||||||
implementation("com.google.code.gson:gson:2.7")
|
implementation("com.google.code.gson:gson:2.8.5")
|
||||||
|
|
||||||
implementation("commons-io:commons-io:2.6")
|
implementation("commons-io:commons-io:2.6")
|
||||||
|
|
||||||
|
37
core/src/main/java/zone/themcgamer/core/api/WebAPI.java
Normal file
37
core/src/main/java/zone/themcgamer/core/api/WebAPI.java
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
package zone.themcgamer.core.api;
|
||||||
|
|
||||||
|
import com.google.gson.JsonElement;
|
||||||
|
import com.google.gson.JsonObject;
|
||||||
|
import lombok.NonNull;
|
||||||
|
import zone.themcgamer.core.api.json.JsonRequest;
|
||||||
|
import zone.themcgamer.core.api.json.JsonResponse;
|
||||||
|
import zone.themcgamer.data.ChatFilterLevel;
|
||||||
|
|
||||||
|
import java.net.http.HttpClient;
|
||||||
|
import java.time.Duration;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Braydon
|
||||||
|
*/
|
||||||
|
public class WebAPI {
|
||||||
|
public static final String API_KEY = "406321cc-48f3-454b-900a-972fd88e4882";
|
||||||
|
private static final String URL = "https://api.mcgamerzone.net/v1";
|
||||||
|
public static HttpClient HTTP_CLIENT;
|
||||||
|
|
||||||
|
static {
|
||||||
|
HTTP_CLIENT = java.net.http.HttpClient.newBuilder()
|
||||||
|
.version(java.net.http.HttpClient.Version.HTTP_1_1)
|
||||||
|
.followRedirects(java.net.http.HttpClient.Redirect.NORMAL)
|
||||||
|
.connectTimeout(Duration.ofSeconds(30L))
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String filterText(@NonNull String text, @NonNull ChatFilterLevel chatFilterLevel) {
|
||||||
|
JsonResponse jsonResponse = new JsonRequest(URL + "/filter/" + text.replaceAll(" ", "%20") + "/" + chatFilterLevel.name()).getResponse();
|
||||||
|
JsonElement jsonElement = jsonResponse.getJsonElement();
|
||||||
|
if (!(jsonElement instanceof JsonObject))
|
||||||
|
return text;
|
||||||
|
JsonObject jsonObject = (JsonObject) jsonElement;
|
||||||
|
return jsonObject.get("value").getAsString();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,64 @@
|
|||||||
|
package zone.themcgamer.core.api.json;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import zone.themcgamer.core.api.WebAPI;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.URI;
|
||||||
|
import java.net.http.HttpRequest;
|
||||||
|
import java.net.http.HttpResponse;
|
||||||
|
import java.time.Duration;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Braydon
|
||||||
|
*/
|
||||||
|
@AllArgsConstructor @Slf4j(topic = "Json Request")
|
||||||
|
public class JsonRequest {
|
||||||
|
private final String url;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the {@link JsonResponse} from the provided url
|
||||||
|
*
|
||||||
|
* @return the response
|
||||||
|
*/
|
||||||
|
public JsonResponse getResponse() {
|
||||||
|
try {
|
||||||
|
return checkResponse(WebAPI.HTTP_CLIENT.send(buildRequest(), HttpResponse.BodyHandlers.ofString()));
|
||||||
|
} catch (IOException | InterruptedException ex) {
|
||||||
|
ex.printStackTrace();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the {@link JsonResponse} from the provided url asynchronously
|
||||||
|
*
|
||||||
|
* @param consumer the consumer the response will be accepted in
|
||||||
|
*/
|
||||||
|
public void getResponseAsync(Consumer<JsonResponse> consumer) {
|
||||||
|
WebAPI.HTTP_CLIENT.sendAsync(buildRequest(), HttpResponse.BodyHandlers.ofString())
|
||||||
|
.thenAccept(httpResponse -> consumer.accept(checkResponse(httpResponse)));
|
||||||
|
}
|
||||||
|
|
||||||
|
private JsonResponse checkResponse(HttpResponse<String> httpResponse) {
|
||||||
|
int statusCode = httpResponse.statusCode();
|
||||||
|
if (statusCode != 200) {
|
||||||
|
log.warn("Response from \"" + url + "\" returned status code " + statusCode + ":");
|
||||||
|
log.warn("Body: " + httpResponse.body());
|
||||||
|
log.warn("Headers: " + httpResponse.headers().toString());
|
||||||
|
}
|
||||||
|
return new JsonResponse(httpResponse);
|
||||||
|
}
|
||||||
|
|
||||||
|
private HttpRequest buildRequest() {
|
||||||
|
return HttpRequest.newBuilder()
|
||||||
|
.GET()
|
||||||
|
.uri(URI.create(url))
|
||||||
|
.timeout(Duration.ofMinutes(1L))
|
||||||
|
.header("Content-Type", "application/json")
|
||||||
|
.header("key", WebAPI.API_KEY)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,25 @@
|
|||||||
|
package zone.themcgamer.core.api.json;
|
||||||
|
|
||||||
|
import com.google.gson.JsonElement;
|
||||||
|
import com.google.gson.JsonParser;
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
import java.net.http.HttpResponse;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class represents a response from a {@link JsonRequest}
|
||||||
|
*
|
||||||
|
* @author Braydon
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
public class JsonResponse {
|
||||||
|
private final HttpResponse<String> httpResponse;
|
||||||
|
private final String json;
|
||||||
|
private final JsonElement jsonElement;
|
||||||
|
|
||||||
|
public JsonResponse(HttpResponse<String> httpResponse) {
|
||||||
|
this.httpResponse = httpResponse;
|
||||||
|
json = httpResponse.body();
|
||||||
|
jsonElement = new JsonParser().parse(json);
|
||||||
|
}
|
||||||
|
}
|
@ -13,6 +13,7 @@ import org.bukkit.event.player.AsyncPlayerChatEvent;
|
|||||||
import org.bukkit.plugin.java.JavaPlugin;
|
import org.bukkit.plugin.java.JavaPlugin;
|
||||||
import zone.themcgamer.core.account.Account;
|
import zone.themcgamer.core.account.Account;
|
||||||
import zone.themcgamer.core.account.AccountManager;
|
import zone.themcgamer.core.account.AccountManager;
|
||||||
|
import zone.themcgamer.core.api.WebAPI;
|
||||||
import zone.themcgamer.core.badSportSystem.BadSportClient;
|
import zone.themcgamer.core.badSportSystem.BadSportClient;
|
||||||
import zone.themcgamer.core.badSportSystem.BadSportSystem;
|
import zone.themcgamer.core.badSportSystem.BadSportSystem;
|
||||||
import zone.themcgamer.core.badSportSystem.Punishment;
|
import zone.themcgamer.core.badSportSystem.Punishment;
|
||||||
@ -26,6 +27,7 @@ import zone.themcgamer.core.common.Style;
|
|||||||
import zone.themcgamer.core.cooldown.CooldownHandler;
|
import zone.themcgamer.core.cooldown.CooldownHandler;
|
||||||
import zone.themcgamer.core.module.Module;
|
import zone.themcgamer.core.module.Module;
|
||||||
import zone.themcgamer.core.module.ModuleInfo;
|
import zone.themcgamer.core.module.ModuleInfo;
|
||||||
|
import zone.themcgamer.data.ChatFilterLevel;
|
||||||
import zone.themcgamer.data.Rank;
|
import zone.themcgamer.data.Rank;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
@ -41,19 +43,21 @@ public class ChatManager extends Module {
|
|||||||
@Getter private final Map<String, String> emotes = new HashMap<>();
|
@Getter private final Map<String, String> emotes = new HashMap<>();
|
||||||
|
|
||||||
{
|
{
|
||||||
emotes.put("¯\\_(ツ)_/¯", ":shrug:");
|
emotes.put(":shrug:", "¯\\_(ツ)_/¯");
|
||||||
emotes.put("⊂(´・◡・⊂ )∘˚˳°", ":happyghost:");
|
emotes.put(":happyghost:", "⊂(´・◡・⊂ )∘˚˳°");
|
||||||
emotes.put("ヽ༼ຈل͜ຈ༽ノ", ":donger:");
|
emotes.put(":donger:", "ヽ༼ຈل͜ຈ༽ノ");
|
||||||
emotes.put("ಠ_ಠ", ":disapproval:");
|
emotes.put(":disapproval:", "ಠ_ಠ");
|
||||||
emotes.put("(≖_≖)", ":squint:");
|
emotes.put(":squint:", "(≖_≖)");
|
||||||
emotes.put("(౮⦦ʖ౮)", ":lenny:");
|
emotes.put(":lenny:", "(౮⦦ʖ౮)");
|
||||||
emotes.put("┬─┬ ノ( ゜-゜ノ)", ":unflip:");
|
emotes.put(":unflip:", "┬─┬ ノ( ゜-゜ノ)");
|
||||||
emotes.put("(☞゚ヮ゚)☞", ":same:");
|
emotes.put(":same:", "(☞゚ヮ゚)☞");
|
||||||
emotes.put("ლ(ಥ Д ಥ )ლ", ":why:");
|
emotes.put(":why:", "ლ(ಥ Д ಥ )ლ");
|
||||||
emotes.put("(╯°□°)╯︵ ┻━┻", ":tableflip:");
|
emotes.put(":tableflip:", "(╯°□°)╯︵ ┻━┻");
|
||||||
emotes.put("⊂(•̀_•́⊂ )∘˚˳°", ":angryghost:");
|
emotes.put(":angryghost:", "⊂(•̀_•́⊂ )∘˚˳°");
|
||||||
emotes.put("( ˘ ³˘)♥", ":kiss:");
|
emotes.put(":kiss:", "( ˘ ³˘)♥");
|
||||||
emotes.put("༼ つ ◕_◕ ༽つ", ":ameno:");
|
emotes.put(":ameno:", "༼ つ ◕_◕ ༽つ");
|
||||||
|
emotes.put(":heart:", "❤");
|
||||||
|
emotes.put("<3", "❤");
|
||||||
}
|
}
|
||||||
|
|
||||||
public ChatManager(JavaPlugin plugin, AccountManager accountManager, BadSportSystem badSportSystem, IChatComponent[] chatComponents) {
|
public ChatManager(JavaPlugin plugin, AccountManager accountManager, BadSportSystem badSportSystem, IChatComponent[] chatComponents) {
|
||||||
@ -88,7 +92,11 @@ public class ChatManager extends Module {
|
|||||||
player.sendMessage(Style.error("Bad Sport", PunishmentCategory.format(optionalMute.get())));
|
player.sendMessage(Style.error("Bad Sport", PunishmentCategory.format(optionalMute.get())));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// TODO: 1/26/21 filter message
|
try {
|
||||||
|
message = WebAPI.filterText(message, ChatFilterLevel.HIGH);
|
||||||
|
} catch (Exception ex) {
|
||||||
|
player.sendMessage(Style.error("Chat", "§cProblem filtering chat message: §f" + ex.getLocalizedMessage()));
|
||||||
|
}
|
||||||
if (message.trim().isEmpty()) {
|
if (message.trim().isEmpty()) {
|
||||||
player.sendMessage(Style.error("Chat", "§cCannot send empty chat message"));
|
player.sendMessage(Style.error("Chat", "§cCannot send empty chat message"));
|
||||||
return;
|
return;
|
||||||
@ -104,7 +112,7 @@ public class ChatManager extends Module {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
for (Map.Entry<String, String> emote : emotes.entrySet())
|
for (Map.Entry<String, String> emote : emotes.entrySet())
|
||||||
message = message.replace(emote.getValue(), emote.getKey());
|
message = message.replace(emote.getKey(), emote.getValue());
|
||||||
List<BaseComponent> components = new ArrayList<>();
|
List<BaseComponent> components = new ArrayList<>();
|
||||||
for (IChatComponent chatComponent : chatComponents) {
|
for (IChatComponent chatComponent : chatComponents) {
|
||||||
BaseComponent component = chatComponent.getComponent(player);
|
BaseComponent component = chatComponent.getComponent(player);
|
||||||
|
@ -21,6 +21,6 @@ public class EmotesCommand {
|
|||||||
Player player = command.getPlayer();
|
Player player = command.getPlayer();
|
||||||
player.sendMessage(Style.main("Chat", "Chat Emotes:"));
|
player.sendMessage(Style.main("Chat", "Chat Emotes:"));
|
||||||
for (Map.Entry<String, String> entry : chatManager.getEmotes().entrySet())
|
for (Map.Entry<String, String> entry : chatManager.getEmotes().entrySet())
|
||||||
player.sendMessage(" §6" + entry.getValue() + " §7-> §b" + entry.getKey());
|
player.sendMessage(" §6" + entry.getKey() + " §7-> §b" + entry.getValue());
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -0,0 +1,17 @@
|
|||||||
|
package zone.themcgamer.data;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Braydon
|
||||||
|
*/
|
||||||
|
@AllArgsConstructor
|
||||||
|
@Getter
|
||||||
|
public enum ChatFilterLevel {
|
||||||
|
LOW(false, true),
|
||||||
|
MEDIUM(true, true),
|
||||||
|
HIGH(true, true);
|
||||||
|
|
||||||
|
private final boolean urls, ips;
|
||||||
|
}
|
Reference in New Issue
Block a user