commit e59f8f4d67b573e981ecf35d0e7016d3dc6ec6a3 Author: Etzelia Date: Wed Sep 12 10:55:10 2018 -0500 Initial commit for Gitea diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..3d13e3f --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +.idea/ +*.iml +target/ +dependency-reduced-pom.xml \ No newline at end of file diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..acb851e --- /dev/null +++ b/pom.xml @@ -0,0 +1,156 @@ + + 4.0.0 + xyz.etztech + MinecraftManager + + 1.1 + jar + + + + MinecraftManager + A plugin used alongside the MinecraftManager Django project. + http://www.etztech.xyz + + + + Zlib License + http://opensource.org/licenses/Zlib + Copyright (c) 2017 EtzTech + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + + 3. This notice may not be removed or altered from any source + distribution. + + + + + + EtzTech + http://www.etztech.xyz + + + + + + EtzTech + xyz.etztech.minecraftmanager.MinecraftManager + UTF-8 + + + + + org.spigotmc + spigot-api + 1.13-pre7-R0.1-SNAPSHOT + + + commons-lang + commons-lang + 2.6 + + + org.apache.httpcomponents + httpclient + 4.5.5 + + + + + + + + spigot-repo + https://hub.spigotmc.org/nexus/content/groups/public/ + + + mvn-repo + https://mvnrepository.com/artifact/ + + + jcenter + http://jcenter.bintray.com + + + jitpack.io + https://jitpack.io + + + + + src/main/java + clean install + + + src/main/resources + + true + + plugin.yml + config.yml + + + + src/main/resources + + false + + **/*.java + plugin.yml + + + + + + maven-compiler-plugin + 3.1 + + 1.7 + 1.7 + + + + + org.apache.maven.plugins + maven-jar-plugin + 3.0.2 + + + + true + lib/ + xyz.etztech.minecraftmanager.MinecraftManager + + + + + + org.apache.maven.plugins + maven-shade-plugin + 3.1.1 + + + package + + shade + + + + + + + \ No newline at end of file diff --git a/src/main/java/xyz/etztech/minecraftmanager/Application.java b/src/main/java/xyz/etztech/minecraftmanager/Application.java new file mode 100644 index 0000000..0bf4416 --- /dev/null +++ b/src/main/java/xyz/etztech/minecraftmanager/Application.java @@ -0,0 +1,123 @@ +package xyz.etztech.minecraftmanager; + +import org.apache.commons.lang.StringUtils; + +import java.util.HashMap; +import java.util.Map; + +public class Application { +// username = models.CharField("Minecraft Username", max_length=20, unique=True) +// age = models.PositiveSmallIntegerField() +// player_type = models.TextField("What type of player are you?", max_length=300) +// ever_banned = models.BooleanField("Have you ever been banned?", default=False) +// ever_banned_explanation = models.TextField("If you were previously banned, will you share why?", max_length=300, blank=True, null=True) +// reference = models.CharField("Were you referred to our server?", max_length=50, blank=True, null=True) +// read_rules = models.CharField("Have you read the rules?", max_length=10) + + private String username; + private String age; + private String playerType; + private String everBanned; + private String everBannedExplanation; + private String reference; + private String readRules; + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } + + public String getAge() { + return age; + } + + public void setAge(String age) { + this.age = age; + } + + public String getPlayerType() { + return playerType; + } + + public void setPlayerType(String playerType) { + this.playerType = playerType; + } + + public String getEverBanned() { + return everBanned; + } + + public void setEverBanned(String everBanned) { + this.everBanned = everBanned; + } + + public String getEverBannedExplanation() { + return everBannedExplanation; + } + + public void setEverBannedExplanation(String everBannedExplanation) { + this.everBannedExplanation = everBannedExplanation; + } + + public String getReference() { + return reference; + } + + public void setReference(String reference) { + this.reference = reference; + } + + public String getReadRules() { + return readRules; + } + + public void setReadRules(String readRules) { + this.readRules = readRules; + } + + public void setAnswer(Question question, String answer) { + if (question == Question.ONE) { + setAge(answer); + } else if (question == Question.TWO) { + setPlayerType(answer); + } else if (question == Question.THREE1) { + setEverBanned(answer); + if ("no".equalsIgnoreCase(answer)) { + setEverBannedExplanation(""); + } + } else if (question == Question.THREE2) { + setEverBannedExplanation(answer); + } else if (question == Question.FOUR) { + setReference(answer); + } else if (question == Question.FIVE) { + setReadRules(answer); + } + } + + public String getFormatted() { + StringBuffer msg = new StringBuffer(); + msg.append("Username: " + getUsername() + "\n"); + msg.append("Age: " + getAge() + "\n"); + msg.append("Player Type: " + getPlayerType() + "\n"); + msg.append("Ever Banned: " + getEverBanned() + "\n"); + msg.append("Explanation: " + getEverBannedExplanation() + "\n"); + msg.append("Reference: " + getReference() + "\n"); + msg.append("Read Rules: " + getReadRules()); + return msg.toString(); + } + + public Map getForm() { + Map form = new HashMap<>(); + form.put("username", getUsername()); + form.put("age", getAge()); + form.put("player_type", getPlayerType()); + form.put("ever_banned", getEverBanned()); + form.put("ever_banned_explanation", getEverBannedExplanation()); + form.put("reference", getReference()); + form.put("read_rules", getReadRules()); + return form; + } +} diff --git a/src/main/java/xyz/etztech/minecraftmanager/MCMAPI.java b/src/main/java/xyz/etztech/minecraftmanager/MCMAPI.java new file mode 100644 index 0000000..fdf6fe5 --- /dev/null +++ b/src/main/java/xyz/etztech/minecraftmanager/MCMAPI.java @@ -0,0 +1,210 @@ +package xyz.etztech.minecraftmanager; + +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; +import org.apache.commons.lang.StringUtils; +import org.apache.http.HttpEntity; +import org.apache.http.HttpResponse; +import org.apache.http.NameValuePair; +import org.apache.http.client.HttpClient; +import org.apache.http.client.entity.UrlEncodedFormEntity; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.impl.client.HttpClients; +import org.apache.http.message.BasicNameValuePair; +import org.bukkit.Bukkit; + +import java.io.BufferedReader; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.net.URL; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class MCMAPI { + private static String url; + private static String api; + + /** + * Turns on testing mode + * @param url The override Django API URL + * @param api The override Django API password + */ + public static void test(String url, String api) { + MCMAPI.url = url; + MCMAPI.api = api; + } + + + public static JsonArray queryModel(String model, Map filters) { + // Querying a model + String djangoUrl = getDjangoUrl(); + djangoUrl += "model/"; + + try { + String get = GET(djangoUrl + model + "/", filters); + JsonParser jsonParser = new JsonParser(); + return (JsonArray)jsonParser.parse(get); + } catch (Exception ex) { + log("Could not connect to Django. Is the web server running?"); + } + return new JsonArray(); + } + + public static JsonObject postApplication(Application application) { + String djangoUrl = getDjangoUrl() + "plugin/application/"; + String post = POST(djangoUrl, application.getForm()); + JsonParser jsonParser = new JsonParser(); + return (JsonObject) jsonParser.parse(post); + } + + public static JsonObject postApplicationAction(String id, boolean accepted, String username) { + String djangoUrl = getDjangoUrl() + "plugin/application_action/"; + Map data = new HashMap<>(); + data.put("application_id", id); + data.put("action", accepted ? "True" : "False"); + data.put("username", username); + String post = POST(djangoUrl, data); + JsonParser jsonParser = new JsonParser(); + return (JsonObject) jsonParser.parse(post); + } + + public static JsonObject postApplicationClear(String id) { + String djangoUrl = getDjangoUrl() + "plugin/application_clear/"; + Map data = new HashMap<>(); + data.put("application_id", id); + String post = POST(djangoUrl, data); + JsonParser jsonParser = new JsonParser(); + return (JsonObject) jsonParser.parse(post); + } + + public static JsonObject postLogin(String username, String uuid, String ip) { + String djangoUrl = getDjangoUrl() + "plugin/login/"; + Map data = new HashMap<>(); + data.put("username", username); + data.put("uuid", uuid); + data.put("ip", ip); + String post = POST(djangoUrl, data); + JsonParser jsonParser = new JsonParser(); + return (JsonObject) jsonParser.parse(post); + } + + public static JsonObject postTicket(String uuid, String message, String x, String y, String z, String world) { + String djangoUrl = getDjangoUrl() + "plugin/ticket/"; + Map data = new HashMap<>(); + data.put("uuid", uuid); + data.put("message", message); + data.put("x", x); + data.put("y", y); + data.put("z", z); + data.put("world", world); + String post = POST(djangoUrl, data); + JsonParser jsonParser = new JsonParser(); + return (JsonObject) jsonParser.parse(post); + } + + public static JsonObject getPassword(String uuid) { + String djangoUrl = getDjangoUrl() + "plugin/register/"; + Map data = new HashMap<>(); + data.put("uuid", uuid); + String post = POST(djangoUrl, data); + JsonParser jsonParser = new JsonParser(); + return (JsonObject) jsonParser.parse(post); + } + + private static void log(String message) { + try { + Bukkit.getConsoleSender().sendMessage(message); + } catch (Exception ex) { + System.out.println(message); + } + } + + private static String GET(String url) { + return GET(url, new HashMap()); + } + + private static String GET(String url, Map data) { + if (StringUtils.isNotEmpty(MCMAPI.api)) { + data.put("api", MCMAPI.api); + } else { + data.put("api", MinecraftManager.config.getString("django.api")); + } + StringBuffer result = new StringBuffer(); + ArrayList query = new ArrayList<>(); + for (String key : data.keySet()) { + query.add(key + "=" + data.get(key)); + } + String dataQuery = StringUtils.join(query, "&"); + try { + HttpClient client = HttpClients.createDefault(); + HttpGet get = new HttpGet(url + "?" + dataQuery); + HttpResponse response = client.execute(get); + HttpEntity entity = response.getEntity(); + + InputStream input = entity.getContent(); + BufferedReader in = new BufferedReader(new InputStreamReader(input)); + String inputLine; + while ((inputLine = in.readLine()) != null) { + result.append(inputLine); + } + input.close(); + } catch (Exception ex) { + log("GET request failed. (" + url + ")"); + } + + return result.toString(); + } + + private static String POST(String url) { + return POST(url, new HashMap()); + } + + private static String POST(String url, Map data) { + StringBuffer result = new StringBuffer(); + if (StringUtils.isNotEmpty(MCMAPI.api)) { + data.put("api", MCMAPI.api); + } else { + data.put("api", MinecraftManager.config.getString("django.api")); + } + try { + HttpClient client = HttpClients.createDefault(); + HttpPost post = new HttpPost(url); + List params = new ArrayList<>(); + for (String key : data.keySet()) { + params.add(new BasicNameValuePair(key, data.get(key))); + } + post.setEntity(new UrlEncodedFormEntity(params, "UTF-8")); + HttpResponse response = client.execute(post); + HttpEntity entity = response.getEntity(); + + InputStream input = entity.getContent(); + BufferedReader in = new BufferedReader(new InputStreamReader(input)); + String inputLine; + while ((inputLine = in.readLine()) != null) { + result.append(inputLine); + } + input.close(); + } catch (Exception ex) { + log("POST request failed. (" + url + ")"); + } + + return result.toString(); + } + + /** + * @return The Django API URL ending with a slash + */ + private static String getDjangoUrl() { + if (StringUtils.isNotEmpty(MCMAPI.url)) { + return MCMAPI.url; + } else { + String configUrl = MinecraftManager.config.getString("django.url"); + return configUrl.endsWith("/") ? configUrl : configUrl + "/"; + } + } +} diff --git a/src/main/java/xyz/etztech/minecraftmanager/MCMResponse.java b/src/main/java/xyz/etztech/minecraftmanager/MCMResponse.java new file mode 100644 index 0000000..9e8ab51 --- /dev/null +++ b/src/main/java/xyz/etztech/minecraftmanager/MCMResponse.java @@ -0,0 +1,58 @@ +package xyz.etztech.minecraftmanager; + +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import org.bukkit.ChatColor; + +public class MCMResponse { + private Boolean status; + private String message; + private JsonElement extra; + + public MCMResponse(JsonArray httpResponse) { + JsonObject json = httpResponse.get(0).getAsJsonObject(); + setStatus(json.get("status").getAsBoolean()); + setMessage(json.get("message").getAsString()); + setExtra(json.get("extra")); + } + + public MCMResponse(JsonObject httpResponse) { + setStatus(httpResponse.get("status").getAsBoolean()); + setMessage(httpResponse.get("message").getAsString()); + setExtra(httpResponse.get("extra")); + } + + public Boolean getStatus() { + return status; + } + + public void setStatus(Boolean status) { + this.status = status; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + + public JsonElement getExtra() { + return extra; + } + + public void setExtra(JsonElement extra) { + this.extra = extra; + } + + public String getMCMessage() { + if (status) { + return ChatColor.GREEN + message; + } else { + return ChatColor.RED + message; + } + } + +} diff --git a/src/main/java/xyz/etztech/minecraftmanager/MCMUtil.java b/src/main/java/xyz/etztech/minecraftmanager/MCMUtil.java new file mode 100644 index 0000000..d79323f --- /dev/null +++ b/src/main/java/xyz/etztech/minecraftmanager/MCMUtil.java @@ -0,0 +1,84 @@ +package xyz.etztech.minecraftmanager; + +import net.md_5.bungee.api.chat.ComponentBuilder; +import net.md_5.bungee.api.chat.HoverEvent; +import net.md_5.bungee.api.chat.ClickEvent; +import net.md_5.bungee.api.chat.TextComponent; +import org.apache.commons.lang.StringUtils; +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.entity.Player; + +import java.io.FileWriter; +import java.io.PrintWriter; +import java.text.SimpleDateFormat; +import java.util.Date; + +public class MCMUtil { + private static FileWriter globalFile; + public static PrintWriter globalLog; + private static FileWriter staffFile; + public static PrintWriter staffLog; + + public static void init() { + MinecraftManager plugin = (MinecraftManager) Bukkit.getPluginManager().getPlugin("MinecraftManager"); + String pluginPath = plugin.getDataFolder().getAbsolutePath(); + String globalPath = pluginPath + "/logs/global.log"; + try { + globalFile = new FileWriter(globalPath, true); + globalLog = new PrintWriter(globalFile); + } catch (Exception e) { + plugin.log("Could not connect to global log (" + globalPath + ")."); + } + if (plugin.getConfig().getBoolean("staff-chat.enabled")) { + String staffPath = pluginPath + "/logs/staff.log"; + try { + staffFile = new FileWriter(staffPath, true); + staffLog = new PrintWriter(staffFile); + } catch (Exception e) { + plugin.log("Could not connect to staff log (" + staffPath + ")."); + } + } + } + + public static void staffMessage(String message) { + staffMessage(message, null); + } + + public static void staffMessage(String message, String command) { + log(staffLog, message); + HoverEvent hover = new HoverEvent(HoverEvent.Action.SHOW_TEXT, new ComponentBuilder("Staff Chat").create()); + TextComponent text = new TextComponent(message); + text.setHoverEvent(hover); + if (StringUtils.isNotEmpty(command)) { + text.setClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, command)); + } + for (Player player : Bukkit.getServer().getOnlinePlayers()) { + if (player.hasPermission("minecraftmanager.staff")) { + player.spigot().sendMessage(text); + } + } + } + + public static void globalMessage(String message) { + log(globalLog, message); + for (Player player : Bukkit.getServer().getOnlinePlayers()) { + player.sendMessage(message); + } + } + + public static void log(PrintWriter logger, String message) { + try { + //[4/21/17 7:12 PM] + //Bukkit.getServer().getConsoleSender().sendMessage(message); + message = ChatColor.stripColor(message); + Date date = new Date(); + SimpleDateFormat sdf = new SimpleDateFormat("M/d/yy hh:mm a"); + String text = "[" + sdf.format(date) + "] " + message; + logger.append(text + "\n"); + logger.flush(); + } catch (Exception ex) { + Bukkit.getServer().getConsoleSender().sendMessage("Could not log message! Check your log files!"); + } + } +} diff --git a/src/main/java/xyz/etztech/minecraftmanager/MinecraftManager.java b/src/main/java/xyz/etztech/minecraftmanager/MinecraftManager.java new file mode 100644 index 0000000..a2a4420 --- /dev/null +++ b/src/main/java/xyz/etztech/minecraftmanager/MinecraftManager.java @@ -0,0 +1,148 @@ +package xyz.etztech.minecraftmanager; + +import org.bukkit.Bukkit; +import org.bukkit.configuration.file.FileConfiguration; +import org.bukkit.plugin.java.JavaPlugin; +import xyz.etztech.minecraftmanager.command.*; +import xyz.etztech.minecraftmanager.listeners.AsyncPlayerChatListener; +import xyz.etztech.minecraftmanager.listeners.BlockBreakListener; +import xyz.etztech.minecraftmanager.listeners.SessionListener; + +import java.io.File; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.logging.Logger; + +public class MinecraftManager extends JavaPlugin { + + public static MinecraftManager instance; + + public static FileConfiguration config; + private Logger log = Logger.getLogger( "Minecraft" ); + private static Map applyMode = new HashMap<>(); + private static Map applyQuestion = new HashMap<>(); + private static Map applications = new HashMap<>(); + private static List diamonds = new ArrayList<>(); + + // Objects that can be reloaded + AsyncPlayerChatListener chatListener; + CommandRules cmdRules; + + + + @Override + public void onEnable() { + + instance = this; + saveDefaultConfig(); + loadConfig(); + + // Create log directory if it doesn't exist + new File(getDataFolder().getAbsolutePath() + "/logs/").mkdir(); + + if (isEnabled()) { + + // Add Commands + CommandMain cmdMain = new CommandMain(this); + this.getCommand("minecraftmanager").setExecutor(cmdMain); + cmdMain.startThread(); + CommandApplication cmdApplication = new CommandApplication(this); + this.getCommand("application").setExecutor(cmdApplication); + CommandApply cmdApply = new CommandApply(this); + this.getCommand("apply").setExecutor(cmdApply); + CommandTicket cmdTicket = new CommandTicket(this); + this.getCommand("ticket").setExecutor(cmdTicket); + + // Rules is optional + if (getConfig().getBoolean("rules.enabled")) { + cmdRules = new CommandRules(this); + this.getCommand("rules").setExecutor(cmdRules); + } + + // Add Listeners + chatListener = new AsyncPlayerChatListener(this); + getServer().getPluginManager().registerEvents(chatListener, this); + SessionListener sessionListener = new SessionListener(this); + getServer().getPluginManager().registerEvents(sessionListener, this); + BlockBreakListener blockBreakListener = new BlockBreakListener(this); + getServer().getPluginManager().registerEvents(blockBreakListener, this); + + Bukkit.getConsoleSender().sendMessage("MinecraftManager has started successfully."); + } + } + + @Override + public void onDisable() { + + } + + public void loadConfig() { + config = Bukkit.getPluginManager().getPlugin("MinecraftManager").getConfig(); + } + + @Override + public void reloadConfig() { + super.reloadConfig(); + loadConfig(); + if (chatListener != null) { + chatListener.reload(); + } + if (cmdRules != null) { + cmdRules.reload(); + } + } + + + + public void log(String message) { + log.info( "[MinecraftManager]: " + message ); + } + + public static Boolean inApplyMode(String uuid) { + if (applyMode.containsKey(uuid)) { + return applyMode.get(uuid); + } + return false; + } + + public static void setApplyMode(String uuid, Boolean inApplyMode) { + applyMode.put(uuid, inApplyMode); + } + + public static Question getApplyQuestion(String uuid) { + if (applyQuestion.containsKey(uuid)) { + return applyQuestion.get(uuid); + } + return Question.ONE; + } + + public static void setApplyQuestion(String uuid, Question question) { + if (Question.COMPLETE == question) { + applyQuestion.remove(uuid); + } else { + applyQuestion.put(uuid, question); + } + } + + public static Application getApplication(String uuid) { + if (applications.containsKey(uuid)) { + return applications.get(uuid); + } + return new Application(); + } + + public static void setApplication(String uuid, Application application) { + applications.put(uuid, application); + } + + public static boolean addDiamond(String location) { + if (diamonds.contains(location)) { + return false; + } + diamonds.add(location); + return true; + } +} + diff --git a/src/main/java/xyz/etztech/minecraftmanager/MinecraftManagerThread.java b/src/main/java/xyz/etztech/minecraftmanager/MinecraftManagerThread.java new file mode 100644 index 0000000..ab09c48 --- /dev/null +++ b/src/main/java/xyz/etztech/minecraftmanager/MinecraftManagerThread.java @@ -0,0 +1,141 @@ +package xyz.etztech.minecraftmanager; + +import org.apache.commons.lang.StringUtils; +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.entity.Player; +import org.bukkit.scheduler.BukkitScheduler; + +import java.io.BufferedReader; +import java.io.InputStreamReader; +import java.net.InetAddress; +import java.net.ServerSocket; +import java.net.Socket; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +public class MinecraftManagerThread extends Thread { + private boolean running = true; + + private MinecraftManager plugin; + + public MinecraftManagerThread(MinecraftManager plugin) {this.plugin = plugin;} + + public boolean getRunning() { + return running; + } + + public void setRunning(boolean running) { + this.running = running; + } + + + public void run() { + List commands = Arrays.asList("application", "accept", "deny", "global", "staff"); + try { + ServerSocket cmdSock = new ServerSocket(this.plugin.getConfig().getInt("port"), 0, InetAddress.getByName(null)); + while (getRunning()) { + Socket data = cmdSock.accept(); + BufferedReader myInput = new BufferedReader(new InputStreamReader(data.getInputStream())); + + String buf = myInput.readLine(); + + if (buf != null) { + String[] input = buf.split(" "); + String base = input[0]; + ArrayList args = new ArrayList<>(); + if (input.length > 1) { + args = new ArrayList<>(Arrays.asList(buf.split(" "))); + args.remove(0); + } + if (commands.contains(base)) { + switch (base) { + case "application": + application(args.get(0), args.get(1)); + break; + case "accept": + action(args.get(0), true); + break; + case "deny": + action(args.get(0), false); + break; + case "global": + globalChat(args); + break; + case "staff": + staffChat(args); + break; + default: + Bukkit.getConsoleSender().sendMessage("Input not recognized, ignoring."); + break; + } + } + } + } + Bukkit.getConsoleSender().sendMessage("Closing MinecraftManager on Port " + this.plugin.getConfig().get("port")); + cmdSock.close(); + } catch (Exception ex) { + Bukkit.getConsoleSender().sendMessage("Error: " + ex.getMessage()); + } + } + + private void application(String username, String id) { + String message = ChatColor.GREEN + "New application #" + id + " from " + username; + MCMUtil.staffMessage(message); + } + + public static void action(final String username, boolean accepted) { + String path = accepted ? "accept" : "deny"; + String message = MinecraftManager.config.getString(path + ".message").replace("", username); + message = ChatColor.translateAlternateColorCodes('&', message); + Player online = null; + for (Player player : Bukkit.getServer().getOnlinePlayers()) { + if (username.equalsIgnoreCase(player.getName())) { + online = player; + player.sendMessage(message); + break; + } + } + + if (online != null) { + // Set their group + String engine = MinecraftManager.config.getString("permissions.engine"); + String promote = MinecraftManager.config.getString("permissions.promote"); + if ("permissionsex".equalsIgnoreCase(engine)) { + runTask("pex user group set " + promote, username); + } else if ("luckperms".equalsIgnoreCase(engine)) { + runTask("lp user group set " + promote, username); + } + + // Run misc commands + List commands = MinecraftManager.config.getStringList(path + ".commands"); + for (final String command : commands) { + runTask(command, username); + } + } + } + + private static void runTask(final String command, final String username) { + Bukkit.getScheduler().runTask(MinecraftManager.instance, new Runnable() { + @Override + public void run() { + Bukkit.dispatchCommand(Bukkit.getConsoleSender(), command.replace("", username)); + } + }); + } + + + private void globalChat(ArrayList args) { + String name = args.get(0); + args.remove(0); + MCMUtil.globalMessage("[MCM] " + name + " > " + StringUtils.join(args, " ")); + } + + private void staffChat(ArrayList args) { + String name = args.get(0); + args.remove(0); + MCMUtil.staffMessage(ChatColor.GOLD + "[MCM] " + name + " > " + ChatColor.GREEN + StringUtils.join(args, " ")); + } + +} diff --git a/src/main/java/xyz/etztech/minecraftmanager/Question.java b/src/main/java/xyz/etztech/minecraftmanager/Question.java new file mode 100644 index 0000000..5e806aa --- /dev/null +++ b/src/main/java/xyz/etztech/minecraftmanager/Question.java @@ -0,0 +1,81 @@ +package xyz.etztech.minecraftmanager; + +import org.apache.commons.lang.StringUtils; + +public enum Question { + + ONE("How old are you?", "Your answer must be numeric."), + TWO("What type of player are you?", "Your answer must be under 300 characters long."), + THREE1("Have you ever been banned? Please answer just 'yes' or 'no'.", "Your answer must be just 'yes' or 'no'."), + THREE2("Oof. That's okay, it's happened to plenty of people. Do you mind letting us know why?", "Your answer must be under 300 characters long."), + FOUR("Were you referred to our server by someone?", "Your answer must be under 50 characters long."), + FIVE("Have you read the rules thoroughly?", "Are you sure? Maybe you should read them again..."), + COMPLETE("All done! Staff should be reviewing your application any second now!", ""); + + private String question; + private String error; + + Question(String s, String e) { + question = s; + error = e; + } + + + public String getQuestion() { + return question; + } + + public String getError() { + return error; + } + + public static Question last(Question question) { + if (question == TWO) { + return ONE; + } else if (question == THREE1) { + return TWO; + } else if (question == THREE2) { + return THREE1; + } else if (question == FOUR) { + return THREE2; + } else { + return FOUR; + } + } + + public static Question next(Question question, String answer) { + if (question == ONE) { + return TWO; + } else if (question == TWO) { + return THREE1; + } else if (question == THREE1) { + return answer.equalsIgnoreCase("yes") ? THREE2 : FOUR; + } else if (question == THREE2) { + return FOUR; + } else if (question == FOUR) { + return FIVE; + } else { + return COMPLETE; + } + } + + public static boolean validate(Question question, String answer) { + if (question == ONE) { + return StringUtils.isNumeric(answer); + } else if (question == TWO) { + return answer.length() <= 300; + } else if (question == THREE1) { + return answer.equalsIgnoreCase("yes") || answer.equalsIgnoreCase("no"); + } else if (question == THREE2) { + return answer.length() <= 300; + } else if (question == FOUR) { + return answer.length() <= 50; + } else if (question == FIVE) { + String a = MinecraftManager.config.getString("rules.application.answer"); + return answer.equalsIgnoreCase(a); + } + return false; + } + + +} diff --git a/src/main/java/xyz/etztech/minecraftmanager/command/CommandApplication.java b/src/main/java/xyz/etztech/minecraftmanager/command/CommandApplication.java new file mode 100644 index 0000000..e016c56 --- /dev/null +++ b/src/main/java/xyz/etztech/minecraftmanager/command/CommandApplication.java @@ -0,0 +1,200 @@ +package xyz.etztech.minecraftmanager.command; + +import com.google.gson.JsonArray; +import com.google.gson.JsonObject; +import com.google.gson.JsonElement; +import net.md_5.bungee.api.chat.ClickEvent; +import net.md_5.bungee.api.chat.ComponentBuilder; +import net.md_5.bungee.api.chat.HoverEvent; +import net.md_5.bungee.api.chat.TextComponent; +import org.apache.commons.lang.StringUtils; +import org.bukkit.ChatColor; +import org.bukkit.command.Command; +import org.bukkit.command.CommandExecutor; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import xyz.etztech.minecraftmanager.MCMAPI; +import xyz.etztech.minecraftmanager.MCMResponse; +import xyz.etztech.minecraftmanager.MinecraftManager; +import xyz.etztech.minecraftmanager.MinecraftManagerThread; + +import javax.xml.soap.Text; +import java.awt.*; +import java.util.HashMap; +import java.util.Map; + +public class CommandApplication implements CommandExecutor { + + MinecraftManager plugin; + + public CommandApplication(MinecraftManager plugin) { + this.plugin = plugin; + } + + @Override + public boolean onCommand(CommandSender sender, Command command, String base, String[] args) { + + if (args.length != 2) { + sender.sendMessage(ChatColor.RED + "This command takes two arguments."); + return true; + } + String subcommand = args[0].toLowerCase(); + switch (subcommand) { + case "search": + search(sender, args[1]); + break; + case "info": + info(sender, args[1]); + break; + case "accept": + action(sender, args[1], true); + break; + case "deny": + action(sender, args[1], false); + break; + case "clear": + clear(sender, args[1]); + break; + default: + sender.sendMessage(ChatColor.RED + "Unknown sub-command. You can search, accept, or deny applications."); + break; + } + + + return true; + } + + private void search(CommandSender sender, String name) { + if (sender.hasPermission("minecraftmanager.application.search")) { + Map filter = new HashMap<>(); + filter.put("username__icontains", name); + JsonArray results = MCMAPI.queryModel("application", filter); + StringBuffer response = new StringBuffer(); + if (results.size() > 0) { + response.append(ChatColor.GOLD).append("===== Results ====="); + int max = results.size() >= 10 ? 10 : results.size(); + for (int i = 0; i < max; i++) { + JsonObject result = results.get(i).getAsJsonObject(); + response.append("\n").append(ChatColor.YELLOW).append("#") + .append(result.get("id")).append(" - ").append(result.get("username").getAsString()); + } + if (results.size() > 10) { + response.append("\n").append(ChatColor.YELLOW).append("This search returned more than ten results. " + + "Try to refine your search if you didn't find what you needed."); + } + } else { + response.append(ChatColor.YELLOW).append("No results found..."); + } + + sender.sendMessage(response.toString()); + } else { + sender.sendMessage(ChatColor.RED + "You do not have permission to search applications."); + } + } + + private String getAsStringOrNull(JsonElement json) { + if (json.isJsonNull()) { + return "None"; + } else { + return json.getAsString(); + } + } + + private void info(CommandSender sender, String key) { + if (sender.hasPermission("minecraftmanager.application.search")) { + Map filter = new HashMap<>(); + if (StringUtils.isNumeric(key)) { + filter.put("id__exact", key); + } else { + filter.put("username__iexact", key); + } + JsonArray results = MCMAPI.queryModel("application", filter); + StringBuffer response = new StringBuffer(); + TextComponent text = new TextComponent(); + if (results.size() == 1) { + JsonObject result = results.get(0).getAsJsonObject(); + response.append(ChatColor.GOLD).append("===== " + result.get("username").getAsString() + " ====="); + response.append("\n").append(ChatColor.RESET).append(ChatColor.YELLOW).append(ChatColor.BOLD); + response.append("Application ID: "); + response.append(ChatColor.RESET); + response.append(getAsStringOrNull(result.get("id"))); + response.append("\n").append(ChatColor.RESET).append(ChatColor.YELLOW).append(ChatColor.BOLD); + response.append("Age: "); + response.append(ChatColor.RESET); + response.append(getAsStringOrNull(result.get("age"))); + response.append("\n").append(ChatColor.RESET).append(ChatColor.YELLOW).append(ChatColor.BOLD); + response.append("Player Type: "); + response.append(ChatColor.RESET); + response.append(getAsStringOrNull(result.get("player_type"))); + response.append("\n").append(ChatColor.RESET).append(ChatColor.YELLOW).append(ChatColor.BOLD); + response.append("Ever Banned: "); + response.append(ChatColor.RESET); + response.append(getAsStringOrNull(result.get("ever_banned"))); + response.append("\n").append(ChatColor.RESET).append(ChatColor.YELLOW).append(ChatColor.BOLD); + response.append("Explanation: "); + response.append(ChatColor.RESET); + response.append(getAsStringOrNull(result.get("ever_banned_explanation"))); + response.append("\n").append(ChatColor.RESET).append(ChatColor.YELLOW).append(ChatColor.BOLD); + response.append("Reference: "); + response.append(ChatColor.RESET); + response.append(getAsStringOrNull(result.get("reference"))); + response.append("\n").append(ChatColor.RESET).append(ChatColor.YELLOW).append(ChatColor.BOLD); + response.append("Read Rules: "); + response.append(ChatColor.RESET); + response.append(getAsStringOrNull(result.get("read_rules"))); + response.append("\n").append(ChatColor.RESET).append(ChatColor.YELLOW).append(ChatColor.BOLD); + response.append("Accepted: "); + response.append(ChatColor.RESET); + response.append(result.get("accepted").isJsonNull() ? "Unanswered" : result.get("accepted").getAsString()); + response.append("\n").append(ChatColor.RESET).append(ChatColor.GOLD).append(ChatColor.ITALIC); + response.append("More info can be found on the MCM web app."); + text.setText(response.toString()); + text.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new ComponentBuilder("Click for more info").create())); + text.setClickEvent(new ClickEvent(ClickEvent.Action.OPEN_URL, result.get("link").getAsString())); + } else { + response.append(ChatColor.RED).append("Could not identify an application."); + text.setText(response.toString()); + } + + sender.spigot().sendMessage(text); + } else { + sender.sendMessage(ChatColor.RED + "You do not have permission to search applications."); + } + } + + + private void action(CommandSender sender, String id, boolean accepted) { + if (sender.hasPermission("minecraftmanager.application.action")) { + String username; + if (sender instanceof Player) { + username = sender.getName(); + } else { + username = "Console"; + } + if (StringUtils.isNumeric(id)) { + MCMResponse response = new MCMResponse(MCMAPI.postApplicationAction(id, accepted, username)); + sender.sendMessage(response.getMCMessage()); + } else { + sender.sendMessage(ChatColor.RED + "You must use an application ID to ensure accuracy."); + } + } else { + sender.sendMessage(ChatColor.RED + "You do not have permission to take action on an application."); + } + } + + private void clear(CommandSender sender, String id) { + if (sender.hasPermission("minecraftmanager.application.action")) { + if (StringUtils.isNumeric(id)) { + MCMResponse response = new MCMResponse(MCMAPI.postApplicationClear(id)); + sender.sendMessage(ChatColor.GREEN + response.getMCMessage()); + } else { + sender.sendMessage(ChatColor.RED + "You must use an application ID to ensure accuracy."); + } + } else { + sender.sendMessage(ChatColor.RED + "You do not have permission to take action on an application."); + } + } + + + +} diff --git a/src/main/java/xyz/etztech/minecraftmanager/command/CommandApply.java b/src/main/java/xyz/etztech/minecraftmanager/command/CommandApply.java new file mode 100644 index 0000000..10f216d --- /dev/null +++ b/src/main/java/xyz/etztech/minecraftmanager/command/CommandApply.java @@ -0,0 +1,47 @@ +package xyz.etztech.minecraftmanager.command; + +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.command.Command; +import org.bukkit.command.CommandExecutor; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import xyz.etztech.minecraftmanager.MinecraftManager; +import xyz.etztech.minecraftmanager.MinecraftManagerThread; + +import java.io.DataOutputStream; +import java.io.IOException; +import java.net.Socket; + +public class CommandApply implements CommandExecutor { + + MinecraftManager plugin; + + public CommandApply(MinecraftManager plugin) { + this.plugin = plugin; + } + + @Override + public boolean onCommand(CommandSender sender, Command command, String base, String[] args) { + if (!(sender instanceof Player)) { + sender.sendMessage(ChatColor.RED + "The console cannot fill out an application."); + return true; + } + Player player = (Player) sender; + if (sender.hasPermission("minecraftmanager.apply")) { + boolean inApplyMode = MinecraftManager.inApplyMode(player.getUniqueId().toString()); + if (!inApplyMode) { + MinecraftManager.setApplyMode(player.getUniqueId().toString(), true); + sender.sendMessage(ChatColor.GREEN + "Entering apply mode. Say \"stop\" in chat to pause your application, or say \"last\" in chat to go to the previous question."); + sender.sendMessage(ChatColor.GREEN + MinecraftManager.getApplyQuestion(player.getUniqueId().toString()).getQuestion()); + } else { + sender.sendMessage(ChatColor.RED + "You are already applying. Say \"stop\" in chat to pause your application."); + } + } else { + sender.sendMessage(ChatColor.RED + "You do not have permission to apply."); + } + + return true; + } + +} diff --git a/src/main/java/xyz/etztech/minecraftmanager/command/CommandMain.java b/src/main/java/xyz/etztech/minecraftmanager/command/CommandMain.java new file mode 100644 index 0000000..4ec9965 --- /dev/null +++ b/src/main/java/xyz/etztech/minecraftmanager/command/CommandMain.java @@ -0,0 +1,143 @@ +package xyz.etztech.minecraftmanager.command; + +import net.md_5.bungee.api.chat.ClickEvent; +import net.md_5.bungee.api.chat.TextComponent; +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.command.Command; +import org.bukkit.command.CommandExecutor; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import xyz.etztech.minecraftmanager.MCMAPI; +import xyz.etztech.minecraftmanager.MCMResponse; +import xyz.etztech.minecraftmanager.MinecraftManager; +import xyz.etztech.minecraftmanager.MinecraftManagerThread; + +import javax.xml.soap.Text; +import java.io.DataOutputStream; +import java.io.IOException; +import java.net.Socket; + +public class CommandMain implements CommandExecutor { + + MinecraftManager plugin; + + private MinecraftManagerThread cmdThread; + + public CommandMain(MinecraftManager plugin) { + this.plugin = plugin; + this.cmdThread = new MinecraftManagerThread(plugin); + } + + @Override + public boolean onCommand(CommandSender sender, Command command, String base, String[] args) { + if (args.length == 0) { + other(sender); + } else if (args.length == 1) { + switch (args[0].toLowerCase()) { + case "help": + sender.sendMessage(ChatColor.GOLD + "----- MinecraftManager Commands -----"); + sender.sendMessage(ChatColor.YELLOW + "/mcm reload - Reload the config"); + sender.sendMessage(ChatColor.YELLOW + "/mcm port - Display the port MinecraftManager is on"); + sender.sendMessage(ChatColor.YELLOW + "/mcm register - Register for the web application"); + sender.sendMessage(ChatColor.GOLD + "----- Application Command -----"); + sender.sendMessage(ChatColor.YELLOW + "/application [accept|deny] "); + sender.sendMessage(ChatColor.YELLOW + "/application [search|info] "); + break; + case "port": + port(sender); + break; + case "reload": + reload(sender); + break; + case "register": + register(sender); + break; + default: + other(sender); + } + } + + return true; + } + + private void other(CommandSender sender) { + String version = Bukkit.getPluginManager().getPlugin("MinecraftManager").getDescription().getVersion(); + sender.sendMessage(ChatColor.GOLD + "----- MinecraftManager v" + version + " -----"); + sender.sendMessage(ChatColor.YELLOW + "Developed by EtzTech"); + sender.sendMessage(ChatColor.YELLOW + "Use \"/mcm help\" for help."); + } + + private void port(CommandSender sender) { + if (!sender.hasPermission("minecraftmanager.use")) { + sender.sendMessage(ChatColor.RED + "You do not have permission to use this command."); + return; + } + sender.sendMessage("MinecraftManager is listening on port " + plugin.getConfig().getInt("port")); + } + + private void reload(CommandSender sender) { + if (!sender.hasPermission("minecraftmanager.use")) { + sender.sendMessage(ChatColor.RED + "You do not have permission to use this command."); + return; + } + try { + sender.sendMessage("Reloading MinecraftManager..."); + stopThread(); + Thread.sleep(1000); + this.plugin.reloadConfig(); + Thread.sleep(1000); + startThread(); + sender.sendMessage("MinecraftManager reloaded."); + } catch (Exception ex) { + sender.sendMessage("MinecraftManager reload was interrupted."); + } + } + + private void register(CommandSender sender) { + if (!(sender instanceof Player)) { + sender.sendMessage(ChatColor.RED + "Console cannot register for the web application."); + return; + } + + if (!sender.hasPermission("minecraftmanager.register")) { + sender.sendMessage(ChatColor.RED + "You do not have permission to register for the web application."); + return; + } + + Player player = (Player) sender; + MCMResponse response = new MCMResponse(MCMAPI.getPassword(player.getUniqueId().toString())); + if (response.getStatus()) { + TextComponent password = new TextComponent(ChatColor.YELLOW + response.getMessage()); + password.setClickEvent(new ClickEvent(ClickEvent.Action.SUGGEST_COMMAND, response.getMessage())); + TextComponent message = new TextComponent(ChatColor.GREEN + "Your password is "); + message.addExtra(password); + message.addExtra(new TextComponent(ChatColor.GREEN + ".")); + player.spigot().sendMessage(message); + player.sendMessage(ChatColor.GREEN + "This password is not shown in Console, however you should consider changing it immediately from the web application."); + player.sendMessage(ChatColor.GREEN + "You can click the password to bring it into your chat for easy copying."); + } else { + player.sendMessage(ChatColor.RED + response.getMessage()); + } + } + + public void startThread() { + Bukkit.getConsoleSender().sendMessage("Starting MinecraftManager on Port " + plugin.getConfig().get("port")); + cmdThread.setRunning(true); + Thread th = new Thread(cmdThread); + th.start(); + } + + public void stopThread() { + cmdThread.setRunning(false); + try { + Socket trashSock = new Socket("127.0.0.1", plugin.getConfig().getInt("port")); + DataOutputStream trashStream = new DataOutputStream(trashSock.getOutputStream()); + trashStream.writeUTF("trash"); + trashStream.flush(); + trashStream.close(); + } catch (IOException ex) { + Bukkit.getConsoleSender().sendMessage("Error: " + ex.getMessage()); + } + } +} diff --git a/src/main/java/xyz/etztech/minecraftmanager/command/CommandRules.java b/src/main/java/xyz/etztech/minecraftmanager/command/CommandRules.java new file mode 100644 index 0000000..2ccb258 --- /dev/null +++ b/src/main/java/xyz/etztech/minecraftmanager/command/CommandRules.java @@ -0,0 +1,52 @@ +package xyz.etztech.minecraftmanager.command; + +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.command.Command; +import org.bukkit.command.CommandExecutor; +import org.bukkit.command.CommandSender; +import xyz.etztech.minecraftmanager.MinecraftManager; +import xyz.etztech.minecraftmanager.MinecraftManagerThread; + +import java.io.DataOutputStream; +import java.io.IOException; +import java.net.Socket; +import java.util.List; + +public class CommandRules implements CommandExecutor { + + MinecraftManager plugin; + String rules; + + + public CommandRules(MinecraftManager plugin) { + this.plugin = plugin; + + reload(); + } + + public void reload() { + List rules = this.plugin.getConfig().getStringList("rules.rules"); + if (this.plugin.getConfig().getBoolean("rules.application.validate")) { + String finalAnswer = this.plugin.getConfig().getString("rules.application.answer"); + rules.add("The answer for the final question is \"" + finalAnswer + "\""); + } + StringBuilder rulesMessage = new StringBuilder(ChatColor.GOLD + "===== Rules ====="); + for (int i = 0; i < rules.size(); i++) { + rulesMessage.append("\n" + ChatColor.YELLOW + (i + 1) + ". " + rules.get(i)); + } + this.rules = rulesMessage.toString(); + } + + + @Override + public boolean onCommand(CommandSender sender, Command command, String base, String[] args) { + + sender.sendMessage(this.rules); + + return true; + } + + + +} diff --git a/src/main/java/xyz/etztech/minecraftmanager/command/CommandTicket.java b/src/main/java/xyz/etztech/minecraftmanager/command/CommandTicket.java new file mode 100644 index 0000000..821ac0f --- /dev/null +++ b/src/main/java/xyz/etztech/minecraftmanager/command/CommandTicket.java @@ -0,0 +1,59 @@ +package xyz.etztech.minecraftmanager.command; + +import org.apache.commons.lang.StringUtils; +import org.bukkit.ChatColor; +import org.bukkit.Location; +import org.bukkit.World; +import org.bukkit.command.Command; +import org.bukkit.command.CommandExecutor; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import xyz.etztech.minecraftmanager.MCMAPI; +import xyz.etztech.minecraftmanager.MCMResponse; +import xyz.etztech.minecraftmanager.MinecraftManager; + +public class CommandTicket implements CommandExecutor { + + MinecraftManager plugin; + + public CommandTicket(MinecraftManager plugin) { + this.plugin = plugin; + } + + @Override + public boolean onCommand(CommandSender sender, Command command, String base, String[] args) { + if (!(sender instanceof Player)) { + sender.sendMessage(ChatColor.RED + "The console cannot submit tickets."); + return true; + } + Player player = (Player) sender; + if (sender.hasPermission("minecraftmanager.ticket")) { + if (args.length == 0) { + sender.sendMessage(ChatColor.RED + "You cannot send a ticket with no message."); + return true; + } + Location location = player.getLocation(); + String x = String.valueOf(location.getBlockX()); + String y = String.valueOf(location.getBlockY()); + String z = String.valueOf(location.getBlockZ()); + World.Environment env = location.getWorld().getEnvironment(); + String world = ""; + if (World.Environment.NORMAL == env) { + world = "O"; + } else if (World.Environment.NETHER == env) { + world = "N"; + } else if (World.Environment.THE_END == env) { + world = "E"; + } + MCMResponse response = new MCMResponse(MCMAPI.postTicket(player.getUniqueId().toString(), + StringUtils.join(args, " "), x, y, z, world)); + sender.sendMessage(response.getMCMessage()); + } else { + sender.sendMessage(ChatColor.RED + "You do not have permission to submit a ticket."); + sender.sendMessage(ChatColor.RED + "If you were submitting a ticket about not being able to submit a ticket, that is known as irony."); + } + + return true; + } + +} diff --git a/src/main/java/xyz/etztech/minecraftmanager/listeners/AsyncPlayerChatListener.java b/src/main/java/xyz/etztech/minecraftmanager/listeners/AsyncPlayerChatListener.java new file mode 100644 index 0000000..59b6277 --- /dev/null +++ b/src/main/java/xyz/etztech/minecraftmanager/listeners/AsyncPlayerChatListener.java @@ -0,0 +1,158 @@ +package xyz.etztech.minecraftmanager.listeners; + +import net.md_5.bungee.api.chat.BaseComponent; +import net.md_5.bungee.api.chat.ComponentBuilder; +import net.md_5.bungee.api.chat.HoverEvent; +import net.md_5.bungee.api.chat.TextComponent; +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.configuration.file.FileConfiguration; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; +import org.bukkit.event.player.AsyncPlayerChatEvent; +import xyz.etztech.minecraftmanager.*; + +import java.io.FileWriter; +import java.io.PrintWriter; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import java.util.regex.Pattern; + +public class AsyncPlayerChatListener implements Listener { + + private MinecraftManager plugin; + private List staffPrefixes; + + public AsyncPlayerChatListener(MinecraftManager minecraftManager) { + this.plugin = minecraftManager; + reload(); + MCMUtil.init(); + } + + public void reload() { + this.staffPrefixes = new ArrayList<>(); + this.staffPrefixes.addAll(trimmed(this.plugin.getConfig().getStringList("staff-chat.prefix"))); + } + + @EventHandler(priority=EventPriority.HIGHEST, ignoreCancelled=true) + public void onChat(AsyncPlayerChatEvent event) { + + Player sender = event.getPlayer(); + String chat = event.getMessage(); + boolean staffChat = isStaffChat(sender, chat); + boolean applyChat = MinecraftManager.inApplyMode(sender.getUniqueId().toString()); + + TextComponent pre = new TextComponent(ChatColor.GOLD + sender.getName() + " > "); + if (!applyChat) { + if (staffChat) { + event.setCancelled(true); + for (String prefix : this.staffPrefixes) { + chat = chat.replaceFirst(Pattern.quote(prefix), ""); + } + HoverEvent hover = new HoverEvent(HoverEvent.Action.SHOW_TEXT, new ComponentBuilder("Staff Chat").create()); + pre.setHoverEvent(hover); + TextComponent message = generateMessage(chat); + message.setHoverEvent(hover); + for (Player player : event.getRecipients()) { + if (player.hasPermission("minecraftmanager.staff")) { + player.spigot().sendMessage(pre, message); + } + } + MCMUtil.log(MCMUtil.staffLog, componentText(pre, message)); + } else { + TextComponent message = generateMessage(chat); + MCMUtil.log(MCMUtil.globalLog, componentText(pre, message)); + } + } else { + // Applying + event.setCancelled(true); + + Question applyQuestion = MinecraftManager.getApplyQuestion(sender.getUniqueId().toString()); + if ("stop".equalsIgnoreCase(chat)) { + // Pause application + MinecraftManager.setApplyMode(sender.getUniqueId().toString(), false); + sender.sendMessage(ChatColor.GREEN + "Exiting apply mode. Use \"/apply\" to return to your application."); + } else if ("last".equalsIgnoreCase(chat)) { + // Previous question + if (Question.ONE == applyQuestion) { + sender.sendMessage(ChatColor.RED + "This is the first question you ding dong. Say \"stop\" in chat to pause your application."); + } else { + Question lastQuestion = Question.last(applyQuestion); + MinecraftManager.setApplyQuestion(sender.getUniqueId().toString(), lastQuestion); + sender.sendMessage(ChatColor.GREEN + lastQuestion.getQuestion()); + } + } else { + // Answering question + boolean valid = Question.validate(applyQuestion, chat); + boolean rules = this.plugin.getConfig().getBoolean("rules.application.validate"); + if (Question.FIVE == applyQuestion && !rules) { + valid = true; + } + if (!valid) { + sender.sendMessage(ChatColor.RED + applyQuestion.getError()); + return; + } + Application app = MinecraftManager.getApplication(sender.getUniqueId().toString()); + app.setUsername(sender.getName()); + app.setAnswer(applyQuestion, chat); + MinecraftManager.setApplication(sender.getUniqueId().toString(), app); + Question nextQuestion = Question.next(applyQuestion, chat); + MinecraftManager.setApplyQuestion(sender.getUniqueId().toString(), nextQuestion); + + if (Question.COMPLETE == nextQuestion) { + MinecraftManager.setApplyMode(sender.getUniqueId().toString(), false); + Bukkit.getConsoleSender().sendMessage(app.getFormatted()); + MCMResponse response = new MCMResponse(MCMAPI.postApplication(app)); + if (response.getStatus()) { + sender.sendMessage(ChatColor.GOLD + nextQuestion.getQuestion()); + MCMUtil.staffMessage(ChatColor.GREEN + "New application #" + response.getExtra().getAsString() + " from " + sender.getName(), "/app info " + response.getExtra().getAsString()); + } else { + sender.sendMessage(ChatColor.RED + response.getMessage()); + } + } else { + sender.sendMessage(ChatColor.GREEN + nextQuestion.getQuestion()); + } + } + } + } + + private boolean isStaffChat(Player player, String message) { + if (!player.hasPermission("minecraftmanager.staff")) { + return false; + } + for (String prefix : this.staffPrefixes) { + if (message.startsWith(prefix) && !message.startsWith(prefix+prefix)) { + return true; + } + } + return false; + } + + private TextComponent generateMessage(String message) { + TextComponent text = new TextComponent(); + for (String part : message.split(" ")) { + text.addExtra(new TextComponent(ChatColor.GREEN + part + " ")); + } + return text; + } + + private List trimmed(List list) { + for (int i = 0; i < list.size(); i++) { + list.set(i, list.get(i).trim()); + } + return list; + } + + public String componentText(BaseComponent... components) { + StringBuilder text = new StringBuilder(); + for (BaseComponent component : components) { + text.append(ChatColor.stripColor(component.toPlainText())); + } + return text.toString(); + } + +} diff --git a/src/main/java/xyz/etztech/minecraftmanager/listeners/BlockBreakListener.java b/src/main/java/xyz/etztech/minecraftmanager/listeners/BlockBreakListener.java new file mode 100644 index 0000000..f5cf0a4 --- /dev/null +++ b/src/main/java/xyz/etztech/minecraftmanager/listeners/BlockBreakListener.java @@ -0,0 +1,69 @@ +package xyz.etztech.minecraftmanager.listeners; + +import org.bukkit.Material; +import org.bukkit.block.Block; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.block.BlockBreakEvent; +import org.bukkit.event.player.PlayerLoginEvent; +import xyz.etztech.minecraftmanager.MCMAPI; +import xyz.etztech.minecraftmanager.MinecraftManager; + +import java.util.ArrayList; +import java.util.List; + +public class BlockBreakListener implements Listener { + + private MinecraftManager plugin; + + public BlockBreakListener(MinecraftManager minecraftManager) { + this.plugin = minecraftManager; + } + + @EventHandler + public void onBlockBreak(BlockBreakEvent event) { + + Block block = event.getBlock(); + boolean isDiamond = Material.DIAMOND_ORE == block.getType(); + if (isDiamond) { + boolean notify = MinecraftManager.addDiamond(getLocationString(block)); + for (Block radiusBlock : getBlocks(block, 5)) { + MinecraftManager.addDiamond(getLocationString(radiusBlock)); + } + if (notify) { + plugin.log("[OreAlert]: " + event.getPlayer().getName()); + } + } + } + + private List getBlocks(Block start, int radius) { + if (radius < 0) { + return new ArrayList(0); + } + int iterations = (radius * 2) + 1; + List blocks = new ArrayList(iterations * iterations * iterations); + for (int x = -radius; x <= radius; x++) { + for (int y = -radius; y <= radius; y++) { + for (int z = -radius; z <= radius; z++) { + blocks.add(start.getRelative(x, y, z)); + } + } + } + return blocks; + } + + private String getLocationString(Block block) { + int X = block.getX(); + int Y = block.getY(); + int Z = block.getZ(); + + String x = String.valueOf(X); + String y = String.valueOf(Y); + String z = String.valueOf(Z); + + return x + y + z; + } + + +} diff --git a/src/main/java/xyz/etztech/minecraftmanager/listeners/SessionListener.java b/src/main/java/xyz/etztech/minecraftmanager/listeners/SessionListener.java new file mode 100644 index 0000000..363badf --- /dev/null +++ b/src/main/java/xyz/etztech/minecraftmanager/listeners/SessionListener.java @@ -0,0 +1,56 @@ +package xyz.etztech.minecraftmanager.listeners; + +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; +import org.bukkit.event.player.PlayerLoginEvent; +import org.bukkit.event.player.PlayerQuitEvent; +import xyz.etztech.minecraftmanager.MCMAPI; +import xyz.etztech.minecraftmanager.MCMUtil; +import xyz.etztech.minecraftmanager.MinecraftManager; +import xyz.etztech.minecraftmanager.MinecraftManagerThread; + +import java.util.HashMap; +import java.util.Map; + +public class SessionListener implements Listener { + + private MinecraftManager plugin; + + public SessionListener(MinecraftManager minecraftManager) { + this.plugin = minecraftManager; + } + + @EventHandler + public void onLogin(PlayerLoginEvent event) { + Player player = event.getPlayer(); + MCMAPI.postLogin(player.getName(), player.getUniqueId().toString(), event.getAddress().getHostAddress()); + MCMUtil.log(MCMUtil.globalLog, player.getName() + " logged in."); + + // Check for guests + if (player.hasPermission("minecraftmanager.guest")) { + Map filters = new HashMap<>(); + filters.put("username__iexact", player.getName()); + JsonArray query = MCMAPI.queryModel("application", filters); + if (query.size() == 1) { + JsonElement element = query.get(0).getAsJsonObject().get("accepted"); + boolean accepted = !element.isJsonNull() && element.getAsBoolean(); + if (accepted) { + MinecraftManagerThread.action(player.getName(), true); + } + } + } + } + + @EventHandler + public void onLogout(PlayerQuitEvent event) { + Player player = event.getPlayer(); + MCMUtil.log(MCMUtil.globalLog, player.getName() + " logged out."); + } + + +} diff --git a/src/main/java/xyz/etztech/minecraftmanager/test/Test.java b/src/main/java/xyz/etztech/minecraftmanager/test/Test.java new file mode 100644 index 0000000..24b9e63 --- /dev/null +++ b/src/main/java/xyz/etztech/minecraftmanager/test/Test.java @@ -0,0 +1,155 @@ +package xyz.etztech.minecraftmanager.test; + +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import org.apache.commons.lang.StringUtils; +import xyz.etztech.minecraftmanager.Application; +import xyz.etztech.minecraftmanager.MCMAPI; +import xyz.etztech.minecraftmanager.MCMResponse; + +import java.util.HashMap; +import java.util.Map; +import java.util.Scanner; + +public class Test { + + public static void main(String[] args) { + String testUrl = "http://127.0.0.1:8000/api/"; + String testApi = "Testing1"; + try { + testUrl = args[0]; + testApi = args[1]; + } catch (Exception ex) { + System.out.println("Using default test URL and password"); + } + System.out.println("URL: " + testUrl); + System.out.println("Password: " + testApi); + MCMAPI.test(testUrl, testApi); + int option = 0; + + while (option != 99) { + System.out.println("===== Test Util ====="); + System.out.println("1. Test Model Query - Search for applications with a username containing the number 1."); + System.out.println("2. Test Application Posting - Post two applications"); + System.out.println("3. Test Application Action - Accept Testing1 application"); + System.out.println("4. Test Application Action - Deny Testing2 application"); + System.out.println("5. Test Application Clear - Clear Testing2 application"); + System.out.println("6. Test Login - Spoof a login of user Etzelia with IP 127.0.0.1"); + System.out.println("7. Test Ticket - Send a test ticket"); + System.out.println("99. Exit"); + System.out.print("Select Option: "); + Scanner scanner = new Scanner(System.in); + String input = scanner.next(); + int choice = StringUtils.isNumeric(input) ? Integer.parseInt(input) : 0; + switch (choice) { + case 1: + option = 1; + break; + case 2: + option = 2; + break; + case 3: + option = 3; + break; + case 4: + option = 4; + break; + case 5: + option = 5; + break; + case 6: + option = 6; + break; + case 7: + option = 7; + break; + case 99: + option = 99; + break; + default: + break; + } + + + if (option == 1) { + // Query Model + Map filters = new HashMap<>(); + filters.put("username__icontains", "1"); + JsonArray results = MCMAPI.queryModel("application", filters); + System.out.println(results.size()); + for (JsonElement jsonElement : results) { + System.out.println("Raw JSON: " + jsonElement.toString()); + System.out.println("Username: " + jsonElement.getAsJsonObject().get("username").getAsString()); + System.out.println("Ever Banned: " + jsonElement.getAsJsonObject().get("ever_banned").getAsBoolean()); + } + } else if (option == 2) { + // Post two applications + Application app1 = new Application(); + app1.setUsername("Testing1"); + app1.setAge("20"); + app1.setPlayerType("First test application."); + app1.setEverBanned("no"); + app1.setEverBannedExplanation(""); + app1.setReference("reddit"); + app1.setReadRules("24karrot"); + MCMResponse response1 = new MCMResponse(MCMAPI.postApplication(app1)); + System.out.println("===== App 1 ====="); + System.out.println("Status: " + response1.getStatus()); + System.out.println("Message: " + response1.getMessage()); + + Application app2 = new Application(); + app2.setUsername("Testing2"); + app2.setAge("20"); + app2.setPlayerType("Second test application."); + app2.setEverBanned("yes"); + app2.setEverBannedExplanation("Griefing"); + app2.setReference("planet minecraft"); + app2.setReadRules("24karrot"); + MCMResponse response2 = new MCMResponse(MCMAPI.postApplication(app2)); + System.out.println("===== App 2 ====="); + System.out.println("Status: " + response2.getStatus()); + System.out.println("Message: " + response2.getMessage()); + } else if (option == 3 || option == 4) { + boolean accept = option == 3; + String username = option == 3 ? "Testing1" : "Testing2"; + Map filters = new HashMap<>(); + filters.put("username__exact", username); + JsonArray array = MCMAPI.queryModel("application", filters); + if (array.size() != 1) { + System.out.println("Couldn't find the application for " + username + ". Does it exist?"); + } else { + String id = array.get(0).getAsJsonObject().get("id").getAsString(); + MCMResponse response = new MCMResponse(MCMAPI.postApplicationAction(id, accept, "Plugin Test")); + System.out.println("===== " + username + " ====="); + System.out.println("Status: " + response.getStatus()); + System.out.println("Message: " + response.getMessage()); + } + } else if (option == 5) { + Map filters = new HashMap<>(); + filters.put("username__exact", "Testing2"); + JsonArray array = MCMAPI.queryModel("application", filters); + if (array.size() != 1) { + System.out.println("Couldn't find the application for Testing2. Does it exist?"); + } else { + String id = array.get(0).getAsJsonObject().get("id").getAsString(); + MCMResponse response = new MCMResponse(MCMAPI.postApplicationClear(id)); + System.out.println("===== Testing2 ====="); + System.out.println("Status: " + response.getStatus()); + System.out.println("Message: " + response.getMessage()); + } + } else if (option == 6) { + MCMResponse response = new MCMResponse(MCMAPI.postLogin("Etzelia", "bf0446a8-9695-4c41-aa4c-7ff45bfd1171", "127.0.0.1")); + System.out.println("===== Login ====="); + System.out.println("Status: " + response.getStatus()); + System.out.println("Message: " + response.getMessage()); + } else if (option == 7) { + MCMResponse response = new MCMResponse(MCMAPI.postTicket("bf0446a8-9695-4c41-aa4c-7ff45bfd1171", "Test ticket.", "1", "2", "3", "O")); + System.out.println("===== Ticket ====="); + System.out.println("Status: " + response.getStatus()); + System.out.println("Message: " + response.getMessage()); + } + } + } + +} \ No newline at end of file diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml new file mode 100644 index 0000000..0bb3007 --- /dev/null +++ b/src/main/resources/config.yml @@ -0,0 +1,50 @@ +# The port to listen for commands on +port: 9999 + +# Enable/Disable Staff Chat (Highly recommended to enable) +# You can disable this if another chat plugin provides staff chat functionality and a log file for your Django project to read +staff-chat: + enabled: true + prefix: + - "#" + +rules: + enabled: true + rules: + - "Be respectful of other players and staff." + - "Do not troll, harass, or ruin the game-play of other players. No PvP unless agreed upon." + - "Respect the boundaries of other players and Spawn." + - "No cheating. (X-ray, Duping, etc.)" + - "Don't steal. All chests are private unless marked otherwise." + application: + validate: true + answer: "24karrot" + +permissions: + # Can be PermissionsEX or LuckPerms + engine: "PermissionsEX" + # The name of the group to promote to if accepted + promote: "member" + +# All commands are ONLY executed if the player is online + +# Accepting an application +accept: + message: "Welcome to the community, !" + commands: + - "broadcast has been accepted!" + +# Denying an application +deny: + message: "Your application was denied, ." + commands: + - "mute " + + +django: + # URL to the base MCM API + url: "http://localhost:8000/api/" + # MCM API password - defined in your Django settings + api: "Testing1" + + diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml new file mode 100644 index 0000000..9a996d3 --- /dev/null +++ b/src/main/resources/plugin.yml @@ -0,0 +1,63 @@ +name: ${name} +version: ${version} +description: ${description} +author: ${author} +website: ${url} +main: ${mainClass} +commands: + minecraftmanager: + description: Base MCM command + aliases: [mcm] + rules: + description: View the rules + aliases: [] + apply: + description: Apply to become whitelisted + aliases: [] + ticket: + description: Submit a help ticket + aliases: [] + application: + description: Application commands. Accept, Deny, Search, Info + aliases: [app] +permissions: + minecraftmanager.use: + description: Allows use of MinecraftManager commands + default: op + minecraftmanager.guest: + description: Permission node assigned ONLY to guests + default: false + minecraftmanager.apply: + description: Allows use of the Apply command. Probably everyone... + default: op + minecraftmanager.ticket: + description: Allows use of the Ticket command. + default: op + minecraftmanager.application.search: + description: Allows a player to search through applications + default: op + minecraftmanager.application.action: + description: Allows a player to take action on an application + default: op + minecraftmanager.staff: + description: Who should get staff messages + default: op + minecraftmanager.register: + description: Who is allowed to register for the MCM web application + default: op + minecraftmanager.application.*: + description: Wildcard permission for MCM applications + default: op + children: + minecraftmanager.application.search: true + minecraftmanager.application.action: true + minecraftmanager.*: + description: Wildcard permission for MCM + default: op + children: + minecraftmanager.use: true + minecraftmanager.apply: true + minecraftmanager.ticket: true + minecraftmanager.application.*: true + minecraftmanager.staff: true + minecraftmanager.register: true \ No newline at end of file