From 109eb3a43a2574023cc18bf6b11f4166e795f540 Mon Sep 17 00:00:00 2001 From: TheTelly1 <93684527+TheTelly1@users.noreply.github.com> Date: Wed, 12 Jul 2023 22:00:29 -0500 Subject: [PATCH] Added customization to the punishments, so its no longer just a ban, and also added location to the discord log of dangerous block usage. --- ExamplePlugin.iml | 9 -- gradle.properties | 2 +- gradle/wrapper/gradle-wrapper.jar | Bin 59536 -> 63282 bytes gradle/wrapper/gradle-wrapper.properties | 4 +- gradlew | 40 +++-- gradlew.bat | 15 +- .../github/thetrouper/sentinel/Sentinel.java | 26 ++-- .../sentinel/commands/InfoCommand.java | 2 +- .../thetrouper/sentinel/data/Config.java | 22 ++- .../thetrouper/sentinel/events/ChatEvent.java | 1 + .../sentinel/events/CmdBlockEvents.java | 4 + .../sentinel/events/CommandEvent.java | 10 +- .../sentinel/server/TakeAction.java | 131 +++++++++++----- .../sentinel/server/functions/AntiSpam.java | 18 +-- .../server/functions/Authenticator.java | 76 +++++++--- .../server/functions/ProfanityFilter.java | 24 +-- .../sentinel/server/util/ArrayUtils.java | 2 +- .../util/Notifications/NotifyConsole.java | 74 +++++---- .../util/Notifications/NotifyDiscord.java | 58 +++++-- .../util/Notifications/NotifyTrusted.java | 142 ++++++++++-------- src/main/resources/config.yml | 24 ++- 21 files changed, 447 insertions(+), 237 deletions(-) delete mode 100644 ExamplePlugin.iml diff --git a/ExamplePlugin.iml b/ExamplePlugin.iml deleted file mode 100644 index 18ec59d..0000000 --- a/ExamplePlugin.iml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - \ No newline at end of file diff --git a/gradle.properties b/gradle.properties index c0b2d4f..2f9d518 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,7 +1,7 @@ # Plugin group = 'io.github.thetrouper' -version = 0.1.3 +version = 0.1.5 # Minecraft mc_version = 1.19.4 diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 7454180f2ae8848c63b8b4dea2cb829da983f2fa..f03f475efe8cbb781d8a1f9dfcd7fbfc89bcef5a 100644 GIT binary patch delta 41358 zcmaI7V{~Rw(=8g?wrv|7+qP{xPn?cz+tw4?cG9srHakftx4-Y)^PTgKamW3$){j+t z?Xkz0RWDU`<{NNGWjSyNjHE)$Bs_Fbj3g$Pe@h|xe=V3vo0$K-r?9L;q`-jU zVqk!Pz`%fjfQW!ZoUMCN!-0SpVyCb&vjhC`R|&ri89t65N5$q;v1D^cn%NOxgGXRt zG3?uVNU<&U2S(6|HULu=Cs(LEV=`xQoQNfS|vYKpkv~{E)j|^HX2^ zyqarWHXH%{$LG7>e_#FQk%fJ313%PHHaDyG$8gZ}*DAyJd%pJ$m5-ei%JkgCFX(gC80k``~awmBlK}UEp4{Jg4J3 zblLZ$n8agJ$Lmrj$w|{dV)Vf65(t-U=!Aow=nv=qXy`i^%z^=GOo7UMH9FmU z8%*v)_CSA4G=bysVK^abVPR(E{=!34|0X!2p%OTvluV;^2G}pSKDvyCsyDvAqQjiG z^bn_-pZok^G2QRK_{j34kR|y);yqt)E(L!174}zn_5UDo%?s3Zin^RUNC#9pj3y8B zL;UW@nM|#tz83QpaDWMuo#5yD*zzUIBjgo&)=8~FdU1a_Eu4lgq!h>GH=E4tl`CY} zc9$MlcSKUrRiH@cc&R`iN31atCgLtl{#{5UT&l;~IS&@_BF#YA$YiQJ%s8Abgu$&l z#t`7X(x}^&du`&?p_D*rlL}xSGzykDATOihU-Gca{Jap1hg@MerFWMr{5ASBi_y=_ zCA4C-Bz;nh-?EfK{6~}g^36}w4pa3GRVZQ2(@S2Qgtpe4sIYv3UKJmNUlkJ*VysfvI7g?XOG)ghQc_R9)KT@iCfWeZ4&#T6%g#0x z)0ZS^*IekWEo6>J$Z{4LJ`$vd1j+SO@aF<%2;~kbZ+1O*$k?Wn;-$ihBN5B#ObTe$ z*}=7f#A&Txq;3qj+|Q)JX@=&4gqv=-yL0TJ5tm$$dlqPCVq&8=mf}OZ@wD=hLwPf` zX$NH5E?+Aa9#hzw_)Gwi$8jB~dh%x4OpdGc&;UUJ^w_azFykltrM3BE1ad_h=9br- zYZt+^3l_yI&gID>#c5YUqPFM3l#eHsiU|yVC1W@57Y;fVkJsFvmQ%Q#w&isq!*vxB zl#snLaOS%{jhWFk5rG6N&KT=B?2L1NBNSissH_Gg;Gu!eDLwL#^+6W&)m zKpOf>&A3YIegg0ZB>}t3?cy%TF`>0gRWgLuT!!j9c^Vxoj%dPfgI0};d&y@;XuS(? zBm>GQTxDG#*J;zWDck<7@{=Ykvm%O3Quj@~lZsB9H)oks9?dT9hlWs;a#(?Tu_|gc zRdrbT&p+9fSe((7tKxYuG{uJK@FSvB>j)>}9rD!DMtlI9aWu&rx2_9KMxMHRz&1DKoh5T8V1(j$h!O!vMR8(929NTU6 z#MIvL26iY11qRINQs7Cnc2QK?A(%uMM-$w7%k_-@b+$I+6y{=K6sIZUvRbX0cnQ@I z+6F~RI0GO=NvBBFk{$n~HCABV`cHhy4hIqUI1-f-l}=W#+OmxT(1wY;X=sM6cg4+l zexR6p{nc{VBs%u2ip!2Ck0trVzWU@%Q&EAM>hxD~gqCe=F67BvfN}krH`0{=TZLMq z9WuV>*OfLKC%>!|FuB(R<|<1pX6|Unv$>?onikXnXxRlyNz2g zwnkcI`j+9Uz?~-%^^gc`3Bianjb3RDwrR7?e@{+_sM)KR*>5;osuannVf`jg@hHTQEpuT1Ao5_-2#K~bkpawC z81cYY{4TB-b01e^eye??;O1SQMNCm5qRanF9;WqrP3N5;DgS8ho2pfRx2h1?2=~A& z9fT}$CB+PZns*YS1QL;zhWCf`pUfU*dUb@lX4-{= zBOKW1b7F&n1GD?nctY%cN|@e*qye&(Hq6jzVrmP5oQN|X{-#vo;6yH6z`wKI5hJ}% z&6l_qGALsb-a)onLp`!r=0mMZJJ&%F=Zh24g4dl4y2|JgKXF<$7Pgs!!Rw_Jidv6S zV4+&LK*_PeK>0McuFj)>kHIpeY@O7l;ZrphYamwR*4o!)hvC3zLNURFg#a{gYw^Y} zG#M+ol!}A*3%Q~=!6}Hwf4S7=h?Dz7vRh}rh!bNuJCq&`xAwxWYA1|t1YvIcjA?@1 z0VaY1f9C%RG24Ix&)7$3KiIS$RoIBiX@c)C=61AtyBQ)9i0+NoD!BDUQW|el)FwVy zzQGYRh>9$Hv?HPvoRHdOO$DgzQb4ha*VZ_bQ|20T#19U!NaE0f!;Ux;Vob$8l>5b! z_TduxV^L0AV@)XynU^|_m*I@kmd_YilXyfYwGnQD+2lVmrYS_@{K>fQ2zIn3+Cb43 zMtXNAC%ge!I|VH#)VNO659ZU4TK&l*8KKV=@9W&B$R|0~a1@_Z?GG5Y9Ce)iZHgJ% zH~H7Ao`&4-k*#^^9%tgvK3+l(%c*H4#a{RAduTu+cox?lcYJj8s@UfW>vZEjF3;kX zCyy_o|1T)j@)`ou89&Z9ZT^A9KWxTlBa-7bt zG9;fiok?Kuq{EFada*lmx0-l^>rLhLT-pOVU;MJudI3cR0gauqC>VhBy*{{JVf=w! zsqSo6DOIGbAyn1^h0L=FQfrU&FZDZ(f=QWmo=@(>RlPverz$xzOvAs!jE*&?`j_u? zE=?+GS>ukVMj!AC(p&0j%0E+(9UF?N9BpV35V9v2c%xW}-g#i*(Qqh%ju+1%6|Izj$7XHB{AV*g(hmE9W` z6r)AKI~oiWBPC}KH^poZJ7sf^qJ_avAL8Fh6d(=s-$op4^j{kwL;~uc9nt}A%I?oa zr2oTf&)#hMQ+lJ60eU=*jLOv{yQuV{%&8$T+RC6Ox->A!`~77Gm!g}LTN3_|1w&c` z;-RvppB496u`Y9t!E37RIB4Iw(=)kFeZ2haet}g*K)a07)xx_6&9tS-EI(rz;y_ zeQlI>S*6vqG0jO@u@E{5mD#pJ=9w3+T;E$mXjaizXgf6s`LKc|EF7?dLvw3grnM87 zyvY#BzPfXDQxSA8kVR4p7C@etCG}XD)rp*G{!2({sJ+;7+A(p(xl_z$JojT90ocgH zr}6|wC1CagKpF?n-C;8ok-g2Kx@(MeaKXO8L93Jl_EJL2RV50RonzMk(hCl{`b3CV` zMf9aY1J0r8nHh|xTfB(wnpbQqTUGRv4P(nWs@I7a00i6rt|aTI3OOb7F!RL(ss-U% zQEQmxO8U67z3ROC7wn$}O_`Hn4Sn>H-?T}DgfkjJPIaX}HM5L8!BlK8ognKVSxa%C zzN*Hmqb6T?+UfCSZRFE10<4(vrUFhG_&8zh$*0(P^E4m+>?<={*Z?rY7acOrq`2Q~CoUPA)1}@fHpG3&HGcPD5c`mnlEnmTh3lCw!Nxd8d zD*0jSTH9mramCp27}+VvDjRQ+7mzfK_{*u?Hj;LSzpEw(c!%?G>1t32x^kxXrXLvw1R2I zjFFx2bQQP2=vWZJ7`fo8)5maz5ZNZpRZLzB{wtbTvc}BP4QH-aipjGbolhubL|?ce zubV_4cpP1lGmzB=r*j{pk+~i95vPkI2$X;1>2xTy(!`f>T<~8eKd2A7TVIUgfg;`2 za-kq0(sLj`S^CigLiEQlQ>e&r+=IUr#kQ=sT1N4OakNESIFOpH(_1%3+Oj2yG;|QW~DM%xWKWH!g^ZJciwEUU=mM0ZC zwLWF{pQKMq%C^enA0H%+6%&^K6RD7b`}?%{dQE5a%zC4mGqLdP|PE#FKO+j^2(uB>5M^jk>&=}(o9^b zZR><&O0HJ85sZ)5gw&`~)+k})wIHrgoO!0Liz*I6yn+liD~34-!BvkqH)N)}5+6rg z@3BYnZ#9|cTdPBYSxCr$uHFil ztg=ZF=`_pkYSUD?^vGLT$|or?KvXFexmIq2=gn(kL0FjysnhlRigH+yk59mb+G)Ft zL2_tr6U_3f4J;|AtJYD(w4Y{~-c+1S<$gli3L9+DwGc6g6nyvOlq!&R#l8V`cy!oO zZ-_@mKyFt~b9(1t%F!nj0pJv^dEQnl_<|axhQw*Lw%LXaQp@a5K&I!r{0e;|#I4HGN}QiV3si;G znrjXbF?B3E@;)9N01fw_#wsK@w~&Ke(D%6ZX0Kb0wLQU0%eswzCmc_FXmqEk*&1oq zI#(f&2lw)XsW(MTUg7=1Ju-IR@ZK38-!WYyGPPu)y~`+V`V1IoqdA&^Z{m#5!&|N0 z3Vy<~vJ7A3{!QMd$X~ZMx5NA#`B+x=L;?1oBI#q@6!_)rfTeMo&4`v_U0JpWWalQE zXJ+T8#o8M&x-oQn!vo*|uccg=WiBTShP}U`_{9Cg^ z93jTPvFs9n<~y(=L4>ca1ZP%Wvfd@%%TDyfpm(B92tBe)E!L@Y*0Flh!Fuv(%_>HH zuR?x4 z`o$T-n+;O0ze6nDhdl9}bkOm0&uQrAfL4C#%Lyx4g zk3fp|V}!#Mq7T{)4R z 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 diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 2e6e589..38f7c5a 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,7 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.3-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.2-rc-2-bin.zip +networkTimeout=10000 +validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew index c53aefa..fcb6fca 100644 --- a/gradlew +++ b/gradlew @@ -1,7 +1,7 @@ #!/bin/sh # -# Copyright © 2015-2021 the original authors. +# Copyright © 2015-2021 the original authors. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -32,10 +32,10 @@ # Busybox and similar reduced shells will NOT work, because this script # requires all of these POSIX shell features: # * functions; -# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», -# «${var#prefix}», «${var%suffix}», and «$( cmd )»; -# * compound commands having a testable exit status, especially «case»; -# * various built-in commands including «command», «set», and «ulimit». +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». # # Important for patching: # @@ -55,7 +55,7 @@ # Darwin, MinGW, and NonStop. # # (3) This script is generated from the Groovy template -# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt # within the Gradle project. # # You can find Gradle at https://github.com/gradle/gradle/. @@ -80,13 +80,10 @@ do esac done -APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit - -APP_NAME="Gradle" +# This is normally unused +# shellcheck disable=SC2034 APP_BASE_NAME=${0##*/} - -# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' +APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD=maximum @@ -133,22 +130,29 @@ location of your Java installation." fi else JAVACMD=java - which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + if ! command -v java >/dev/null 2>&1 + then + die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. Please set the JAVA_HOME variable in your environment to match the location of your Java installation." + fi fi # Increase the maximum file descriptors if we can. if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then case $MAX_FD in #( max*) + # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC3045 MAX_FD=$( ulimit -H -n ) || warn "Could not query maximum file descriptor limit" esac case $MAX_FD in #( '' | soft) :;; #( *) + # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC3045 ulimit -n "$MAX_FD" || warn "Could not set maximum file descriptor limit to $MAX_FD" esac @@ -193,6 +197,10 @@ if "$cygwin" || "$msys" ; then done fi + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + # Collect all arguments for the java command; # * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of # shell script including quotes and variable substitutions, so put them in @@ -205,6 +213,12 @@ set -- \ org.gradle.wrapper.GradleWrapperMain \ "$@" +# Stop when "xargs" is not available. +if ! command -v xargs >/dev/null 2>&1 +then + die "xargs is not available" +fi + # Use "xargs" to parse quoted args. # # With -n1 it outputs one arg per line, with the quotes and backslashes removed. diff --git a/gradlew.bat b/gradlew.bat index ac1b06f..6689b85 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -14,7 +14,7 @@ @rem limitations under the License. @rem -@if "%DEBUG%" == "" @echo off +@if "%DEBUG%"=="" @echo off @rem ########################################################################## @rem @rem Gradle startup script for Windows @@ -25,7 +25,8 @@ if "%OS%"=="Windows_NT" setlocal set DIRNAME=%~dp0 -if "%DIRNAME%" == "" set DIRNAME=. +if "%DIRNAME%"=="" set DIRNAME=. +@rem This is normally unused set APP_BASE_NAME=%~n0 set APP_HOME=%DIRNAME% @@ -40,7 +41,7 @@ if defined JAVA_HOME goto findJavaFromJavaHome set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto execute +if %ERRORLEVEL% equ 0 goto execute echo. echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. @@ -75,13 +76,15 @@ set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar :end @rem End local scope for the variables with windows NT shell -if "%ERRORLEVEL%"=="0" goto mainEnd +if %ERRORLEVEL% equ 0 goto mainEnd :fail rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of rem the _cmd.exe /c_ return code! -if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 -exit /b 1 +set EXIT_CODE=%ERRORLEVEL% +if %EXIT_CODE% equ 0 set EXIT_CODE=1 +if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% +exit /b %EXIT_CODE% :mainEnd if "%OS%"=="Windows_NT" endlocal diff --git a/src/main/java/io/github/thetrouper/sentinel/Sentinel.java b/src/main/java/io/github/thetrouper/sentinel/Sentinel.java index 5724e1b..99966e8 100644 --- a/src/main/java/io/github/thetrouper/sentinel/Sentinel.java +++ b/src/main/java/io/github/thetrouper/sentinel/Sentinel.java @@ -21,6 +21,7 @@ import org.bukkit.plugin.Plugin; import org.bukkit.plugin.PluginManager; import org.bukkit.plugin.java.JavaPlugin; +import javax.swing.*; import java.io.File; import java.io.IOException; import java.util.List; @@ -35,6 +36,7 @@ public final class Sentinel extends JavaPlugin { public static final PluginManager manager = Bukkit.getPluginManager(); public static String prefix = ""; + public static String key = ""; public static final Logger log = Bukkit.getLogger(); /** @@ -42,25 +44,27 @@ public final class Sentinel extends JavaPlugin { */ @Override public void onEnable() { - log.info("Your server ID is: " + Authenticator.getServerID()); - switch (Authenticator.authorize(Config.license, Authenticator.getServerID())) { - case "AUTHORIZED" -> { + Config.loadConfiguration(); + String serverID = Authenticator.getServerID(); + log.info("Your license key is: " + key + " Your server ID is: " + serverID); + switch (Authenticator.authorize(key, serverID)) { + case "AUTHORIZED": log.info("Authentication Success!"); - } - case "INVALID-ID" -> { + break; + case "INVALID-ID": log.info("Authentication Failure, You have not whitelisted this server ID yet."); - } - case "UNREGISTERED" -> { - log.info("YOU SHALL NOT PASS! License: " + Config.license + " Server ID: " + Authenticator.getServerID()); - throw new IllegalStateException("YOU SHALL NOT PASS! License: " + Config.license + " Server ID: " + Authenticator.getServerID()); - } + getServer().getPluginManager().disablePlugin(this); + break; + case "UNREGISTERED": + log.warning("Authentication Failure, YOU SHALL NOT PASS! License: " + key + " Server ID: " + serverID); + getServer().getPluginManager().disablePlugin(this); + return; } // Files getConfig().options().copyDefaults(); saveDefaultConfig(); // Plugin startup logic - Config.loadConfiguration(); log.info("Sentinel has loaded! (" + getDescription().getVersion() + ")"); // Enable Functions diff --git a/src/main/java/io/github/thetrouper/sentinel/commands/InfoCommand.java b/src/main/java/io/github/thetrouper/sentinel/commands/InfoCommand.java index 605bcc3..2adb2a4 100644 --- a/src/main/java/io/github/thetrouper/sentinel/commands/InfoCommand.java +++ b/src/main/java/io/github/thetrouper/sentinel/commands/InfoCommand.java @@ -29,7 +29,7 @@ public class InfoCommand implements TabExecutor { public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { try { if (args.length == 0) { - sender.sendMessage(TextUtils.prefix("&cYou must specify an item to give.")); + sender.sendMessage(TextUtils.prefix("§cYou must specify an option!")); return true; } switch (args[0]) { diff --git a/src/main/java/io/github/thetrouper/sentinel/data/Config.java b/src/main/java/io/github/thetrouper/sentinel/data/Config.java index c801a3f..b11063f 100644 --- a/src/main/java/io/github/thetrouper/sentinel/data/Config.java +++ b/src/main/java/io/github/thetrouper/sentinel/data/Config.java @@ -18,6 +18,10 @@ import java.util.Map; public abstract class Config { private static final FileConfiguration config = Sentinel.getInstance().getConfig(); + public static List getPunishCommands() { + return punishCommands; + } + /** * Config plugin section */ @@ -26,7 +30,6 @@ public abstract class Config { return config.getString("config.plugin.prefix"); } } - public static String license; public static String webhook; public static List trustedPlayers; public static boolean blockSpecificCommands; @@ -34,11 +37,16 @@ public abstract class Config { public static boolean logNBT; public static boolean preventCmdBlocks; public static boolean logCmdBlocks; + public static boolean cmdBlockOpCheck; public static List dangerousCommands; public static boolean logDangerousCommands; public static List loggedCommands; public static boolean deop; - public static boolean ban; + public static boolean nbtPunish; + public static boolean commandPunish; + public static boolean cmdblockPunish; + public static boolean specificPunish; + public static List punishCommands; public static boolean reopCommand; public static boolean antiSpamEnabled; @@ -73,7 +81,7 @@ public abstract class Config { public static void loadConfiguration() { Sentinel.prefix = config.getString("config.plugin.prefix"); - license = config.getString("config.plugin.license"); + Sentinel.key = config.getString("config.plugin.key"); // antiNuke webhook = config.getString("config.plugin.webhook"); trustedPlayers = config.getStringList("config.plugin.trusted"); @@ -82,11 +90,16 @@ public abstract class Config { logNBT = config.getBoolean("config.plugin.log-nbt"); preventCmdBlocks = config.getBoolean("config.plugin.prevent-cmdblocks"); logCmdBlocks = config.getBoolean("config.plugin.log-cmdblocks"); + cmdBlockOpCheck = config.getBoolean("config.plugin.cmdblock-op-check"); dangerousCommands = config.getStringList("config.plugin.dangerous"); logDangerousCommands = config.getBoolean("config.plugin.log-dangerous"); loggedCommands = config.getStringList("config.plugin.logged"); deop = config.getBoolean("config.plugin.deop"); - ban = config.getBoolean("config.plugin.ban"); + nbtPunish = config.getBoolean("config.plugin.nbt-punish"); + commandPunish = config.getBoolean("config.plugin.command-punish"); + cmdblockPunish = config.getBoolean("config.plugin.cmdblock-punish"); + specificPunish = config.getBoolean("config.plugin.punish-specific"); + punishCommands = config.getStringList("config.plugin.punish-commands"); reopCommand = config.getBoolean("config.plugin.reop-command"); // antiSpam antiSpamEnabled = config.getBoolean("config.chat.anti-spam.enabled"); @@ -132,4 +145,5 @@ public abstract class Config { return dictionary; } + } diff --git a/src/main/java/io/github/thetrouper/sentinel/events/ChatEvent.java b/src/main/java/io/github/thetrouper/sentinel/events/ChatEvent.java index 62112de..e919e14 100644 --- a/src/main/java/io/github/thetrouper/sentinel/events/ChatEvent.java +++ b/src/main/java/io/github/thetrouper/sentinel/events/ChatEvent.java @@ -12,6 +12,7 @@ public class ChatEvent implements Listener { @EventHandler public static void onChat(AsyncPlayerChatEvent e) { + if (e.isCancelled()) return; if (!Sentinel.isTrusted(e.getPlayer()) || !e.getPlayer().hasPermission("sentinel.chat.antiswear.bypass")) if (Config.antiSwearEnabled) ProfanityFilter.handleProfanityFilter(e); if (!Sentinel.isTrusted(e.getPlayer()) || !e.getPlayer().hasPermission("sentinel.chat.antispam.bypass")) if (Config.antiSpamEnabled) AntiSpam.handleAntiSpam(e); } diff --git a/src/main/java/io/github/thetrouper/sentinel/events/CmdBlockEvents.java b/src/main/java/io/github/thetrouper/sentinel/events/CmdBlockEvents.java index c9655de..508a9ef 100644 --- a/src/main/java/io/github/thetrouper/sentinel/events/CmdBlockEvents.java +++ b/src/main/java/io/github/thetrouper/sentinel/events/CmdBlockEvents.java @@ -17,6 +17,7 @@ public class CmdBlockEvents implements Listener { @EventHandler private void onCMDBlockUse(PlayerInteractEvent e) { if (!Config.preventCmdBlocks) return; + if (Config.cmdBlockOpCheck && !e.getPlayer().isOp()) return; if (e.getClickedBlock() == null) return; Block b = e.getClickedBlock(); if (b.getType() == Material.COMMAND_BLOCK || b.getType() == Material.REPEATING_COMMAND_BLOCK || b.getType() == Material.CHAIN_COMMAND_BLOCK) { @@ -30,6 +31,7 @@ public class CmdBlockEvents implements Listener { @EventHandler private void onCMDBlockPlace(BlockPlaceEvent e) { if (!Config.preventCmdBlocks) return; + if (Config.cmdBlockOpCheck && !e.getPlayer().isOp()) return; Block b = e.getBlockPlaced(); if (b.getType() == Material.COMMAND_BLOCK || b.getType() == Material.CHAIN_COMMAND_BLOCK || b.getType() == Material.REPEATING_COMMAND_BLOCK ) { Player p = e.getPlayer(); @@ -42,6 +44,7 @@ public class CmdBlockEvents implements Listener { @EventHandler private void onCMDBlockMinecartUse(PlayerInteractEntityEvent e) { if (!Config.preventCmdBlocks) return; + if (Config.cmdBlockOpCheck && !e.getPlayer().isOp()) return; if (e.getRightClicked().getType() == EntityType.MINECART_COMMAND) { Player p = e.getPlayer(); if (!Sentinel.isTrusted(p)) { @@ -53,6 +56,7 @@ public class CmdBlockEvents implements Listener { @EventHandler private void onCMDBlockMinecartPlace(PlayerInteractEvent e) { if (!Config.preventCmdBlocks) { + if (Config.cmdBlockOpCheck && !e.getPlayer().isOp()) return; if (e.getItem() == null) return; if (e.getClickedBlock() == null) return; if (!e.getItem().getType().equals(Material.COMMAND_BLOCK_MINECART)) return; diff --git a/src/main/java/io/github/thetrouper/sentinel/events/CommandEvent.java b/src/main/java/io/github/thetrouper/sentinel/events/CommandEvent.java index 2bddca7..5d3a18e 100644 --- a/src/main/java/io/github/thetrouper/sentinel/events/CommandEvent.java +++ b/src/main/java/io/github/thetrouper/sentinel/events/CommandEvent.java @@ -3,6 +3,9 @@ package io.github.thetrouper.sentinel.events; import io.github.thetrouper.sentinel.Sentinel; import io.github.thetrouper.sentinel.data.Config; import io.github.thetrouper.sentinel.server.TakeAction; +import io.github.thetrouper.sentinel.server.util.Notifications.NotifyConsole; +import io.github.thetrouper.sentinel.server.util.Notifications.NotifyDiscord; +import io.github.thetrouper.sentinel.server.util.Notifications.NotifyTrusted; import io.github.thetrouper.sentinel.server.util.ServerUtils; import io.github.thetrouper.sentinel.server.util.TextUtils; import org.bukkit.entity.Player; @@ -32,9 +35,14 @@ public class CommandEvent implements Listener { if (!Sentinel.isTrusted(p)) { e.setCancelled(true); ServerUtils.sendDebugMessage(TextUtils.prefix("Command is canceled")); - TakeAction.command(e); + TakeAction.specific(e); } } } + if (Sentinel.isLoggedCommand(command)) { + NotifyConsole.command(p,command,false,false,false,true); + NotifyDiscord.command(p,command,false,false,false,true); + NotifyTrusted.command(p,command,false,false,false,true); + } } } \ No newline at end of file diff --git a/src/main/java/io/github/thetrouper/sentinel/server/TakeAction.java b/src/main/java/io/github/thetrouper/sentinel/server/TakeAction.java index 08bd69f..81d4095 100644 --- a/src/main/java/io/github/thetrouper/sentinel/server/TakeAction.java +++ b/src/main/java/io/github/thetrouper/sentinel/server/TakeAction.java @@ -7,6 +7,7 @@ import io.github.thetrouper.sentinel.server.util.Notifications.NotifyConsole; import io.github.thetrouper.sentinel.server.util.Notifications.NotifyDiscord; import io.github.thetrouper.sentinel.server.util.Notifications.NotifyTrusted; import io.github.thetrouper.sentinel.server.util.ServerUtils; +import io.github.thetrouper.sentinel.server.util.TextUtils; import org.bukkit.Bukkit; import org.bukkit.GameMode; import org.bukkit.Material; @@ -20,11 +21,54 @@ import org.bukkit.event.player.PlayerInteractEntityEvent; import org.bukkit.event.player.PlayerInteractEvent; import org.bukkit.inventory.ItemStack; +import java.util.List; + public class TakeAction { - // command nbt place useblock useentity + static List punishCommands = Config.getPunishCommands(); + public static void specific(PlayerCommandPreprocessEvent e) { + boolean deoped = false; + boolean punished = false; + boolean denied = false; + boolean logged = false; + Player p = e.getPlayer(); + String message = e.getMessage(); + String command = e.getMessage().substring(1).split(" ")[0]; + if (Sentinel.isDangerousCommand(command)) { + if (!Sentinel.isTrusted(p)) { + e.setCancelled(true); + denied = true; + } + } + if (Config.blockSpecificCommands) { + if (command.contains(":")) { + if (!Sentinel.isTrusted(p)) { + e.setCancelled(true); + p.sendMessage(TextUtils.prefix("§cPlugin specific commands are disabled!")); + denied = true; + } + } + } + if (Config.deop) { + e.getPlayer().setOp(false); + deoped = true; + } + if (Config.specificPunish) { + for (String execute : punishCommands) { + Sentinel.log.info("Dispatching a sentinel command! (" + execute.replace("%player%", p.getName()) + ")"); + ServerUtils.sendCommand(execute.replace("%player%",p.getName())); + } + punished = true; + } + if (Config.logDangerousCommands) { + logged = true; + NotifyDiscord.specific(e.getPlayer(),message,denied,deoped,punished,true); + } + NotifyConsole.specific(e.getPlayer(),message,denied,deoped,punished,logged); + NotifyTrusted.specific(e.getPlayer(),message,denied,deoped,punished,logged); + } public static void command(PlayerCommandPreprocessEvent e) { boolean deoped = false; - boolean banned = false; + boolean punished = false; boolean denied = false; boolean logged = false; Player p = e.getPlayer(); @@ -48,23 +92,26 @@ public class TakeAction { e.getPlayer().setOp(false); deoped = true; } - if (Config.ban) { - ServerUtils.sendCommand("ban " + e.getPlayer().getName() + " ]=- Sentinel Anti-Grief -=[ You have been banned for attempting to use dangerous commands. Contact an administrator if you believe this to be a mistake."); - banned = true; + if (Config.commandPunish) { + for (String execute : punishCommands) { + Sentinel.log.info("Dispatching a sentinel command! (" + execute.replace("%player%", p.getName()) + ")"); + ServerUtils.sendCommand(execute.replace("%player%",p.getName())); + } + punished = true; } if (Config.logDangerousCommands) { logged = true; - NotifyDiscord.command(e.getPlayer(),message,denied,deoped,banned,true); + NotifyDiscord.command(e.getPlayer(),message,denied,deoped,punished,true); } - NotifyConsole.command(e.getPlayer(),message,denied,deoped,banned,logged); - NotifyTrusted.command(e.getPlayer(),message,denied,deoped,banned,logged); + NotifyConsole.command(e.getPlayer(),message,denied,deoped,punished,logged); + NotifyTrusted.command(e.getPlayer(),message,denied,deoped,punished,logged); } public static void NBT(InventoryCreativeEvent e) { Player p = (Player) e.getWhoClicked(); final ItemStack item = e.getCursor(); boolean removed = false; boolean deoped = false; - boolean banned = false; + boolean punished = false; boolean logged = false; boolean gms = false; if (Config.preventNBT) { @@ -80,23 +127,26 @@ public class TakeAction { p.setOp(false); deoped = true; } - if (Config.ban) { - ServerUtils.sendCommand("ban " + p.getName() + " ]=- Sentinel Anti-Grief -=[ You have been banned for attempting to use dangerous items. Contact an administrator if you believe this to be a mistake."); - banned = true; + if (Config.nbtPunish) { + for (String execute : punishCommands) { + Sentinel.log.info("Dispatching a sentinel command! (" + execute.replace("%player%", p.getName()) + ")"); + ServerUtils.sendCommand(execute.replace("%player%",p.getName())); + } + punished = true; } if (Config.logNBT) { logged = true; - NotifyDiscord.NBT(p,item,removed,deoped,gms,banned, true,FileUtils.createNBTLog(item.getType().toString().toLowerCase() + item.getItemMeta().getAsString())); + NotifyDiscord.NBT(p,item,removed,deoped,gms,punished, true,FileUtils.createNBTLog(item.getType().toString().toLowerCase() + item.getItemMeta().getAsString())); } - NotifyConsole.NBT(p,item,removed,deoped,gms,banned,logged); - NotifyTrusted.NBT(p,item,removed,deoped,gms,banned,logged); + NotifyConsole.NBT(p,item,removed,deoped,gms,punished,logged); + NotifyTrusted.NBT(p,item,removed,deoped,gms,punished,logged); } public static void placeBlock(BlockPlaceEvent e) { Block b = e.getBlock(); Player p = e.getPlayer(); boolean deleted = false; boolean deoped = false; - boolean banned = false; + boolean punished = false; boolean logged = false; if (Config.preventCmdBlocks) { e.setCancelled(true); @@ -109,16 +159,19 @@ public class TakeAction { p.setOp(false); deoped = true; } - if (Config.ban) { - ServerUtils.sendCommand("ban " + p.getName() + " ]=- Sentinel Anti-Grief -=[ You have been banned for attempting to place dangerous blocks. Contact an administrator if you believe this to be a mistake."); - banned = true; + if (Config.cmdblockPunish) { + for (String execute : punishCommands) { + Sentinel.log.info("Dispatching a sentinel command! (" + execute.replace("%player%", p.getName()) + ")"); + ServerUtils.sendCommand(execute.replace("%player%",p.getName())); + } + punished = true; } if (Config.logCmdBlocks) { logged = true; - NotifyDiscord.placeBlock(p,b,deleted,deoped,banned,logged); + NotifyDiscord.placeBlock(p,b,deleted,deoped,punished,logged); } - NotifyConsole.placeBlock(p,b,deleted,deoped,banned,logged); - NotifyTrusted.placeBlock(p,b,deleted,deoped,banned,logged); + NotifyConsole.placeBlock(p,b,deleted,deoped,punished,logged); + NotifyTrusted.placeBlock(p,b,deleted,deoped,punished,logged); } public static void useBlock(PlayerInteractEvent e) { if (e.getClickedBlock() == null) return; @@ -126,7 +179,7 @@ public class TakeAction { Block b = e.getClickedBlock(); boolean denied = false; boolean deoped = false; - boolean banned = false; + boolean punished = false; boolean logged = false; if (Config.preventCmdBlocks) { e.setCancelled(true); @@ -136,16 +189,19 @@ public class TakeAction { p.setOp(false); deoped = true; } - if (Config.ban) { - ServerUtils.sendCommand("ban " + p.getName() + " ]=- Sentinel Anti-Grief -=[ You have been banned for attempting to use dangerous blocks. Contact an administrator if you believe this to be a mistake."); - banned = true; + if (Config.cmdblockPunish) { + for (String execute : punishCommands) { + Sentinel.log.info("Dispatching a sentinel command! (" + execute.replace("%player%", p.getName()) + ")"); + ServerUtils.sendCommand(execute.replace("%player%",p.getName())); + } + punished = true; } if (Config.logCmdBlocks) { logged = true; - NotifyDiscord.usedBlock(p,b,denied,deoped,banned,logged); + NotifyDiscord.usedBlock(p,b,denied,deoped,punished,logged); } - NotifyConsole.usedBlock(p,b,denied,deoped,banned,logged); - NotifyTrusted.usedBlock(p,b,denied,deoped,banned,logged); + NotifyConsole.usedBlock(p,b,denied,deoped,punished,logged); + NotifyTrusted.usedBlock(p,b,denied,deoped,punished,logged); } public static void useEntity(PlayerInteractEntityEvent e) { if (e.getRightClicked() == null) return; @@ -153,7 +209,7 @@ public class TakeAction { Entity ent = e.getRightClicked(); boolean denied = false; boolean deoped = false; - boolean banned = false; + boolean punished = false; boolean logged = false; if (Config.preventCmdBlocks) { e.setCancelled(true); @@ -163,15 +219,18 @@ public class TakeAction { p.setOp(false); deoped = true; } - if (Config.ban) { - ServerUtils.sendCommand("ban " + p.getName() + " ]=- Sentinel Anti-Grief -=[ You have been banned for attempting to use dangerous entities. Contact an administrator if you believe this to be a mistake."); - banned = true; + if (Config.cmdblockPunish) { + for (String execute : punishCommands) { + Sentinel.log.info("Dispatching a sentinel command! (" + execute.replace("%player%", p.getName()) + ")"); + ServerUtils.sendCommand(execute.replace("%player%",p.getName())); + } + punished = true; } if (Config.logCmdBlocks) { logged = true; - NotifyDiscord.usedEntity(p,ent,denied,deoped,banned,logged); + NotifyDiscord.usedEntity(p,ent,denied,deoped,punished,logged); } - NotifyConsole.usedEntity(p,ent,denied,deoped,banned,logged); - NotifyTrusted.usedEntity(p,ent,denied,deoped,banned,logged); + NotifyConsole.usedEntity(p,ent,denied,deoped,punished,logged); + NotifyTrusted.usedEntity(p,ent,denied,deoped,punished,logged); } } diff --git a/src/main/java/io/github/thetrouper/sentinel/server/functions/AntiSpam.java b/src/main/java/io/github/thetrouper/sentinel/server/functions/AntiSpam.java index 460aa25..b08fac5 100644 --- a/src/main/java/io/github/thetrouper/sentinel/server/functions/AntiSpam.java +++ b/src/main/java/io/github/thetrouper/sentinel/server/functions/AntiSpam.java @@ -64,12 +64,12 @@ public class AntiSpam { public static void alertSpam(Player p, String message1, String message2) { TextComponent text = new TextComponent(); p.sendMessage(TextUtils.prefix("Do not spam in chat! Please wait before sending another message.")); - String hover = TextUtils.color("§8]==-- §d§lSentinel §8--==[" + - "\n&bPrevious: &f" + message2 + - "\n&bCurrent: &f" + message1 + - "\n&bSimilarity &f" + GPTUtils.calculateSimilarity(message1,message2 + "%")); - text.setText(TextUtils.prefix(TextUtils.color - ("&b&n" + p.getName() + "&7 might be spamming! &8(&c" + heatMap.get(p) + "&7/&4" + Config.punishHeat + "&8)"))); + String hover ="§8]==-- §d§lSentinel §8--==[" + + "\n§bPrevious: §f" + message2 + + "\n§bCurrent: §f" + message1 + + "\n§bSimilarity §f" + GPTUtils.calculateSimilarity(message1,message2 + "%"); + text.setText(TextUtils.prefix( + "§b§n" + p.getName() + "§7 might be spamming! §8(§c" + heatMap.get(p) + "§7/§4" + Config.punishHeat + "§8)")); text.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, TextComponent.fromLegacyText(hover))); ServerUtils.forEachStaff(staff -> { staff.spigot().sendMessage(text); @@ -82,10 +82,10 @@ public class AntiSpam { chatCleared = true; } ServerUtils.sendCommand(Config.punishSpamCommand.replace("%player%", player.getName())); - player.sendMessage(TextUtils.prefix(TextUtils.color("&cYou have been auto-punished for violating the anti-spam repetitively!"))); + player.sendMessage(TextUtils.prefix("§cYou have been auto-punished for violating the anti-spam repetitively!")); TextComponent text = new TextComponent(); - text.setText(TextUtils.prefix(TextUtils.color - ("&b&n" + player.getName() + "&7 has been auto-muted by the anti-spam! &8(&c" + heatMap.get(player) + "&7/&4" + Config.punishHeat + "&8)"))); + text.setText(TextUtils.prefix( + "§b§n" + player.getName() + "§7 has been auto-muted by the anti-spam! §8(§c" + heatMap.get(player) + "§7/§4" + Config.punishHeat + "§8)")); ServerUtils.forEachStaff(staff -> { staff.spigot().sendMessage(text); }); diff --git a/src/main/java/io/github/thetrouper/sentinel/server/functions/Authenticator.java b/src/main/java/io/github/thetrouper/sentinel/server/functions/Authenticator.java index 7c102b0..b914dc6 100644 --- a/src/main/java/io/github/thetrouper/sentinel/server/functions/Authenticator.java +++ b/src/main/java/io/github/thetrouper/sentinel/server/functions/Authenticator.java @@ -12,7 +12,17 @@ import java.net.InetAddress; import java.net.URL; import java.net.UnknownHostException; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; +import java.security.KeyManagementException; +import java.security.NoSuchAlgorithmException; +import java.security.cert.X509Certificate; +import javax.net.ssl.HostnameVerifier; +import javax.net.ssl.HttpsURLConnection; +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLSession; +import javax.net.ssl.TrustManager; +import javax.net.ssl.X509TrustManager; public class Authenticator { @@ -31,33 +41,65 @@ public class Authenticator { } } - public static String authorize(String license, String serverID) { + public static String authorize(String licenseKey, String serverID) { + String authStatus = ""; + try { - URL url = new URL("https://sentinelauth.000webhostapp.com"); + URL url = new URL("https://sentinelauth.000webhostapp.com/index.html"); BufferedReader reader = new BufferedReader(new InputStreamReader(url.openStream())); - String line; - while ((line = reader.readLine()) != null) { - if (line.contains(license)) { - String[] parts = line.split(":"); - if (parts.length > 1) { - String[] allowedIDs = parts[1].split("\\s+"); - for (String id : allowedIDs) { - if (id.equals(serverID)) { - reader.close(); - return "AUTHORIZED"; - } + List lines = readLines(reader); + + for (String line : lines) { + if (line.contains("data-key")) { + String key = extractValue(line, "data-key"); + String allowedIDs = extractValue(line, "data-allowed"); + String[] allowedArr = allowedIDs.split(":"); + + if (key.equals(licenseKey)) { + if (Arrays.asList(allowedArr).contains(serverID)) { + authStatus = "AUTHORIZED"; + } else { + authStatus = "INVALID-ID"; } + break; } - reader.close(); - return "INVALID-ID"; } } - reader.close(); + + if (authStatus.isEmpty()) { + authStatus = "UNREGISTERED"; + } } catch (IOException e) { e.printStackTrace(); } - return "UNREGISTERED"; + + return authStatus; } + + public static List readLines(BufferedReader reader) { + try { + List lines = new ArrayList<>(); + String line = reader.readLine(); + while (line != null) { + lines.add(line); + line = reader.readLine(); + } + reader.close(); + return lines; + } catch (Exception ex) { + ex.printStackTrace(); + } + return new ArrayList<>(); + } + + public static String extractValue(String line, String attribute) { + int start = line.indexOf(attribute + "=\"") + attribute.length() + 2; + int end = line.indexOf("\"", start); + return line.substring(start, end); + } + + + public static String getServerID() { return encrypt(IP.getHostAddress()); } diff --git a/src/main/java/io/github/thetrouper/sentinel/server/functions/ProfanityFilter.java b/src/main/java/io/github/thetrouper/sentinel/server/functions/ProfanityFilter.java index a63a3ae..9c9ee1c 100644 --- a/src/main/java/io/github/thetrouper/sentinel/server/functions/ProfanityFilter.java +++ b/src/main/java/io/github/thetrouper/sentinel/server/functions/ProfanityFilter.java @@ -72,11 +72,11 @@ public class ProfanityFilter { } public static void punishSwear(Player player, String highlightedMSG, String origMessage) { ServerUtils.sendCommand(Config.swearPunishCommand.replace("%player%", player.getName())); - player.sendMessage(TextUtils.prefix(TextUtils.color("&cYou have been auto-muted for violating the anti-swear repetitively!"))); - String hover = TextUtils.color("&bOriginal: &f" + origMessage + "\n&bSanitized: &f" + highlightedMSG + "\n&7&o(click to copy)"); + player.sendMessage(TextUtils.prefix(("§cYou have been auto-muted for violating the anti-swear repetitively!"))); + String hover = ("§bOriginal: §f" + origMessage + "\n§bSanitized: §f" + highlightedMSG + "\n§7§o(click to copy)"); TextComponent text = new TextComponent(); - text.setText(TextUtils.prefix(TextUtils.color - ("&b&n" + player.getName() + "&7 has been auto-muted by the anti-swear! &8(&c" + scoreMap.get(player) + "&7/&4" + Config.punishScore + "&8)"))); + text.setText(TextUtils.prefix( + ("§b§n" + player.getName() + "§7 has been auto-muted by the anti-swear! §8(§c" + scoreMap.get(player) + "§7/§4" + Config.punishScore + "§8)"))); text.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, TextComponent.fromLegacyText(hover))); text.setClickEvent(new ClickEvent(ClickEvent.Action.COPY_TO_CLIPBOARD, origMessage)); @@ -88,11 +88,11 @@ public class ProfanityFilter { public static void punishSlur(Player player, String highlightedMSG, String origMessage) { if (!Config.slurInstaPunish) return; ServerUtils.sendCommand(Config.slurPunishCommand.replace("%player%", player.getName())); - player.sendMessage(TextUtils.prefix(TextUtils.color("&cYou have been insta-muted for saying a slur!"))); - String hover = TextUtils.color("&bOriginal: &f" + origMessage + "\n&bSanitized: &f" + highlightedMSG + "\n&7&o(click to copy)"); + player.sendMessage(TextUtils.prefix(("§cYou have been insta-muted for saying a slur!"))); + String hover = ("§bOriginal: §f" + origMessage + "\n§bSanitized: §f" + highlightedMSG + "\n§7§o(click to copy)"); TextComponent text = new TextComponent(); - text.setText(TextUtils.prefix(TextUtils.color - ("&b&n" + player.getName() + "&7 has been insta-muted by the anti-swear! &8(&e" + scoreMap.get(player) + "&7/&4" + Config.punishScore + "&8)"))); + text.setText(TextUtils.prefix( + ("§b§n" + player.getName() + "§7 has been insta-muted by the anti-swear! §8(§e" + scoreMap.get(player) + "§7/§4" + Config.punishScore + "§8)"))); text.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, TextComponent.fromLegacyText(hover))); text.setClickEvent(new ClickEvent(ClickEvent.Action.COPY_TO_CLIPBOARD, origMessage)); @@ -102,11 +102,11 @@ public class ProfanityFilter { if (Config.logSwear) WebhookSender.sendSlurLog(player,origMessage,scoreMap.get(player)); } public static void blockSwear(Player player, String highlightedMSG, String origMessage, String severity) { - player.sendMessage(TextUtils.prefix(TextUtils.color("&cPlease do not swear in chat! Attempting to bypass this filter will result in a mute!"))); - String hover = TextUtils.color("&bOriginal: &f" + origMessage + "\n&bSanitized: &f" + highlightedMSG + "\n&bSeverity" + severity + "\n&7&o(click to copy)"); + player.sendMessage(TextUtils.prefix(("§cPlease do not swear in chat! Attempting to bypass this filter will result in a mute!"))); + String hover = ("§bOriginal: §f" + origMessage + "\n§bSanitized: §f" + highlightedMSG + "\n§bSeverity" + severity + "\n§7§o(click to copy)"); TextComponent text = new TextComponent(); - text.setText(TextUtils.prefix(TextUtils.color - ("&b&n" + player.getName() + "&7 has triggered the anti-swear! &8(&c" + scoreMap.get(player) + "&7/&4" + Config.punishScore + "&8)"))); + text.setText(TextUtils.prefix( + ("§b§n" + player.getName() + "§7 has triggered the anti-swear! §8(§c" + scoreMap.get(player) + "§7/§4" + Config.punishScore + "§8)"))); text.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, TextComponent.fromLegacyText(hover))); text.setClickEvent(new ClickEvent(ClickEvent.Action.COPY_TO_CLIPBOARD, origMessage)); diff --git a/src/main/java/io/github/thetrouper/sentinel/server/util/ArrayUtils.java b/src/main/java/io/github/thetrouper/sentinel/server/util/ArrayUtils.java index 2fb3351..d451de7 100644 --- a/src/main/java/io/github/thetrouper/sentinel/server/util/ArrayUtils.java +++ b/src/main/java/io/github/thetrouper/sentinel/server/util/ArrayUtils.java @@ -25,7 +25,7 @@ public final class ArrayUtils { } public static String list2string(List list) { - return TextUtils.color("&7[&e" + String.join("&7, &e", ArrayUtils.toNewList(list, Object::toString)) + "&7]"); + return ("§7[§e" + String.join("§7, §e", ArrayUtils.toNewList(list, Object::toString)) + "§7]"); } public static List bind(Iterable tList, T... ts) { diff --git a/src/main/java/io/github/thetrouper/sentinel/server/util/Notifications/NotifyConsole.java b/src/main/java/io/github/thetrouper/sentinel/server/util/Notifications/NotifyConsole.java index 127518c..06e6134 100644 --- a/src/main/java/io/github/thetrouper/sentinel/server/util/Notifications/NotifyConsole.java +++ b/src/main/java/io/github/thetrouper/sentinel/server/util/Notifications/NotifyConsole.java @@ -13,67 +13,79 @@ import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; public class NotifyConsole { - public static void command(Player p, String command, boolean denied, boolean deoped, boolean banned, boolean logged) { + public static void specific(Player p, String command, boolean denied, boolean deoped, boolean punished, boolean logged) { final String log = ( - "Sentinel caught a dangerous command! \n]==-- &d&lSentinel --==[" + + "Sentinel caught a specific command! \n]==-- Sentinel --==[" + + "\nPlayer: " + p.getName() + + "\nCommand: " + command + + "\nDenied: " + TextUtils.boolString(denied,"\u2714","\u2718") + + "\nDeoped: " + TextUtils.boolString(deoped,"\u2714","\u2718") + + "\nPunished: " + TextUtils.boolString(punished,"\u2714","\u2718") + + "\nLogged: " + TextUtils.boolString(logged,"\u2714","\u2718") + ); + Sentinel.log.info(log); + } + public static void command(Player p, String command, boolean denied, boolean deoped, boolean punished, boolean logged) { + final String log = ( + "Sentinel caught a dangerous command! \n]==-- Sentinel --==[" + "\nPlayer: " + p.getName() + "\nCommand: " + command + - "\nDenied: " + TextUtils.boolString(denied,"✔","✘") + - "\nDeoped: " + TextUtils.boolString(deoped,"✔","✘") + - "\nBanned: " + TextUtils.boolString(banned,"✔","✘") + - "\nLogged: " + TextUtils.boolString(logged,"✔","✘") + "\nDenied: " + TextUtils.boolString(denied,"\u2714","\u2718") + + "\nDeoped: " + TextUtils.boolString(deoped,"\u2714","\u2718") + + "\nPunished: " + TextUtils.boolString(punished,"\u2714","\u2718") + + "\nLogged: " + TextUtils.boolString(logged,"\u2714","\u2718") ); Sentinel.log.info(log); } - public static void NBT(Player p, ItemStack item, boolean removed, boolean deoped, boolean gms, boolean banned, boolean logged) { + public static void NBT(Player p, ItemStack item, boolean removed, boolean deoped, boolean gms, boolean punished, boolean logged) { String log = ( - "Sentinel caught a dangerous NBT! \n]==-- &d&lSentinel --==[" + + "Sentinel caught a dangerous NBT! \n]==-- Sentinel --==[" + "\nPlayer: " + p.getName() + "\nItemType: " + item.getType() + - "\nRemoved: " + TextUtils.boolString(removed,"✔","✘") + - "\nDeoped: " + TextUtils.boolString(deoped,"✔","✘") + - "\nRevert GM: " + TextUtils.boolString(gms, "✔", "✘") + - "\nBanned: " + TextUtils.boolString(banned,"✔","✘") + - "\nLogged: " + TextUtils.boolString(logged,"✔","✘") + "\nRemoved: " + TextUtils.boolString(removed,"\u2714","\u2718") + + "\nDeoped: " + TextUtils.boolString(deoped,"\u2714","\u2718") + + "\nRevert GM: " + TextUtils.boolString(gms, "\u2714","\u2718") + + "\nPunished: " + TextUtils.boolString(punished,"\u2714","\u2718") + + "\nLogged: " + TextUtils.boolString(logged,"\u2714","\u2718") ); Sentinel.log.info(log); } - public static void placeBlock(Player p, Block b, boolean deleted, boolean deoped, boolean banned, boolean logged) { + public static void placeBlock(Player p, Block b, boolean deleted, boolean deoped, boolean punished, boolean logged) { String log = ( - "Sentinel has caught the placing of a dangerous block! \n]==-- &d&lSentinel --==[" + + "Sentinel has caught the placing of a dangerous block! \n]==-- Sentinel --==[" + "\nPlayer: " + p.getName() + "\nBlockType: " + b.getType() + "\nLocation: " + b.getX() + " " + b.getY() + " " + b.getZ() + - "\nDeleted: " + TextUtils.boolString(deleted,"✔","✘") + - "\nDeoped: " + TextUtils.boolString(deoped,"✔","✘") + - "\nBanned: " + TextUtils.boolString(banned,"✔","✘") + - "\nLogged: " + TextUtils.boolString(logged,"✔","✘") + "\nDeleted: " + TextUtils.boolString(deleted,"\u2714","\u2718") + + "\nDeoped: " + TextUtils.boolString(deoped,"\u2714","\u2718") + + "\nPunished: " + TextUtils.boolString(punished,"\u2714","\u2718") + + "\nLogged: " + TextUtils.boolString(logged,"\u2714","\u2718") ); Sentinel.log.info(log); } - public static void usedBlock(Player p, Block b, boolean denied, boolean deoped, boolean banned, boolean logged) { + public static void usedBlock(Player p, Block b, boolean denied, boolean deoped, boolean punished, boolean logged) { String log = ( - "]==-- &d&lSentinel --==[" + + "]==-- Sentinel --==[" + "\nPlayer: " + p.getName() + "\nBlockType: " + b.getType() + "\nLocation: " + b.getX() + " " + b.getY() + " " + b.getZ() + - "\nDenied: " + TextUtils.boolString(denied,"✔","✘") + - "\nDeoped: " + TextUtils.boolString(deoped,"✔","✘") + - "\nBanned: " + TextUtils.boolString(banned,"✔","✘") + - "\nLogged: " + TextUtils.boolString(logged,"✔","✘") + "\nDenied: " + TextUtils.boolString(denied,"\u2714","\u2718") + + "\nDeoped: " + TextUtils.boolString(deoped,"\u2714","\u2718") + + "\nPunished: " + TextUtils.boolString(punished,"\u2714","\u2718") + + "\nLogged: " + TextUtils.boolString(logged,"\u2714","\u2718") ); Sentinel.log.info(log); } - public static void usedEntity(Player p, Entity e, boolean denied, boolean deoped, boolean banned, boolean logged) { + public static void usedEntity(Player p, Entity e, boolean denied, boolean deoped, boolean punished, boolean logged) { String log = ( - "]==-- &d&lSentinel --==[" + + "]==-- Sentinel --==[" + "\nPlayer: " + p.getName() + "\nEntityType: " + e.getType() + "\nLocation: " + e.getLocation().getX() + " " + e.getLocation().getY() + " " + e.getLocation().getZ() + - "\nDenied: " + TextUtils.boolString(denied,"✔","✘") + - "\nDeoped: " + TextUtils.boolString(deoped,"✔","✘") + - "\nBanned: " + TextUtils.boolString(banned,"✔","✘") + - "\nLogged: " + TextUtils.boolString(logged,"✔","✘") + "\nDenied: " + TextUtils.boolString(denied,"\u2714","\u2718") + + "\nDeoped: " + TextUtils.boolString(deoped,"\u2714","\u2718") + + "\nPunished: " + TextUtils.boolString(punished,"\u2714","\u2718") + + "\nLogged: " + TextUtils.boolString(logged,"\u2714","\u2718") ); Sentinel.log.info(log); } diff --git a/src/main/java/io/github/thetrouper/sentinel/server/util/Notifications/NotifyDiscord.java b/src/main/java/io/github/thetrouper/sentinel/server/util/Notifications/NotifyDiscord.java index 822e59b..49dbbc4 100644 --- a/src/main/java/io/github/thetrouper/sentinel/server/util/Notifications/NotifyDiscord.java +++ b/src/main/java/io/github/thetrouper/sentinel/server/util/Notifications/NotifyDiscord.java @@ -16,7 +16,36 @@ import java.awt.*; import java.io.IOException; public class NotifyDiscord { - public static void command(Player player, String command, boolean denied, boolean deoped, boolean banned, boolean logged) { + public static void specific(Player player, String command, boolean denied, boolean deoped, boolean punished, boolean logged) { + ServerUtils.sendDebugMessage("Creating Specific Webhook..."); + DiscordWebhook webhook = new DiscordWebhook(Config.webhook); + webhook.setAvatarUrl("https://r2.e-z.host/d440b58a-ba90-4839-8df6-8bba298cf817/3lwit5nt.png"); + webhook.setUsername("Sentinel Anti-Nuke | Logs"); + DiscordWebhook.EmbedObject embed = new DiscordWebhook.EmbedObject() + .setAuthor("Anti-Nuke has been triggered","","") + .setTitle("The use of a specific command has been detected!") + .setDescription( + Emojis.rightSort + " **Player:** " + player.getName() + " " + Emojis.member + "\\n" + + Emojis.rightSort + " **Command:** " + command + " " + Emojis.nuke + "\\n" + ) + .addField("Actions:", + Emojis.rightSort + " **Denied:** " + TextUtils.boolString(denied,Emojis.success, Emojis.failure) + "\\n" + + Emojis.rightSort + " **De-oped:** " + TextUtils.boolString(deoped,Emojis.success, Emojis.failure) + "\\n" + + Emojis.rightSort + " **Punished:** " + TextUtils.boolString(punished,Emojis.success, Emojis.failure) + "\\n" + + Emojis.rightSort + "**Logged:** " + TextUtils.boolString(logged,Emojis.success, Emojis.failure), false + ) + .setThumbnail("https://crafatar.com/avatars/" + player.getUniqueId() + "?size=64&&overlay") + .setColor(Color.RED); + webhook.addEmbed(embed); + try { + ServerUtils.sendDebugMessage("Executing webhook..."); + webhook.execute(); + } catch (IOException e) { + ServerUtils.sendDebugMessage(TextUtils.prefix("Epic webhook failure!!!")); + Sentinel.log.info(e.toString()); + } + } + public static void command(Player player, String command, boolean denied, boolean deoped, boolean punished, boolean logged) { ServerUtils.sendDebugMessage("Creating Command Webhook..."); DiscordWebhook webhook = new DiscordWebhook(Config.webhook); webhook.setAvatarUrl("https://r2.e-z.host/d440b58a-ba90-4839-8df6-8bba298cf817/3lwit5nt.png"); @@ -31,7 +60,7 @@ public class NotifyDiscord { .addField("Actions:", Emojis.rightSort + " **Denied:** " + TextUtils.boolString(denied,Emojis.success, Emojis.failure) + "\\n" + Emojis.rightSort + " **De-oped:** " + TextUtils.boolString(deoped,Emojis.success, Emojis.failure) + "\\n" + - Emojis.rightSort + " **Banned:** " + TextUtils.boolString(banned,Emojis.success, Emojis.failure) + "\\n" + + Emojis.rightSort + " **Punished:** " + TextUtils.boolString(punished,Emojis.success, Emojis.failure) + "\\n" + Emojis.rightSort + "**Logged:** " + TextUtils.boolString(logged,Emojis.success, Emojis.failure), false ) .setThumbnail("https://crafatar.com/avatars/" + player.getUniqueId() + "?size=64&&overlay") @@ -45,7 +74,7 @@ public class NotifyDiscord { Sentinel.log.info(e.toString()); } } - public static void NBT(Player player, ItemStack item, boolean removed, boolean deoped, boolean gms, boolean banned, boolean logged, String logFileName) { + public static void NBT(Player player, ItemStack item, boolean removed, boolean deoped, boolean gms, boolean punished, boolean logged, String logFileName) { ServerUtils.sendDebugMessage("Creating NBT Webhook..."); DiscordWebhook webhook = new DiscordWebhook(Config.webhook); @@ -63,7 +92,7 @@ public class NotifyDiscord { Emojis.rightSort + " **Removed:** " + TextUtils.boolString(removed,Emojis.success, Emojis.failure) + "\\n" + Emojis.rightSort + " **De-oped:** " + TextUtils.boolString(deoped,Emojis.success, Emojis.failure) + "\\n" + Emojis.rightSort + " **GM Reverted:** " + TextUtils.boolString(gms,Emojis.success, Emojis.failure) + "\\n" + - Emojis.rightSort + " **Banned:** " + TextUtils.boolString(banned,Emojis.success, Emojis.failure) + "\\n"+ + Emojis.rightSort + " **Punished:** " + TextUtils.boolString(punished,Emojis.success, Emojis.failure) + "\\n"+ Emojis.rightSort + " **Logged:** " + TextUtils.boolString(logged,Emojis.success, Emojis.failure), false ) .setColor(Color.BLUE); @@ -76,7 +105,7 @@ public class NotifyDiscord { Sentinel.log.info(e.toString()); } } - public static void placeBlock(Player player, Block b, boolean deleted, boolean deoped, boolean banned, boolean logged) { + public static void placeBlock(Player player, Block b, boolean deleted, boolean deoped, boolean punished, boolean logged) { ServerUtils.sendDebugMessage("Creating placeBlock Webhook..."); DiscordWebhook webhook = new DiscordWebhook(Config.webhook); webhook.setAvatarUrl("https://r2.e-z.host/d440b58a-ba90-4839-8df6-8bba298cf817/3lwit5nt.png"); @@ -86,12 +115,13 @@ public class NotifyDiscord { .setTitle("The placing of a dangerous block has been detected!") .setDescription( Emojis.rightSort + " **Player:** " + player.getName() + " " + Emojis.member + "\\n" + - Emojis.rightSort + " **Block:** " + b.getType().toString().toLowerCase() + " " + Emojis.nuke + "\\n" + Emojis.rightSort + " **Block:** " + b.getType().toString().toLowerCase() + " " + Emojis.nuke + "\\n" + + Emojis.space + Emojis.rightDoubleArrow + " **Location:** X: " + b.getX() + " Y: " + b.getY() + " Z: " + b.getZ() + "\\n" ) .addField("Actions:", Emojis.rightSort + " **Deleted:** " + TextUtils.boolString(deleted,Emojis.success, Emojis.failure) + "\\n" + Emojis.rightSort + " **De-oped:** " + TextUtils.boolString(deoped,Emojis.success, Emojis.failure) + "\\n" + - Emojis.rightSort + " **Banned:** " + TextUtils.boolString(banned,Emojis.success, Emojis.failure) + "\\n"+ + Emojis.rightSort + " **Punished:** " + TextUtils.boolString(punished,Emojis.success, Emojis.failure) + "\\n"+ Emojis.rightSort + " **Logged:** " + TextUtils.boolString(logged,Emojis.success, Emojis.failure), false ) .setColor(Color.RED); @@ -104,7 +134,7 @@ public class NotifyDiscord { Sentinel.log.info(e.toString()); } } - public static void usedBlock(Player player, Block b, boolean denied, boolean deoped, boolean banned, boolean logged) { + public static void usedBlock(Player player, Block b, boolean denied, boolean deoped, boolean punished, boolean logged) { ServerUtils.sendDebugMessage("Creating useBlock Webhook..."); DiscordWebhook webhook = new DiscordWebhook(Config.webhook); webhook.setAvatarUrl("https://r2.e-z.host/d440b58a-ba90-4839-8df6-8bba298cf817/3lwit5nt.png"); @@ -114,12 +144,13 @@ public class NotifyDiscord { .setTitle("The use of a dangerous block has been detected!") .setDescription( Emojis.rightSort + " **Player:** " + player.getName() + " " + Emojis.member + "\\n" + - Emojis.rightSort + " **Block:** " + b.getType() + " " + Emojis.nuke + "\\n" + Emojis.rightSort + " **Block:** " + b.getType() + " " + Emojis.nuke + "\\n" + + Emojis.space + Emojis.rightDoubleArrow + " **Location:** X: " + b.getX() + " Y: " + b.getY() + " Z: " + b.getZ() + "\\n" ) .addField("Actions:", Emojis.rightSort + " **Denied:** " + TextUtils.boolString(denied,Emojis.success, Emojis.failure) + "\\n" + Emojis.rightSort + " **De-oped:** " + TextUtils.boolString(deoped,Emojis.success, Emojis.failure) + "\\n" + - Emojis.rightSort + " **Banned:** " + TextUtils.boolString(banned,Emojis.success, Emojis.failure) + "\\n"+ + Emojis.rightSort + " **Punished:** " + TextUtils.boolString(punished,Emojis.success, Emojis.failure) + "\\n"+ Emojis.rightSort + " **Logged:** " + TextUtils.boolString(logged,Emojis.success, Emojis.failure), false ) .setColor(Color.RED); @@ -132,7 +163,7 @@ public class NotifyDiscord { Sentinel.log.info(e.toString()); } } - public static void usedEntity(Player player, Entity e, boolean denied, boolean deoped, boolean banned, boolean logged) { + public static void usedEntity(Player player, Entity e, boolean denied, boolean deoped, boolean punished, boolean logged) { ServerUtils.sendDebugMessage("Creating useEntity Webhook..."); DiscordWebhook webhook = new DiscordWebhook(Config.webhook); webhook.setAvatarUrl("https://r2.e-z.host/d440b58a-ba90-4839-8df6-8bba298cf817/3lwit5nt.png"); @@ -142,12 +173,13 @@ public class NotifyDiscord { .setTitle("The use of a dangerous entity has been detected!") .setDescription( Emojis.rightSort + " **Player:** " + player.getName() + " " + Emojis.member + "\\n" + - Emojis.rightSort + " **Entity:** " + e.getType() + " " + Emojis.nuke + "\\n" + Emojis.rightSort + " **Entity:** " + e.getType() + " " + Emojis.nuke + "\\n" + + Emojis.space + Emojis.rightDoubleArrow + " **Location:** X: " + e.getLocation().getX() + " Y: " + e.getLocation().getY() + " Z: " + e.getLocation().getZ() + "\\n" ) .addField("Actions:", Emojis.rightSort + " **Denied:** " + TextUtils.boolString(denied,Emojis.success, Emojis.failure) + "\\n" + Emojis.rightSort + " **De-oped:** " + TextUtils.boolString(deoped,Emojis.success, Emojis.failure) + "\\n" + - Emojis.rightSort + " **Banned:** " + TextUtils.boolString(banned,Emojis.success, Emojis.failure) + "\\n"+ + Emojis.rightSort + " **Punished:** " + TextUtils.boolString(punished,Emojis.success, Emojis.failure) + "\\n"+ Emojis.rightSort + " **Logged:** " + TextUtils.boolString(logged,Emojis.success, Emojis.failure), false ) .setColor(Color.RED); diff --git a/src/main/java/io/github/thetrouper/sentinel/server/util/Notifications/NotifyTrusted.java b/src/main/java/io/github/thetrouper/sentinel/server/util/Notifications/NotifyTrusted.java index 57c9b2a..c6213e5 100644 --- a/src/main/java/io/github/thetrouper/sentinel/server/util/Notifications/NotifyTrusted.java +++ b/src/main/java/io/github/thetrouper/sentinel/server/util/Notifications/NotifyTrusted.java @@ -15,18 +15,35 @@ import org.bukkit.event.server.ServerEvent; import org.bukkit.inventory.ItemStack; public class NotifyTrusted { - public static void command(Player p, String command, boolean denied, boolean deoped, boolean banned, boolean logged) { - TextComponent notification = new TextComponent(TextUtils.prefix(TextUtils.color("&b&n" + p.getName() + "&7 Has just attempted a dangerous command!"))); + public static void specific(Player p, String command, boolean denied, boolean deoped, boolean punished, boolean logged) { + TextComponent notification = new TextComponent(TextUtils.prefix("§b§n" + p.getName() + "§7 Has just attempted a specific command!")); notification.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new Text( - TextUtils.color( - "&8]==-- &d&lSentinel &8--==[" + - "\n&bPlayer: &f" + p.getName() + - "\n&bCommand: &f" + command + - "\n&bDenied: " + TextUtils.boolString(denied,"&a✔","&c✘") + - "\n&bDeoped: " + TextUtils.boolString(deoped,"&a✔","&c✘") + - "\n&bBanned: " + TextUtils.boolString(banned,"&a✔","&c✘") + - "\n&bLogged: " + TextUtils.boolString(logged,"&a✔","&c✘") - ) + "§8]==-- §d§lSentinel §8--==[" + + "\n§bPlayer: §f" + p.getName() + + "\n§bCommand: §f" + command + + "\n§bDenied: " + TextUtils.boolString(denied,"§a\u2714","§c\u2718") + + "\n§bDeoped: " + TextUtils.boolString(deoped,"§a\u2714","§c\u2718") + + "\n§bPunished: " + TextUtils.boolString(punished,"§a\u2714","§c\u2718") + + "\n§bLogged: " + TextUtils.boolString(logged,"§a\u2714","§c\u2718") + + ))); + for (Player trustedPlayer : Bukkit.getOnlinePlayers()) { + if (Sentinel.isTrusted(trustedPlayer)) { + trustedPlayer.spigot().sendMessage(notification); + } + } + } + public static void command(Player p, String command, boolean denied, boolean deoped, boolean punished, boolean logged) { + TextComponent notification = new TextComponent(TextUtils.prefix("§b§n" + p.getName() + "§7 Has just attempted a dangerous command!")); + notification.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new Text( + "§8]==-- §d§lSentinel §8--==[" + + "\n§bPlayer: §f" + p.getName() + + "\n§bCommand: §f" + command + + "\n§bDenied: " + TextUtils.boolString(denied,"§a\u2714","§c\u2718") + + "\n§bDeoped: " + TextUtils.boolString(deoped,"§a\u2714","§c\u2718") + + "\n§bPunished: " + TextUtils.boolString(punished,"§a\u2714","§c\u2718") + + "\n§bLogged: " + TextUtils.boolString(logged,"§a\u2714","§c\u2718") + ))); for (Player trustedPlayer : Bukkit.getOnlinePlayers()) { @@ -35,21 +52,20 @@ public class NotifyTrusted { } } } - public static void NBT(Player p, ItemStack item, boolean removed, boolean deoped, boolean gms, boolean banned, boolean logged) { - TextComponent notification = new TextComponent(TextUtils.prefix(TextUtils.color("&b&n" + p.getName() + "&7 Has just attempted to use a dangerous NBT item!"))); + public static void NBT(Player p, ItemStack item, boolean removed, boolean deoped, boolean gms, boolean punished, boolean logged) { + TextComponent notification = new TextComponent(TextUtils.prefix("§b§n" + p.getName() + "§7 Has just attempted to use a dangerous NBT item!")); notification.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new Text( - TextUtils.color( - "&8]==-- &d&lSentinel &8--==[" + - "\n&bPlayer: &f" + p.getName() + - "\n&bItemType: &f" + item.getType() + - "\n&bRemoved: " + TextUtils.boolString(removed,"&a✔","&c✘") + - "\n&bDeoped: " + TextUtils.boolString(deoped,"&a✔","&c✘") + - "\n&bRevert GM: " + TextUtils.boolString(gms, "&a✔", "&c✘") + - "\n&bBanned: " + TextUtils.boolString(banned,"&a✔","&c✘") + - "\n&bLogged: " + TextUtils.boolString(logged,"&a✔","&c✘") + - "\n&7(Click to copy NBT)" + "§8]==-- §d§lSentinel §8--==[" + + "\n§bPlayer: §f" + p.getName() + + "\n§bItemType: §f" + item.getType() + + "\n§bRemoved: " + TextUtils.boolString(removed,"§a\u2714","§c\u2718") + + "\n§bDeoped: " + TextUtils.boolString(deoped,"§a\u2714","§c\u2718") + + "\n§bRevert GM: " + TextUtils.boolString(gms, "§a\u2714","§c\u2718") + + "\n§bPunished: " + TextUtils.boolString(punished,"§a\u2714","§c\u2718") + + "\n§bLogged: " + TextUtils.boolString(logged,"§a\u2714","§c\u2718") + + "\n§7(Click to copy NBT)" - )))); + ))); notification.setClickEvent(new ClickEvent(ClickEvent.Action.COPY_TO_CLIPBOARD, new String(item.getType().toString().toLowerCase() + item.getItemMeta().getAsString()))); for (Player trustedPlayer : Bukkit.getOnlinePlayers()) { if (Sentinel.isTrusted(trustedPlayer)) { @@ -57,19 +73,19 @@ public class NotifyTrusted { } } } - public static void placeBlock(Player p, Block b, boolean removed, boolean deoped, boolean banned, boolean logged) { - TextComponent notification = new TextComponent(TextUtils.prefix(TextUtils.color("&b&n" + p.getName() + "&7 Has just attempted to place a dangerous block!"))); - notification.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new Text(TextUtils.color( - "&8]==-- &d&lSentinel &8--==[" + - "\n&bPlayer: &f" + p.getName() + - "\n&bBlockType: &f" + b.getType() + - "\n&bLocation: " + b.getX() + " " + b.getY() + " " + b.getZ() + - "\n&bRemoved: " + TextUtils.boolString(removed,"&a✔","&c✘") + - "\n&bDeoped: " + TextUtils.boolString(deoped,"&a✔","&c✘") + - "\n&bBanned: " + TextUtils.boolString(banned,"&a✔","&c✘") + - "\n&bLogged: " + TextUtils.boolString(logged,"&a✔","&c✘") + - "\n&7(Click to Teleport)" - )))); + public static void placeBlock(Player p, Block b, boolean removed, boolean deoped, boolean punished, boolean logged) { + TextComponent notification = new TextComponent(TextUtils.prefix("§b§n" + p.getName() + "§7 Has just attempted to place a dangerous block!")); + notification.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new Text( + "§8]==-- §d§lSentinel §8--==[" + + "\n§bPlayer: §f" + p.getName() + + "\n§bBlockType: §f" + b.getType() + + "\n§bLocation: " + b.getX() + " " + b.getY() + " " + b.getZ() + + "\n§bRemoved: " + TextUtils.boolString(removed,"§a\u2714","§c\u2718") + + "\n§bDeoped: " + TextUtils.boolString(deoped,"§a\u2714","§c\u2718") + + "\n§bPunished: " + TextUtils.boolString(punished,"§a\u2714","§c\u2718") + + "\n§bLogged: " + TextUtils.boolString(logged,"§a\u2714","§c\u2718") + + "\n§7(Click to Teleport)" + ))); notification.setClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, "tp " + p.getName())); for (Player trustedPlayer : Bukkit.getOnlinePlayers()) { if (Sentinel.isTrusted(trustedPlayer)) { @@ -77,19 +93,19 @@ public class NotifyTrusted { } } } - public static void usedBlock(Player p, Block b, boolean denied, boolean deoped, boolean banned, boolean logged) { - TextComponent notification = new TextComponent(TextUtils.prefix(TextUtils.color("&b&n" + p.getName() + "&7 Has just attempted to use a dangerous block!"))); - notification.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new Text(TextUtils.color( - "&8]==-- &d&lSentinel &8--==[" + - "\n&bPlayer: &f" + p.getName() + - "\n&bBlockType: &f" + b.getType() + - "\n&bLocation: " + b.getX() + " " + b.getY() + " " + b.getZ() + - "\n&bDenied: " + TextUtils.boolString(denied,"&a✔","&c✘") + - "\n&bDeoped: " + TextUtils.boolString(deoped,"&a✔","&c✘") + - "\n&bBanned: " + TextUtils.boolString(banned,"&a✔","&c✘") + - "\n&bLogged: " + TextUtils.boolString(logged,"&a✔","&c✘") + - "\n&7(Click to Teleport)" - )))); + public static void usedBlock(Player p, Block b, boolean denied, boolean deoped, boolean punished, boolean logged) { + TextComponent notification = new TextComponent(TextUtils.prefix("§b§n" + p.getName() + "§7 Has just attempted to use a dangerous block!")); + notification.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new Text( + "§8]==-- §d§lSentinel §8--==[" + + "\n§bPlayer: §f" + p.getName() + + "\n§bBlockType: §f" + b.getType() + + "\n§bLocation: " + b.getX() + " " + b.getY() + " " + b.getZ() + + "\n§bDenied: " + TextUtils.boolString(denied,"§a\u2714","§c\u2718") + + "\n§bDeoped: " + TextUtils.boolString(deoped,"§a\u2714","§c\u2718") + + "\n§bPunished: " + TextUtils.boolString(punished,"§a\u2714","§c\u2718") + + "\n§bLogged: " + TextUtils.boolString(logged,"§a\u2714","§c\u2718") + + "\n§7(Click to Teleport)" + ))); notification.setClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, "tp " + p.getName())); for (Player trustedPlayer : Bukkit.getOnlinePlayers()) { if (Sentinel.isTrusted(trustedPlayer)) { @@ -97,19 +113,19 @@ public class NotifyTrusted { } } } - public static void usedEntity(Player p, Entity e, boolean denied, boolean deoped, boolean banned, boolean logged) { - TextComponent notification = new TextComponent(TextUtils.prefix(TextUtils.color("&b&n" + p.getName() + "&7 Has just attempted to use a dangerous entity!"))); - notification.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new Text(TextUtils.color( - "&8]==-- &d&lSentinel &8--==[" + - "\n&bPlayer: &f" + p.getName() + - "\n&bEntityType: &f" + e.getType() + - "\n&bLocation: " + e.getLocation().getX() + " " + e.getLocation().getY() + " " + e.getLocation().getZ() + - "\n&bDenied: " + TextUtils.boolString(denied,"&a✔","&c✘") + - "\n&bDeoped: " + TextUtils.boolString(deoped,"&a✔","&c✘") + - "\n&bBanned: " + TextUtils.boolString(banned,"&a✔","&c✘") + - "\n&bLogged: " + TextUtils.boolString(logged,"&a✔","&c✘") + - "\n&7(Click to Teleport)" - )))); + public static void usedEntity(Player p, Entity e, boolean denied, boolean deoped, boolean punished, boolean logged) { + TextComponent notification = new TextComponent(TextUtils.prefix("§b§n" + p.getName() + "§7 Has just attempted to use a dangerous entity!")); + notification.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new Text( + "§8]==-- §d§lSentinel §8--==[" + + "\n§bPlayer: §f" + p.getName() + + "\n§bEntityType: §f" + e.getType() + + "\n§bLocation: " + e.getLocation().getX() + " " + e.getLocation().getY() + " " + e.getLocation().getZ() + + "\n§bDenied: " + TextUtils.boolString(denied,"§a\u2714","§c\u2718") + + "\n§bDeoped: " + TextUtils.boolString(deoped,"§a\u2714","§c\u2718") + + "\n§bPunished: " + TextUtils.boolString(punished,"§a\u2714","§c\u2718") + + "\n§bLogged: " + TextUtils.boolString(logged,"§a\u2714","§c\u2718") + + "\n§7(Click to Teleport)" + ))); notification.setClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, "tp " + p.getName())); for (Player trustedPlayer : Bukkit.getOnlinePlayers()) { if (Sentinel.isTrusted(trustedPlayer)) { diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index b4a41e1..ad590a7 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -1,4 +1,4 @@ -# Sentinel 0.0.2 +# Sentinel 0.1.5 # ____ __ ___ #/\ _`\ /\ \__ __ /\_ \ #\ \,\L\_\ __ ___\ \ ,_\/\_\ ___ __\//\ \ @@ -11,7 +11,7 @@ # Be sure to check out their amazing discord bot! config : plugin: - license: "beta" # if you are a beta tester, leave this value as "beta" + key: "beta" # if you are a beta tester, leave this value as "beta" # -------------------------------- # Anti-Nuke Setup (Do this first) # -------------------------------- @@ -22,26 +22,34 @@ config : block-specific: true # Defaulted true | Weather or not to block ALL plugin specific commands from non-trusted members (EX: minecraft:execute) these will not be logged. prevent-nbt: true # Defaulted true | Should NBT items be blocked from the creative hotbar prevent-cmdblocks: true # Defaulted true | Should all command block actions be blocked + cmdblock-op-check: true # Defaulted true | Will check if a player is op'd before preforming actions against command blocks (To prevent spam from non oped users attempting command blocks, which they cant by default) dangerous: # These commands can only be run by "trusted" users - "op" - "deop" - "stop" + - "restart" - "execute" # Could run commands as a trusted player - "sudo" # same as above + - "esudo" # WATCH OUT FOR ESSENTIALS ALIASES !!! - "fill" # Most client side nukers use it - "setblock" # could setblock a command block with anything - "data" # Could modify a command block to whatever they wanted + - "whitelist" # Could add other players to the whitelist log-dangerous: true # Default true | Weather or not to log to discord when a dangerous command is executed log-cmdblocks: true # Defaulted true | Log attempts of command-block place-ery in discord log-nbt: true # Defaulted true | Should items and their NBT's be logged to discord + log-specific: false # Default false | Weather or not to log to discord when a plugin specific command is executed logged: # Commands that will always be logged to discord when executed. - - "gamemode" - "give" + - "item" deop: true # Defaulted true | This will remove an untrusted player's operator permissions whenever they attempt dangerous actions - ban: false # Default false | Weather or not to ban a player if they attempt something dangerous. - nbt-punish: false # Defaulted false | This will ban a player when they attempt to use an NBT item - cmdblock-punish: false # Defaulted false | This will ban a player when they attempt to use a command block - command-punish: true # Defaulted true | This will ban a player when they attempt to use a dangerous command + nbt-punish: false # Defaulted false | This will punish a player when they attempt to use an NBT item + cmdblock-punish: false # Defaulted false | This will punish a player when they attempt to use a command block + command-punish: false # Defaulted false | This will ban punish player when they attempt to use a dangerous command + specific-punish: false # Defaulted false | This will punish a player when they run a specific command (Not recomended) + punish-commands: # Commands to run when a dangerous action is to be punished. Use %player% for the punished player's name + - "smite %player%" + - "ban %player% ]=- Sentinel -=[ You have been banned for attempting a dangerous action. If you believe this to be a mistake, please contact the server owner." reop-command: false # Defaulted false | This enables the command allowing trusted players to op themselves if they get deoped. # ------------------------------- # Chat Filter Setup & AntiSpam @@ -108,7 +116,7 @@ config : - grape - grass - harass - - hot water + - hotwater - identit - kassa - kassi