diff --git a/.gitignore b/.gitignore deleted file mode 100644 index 1bf30b3..0000000 --- a/.gitignore +++ /dev/null @@ -1,45 +0,0 @@ -.gradle -build/ -!gradle/wrapper/gradle-wrapper.jar -!**/src/main/**/build/ -!**/src/test/**/build/ - -### IntelliJ IDEA ### -.idea/modules.xml -.idea/jarRepositories.xml -.idea/compiler.xml -.idea/libraries/ -*.iws -*.iml -*.ipr -out/ -!**/src/main/**/out/ -!**/src/test/**/out/ - -### Eclipse ### -.apt_generated -.classpath -.factorypath -.project -.settings -.springBeans -.sts4-cache -bin/ -!**/src/main/**/bin/ -!**/src/test/**/bin/ - -### NetBeans ### -/nbproject/private/ -/nbbuild/ -/dist/ -/nbdist/ -/.nb-gradle/ - -### VS Code ### -.vscode/ - -### Mac OS ### -.DS_Store - -### Idea ### -.idea \ No newline at end of file diff --git a/.gradle/7.5.1/checksums/checksums.lock b/.gradle/7.5.1/checksums/checksums.lock new file mode 100644 index 0000000..6aed38d Binary files /dev/null and b/.gradle/7.5.1/checksums/checksums.lock differ diff --git a/.gradle/7.5.1/checksums/md5-checksums.bin b/.gradle/7.5.1/checksums/md5-checksums.bin new file mode 100644 index 0000000..4fad43f Binary files /dev/null and b/.gradle/7.5.1/checksums/md5-checksums.bin differ diff --git a/.gradle/7.5.1/checksums/sha1-checksums.bin b/.gradle/7.5.1/checksums/sha1-checksums.bin new file mode 100644 index 0000000..3e42c84 Binary files /dev/null and b/.gradle/7.5.1/checksums/sha1-checksums.bin differ diff --git a/.gradle/7.5.1/dependencies-accessors/dependencies-accessors.lock b/.gradle/7.5.1/dependencies-accessors/dependencies-accessors.lock new file mode 100644 index 0000000..8e1b9a0 Binary files /dev/null and b/.gradle/7.5.1/dependencies-accessors/dependencies-accessors.lock differ diff --git a/.gradle/7.5.1/dependencies-accessors/gc.properties b/.gradle/7.5.1/dependencies-accessors/gc.properties new file mode 100644 index 0000000..e69de29 diff --git a/.gradle/7.5.1/executionHistory/executionHistory.bin b/.gradle/7.5.1/executionHistory/executionHistory.bin new file mode 100644 index 0000000..da9486f Binary files /dev/null and b/.gradle/7.5.1/executionHistory/executionHistory.bin differ diff --git a/.gradle/7.5.1/executionHistory/executionHistory.lock b/.gradle/7.5.1/executionHistory/executionHistory.lock new file mode 100644 index 0000000..ffd7142 Binary files /dev/null and b/.gradle/7.5.1/executionHistory/executionHistory.lock differ diff --git a/.gradle/7.5.1/fileChanges/last-build.bin b/.gradle/7.5.1/fileChanges/last-build.bin new file mode 100644 index 0000000..f76dd23 Binary files /dev/null and b/.gradle/7.5.1/fileChanges/last-build.bin differ diff --git a/.gradle/7.5.1/fileHashes/fileHashes.bin b/.gradle/7.5.1/fileHashes/fileHashes.bin new file mode 100644 index 0000000..127f007 Binary files /dev/null and b/.gradle/7.5.1/fileHashes/fileHashes.bin differ diff --git a/.gradle/7.5.1/fileHashes/fileHashes.lock b/.gradle/7.5.1/fileHashes/fileHashes.lock new file mode 100644 index 0000000..ab25736 Binary files /dev/null and b/.gradle/7.5.1/fileHashes/fileHashes.lock differ diff --git a/.gradle/7.5.1/fileHashes/resourceHashesCache.bin b/.gradle/7.5.1/fileHashes/resourceHashesCache.bin new file mode 100644 index 0000000..cca3e20 Binary files /dev/null and b/.gradle/7.5.1/fileHashes/resourceHashesCache.bin differ diff --git a/.gradle/7.5.1/gc.properties b/.gradle/7.5.1/gc.properties new file mode 100644 index 0000000..e69de29 diff --git a/.gradle/buildOutputCleanup/buildOutputCleanup.lock b/.gradle/buildOutputCleanup/buildOutputCleanup.lock new file mode 100644 index 0000000..bbe0e22 Binary files /dev/null and b/.gradle/buildOutputCleanup/buildOutputCleanup.lock differ diff --git a/.gradle/buildOutputCleanup/cache.properties b/.gradle/buildOutputCleanup/cache.properties new file mode 100644 index 0000000..7b397cd --- /dev/null +++ b/.gradle/buildOutputCleanup/cache.properties @@ -0,0 +1,2 @@ +#Mon Jan 22 14:15:34 ICT 2024 +gradle.version=7.5.1 diff --git a/.gradle/buildOutputCleanup/outputFiles.bin b/.gradle/buildOutputCleanup/outputFiles.bin new file mode 100644 index 0000000..b684a37 Binary files /dev/null and b/.gradle/buildOutputCleanup/outputFiles.bin differ diff --git a/.gradle/file-system.probe b/.gradle/file-system.probe new file mode 100644 index 0000000..4367e53 Binary files /dev/null and b/.gradle/file-system.probe differ diff --git a/.gradle/vcs-1/gc.properties b/.gradle/vcs-1/gc.properties new file mode 100644 index 0000000..e69de29 diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..26d3352 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,3 @@ +# Default ignored files +/shelf/ +/workspace.xml diff --git a/.idea/.name b/.idea/.name new file mode 100644 index 0000000..b4d14b6 --- /dev/null +++ b/.idea/.name @@ -0,0 +1 @@ +tudubucket \ No newline at end of file diff --git a/.idea/compiler.xml b/.idea/compiler.xml new file mode 100644 index 0000000..b0bead3 --- /dev/null +++ b/.idea/compiler.xml @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/discord.xml b/.idea/discord.xml new file mode 100644 index 0000000..8cf359d --- /dev/null +++ b/.idea/discord.xml @@ -0,0 +1,7 @@ + + + + + \ No newline at end of file diff --git a/.idea/encodings.xml b/.idea/encodings.xml new file mode 100644 index 0000000..aa00ffa --- /dev/null +++ b/.idea/encodings.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/.idea/gradle.xml b/.idea/gradle.xml new file mode 100644 index 0000000..592fdc7 --- /dev/null +++ b/.idea/gradle.xml @@ -0,0 +1,19 @@ + + + + + + + \ No newline at end of file diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml new file mode 100644 index 0000000..df543e3 --- /dev/null +++ b/.idea/inspectionProfiles/Project_Default.xml @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/.idea/jarRepositories.xml b/.idea/jarRepositories.xml new file mode 100644 index 0000000..a33a07b --- /dev/null +++ b/.idea/jarRepositories.xml @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/kotlinc.xml b/.idea/kotlinc.xml new file mode 100644 index 0000000..7e340a7 --- /dev/null +++ b/.idea/kotlinc.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..715593d --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/modules/tudubucket.main.iml b/.idea/modules/tudubucket.main.iml new file mode 100644 index 0000000..a589521 --- /dev/null +++ b/.idea/modules/tudubucket.main.iml @@ -0,0 +1,13 @@ + + + + + + + SPIGOT + + 1 + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..2c9deb1 --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/LICENSE b/LICENSE index ce18c15..261eeb9 100644 --- a/LICENSE +++ b/LICENSE @@ -1,13 +1,201 @@ - DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE - Version 2, December 2004 + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ - Copyright (C) 2023 LangDuaMC developers + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - Everyone is permitted to copy and distribute verbatim or modified - copies of this license document, and changing it is allowed as long - as the name is changed. + 1. Definitions. - DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. - 0. You just DO WHAT THE FUCK YOU WANT TO. \ No newline at end of file + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/README.MD b/README.MD index 72c9d2d..caa45da 100644 --- a/README.MD +++ b/README.MD @@ -1,10 +1,2 @@ -# WhitelistedAdmins - Protect from OP brute. -[![CodeQL](https://github.com/LangDuaMC/WhitelistedAdmin/actions/workflows/codeql.yml/badge.svg)](https://github.com/LangDuaMC/WhitelistedAdmin/actions/workflows/codeql.yml) - -- ### [Download](https://github.com/LangDuaMC/WhitelistedAdmin/actions/workflows/gradle.yml) - -## Function - -Basically force users with administrator permissions to whitelist their IP address. - -### Have fun! +# WhitelistedAdmin +hallo diff --git a/WhitelistedAdmin.iml b/WhitelistedAdmin.iml new file mode 100644 index 0000000..2e86d14 --- /dev/null +++ b/WhitelistedAdmin.iml @@ -0,0 +1,41 @@ + + + + + + + SPIGOT + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/build.gradle b/build.gradle new file mode 100644 index 0000000..d521ce4 --- /dev/null +++ b/build.gradle @@ -0,0 +1,49 @@ +/* + * This file was generated by the Gradle 'init' task. + */ + +plugins { + id 'java' + id 'maven-publish' +} + +repositories { + mavenLocal() + maven { + url = uri('https://hub.spigotmc.org/nexus/content/repositories/snapshots/') + } + + maven { + url = uri('https://oss.sonatype.org/content/groups/public/') + } + + maven { + url = uri('https://repo.extendedclip.com/content/repositories/placeholderapi/') + } + + maven { + url = uri('https://repo.maven.apache.org/maven2/') + } +} + +dependencies { + compileOnly 'org.spigotmc:spigot-api:1.18.2-R0.1-SNAPSHOT' + compileOnly 'me.clip:placeholderapi:2.11.2' +} + +group = 'ankita' +version = '1' +description = 'WhitelistedAdmin' +java.sourceCompatibility = JavaVersion.VERSION_1_8 + +publishing { + publications { + maven(MavenPublication) { + from(components.java) + } + } +} + +tasks.withType(JavaCompile) { + options.encoding = 'UTF-8' +} diff --git a/build.gradle.kts b/build.gradle.kts deleted file mode 100644 index 16685a3..0000000 --- a/build.gradle.kts +++ /dev/null @@ -1,91 +0,0 @@ -import org.apache.tools.ant.filters.FixCrLfFilter -import org.apache.tools.ant.filters.ReplaceTokens -import org.jetbrains.kotlin.gradle.tasks.KotlinCompile -import java.io.ByteArrayOutputStream - -plugins { - kotlin("jvm") version "1.8.21" - id("com.github.johnrengelman.shadow") version "7.0.0" - id("com.github.gmazzo.buildconfig") version "3.0.0" - id("org.jlleitschuh.gradle.ktlint") version "11.3.2" -} - -group = "net.langdua" -version = "1.0.0" - -repositories { - maven(url = "https://papermc.io/repo/repository/maven-public/") - maven(url = "https://repo.extendedclip.com/content/repositories/placeholderapi/") - maven(url = "https://s01.oss.sonatype.org/content/repositories/snapshots/") { - name = "sonatype-oss-snapshots1" - } - mavenCentral() -} - -val minecraftVersion: String = project.extra["minecraftVersion"].toString() -val bstatsID: String = project.extra["bstatsID"].toString() - -dependencies { - // PaperMC Dependency - compileOnly("com.destroystokyo.paper", "paper-api", "$minecraftVersion-R0.1-SNAPSHOT") - compileOnly("me.clip", "placeholderapi", "2.11.3") - implementation("org.bstats", "bstats-bukkit", "3.0.2") - implementation("net.kyori", "adventure-text-minimessage", "4.13.1") - - // Add your dependencies here - // Examples - // implementation("io.ktor", "ktor-client", "1.4.0") // Would be shaded into the final jar - // compileOnly("io.ktor", "ktor-client", "1.4.0") // Only used on compile time - implementation(kotlin("stdlib")) -} - -buildConfig { - className("BuildConfig") - packageName("$group.$name") - val commit = getGitHash() - val branch = getGitBranch() - buildConfigField("String", "GIT_COMMIT", "\"$commit\"") - buildConfigField("String", "GIT_BRANCH", "\"$branch\"") - buildConfigField("Int", "BSTATS_ID", bstatsID) -} - -fun getGitHash(): String { - val stdout = ByteArrayOutputStream() - exec { - commandLine("git", "rev-parse", "--short", "HEAD") - standardOutput = stdout - } - return stdout.toString("UTF-8").trim() -} - -fun getGitBranch(): String { - val stdout = ByteArrayOutputStream() - exec { - commandLine("git", "rev-parse", "--abbrev-ref", "HEAD") - standardOutput = stdout - } - return stdout.toString("UTF-8").trim() -} - -tasks { - processResources { - filter(FixCrLfFilter::class) - filter(ReplaceTokens::class, "tokens" to mapOf("version" to project.version)) - filteringCharset = "UTF-8" - } - jar { - // Disabled, because we use the shadowJar task for building our jar - enabled = false - } - shadowJar { - relocate("org.bstats", "net.langdua.reflected.wladmin.org.bstats") - } - build { - dependsOn(shadowJar) - } - withType { - kotlinOptions { - jvmTarget = "17" - } - } -} diff --git a/build/classes/java/main/ankita/tudubucket/DiscordIntegration.class b/build/classes/java/main/ankita/tudubucket/DiscordIntegration.class new file mode 100644 index 0000000..a630831 Binary files /dev/null and b/build/classes/java/main/ankita/tudubucket/DiscordIntegration.class differ diff --git a/build/classes/java/main/ankita/tudubucket/SendMessage.class b/build/classes/java/main/ankita/tudubucket/SendMessage.class new file mode 100644 index 0000000..edb136c Binary files /dev/null and b/build/classes/java/main/ankita/tudubucket/SendMessage.class differ diff --git a/build/classes/java/main/ankita/tudubucket/commands/WhitelistAdminCommand.class b/build/classes/java/main/ankita/tudubucket/commands/WhitelistAdminCommand.class new file mode 100644 index 0000000..a4b3308 Binary files /dev/null and b/build/classes/java/main/ankita/tudubucket/commands/WhitelistAdminCommand.class differ diff --git a/build/classes/java/main/ankita/tudubucket/main.class b/build/classes/java/main/ankita/tudubucket/main.class new file mode 100644 index 0000000..b18e7c0 Binary files /dev/null and b/build/classes/java/main/ankita/tudubucket/main.class differ diff --git a/build/libs/tudubucket-1.jar b/build/libs/tudubucket-1.jar new file mode 100644 index 0000000..cd4fdcf Binary files /dev/null and b/build/libs/tudubucket-1.jar differ diff --git a/build/resources/main/config.yml b/build/resources/main/config.yml new file mode 100644 index 0000000..737e68e --- /dev/null +++ b/build/resources/main/config.yml @@ -0,0 +1,65 @@ +# WhitelistedAdmin configuration + +# Placeholders list: +# {player}: Player name +# {address}: Player IP Address when joined +# {current_address}: Player IP Address in the configuration + +# Date format for messages +date-format: "yyyy-MM-dd HH:MM:SS" + +# List of permissions to check whether the joined player is an admin or not (only if they are not whitelisted) +# Wildcards (e.g. "bukkit.*") are supported, it will check if the player has any permission starting with "bukkit.", for example. +admin-permissions: + - "bukkit.plugin" + - "bukkit.?" + - "idk" + +# Discord Integration support +integrations: + discord: + enable: true + # Method: "webhook" or "bot" + method: "bot" + + bot: + token: "insert-your-bot-token-here" + # For more information about getting a Channel ID, refer to https://support.discord.com/hc/en-us/articles/206346498 + alert-channel-id: "0123456789123456789" + + webhook: + url: "https://discord.com/api/webhooks/0123456789123456789/webhook-token" + +# Hide the plugin +plugin: + hide: true + message-unknown-command: 'Unknown command. Type "/help" for help.' + +# Messages to announce to integrations, placeholder, and color code supported +messages: + logging: + unknown-admin: "{time} {player} have matched administrator permissions but not have whitelisted!" + invalid-address: "{time} {player} have different IP address with whitelisted! Currently whitelisted address: {current_address}" + success-whitelisted-ip: "{time} {player} have been whitelisted with IP address {current_address}" + success-removed-admin: "{time} {player} have been removed from administrator list" + console: + configuration-reloaded: 'Configuration reloaded!' + invalid-command: 'Invalid command argument!' + unknown-admin: "{time} {player} have matched administrator permissions but not have whitelisted!" + invalid-address: "{time} {player} have different IP address with whitelisted! Current whitelisted address: {current_address}" + success-whitelisted-ip: "{time} {player} have been whitelisted with IP address {current_address}" + success-removed-admin: "{time} {player} have been removed from administrator list" + integration: + unknown-admin: "{time} {player} have matched administrator permissions but not have whitelisted!" + invalid-address: "{time} {player} have different IP address with whitelisted! Current whitelisted address: {current_address}" + success-whitelisted-ip: "{time} {player} have been whitelisted with IP address {current_address}" + success-removed-admin: "{time} {player} have been removed from administrator list" + kick: + unknown-admin: "You have matched administrator permissions but not have whitelisted!" + invalid-address: "You have a different IP address than the whitelisted one!" + + +# List of whitelisted administrators and their IP address +whitelisted-admins: + admin1: "127.0.0.1" + admin2: "127.0.0.1" diff --git a/build/resources/main/plugin.yml b/build/resources/main/plugin.yml new file mode 100644 index 0000000..1dfd91e --- /dev/null +++ b/build/resources/main/plugin.yml @@ -0,0 +1,17 @@ +name: WhitelistedAdmin +version: '${project.version}' +main: ankita.tudubucket.main +api-version: 1.18 +authors: [tudubucket] +description: A Minecraft plugin for Server Administrator safety purposes +website: https://tudubucket.dev +prefix: WhitelistedAdmin +softdepend: [PlaceholderAPI] +commands: + whitelist-admin: + description: Main command for WhitelistedAdmin plugin + aliases: + - wla + - wladmin + permission: whitelistedadmin.wladmin + diff --git a/build/tmp/compileJava/previous-compilation-data.bin b/build/tmp/compileJava/previous-compilation-data.bin new file mode 100644 index 0000000..136a5ac Binary files /dev/null and b/build/tmp/compileJava/previous-compilation-data.bin differ diff --git a/build/tmp/jar/MANIFEST.MF b/build/tmp/jar/MANIFEST.MF new file mode 100644 index 0000000..59499bc --- /dev/null +++ b/build/tmp/jar/MANIFEST.MF @@ -0,0 +1,2 @@ +Manifest-Version: 1.0 + diff --git a/gradle.properties b/gradle.properties deleted file mode 100644 index 0ae7e88..0000000 --- a/gradle.properties +++ /dev/null @@ -1,3 +0,0 @@ -kotlin.code.style=official -minecraftVersion=1.16.5 -bstatsID=18465 \ No newline at end of file diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 60c76b3..ae04661 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.4.2-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.5.1-bin.zip zipStoreBase=GRADLE_USER_HOME -zipStorePath=wrapper/dists \ No newline at end of file +zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew old mode 100755 new mode 100644 index 1b6c787..a69d9cb --- a/gradlew +++ b/gradlew @@ -205,6 +205,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 107acd3..f127cfd 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,7 @@ if "%OS%"=="Windows_NT" setlocal set DIRNAME=%~dp0 -if "%DIRNAME%" == "" set DIRNAME=. +if "%DIRNAME%"=="" set DIRNAME=. set APP_BASE_NAME=%~n0 set APP_HOME=%DIRNAME% @@ -40,7 +40,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 +75,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/pom.xml b/pom.xml new file mode 100644 index 0000000..0b378fb --- /dev/null +++ b/pom.xml @@ -0,0 +1,85 @@ + + + 4.0.0 + + ankita + tudubucket + 1 + jar + + WhitelistedAdmin + + A Minecraft plugin for Server Administrator safety purposes + + 1.8 + UTF-8 + + https://tudubucket.dev + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.8.1 + + ${java.version} + ${java.version} + + + + org.apache.maven.plugins + maven-shade-plugin + 3.2.4 + + + package + + shade + + + false + + + + + + + + src/main/resources + true + + + + + + spigotmc-repo + https://hub.spigotmc.org/nexus/content/repositories/snapshots/ + + + sonatype + https://oss.sonatype.org/content/groups/public/ + + + placeholderapi + https://repo.extendedclip.com/content/repositories/placeholderapi/ + + + + + + org.spigotmc + spigot-api + 1.18.2-R0.1-SNAPSHOT + provided + + + me.clip + placeholderapi + 2.11.2 + provided + + + diff --git a/settings.gradle b/settings.gradle new file mode 100644 index 0000000..3c51985 --- /dev/null +++ b/settings.gradle @@ -0,0 +1,5 @@ +/* + * This file was generated by the Gradle 'init' task. + */ + +rootProject.name = 'tudubucket' diff --git a/settings.gradle.kts b/settings.gradle.kts deleted file mode 100644 index 6344474..0000000 --- a/settings.gradle.kts +++ /dev/null @@ -1,2 +0,0 @@ - -rootProject.name = "WhitelistedAdmin" diff --git a/src/main/java/ankita/tudubucket/DiscordIntegration.java b/src/main/java/ankita/tudubucket/DiscordIntegration.java new file mode 100644 index 0000000..af9c515 --- /dev/null +++ b/src/main/java/ankita/tudubucket/DiscordIntegration.java @@ -0,0 +1,72 @@ +package ankita.tudubucket; + +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.configuration.file.FileConfiguration; + +import javax.sql.rowset.spi.SyncFactoryException; +import java.io.IOException; +import java.io.OutputStream; +import java.net.HttpURLConnection; +import java.net.URL; +import java.nio.charset.StandardCharsets; +import java.util.logging.Logger; + +import static org.bukkit.Bukkit.getLogger; + +public class DiscordIntegration { + + private final String sendMethod; + private final String botToken; + private final String webhookUrl; + private final String alertChannelId; + + public DiscordIntegration(FileConfiguration config) { + ConfigurationSection discordConfig = config.getConfigurationSection("integrations.discord"); + assert discordConfig != null; + sendMethod = discordConfig.getString("method"); + botToken = discordConfig.getString("bot-token"); + webhookUrl = discordConfig.getString("webhook-url"); + alertChannelId = discordConfig.getString("alert-channel-id"); + } + + public void sendMessage(String message) throws IOException, SyncFactoryException { + try { + String payload = "{\"content\":\"" + message + "\"}"; + if (!sendMethod.equals("webhook") && !sendMethod.equals("bot")) { + throw new IllegalStateException("Invalid sending message method! Please check your configuration file again."); + } else if (sendMethod.equals("bot") && (botToken != null)) { + // Sending message using a bot + String url = "https://discord.com/api/channels/" + alertChannelId + "/messages"; + HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection(); + connection.setRequestMethod("POST"); + connection.setRequestProperty("Authorization", "Bot " + botToken); + connection.setRequestProperty("Content-Type", "application/json"); + connection.setDoOutput(true); + OutputStream outputStream = connection.getOutputStream(); + outputStream.write(payload.getBytes(StandardCharsets.UTF_8)); + outputStream.flush(); + outputStream.close(); + connection.getInputStream().close(); + connection.disconnect(); + } else if (sendMethod.equals("webhook") && (webhookUrl != null)) { + // Sending message using a webhook + HttpURLConnection connection = (HttpURLConnection) new URL(webhookUrl).openConnection(); + connection.setRequestMethod("POST"); + connection.setRequestProperty("Content-Type", "application/json"); + connection.setDoOutput(true); + OutputStream outputStream = connection.getOutputStream(); + outputStream.write(payload.getBytes(StandardCharsets.UTF_8)); + outputStream.flush(); + outputStream.close(); + connection.getInputStream().close(); + connection.disconnect(); + } else { + // Both bot token and webhook url are not defined + throw new IllegalStateException("Neither bot token nor webhook url is defined for Discord integration"); + } + } catch (IOException e) { + Logger logger = getLogger(); + logger.severe("Failed to send message to Discord: " + e.getMessage()); + } + } +} diff --git a/src/main/java/ankita/tudubucket/SendMessage.java b/src/main/java/ankita/tudubucket/SendMessage.java new file mode 100644 index 0000000..5ba3431 --- /dev/null +++ b/src/main/java/ankita/tudubucket/SendMessage.java @@ -0,0 +1,21 @@ +package ankita.tudubucket; + +import me.clip.placeholderapi.PlaceholderAPI; +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +public class SendMessage { + + public static void send(CommandSender sender, String message) { + if (sender instanceof Player) { + Player player = (Player) sender; + String msg = PlaceholderAPI.setPlaceholders(player, message); + player.sendMessage(ChatColor.translateAlternateColorCodes('&', msg)); + } else { + String msg = PlaceholderAPI.setPlaceholders(null, message); + Bukkit.getServer().getConsoleSender().sendMessage(ChatColor.translateAlternateColorCodes('&', msg)); + } + } +} \ No newline at end of file diff --git a/src/main/java/ankita/tudubucket/commands/WhitelistAdminCommand.java b/src/main/java/ankita/tudubucket/commands/WhitelistAdminCommand.java new file mode 100644 index 0000000..5f6fd8e --- /dev/null +++ b/src/main/java/ankita/tudubucket/commands/WhitelistAdminCommand.java @@ -0,0 +1,179 @@ +package ankita.tudubucket.commands; + +import ankita.tudubucket.SendMessage; +import ankita.tudubucket.DiscordIntegration; +import org.bukkit.command.Command; +import org.bukkit.command.CommandExecutor; +import org.bukkit.command.CommandSender; +import org.bukkit.configuration.file.FileConfiguration; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.player.AsyncPlayerPreLoginEvent; +import org.bukkit.event.player.PlayerLoginEvent; +import org.bukkit.plugin.java.JavaPlugin; +import org.jetbrains.annotations.NotNull; + +import javax.sql.rowset.spi.SyncFactoryException; +import java.io.File; +import java.io.IOException; +import java.time.format.DateTimeFormatter; +import java.util.List; +import java.util.Objects; + +public class WhitelistAdminCommand implements CommandExecutor, Listener { + + public WhitelistAdminCommand(JavaPlugin plugin) { + this.plugin = plugin; + } + + public String getConfigMessage(String path, String player, String ipAddress) { + FileConfiguration config = plugin.getConfig(); + + String pattern = Objects.requireNonNull(config.getString("date-format")); + + DateTimeFormatter formatter = DateTimeFormatter.ofPattern(pattern); + + return Objects.requireNonNull(config.getString(path)) + .replace("{time}", formatter.toString()) + .replace("{player}", player) + .replace("{current_address}", ipAddress); + } + + private final JavaPlugin plugin; + + + @Override + public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, String[] args) { + + + if (args.length == 0) { + SendMessage.send(sender, "&c&oWhitelistedAdmin &r&eby &6tudubucket"); + SendMessage.send(sender, "&6For help, type &e/help"); + return false; + } + + if (args[0].equals("reload")) { + // Reload the config + plugin.reloadConfig(); + SendMessage.send(sender, "Configuration reloaded."); + return true; + } + if (args[0].equals("+") && args.length != 3) { + if (args.length < 3) { + SendMessage.send(sender, "&cToo few arguments."); + } + else { + SendMessage.send(sender, "&cToo many arguments."); + } + SendMessage.send(sender, "&cUsage: /whitelist-admin + playerName ipAddress"); + return false; + } + if (args[0].equals("+")) { + // Add player to the whitelist + String playerName = args[1]; + String ip = args[2]; + FileConfiguration config = plugin.getConfig(); + config.set("whitelisted." + playerName, ip); + try { + config.save(new File(plugin.getDataFolder(), "config.yml")); + } catch (IOException e) { + e.printStackTrace(); + } + DiscordIntegration Discord = new DiscordIntegration(plugin.getConfig()); + SendMessage.send(sender, playerName + " has been added to the whitelist."); + if(Objects.equals(config.getBoolean("integrations.discord.enabled"), true)) { + try { + Discord.sendMessage(getConfigMessage("messages.integration.success-whitelisted-admin", args[1], args[2])); + } catch (IOException | SyncFactoryException e) { + throw new RuntimeException(e); + } + } + plugin.reloadConfig(); + return true; + } + if (args[0].equals("-") && args.length != 2) { + if (args.length < 2) { + SendMessage.send(sender, "&cToo few arguments."); + } + else { + SendMessage.send(sender, "&cToo many arguments."); + } + SendMessage.send(sender, "&cUsage: /whitelist-admin - playerName"); + } + if (args[0].equals("-") && args.length == 2) { + // Remove player from the whitelist + String playerName = args[1]; + FileConfiguration config = plugin.getConfig(); + if (config.contains("whitelisted." + playerName)) { + config.set("whitelisted." + playerName, null); + try { + config.save(new File(plugin.getDataFolder(), "config.yml")); + } catch (IOException e) { + e.printStackTrace(); + } + DiscordIntegration Discord = new DiscordIntegration(plugin.getConfig()); + SendMessage.send(sender, playerName + " has been removed from the whitelist."); + if(Objects.equals(config.getBoolean("integrations.discord.enabled"), true)) { + try { + Discord.sendMessage(getConfigMessage("messages.integration.success-removed-admin", args[1], "null")); + } catch (IOException | SyncFactoryException e) { + throw new RuntimeException(e); + } + } + plugin.reloadConfig(); + } else { + SendMessage.send(sender, playerName + " does not in the whitelist."); + plugin.reloadConfig(); + } + return true; + } + + SendMessage.send(sender, "&cInvalid command name!"); + return false; + } + + @EventHandler + public void onPlayerPreLogin(AsyncPlayerPreLoginEvent event) throws SyncFactoryException, IOException { + FileConfiguration config = plugin.getConfig(); + + String player = event.getName(); + String playerIP = event.getAddress().toString(); + String storedIP = config.getString("whitelisted." + playerIP); + + if (storedIP != null && !storedIP.equals(playerIP)) { + event.disallow( + AsyncPlayerPreLoginEvent.Result.KICK_OTHER, + getConfigMessage("messages.kick.invalid-address", player, playerIP) + ); + + if(Objects.equals(config.getBoolean("integrations.discord.enabled"), true)) { + DiscordIntegration Discord = new DiscordIntegration(plugin.getConfig()); + Discord.sendMessage(getConfigMessage("messages.integration.invalid-address", player, playerIP)); + } + } + } + @EventHandler + public void onPlayerJoin(PlayerLoginEvent event) { + FileConfiguration config = plugin.getConfig(); + + List permissions = config.getStringList("admin-permissions"); + Player player = event.getPlayer(); + if (config.getString("whitelisted." + player) == null) { + for (String permission: permissions) { + if (player.hasPermission(permission)) { + player.kickPlayer(getConfigMessage("messages.kick.unknown-admin", player.getName(), Objects.toString(player.getAddress()))); + if(Objects.equals(config.getBoolean("integrations.discord.enabled"), true)) { + try { + DiscordIntegration Discord = new DiscordIntegration(plugin.getConfig()); + Discord.sendMessage(getConfigMessage("messages.integration.unknown-admin", player.getName(), Objects.toString(player.getAddress()))); + } catch (IOException | SyncFactoryException e) { + throw new RuntimeException(e); + } + } + return; + } + } + } + } +} diff --git a/src/main/java/ankita/tudubucket/main.java b/src/main/java/ankita/tudubucket/main.java new file mode 100644 index 0000000..1862444 --- /dev/null +++ b/src/main/java/ankita/tudubucket/main.java @@ -0,0 +1,48 @@ +package ankita.tudubucket; + +import ankita.tudubucket.commands.WhitelistAdminCommand; +import org.bukkit.Bukkit; +import org.bukkit.configuration.file.FileConfiguration; +import org.bukkit.configuration.file.YamlConfiguration; +import org.bukkit.event.Listener; +import org.bukkit.plugin.java.JavaPlugin; +import java.io.File; +import java.util.Objects; +import java.util.logging.Logger; + +public final class main extends JavaPlugin implements Listener { + + @Override + public void onEnable() { + Logger logger = getLogger(); + File whitelistFolder = new File(getDataFolder(), "WhitelistedAdmin"); + File configFile = new File(getDataFolder(), "config.yml"); + if (!configFile.exists()) saveDefaultConfig(); + getConfig().options().copyDefaults(true); + saveDefaultConfig(); + FileConfiguration config = YamlConfiguration.loadConfiguration(configFile); + Objects.requireNonNull(getCommand("whitelist-admin")).setExecutor(new WhitelistAdminCommand(this)); + + // Register the listener + Bukkit.getPluginManager().registerEvents(new WhitelistAdminCommand(this), this); + + if (Bukkit.getPluginManager().getPlugin("PlaceholderAPI") != null) { + /* + * We register the EventListener here, when PlaceholderAPI is installed. + * Since all events are in the main class (this class), we simply use "this" + */ + Bukkit.getPluginManager().registerEvents(this, this); + } else { + /* + * We inform about the fact that PlaceholderAPI isn't installed and then + * disable this plugin to prevent issues. + */ + System.out.print("Could not find PlaceholderAPI! This plugin is required."); + Bukkit.getPluginManager().disablePlugin(this); + } + } + @Override + public void onDisable() { + // Plugin shutdown logic + } +} diff --git a/src/main/kotlin/net/langdua/bootstrap/PluginBootstrap.kt b/src/main/kotlin/net/langdua/bootstrap/PluginBootstrap.kt deleted file mode 100644 index e1548c2..0000000 --- a/src/main/kotlin/net/langdua/bootstrap/PluginBootstrap.kt +++ /dev/null @@ -1,9 +0,0 @@ -package net.langdua.bootstrap - -import net.kyori.adventure.text.minimessage.MiniMessage -import org.bukkit.event.Listener -import org.bukkit.plugin.java.JavaPlugin - -abstract class PluginBootstrap : JavaPlugin(), Listener { - val mm = MiniMessage.miniMessage() -} diff --git a/src/main/kotlin/net/langdua/bootstrap/Utility.kt b/src/main/kotlin/net/langdua/bootstrap/Utility.kt deleted file mode 100644 index 774a496..0000000 --- a/src/main/kotlin/net/langdua/bootstrap/Utility.kt +++ /dev/null @@ -1,9 +0,0 @@ -package net.langdua.bootstrap - -import net.kyori.adventure.text.Component - -class Utility(private val plugin: PluginBootstrap) { - fun getAdventureComponent(name: String): Component? { - return plugin.config.getString(name)?.let { plugin.mm.deserialize(it) } - } -} diff --git a/src/main/kotlin/net/langdua/wladmin/DiscordIntegration.kt b/src/main/kotlin/net/langdua/wladmin/DiscordIntegration.kt deleted file mode 100644 index 3978bdd..0000000 --- a/src/main/kotlin/net/langdua/wladmin/DiscordIntegration.kt +++ /dev/null @@ -1,69 +0,0 @@ -package net.langdua.wladmin - -import org.bukkit.Bukkit -import org.bukkit.configuration.ConfigurationSection -import org.bukkit.configuration.file.FileConfiguration -import java.io.IOException -import java.net.HttpURLConnection -import java.net.URL -import java.nio.charset.StandardCharsets -import javax.sql.rowset.spi.SyncFactoryException - -class DiscordIntegration(pluginConfig: FileConfiguration) { - private val config = pluginConfig.getConfigurationSection("integrations.discord")?.let { Config.fromConfig(it) } - - class Config( - val method: String?, - val token: String?, - val url: String?, - val channelId: String? - ) { - companion object { - fun fromConfig(config: ConfigurationSection): Config { - return Config( - config.getString("method"), - config.getString("bot-token"), - config.getString("webhook-url"), - config.getString("alert-channel-id") - ) - } - } - } - - @Throws(IOException::class, SyncFactoryException::class) - fun sendMessage(message: String) { - if (config == null) { - throw IllegalStateException("Improper Discord hook configuration") - } - try { - if ((config.method == "webhook" || config.method == "bot") && - (config.method == "bot" && !config.token.isNullOrBlank()) || - (config.method == "webhook" && !config.url.isNullOrBlank()) - ) { - val connection = - URL(if (config.method == "bot") "https://discord.com/api/channels/${config.channelId}/messages" else config.url).openConnection() as HttpURLConnection - if (config.method == "bot") { - config.token?.let { - connection.setRequestProperty("Authorization", "Bot $it") - } - } - connection.requestMethod = "POST" - connection.setRequestProperty("Content-Type", "application/json") - connection.doOutput = true - val outputStream = connection.outputStream - val payload = - "{\"content\":\"$message\"}" // Both bot token and webhook url are not defined// Sending message using a webhook - outputStream.write(payload.toByteArray(StandardCharsets.UTF_8)) - outputStream.flush() - outputStream.close() - connection.inputStream.close() - connection.disconnect() - } else { - throw IllegalStateException("Neither bot token nor webhook url is defined for Discord integration") - } - } catch (e: IOException) { - val logger = Bukkit.getLogger() - logger.severe("Failed to send message to Discord: " + e.message) - } - } -} diff --git a/src/main/kotlin/net/langdua/wladmin/Plugin.kt b/src/main/kotlin/net/langdua/wladmin/Plugin.kt deleted file mode 100644 index e83e81e..0000000 --- a/src/main/kotlin/net/langdua/wladmin/Plugin.kt +++ /dev/null @@ -1,31 +0,0 @@ -package net.langdua.wladmin - -import net.langdua.bootstrap.PluginBootstrap -import net.langdua.bootstrap.Utility -import net.langdua.main.BuildConfig -import net.langdua.wladmin.commands.WhitelistAdminCommand -import org.bstats.bukkit.Metrics -import org.bukkit.Bukkit -import org.bukkit.configuration.file.YamlConfiguration -import java.io.File -import java.util.* - -class Plugin : PluginBootstrap() { - val whitelistFolder = File(dataFolder, "WhitelistedAdmin") - private val configFile = File(dataFolder, "config.yml") - var utility = Utility(this) - override fun onEnable() { - Metrics(this, BuildConfig.BSTATS_ID) - if (!configFile.exists()) saveDefaultConfig() - config.options().copyDefaults(true) - saveDefaultConfig() - YamlConfiguration.loadConfiguration(configFile) - Objects.requireNonNull(getCommand("whitelist-admin"))?.setExecutor(WhitelistAdminCommand(this)) - // Register the listener - Bukkit.getPluginManager().registerEvents(WhitelistAdminCommand(this), this) - } - - override fun onDisable() { - // Plugin shutdown logic - } -} diff --git a/src/main/kotlin/net/langdua/wladmin/SendMessage.kt b/src/main/kotlin/net/langdua/wladmin/SendMessage.kt deleted file mode 100644 index 659f0a6..0000000 --- a/src/main/kotlin/net/langdua/wladmin/SendMessage.kt +++ /dev/null @@ -1,28 +0,0 @@ -package net.langdua.wladmin - -import me.clip.placeholderapi.PlaceholderAPI -import org.bukkit.Bukkit -import org.bukkit.ChatColor -import org.bukkit.command.CommandSender -import org.bukkit.command.ConsoleCommandSender -import org.bukkit.entity.Player - -class SendMessage { - companion object { - fun send(sender: CommandSender?, message: String) { - val msg = - ChatColor.translateAlternateColorCodes( - '&', - PlaceholderAPI.setPlaceholders( - if (sender is Player && sender !is ConsoleCommandSender) sender else null, - message - ) - ) - if (sender != null) { - sender.sendMessage(msg) - } else { - Bukkit.getServer().consoleSender.sendMessage(msg) - } - } - } -} diff --git a/src/main/kotlin/net/langdua/wladmin/commands/WhitelistAdminCommand.kt b/src/main/kotlin/net/langdua/wladmin/commands/WhitelistAdminCommand.kt deleted file mode 100644 index db03c6c..0000000 --- a/src/main/kotlin/net/langdua/wladmin/commands/WhitelistAdminCommand.kt +++ /dev/null @@ -1,120 +0,0 @@ -package net.langdua.wladmin.commands - -import net.langdua.wladmin.DiscordIntegration -import net.langdua.wladmin.Plugin -import net.langdua.wladmin.SendMessage -import org.bukkit.command.Command -import org.bukkit.command.CommandExecutor -import org.bukkit.command.CommandSender -import org.bukkit.event.EventHandler -import org.bukkit.event.Listener -import org.bukkit.event.player.PlayerJoinEvent -import java.io.File -import java.io.IOException -import java.util.* -import javax.sql.rowset.spi.SyncFactoryException - -class WhitelistAdminCommand(private val plugin: Plugin) : CommandExecutor, Listener { - private val config = plugin.config - private val discord = DiscordIntegration(config) - override fun onCommand(sender: CommandSender, command: Command, label: String, args: Array): Boolean { - if (args.isEmpty()) { - SendMessage.send(sender, "&c&oWhitelistedAdmin &r&eby &6LangDuaMC developers [tudubucket, hUwUtao]") - SendMessage.send(sender, "&6For help, type &e/help") - return false - } else if (args[0] == "reload") { - // Reload the config - plugin.reloadConfig() - SendMessage.send(sender, "Configuration reloaded.") - return true - } else if (args[0] == "+" && args.size == 3) { - // Add player to the whitelist - val playerName = args[1] - val ip = args[2] - config["whitelisted.$playerName"] = ip - try { - config.save(File(plugin.dataFolder, "config.yml")) - } catch (e: IOException) { - e.printStackTrace() - } - SendMessage.send(sender, "$playerName has been added to the whitelist.") - if (config.getBoolean("integrations.discord.enabled")) { - try { - discord.sendMessage(config.getString("messages.integration.success-whitelisted-admin")!!) - } catch (e: IOException) { - throw RuntimeException(e) - } catch (e: SyncFactoryException) { - throw RuntimeException(e) - } - } - plugin.reloadConfig() - return true - } else if (args[0] == "-" && args.size == 2) { - // Remove player from the whitelist - val playerName = args[1] - - if (config.contains("whitelisted.$playerName")) { - config["whitelisted.$playerName"] = null - try { - config.save(File(plugin.dataFolder, "config.yml")) - } catch (e: IOException) { - e.printStackTrace() - } - SendMessage.send(sender, "$playerName has been removed from the whitelist.") - if (config.getBoolean("integrations.discord.enabled")) { - try { - discord.sendMessage(config.getString("messages.integration.success-removed-admin")!!) - } catch (e: IOException) { - throw RuntimeException(e) - } catch (e: SyncFactoryException) { - throw RuntimeException(e) - } - } - plugin.reloadConfig() - } else { - SendMessage.send(sender, "$playerName is not in the whitelist.") - plugin.reloadConfig() - } - return true - } - SendMessage.send(sender, "&cInvalid command!") - return false - } - - @EventHandler - @Throws(SyncFactoryException::class, IOException::class) - fun onPlayerJoin(event: PlayerJoinEvent) { - // Get the configuration - - // Check if the player has any forbidden permissions - val permissions = config.getStringList("permissions") - val player = event.player - val checkValid = config.getString("whitelisted.$player") - for (permission in permissions) { - if (player.hasPermission(permission!!) && checkValid == null) { - player.kick(plugin.utility.getAdventureComponent("messages.kick.unknown-admin")) - if (config.getBoolean("integrations.discord.enabled")) { - try { - discord.sendMessage(config.getString("messages.integration.unknown-admin")!!) - } catch (e: IOException) { - throw RuntimeException(e) - } catch (e: SyncFactoryException) { - throw RuntimeException(e) - } - } - return - } - } - - // Check if the player is whitelisted - val playerName = player.name - val playerIP = Objects.requireNonNull(player.address).hostString - val storedIP = config.getString("whitelisted.$playerName") - if (storedIP != null && storedIP != playerIP) { - player.kick(plugin.utility.getAdventureComponent("messages.kick.invalid-address")) - if (config.getBoolean("integrations.discord.enabled")) { - discord.sendMessage(config.getString("messages.integration.invalid-address")!!) - } - } - } -} diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index 856236d..8dff0cd 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -1,61 +1,65 @@ # WhitelistedAdmin configuration -# Placeholder list: +# Placeholders list: # {player}: Player name -# {address}: Player IP Address in PlayerJoinEvent +# {address}: Player IP Address when joined # {current_address}: Player IP Address in the configuration -# List of permissions to check -# Wildcard (e.g. "bukkit.*") are supported, it will check if the player have any permission starting with "bukkit.", for example. -permissions: +# Date format for messages +date-format: "yyyy-MM-dd HH:MM:SS" + +# List of permissions to check whether the joined player is an admin or not (only if they are not whitelisted) +# Wildcards (e.g. "bukkit.*") are supported, it will check if the player has any permission starting with "bukkit.", for example. +admin-permissions: - "bukkit.plugin" - "bukkit.?" - "idk" -# List of whitelisted administrator and their IP address -whitelisted: - remember-to-replace-this-to-your-admin-name: "127.0.0.1" - you-can-add: "127.0.0.2" - as-much-player-as-you-want: "172.0.0.3" - - # Discord Integration support - integrations: discord: - enabled: true + enable: true # Method: "webhook" or "bot" method: "bot" - bot-token: "insert-your-bot-token-here" - webhook-url: "https://discord.com/api/webhooks/0123456789123456789/webhook-token" - # This setting required only if you are using Discord bot instead of Webhook. Remember, this is Channel ID, not the Channel name. - # For more information about getting Channel ID, refer to https://support.discord.com/hc/en-us/articles/206346498 - alert-channel-id: "0123456789123456789" + + bot: + token: "insert-your-bot-token-here" + # For more information about getting a Channel ID, refer to https://support.discord.com/hc/en-us/articles/206346498 + alert-channel-id: "0123456789123456789" + + webhook: + url: "https://discord.com/api/webhooks/0123456789123456789/webhook-token" # Hide the plugin plugin: hide: true message-unknown-command: 'Unknown command. Type "/help" for help.' -# Messages to announce to integrations, placeholder and color code supported +# Messages to announce to integrations, placeholder, and color code supported messages: logging: unknown-admin: "{time} {player} have matched administrator permissions but not have whitelisted!" - invalid-address: "{time} {player} have different IP address with whitelisted! Currently whitelisted address: %old_address%" - success-whitelisted-ip: "{time} {player} have been whitelisted with IP address %ip_address%" + invalid-address: "{time} {player} have different IP address with whitelisted! Currently whitelisted address: {current_address}" + success-whitelisted-ip: "{time} {player} have been whitelisted with IP address {current_address}" success-removed-admin: "{time} {player} have been removed from administrator list" console: configuration-reloaded: 'Configuration reloaded!' invalid-command: 'Invalid command argument!' unknown-admin: "{time} {player} have matched administrator permissions but not have whitelisted!" - invalid-address: "{time} {player} have different IP address with whitelisted! Currently whitelisted address: %old_address%" - success-whitelisted-ip: "{time} {player} have been whitelisted with IP address %ip_address%" + invalid-address: "{time} {player} have different IP address with whitelisted! Current whitelisted address: {current_address}" + success-whitelisted-ip: "{time} {player} have been whitelisted with IP address {current_address}" success-removed-admin: "{time} {player} have been removed from administrator list" integration: unknown-admin: "{time} {player} have matched administrator permissions but not have whitelisted!" - invalid-address: "{time} {player} have different IP address with whitelisted! Currently whitelisted address: %old_address%" - success-whitelisted-ip: "{time} {player} have been whitelisted with IP address %ip_address%" + invalid-address: "{time} {player} have different IP address with whitelisted! Current whitelisted address: {current_address}" + success-whitelisted-ip: "{time} {player} have been whitelisted with IP address {current_address}" success-removed-admin: "{time} {player} have been removed from administrator list" kick: unknown-admin: "You have matched administrator permissions but not have whitelisted!" - invalid-address: "You have different IP address with whitelisted!" \ No newline at end of file + invalid-address: "You have a different IP address than the whitelisted one!" + + +# List of whitelisted administrators and their IP address +whitelisted-admins: + admin1: "127.0.0.1" + admin2: "127.0.0.1" diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index 7a16f2b..1dfd91e 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -1,16 +1,17 @@ name: WhitelistedAdmin -version: '1.0.0' -main: net.langdua.wladmin.Plugin -api-version: 1.16 -authors: [tudubucket, hUwUtao] +version: '${project.version}' +main: ankita.tudubucket.main +api-version: 1.18 +authors: [tudubucket] description: A Minecraft plugin for Server Administrator safety purposes -website: https://github.com/LangDuaMC/WhitelistedAdmin -prefix: WLAdmin -depend: [PlaceholderAPI] +website: https://tudubucket.dev +prefix: WhitelistedAdmin +softdepend: [PlaceholderAPI] commands: whitelist-admin: description: Main command for WhitelistedAdmin plugin aliases: - wla + - wladmin permission: whitelistedadmin.wladmin