├── LICENSE ├── README.md ├── pom.xml └── src └── main ├── java └── me │ └── tini │ └── announcer │ ├── BanAnnouncer.java │ ├── BanAnnouncerPlugin.java │ ├── MessageFormatter.java │ ├── PunishmentInfo.java │ ├── PunishmentListener.java │ ├── ReloadCommand.java │ ├── addon │ └── BanAnnouncerAddon.java │ ├── config │ ├── Config.java │ └── Messages.java │ ├── extension │ ├── AbstractExtension.java │ ├── ExtensionContainer.java │ ├── ExtensionInfo.java │ ├── FileExtensionContainer.java │ └── impl │ │ ├── advancedban │ │ ├── AdvancedBanExtensionBukkit.java │ │ ├── AdvancedBanExtensionBungee.java │ │ ├── AdvancedBanListenerBukkit.java │ │ ├── AdvancedBanListenerBungee.java │ │ └── AdvancedBanUtil.java │ │ ├── betterjails │ │ ├── BetterJailsExtension.java │ │ ├── BetterJailsListener.java │ │ └── TimeUtils.java │ │ ├── essentialsjail │ │ ├── EssentialsJailExtension.java │ │ └── EssentialsJailListener.java │ │ ├── libertybans │ │ ├── LibertyBansExtension.java │ │ └── LibertyBansListener.java │ │ ├── litebans │ │ ├── LiteBansExtension.java │ │ └── LiteBansListener.java │ │ ├── maxbans │ │ ├── MaxBansExtension.java │ │ └── MaxBansListener.java │ │ └── spongevanilla │ │ ├── SpongeVanillaExtension.java │ │ └── SpongeVanillaListener.java │ └── plugin │ ├── bukkit │ ├── BanAnnouncerBukkit.java │ └── BukkitPunishmentListener.java │ ├── bungee │ ├── BanAnnouncerBungee.java │ └── BungeePunishmentListener.java │ ├── sponge │ ├── BanAnnouncerSponge.java │ └── SpongePunishmentListener.java │ └── velocity │ └── BanAnnouncerVelocity.java └── resources ├── bungee.yml ├── config.yml ├── embed ├── ban.json ├── banip.json ├── jail.json ├── kick.json ├── mute.json ├── note.json ├── tempban.json ├── tempbanip.json ├── tempmute.json ├── tempwarn.json ├── unban.json ├── unbanip.json ├── unjail.json ├── unmute.json ├── unnote.json ├── unwarn.json └── warn.json ├── plugin.yml └── sponge_plugins.json /LICENSE: -------------------------------------------------------------------------------- 1 | GNU AFFERO GENERAL PUBLIC LICENSE 2 | Version 3, 19 November 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | Preamble 9 | 10 | The GNU Affero General Public License is a free, copyleft license for 11 | software and other kinds of works, specifically designed to ensure 12 | cooperation with the community in the case of network server software. 13 | 14 | The licenses for most software and other practical works are designed 15 | to take away your freedom to share and change the works. By contrast, 16 | our General Public Licenses are intended to guarantee your freedom to 17 | share and change all versions of a program--to make sure it remains free 18 | software for all its users. 19 | 20 | When we speak of free software, we are referring to freedom, not 21 | price. Our General Public Licenses are designed to make sure that you 22 | have the freedom to distribute copies of free software (and charge for 23 | them if you wish), that you receive source code or can get it if you 24 | want it, that you can change the software or use pieces of it in new 25 | free programs, and that you know you can do these things. 26 | 27 | Developers that use our General Public Licenses protect your rights 28 | with two steps: (1) assert copyright on the software, and (2) offer 29 | you this License which gives you legal permission to copy, distribute 30 | and/or modify the software. 31 | 32 | A secondary benefit of defending all users' freedom is that 33 | improvements made in alternate versions of the program, if they 34 | receive widespread use, become available for other developers to 35 | incorporate. Many developers of free software are heartened and 36 | encouraged by the resulting cooperation. However, in the case of 37 | software used on network servers, this result may fail to come about. 38 | The GNU General Public License permits making a modified version and 39 | letting the public access it on a server without ever releasing its 40 | source code to the public. 41 | 42 | The GNU Affero General Public License is designed specifically to 43 | ensure that, in such cases, the modified source code becomes available 44 | to the community. It requires the operator of a network server to 45 | provide the source code of the modified version running there to the 46 | users of that server. Therefore, public use of a modified version, on 47 | a publicly accessible server, gives the public access to the source 48 | code of the modified version. 49 | 50 | An older license, called the Affero General Public License and 51 | published by Affero, was designed to accomplish similar goals. This is 52 | a different license, not a version of the Affero GPL, but Affero has 53 | released a new version of the Affero GPL which permits relicensing under 54 | this license. 55 | 56 | The precise terms and conditions for copying, distribution and 57 | modification follow. 58 | 59 | TERMS AND CONDITIONS 60 | 61 | 0. Definitions. 62 | 63 | "This License" refers to version 3 of the GNU Affero General Public License. 64 | 65 | "Copyright" also means copyright-like laws that apply to other kinds of 66 | works, such as semiconductor masks. 67 | 68 | "The Program" refers to any copyrightable work licensed under this 69 | License. Each licensee is addressed as "you". "Licensees" and 70 | "recipients" may be individuals or organizations. 71 | 72 | To "modify" a work means to copy from or adapt all or part of the work 73 | in a fashion requiring copyright permission, other than the making of an 74 | exact copy. The resulting work is called a "modified version" of the 75 | earlier work or a work "based on" the earlier work. 76 | 77 | A "covered work" means either the unmodified Program or a work based 78 | on the Program. 79 | 80 | To "propagate" a work means to do anything with it that, without 81 | permission, would make you directly or secondarily liable for 82 | infringement under applicable copyright law, except executing it on a 83 | computer or modifying a private copy. Propagation includes copying, 84 | distribution (with or without modification), making available to the 85 | public, and in some countries other activities as well. 86 | 87 | To "convey" a work means any kind of propagation that enables other 88 | parties to make or receive copies. Mere interaction with a user through 89 | a computer network, with no transfer of a copy, is not conveying. 90 | 91 | An interactive user interface displays "Appropriate Legal Notices" 92 | to the extent that it includes a convenient and prominently visible 93 | feature that (1) displays an appropriate copyright notice, and (2) 94 | tells the user that there is no warranty for the work (except to the 95 | extent that warranties are provided), that licensees may convey the 96 | work under this License, and how to view a copy of this License. If 97 | the interface presents a list of user commands or options, such as a 98 | menu, a prominent item in the list meets this criterion. 99 | 100 | 1. Source Code. 101 | 102 | The "source code" for a work means the preferred form of the work 103 | for making modifications to it. "Object code" means any non-source 104 | form of a work. 105 | 106 | A "Standard Interface" means an interface that either is an official 107 | standard defined by a recognized standards body, or, in the case of 108 | interfaces specified for a particular programming language, one that 109 | is widely used among developers working in that language. 110 | 111 | The "System Libraries" of an executable work include anything, other 112 | than the work as a whole, that (a) is included in the normal form of 113 | packaging a Major Component, but which is not part of that Major 114 | Component, and (b) serves only to enable use of the work with that 115 | Major Component, or to implement a Standard Interface for which an 116 | implementation is available to the public in source code form. A 117 | "Major Component", in this context, means a major essential component 118 | (kernel, window system, and so on) of the specific operating system 119 | (if any) on which the executable work runs, or a compiler used to 120 | produce the work, or an object code interpreter used to run it. 121 | 122 | The "Corresponding Source" for a work in object code form means all 123 | the source code needed to generate, install, and (for an executable 124 | work) run the object code and to modify the work, including scripts to 125 | control those activities. However, it does not include the work's 126 | System Libraries, or general-purpose tools or generally available free 127 | programs which are used unmodified in performing those activities but 128 | which are not part of the work. For example, Corresponding Source 129 | includes interface definition files associated with source files for 130 | the work, and the source code for shared libraries and dynamically 131 | linked subprograms that the work is specifically designed to require, 132 | such as by intimate data communication or control flow between those 133 | subprograms and other parts of the work. 134 | 135 | The Corresponding Source need not include anything that users 136 | can regenerate automatically from other parts of the Corresponding 137 | Source. 138 | 139 | The Corresponding Source for a work in source code form is that 140 | same work. 141 | 142 | 2. Basic Permissions. 143 | 144 | All rights granted under this License are granted for the term of 145 | copyright on the Program, and are irrevocable provided the stated 146 | conditions are met. This License explicitly affirms your unlimited 147 | permission to run the unmodified Program. The output from running a 148 | covered work is covered by this License only if the output, given its 149 | content, constitutes a covered work. This License acknowledges your 150 | rights of fair use or other equivalent, as provided by copyright law. 151 | 152 | You may make, run and propagate covered works that you do not 153 | convey, without conditions so long as your license otherwise remains 154 | in force. You may convey covered works to others for the sole purpose 155 | of having them make modifications exclusively for you, or provide you 156 | with facilities for running those works, provided that you comply with 157 | the terms of this License in conveying all material for which you do 158 | not control copyright. Those thus making or running the covered works 159 | for you must do so exclusively on your behalf, under your direction 160 | and control, on terms that prohibit them from making any copies of 161 | your copyrighted material outside their relationship with you. 162 | 163 | Conveying under any other circumstances is permitted solely under 164 | the conditions stated below. Sublicensing is not allowed; section 10 165 | makes it unnecessary. 166 | 167 | 3. Protecting Users' Legal Rights From Anti-Circumvention Law. 168 | 169 | No covered work shall be deemed part of an effective technological 170 | measure under any applicable law fulfilling obligations under article 171 | 11 of the WIPO copyright treaty adopted on 20 December 1996, or 172 | similar laws prohibiting or restricting circumvention of such 173 | measures. 174 | 175 | When you convey a covered work, you waive any legal power to forbid 176 | circumvention of technological measures to the extent such circumvention 177 | is effected by exercising rights under this License with respect to 178 | the covered work, and you disclaim any intention to limit operation or 179 | modification of the work as a means of enforcing, against the work's 180 | users, your or third parties' legal rights to forbid circumvention of 181 | technological measures. 182 | 183 | 4. Conveying Verbatim Copies. 184 | 185 | You may convey verbatim copies of the Program's source code as you 186 | receive it, in any medium, provided that you conspicuously and 187 | appropriately publish on each copy an appropriate copyright notice; 188 | keep intact all notices stating that this License and any 189 | non-permissive terms added in accord with section 7 apply to the code; 190 | keep intact all notices of the absence of any warranty; and give all 191 | recipients a copy of this License along with the Program. 192 | 193 | You may charge any price or no price for each copy that you convey, 194 | and you may offer support or warranty protection for a fee. 195 | 196 | 5. Conveying Modified Source Versions. 197 | 198 | You may convey a work based on the Program, or the modifications to 199 | produce it from the Program, in the form of source code under the 200 | terms of section 4, provided that you also meet all of these conditions: 201 | 202 | a) The work must carry prominent notices stating that you modified 203 | it, and giving a relevant date. 204 | 205 | b) The work must carry prominent notices stating that it is 206 | released under this License and any conditions added under section 207 | 7. This requirement modifies the requirement in section 4 to 208 | "keep intact all notices". 209 | 210 | c) You must license the entire work, as a whole, under this 211 | License to anyone who comes into possession of a copy. This 212 | License will therefore apply, along with any applicable section 7 213 | additional terms, to the whole of the work, and all its parts, 214 | regardless of how they are packaged. This License gives no 215 | permission to license the work in any other way, but it does not 216 | invalidate such permission if you have separately received it. 217 | 218 | d) If the work has interactive user interfaces, each must display 219 | Appropriate Legal Notices; however, if the Program has interactive 220 | interfaces that do not display Appropriate Legal Notices, your 221 | work need not make them do so. 222 | 223 | A compilation of a covered work with other separate and independent 224 | works, which are not by their nature extensions of the covered work, 225 | and which are not combined with it such as to form a larger program, 226 | in or on a volume of a storage or distribution medium, is called an 227 | "aggregate" if the compilation and its resulting copyright are not 228 | used to limit the access or legal rights of the compilation's users 229 | beyond what the individual works permit. Inclusion of a covered work 230 | in an aggregate does not cause this License to apply to the other 231 | parts of the aggregate. 232 | 233 | 6. Conveying Non-Source Forms. 234 | 235 | You may convey a covered work in object code form under the terms 236 | of sections 4 and 5, provided that you also convey the 237 | machine-readable Corresponding Source under the terms of this License, 238 | in one of these ways: 239 | 240 | a) Convey the object code in, or embodied in, a physical product 241 | (including a physical distribution medium), accompanied by the 242 | Corresponding Source fixed on a durable physical medium 243 | customarily used for software interchange. 244 | 245 | b) Convey the object code in, or embodied in, a physical product 246 | (including a physical distribution medium), accompanied by a 247 | written offer, valid for at least three years and valid for as 248 | long as you offer spare parts or customer support for that product 249 | model, to give anyone who possesses the object code either (1) a 250 | copy of the Corresponding Source for all the software in the 251 | product that is covered by this License, on a durable physical 252 | medium customarily used for software interchange, for a price no 253 | more than your reasonable cost of physically performing this 254 | conveying of source, or (2) access to copy the 255 | Corresponding Source from a network server at no charge. 256 | 257 | c) Convey individual copies of the object code with a copy of the 258 | written offer to provide the Corresponding Source. This 259 | alternative is allowed only occasionally and noncommercially, and 260 | only if you received the object code with such an offer, in accord 261 | with subsection 6b. 262 | 263 | d) Convey the object code by offering access from a designated 264 | place (gratis or for a charge), and offer equivalent access to the 265 | Corresponding Source in the same way through the same place at no 266 | further charge. You need not require recipients to copy the 267 | Corresponding Source along with the object code. If the place to 268 | copy the object code is a network server, the Corresponding Source 269 | may be on a different server (operated by you or a third party) 270 | that supports equivalent copying facilities, provided you maintain 271 | clear directions next to the object code saying where to find the 272 | Corresponding Source. Regardless of what server hosts the 273 | Corresponding Source, you remain obligated to ensure that it is 274 | available for as long as needed to satisfy these requirements. 275 | 276 | e) Convey the object code using peer-to-peer transmission, provided 277 | you inform other peers where the object code and Corresponding 278 | Source of the work are being offered to the general public at no 279 | charge under subsection 6d. 280 | 281 | A separable portion of the object code, whose source code is excluded 282 | from the Corresponding Source as a System Library, need not be 283 | included in conveying the object code work. 284 | 285 | A "User Product" is either (1) a "consumer product", which means any 286 | tangible personal property which is normally used for personal, family, 287 | or household purposes, or (2) anything designed or sold for incorporation 288 | into a dwelling. In determining whether a product is a consumer product, 289 | doubtful cases shall be resolved in favor of coverage. For a particular 290 | product received by a particular user, "normally used" refers to a 291 | typical or common use of that class of product, regardless of the status 292 | of the particular user or of the way in which the particular user 293 | actually uses, or expects or is expected to use, the product. A product 294 | is a consumer product regardless of whether the product has substantial 295 | commercial, industrial or non-consumer uses, unless such uses represent 296 | the only significant mode of use of the product. 297 | 298 | "Installation Information" for a User Product means any methods, 299 | procedures, authorization keys, or other information required to install 300 | and execute modified versions of a covered work in that User Product from 301 | a modified version of its Corresponding Source. The information must 302 | suffice to ensure that the continued functioning of the modified object 303 | code is in no case prevented or interfered with solely because 304 | modification has been made. 305 | 306 | If you convey an object code work under this section in, or with, or 307 | specifically for use in, a User Product, and the conveying occurs as 308 | part of a transaction in which the right of possession and use of the 309 | User Product is transferred to the recipient in perpetuity or for a 310 | fixed term (regardless of how the transaction is characterized), the 311 | Corresponding Source conveyed under this section must be accompanied 312 | by the Installation Information. But this requirement does not apply 313 | if neither you nor any third party retains the ability to install 314 | modified object code on the User Product (for example, the work has 315 | been installed in ROM). 316 | 317 | The requirement to provide Installation Information does not include a 318 | requirement to continue to provide support service, warranty, or updates 319 | for a work that has been modified or installed by the recipient, or for 320 | the User Product in which it has been modified or installed. Access to a 321 | network may be denied when the modification itself materially and 322 | adversely affects the operation of the network or violates the rules and 323 | protocols for communication across the network. 324 | 325 | Corresponding Source conveyed, and Installation Information provided, 326 | in accord with this section must be in a format that is publicly 327 | documented (and with an implementation available to the public in 328 | source code form), and must require no special password or key for 329 | unpacking, reading or copying. 330 | 331 | 7. Additional Terms. 332 | 333 | "Additional permissions" are terms that supplement the terms of this 334 | License by making exceptions from one or more of its conditions. 335 | Additional permissions that are applicable to the entire Program shall 336 | be treated as though they were included in this License, to the extent 337 | that they are valid under applicable law. If additional permissions 338 | apply only to part of the Program, that part may be used separately 339 | under those permissions, but the entire Program remains governed by 340 | this License without regard to the additional permissions. 341 | 342 | When you convey a copy of a covered work, you may at your option 343 | remove any additional permissions from that copy, or from any part of 344 | it. (Additional permissions may be written to require their own 345 | removal in certain cases when you modify the work.) You may place 346 | additional permissions on material, added by you to a covered work, 347 | for which you have or can give appropriate copyright permission. 348 | 349 | Notwithstanding any other provision of this License, for material you 350 | add to a covered work, you may (if authorized by the copyright holders of 351 | that material) supplement the terms of this License with terms: 352 | 353 | a) Disclaiming warranty or limiting liability differently from the 354 | terms of sections 15 and 16 of this License; or 355 | 356 | b) Requiring preservation of specified reasonable legal notices or 357 | author attributions in that material or in the Appropriate Legal 358 | Notices displayed by works containing it; or 359 | 360 | c) Prohibiting misrepresentation of the origin of that material, or 361 | requiring that modified versions of such material be marked in 362 | reasonable ways as different from the original version; or 363 | 364 | d) Limiting the use for publicity purposes of names of licensors or 365 | authors of the material; or 366 | 367 | e) Declining to grant rights under trademark law for use of some 368 | trade names, trademarks, or service marks; or 369 | 370 | f) Requiring indemnification of licensors and authors of that 371 | material by anyone who conveys the material (or modified versions of 372 | it) with contractual assumptions of liability to the recipient, for 373 | any liability that these contractual assumptions directly impose on 374 | those licensors and authors. 375 | 376 | All other non-permissive additional terms are considered "further 377 | restrictions" within the meaning of section 10. If the Program as you 378 | received it, or any part of it, contains a notice stating that it is 379 | governed by this License along with a term that is a further 380 | restriction, you may remove that term. If a license document contains 381 | a further restriction but permits relicensing or conveying under this 382 | License, you may add to a covered work material governed by the terms 383 | of that license document, provided that the further restriction does 384 | not survive such relicensing or conveying. 385 | 386 | If you add terms to a covered work in accord with this section, you 387 | must place, in the relevant source files, a statement of the 388 | additional terms that apply to those files, or a notice indicating 389 | where to find the applicable terms. 390 | 391 | Additional terms, permissive or non-permissive, may be stated in the 392 | form of a separately written license, or stated as exceptions; 393 | the above requirements apply either way. 394 | 395 | 8. Termination. 396 | 397 | You may not propagate or modify a covered work except as expressly 398 | provided under this License. Any attempt otherwise to propagate or 399 | modify it is void, and will automatically terminate your rights under 400 | this License (including any patent licenses granted under the third 401 | paragraph of section 11). 402 | 403 | However, if you cease all violation of this License, then your 404 | license from a particular copyright holder is reinstated (a) 405 | provisionally, unless and until the copyright holder explicitly and 406 | finally terminates your license, and (b) permanently, if the copyright 407 | holder fails to notify you of the violation by some reasonable means 408 | prior to 60 days after the cessation. 409 | 410 | Moreover, your license from a particular copyright holder is 411 | reinstated permanently if the copyright holder notifies you of the 412 | violation by some reasonable means, this is the first time you have 413 | received notice of violation of this License (for any work) from that 414 | copyright holder, and you cure the violation prior to 30 days after 415 | your receipt of the notice. 416 | 417 | Termination of your rights under this section does not terminate the 418 | licenses of parties who have received copies or rights from you under 419 | this License. If your rights have been terminated and not permanently 420 | reinstated, you do not qualify to receive new licenses for the same 421 | material under section 10. 422 | 423 | 9. Acceptance Not Required for Having Copies. 424 | 425 | You are not required to accept this License in order to receive or 426 | run a copy of the Program. Ancillary propagation of a covered work 427 | occurring solely as a consequence of using peer-to-peer transmission 428 | to receive a copy likewise does not require acceptance. However, 429 | nothing other than this License grants you permission to propagate or 430 | modify any covered work. These actions infringe copyright if you do 431 | not accept this License. Therefore, by modifying or propagating a 432 | covered work, you indicate your acceptance of this License to do so. 433 | 434 | 10. Automatic Licensing of Downstream Recipients. 435 | 436 | Each time you convey a covered work, the recipient automatically 437 | receives a license from the original licensors, to run, modify and 438 | propagate that work, subject to this License. You are not responsible 439 | for enforcing compliance by third parties with this License. 440 | 441 | An "entity transaction" is a transaction transferring control of an 442 | organization, or substantially all assets of one, or subdividing an 443 | organization, or merging organizations. If propagation of a covered 444 | work results from an entity transaction, each party to that 445 | transaction who receives a copy of the work also receives whatever 446 | licenses to the work the party's predecessor in interest had or could 447 | give under the previous paragraph, plus a right to possession of the 448 | Corresponding Source of the work from the predecessor in interest, if 449 | the predecessor has it or can get it with reasonable efforts. 450 | 451 | You may not impose any further restrictions on the exercise of the 452 | rights granted or affirmed under this License. For example, you may 453 | not impose a license fee, royalty, or other charge for exercise of 454 | rights granted under this License, and you may not initiate litigation 455 | (including a cross-claim or counterclaim in a lawsuit) alleging that 456 | any patent claim is infringed by making, using, selling, offering for 457 | sale, or importing the Program or any portion of it. 458 | 459 | 11. Patents. 460 | 461 | A "contributor" is a copyright holder who authorizes use under this 462 | License of the Program or a work on which the Program is based. The 463 | work thus licensed is called the contributor's "contributor version". 464 | 465 | A contributor's "essential patent claims" are all patent claims 466 | owned or controlled by the contributor, whether already acquired or 467 | hereafter acquired, that would be infringed by some manner, permitted 468 | by this License, of making, using, or selling its contributor version, 469 | but do not include claims that would be infringed only as a 470 | consequence of further modification of the contributor version. For 471 | purposes of this definition, "control" includes the right to grant 472 | patent sublicenses in a manner consistent with the requirements of 473 | this License. 474 | 475 | Each contributor grants you a non-exclusive, worldwide, royalty-free 476 | patent license under the contributor's essential patent claims, to 477 | make, use, sell, offer for sale, import and otherwise run, modify and 478 | propagate the contents of its contributor version. 479 | 480 | In the following three paragraphs, a "patent license" is any express 481 | agreement or commitment, however denominated, not to enforce a patent 482 | (such as an express permission to practice a patent or covenant not to 483 | sue for patent infringement). To "grant" such a patent license to a 484 | party means to make such an agreement or commitment not to enforce a 485 | patent against the party. 486 | 487 | If you convey a covered work, knowingly relying on a patent license, 488 | and the Corresponding Source of the work is not available for anyone 489 | to copy, free of charge and under the terms of this License, through a 490 | publicly available network server or other readily accessible means, 491 | then you must either (1) cause the Corresponding Source to be so 492 | available, or (2) arrange to deprive yourself of the benefit of the 493 | patent license for this particular work, or (3) arrange, in a manner 494 | consistent with the requirements of this License, to extend the patent 495 | license to downstream recipients. "Knowingly relying" means you have 496 | actual knowledge that, but for the patent license, your conveying the 497 | covered work in a country, or your recipient's use of the covered work 498 | in a country, would infringe one or more identifiable patents in that 499 | country that you have reason to believe are valid. 500 | 501 | If, pursuant to or in connection with a single transaction or 502 | arrangement, you convey, or propagate by procuring conveyance of, a 503 | covered work, and grant a patent license to some of the parties 504 | receiving the covered work authorizing them to use, propagate, modify 505 | or convey a specific copy of the covered work, then the patent license 506 | you grant is automatically extended to all recipients of the covered 507 | work and works based on it. 508 | 509 | A patent license is "discriminatory" if it does not include within 510 | the scope of its coverage, prohibits the exercise of, or is 511 | conditioned on the non-exercise of one or more of the rights that are 512 | specifically granted under this License. You may not convey a covered 513 | work if you are a party to an arrangement with a third party that is 514 | in the business of distributing software, under which you make payment 515 | to the third party based on the extent of your activity of conveying 516 | the work, and under which the third party grants, to any of the 517 | parties who would receive the covered work from you, a discriminatory 518 | patent license (a) in connection with copies of the covered work 519 | conveyed by you (or copies made from those copies), or (b) primarily 520 | for and in connection with specific products or compilations that 521 | contain the covered work, unless you entered into that arrangement, 522 | or that patent license was granted, prior to 28 March 2007. 523 | 524 | Nothing in this License shall be construed as excluding or limiting 525 | any implied license or other defenses to infringement that may 526 | otherwise be available to you under applicable patent law. 527 | 528 | 12. No Surrender of Others' Freedom. 529 | 530 | If conditions are imposed on you (whether by court order, agreement or 531 | otherwise) that contradict the conditions of this License, they do not 532 | excuse you from the conditions of this License. If you cannot convey a 533 | covered work so as to satisfy simultaneously your obligations under this 534 | License and any other pertinent obligations, then as a consequence you may 535 | not convey it at all. For example, if you agree to terms that obligate you 536 | to collect a royalty for further conveying from those to whom you convey 537 | the Program, the only way you could satisfy both those terms and this 538 | License would be to refrain entirely from conveying the Program. 539 | 540 | 13. Remote Network Interaction; Use with the GNU General Public License. 541 | 542 | Notwithstanding any other provision of this License, if you modify the 543 | Program, your modified version must prominently offer all users 544 | interacting with it remotely through a computer network (if your version 545 | supports such interaction) an opportunity to receive the Corresponding 546 | Source of your version by providing access to the Corresponding Source 547 | from a network server at no charge, through some standard or customary 548 | means of facilitating copying of software. This Corresponding Source 549 | shall include the Corresponding Source for any work covered by version 3 550 | of the GNU General Public License that is incorporated pursuant to the 551 | following paragraph. 552 | 553 | Notwithstanding any other provision of this License, you have 554 | permission to link or combine any covered work with a work licensed 555 | under version 3 of the GNU General Public License into a single 556 | combined work, and to convey the resulting work. The terms of this 557 | License will continue to apply to the part which is the covered work, 558 | but the work with which it is combined will remain governed by version 559 | 3 of the GNU General Public License. 560 | 561 | 14. Revised Versions of this License. 562 | 563 | The Free Software Foundation may publish revised and/or new versions of 564 | the GNU Affero General Public License from time to time. Such new versions 565 | will be similar in spirit to the present version, but may differ in detail to 566 | address new problems or concerns. 567 | 568 | Each version is given a distinguishing version number. If the 569 | Program specifies that a certain numbered version of the GNU Affero General 570 | Public License "or any later version" applies to it, you have the 571 | option of following the terms and conditions either of that numbered 572 | version or of any later version published by the Free Software 573 | Foundation. If the Program does not specify a version number of the 574 | GNU Affero General Public License, you may choose any version ever published 575 | by the Free Software Foundation. 576 | 577 | If the Program specifies that a proxy can decide which future 578 | versions of the GNU Affero General Public License can be used, that proxy's 579 | public statement of acceptance of a version permanently authorizes you 580 | to choose that version for the Program. 581 | 582 | Later license versions may give you additional or different 583 | permissions. However, no additional obligations are imposed on any 584 | author or copyright holder as a result of your choosing to follow a 585 | later version. 586 | 587 | 15. Disclaimer of Warranty. 588 | 589 | THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY 590 | APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT 591 | HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY 592 | OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, 593 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 594 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM 595 | IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF 596 | ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 597 | 598 | 16. Limitation of Liability. 599 | 600 | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 601 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS 602 | THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY 603 | GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE 604 | USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF 605 | DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD 606 | PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), 607 | EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF 608 | SUCH DAMAGES. 609 | 610 | 17. Interpretation of Sections 15 and 16. 611 | 612 | If the disclaimer of warranty and limitation of liability provided 613 | above cannot be given local legal effect according to their terms, 614 | reviewing courts shall apply local law that most closely approximates 615 | an absolute waiver of all civil liability in connection with the 616 | Program, unless a warranty or assumption of liability accompanies a 617 | copy of the Program in return for a fee. 618 | 619 | END OF TERMS AND CONDITIONS 620 | 621 | How to Apply These Terms to Your New Programs 622 | 623 | If you develop a new program, and you want it to be of the greatest 624 | possible use to the public, the best way to achieve this is to make it 625 | free software which everyone can redistribute and change under these terms. 626 | 627 | To do so, attach the following notices to the program. It is safest 628 | to attach them to the start of each source file to most effectively 629 | state the exclusion of warranty; and each file should have at least 630 | the "copyright" line and a pointer to where the full notice is found. 631 | 632 | 633 | Copyright (C) 634 | 635 | This program is free software: you can redistribute it and/or modify 636 | it under the terms of the GNU Affero General Public License as published 637 | by the Free Software Foundation, either version 3 of the License, or 638 | (at your option) any later version. 639 | 640 | This program is distributed in the hope that it will be useful, 641 | but WITHOUT ANY WARRANTY; without even the implied warranty of 642 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 643 | GNU Affero General Public License for more details. 644 | 645 | You should have received a copy of the GNU Affero General Public License 646 | along with this program. If not, see . 647 | 648 | Also add information on how to contact you by electronic and paper mail. 649 | 650 | If your software can interact with users remotely through a computer 651 | network, you should also make sure that it provides a way for users to 652 | get its source. For example, if your program is a web application, its 653 | interface could display a "Source" link that leads users to an archive 654 | of the code. There are many ways you could offer source, and different 655 | solutions will be better for different programs; see section 13 for the 656 | specific requirements. 657 | 658 | You should also get your employer (if you work as a programmer) or school, 659 | if any, to sign a "copyright disclaimer" for the program, if necessary. 660 | For more information on this, and how to apply and follow the GNU AGPL, see 661 | . 662 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # BanAnnouncer 2 | Announce the Minecraft bans on your Discord server. https://www.spigotmc.org/resources/banannouncer.64976/ 3 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 4 | 4.0.0 5 | 6 | me.tini 7 | ban-announcer 8 | 2.9.0 9 | BanAnnouncer 10 | 11 | 12 | 13 | spigot-repo 14 | https://hub.spigotmc.org/nexus/content/repositories/snapshots/ 15 | 16 | 17 | bungeecord-repo 18 | https://oss.sonatype.org/content/repositories/snapshots 19 | 20 | 21 | velocity-repo 22 | https://repo.velocitypowered.com/snapshots/ 23 | 24 | 25 | sponge-repo 26 | https://repo.spongepowered.org/maven/ 27 | 28 | 29 | jcenter 30 | https://jcenter.bintray.com 31 | 32 | 33 | 34 | spicord-repo 35 | https://repo.spicord.org/ 36 | 37 | 38 | 39 | arim-mvn-agpl3 40 | https://mvn-repo.arim.space/affero-gpl3/ 41 | 42 | 43 | 44 | s01-sonatype 45 | https://s01.oss.sonatype.org/content/repositories/snapshots/ 46 | 47 | 48 | 49 | essentialsx 50 | https://repo.essentialsx.net/releases/ 51 | 52 | 53 | 54 | 55 | 56 | org.spigotmc 57 | spigot-api 58 | 1.19-R0.1-SNAPSHOT 59 | provided 60 | 61 | 62 | net.md-5 63 | bungeecord-api 64 | 1.19-R0.1-SNAPSHOT 65 | provided 66 | 67 | 68 | com.velocitypowered 69 | velocity-api 70 | 3.1.1-SNAPSHOT 71 | provided 72 | 73 | 74 | org.spongepowered 75 | spongeapi 76 | 8.0.0 77 | provided 78 | 79 | 80 | org.spicord 81 | spicord-common 82 | 5.3.1 83 | provided 84 | 85 | 86 | org.projectlombok 87 | lombok 88 | 1.18.8 89 | provided 90 | 91 | 92 | net.dv8tion 93 | JDA 94 | 5.0.0-beta.4 95 | provided 96 | 97 | 98 | space.arim.libertybans 99 | bans-api 100 | 1.0.4 101 | provided 102 | 103 | 104 | litebans 105 | api 106 | 0.4.1 107 | provided 108 | 109 | 110 | me.leoko.advancedban 111 | AdvancedBan-Bukkit 112 | 2.3.0 113 | provided 114 | 115 | 116 | me.leoko.advancedban 117 | AdvancedBan-Bungee 118 | 2.3.0 119 | provided 120 | 121 | 122 | org.maxgamer 123 | maxbans-plus 124 | 1.9 125 | provided 126 | 127 | 128 | net.ess3 129 | EssentialsX 130 | 2.18.2 131 | provided 132 | 133 | 134 | com.github.fefo6644 135 | betterjails-api 136 | 1.5-SNAPSHOT 137 | provided 138 | 139 | 140 | 141 | 142 | 1.8 143 | 1.8 144 | 1.8 145 | UTF-8 146 | 147 | 148 | 149 | ${project.name}_${project.version} 150 | 151 | 152 | ${basedir}/src/main/resources 153 | true 154 | 155 | **/* 156 | 157 | 158 | 159 | ${basedir}/src/main/resources 160 | true 161 | 162 | sponge_plugins.json 163 | 164 | META-INF 165 | 166 | 167 | src/main/java 168 | 169 | 170 | 171 | -------------------------------------------------------------------------------- /src/main/java/me/tini/announcer/BanAnnouncer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 OopsieWoopsie 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU Affero General Public License as 6 | * published by the Free Software Foundation, either version 3 of the 7 | * License, or (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU Affero General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU Affero General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package me.tini.announcer; 19 | 20 | import static me.tini.announcer.PunishmentInfo.Type.*; 21 | 22 | import java.io.File; 23 | import java.util.Collection; 24 | import java.util.Date; 25 | import java.util.EnumMap; 26 | import java.util.HashMap; 27 | import java.util.Map; 28 | import java.util.Map.Entry; 29 | import java.util.function.BiFunction; 30 | import java.util.function.Function; 31 | import java.util.function.Supplier; 32 | import java.util.logging.Logger; 33 | 34 | import org.spicord.Spicord; 35 | import org.spicord.bot.DiscordBot; 36 | import org.spicord.embed.Embed; 37 | import org.spicord.embed.EmbedSender; 38 | 39 | import lombok.Getter; 40 | import me.tini.announcer.config.Config; 41 | import me.tini.announcer.config.Messages; 42 | import me.tini.announcer.extension.AbstractExtension; 43 | import me.tini.announcer.extension.ExtensionContainer; 44 | import me.tini.announcer.extension.ExtensionInfo; 45 | import me.tini.announcer.extension.FileExtensionContainer; 46 | import net.dv8tion.jda.api.JDA; 47 | import net.dv8tion.jda.api.entities.channel.middleman.GuildChannel; 48 | import net.dv8tion.jda.api.entities.channel.middleman.GuildMessageChannel; 49 | 50 | public final class BanAnnouncer { 51 | 52 | private Map allExtensions = new HashMap<>(0); 53 | 54 | @Getter private Config config; 55 | @Getter private final BanAnnouncerPlugin plugin; 56 | @Getter private Logger logger; 57 | @Getter private boolean enabled = true; 58 | 59 | private Map> callbacks; 60 | private DiscordBot bot; 61 | 62 | private Map> allPlaceholders = new HashMap<>(); 63 | 64 | public BanAnnouncer(Config config, Spicord spicord, BanAnnouncerPlugin plugin) { 65 | this.config = config; 66 | this.plugin = plugin; 67 | this.logger = plugin.getLogger(); 68 | 69 | this.callbacks = new EnumMap<>(PunishmentInfo.Type.class); 70 | 71 | BiFunction builder; 72 | 73 | allPlaceholders.put("id", punishment -> punishment.getId()); 74 | allPlaceholders.put("player", punishment -> punishment.getPlayer()); 75 | allPlaceholders.put("player_uuid", punishment -> punishment.getPlayerId()); 76 | allPlaceholders.put("staff", punishment -> punishment.getOperator()); 77 | allPlaceholders.put("reason", punishment -> punishment.getReason()); 78 | allPlaceholders.put("duration", punishment -> punishment.getDuration()); 79 | allPlaceholders.put("jail", punishment -> punishment.getJail()); 80 | 81 | allPlaceholders.put("litebans_server_origin", punishment -> punishment.getLitebansServerOrigin()); 82 | allPlaceholders.put("litebans_server_scope", punishment -> punishment.getLitebansServerScope()); 83 | allPlaceholders.put("litebans_random_id", punishment -> punishment.getLitebansRandomId()); 84 | allPlaceholders.put("litebans_removal_reason", punishment -> punishment.getLitebansRemovalReason()); 85 | allPlaceholders.put("litebans_removed_by_name", punishment -> punishment.getLitebansRemovedByName()); 86 | 87 | for (String fmt : new String[] { "t", "T", "d", "D", "f", "F", "R" }) { 88 | allPlaceholders.put("date_start_" + fmt, punishment -> { 89 | final long seconds; 90 | 91 | if (punishment.isPermanent()) { 92 | seconds = System.currentTimeMillis() / 1000L; 93 | } else { 94 | seconds = punishment.getDateStart() / 1000L; 95 | } 96 | 97 | return ""; 98 | }); 99 | 100 | allPlaceholders.put("date_end_" + fmt, punishment -> { 101 | final long seconds; 102 | 103 | if (punishment.isPermanent()) { 104 | seconds = dateToMillis("31 Dec 9999") / 1000L; 105 | } else { 106 | seconds = punishment.getDateEnd() / 1000L; 107 | } 108 | 109 | return ""; 110 | }); 111 | } 112 | 113 | builder = (punishment, template) -> { 114 | MessageFormatter mf = new MessageFormatter(); 115 | 116 | mf.setOtherPlaceholderHandler(placeholder -> processPlaceholder(punishment, placeholder)); 117 | 118 | for (Entry> placeholders : allPlaceholders.entrySet()) { 119 | String placeholder = placeholders.getKey(); 120 | String value = placeholders.getValue().apply(punishment); 121 | 122 | mf.setString(placeholder, value); 123 | } 124 | 125 | return mf.format(template); 126 | }; 127 | 128 | Messages messages = config.getMessages(); 129 | 130 | callbacks.put(BAN, p -> builder.apply(p, p.isPermanent() ? messages.getBan() : messages.getTempban())); 131 | callbacks.put(BANIP, p -> builder.apply(p, p.isPermanent() ? messages.getBanip() : messages.getTempbanip())); 132 | callbacks.put(MUTE, p -> builder.apply(p, p.isPermanent() ? messages.getMute() : messages.getTempmute())); 133 | callbacks.put(WARN, p -> builder.apply(p, p.isPermanent() ? messages.getWarn() : messages.getTempwarn())); 134 | callbacks.put(KICK, p -> builder.apply(p, messages.getKick())); 135 | callbacks.put(NOTE, p -> builder.apply(p, messages.getNote())); 136 | callbacks.put(UNNOTE, p -> builder.apply(p, messages.getUnnote())); 137 | callbacks.put(JAIL, p -> builder.apply(p, messages.getJail())); 138 | callbacks.put(UNJAIL, p -> builder.apply(p, messages.getUnjail())); 139 | callbacks.put(UNBAN, p -> builder.apply(p, messages.getUnban())); 140 | callbacks.put(UNBANIP, p -> builder.apply(p, messages.getUnbanip())); 141 | callbacks.put(UNMUTE, p -> builder.apply(p, messages.getUnmute())); 142 | callbacks.put(UNWARN, p -> builder.apply(p, messages.getUnwarn())); 143 | 144 | callbacks.put(TEMPBAN, callbacks.get(BAN)); 145 | callbacks.put(TEMPBANIP, callbacks.get(BANIP)); 146 | callbacks.put(TEMPMUTE, callbacks.get(MUTE)); 147 | callbacks.put(TEMPWARN, callbacks.get(WARN)); 148 | } 149 | 150 | public void handlePunishment(PunishmentInfo punishment, PunishmentListener listener) { 151 | if (!enabled) { 152 | logger.warning("BanAnnouncer is not enabled, ignoring punishment."); 153 | logger.warning(punishment.toString()); 154 | return; 155 | } 156 | 157 | logger.info("Got announcement request from the '" + listener.getName() + "' listener."); 158 | 159 | Embed embed = buildEmbed(punishment); 160 | sendDiscordMessage(embed); 161 | } 162 | 163 | public Embed buildEmbed(PunishmentInfo punishment) { 164 | return callbacks.get(punishment.getType()).apply(punishment); 165 | } 166 | 167 | private void sendDiscordMessage(Embed message) { 168 | if (message == null) { 169 | logger.warning("(message is null, ignoring it)"); 170 | return; 171 | } 172 | 173 | if (bot == null || bot.getJda() == null) { 174 | logger.warning("BanAnnouncer does not have access to an active bot."); 175 | return; 176 | } 177 | 178 | JDA jda = bot.getJda(); 179 | 180 | long channelId = config.getChannelToAnnounce(); 181 | 182 | GuildChannel channel = jda.getGuildChannelById(channelId); 183 | 184 | if (channel == null || !(channel instanceof GuildMessageChannel)) { 185 | logger.severe("Cannot find the channel with id '" + channelId + "'. The message was not sent."); 186 | return; 187 | } else { 188 | EmbedSender.prepare((GuildMessageChannel) channel, message).queue(success -> { 189 | logger.info("The punishment message was sent."); 190 | }, fail -> { 191 | logger.warning("Couldn't send the punishment message: " + fail.getMessage()); 192 | }); 193 | } 194 | } 195 | 196 | public void setBot(DiscordBot bot) { 197 | this.bot = bot; 198 | } 199 | 200 | public void removeBot(DiscordBot bot) { 201 | this.bot = null; 202 | } 203 | 204 | public void disable() { 205 | for (ExtensionContainer ext : allExtensions.values()) { 206 | ext.close(); 207 | } 208 | allExtensions.clear(); 209 | callbacks.clear(); 210 | bot = null; 211 | enabled = false; 212 | config = null; 213 | callbacks = null; 214 | } 215 | 216 | public void loadExtensions(File folder) { 217 | if (folder.mkdirs()) { 218 | return; 219 | } 220 | 221 | File[] files = folder.listFiles((d, name) -> name.endsWith(".jar") || name.endsWith(".ext")); 222 | 223 | for (File file : files) { 224 | ExtensionContainer container = new FileExtensionContainer(file); 225 | 226 | ExtensionInfo info = container.getInfo(); 227 | plugin.log("[Extension] Loaded %s (id: %s)", info.getName(), info.getId()); 228 | 229 | allExtensions.put(info.getId(), container); 230 | } 231 | } 232 | 233 | public Collection getExtensions() { 234 | return allExtensions.values(); 235 | } 236 | 237 | public void registerPlaceholder(String placeholder, Function provider) { 238 | allPlaceholders.put(placeholder, provider); 239 | } 240 | 241 | public String processPlaceholder(PunishmentInfo info, String placeholder) { 242 | for (ExtensionContainer loader : allExtensions.values()) { 243 | if (loader.isInstanceCreated()) { 244 | AbstractExtension extension = loader.getInstance(); 245 | String result = extension.processPlaceholder(info, placeholder); 246 | 247 | if (result != null) { 248 | return result; 249 | } 250 | } 251 | } 252 | return null; 253 | } 254 | 255 | @SuppressWarnings("deprecation") 256 | private long dateToMillis(String date) { 257 | return new Date(date).getTime(); 258 | } 259 | 260 | public void registerExtension(String name, String id, Supplier instanceSupplier, String requiredClass) { 261 | ExtensionContainer container = new ExtensionContainer(new ExtensionInfo(name, id, null, requiredClass), instanceSupplier); 262 | allExtensions.put(id, container); 263 | plugin.log("[Extension] Loaded %s (id: %s)", name, id); 264 | } 265 | 266 | public void enableExtensions() { 267 | int enabledCount = 0; 268 | 269 | for (String id : config.getEnabledExtensions()) { 270 | ExtensionContainer container = allExtensions.get(id); 271 | 272 | if (container == null) { 273 | plugin.warn("The extension with the id '%s' was not found", id); 274 | continue; 275 | } 276 | 277 | ExtensionInfo info = container.getInfo(); 278 | 279 | if (!isClassPresent(info.getRequiredClass())) { 280 | plugin.warn("[Extension] %s (id: %s) will not work on this server because it is missing a dependency", info.getName(), info.getId()); 281 | continue; 282 | } 283 | 284 | AbstractExtension instance = container.getInstanceSupplier(plugin).get(); 285 | 286 | plugin.log("[Extension] Enabled %s (id: %s)", info.getName(), info.getId()); 287 | 288 | PunishmentListener listener = instance.getPunishmentListener(); 289 | if (listener != null) { 290 | listener.register(); 291 | } 292 | 293 | enabledCount++; 294 | } 295 | 296 | if (config.isAutoDetect()) { 297 | for (ExtensionContainer ext : allExtensions.values()) { 298 | if (config.getEnabledExtensions().contains(ext.getName())) { 299 | continue; 300 | } 301 | if (isClassPresent(ext.getInfo().getRequiredClass())) { 302 | AbstractExtension instance = ext.getInstanceSupplier(plugin).get(); 303 | 304 | plugin.log("[Extension] [AutoDetect] Enabled %s (id: %s)", ext.getInfo().getName(), ext.getInfo().getId()); 305 | 306 | PunishmentListener listener = instance.getPunishmentListener(); 307 | if (listener != null) { 308 | listener.register(); 309 | } 310 | 311 | enabledCount++; 312 | } 313 | } 314 | } 315 | 316 | if (enabledCount == 0) { 317 | plugin.warn("None of the extensions were enabled!"); 318 | } 319 | } 320 | 321 | private static boolean isClassPresent(String className) { 322 | try { 323 | Class.forName(className, false, BanAnnouncer.class.getClassLoader()); 324 | return true; 325 | } catch (ClassNotFoundException e) {} 326 | return false; 327 | } 328 | } 329 | -------------------------------------------------------------------------------- /src/main/java/me/tini/announcer/BanAnnouncerPlugin.java: -------------------------------------------------------------------------------- 1 | package me.tini.announcer; 2 | 3 | import org.spicord.plugin.PluginInterface; 4 | 5 | public interface BanAnnouncerPlugin extends PluginInterface { 6 | 7 | BanAnnouncer getAnnouncer(); 8 | 9 | String getVersion(); 10 | 11 | default void log(String msg, Object... args) { 12 | getLogger().info(String.format(msg, args)); 13 | } 14 | 15 | default void warn(String msg, Object... args) { 16 | getLogger().warning(String.format(msg, args)); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/me/tini/announcer/MessageFormatter.java: -------------------------------------------------------------------------------- 1 | package me.tini.announcer; 2 | 3 | import java.io.UnsupportedEncodingException; 4 | import java.net.URLEncoder; 5 | import java.util.HashMap; 6 | import java.util.Map; 7 | import java.util.function.Function; 8 | import java.util.regex.Matcher; 9 | import java.util.regex.Pattern; 10 | 11 | import org.spicord.embed.Embed; 12 | 13 | import com.google.gson.Gson; 14 | import com.google.gson.JsonArray; 15 | import com.google.gson.JsonElement; 16 | import com.google.gson.JsonObject; 17 | 18 | public class MessageFormatter { 19 | 20 | private static final Pattern placeholderPattern = Pattern.compile("([%]{1}[A-Za-z0-9_]{1,}[%]{1})"); 21 | 22 | private final Map map; 23 | 24 | private Function otherHandler; 25 | 26 | public MessageFormatter() { 27 | this.map = new HashMap(); 28 | } 29 | 30 | public void setOtherPlaceholderHandler(Function handler) { 31 | this.otherHandler = handler; 32 | } 33 | 34 | public MessageFormatter setString(String key, String value) { 35 | map.put(key, value); 36 | return this; 37 | } 38 | 39 | public Embed format(Embed embed) { 40 | return embed == null ? null : format0(embed); 41 | } 42 | 43 | private Embed format0(Embed embed) { 44 | Gson gson = new Gson(); 45 | 46 | JsonObject root = gson.toJsonTree(embed).getAsJsonObject(); 47 | 48 | formatElement(root); 49 | 50 | return gson.fromJson(root, Embed.class); 51 | } 52 | 53 | private void formatElement(JsonElement element) { 54 | if (element.isJsonObject()) { 55 | JsonObject object = element.getAsJsonObject(); 56 | 57 | for (Map.Entry entry : object.entrySet()) { 58 | String key = entry.getKey(); 59 | JsonElement value = entry.getValue(); 60 | 61 | if (isString(value)) { 62 | boolean isUrl = "url".equals(key) || "icon_url".equals(key); 63 | 64 | String val = getAsString(value); 65 | 66 | val = setPlaceholders(val, isUrl); 67 | 68 | object.addProperty(key, val); 69 | } else { 70 | formatElement(value); 71 | } 72 | } 73 | } else if (element.isJsonArray()) { 74 | JsonArray array = element.getAsJsonArray(); 75 | 76 | for (int i = 0; i < array.size(); i++) { 77 | formatElement(array.get(i)); 78 | } 79 | } 80 | } 81 | 82 | private String urlencode(String str) { 83 | try { 84 | return URLEncoder.encode(str, "UTF-8").replace("+", "%20"); 85 | } catch (UnsupportedEncodingException e) { 86 | return str; 87 | } 88 | } 89 | 90 | private String getAsString(JsonElement value) { 91 | return value.getAsJsonPrimitive().getAsString(); 92 | } 93 | 94 | private boolean isString(JsonElement value) { 95 | return value.isJsonPrimitive() && value.getAsJsonPrimitive().isString(); 96 | } 97 | 98 | private String setPlaceholders(String message, boolean isUrl) { 99 | Matcher matcher = placeholderPattern.matcher(message); 100 | while (matcher.find()) { 101 | final String found = matcher.group(); 102 | final String foundNoSym = found.substring(1, found.length() - 1); 103 | 104 | String value = map.get(foundNoSym); 105 | if (value == null && otherHandler != null) { 106 | value = otherHandler.apply(foundNoSym); 107 | } 108 | if (isUrl) { 109 | value = urlencode(value); 110 | } 111 | 112 | message = message.replace(found, value); 113 | } 114 | return message; 115 | } 116 | } 117 | -------------------------------------------------------------------------------- /src/main/java/me/tini/announcer/PunishmentInfo.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 OopsieWoopsie 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU Affero General Public License as 6 | * published by the Free Software Foundation, either version 3 of the 7 | * License, or (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU Affero General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU Affero General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package me.tini.announcer; 19 | 20 | import eu.mcdb.util.chat.ChatColor; 21 | import lombok.Data; 22 | import lombok.ToString; 23 | 24 | @ToString 25 | @Data 26 | public final class PunishmentInfo { 27 | 28 | private String id; 29 | private String player; 30 | private String operator; 31 | private String reason; 32 | private String duration; 33 | private String jail; 34 | private boolean permanent = false; 35 | private Type type; 36 | 37 | private long dateStart; 38 | private long dateEnd; 39 | private String playerId; 40 | 41 | private String litebansServerScope; 42 | private String litebansServerOrigin; 43 | private String litebansRandomId; 44 | private String litebansRemovalReason; 45 | private String litebansRemovedByName; 46 | 47 | public PunishmentInfo() {} 48 | 49 | public PunishmentInfo(Type type) { 50 | this.type = type; 51 | } 52 | 53 | public void setReason(String reason) { 54 | reason = ChatColor.stripColor(reason); 55 | this.reason = reason.equals("") ? "none" : reason; 56 | } 57 | 58 | public void setDuration(String duration) { 59 | duration = ChatColor.stripColor(duration); 60 | this.duration = duration.equals("") ? "unknown" : duration; 61 | } 62 | 63 | public boolean isRevoked() { 64 | if (type == null) { 65 | throw new IllegalStateException("Type is not set"); 66 | } 67 | switch (type) { 68 | case UNJAIL: 69 | case UNBAN: 70 | case UNBANIP: 71 | case UNMUTE: 72 | case UNWARN: 73 | return true; 74 | default: 75 | return false; 76 | } 77 | } 78 | 79 | public enum Type { 80 | KICK, 81 | JAIL, UNJAIL, 82 | BAN, TEMPBAN, UNBAN, 83 | MUTE, TEMPMUTE, UNMUTE, 84 | BANIP, TEMPBANIP, UNBANIP, 85 | WARN, TEMPWARN, UNWARN, 86 | NOTE, UNNOTE // AdvancedBan only 87 | ; 88 | } 89 | 90 | public void setStart(long dateStart) { 91 | this.dateStart = dateStart; 92 | } 93 | 94 | public void setEnd(long dateEnd) { 95 | this.dateEnd = dateEnd; 96 | } 97 | 98 | public void setPlayerId(String uuidDashed) { 99 | this.playerId = uuidDashed; 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /src/main/java/me/tini/announcer/PunishmentListener.java: -------------------------------------------------------------------------------- 1 | package me.tini.announcer; 2 | 3 | import me.tini.announcer.extension.ExtensionContainer; 4 | 5 | public abstract class PunishmentListener { 6 | 7 | private final BanAnnouncer announcer; 8 | 9 | private ExtensionContainer myLoader; 10 | 11 | public PunishmentListener(BanAnnouncer announcer) { 12 | this.announcer = announcer; 13 | } 14 | 15 | public final void handlePunishment(PunishmentInfo punishment) { 16 | announcer.handlePunishment(punishment, this); 17 | } 18 | 19 | public BanAnnouncer getAnnouncer() { 20 | return announcer; 21 | } 22 | 23 | public ExtensionContainer getExtensionLoader() { 24 | if (myLoader != null) { 25 | return myLoader; 26 | } 27 | for (ExtensionContainer loader : announcer.getExtensions()) { 28 | if (loader.isInstanceCreated()) { 29 | if (loader.getInstance().getPunishmentListener() == this) { 30 | return myLoader = loader; 31 | } 32 | } 33 | } 34 | throw new IllegalStateException("Unable to get extension"); 35 | } 36 | 37 | public String getName() { 38 | return getExtensionLoader().getInfo().getName(); 39 | } 40 | 41 | public abstract void register(); 42 | 43 | public abstract void unregister(); 44 | 45 | } 46 | -------------------------------------------------------------------------------- /src/main/java/me/tini/announcer/ReloadCommand.java: -------------------------------------------------------------------------------- 1 | package me.tini.announcer; 2 | 3 | import eu.mcdb.universal.command.UniversalCommandSender; 4 | import eu.mcdb.universal.command.api.Command; 5 | import me.tini.announcer.config.Config; 6 | 7 | public class ReloadCommand extends Command { 8 | 9 | public ReloadCommand() { 10 | super( 11 | "banannouncer-reload", // main command 12 | "banannouncer.reload", // required permission 13 | "bareload" // alias command 14 | ); 15 | super.setCommandHandler(this::handle); 16 | } 17 | 18 | public boolean handle(UniversalCommandSender sender) { 19 | Config.getInstance().reload(); 20 | sender.sendMessage("Successfully reloaded BanAnnouncer"); 21 | return true; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/me/tini/announcer/addon/BanAnnouncerAddon.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 OopsieWoopsie 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU Affero General Public License as 6 | * published by the Free Software Foundation, either version 3 of the 7 | * License, or (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU Affero General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU Affero General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package me.tini.announcer.addon; 19 | 20 | import java.util.ArrayList; 21 | import java.util.List; 22 | import java.util.UUID; 23 | 24 | import org.spicord.api.addon.SimpleAddon; 25 | import org.spicord.bot.DiscordBot; 26 | import org.spicord.bot.command.SlashCommand; 27 | import org.spicord.embed.Embed; 28 | 29 | import me.tini.announcer.BanAnnouncer; 30 | import me.tini.announcer.BanAnnouncerPlugin; 31 | import me.tini.announcer.PunishmentInfo; 32 | import me.tini.announcer.config.Config; 33 | import net.dv8tion.jda.api.Permission; 34 | import net.dv8tion.jda.api.entities.Guild; 35 | import net.dv8tion.jda.api.entities.channel.middleman.GuildChannel; 36 | import net.dv8tion.jda.api.interactions.commands.OptionMapping; 37 | import net.dv8tion.jda.api.interactions.commands.OptionType; 38 | 39 | public final class BanAnnouncerAddon extends SimpleAddon { 40 | 41 | private BanAnnouncer announcer; 42 | 43 | public BanAnnouncerAddon(BanAnnouncerPlugin plugin) { 44 | super("BanAnnouncer", "ban_announcer", "Tini", plugin.getVersion()); 45 | this.announcer = plugin.getAnnouncer(); 46 | } 47 | 48 | @Override 49 | public void onReady(DiscordBot bot) { 50 | long channelId = announcer.getConfig().getChannelToAnnounce(); 51 | 52 | GuildChannel channel = bot.getJda().getGuildChannelById(channelId); 53 | 54 | if (channel == null) { 55 | getLogger().severe(String.format( 56 | "The channel with id '%d' was not found, please fix it and reload the config!", 57 | channelId 58 | )); 59 | } 60 | 61 | if (!announcer.getConfig().isUseDiscordCommand()) { 62 | getLogger().info("Skipped Discord command registration."); 63 | return; 64 | } 65 | 66 | if (channel == null) { 67 | getLogger().severe(String.format("The channel with id '%d' was not found, the Discord command could not be registered.", channelId)); 68 | return; 69 | } 70 | 71 | Guild guild = channel.getGuild(); 72 | 73 | SlashCommand main = new SlashCommand("banannouncer", "Main BanAnnouncer command") 74 | .setDefaultPermissions(Permission.BAN_MEMBERS) 75 | .addSubcommand( 76 | new SlashCommand("test", "Test an embed file") 77 | .addOption(OptionType.STRING, "embed", "The embed name", true, true) 78 | .setExecutor(event -> { 79 | OptionMapping nameOption = event.getOption("embed"); 80 | 81 | if (nameOption == null) { 82 | return; 83 | } 84 | 85 | String embedName = nameOption.getAsString(); 86 | 87 | final PunishmentInfo.Type type; 88 | try { 89 | type = PunishmentInfo.Type.valueOf(embedName.toUpperCase()); 90 | } catch (IllegalArgumentException e) { 91 | event.reply("The specified embed does not exists") 92 | .setEphemeral(true) 93 | .queue(); 94 | return; 95 | } 96 | 97 | PunishmentInfo action = new PunishmentInfo(type); 98 | action.setId("0"); 99 | action.setPlayer("Wumpus"); 100 | action.setPlayerId(new UUID(0, 0).toString()); 101 | action.setOperator(event.getUser().getName()); 102 | action.setReason("Eating too many cookies"); 103 | 104 | action.setDuration("forever"); 105 | action.setJail("jail1"); 106 | action.setPermanent(true); 107 | 108 | Embed embed = announcer.buildEmbed(action); 109 | 110 | if (embed == null) { 111 | event.reply("The specified embed is disabled in your server").setEphemeral(true).queue(); 112 | return; 113 | } 114 | 115 | if (embed.hasEmbedData() && embed.hasContent()) { 116 | event.replyEmbeds(embed.toJdaEmbed()) 117 | .addContent(embed.getContent()) 118 | .setEphemeral(true) 119 | .queue(); 120 | } else if (embed.hasEmbedData()) { 121 | event.replyEmbeds(embed.toJdaEmbed()) 122 | .setEphemeral(true) 123 | .queue(); 124 | } else if (embed.hasContent()) { 125 | event.reply(embed.getContent()) 126 | .setEphemeral(true) 127 | .queue(); 128 | } else { 129 | event.reply("That embed file appears to be empty") 130 | .setEphemeral(true) 131 | .queue(); 132 | } 133 | }) 134 | .setCompleter(event -> { 135 | List list = new ArrayList<>(); 136 | for (PunishmentInfo.Type type : PunishmentInfo.Type.values()) { 137 | list.add(type.name().toLowerCase()); 138 | } 139 | event.replyChoiceStrings(list).queue(); 140 | }) 141 | ) 142 | .addSubcommand( 143 | new SlashCommand("reload", "Reloads the BanAnnouncer configuration") 144 | .setExecutor(event -> { 145 | Config.getInstance().reload(); 146 | 147 | event.reply("Reloaded the configuration").setEphemeral(true).queue(); 148 | }) 149 | ) 150 | ; 151 | 152 | bot.registerCommand(main, guild); 153 | } 154 | 155 | @Override 156 | public void onLoad(DiscordBot bot) { 157 | announcer.setBot(bot); 158 | } 159 | 160 | @Override 161 | public void onShutdown(DiscordBot bot) { 162 | announcer.removeBot(bot); 163 | } 164 | } 165 | -------------------------------------------------------------------------------- /src/main/java/me/tini/announcer/config/Config.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2020 OopsieWoopsie 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU Affero General Public License as 6 | * published by the Free Software Foundation, either version 3 of the 7 | * License, or (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU Affero General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU Affero General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package me.tini.announcer.config; 19 | 20 | import java.io.File; 21 | import java.io.IOException; 22 | import java.io.InputStream; 23 | import java.nio.file.Files; 24 | import java.nio.file.StandardCopyOption; 25 | import java.util.HashSet; 26 | import java.util.List; 27 | import java.util.Set; 28 | import java.util.logging.Logger; 29 | 30 | import org.spicord.embed.EmbedLoader; 31 | 32 | import eu.mcdb.universal.config.YamlConfiguration; 33 | import lombok.Getter; 34 | import me.tini.announcer.BanAnnouncerPlugin; 35 | 36 | public class Config { 37 | 38 | private final static int CONFIG_VERSION = 4; 39 | 40 | @Getter private static Config instance; 41 | 42 | private File dataFolder; 43 | private EmbedLoader embedLoader; 44 | private File configFile; 45 | private Logger logger; 46 | 47 | @Getter private long channelToAnnounce; 48 | @Getter private Messages messages; 49 | 50 | @Getter private boolean ignoreSilent; 51 | @Getter private String consoleName; 52 | @Getter private String automaticText; 53 | 54 | @Getter private boolean useDiscordCommand; 55 | 56 | @Getter private boolean autoDetect; 57 | 58 | @Getter private Set enabledExtensions; 59 | 60 | public Config(BanAnnouncerPlugin plugin) { 61 | instance = this; 62 | this.dataFolder = plugin.getDataFolder(); 63 | this.logger = plugin.getLogger(); 64 | 65 | try { 66 | this.embedLoader = EmbedLoader.extractAndLoad(plugin.getFile(), new File(dataFolder, "embed")); 67 | } catch (IOException e) { 68 | throw new RuntimeException("An error ocurred while extracting the embed files", e); 69 | } 70 | 71 | this.configFile = new File(dataFolder, "config.yml"); 72 | this.loadConfig(false); 73 | } 74 | 75 | public void reload() { 76 | this.loadConfig(true); 77 | } 78 | 79 | public String getExpiredOperatorName() { 80 | return String.format("%s (%s)", consoleName, automaticText); 81 | } 82 | 83 | private void loadConfig(boolean reload) { 84 | try { 85 | if (!configFile.exists()) 86 | createConfig(); 87 | 88 | final YamlConfiguration config = YamlConfiguration.load(configFile); 89 | final int file_version = config.getInt("config-version", 0); 90 | 91 | if (file_version < CONFIG_VERSION && !reload) { 92 | final File oldConfig = new File(dataFolder, "config.yml." + file_version); 93 | 94 | if (oldConfig.exists()) 95 | oldConfig.delete(); 96 | 97 | configFile.renameTo(oldConfig); 98 | 99 | logger.warning("An outdated config was found and it was renamed to '" + oldConfig.getName() + "'."); 100 | 101 | createConfig(); 102 | 103 | loadConfig(false); 104 | } else { 105 | if (reload) { 106 | messages.reload(); 107 | } else { 108 | messages = new Messages(embedLoader, config, dataFolder); 109 | } 110 | 111 | List oldConfigChannels = config.getLongList("channels-to-announce"); 112 | 113 | channelToAnnounce = config.getLong( 114 | "channel-to-announce", 115 | oldConfigChannels != null && !oldConfigChannels.isEmpty() ? oldConfigChannels.get(0) : 0L 116 | ); 117 | 118 | String punishmentManager = config.getString("punishment-manager", "auto"); 119 | String jailManager = config.getString("jail-manager", "off"); 120 | 121 | Set legacyEnabled = new HashSet<>(); 122 | 123 | if (punishmentManager != null) { 124 | if ("auto".equals(punishmentManager)) { 125 | this.autoDetect = true; 126 | } else { 127 | legacyEnabled.add(punishmentManager); 128 | } 129 | } 130 | if (jailManager != null) { 131 | if (!"off".equals(jailManager) && !"false".equals(jailManager)) { 132 | legacyEnabled.add(jailManager); 133 | } 134 | } 135 | List enabledExt = config.getStringList("enabled-extensions"); 136 | if (enabledExt != null) { 137 | legacyEnabled.addAll(enabledExt); 138 | } 139 | this.enabledExtensions = legacyEnabled; 140 | 141 | ignoreSilent = config.getBoolean("ignore-silent", false); 142 | consoleName = config.getString("console-name", "Console"); 143 | automaticText = config.getString("automatic", "Automatic"); 144 | useDiscordCommand = config.getBoolean("enable-discord-command", true); 145 | } 146 | } catch (Exception e) { 147 | logger.severe("This is a configuration error, NOT a plugin error, please generate a new config or fix it."); 148 | e.printStackTrace(); 149 | } 150 | } 151 | 152 | private void createConfig() throws IOException { 153 | if (!dataFolder.exists()) 154 | dataFolder.mkdir(); 155 | 156 | try (final InputStream in = getClass().getResourceAsStream("/config.yml")) { 157 | Files.copy(in, configFile.toPath(), StandardCopyOption.REPLACE_EXISTING); 158 | } 159 | } 160 | } 161 | -------------------------------------------------------------------------------- /src/main/java/me/tini/announcer/config/Messages.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2020 OopsieWoopsie 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU Affero General Public License as 6 | * published by the Free Software Foundation, either version 3 of the 7 | * License, or (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU Affero General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU Affero General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package me.tini.announcer.config; 19 | 20 | import java.io.File; 21 | import org.spicord.embed.Embed; 22 | import org.spicord.embed.EmbedLoader; 23 | import eu.mcdb.universal.config.YamlConfiguration; 24 | import lombok.Getter; 25 | 26 | @Getter 27 | public final class Messages { 28 | 29 | private Embed kick; 30 | private Embed jail; 31 | 32 | private Embed ban; 33 | private Embed banip; 34 | private Embed mute; 35 | private Embed warn; 36 | private Embed note; 37 | 38 | private Embed tempban; 39 | private Embed tempbanip; 40 | private Embed tempmute; 41 | private Embed tempwarn; 42 | 43 | private Embed unjail; 44 | private Embed unban; 45 | private Embed unbanip; 46 | private Embed unwarn; 47 | private Embed unmute; 48 | private Embed unnote; 49 | 50 | private final EmbedLoader embedLoader; 51 | private final YamlConfiguration config; 52 | private final File embedFolder; 53 | 54 | protected Messages(EmbedLoader embedLoader, YamlConfiguration config, File dataFolder) { 55 | this.embedLoader = embedLoader; 56 | this.config = config; 57 | this.embedFolder = new File(dataFolder, "embed"); 58 | this.load(); 59 | } 60 | 61 | private void load() { 62 | this.kick = getEmbed("kick"); 63 | this.note = getEmbed("note"); 64 | this.jail = getEmbed("jail"); 65 | this.ban = getEmbed("ban"); 66 | this.tempban = getEmbed("tempban"); 67 | this.mute = getEmbed("mute"); 68 | this.tempmute = getEmbed("tempmute"); 69 | this.banip = getEmbed("banip"); 70 | this.tempbanip = getEmbed("tempbanip"); 71 | this.warn = getEmbed("warn"); 72 | this.tempwarn = getEmbed("tempwarn"); 73 | this.unbanip = getEmbed("unbanip"); 74 | this.unwarn = getEmbed("unwarn"); 75 | this.unmute = getEmbed("unmute"); 76 | this.unban = getEmbed("unban"); 77 | this.unjail = getEmbed("unjail"); 78 | this.unnote = getEmbed("unnote"); 79 | } 80 | 81 | public void reload() { 82 | this.embedLoader.load(embedFolder); 83 | this.load(); 84 | } 85 | 86 | private Embed getEmbed(final String key) { 87 | String message = config.getString("messages." + key); 88 | 89 | if (message != null) { 90 | message = message.trim(); 91 | } else { 92 | message = "{embed:" + key + "}"; 93 | } 94 | 95 | if (message.startsWith("{embed:") && message.endsWith("}")) { 96 | final String embedName = message.substring(7, message.length() - 1).trim(); 97 | 98 | return embedLoader.getEmbedByName(embedName); 99 | } 100 | 101 | if (!message.isEmpty()) { 102 | return Embed.fromString(message); 103 | } 104 | 105 | return null; 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /src/main/java/me/tini/announcer/extension/AbstractExtension.java: -------------------------------------------------------------------------------- 1 | package me.tini.announcer.extension; 2 | 3 | import me.tini.announcer.PunishmentInfo; 4 | import me.tini.announcer.PunishmentListener; 5 | 6 | public abstract class AbstractExtension { 7 | 8 | public String processPlaceholder(PunishmentInfo info, String placeholder) { 9 | return null; 10 | } 11 | 12 | public PunishmentListener getPunishmentListener() { 13 | return null; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/me/tini/announcer/extension/ExtensionContainer.java: -------------------------------------------------------------------------------- 1 | package me.tini.announcer.extension; 2 | 3 | import java.util.function.Supplier; 4 | 5 | import me.tini.announcer.BanAnnouncerPlugin; 6 | 7 | public class ExtensionContainer { 8 | 9 | ExtensionInfo info; 10 | Supplier instanceSupplier; 11 | AbstractExtension instance; 12 | 13 | ExtensionContainer() {} 14 | 15 | public ExtensionContainer(ExtensionInfo info, Supplier instanceSupplier) { 16 | this.info = info; 17 | this.instanceSupplier = instanceSupplier; 18 | } 19 | 20 | public String getName() { 21 | return info.getName(); 22 | } 23 | 24 | public ExtensionInfo getInfo() { 25 | return info; 26 | } 27 | 28 | public Supplier getInstanceSupplier(BanAnnouncerPlugin plugin) { 29 | if (instance != null) { 30 | return () -> instance; 31 | } 32 | return () -> (instance = instanceSupplier.get()); 33 | } 34 | 35 | public boolean isInstanceCreated() { 36 | return instance != null; 37 | } 38 | 39 | public AbstractExtension getInstance() { 40 | return instance; 41 | } 42 | 43 | public void close() { 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/main/java/me/tini/announcer/extension/ExtensionInfo.java: -------------------------------------------------------------------------------- 1 | package me.tini.announcer.extension; 2 | 3 | import com.google.gson.annotations.SerializedName; 4 | 5 | public class ExtensionInfo { 6 | 7 | private String name; 8 | 9 | @SerializedName(value = "id", alternate = { "key" }) 10 | private String id; 11 | 12 | @SerializedName("class") 13 | private String mainClass; 14 | 15 | private String requiredClass; 16 | 17 | //################################### 18 | private boolean isPunishmentManager, isJailManager; 19 | //################################### 20 | 21 | public ExtensionInfo(String name, String id, String mainClass, String requiredClass) { 22 | this.name = name; 23 | this.id = id; 24 | this.mainClass = mainClass; 25 | this.requiredClass = requiredClass; 26 | } 27 | 28 | public String getName() { 29 | return name; 30 | } 31 | 32 | public String getId() { 33 | return id; 34 | } 35 | 36 | public String getMainClass() { 37 | return mainClass; 38 | } 39 | 40 | public String getRequiredClass() { 41 | return requiredClass; 42 | } 43 | 44 | @Deprecated 45 | public boolean hasPunishmentManager() { 46 | return isPunishmentManager || isJailManager; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/main/java/me/tini/announcer/extension/FileExtensionContainer.java: -------------------------------------------------------------------------------- 1 | package me.tini.announcer.extension; 2 | 3 | import java.io.File; 4 | import java.io.IOException; 5 | import java.io.InputStream; 6 | import java.io.InputStreamReader; 7 | import java.lang.reflect.Constructor; 8 | import java.net.MalformedURLException; 9 | import java.net.URL; 10 | import java.net.URLClassLoader; 11 | import java.util.function.Supplier; 12 | 13 | import com.google.gson.Gson; 14 | 15 | import me.tini.announcer.BanAnnouncerPlugin; 16 | 17 | public class FileExtensionContainer extends ExtensionContainer { 18 | 19 | private static final Gson GSON = new Gson(); 20 | 21 | private URLClassLoader loader; 22 | 23 | public FileExtensionContainer(File file) { 24 | loader = new URLClassLoader( 25 | new URL[] { fileToUrl(file) }, 26 | FileExtensionContainer.class.getClassLoader() 27 | ); 28 | 29 | InputStream extensionJson = loader.getResourceAsStream("extension.json"); 30 | 31 | if (extensionJson == null) { 32 | throw new IllegalArgumentException("Archive is missing the extension.json file"); 33 | } 34 | 35 | info = GSON.fromJson(new InputStreamReader(extensionJson), ExtensionInfo.class); 36 | } 37 | 38 | @Override 39 | public Supplier getInstanceSupplier(BanAnnouncerPlugin plugin) { 40 | if (instance != null) { 41 | return () -> instance; 42 | } 43 | 44 | return () -> { 45 | try { 46 | Class listenerClass = loader.loadClass(info.getMainClass()); 47 | Constructor constructor = listenerClass.getConstructor(BanAnnouncerPlugin.class); 48 | Object ins = constructor.newInstance(plugin); 49 | 50 | if (ins instanceof AbstractExtension) { 51 | instance = (AbstractExtension) ins; 52 | return instance; 53 | } 54 | 55 | throw new IllegalStateException("Unknown instance type: " + ins.getClass()); 56 | } catch (Exception e) { 57 | throw new RuntimeException("Failed to create listener instance", e); 58 | } 59 | }; 60 | } 61 | 62 | @Override 63 | public void close() { 64 | try { 65 | loader.close(); 66 | } catch (IOException e) {} 67 | } 68 | 69 | private static URL fileToUrl(File file) { 70 | try { 71 | return file.toURI().toURL(); 72 | } catch (MalformedURLException e) { 73 | throw new RuntimeException(e); 74 | } 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /src/main/java/me/tini/announcer/extension/impl/advancedban/AdvancedBanExtensionBukkit.java: -------------------------------------------------------------------------------- 1 | package me.tini.announcer.extension.impl.advancedban; 2 | 3 | import me.tini.announcer.PunishmentListener; 4 | import me.tini.announcer.extension.AbstractExtension; 5 | import me.tini.announcer.plugin.bukkit.BanAnnouncerBukkit; 6 | 7 | public class AdvancedBanExtensionBukkit extends AbstractExtension { 8 | 9 | private PunishmentListener listener; 10 | 11 | public AdvancedBanExtensionBukkit(BanAnnouncerBukkit plugin) { 12 | this.listener = new AdvancedBanListenerBukkit(plugin); 13 | } 14 | 15 | @Override 16 | public PunishmentListener getPunishmentListener() { 17 | return listener; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/me/tini/announcer/extension/impl/advancedban/AdvancedBanExtensionBungee.java: -------------------------------------------------------------------------------- 1 | package me.tini.announcer.extension.impl.advancedban; 2 | 3 | import me.tini.announcer.PunishmentListener; 4 | import me.tini.announcer.extension.AbstractExtension; 5 | import me.tini.announcer.plugin.bungee.BanAnnouncerBungee; 6 | 7 | public class AdvancedBanExtensionBungee extends AbstractExtension { 8 | 9 | private PunishmentListener listener; 10 | 11 | public AdvancedBanExtensionBungee(BanAnnouncerBungee plugin) { 12 | this.listener = new AdvancedBanListenerBungee(plugin); 13 | } 14 | 15 | @Override 16 | public PunishmentListener getPunishmentListener() { 17 | return listener; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/me/tini/announcer/extension/impl/advancedban/AdvancedBanListenerBukkit.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 OopsieWoopsie 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU Affero General Public License as 6 | * published by the Free Software Foundation, either version 3 of the 7 | * License, or (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU Affero General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU Affero General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package me.tini.announcer.extension.impl.advancedban; 19 | 20 | import org.bukkit.event.EventHandler; 21 | 22 | import me.leoko.advancedban.bukkit.event.PunishmentEvent; 23 | import me.leoko.advancedban.bukkit.event.RevokePunishmentEvent; 24 | import me.tini.announcer.PunishmentInfo; 25 | import me.tini.announcer.plugin.bukkit.BanAnnouncerBukkit; 26 | import me.tini.announcer.plugin.bukkit.BukkitPunishmentListener; 27 | 28 | public final class AdvancedBanListenerBukkit extends BukkitPunishmentListener { 29 | 30 | public AdvancedBanListenerBukkit(BanAnnouncerBukkit plugin) { 31 | super(plugin); 32 | } 33 | 34 | @EventHandler 35 | public void onPunishment(PunishmentEvent event) { 36 | PunishmentInfo punishment = AdvancedBanUtil.convertPunishment(getAnnouncer().getConfig(), event.getPunishment(), false); 37 | handlePunishment(punishment); 38 | } 39 | 40 | @EventHandler 41 | public void onRevokePunishment(RevokePunishmentEvent event) { 42 | PunishmentInfo punishment = AdvancedBanUtil.convertPunishment(getAnnouncer().getConfig(), event.getPunishment(), true); 43 | handlePunishment(punishment); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/main/java/me/tini/announcer/extension/impl/advancedban/AdvancedBanListenerBungee.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 OopsieWoopsie 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU Affero General Public License as 6 | * published by the Free Software Foundation, either version 3 of the 7 | * License, or (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU Affero General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU Affero General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package me.tini.announcer.extension.impl.advancedban; 19 | 20 | import me.leoko.advancedban.bungee.event.PunishmentEvent; 21 | import me.leoko.advancedban.bungee.event.RevokePunishmentEvent; 22 | import me.tini.announcer.PunishmentInfo; 23 | import me.tini.announcer.plugin.bungee.BanAnnouncerBungee; 24 | import me.tini.announcer.plugin.bungee.BungeePunishmentListener; 25 | import net.md_5.bungee.event.EventHandler; 26 | 27 | public final class AdvancedBanListenerBungee extends BungeePunishmentListener { 28 | 29 | public AdvancedBanListenerBungee(BanAnnouncerBungee plugin) { 30 | super(plugin); 31 | } 32 | 33 | @EventHandler 34 | public void onPunishment(PunishmentEvent event) { 35 | PunishmentInfo punishment = AdvancedBanUtil.convertPunishment(getAnnouncer().getConfig(), event.getPunishment(), false); 36 | handlePunishment(punishment); 37 | } 38 | 39 | @EventHandler 40 | public void onRevokePunishment(RevokePunishmentEvent event) { 41 | PunishmentInfo punishment = AdvancedBanUtil.convertPunishment(getAnnouncer().getConfig(), event.getPunishment(), true); 42 | handlePunishment(punishment); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/main/java/me/tini/announcer/extension/impl/advancedban/AdvancedBanUtil.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2020 OopsieWoopsie 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU Affero General Public License as 6 | * published by the Free Software Foundation, either version 3 of the 7 | * License, or (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU Affero General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU Affero General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package me.tini.announcer.extension.impl.advancedban; 19 | 20 | import java.math.BigInteger; 21 | import java.util.UUID; 22 | 23 | import me.leoko.advancedban.utils.Punishment; 24 | import me.leoko.advancedban.utils.PunishmentType; 25 | import me.tini.announcer.PunishmentInfo; 26 | import me.tini.announcer.PunishmentInfo.Type; 27 | import me.tini.announcer.config.Config; 28 | 29 | public final class AdvancedBanUtil { 30 | 31 | public static PunishmentInfo convertPunishment(Config config, final Punishment pun, final boolean revoked) { 32 | PunishmentInfo punishment = new PunishmentInfo(); 33 | 34 | String operator = "Console".equalsIgnoreCase(pun.getOperator()) 35 | ? config.getConsoleName() 36 | : pun.getOperator(); 37 | 38 | punishment.setId(String.valueOf(pun.getId())); 39 | punishment.setOperator(operator); 40 | punishment.setPlayer(pun.getName()); 41 | 42 | if (pun.getUuid() != null) { 43 | String uuidString = pun.getUuid(); 44 | 45 | if (uuidString.length() == 32) { 46 | uuidString = undashedToDashedId(uuidString).toString(); 47 | } 48 | 49 | if (uuidString.length() == 36) { 50 | punishment.setPlayerId(uuidString); 51 | } 52 | } 53 | 54 | if (revoked) { 55 | if (pun.isExpired()) { // automatic 56 | punishment.setOperator(config.getExpiredOperatorName()); 57 | } 58 | if (pun.getType() == PunishmentType.NOTE) { 59 | punishment.setReason(pun.getReason()); 60 | } 61 | } else { 62 | punishment.setReason(pun.getReason()); 63 | punishment.setDuration(pun.getDuration(true)); 64 | punishment.setPermanent(punishment.getDuration().equals("permanent")); 65 | } 66 | 67 | if (!punishment.isPermanent()) { 68 | punishment.setStart(pun.getStart()); 69 | punishment.setEnd(pun.getEnd()); 70 | } 71 | 72 | switch (pun.getType()) { 73 | case KICK: 74 | punishment.setType(Type.KICK); 75 | break; 76 | case BAN: 77 | punishment.setType(revoked ? Type.UNBAN : Type.BAN); 78 | break; 79 | case TEMP_BAN: 80 | punishment.setType(revoked ? Type.UNBAN : Type.TEMPBAN); 81 | break; 82 | case IP_BAN: 83 | punishment.setType(revoked ? Type.UNBANIP : Type.BANIP); 84 | break; 85 | case TEMP_IP_BAN: 86 | punishment.setType(revoked ? Type.UNBANIP : Type.TEMPBANIP); 87 | break; 88 | case MUTE: 89 | punishment.setType(revoked ? Type.UNMUTE : Type.MUTE); 90 | break; 91 | case TEMP_MUTE: 92 | punishment.setType(revoked ? Type.UNMUTE : Type.TEMPMUTE); 93 | break; 94 | case WARNING: 95 | punishment.setType(revoked ? Type.UNWARN : Type.WARN); 96 | break; 97 | case TEMP_WARNING: 98 | punishment.setType(revoked ? Type.UNWARN : Type.TEMPWARN); 99 | break; 100 | case NOTE: 101 | punishment.setType(revoked ? Type.UNNOTE : Type.NOTE); 102 | break; 103 | default: 104 | throw new IllegalStateException("Unknown punishment type '" + pun.getType() + "'."); 105 | } 106 | 107 | return punishment; 108 | } 109 | 110 | private static UUID undashedToDashedId(String undashedId) { 111 | return new UUID( 112 | new BigInteger(undashedId.substring(0, 16), 16).longValue(), 113 | new BigInteger(undashedId.substring(16), 16).longValue() 114 | ); 115 | } 116 | } 117 | -------------------------------------------------------------------------------- /src/main/java/me/tini/announcer/extension/impl/betterjails/BetterJailsExtension.java: -------------------------------------------------------------------------------- 1 | package me.tini.announcer.extension.impl.betterjails; 2 | 3 | import me.tini.announcer.PunishmentListener; 4 | import me.tini.announcer.extension.AbstractExtension; 5 | import me.tini.announcer.plugin.bukkit.BanAnnouncerBukkit; 6 | 7 | public class BetterJailsExtension extends AbstractExtension { 8 | 9 | private BetterJailsListener listener; 10 | 11 | public BetterJailsExtension(BanAnnouncerBukkit plugin) { 12 | this.listener = new BetterJailsListener(plugin); 13 | } 14 | 15 | @Override 16 | public PunishmentListener getPunishmentListener() { 17 | return listener; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/me/tini/announcer/extension/impl/betterjails/BetterJailsListener.java: -------------------------------------------------------------------------------- 1 | package me.tini.announcer.extension.impl.betterjails; 2 | 3 | import com.github.fefo.betterjails.api.BetterJails; 4 | import com.github.fefo.betterjails.api.event.prisoner.PlayerImprisonEvent; 5 | import com.github.fefo.betterjails.api.event.prisoner.PrisonerReleaseEvent; 6 | import com.github.fefo.betterjails.api.model.prisoner.Prisoner; 7 | 8 | import me.tini.announcer.PunishmentInfo; 9 | import me.tini.announcer.PunishmentInfo.Type; 10 | import me.tini.announcer.plugin.bukkit.BanAnnouncerBukkit; 11 | import me.tini.announcer.plugin.bukkit.BukkitPunishmentListener; 12 | 13 | public class BetterJailsListener extends BukkitPunishmentListener { 14 | 15 | private final BetterJails betterJails; 16 | 17 | public BetterJailsListener(BanAnnouncerBukkit plugin) { 18 | super(plugin); 19 | this.betterJails = plugin.getServer().getServicesManager().load(BetterJails.class); 20 | } 21 | 22 | @Override 23 | public void register() { 24 | betterJails.getEventBus().subscribe(getPlugin(), PlayerImprisonEvent.class, this::onPlayerImprison); 25 | betterJails.getEventBus().subscribe(getPlugin(), PrisonerReleaseEvent.class, this::onPrisonerRelease); 26 | } 27 | 28 | @Override 29 | public void unregister() { 30 | betterJails.getEventBus().unsubscribe(getPlugin()); 31 | } 32 | 33 | private void onPlayerImprison(PlayerImprisonEvent event) { 34 | handle(event.prisoner(), false); 35 | } 36 | 37 | private void onPrisonerRelease(PrisonerReleaseEvent event) { 38 | handle(event.prisoner(), true); 39 | } 40 | 41 | private void handle(Prisoner prisoner, boolean released) { 42 | String jail = prisoner.jail().name(); 43 | String player = prisoner.name(); 44 | String operator = prisoner.jailedBy(); 45 | 46 | PunishmentInfo punishment = new PunishmentInfo(released ? Type.UNJAIL : Type.JAIL); 47 | 48 | long durationMillis = prisoner.jailedUntil().toEpochMilli() - System.currentTimeMillis(); 49 | 50 | punishment.setJail(jail); 51 | punishment.setPlayer(player); 52 | punishment.setOperator(operator); 53 | punishment.setDuration(TimeUtils.parseMillis(durationMillis)); 54 | 55 | if (released && durationMillis <= 0) { 56 | punishment.setOperator(getPlugin().getAnnouncer().getConfig().getExpiredOperatorName()); 57 | } 58 | 59 | handlePunishment(punishment); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/main/java/me/tini/announcer/extension/impl/betterjails/TimeUtils.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 OopsieWoopsie 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU Affero General Public License as 6 | * published by the Free Software Foundation, either version 3 of the 7 | * License, or (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU Affero General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU Affero General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package me.tini.announcer.extension.impl.betterjails; 19 | 20 | import java.util.concurrent.TimeUnit; 21 | 22 | public class TimeUtils { 23 | 24 | private static final TimeUnit UNIT = TimeUnit.MILLISECONDS; 25 | 26 | private static final long SECOND = 1000; // millis 27 | private static final long MINUTE = SECOND * 60; 28 | private static final long HOUR = MINUTE * 60; 29 | private static final long DAY = HOUR * 24; 30 | // not every month has 30 days, and 365 / 12 = 30.4~ 31 | // so i will not do the month constant 32 | private static final long YEAR = DAY * 365; 33 | 34 | public static String parseMillis(long millis) { 35 | if (millis >= YEAR) { 36 | return UNIT.toDays(millis) / 365 + " year(s)"; 37 | } 38 | else if (millis >= DAY) { 39 | return UNIT.toDays(millis) + " day(s)"; 40 | } 41 | else if (millis >= HOUR) { 42 | return UNIT.toHours(millis) + " hour(s)"; 43 | } 44 | else if (millis >= MINUTE) { 45 | return UNIT.toMinutes(millis) + " minute(s)"; 46 | } 47 | else if (millis >= SECOND) { 48 | return UNIT.toSeconds(millis) + " second(s)"; 49 | } 50 | return "unknown"; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/main/java/me/tini/announcer/extension/impl/essentialsjail/EssentialsJailExtension.java: -------------------------------------------------------------------------------- 1 | package me.tini.announcer.extension.impl.essentialsjail; 2 | 3 | import me.tini.announcer.PunishmentListener; 4 | import me.tini.announcer.extension.AbstractExtension; 5 | import me.tini.announcer.plugin.bukkit.BanAnnouncerBukkit; 6 | 7 | public class EssentialsJailExtension extends AbstractExtension { 8 | 9 | private EssentialsJailListener listener; 10 | 11 | public EssentialsJailExtension(BanAnnouncerBukkit plugin) { 12 | this.listener = new EssentialsJailListener(plugin); 13 | } 14 | 15 | @Override 16 | public PunishmentListener getPunishmentListener() { 17 | return listener; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/me/tini/announcer/extension/impl/essentialsjail/EssentialsJailListener.java: -------------------------------------------------------------------------------- 1 | package me.tini.announcer.extension.impl.essentialsjail; 2 | 3 | import org.bukkit.event.EventHandler; 4 | 5 | import me.tini.announcer.PunishmentInfo; 6 | import me.tini.announcer.PunishmentInfo.Type; 7 | import me.tini.announcer.plugin.bukkit.BanAnnouncerBukkit; 8 | import me.tini.announcer.plugin.bukkit.BukkitPunishmentListener; 9 | import net.ess3.api.IUser; 10 | import net.ess3.api.events.JailStatusChangeEvent; 11 | 12 | public class EssentialsJailListener extends BukkitPunishmentListener { 13 | 14 | public EssentialsJailListener(BanAnnouncerBukkit plugin) { 15 | super(plugin); 16 | } 17 | 18 | @EventHandler 19 | @SuppressWarnings("deprecation") 20 | public void onJailStatusChange(JailStatusChangeEvent event) { 21 | boolean gotJailed = event.getValue(); 22 | 23 | IUser user = event.getAffected(); 24 | IUser staff = event.getController(); 25 | 26 | getPlugin().getServer().getScheduler().scheduleSyncDelayedTask(getPlugin(), () -> { 27 | PunishmentInfo punishment = new PunishmentInfo(); 28 | 29 | punishment.setType(gotJailed ? Type.JAIL : Type.UNJAIL); 30 | punishment.setJail(user.getJail()); 31 | punishment.setPlayer(user.getName()); 32 | punishment.setOperator(staff == null ? getAnnouncer().getConfig().getConsoleName() : staff.getName()); 33 | 34 | handlePunishment(punishment); 35 | }, 20); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/me/tini/announcer/extension/impl/libertybans/LibertyBansExtension.java: -------------------------------------------------------------------------------- 1 | package me.tini.announcer.extension.impl.libertybans; 2 | 3 | import me.tini.announcer.BanAnnouncerPlugin; 4 | import me.tini.announcer.PunishmentListener; 5 | import me.tini.announcer.extension.AbstractExtension; 6 | 7 | public class LibertyBansExtension extends AbstractExtension { 8 | 9 | private LibertyBansListener listener; 10 | 11 | public LibertyBansExtension(BanAnnouncerPlugin plugin) { 12 | this.listener = new LibertyBansListener(plugin); 13 | } 14 | 15 | @Override 16 | public PunishmentListener getPunishmentListener() { 17 | return listener; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/me/tini/announcer/extension/impl/libertybans/LibertyBansListener.java: -------------------------------------------------------------------------------- 1 | package me.tini.announcer.extension.impl.libertybans; 2 | 3 | import java.time.Duration; 4 | import java.util.Optional; 5 | import java.util.UUID; 6 | import java.util.concurrent.ExecutionException; 7 | 8 | import me.tini.announcer.BanAnnouncerPlugin; 9 | import me.tini.announcer.PunishmentInfo; 10 | import me.tini.announcer.PunishmentListener; 11 | import space.arim.libertybans.api.AddressVictim; 12 | import space.arim.libertybans.api.CompositeVictim; 13 | import space.arim.libertybans.api.LibertyBans; 14 | import space.arim.libertybans.api.Operator; 15 | import space.arim.libertybans.api.Operator.OperatorType; 16 | import space.arim.libertybans.api.PlayerOperator; 17 | import space.arim.libertybans.api.PlayerVictim; 18 | import space.arim.libertybans.api.Victim; 19 | import space.arim.libertybans.api.Victim.VictimType; 20 | import space.arim.libertybans.api.event.PostPardonEvent; 21 | import space.arim.libertybans.api.event.PostPunishEvent; 22 | import space.arim.libertybans.api.punish.Punishment; 23 | import space.arim.omnibus.Omnibus; 24 | import space.arim.omnibus.OmnibusProvider; 25 | import space.arim.omnibus.events.EventBus; 26 | import space.arim.omnibus.events.RegisteredListener; 27 | import space.arim.omnibus.util.concurrent.CentralisedFuture; 28 | 29 | public class LibertyBansListener extends PunishmentListener { 30 | 31 | private final LibertyBans libertyBans = findLibertyBansInstance(); 32 | private final EventBus eventBus; 33 | 34 | private RegisteredListener postPunishListenerMarker; 35 | private RegisteredListener postPardonListenerMarker; 36 | 37 | public LibertyBansListener(BanAnnouncerPlugin plugin) { 38 | super(plugin.getAnnouncer()); 39 | eventBus = libertyBans.getOmnibus().getEventBus(); 40 | } 41 | 42 | @Override 43 | public void register() { 44 | if (isRegistered()) { 45 | throw new IllegalStateException("call unregister() first"); 46 | } 47 | postPunishListenerMarker = eventBus.registerListener(PostPunishEvent.class, (byte) 0, this::onPostPunishEvent); 48 | postPardonListenerMarker = eventBus.registerListener(PostPardonEvent.class, (byte) 0, this::onPostPardonEvent); 49 | } 50 | 51 | @Override 52 | public void unregister() { 53 | if (isRegistered()) { 54 | eventBus.unregisterListener(postPunishListenerMarker); 55 | eventBus.unregisterListener(postPardonListenerMarker); 56 | } 57 | postPunishListenerMarker = null; 58 | postPardonListenerMarker = null; 59 | } 60 | 61 | private boolean isRegistered() { 62 | return postPunishListenerMarker != null || postPardonListenerMarker != null; 63 | } 64 | 65 | private void onPostPunishEvent(PostPunishEvent event) { 66 | handle(event.getPunishment().getOperator(), event.getPunishment(), false); 67 | } 68 | 69 | private void onPostPardonEvent(PostPardonEvent event) { 70 | handle(event.getOperator(), event.getPunishment(), true); 71 | } 72 | 73 | private void handle(Operator operator, Punishment pun, boolean isRevoked) { 74 | PunishmentInfo punishment = new PunishmentInfo(); 75 | 76 | boolean isConsole = operator.getType() == OperatorType.CONSOLE; 77 | 78 | String operatorName = isConsole 79 | ? getAnnouncer().getConfig().getConsoleName() 80 | : getOperatorName(operator); 81 | 82 | punishment.setId(Long.toString(pun.getIdentifier())); 83 | 84 | if (isRevoked && pun.isExpired()) { 85 | punishment.setOperator(getAnnouncer().getConfig().getExpiredOperatorName()); 86 | } else { 87 | punishment.setOperator(operatorName); 88 | punishment.setReason(pun.getReason()); 89 | punishment.setPermanent(pun.isPermanent()); 90 | 91 | if (punishment.isPermanent()) { 92 | punishment.setDuration("permanent"); 93 | } else { 94 | punishment.setDuration(libertyBans.getFormatter().formatDuration(Duration.ofSeconds(pun.getEndDateSeconds() - pun.getStartDateSeconds()))); 95 | } 96 | } 97 | 98 | punishment.setPlayer(getVictimName(pun.getVictim())); 99 | 100 | punishment.setPlayerId(getVictimId(pun.getVictim())); 101 | 102 | switch (pun.getType()) { 103 | case BAN: 104 | boolean isBanIP = pun.getVictim().getType() == VictimType.ADDRESS; 105 | 106 | if (isBanIP) { 107 | if (isRevoked) { 108 | punishment.setType(PunishmentInfo.Type.UNBANIP); 109 | } else { 110 | punishment.setType(punishment.isPermanent() ? PunishmentInfo.Type.BANIP : PunishmentInfo.Type.TEMPBANIP); 111 | } 112 | } else { 113 | if (isRevoked) { 114 | punishment.setType(PunishmentInfo.Type.UNBAN); 115 | } else { 116 | punishment.setType(punishment.isPermanent() ? PunishmentInfo.Type.BAN : PunishmentInfo.Type.TEMPBAN); 117 | } 118 | } 119 | 120 | break; 121 | case KICK: 122 | punishment.setType(PunishmentInfo.Type.KICK); 123 | break; 124 | case MUTE: 125 | if (isRevoked) { 126 | punishment.setType(PunishmentInfo.Type.UNMUTE); 127 | } else { 128 | punishment.setType(punishment.isPermanent() ? PunishmentInfo.Type.MUTE : PunishmentInfo.Type.TEMPMUTE); 129 | } 130 | break; 131 | case WARN: 132 | if (isRevoked) { 133 | punishment.setType(PunishmentInfo.Type.UNWARN); 134 | } else { 135 | punishment.setType(punishment.isPermanent() ? PunishmentInfo.Type.WARN : PunishmentInfo.Type.TEMPWARN); 136 | } 137 | break; 138 | default: 139 | break; 140 | } 141 | 142 | if (!punishment.isPermanent()) { 143 | punishment.setStart(pun.getStartDateSeconds() * 1000); 144 | punishment.setEnd(pun.getEndDateSeconds() * 1000); 145 | } 146 | 147 | handlePunishment(punishment); 148 | } 149 | 150 | private String getVictimName(Victim victim) { 151 | if (victim.getType() == VictimType.PLAYER) { 152 | return getPlayerName(((PlayerVictim) victim).getUUID()); 153 | } 154 | if (victim.getType() == VictimType.ADDRESS) { 155 | return ((AddressVictim) victim).getAddress().toInetAddress().getHostAddress(); 156 | } 157 | if (victim.getType() == VictimType.COMPOSITE) { 158 | return getPlayerName(((CompositeVictim) victim).getUUID()); 159 | } 160 | return ""; 161 | } 162 | 163 | private String getVictimId(Victim victim) { 164 | if (victim.getType() == VictimType.PLAYER) { 165 | return ((PlayerVictim) victim).getUUID().toString(); 166 | } 167 | if (victim.getType() == VictimType.COMPOSITE) { 168 | return ((CompositeVictim) victim).getUUID().toString(); 169 | } 170 | return new UUID(0, 0).toString(); 171 | } 172 | 173 | private String getOperatorName(Operator operator) { 174 | return (operator.getType() == OperatorType.CONSOLE) 175 | ? getAnnouncer().getConfig().getConsoleName() 176 | : getPlayerName(((PlayerOperator) operator).getUUID()); 177 | } 178 | 179 | private String getPlayerName(UUID uuid) { 180 | CentralisedFuture> lookup = libertyBans.getUserResolver().lookupName(uuid); 181 | 182 | try { 183 | Optional optional = lookup.get(); 184 | if (optional.isPresent()) { 185 | return optional.get(); 186 | } 187 | } catch (InterruptedException | ExecutionException e) { 188 | e.printStackTrace(); 189 | } 190 | 191 | return ""; 192 | } 193 | 194 | private static LibertyBans findLibertyBansInstance() { 195 | Omnibus omnibus = OmnibusProvider.getOmnibus(); 196 | Optional instance = omnibus.getRegistry().getProvider(LibertyBans.class); 197 | if (!instance.isPresent()) { 198 | throw new IllegalStateException("LibertyBans not found"); 199 | } 200 | return instance.get(); 201 | } 202 | } 203 | -------------------------------------------------------------------------------- /src/main/java/me/tini/announcer/extension/impl/litebans/LiteBansExtension.java: -------------------------------------------------------------------------------- 1 | package me.tini.announcer.extension.impl.litebans; 2 | 3 | import me.tini.announcer.BanAnnouncerPlugin; 4 | import me.tini.announcer.PunishmentListener; 5 | import me.tini.announcer.extension.AbstractExtension; 6 | 7 | public final class LiteBansExtension extends AbstractExtension { 8 | 9 | private LiteBansListener listener; 10 | 11 | public LiteBansExtension(BanAnnouncerPlugin plugin) { 12 | this.listener = new LiteBansListener(plugin); 13 | } 14 | 15 | @Override 16 | public PunishmentListener getPunishmentListener() { 17 | return listener; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/me/tini/announcer/extension/impl/litebans/LiteBansListener.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2020 OopsieWoopsie 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU Affero General Public License as 6 | * published by the Free Software Foundation, either version 3 of the 7 | * License, or (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU Affero General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU Affero General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package me.tini.announcer.extension.impl.litebans; 19 | 20 | import java.sql.PreparedStatement; 21 | import java.sql.ResultSet; 22 | import java.sql.SQLException; 23 | 24 | import litebans.api.Database; 25 | import litebans.api.Entry; 26 | import litebans.api.Events; 27 | import litebans.api.Events.Listener; 28 | import me.tini.announcer.BanAnnouncerPlugin; 29 | import me.tini.announcer.PunishmentInfo; 30 | import me.tini.announcer.PunishmentListener; 31 | import me.tini.announcer.PunishmentInfo.Type; 32 | 33 | public final class LiteBansListener extends PunishmentListener { 34 | 35 | private final Events events; 36 | private final Database database; 37 | private final InternalListener theListener; 38 | 39 | public LiteBansListener(BanAnnouncerPlugin plugin) { 40 | super(plugin.getAnnouncer()); 41 | this.events = Events.get(); 42 | this.database = Database.get(); 43 | this.theListener = new InternalListener(); 44 | } 45 | 46 | @Override 47 | public void register() { 48 | events.register(theListener); 49 | } 50 | 51 | @Override 52 | public void unregister() { 53 | events.unregister(theListener); 54 | } 55 | 56 | public void handleEntry(final Entry entry, final boolean revoked) { 57 | final PunishmentInfo punishment = new PunishmentInfo(); 58 | 59 | punishment.setId(String.valueOf(entry.getId())); 60 | 61 | switch (entry.getType()) { 62 | case "ban": 63 | if (entry.isIpban()) { 64 | punishment.setType(revoked ? Type.UNBANIP : entry.isPermanent() ? Type.BANIP : Type.TEMPBANIP); 65 | } else { 66 | punishment.setType(revoked ? Type.UNBAN : entry.isPermanent() ? Type.BAN : Type.TEMPBAN); 67 | } 68 | break; 69 | case "mute": 70 | punishment.setType(revoked ? Type.UNMUTE : entry.isPermanent() ? Type.MUTE : Type.TEMPMUTE); 71 | break; 72 | case "warn": 73 | punishment.setType(revoked ? Type.UNWARN : entry.isPermanent() ? Type.WARN : Type.TEMPWARN); 74 | break; 75 | case "kick": 76 | punishment.setType(Type.KICK); 77 | break; 78 | default: 79 | throw new IllegalStateException("Unknown punishment type '" + entry.getType() + "'."); 80 | } 81 | 82 | final String uuidDashed = entry.getUuid(); 83 | 84 | punishment.setPlayerId(uuidDashed); 85 | 86 | final String name = getPlayerName(uuidDashed); 87 | 88 | if (name == null) { 89 | throw new IllegalStateException("Couldn't fetch player name from UUID '" + entry.getUuid() + "'. The message was not sent."); 90 | } 91 | 92 | boolean isConsole = entry.getExecutorName() == null 93 | || "Console".equalsIgnoreCase(entry.getExecutorName()); 94 | 95 | String operator = isConsole 96 | ? getAnnouncer().getConfig().getConsoleName() 97 | : entry.getExecutorName(); 98 | 99 | punishment.setPlayer(name); 100 | punishment.setOperator(operator); 101 | 102 | if (revoked) { 103 | if (!entry.isPermanent() && entry.isExpired(System.currentTimeMillis())) { 104 | // automatic 105 | punishment.setOperator(getAnnouncer().getConfig().getExpiredOperatorName()); 106 | } 107 | } else { 108 | punishment.setPermanent(entry.isPermanent()); 109 | punishment.setDuration(entry.getDurationString()); 110 | } 111 | 112 | punishment.setReason(entry.getReason()); 113 | 114 | if (!punishment.isPermanent()) { 115 | punishment.setStart(entry.getDateStart()); 116 | punishment.setEnd(entry.getDateEnd()); 117 | } 118 | 119 | punishment.setLitebansServerOrigin(entry.getServerOrigin()); 120 | punishment.setLitebansServerScope(entry.getServerScope()); 121 | punishment.setLitebansRandomId(entry.getRandomID()); 122 | punishment.setLitebansRemovalReason(entry.getRemovalReason()); 123 | punishment.setLitebansRemovedByName(entry.getRemovedByName()); 124 | 125 | handlePunishment(punishment); 126 | } 127 | 128 | private String getPlayerName(final String uuid) { 129 | final String sentence = "SELECT name FROM {history} WHERE uuid = ? ORDER BY id DESC LIMIT 1"; 130 | 131 | try (final PreparedStatement stmt = database.prepareStatement(sentence)) { 132 | stmt.setString(1, uuid); 133 | 134 | final ResultSet rs = stmt.executeQuery(); 135 | 136 | if (rs.next()) 137 | return rs.getString(1); 138 | } catch (SQLException e) { 139 | e.printStackTrace(); 140 | } 141 | 142 | return null; 143 | } 144 | 145 | private class InternalListener extends Listener { 146 | 147 | @Override 148 | public void entryAdded(final Entry entry) { 149 | if (!entry.isActive() && !entry.getType().equals("kick")) 150 | return; 151 | 152 | if (entry.isSilent() && getAnnouncer().getConfig().isIgnoreSilent()) 153 | return; 154 | 155 | handleEntry(entry, false); 156 | } 157 | 158 | @Override 159 | public void entryRemoved(final Entry entry) { 160 | if (entry.getType().equals("kick")) 161 | return; 162 | 163 | if (entry.isSilent() && getAnnouncer().getConfig().isIgnoreSilent()) 164 | return; 165 | 166 | handleEntry(entry, true); 167 | } 168 | } 169 | } 170 | -------------------------------------------------------------------------------- /src/main/java/me/tini/announcer/extension/impl/maxbans/MaxBansExtension.java: -------------------------------------------------------------------------------- 1 | package me.tini.announcer.extension.impl.maxbans; 2 | 3 | import me.tini.announcer.PunishmentListener; 4 | import me.tini.announcer.extension.AbstractExtension; 5 | import me.tini.announcer.plugin.bukkit.BanAnnouncerBukkit; 6 | 7 | public class MaxBansExtension extends AbstractExtension { 8 | 9 | private MaxBansListener listener; 10 | 11 | public MaxBansExtension(BanAnnouncerBukkit plugin) { 12 | this.listener = new MaxBansListener(plugin); 13 | } 14 | 15 | @Override 16 | public PunishmentListener getPunishmentListener() { 17 | return listener; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/me/tini/announcer/extension/impl/maxbans/MaxBansListener.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 OopsieWoopsie 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU Affero General Public License as 6 | * published by the Free Software Foundation, either version 3 of the 7 | * License, or (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU Affero General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU Affero General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package me.tini.announcer.extension.impl.maxbans; 19 | 20 | import java.time.Duration; 21 | 22 | import org.bukkit.event.EventHandler; 23 | import org.maxgamer.maxbans.event.BanAddressEvent; 24 | import org.maxgamer.maxbans.event.BanUserEvent; 25 | import org.maxgamer.maxbans.event.KickUserEvent; 26 | import org.maxgamer.maxbans.event.MaxBansRestrictEvent; 27 | import org.maxgamer.maxbans.event.MuteAddressEvent; 28 | import org.maxgamer.maxbans.event.MuteUserEvent; 29 | import org.maxgamer.maxbans.event.UnbanAddressEvent; 30 | import org.maxgamer.maxbans.event.UnbanUserEvent; 31 | import org.maxgamer.maxbans.event.UnmuteAddressEvent; 32 | import org.maxgamer.maxbans.event.UnmuteUserEvent; 33 | import org.maxgamer.maxbans.event.WarnUserEvent; 34 | import org.maxgamer.maxbans.orm.Restriction; 35 | import org.maxgamer.maxbans.util.TemporalDuration; 36 | 37 | import me.tini.announcer.PunishmentInfo; 38 | import me.tini.announcer.PunishmentInfo.Type; 39 | import me.tini.announcer.plugin.bukkit.BanAnnouncerBukkit; 40 | import me.tini.announcer.plugin.bukkit.BukkitPunishmentListener; 41 | 42 | public class MaxBansListener extends BukkitPunishmentListener { 43 | 44 | public MaxBansListener(BanAnnouncerBukkit plugin) { 45 | super(plugin); 46 | } 47 | 48 | @EventHandler 49 | public void onBanAddress(BanAddressEvent event) { 50 | handleRestriction(event, event.getBan(), Type.BANIP, Type.TEMPBANIP); 51 | } 52 | 53 | @EventHandler 54 | public void onBanUser(BanUserEvent event) { 55 | handleRestriction(event, event.getBan(), Type.BAN, Type.TEMPBAN); 56 | } 57 | 58 | @EventHandler 59 | public void onKickUser(KickUserEvent event) { 60 | final PunishmentInfo punishment = new PunishmentInfo(Type.KICK); 61 | final String staff = event.getSource().getName(); 62 | final String player = event.getTarget().getName(); 63 | 64 | punishment.setReason("unknown"); 65 | punishment.setOperator(staff); 66 | punishment.setPlayer(player); 67 | 68 | handlePunishment(punishment); 69 | } 70 | 71 | @EventHandler 72 | public void onMuteAddress(MuteAddressEvent event) {} // unused 73 | 74 | @EventHandler 75 | public void onMuteUser(MuteUserEvent event) { 76 | handleRestriction(event, event.getMute(), Type.MUTE, Type.TEMPMUTE); 77 | } 78 | 79 | @EventHandler 80 | public void onUnbanAddress(UnbanAddressEvent event) { 81 | handleRevokedRestriction(event, Type.UNBANIP); 82 | } 83 | 84 | @EventHandler 85 | public void onUnbanUser(UnbanUserEvent event) { 86 | handleRevokedRestriction(event, Type.UNBAN); 87 | } 88 | 89 | @EventHandler 90 | public void onUnmuteAddress(UnmuteAddressEvent event) {} // unused 91 | 92 | @EventHandler 93 | public void onUnmuteUser(UnmuteUserEvent event) { 94 | handleRevokedRestriction(event, Type.UNMUTE); 95 | } 96 | 97 | @EventHandler 98 | public void onWarnUser(WarnUserEvent event) { 99 | handleRestriction(event, event.getWarning(), Type.WARN, Type.TEMPWARN); 100 | } 101 | 102 | // missing UnwarnUserEvent 103 | 104 | private void handleRestriction(MaxBansRestrictEvent event, Restriction restriction, Type perm, Type temp) { 105 | final PunishmentInfo punishment = new PunishmentInfo(); 106 | 107 | punishment.setPlayer(event.getTarget().getName()); 108 | punishment.setOperator(event.isPlayerAdministered() ? event.getAdmin().getName() : "Console"); 109 | punishment.setPermanent(restriction.getExpiresAt() == null); 110 | punishment.setType(punishment.isPermanent() ? perm : temp); 111 | punishment.setReason(restriction.getReason()); 112 | punishment.setDuration(getDuration(restriction)); 113 | 114 | handlePunishment(punishment); 115 | } 116 | 117 | private void handleRevokedRestriction(MaxBansRestrictEvent event, Type type) { 118 | final PunishmentInfo punishment = new PunishmentInfo(type); 119 | 120 | punishment.setPlayer(event.getTarget().getName()); 121 | punishment.setOperator(event.isPlayerAdministered() ? event.getAdmin().getName() : "Console"); 122 | 123 | handlePunishment(punishment); 124 | } 125 | 126 | private String getDuration(Restriction restriction) { 127 | if (restriction.getExpiresAt() == null) return "permanent"; 128 | long millis = (restriction.getExpiresAt().getEpochSecond() - restriction.getCreated().getEpochSecond()) * 1000; 129 | return new TemporalDuration(Duration.ofMillis(millis)).toString(); 130 | } 131 | } 132 | -------------------------------------------------------------------------------- /src/main/java/me/tini/announcer/extension/impl/spongevanilla/SpongeVanillaExtension.java: -------------------------------------------------------------------------------- 1 | package me.tini.announcer.extension.impl.spongevanilla; 2 | 3 | import me.tini.announcer.PunishmentListener; 4 | import me.tini.announcer.extension.AbstractExtension; 5 | import me.tini.announcer.plugin.sponge.BanAnnouncerSponge; 6 | 7 | public class SpongeVanillaExtension extends AbstractExtension { 8 | 9 | private SpongeVanillaListener listener; 10 | 11 | public SpongeVanillaExtension(BanAnnouncerSponge plugin) { 12 | this.listener = new SpongeVanillaListener(plugin); 13 | } 14 | 15 | @Override 16 | public PunishmentListener getPunishmentListener() { 17 | return listener; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/me/tini/announcer/extension/impl/spongevanilla/SpongeVanillaListener.java: -------------------------------------------------------------------------------- 1 | package me.tini.announcer.extension.impl.spongevanilla; 2 | 3 | import java.net.Inet4Address; 4 | import java.net.Inet6Address; 5 | import java.net.InetAddress; 6 | import java.util.Optional; 7 | 8 | import org.spongepowered.api.entity.living.player.Player; 9 | import org.spongepowered.api.entity.living.player.User; 10 | import org.spongepowered.api.event.Listener; 11 | import org.spongepowered.api.event.entity.living.player.KickPlayerEvent; 12 | import org.spongepowered.api.event.network.BanIpEvent; 13 | import org.spongepowered.api.event.network.PardonIpEvent; 14 | import org.spongepowered.api.event.user.BanUserEvent; 15 | import org.spongepowered.api.event.user.PardonUserEvent; 16 | 17 | import me.tini.announcer.PunishmentInfo; 18 | import me.tini.announcer.PunishmentInfo.Type; 19 | import me.tini.announcer.plugin.sponge.BanAnnouncerSponge; 20 | import me.tini.announcer.plugin.sponge.SpongePunishmentListener; 21 | import net.kyori.adventure.text.Component; 22 | import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer; 23 | 24 | public class SpongeVanillaListener extends SpongePunishmentListener { 25 | 26 | public SpongeVanillaListener(BanAnnouncerSponge plugin) { 27 | super(plugin); 28 | } 29 | 30 | @Listener 31 | public void onKickPlayer(KickPlayerEvent event) { 32 | Player player = event.player(); 33 | Component messageComponent = event.message(); 34 | 35 | PunishmentInfo pun = new PunishmentInfo(Type.KICK); 36 | 37 | pun.setPlayer(player.name()); 38 | pun.setPlayerId(player.uniqueId().toString()); 39 | 40 | Optional operator = event.cause().first(Player.class); 41 | 42 | if (operator.isPresent()) { 43 | pun.setOperator(operator.get().name()); 44 | } else { 45 | pun.setOperator("Console"); 46 | } 47 | 48 | if (messageComponent != null) { 49 | String reason = PlainTextComponentSerializer.plainText().serialize(messageComponent); 50 | 51 | pun.setReason(reason); 52 | } 53 | 54 | super.handlePunishment(pun); 55 | } 56 | 57 | @Listener 58 | public void onBanUser(BanUserEvent event) { 59 | User player = event.user(); 60 | 61 | PunishmentInfo pun = new PunishmentInfo(Type.BAN); 62 | 63 | pun.setPlayer(player.name()); 64 | pun.setPlayerId(player.uniqueId().toString()); 65 | 66 | Optional operator = event.cause().first(Player.class); 67 | 68 | if (operator.isPresent()) { 69 | pun.setOperator(operator.get().name()); 70 | } else { 71 | pun.setOperator("Console"); 72 | } 73 | 74 | pun.setPermanent(true); 75 | 76 | super.handlePunishment(pun); 77 | } 78 | 79 | @Listener 80 | public void onBanUser(PardonUserEvent event) { 81 | User player = event.user(); 82 | 83 | PunishmentInfo pun = new PunishmentInfo(Type.UNBAN); 84 | 85 | pun.setPlayer(player.name()); 86 | pun.setPlayerId(player.uniqueId().toString()); 87 | 88 | Optional operator = event.cause().first(Player.class); 89 | 90 | if (operator.isPresent()) { 91 | pun.setOperator(operator.get().name()); 92 | } else { 93 | pun.setOperator("Console"); 94 | } 95 | 96 | super.handlePunishment(pun); 97 | } 98 | 99 | @Listener 100 | public void onBanIp(BanIpEvent event) { 101 | InetAddress address = event.ban().address(); 102 | 103 | PunishmentInfo pun = new PunishmentInfo(Type.BANIP); 104 | 105 | pun.setPlayer(censorIp(address)); 106 | 107 | Optional operator = event.cause().first(Player.class); 108 | 109 | if (operator.isPresent()) { 110 | pun.setOperator(operator.get().name()); 111 | } else { 112 | pun.setOperator("Console"); 113 | } 114 | 115 | pun.setPermanent(true); 116 | 117 | super.handlePunishment(pun); 118 | } 119 | 120 | @Listener 121 | public void onPardonIp(PardonIpEvent event) { 122 | InetAddress address = event.ban().address(); 123 | 124 | PunishmentInfo pun = new PunishmentInfo(Type.UNBANIP); 125 | 126 | pun.setPlayer(censorIp(address)); 127 | 128 | Optional operator = event.cause().first(Player.class); 129 | 130 | if (operator.isPresent()) { 131 | pun.setOperator(operator.get().name()); 132 | } else { 133 | pun.setOperator("Console"); 134 | } 135 | 136 | super.handlePunishment(pun); 137 | } 138 | 139 | private static String censorIp(InetAddress address) { 140 | String ip = address.getHostAddress(); 141 | 142 | if (address instanceof Inet4Address) { 143 | return ip.substring(0, ip.lastIndexOf('.') + 1) + "***"; 144 | } 145 | if (address instanceof Inet6Address) { 146 | return ip.substring(0, ip.length() - 3) + "***"; 147 | } 148 | 149 | return ip; // :shrug: 150 | } 151 | } 152 | -------------------------------------------------------------------------------- /src/main/java/me/tini/announcer/plugin/bukkit/BanAnnouncerBukkit.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 OopsieWoopsie 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU Affero General Public License as 6 | * published by the Free Software Foundation, either version 3 of the 7 | * License, or (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU Affero General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU Affero General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package me.tini.announcer.plugin.bukkit; 19 | 20 | import java.io.File; 21 | 22 | import org.bukkit.plugin.java.JavaPlugin; 23 | import org.spicord.Spicord; 24 | import org.spicord.SpicordLoader; 25 | 26 | import me.tini.announcer.BanAnnouncer; 27 | import me.tini.announcer.BanAnnouncerPlugin; 28 | import me.tini.announcer.ReloadCommand; 29 | import me.tini.announcer.addon.BanAnnouncerAddon; 30 | import me.tini.announcer.config.Config; 31 | import me.tini.announcer.extension.impl.advancedban.AdvancedBanExtensionBukkit; 32 | import me.tini.announcer.extension.impl.betterjails.BetterJailsExtension; 33 | import me.tini.announcer.extension.impl.essentialsjail.EssentialsJailExtension; 34 | import me.tini.announcer.extension.impl.libertybans.LibertyBansExtension; 35 | import me.tini.announcer.extension.impl.litebans.LiteBansExtension; 36 | import me.tini.announcer.extension.impl.maxbans.MaxBansExtension; 37 | 38 | public class BanAnnouncerBukkit extends JavaPlugin implements BanAnnouncerPlugin { 39 | 40 | private BanAnnouncer announcer; 41 | 42 | @Override 43 | public void onEnable() { 44 | SpicordLoader.addStartupListener(this::onSpicordLoad); 45 | } 46 | 47 | private void onSpicordLoad(Spicord spicord) { 48 | Config config = new Config(this); 49 | 50 | new ReloadCommand().register(this); 51 | 52 | announcer = new BanAnnouncer(config, spicord, this); 53 | 54 | announcer.loadExtensions(new File(getDataFolder(), "extensions")); 55 | 56 | announcer.registerExtension("AdvancedBan", "advancedban", () -> new AdvancedBanExtensionBukkit(this), "me.leoko.advancedban.Universal"); 57 | announcer.registerExtension("LiteBans" , "litebans" , () -> new LiteBansExtension(this) , "litebans.api.Events"); 58 | announcer.registerExtension("LibertyBans", "libertybans", () -> new LibertyBansExtension(this) , "space.arim.libertybans.api.LibertyBans"); 59 | announcer.registerExtension("MaxBansPlus", "maxbans" , () -> new MaxBansExtension(this) , "org.maxgamer.maxbans.MaxBansPlus"); 60 | announcer.registerExtension("BetterJails", "betterjails", () -> new BetterJailsExtension(this) , "com.github.fefo.betterjails.api.BetterJails"); 61 | announcer.registerExtension("EssentialsX", "essentials" , () -> new EssentialsJailExtension(this), "net.ess3.api.events.JailStatusChangeEvent"); 62 | 63 | announcer.enableExtensions(); 64 | 65 | spicord.getAddonManager().registerAddon(new BanAnnouncerAddon(this), this); 66 | } 67 | 68 | @Override 69 | public BanAnnouncer getAnnouncer() { 70 | return announcer; 71 | } 72 | 73 | @Override 74 | public File getFile() { 75 | return super.getFile(); 76 | } 77 | 78 | @Override 79 | public void onDisable() { 80 | if (announcer != null) { 81 | announcer.disable(); 82 | announcer = null; 83 | } 84 | } 85 | 86 | @Override 87 | public String getVersion() { 88 | return getDescription().getVersion(); 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /src/main/java/me/tini/announcer/plugin/bukkit/BukkitPunishmentListener.java: -------------------------------------------------------------------------------- 1 | package me.tini.announcer.plugin.bukkit; 2 | 3 | import org.bukkit.event.HandlerList; 4 | import org.bukkit.event.Listener; 5 | 6 | import me.tini.announcer.PunishmentListener; 7 | 8 | public class BukkitPunishmentListener extends PunishmentListener implements Listener { 9 | 10 | private final BanAnnouncerBukkit plugin; 11 | 12 | public BukkitPunishmentListener(BanAnnouncerBukkit plugin) { 13 | super(plugin.getAnnouncer()); 14 | this.plugin = plugin; 15 | } 16 | 17 | public BanAnnouncerBukkit getPlugin() { 18 | return plugin; 19 | } 20 | 21 | @Override 22 | public void register() { 23 | plugin.getServer().getPluginManager().registerEvents(this, plugin); 24 | } 25 | 26 | @Override 27 | public void unregister() { 28 | HandlerList.unregisterAll(this); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/me/tini/announcer/plugin/bungee/BanAnnouncerBungee.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 OopsieWoopsie 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU Affero General Public License as 6 | * published by the Free Software Foundation, either version 3 of the 7 | * License, or (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU Affero General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU Affero General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package me.tini.announcer.plugin.bungee; 19 | 20 | import java.io.File; 21 | 22 | import org.spicord.Spicord; 23 | import org.spicord.SpicordLoader; 24 | 25 | import me.tini.announcer.BanAnnouncer; 26 | import me.tini.announcer.BanAnnouncerPlugin; 27 | import me.tini.announcer.ReloadCommand; 28 | import me.tini.announcer.addon.BanAnnouncerAddon; 29 | import me.tini.announcer.config.Config; 30 | import me.tini.announcer.extension.impl.advancedban.AdvancedBanExtensionBungee; 31 | import me.tini.announcer.extension.impl.libertybans.LibertyBansExtension; 32 | import me.tini.announcer.extension.impl.litebans.LiteBansExtension; 33 | import net.md_5.bungee.api.plugin.Plugin; 34 | 35 | public final class BanAnnouncerBungee extends Plugin implements BanAnnouncerPlugin { 36 | 37 | private BanAnnouncer announcer; 38 | 39 | @Override 40 | public void onEnable() { 41 | SpicordLoader.addStartupListener(this::onSpicordLoad); 42 | } 43 | 44 | private void onSpicordLoad(Spicord spicord) { 45 | Config config = new Config(this); 46 | 47 | new ReloadCommand().register(this); 48 | 49 | announcer = new BanAnnouncer(config, spicord, this); 50 | 51 | announcer.loadExtensions(new File(getDataFolder(), "extensions")); 52 | 53 | announcer.registerExtension("AdvancedBan", "advancedban", () -> new AdvancedBanExtensionBungee(this), "me.leoko.advancedban.Universal"); 54 | announcer.registerExtension("LiteBans" , "litebans" , () -> new LiteBansExtension(this) , "litebans.api.Events"); 55 | announcer.registerExtension("LibertyBans", "libertybans", () -> new LibertyBansExtension(this), "space.arim.libertybans.api.LibertyBans"); 56 | 57 | announcer.enableExtensions(); 58 | 59 | spicord.getAddonManager().registerAddon(new BanAnnouncerAddon(this), this); 60 | } 61 | 62 | public BanAnnouncer getAnnouncer() { 63 | return announcer; 64 | } 65 | 66 | @Override 67 | public void onDisable() { 68 | if (announcer != null) { 69 | announcer.disable(); 70 | announcer = null; 71 | } 72 | } 73 | 74 | @Override 75 | public String getVersion() { 76 | return getDescription().getVersion(); 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /src/main/java/me/tini/announcer/plugin/bungee/BungeePunishmentListener.java: -------------------------------------------------------------------------------- 1 | package me.tini.announcer.plugin.bungee; 2 | 3 | import me.tini.announcer.PunishmentListener; 4 | import net.md_5.bungee.api.plugin.Listener; 5 | 6 | public class BungeePunishmentListener extends PunishmentListener implements Listener { 7 | 8 | private final BanAnnouncerBungee plugin; 9 | 10 | public BungeePunishmentListener(BanAnnouncerBungee plugin) { 11 | super(plugin.getAnnouncer()); 12 | this.plugin = plugin; 13 | } 14 | 15 | public BanAnnouncerBungee getPlugin() { 16 | return plugin; 17 | } 18 | 19 | @Override 20 | public void register() { 21 | plugin.getProxy().getPluginManager().registerListener(plugin, this); 22 | } 23 | 24 | @Override 25 | public void unregister() { 26 | plugin.getProxy().getPluginManager().unregisterListener(this); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/me/tini/announcer/plugin/sponge/BanAnnouncerSponge.java: -------------------------------------------------------------------------------- 1 | package me.tini.announcer.plugin.sponge; 2 | 3 | import java.io.File; 4 | import java.nio.file.Path; 5 | import java.util.logging.Logger; 6 | 7 | import org.apache.maven.artifact.versioning.ArtifactVersion; 8 | import org.spicord.Spicord; 9 | import org.spicord.SpicordLoader; 10 | import org.spicord.reflect.ReflectUtils; 11 | import org.spongepowered.api.Game; 12 | import org.spongepowered.api.config.ConfigDir; 13 | import org.spongepowered.plugin.PluginContainer; 14 | import org.spongepowered.plugin.builtin.jvm.Plugin; 15 | 16 | import com.google.inject.Inject; 17 | 18 | import me.tini.announcer.BanAnnouncer; 19 | import me.tini.announcer.BanAnnouncerPlugin; 20 | import me.tini.announcer.ReloadCommand; 21 | import me.tini.announcer.addon.BanAnnouncerAddon; 22 | import me.tini.announcer.config.Config; 23 | import me.tini.announcer.extension.impl.libertybans.LibertyBansExtension; 24 | import me.tini.announcer.extension.impl.spongevanilla.SpongeVanillaExtension; 25 | 26 | @Plugin("banannouncer") 27 | public class BanAnnouncerSponge implements BanAnnouncerPlugin { 28 | 29 | private final Path dataFolder; 30 | private final Game game; 31 | private final PluginContainer pluginContainer; 32 | 33 | private BanAnnouncer announcer; 34 | 35 | @Inject 36 | public BanAnnouncerSponge( 37 | @ConfigDir(sharedRoot = false) Path dataFolder, 38 | Game game, 39 | PluginContainer pluginContainer 40 | ) { 41 | this.dataFolder = dataFolder; 42 | this.game = game; 43 | this.pluginContainer = pluginContainer; 44 | } 45 | 46 | public Game getGame() { 47 | return game; 48 | } 49 | 50 | public PluginContainer getPluginContainer() { 51 | return pluginContainer; 52 | } 53 | 54 | public void onEnable() { 55 | SpicordLoader.addStartupListener(this::onSpicordLoad); 56 | } 57 | 58 | private void onSpicordLoad(Spicord spicord) { 59 | Config config = new Config(this); 60 | 61 | new ReloadCommand().register(this); 62 | 63 | announcer = new BanAnnouncer(config, spicord, this); 64 | 65 | announcer.loadExtensions(new File(getDataFolder(), "extensions")); 66 | 67 | announcer.registerExtension("LibertyBans", "libertybans", () -> new LibertyBansExtension(this) , "space.arim.libertybans.api.LibertyBans"); 68 | announcer.registerExtension("Sponge" , "sponge" , () -> new SpongeVanillaExtension(this), "org.spongepowered.api.Game"); 69 | 70 | announcer.enableExtensions(); 71 | 72 | spicord.getAddonManager().registerAddon(new BanAnnouncerAddon(this), this); 73 | } 74 | 75 | public void onDisable() { 76 | if (announcer != null) { 77 | announcer.disable(); 78 | announcer = null; 79 | } 80 | } 81 | 82 | @Override 83 | public BanAnnouncer getAnnouncer() { 84 | return announcer; 85 | } 86 | 87 | @Override 88 | public String getVersion() { 89 | ArtifactVersion version = pluginContainer.metadata().version(); 90 | 91 | return String.format( 92 | "%d.%d.%d", 93 | version.getMajorVersion(), 94 | version.getMinorVersion(), 95 | version.getIncrementalVersion() 96 | ); 97 | } 98 | 99 | @Override 100 | public File getFile() { 101 | return ReflectUtils.getJarFile(BanAnnouncerSponge.class); 102 | } 103 | 104 | @Override 105 | public Logger getLogger() { 106 | return Logger.getLogger("banannouncer"); 107 | } 108 | 109 | @Override 110 | public File getDataFolder() { 111 | return dataFolder.toFile(); 112 | } 113 | } 114 | -------------------------------------------------------------------------------- /src/main/java/me/tini/announcer/plugin/sponge/SpongePunishmentListener.java: -------------------------------------------------------------------------------- 1 | package me.tini.announcer.plugin.sponge; 2 | 3 | import me.tini.announcer.PunishmentListener; 4 | 5 | public class SpongePunishmentListener extends PunishmentListener { 6 | 7 | private final BanAnnouncerSponge plugin; 8 | 9 | public SpongePunishmentListener(BanAnnouncerSponge plugin) { 10 | super(plugin.getAnnouncer()); 11 | this.plugin = plugin; 12 | } 13 | 14 | public BanAnnouncerSponge getPlugin() { 15 | return plugin; 16 | } 17 | 18 | @Override 19 | public void register() { 20 | plugin.getGame().eventManager().registerListeners(plugin.getPluginContainer(), this); 21 | } 22 | 23 | @Override 24 | public void unregister() { 25 | plugin.getGame().eventManager().unregisterListeners(this); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/me/tini/announcer/plugin/velocity/BanAnnouncerVelocity.java: -------------------------------------------------------------------------------- 1 | package me.tini.announcer.plugin.velocity; 2 | 3 | import java.io.File; 4 | 5 | import org.spicord.Spicord; 6 | import org.spicord.SpicordLoader; 7 | import org.spicord.plugin.VelocityPlugin; 8 | import org.spicord.reflect.ReflectUtils; 9 | 10 | import com.google.inject.Inject; 11 | import com.velocitypowered.api.event.Subscribe; 12 | import com.velocitypowered.api.event.proxy.ProxyInitializeEvent; 13 | import com.velocitypowered.api.event.proxy.ProxyShutdownEvent; 14 | import com.velocitypowered.api.plugin.Dependency; 15 | import com.velocitypowered.api.plugin.Plugin; 16 | import com.velocitypowered.api.proxy.ProxyServer; 17 | 18 | import me.tini.announcer.BanAnnouncer; 19 | import me.tini.announcer.BanAnnouncerPlugin; 20 | import me.tini.announcer.ReloadCommand; 21 | import me.tini.announcer.addon.BanAnnouncerAddon; 22 | import me.tini.announcer.config.Config; 23 | import me.tini.announcer.extension.impl.libertybans.LibertyBansExtension; 24 | import me.tini.announcer.extension.impl.litebans.LiteBansExtension; 25 | 26 | @Plugin( 27 | id = "ban_announcer", 28 | name = "BanAnnouncer", 29 | version = "2.9.0", 30 | authors = { "Tini" }, 31 | dependencies = { 32 | @Dependency(id = "spicord", optional = false), 33 | @Dependency(id = "libertybans", optional = true), 34 | @Dependency(id = "litebans", optional = true) 35 | } 36 | ) 37 | public class BanAnnouncerVelocity extends VelocityPlugin implements BanAnnouncerPlugin { 38 | 39 | private BanAnnouncer announcer; 40 | private Config config; 41 | 42 | @Inject 43 | public BanAnnouncerVelocity(ProxyServer proxyServer) { 44 | super(proxyServer); 45 | } 46 | 47 | @Subscribe 48 | public void onProxyInitialize(ProxyInitializeEvent event) { 49 | SpicordLoader.addStartupListener(this::onSpicordLoad); 50 | } 51 | 52 | private void onSpicordLoad(Spicord spicord) { 53 | config = new Config(this); 54 | 55 | new ReloadCommand().register(this); 56 | 57 | announcer = new BanAnnouncer(config, spicord, this); 58 | 59 | announcer.loadExtensions(new File(getDataFolder(), "extensions")); 60 | 61 | announcer.registerExtension("LiteBans" , "litebans" , () -> new LiteBansExtension(this) , "litebans.api.Events"); 62 | announcer.registerExtension("LibertyBans", "libertybans", () -> new LibertyBansExtension(this), "space.arim.libertybans.api.LibertyBans"); 63 | 64 | announcer.enableExtensions(); 65 | 66 | spicord.getAddonManager().registerAddon(new BanAnnouncerAddon(this), this); 67 | } 68 | 69 | @Override 70 | public File getFile() { 71 | return ReflectUtils.getJarFile(BanAnnouncerVelocity.class); 72 | } 73 | 74 | @Override 75 | public BanAnnouncer getAnnouncer() { 76 | return announcer; 77 | } 78 | 79 | @Subscribe 80 | public void onShutdown(ProxyShutdownEvent event) { 81 | if (announcer != null) { 82 | announcer.disable(); 83 | announcer = null; 84 | } 85 | } 86 | 87 | @Override 88 | public String getVersion() { 89 | Plugin info = BanAnnouncerVelocity.class.getAnnotation(Plugin.class); 90 | if (info == null) { 91 | return "unknown"; 92 | } 93 | return info.version(); 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /src/main/resources/bungee.yml: -------------------------------------------------------------------------------- 1 | name: BanAnnouncer 2 | author: Tini 3 | main: me.tini.announcer.plugin.bungee.BanAnnouncerBungee 4 | version: ${project.version} 5 | depends: [Spicord] 6 | softdepends: [AdvancedBan, LiteBans] 7 | -------------------------------------------------------------------------------- /src/main/resources/config.yml: -------------------------------------------------------------------------------- 1 | # The channel id where the messages will be sent 2 | # If you don't know how to get a channel id... https://www.google.com/?q=discord+how+to+get+channel+id 3 | channel-to-announce: 123456789012345678 4 | 5 | # If the text is empty (nothing between the double quotes), 6 | # the message will not be sent (a.k.a. the message is "disabled"), for example: 7 | # 8 | # kick: "" <-- this will disable the message 9 | # 10 | # If you don't want to use embed messages you can use pure text, for ex.: 11 | # 12 | # kick: "The player %player% was kicked by %staff%" 13 | # 14 | # 15 | # Variables are self-explained... 16 | messages: 17 | kick: "{embed:kick}" 18 | note: "{embed:note}" 19 | jail: "{embed:jail}" 20 | ban: "{embed:ban}" 21 | tempban: "{embed:tempban}" 22 | mute: "{embed:mute}" 23 | tempmute: "{embed:tempmute}" 24 | banip: "{embed:banip}" 25 | tempbanip: "{embed:tempbanip}" 26 | warn: "{embed:warn}" 27 | tempwarn: "{embed:tempwarn}" 28 | unbanip: "{embed:unbanip}" 29 | unwarn: "{embed:unwarn}" 30 | unmute: "{embed:unmute}" 31 | unban: "{embed:unban}" 32 | unnote: "{embed:unnote}" 33 | unjail: "{embed:unjail}" 34 | 35 | ### Discord Command ### 36 | # Set to true to enable the discord "/banannouncer" slash command. 37 | # 38 | # The command does NOT provides moderation tools, it is for testing 39 | # your embed files and reloading them without going to the console. 40 | # 41 | # Only members with the "BAN_MEMBERS" permission can use the command. 42 | enable-discord-command: true 43 | 44 | # The list of enabled extensions. 45 | # They can provide support for various punishment plugins or 46 | # provide extra functionality to BanAnnouncer. 47 | # 48 | # You can add as many as you want. 49 | # 50 | # (Some) Possible values: 51 | # advancedban = For AdvancedBan 52 | # litebans = For LiteBans 53 | # maxbans = For MaxBansPlus 54 | # libertybans = For LibertyBans 55 | # essentials = For EssentialsX Jails 56 | # betterjails = For BetterJails 57 | enabled-extensions: 58 | - advancedban 59 | - essentials 60 | 61 | # If it's set to false, the punishments made 62 | # with the '-s' flag of LiteBans will be sent anyways. 63 | ignore-silent: false 64 | 65 | # Name to show when the console does stuff 66 | console-name: "Console" 67 | 68 | # When a punishment expires this text will be added to the staff name 69 | # for example: 70 | # "X was unbanned by StaffName (Automatic)" 71 | automatic: "Automatic" 72 | 73 | # Do not change this or i'll eat your cookies 74 | config-version: 4 75 | -------------------------------------------------------------------------------- /src/main/resources/embed/ban.json: -------------------------------------------------------------------------------- 1 | { 2 | "embed": { 3 | "title": "New punishment", 4 | "description": "The player `%player%` has been banned by `%staff%` for `%reason%`", 5 | "color": 14169911, 6 | "footer": { 7 | "icon_url": "https://i.imgur.com/JhEluGV.png", 8 | "text": "Powered by BanAnnouncer" 9 | } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/main/resources/embed/banip.json: -------------------------------------------------------------------------------- 1 | { 2 | "embed": { 3 | "title": "New punishment", 4 | "description": "The player `%player%` has been ip-banned by `%staff%` for `%reason%`", 5 | "color": 14169911, 6 | "footer": { 7 | "icon_url": "https://i.imgur.com/JhEluGV.png", 8 | "text": "Powered by BanAnnouncer" 9 | } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/main/resources/embed/jail.json: -------------------------------------------------------------------------------- 1 | { 2 | "embed": { 3 | "title": "New punishment", 4 | "description": "The player `%player%` was jailed on `%jail%` by `%staff%`", 5 | "color": 5540790, 6 | "footer": { 7 | "icon_url": "https://i.imgur.com/JhEluGV.png", 8 | "text": "Powered by BanAnnouncer" 9 | } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/main/resources/embed/kick.json: -------------------------------------------------------------------------------- 1 | { 2 | "embed": { 3 | "title": "New punishment", 4 | "description": "The player `%player%` was kicked by `%staff%` for `%reason%`", 5 | "color": 5540790, 6 | "footer": { 7 | "icon_url": "https://i.imgur.com/JhEluGV.png", 8 | "text": "Powered by BanAnnouncer" 9 | } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/main/resources/embed/mute.json: -------------------------------------------------------------------------------- 1 | { 2 | "embed": { 3 | "title": "New punishment 🤐", 4 | "description": "The player `%player%` has been muted by `%staff%` for `%reason%`", 5 | "color": 1755751, 6 | "footer": { 7 | "icon_url": "https://i.imgur.com/JhEluGV.png", 8 | "text": "Powered by BanAnnouncer" 9 | } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/main/resources/embed/note.json: -------------------------------------------------------------------------------- 1 | { 2 | "embed": { 3 | "title": "New note", 4 | "description": "The player `%player%` was noted by `%staff%` for `%reason%`", 5 | "color": 5540790, 6 | "footer": { 7 | "icon_url": "https://i.imgur.com/JhEluGV.png", 8 | "text": "Powered by BanAnnouncer" 9 | } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/main/resources/embed/tempban.json: -------------------------------------------------------------------------------- 1 | { 2 | "embed": { 3 | "title": "New punishment ⏲️", 4 | "description": "The player `%player%` was temporarily banned by `%staff%` for `%reason%`, duration: `%duration%`", 5 | "color": 5540790, 6 | "footer": { 7 | "icon_url": "https://i.imgur.com/JhEluGV.png", 8 | "text": "Powered by BanAnnouncer" 9 | } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/main/resources/embed/tempbanip.json: -------------------------------------------------------------------------------- 1 | { 2 | "embed": { 3 | "title": "New punishment ⏲️", 4 | "description": "The player `%player%` was temporarily ip-banned by `%staff%` for `%reason%`, duration: `%duration%`", 5 | "color": 5540790, 6 | "footer": { 7 | "icon_url": "https://i.imgur.com/JhEluGV.png", 8 | "text": "Powered by BanAnnouncer" 9 | } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/main/resources/embed/tempmute.json: -------------------------------------------------------------------------------- 1 | { 2 | "embed": { 3 | "title": "New punishment 🤐", 4 | "description": "The player `%player%` was temporarily muted by `%staff%` for `%reason%`, duration: `%duration%`", 5 | "color": 5540790, 6 | "footer": { 7 | "icon_url": "https://i.imgur.com/JhEluGV.png", 8 | "text": "Powered by BanAnnouncer" 9 | } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/main/resources/embed/tempwarn.json: -------------------------------------------------------------------------------- 1 | { 2 | "embed": { 3 | "title": "New punishment ⏲️", 4 | "description": "The player `%player%` has been temporarily warned by `%staff%` for `%reason%`, duration: `%duration%`", 5 | "color": 5540790, 6 | "footer": { 7 | "icon_url": "https://i.imgur.com/JhEluGV.png", 8 | "text": "Powered by BanAnnouncer" 9 | } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/main/resources/embed/unban.json: -------------------------------------------------------------------------------- 1 | { 2 | "embed": { 3 | "title": "Revoked punishment", 4 | "description": "The player `%player%` has been unbanned by `%staff%`", 5 | "color": 10771377, 6 | "footer": { 7 | "icon_url": "https://i.imgur.com/JhEluGV.png", 8 | "text": "Powered by BanAnnouncer" 9 | } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/main/resources/embed/unbanip.json: -------------------------------------------------------------------------------- 1 | { 2 | "embed": { 3 | "title": "Revoked punishment", 4 | "description": "The player `%player%` has been ip-unbanned by `%staff%`", 5 | "color": 10771377, 6 | "footer": { 7 | "icon_url": "https://i.imgur.com/JhEluGV.png", 8 | "text": "Powered by BanAnnouncer" 9 | } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/main/resources/embed/unjail.json: -------------------------------------------------------------------------------- 1 | { 2 | "embed": { 3 | "title": "Revoked punishment", 4 | "description": "The player `%player%` has beed unjailed from `%jail%` by `%staff%`", 5 | "color": 10771377, 6 | "footer": { 7 | "icon_url": "https://i.imgur.com/JhEluGV.png", 8 | "text": "Powered by BanAnnouncer" 9 | } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/main/resources/embed/unmute.json: -------------------------------------------------------------------------------- 1 | { 2 | "embed": { 3 | "title": "Revoked punishment", 4 | "description": "The player `%player%` has been unmuted by `%staff%`", 5 | "color": 10771377, 6 | "footer": { 7 | "icon_url": "https://i.imgur.com/JhEluGV.png", 8 | "text": "Powered by BanAnnouncer" 9 | } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/main/resources/embed/unnote.json: -------------------------------------------------------------------------------- 1 | { 2 | "embed": { 3 | "title": "Removed note", 4 | "description": "A note for `%player%` has been removed by `%staff%`. Note: `%reason%`", 5 | "color": 5540790, 6 | "footer": { 7 | "icon_url": "https://i.imgur.com/JhEluGV.png", 8 | "text": "Powered by BanAnnouncer" 9 | } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/main/resources/embed/unwarn.json: -------------------------------------------------------------------------------- 1 | { 2 | "embed": { 3 | "title": "Revoked punishment", 4 | "description": "The player `%player%` has been unwarned by `%staff%`", 5 | "color": 10771377, 6 | "footer": { 7 | "icon_url": "https://i.imgur.com/JhEluGV.png", 8 | "text": "Powered by BanAnnouncer" 9 | } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/main/resources/embed/warn.json: -------------------------------------------------------------------------------- 1 | { 2 | "embed": { 3 | "title": "New punishment", 4 | "description": "The player `%player%` has been warned by `%staff%` for `%reason%`", 5 | "color": 5540790, 6 | "footer": { 7 | "icon_url": "https://i.imgur.com/JhEluGV.png", 8 | "text": "Powered by BanAnnouncer" 9 | } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/main/resources/plugin.yml: -------------------------------------------------------------------------------- 1 | name: BanAnnouncer 2 | author: Tini 3 | main: me.tini.announcer.plugin.bukkit.BanAnnouncerBukkit 4 | version: ${project.version} 5 | depend: [Spicord] 6 | softdepend: [AdvancedBan, LiteBans, MaxBansPlus, Essentials, BetterJails] 7 | description: Announce the punishments on your Discord server 8 | api-version: 1.13 9 | 10 | commands: 11 | banannouncer-reload: 12 | aliases: [ bareload ] 13 | -------------------------------------------------------------------------------- /src/main/resources/sponge_plugins.json: -------------------------------------------------------------------------------- 1 | { 2 | "loader": { 3 | "name": "java_plain", 4 | "version": "1.0" 5 | }, 6 | "license": "AGPL-3.0", 7 | "plugins": [ 8 | { 9 | "id": "banannouncer", 10 | "name": "BanAnnouncer", 11 | "version": "${project.version}", 12 | "entrypoint": "me.tini.announcer.plugin.sponge.BanAnnouncerSponge", 13 | "description": "Announce the Minecraft bans on your Discord server.", 14 | "links": { 15 | "homepage": "https://github.com/Spicord/BanAnnouncer", 16 | "source": "https://github.com/Spicord/BanAnnouncer", 17 | "issues": "https://github.com/Spicord/BanAnnouncer/issues" 18 | }, 19 | "contributors": [ 20 | { 21 | "name": "Tini", 22 | "description": "Lead Developer" 23 | } 24 | ], 25 | "dependencies": [ 26 | { 27 | "id": "spicord", 28 | "version": "[5.3.1,)", 29 | "load-order": "after", 30 | "optional": false 31 | }, 32 | { 33 | "id": "libertybans", 34 | "version": "[1.0.4,)", 35 | "load-order": "after", 36 | "optional": true 37 | } 38 | ] 39 | } 40 | ] 41 | } 42 | --------------------------------------------------------------------------------