├── .github ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── FUNDING.yml ├── ISSUE_TEMPLATE │ ├── bug_report.yml │ └── feature_request.yml ├── PULL_REQUEST_TEMPLATE.md └── workflows │ ├── codeql-analysis.yml │ └── main.yml ├── .gitignore ├── LICENSE ├── README.md ├── config.example.yml ├── crowdin.yml ├── licenses ├── FlareBot └── FredBoat ├── pom.xml └── src ├── main ├── java │ └── org │ │ └── cascadebot │ │ └── cascadebot │ │ ├── CascadeBot.java │ │ ├── Constants.java │ │ ├── Environment.java │ │ ├── MDCException.java │ │ ├── ShutdownHandler.java │ │ ├── UnicodeConstants.java │ │ ├── commandmeta │ │ ├── ArgumentManager.java │ │ ├── CommandManager.java │ │ └── Module.java │ │ ├── commands │ │ ├── core │ │ │ ├── HelpCommand.java │ │ │ ├── InviteCommand.java │ │ │ ├── PrefixCommand.java │ │ │ ├── SupportCommand.java │ │ │ └── UsageCommand.java │ │ ├── developer │ │ │ ├── DumpCommand.java │ │ │ ├── EvalCommand.java │ │ │ ├── GuildCommand.java │ │ │ ├── GuildFlagSubCommand.java │ │ │ ├── GuildInfoSubCommand.java │ │ │ ├── GuildLeaveSubCommand.java │ │ │ ├── GuildSaveSubCommand.java │ │ │ ├── RestartCommand.java │ │ │ └── ShutdownCommand.java │ │ ├── fun │ │ │ ├── CatCommand.java │ │ │ ├── ColorCommand.java │ │ │ ├── DogCommand.java │ │ │ ├── JokeCommand.java │ │ │ ├── RandomChoiceSubCommand.java │ │ │ ├── RandomColorSubCommand.java │ │ │ └── RandomCommand.java │ │ ├── informational │ │ │ ├── RolesCommand.java │ │ │ ├── ServerInfoCommand.java │ │ │ └── UserInfoCommand.java │ │ ├── management │ │ │ ├── FlagsCommand.java │ │ │ ├── module │ │ │ │ ├── ModuleCommand.java │ │ │ │ ├── ModuleDisableSubCommand.java │ │ │ │ ├── ModuleEnableSubCommand.java │ │ │ │ └── ModuleListSubCommand.java │ │ │ ├── permission │ │ │ │ ├── GroupPermissionAddSubCommand.java │ │ │ │ ├── GroupPermissionCommand.java │ │ │ │ ├── GroupPermissionCreateSubCommand.java │ │ │ │ ├── GroupPermissionDeleteSubCommand.java │ │ │ │ ├── GroupPermissionInfoSubCommand.java │ │ │ │ ├── GroupPermissionLinkRoleSubCommand.java │ │ │ │ ├── GroupPermissionListSubCommand.java │ │ │ │ ├── GroupPermissionMoveSubCommand.java │ │ │ │ ├── GroupPermissionRemoveSubCommand.java │ │ │ │ ├── GroupPermissionSwitchSubCommand.java │ │ │ │ ├── GroupPermissionUnlinkRoleSubCommand.java │ │ │ │ ├── UserPermissionAddSubCommand.java │ │ │ │ ├── UserPermissionCommand.java │ │ │ │ ├── UserPermissionGroupSubCommand.java │ │ │ │ ├── UserPermissionListSubCommand.java │ │ │ │ ├── UserPermissionRemoveSubCommand.java │ │ │ │ └── UserPermissionTestSubCommand.java │ │ │ └── tag │ │ │ │ ├── TagCategorySubCommand.java │ │ │ │ ├── TagCommand.java │ │ │ │ ├── TagCreateSubCommand.java │ │ │ │ ├── TagDeleteSubCommand.java │ │ │ │ ├── TagEditSubCommand.java │ │ │ │ ├── TagListSubCommand.java │ │ │ │ ├── TagPlaceholdersSubCommand.java │ │ │ │ └── TagRawSubCommand.java │ │ ├── moderation │ │ │ ├── BanCommand.java │ │ │ ├── KickCommand.java │ │ │ ├── PurgeAttachmentSubCommand.java │ │ │ ├── PurgeBotSubCommand.java │ │ │ ├── PurgeCommand.java │ │ │ ├── PurgeContainSubCommand.java │ │ │ ├── PurgeLinkSubCommand.java │ │ │ ├── PurgeUserSubCommand.java │ │ │ ├── SoftBanCommand.java │ │ │ └── UnbanCommand.java │ │ ├── music │ │ │ ├── EqualizerCommand.java │ │ │ ├── EqualizerResetSubCommand.java │ │ │ ├── JoinCommand.java │ │ │ ├── KaraokeCommand.java │ │ │ ├── LeaveCommand.java │ │ │ ├── LoopCommand.java │ │ │ ├── PauseCommand.java │ │ │ ├── PlayCommand.java │ │ │ ├── PlayTopCommand.java │ │ │ ├── PlayingCommand.java │ │ │ ├── QueueCommand.java │ │ │ ├── QueueLoadSubCommand.java │ │ │ ├── QueueMoveSubCommand.java │ │ │ ├── QueueRemoveSubCommand.java │ │ │ ├── QueueSaveSubCommand.java │ │ │ ├── ResumeCommand.java │ │ │ ├── SearchCommand.java │ │ │ ├── SeekCommand.java │ │ │ ├── ShuffleCommand.java │ │ │ ├── SkipCommand.java │ │ │ ├── StopCommand.java │ │ │ └── VolumeCommand.java │ │ └── useful │ │ │ ├── TodoAddSubCommand.java │ │ │ ├── TodoAddUserSubCommand.java │ │ │ ├── TodoCommand.java │ │ │ ├── TodoCreateSubCommand.java │ │ │ ├── TodoRemoveSubCommand.java │ │ │ ├── TodoRemoveUserSubCommand.java │ │ │ ├── TodoSendSubCommand.java │ │ │ └── TodoViewSubCommand.java │ │ ├── data │ │ ├── Config.java │ │ ├── database │ │ │ ├── DatabaseManager.java │ │ │ ├── DebugLogCallback.java │ │ │ ├── IAsyncMongoTask.java │ │ │ └── IMongoTask.java │ │ ├── language │ │ │ └── Locale.java │ │ ├── managers │ │ │ ├── GuildDataManager.java │ │ │ └── PlaylistManager.java │ │ └── objects │ │ │ ├── Flag.java │ │ │ ├── GuildModeration.java │ │ │ ├── GuildPermissions.java │ │ │ ├── GuildSettingsUseful.java │ │ │ ├── PerGuildPermissionsManager.java │ │ │ ├── PermissionObject.java │ │ │ ├── Playlist.java │ │ │ ├── Setting.java │ │ │ ├── SettingsContainer.java │ │ │ └── Tag.java │ │ ├── events │ │ ├── ButtonEventListener.java │ │ ├── CommandListener.java │ │ ├── GuildSaveListener.java │ │ ├── JDAEventMetricsListener.java │ │ ├── PlayerListener.java │ │ └── VoiceEventListener.java │ │ ├── messaging │ │ ├── MessagingDirectMessage.java │ │ ├── MessagingObjects.java │ │ ├── MessagingTimed.java │ │ ├── MessagingTyped.java │ │ ├── MessagingUI.java │ │ └── NoOpWebhookClient.java │ │ ├── metrics │ │ ├── BotMetricsCollector.java │ │ └── Metrics.java │ │ ├── moderation │ │ ├── ModAction.java │ │ └── ModerationManager.java │ │ ├── music │ │ ├── Captions.java │ │ ├── CaptionsTask.java │ │ ├── CascadeLavalinkPlayer.java │ │ ├── CascadeLavaplayerPlayer.java │ │ ├── CascadePlayer.java │ │ ├── KaraokeHandler.java │ │ ├── LavaPlayerAudioSendHandler.java │ │ ├── MovableAudioTrack.java │ │ └── TrackData.java │ │ ├── permissions │ │ ├── CascadePermission.java │ │ ├── PermissionNode.java │ │ ├── PermissionsManager.java │ │ ├── Security.java │ │ └── objects │ │ │ ├── Group.java │ │ │ ├── PermissionHolder.java │ │ │ ├── Result.java │ │ │ └── User.java │ │ ├── tasks │ │ └── Task.java │ │ └── utils │ │ ├── CollectionUtils.java │ │ ├── DiscordUtils.java │ │ ├── EventWaiter.java │ │ ├── FormatUtils.java │ │ ├── LogbackUtils.java │ │ ├── ParserUtils.java │ │ ├── PasteUtils.java │ │ ├── PermissionCommandUtils.java │ │ ├── RandomUtils.java │ │ ├── ReflectionUtils.java │ │ ├── StringsUtil.java │ │ ├── Table.java │ │ ├── WebUtils.java │ │ ├── interactions │ │ ├── IButtonRunnable.java │ │ ├── ISelectionRunnable.java │ │ └── InteractionCache.java │ │ ├── language │ │ └── LanguageUtils.java │ │ ├── move │ │ ├── MovableItem.java │ │ └── MovableList.java │ │ ├── pagination │ │ ├── Page.java │ │ ├── PageCache.java │ │ ├── PageObjects.java │ │ └── PageUtils.java │ │ └── votes │ │ ├── VoteFinishConsumer.java │ │ ├── VoteGroup.java │ │ ├── VoteGroupBuilder.java │ │ ├── VotePeriodicConsumer.java │ │ └── VoteResult.java ├── kotlin │ └── org │ │ └── cascadebot │ │ └── cascadebot │ │ ├── Exceptions.kt │ │ ├── commandmeta │ │ ├── Argument.kt │ │ ├── CommandContext.kt │ │ ├── CoreCommand.kt │ │ ├── ExecutableCommand.kt │ │ ├── MainCommand.kt │ │ ├── RestrictedCommand.kt │ │ └── SubCommand.kt │ │ ├── commands │ │ ├── core │ │ │ └── StatsCommand.kt │ │ ├── management │ │ │ ├── AutoRoleAddSubCommand.kt │ │ │ ├── AutoRoleCommand.kt │ │ │ ├── AutoRoleListSubCommand.kt │ │ │ ├── AutoRoleRemoveSubCommand.kt │ │ │ ├── SettingsCommand.kt │ │ │ ├── SettingsListSubCommand.kt │ │ │ ├── filters │ │ │ │ ├── FiltersChannelsSubCommand.kt │ │ │ │ ├── FiltersCommand.kt │ │ │ │ ├── FiltersCommandsSubCommand.kt │ │ │ │ ├── FiltersCreateSubCommand.kt │ │ │ │ ├── FiltersDeleteSubCommand.kt │ │ │ │ ├── FiltersDisableSubCommand.kt │ │ │ │ ├── FiltersEnableSubCommand.kt │ │ │ │ ├── FiltersListSubCommand.kt │ │ │ │ ├── FiltersOperatorSubCommand.kt │ │ │ │ ├── FiltersRolesSubCommand.kt │ │ │ │ ├── FiltersTypeSubCommand.kt │ │ │ │ └── FiltersUsersSubCommand.kt │ │ │ ├── goodbye │ │ │ │ ├── GoodbyeAddSubCommand.kt │ │ │ │ ├── GoodbyeClearSubCommand.kt │ │ │ │ ├── GoodbyeCommand.kt │ │ │ │ ├── GoodbyeListSubCommand.kt │ │ │ │ ├── GoodbyeRemoveSubCommand.kt │ │ │ │ └── GoodbyeWeightSubCommand.kt │ │ │ └── welcome │ │ │ │ ├── WelcomeAddSubCommand.kt │ │ │ │ ├── WelcomeChannelSubCommand.kt │ │ │ │ ├── WelcomeClearSubCommand.kt │ │ │ │ ├── WelcomeCommand.kt │ │ │ │ ├── WelcomeDMAddSubCommand.kt │ │ │ │ ├── WelcomeDMClearSubCommand.kt │ │ │ │ ├── WelcomeDMCommand.kt │ │ │ │ ├── WelcomeDMListSubCommand.kt │ │ │ │ ├── WelcomeDMRemoveSubCommand.kt │ │ │ │ ├── WelcomeDMWeightSubCommand.kt │ │ │ │ ├── WelcomeListSubCommand.kt │ │ │ │ ├── WelcomeRemoveSubCommand.kt │ │ │ │ └── WelcomeWeightSubCommand.kt │ │ ├── moderation │ │ │ ├── MuteChannelSetupSubCommand.kt │ │ │ ├── MuteCommand.kt │ │ │ ├── MuteRoleSubCommand.kt │ │ │ ├── SlowmodeCommand.kt │ │ │ ├── SlowmodeResetSubCommand.kt │ │ │ ├── TempBan.kt │ │ │ ├── TempMute.kt │ │ │ ├── TempSlowmodeCommand.kt │ │ │ └── UnMuteCommand.kt │ │ └── useful │ │ │ ├── RemindMeCommand.kt │ │ │ └── RemindMeListSubCommand.kt │ │ ├── data │ │ ├── language │ │ │ └── Language.kt │ │ ├── managers │ │ │ └── ScheduledActionManager.kt │ │ └── objects │ │ │ ├── CommandFilter.kt │ │ │ ├── Enums.kt │ │ │ ├── Greetings.kt │ │ │ ├── GuildCommandInfo.kt │ │ │ ├── GuildData.kt │ │ │ ├── GuildSettingsCore.kt │ │ │ ├── GuildSettingsManagement.kt │ │ │ ├── GuildSettingsModeration.kt │ │ │ ├── GuildSettingsMusic.kt │ │ │ └── TodoList.kt │ │ ├── events │ │ ├── BotEvents.kt │ │ └── GuildEvents.kt │ │ ├── messaging │ │ ├── Embeds.kt │ │ ├── MessageType.kt │ │ └── Messaging.kt │ │ ├── music │ │ └── MusicHandler.kt │ │ ├── scheduler │ │ ├── ActionType.kt │ │ └── ScheduledAction.kt │ │ └── utils │ │ ├── CSSColor.kt │ │ ├── ColorUtils.kt │ │ ├── ConfirmUtils.kt │ │ ├── Extensions.kt │ │ ├── PurgeUtils.kt │ │ ├── interactions │ │ ├── CascadeActionRow.kt │ │ ├── CascadeButton.kt │ │ ├── CascadeComponent.kt │ │ ├── CascadeLinkButton.kt │ │ ├── CascadeSelectBox.kt │ │ ├── ComponentContainer.kt │ │ ├── InteractionMessage.kt │ │ └── PersistentComponent.kt │ │ ├── lists │ │ ├── ChangeList.kt │ │ └── WeightedList.kt │ │ └── placeholders │ │ ├── Placeholder.kt │ │ └── Placeholders.kt └── resources │ ├── arguments.json │ ├── lang │ ├── en-GB.json │ └── languagetester │ │ ├── languagetester.js │ │ └── testerconfig.json │ ├── logback.xml │ ├── sentry.properties │ └── version.txt └── test ├── java └── org │ └── cascadebot │ └── cascadebot │ ├── ConstantsTest.java │ └── move │ ├── MovableListTest.java │ ├── TestListsObject.java │ └── TestMovableItem.java └── kotlin └── org └── cascadebot └── cascadebot └── utils ├── ChangeListTest.kt └── WeightedListTest.kt /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | patreon: cascadebot 4 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.yml: -------------------------------------------------------------------------------- 1 | name: Bug report 2 | title: "[Bug] " 3 | labels: bug 4 | description: report a bug with Cascade Bot 5 | body: 6 | - type: textarea 7 | id: describe 8 | attributes: 9 | label: Describe the bug 10 | description: A clear and concise description of what the bug is. 11 | validations: 12 | required: true 13 | - type: textarea 14 | id: reproduce 15 | attributes: 16 | label: What are the steps to reproduce 17 | description: If you are unsure of how to reproduce, the give us as much info about what you where doing when the bug happened 18 | placeholder: | 19 | Steps to reproduce the behavior: 20 | 1. 21 | 2. 22 | 3. 23 | 4. 24 | validations: 25 | required: true 26 | - type: textarea 27 | id: expected 28 | attributes: 29 | label: Expected behavior 30 | description: A clear and concise description of what you expected to happen. 31 | validations: 32 | required: true 33 | - type: input 34 | id: error 35 | attributes: 36 | label: Error id 37 | description: The error id you got (if applicable) 38 | validations: 39 | required: false 40 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | # Pull request 2 | 3 | - [ ] I have read and agreed to the [code of conduct](https://github.com/CascadeBot/CascadeBot/blob/master/.github/CODE_OF_CONDUCT.md). 4 | - [ ] I have read and complied with the [contributing guidelines](https://github.com/CascadeBot/CascadeBot/blob/master/.github/CONTRIBUTING.md). 5 | - [ ] What I'm implementing was assigned to me or was not being worked on and is a somewhat requested feature. For reference see our [GitHub projects](https://github.com/orgs/CascadeBot/projects). 6 | - [ ] I have tested all of my changes. 7 | 8 | ## Added/Changed 9 | What did you add and/or change for this. 10 | 11 | ## Feature 12 | If this is a new feature, why should we add it to the bot. 13 | -------------------------------------------------------------------------------- /.github/workflows/main.yml: -------------------------------------------------------------------------------- 1 | name: cascade-changelog 2 | 3 | on: 4 | issue_comment: 5 | types: [created] 6 | 7 | jobs: 8 | build: 9 | runs-on: ubuntu-latest 10 | steps: 11 | - uses: CascadeBot/Changelog-Action@master 12 | with: 13 | discordPreviewWebhook: ${{ secrets.discordPreviewWebhook }} 14 | discordPublishWebhook: ${{ secrets.discordPublishWebhook }} 15 | authorisedUsers: mrjvs,binaryoverload,weeryan17 16 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .idea/ 2 | 3 | ### Java ### 4 | # Compiled class file 5 | *.class 6 | 7 | # Log file 8 | *.log 9 | logs/ 10 | 11 | # Mobile Tools for Java (J2ME) 12 | .mtj.tmp/ 13 | 14 | # Package Files # 15 | *.jar 16 | *.zip 17 | *.tar.gz 18 | 19 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 20 | hs_err_pid* 21 | 22 | target/ 23 | *.yml 24 | config.yml 25 | !config.example.yml 26 | 27 | *.iml 28 | TestCommand.java -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 CascadeBot 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /crowdin.yml: -------------------------------------------------------------------------------- 1 | files: 2 | - source: /src/main/resources/lang/en-GB.json 3 | translation: /src/main/resources/lang/%locale%.json 4 | -------------------------------------------------------------------------------- /licenses/FlareBot: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 ArsenArsen, Daniel Walsh & William Oldham 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /licenses/FredBoat: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Frederik Ar. Mikkelsen 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /src/main/java/org/cascadebot/cascadebot/Constants.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019 CascadeBot. All rights reserved. 3 | * Licensed under the MIT license. 4 | */ 5 | 6 | package org.cascadebot.cascadebot; 7 | 8 | import lombok.experimental.UtilityClass; 9 | import org.cascadebot.shared.SharedConstants; 10 | 11 | import java.awt.Color; 12 | 13 | @UtilityClass 14 | public class Constants { 15 | 16 | // Changeable constants if needed 17 | public static String serverInvite = "https://discord.cascadebot.org"; 18 | 19 | // Semantic colors used for embeds 20 | public static final Color COLOR_SUCCESS = new Color(132, 214, 162); // #84D6A2 21 | public static final Color COLOR_INFO = new Color(152, 159, 255); // #989FFF 22 | public static final Color COLOR_WARNING = new Color(255, 187, 95); // #FFBB5F 23 | public static final Color COLOR_DANGER = new Color(16741492); // #FF7474 24 | public static final Color COLOR_MODERATION = Color.WHITE; 25 | public static final Color COLOR_NEUTRAL = SharedConstants.CASCADE_COLOR; 26 | 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/org/cascadebot/cascadebot/Environment.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019 CascadeBot. All rights reserved. 3 | * Licensed under the MIT license. 4 | */ 5 | 6 | package org.cascadebot.cascadebot; 7 | 8 | import lombok.experimental.UtilityClass; 9 | 10 | // I've created a new class because we may want extra 11 | // logic here in the future such as a Patreon bot 12 | @UtilityClass 13 | public class Environment { 14 | 15 | public static boolean isDevelopment() { 16 | return CascadeBot.getVersion().getBuild().equalsIgnoreCase("dev"); 17 | } 18 | 19 | public static boolean isProduction() { 20 | return !isDevelopment(); 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/org/cascadebot/cascadebot/MDCException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019 CascadeBot. All rights reserved. 3 | * Licensed under the MIT license. 4 | */ 5 | 6 | package org.cascadebot.cascadebot; 7 | 8 | import org.slf4j.MDC; 9 | 10 | import java.io.PrintStream; 11 | import java.io.PrintWriter; 12 | import java.util.stream.Collectors; 13 | 14 | public class MDCException extends RuntimeException { 15 | 16 | private MDCException(String message, Throwable cause) { 17 | super(message, cause); 18 | 19 | } 20 | 21 | public static MDCException from(Throwable cause) { 22 | String message = ""; 23 | if (MDC.getCopyOfContextMap() != null) { 24 | message = MDC.getCopyOfContextMap() 25 | .entrySet() 26 | .stream() 27 | .map(entry -> entry.getKey() + ": " + entry.getValue()) 28 | .collect(Collectors.joining("\n")); 29 | } 30 | return new MDCException(message, cause); 31 | } 32 | 33 | /* 34 | 35 | We don't want the main exception to be printed as it is just a wrapper. 36 | That is why these exist :P 37 | 38 | */ 39 | 40 | @Override 41 | public void printStackTrace(PrintWriter s) { 42 | s.println(getMessage()); 43 | s.println(); 44 | getCause().printStackTrace(s); 45 | } 46 | 47 | @Override 48 | public void printStackTrace(PrintStream s) { 49 | s.println(getMessage()); 50 | s.println(); 51 | getCause().printStackTrace(s); 52 | } 53 | 54 | } 55 | -------------------------------------------------------------------------------- /src/main/java/org/cascadebot/cascadebot/commands/core/InviteCommand.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019 CascadeBot. All rights reserved. 3 | * Licensed under the MIT license. 4 | */ 5 | 6 | package org.cascadebot.cascadebot.commands.core; 7 | 8 | import net.dv8tion.jda.api.entities.Member; 9 | import org.cascadebot.cascadebot.CascadeBot; 10 | import org.cascadebot.cascadebot.Environment; 11 | import org.cascadebot.cascadebot.commandmeta.CommandContext; 12 | import org.cascadebot.cascadebot.commandmeta.CoreCommand; 13 | 14 | public class InviteCommand extends CoreCommand { 15 | 16 | @Override 17 | public void onCommand(Member sender, CommandContext context) { 18 | if (Environment.isProduction()) { 19 | context.getDirectMessaging().replyDM(CascadeBot.getInvite(), true); 20 | } else { 21 | context.getDirectMessaging().replyDM("https://www.youtube.com/watch?v=ARJ8cAGm6JE"); 22 | } 23 | } 24 | 25 | @Override 26 | public String command() { 27 | return "invite"; 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/org/cascadebot/cascadebot/commands/core/PrefixCommand.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019 CascadeBot. All rights reserved. 3 | * Licensed under the MIT license. 4 | */ 5 | 6 | package org.cascadebot.cascadebot.commands.core; 7 | 8 | import net.dv8tion.jda.api.entities.Member; 9 | import org.cascadebot.cascadebot.commandmeta.CommandContext; 10 | import org.cascadebot.cascadebot.commandmeta.CoreCommand; 11 | import org.cascadebot.cascadebot.data.Config; 12 | 13 | public class PrefixCommand extends CoreCommand { 14 | 15 | @Override 16 | public void onCommand(Member sender, CommandContext context) { 17 | if (context.getArgs().length > 0) { 18 | String newPrefix = context.getArg(0); 19 | 20 | if (context.testForArg("reset")) { 21 | if (context.hasPermission("prefix.reset")) { 22 | context.getCoreSettings().setPrefix(Config.INS.getDefaultPrefix()); 23 | context.getTypedMessaging().replyInfo(context.i18n("commands.prefix.prefix_reset", Config.INS.getDefaultPrefix())); 24 | } else { 25 | context.getUiMessaging().sendPermissionError("prefix.reset"); 26 | } 27 | return; 28 | } 29 | 30 | if (!context.hasPermission("prefix.set")) { 31 | context.getUiMessaging().sendPermissionError("prefix.set"); 32 | return; 33 | } 34 | 35 | if (newPrefix.length() > 5) { 36 | context.getTypedMessaging().replyDanger(context.i18n("commands.prefix.prefix_too_long")); 37 | return; 38 | } 39 | context.getCoreSettings().setPrefix(newPrefix); 40 | context.getTypedMessaging().replyInfo(context.i18n("commands.prefix.new_prefix", newPrefix)); 41 | } else { 42 | context.getTypedMessaging().replyInfo(context.i18n("commands.prefix.current_prefix", context.getCoreSettings().getPrefix())); 43 | } 44 | } 45 | 46 | @Override 47 | public String command() { 48 | return "prefix"; 49 | } 50 | 51 | } 52 | -------------------------------------------------------------------------------- /src/main/java/org/cascadebot/cascadebot/commands/core/SupportCommand.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019 CascadeBot. All rights reserved. 3 | * Licensed under the MIT license. 4 | */ 5 | 6 | package org.cascadebot.cascadebot.commands.core; 7 | 8 | import net.dv8tion.jda.api.entities.Member; 9 | import org.cascadebot.cascadebot.Constants; 10 | import org.cascadebot.cascadebot.commandmeta.CommandContext; 11 | import org.cascadebot.cascadebot.commandmeta.CoreCommand; 12 | 13 | public class SupportCommand extends CoreCommand { 14 | 15 | @Override 16 | public void onCommand(Member sender, CommandContext context) { 17 | context.getTypedMessaging().replyInfo(context.i18n("commands.support.cascade_support_server", Constants.serverInvite)); 18 | } 19 | 20 | @Override 21 | public String command() { 22 | return "support"; 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/org/cascadebot/cascadebot/commands/core/UsageCommand.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019 CascadeBot. All rights reserved. 3 | * Licensed under the MIT license. 4 | */ 5 | 6 | package org.cascadebot.cascadebot.commands.core; 7 | 8 | import net.dv8tion.jda.api.entities.Member; 9 | import org.cascadebot.cascadebot.CascadeBot; 10 | import org.cascadebot.cascadebot.commandmeta.CommandContext; 11 | import org.cascadebot.cascadebot.commandmeta.CoreCommand; 12 | import org.cascadebot.cascadebot.commandmeta.MainCommand; 13 | import org.cascadebot.cascadebot.commandmeta.RestrictedCommand; 14 | import org.cascadebot.cascadebot.permissions.Security; 15 | 16 | public class UsageCommand extends CoreCommand { 17 | 18 | @Override 19 | public void onCommand(Member sender, CommandContext context) { 20 | if (context.getArgs().length < 1) { 21 | context.getTypedMessaging().replyDanger(context.i18n("commands.usage.specify_usage")); 22 | return; 23 | } 24 | 25 | MainCommand command = CascadeBot.INS.getCommandManager().getCommand(context.getArg(0), context.getData()); 26 | // If the user isn't authorised to run the command (i.e. it's a dev command) then we pretend it doesn't exist ✨ 27 | if (command == null || (command instanceof RestrictedCommand && !Security.isAuthorised(sender.getIdLong(), ((RestrictedCommand) command).commandLevel()))) { 28 | context.getTypedMessaging().replyDanger(context.i18n("commands.usage.command_not_found", context.getArg(0))); 29 | return; 30 | } 31 | 32 | context.getUiMessaging().replyUsage(command); 33 | } 34 | 35 | @Override 36 | public String command() { 37 | return "usage"; 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/org/cascadebot/cascadebot/commands/developer/GuildCommand.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019 CascadeBot. All rights reserved. 3 | * Licensed under the MIT license. 4 | */ 5 | 6 | package org.cascadebot.cascadebot.commands.developer; 7 | 8 | import net.dv8tion.jda.api.entities.Member; 9 | import org.cascadebot.cascadebot.commandmeta.CommandContext; 10 | import org.cascadebot.cascadebot.commandmeta.Module; 11 | import org.cascadebot.cascadebot.commandmeta.RestrictedCommand; 12 | import org.cascadebot.cascadebot.commandmeta.SubCommand; 13 | import org.cascadebot.shared.SecurityLevel; 14 | 15 | import java.util.Set; 16 | 17 | public class GuildCommand extends RestrictedCommand { 18 | 19 | @Override 20 | public void onCommand(Member sender, CommandContext context) { 21 | context.getUiMessaging().replyUsage(); 22 | } 23 | 24 | @Override 25 | public Module module() { 26 | return Module.DEVELOPER; 27 | } 28 | 29 | @Override 30 | public String description() { 31 | return "Allows administrative actions to be run on guilds."; 32 | } 33 | 34 | @Override 35 | public SecurityLevel commandLevel() { 36 | return SecurityLevel.DEVELOPER; 37 | } 38 | 39 | @Override 40 | public Set subCommands() { 41 | return Set.of(new GuildSaveSubCommand(), new GuildLeaveSubCommand(), new GuildFlagSubCommand(), new GuildInfoSubCommand()); 42 | } 43 | 44 | @Override 45 | public String command() { 46 | return "guild"; 47 | } 48 | 49 | } 50 | -------------------------------------------------------------------------------- /src/main/java/org/cascadebot/cascadebot/commands/developer/GuildLeaveSubCommand.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019 CascadeBot. All rights reserved. 3 | * Licensed under the MIT license. 4 | */ 5 | 6 | package org.cascadebot.cascadebot.commands.developer; 7 | 8 | import net.dv8tion.jda.api.entities.Member; 9 | import org.cascadebot.cascadebot.commandmeta.CommandContext; 10 | import org.cascadebot.cascadebot.commandmeta.SubCommand; 11 | import org.cascadebot.cascadebot.messaging.MessageType; 12 | import org.cascadebot.cascadebot.messaging.Messaging; 13 | import org.cascadebot.cascadebot.permissions.CascadePermission; 14 | 15 | public class GuildLeaveSubCommand extends SubCommand { 16 | 17 | @Override 18 | public void onCommand(Member sender, CommandContext context) { 19 | // TODO: Leave other guilds 20 | Messaging.sendMessage(MessageType.SUCCESS, context.getChannel(), "Goodbye!") 21 | .thenAccept(message -> context.getGuild().leave().queue()); 22 | } 23 | 24 | @Override 25 | public String command() { 26 | return "leave"; 27 | } 28 | 29 | @Override 30 | public String parent() { 31 | return "guild"; 32 | } 33 | 34 | @Override 35 | public String description() { 36 | return "Instructs the bot to leave the current guild."; 37 | } 38 | 39 | @Override 40 | public CascadePermission permission() { 41 | return null; 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /src/main/java/org/cascadebot/cascadebot/commands/developer/RestartCommand.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019 CascadeBot. All rights reserved. 3 | * Licensed under the MIT license. 4 | */ 5 | 6 | package org.cascadebot.cascadebot.commands.developer; 7 | 8 | import net.dv8tion.jda.api.entities.Member; 9 | import org.cascadebot.cascadebot.CascadeBot; 10 | import org.cascadebot.cascadebot.ShutdownHandler; 11 | import org.cascadebot.cascadebot.commandmeta.CommandContext; 12 | import org.cascadebot.cascadebot.commandmeta.Module; 13 | import org.cascadebot.cascadebot.commandmeta.RestrictedCommand; 14 | import org.cascadebot.shared.SecurityLevel; 15 | 16 | public class RestartCommand extends RestrictedCommand { 17 | 18 | @Override 19 | public void onCommand(Member sender, CommandContext context) { 20 | if (ShutdownHandler.SHUTDOWN_LOCK.get()) { 21 | context.getTypedMessaging().replyDanger("The bot is already shutting down!"); 22 | return; 23 | } 24 | context.getTypedMessaging().replyInfo("Bot is restarting!"); 25 | CascadeBot.LOGGER.info("Restarting via command! Issuer: " + context.getUser().getAsTag()); 26 | ShutdownHandler.restart(); 27 | } 28 | 29 | @Override 30 | public String command() { 31 | return "restart"; 32 | } 33 | 34 | @Override 35 | public String description() { 36 | return "Restarts the bot via the wrapper."; 37 | } 38 | 39 | @Override 40 | public SecurityLevel commandLevel() { 41 | return SecurityLevel.OWNER; 42 | } 43 | 44 | @Override 45 | public Module module() { 46 | return Module.DEVELOPER; 47 | } 48 | 49 | } 50 | -------------------------------------------------------------------------------- /src/main/java/org/cascadebot/cascadebot/commands/fun/ColorCommand.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019 CascadeBot. All rights reserved. 3 | * Licensed under the MIT license. 4 | */ 5 | 6 | 7 | package org.cascadebot.cascadebot.commands.fun; 8 | 9 | import net.dv8tion.jda.api.entities.Member; 10 | import org.cascadebot.cascadebot.commandmeta.CommandContext; 11 | import org.cascadebot.cascadebot.commandmeta.MainCommand; 12 | import org.cascadebot.cascadebot.commandmeta.Module; 13 | import org.cascadebot.cascadebot.permissions.CascadePermission; 14 | import org.cascadebot.cascadebot.utils.ColorUtils; 15 | 16 | import java.awt.Color; 17 | 18 | public class ColorCommand extends MainCommand { 19 | 20 | @Override 21 | public void onCommand(Member sender, CommandContext context) { 22 | if (context.getArgs().length == 0) { 23 | context.getUiMessaging().replyUsage(); 24 | return; 25 | } 26 | 27 | try { 28 | Color color = ColorUtils.getColor(context.getMessage(0), context); 29 | context.reply(ColorUtils.getColorEmbed(color, context)); 30 | } catch (ColorUtils.ColorException e) { 31 | context.getTypedMessaging().replyDanger(e.getI18nMessage(context.getLocale())); 32 | } 33 | 34 | } 35 | 36 | @Override 37 | public Module module() { 38 | return Module.FUN; 39 | } 40 | 41 | 42 | @Override 43 | public String command() { 44 | return "color"; 45 | } 46 | 47 | @Override 48 | public CascadePermission permission() { 49 | return CascadePermission.of("color", true); 50 | } 51 | 52 | } 53 | -------------------------------------------------------------------------------- /src/main/java/org/cascadebot/cascadebot/commands/fun/JokeCommand.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019 CascadeBot. All rights reserved. 3 | * Licensed under the MIT license. 4 | */ 5 | 6 | package org.cascadebot.cascadebot.commands.fun; 7 | 8 | import net.dv8tion.jda.api.entities.Member; 9 | import org.cascadebot.cascadebot.commandmeta.CommandContext; 10 | import org.cascadebot.cascadebot.commandmeta.MainCommand; 11 | import org.cascadebot.cascadebot.commandmeta.Module; 12 | import org.cascadebot.cascadebot.permissions.CascadePermission; 13 | import org.cascadebot.cascadebot.utils.RandomUtils; 14 | 15 | import java.io.IOException; 16 | 17 | public class JokeCommand extends MainCommand { 18 | 19 | @Override 20 | public void onCommand(Member sender, CommandContext context) { 21 | try { 22 | context.getTypedMessaging().replyInfo(RandomUtils.randomJoke()); 23 | } catch (IOException | IllegalArgumentException e) { 24 | context.getTypedMessaging().replyDanger(context.i18n("commands.joke.error_loading")); 25 | } 26 | } 27 | 28 | @Override 29 | public String command() { 30 | return "joke"; 31 | } 32 | 33 | @Override 34 | public CascadePermission permission() { 35 | return CascadePermission.of("joke", true); 36 | } 37 | 38 | @Override 39 | public Module module() { 40 | return Module.FUN; 41 | } 42 | 43 | } -------------------------------------------------------------------------------- /src/main/java/org/cascadebot/cascadebot/commands/fun/RandomChoiceSubCommand.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019 CascadeBot. All rights reserved. 3 | * Licensed under the MIT license. 4 | */ 5 | 6 | 7 | package org.cascadebot.cascadebot.commands.fun; 8 | 9 | import net.dv8tion.jda.api.entities.Member; 10 | import org.cascadebot.cascadebot.commandmeta.CommandContext; 11 | import org.cascadebot.cascadebot.commandmeta.SubCommand; 12 | import org.cascadebot.cascadebot.permissions.CascadePermission; 13 | import org.cascadebot.cascadebot.utils.RandomUtils; 14 | 15 | public class RandomChoiceSubCommand extends SubCommand { 16 | 17 | @Override 18 | public void onCommand(Member sender, CommandContext context) { 19 | if (context.getArgs().length > 1) { 20 | context.getTypedMessaging().replySuccess(context.i18n("commands.random.random_choice_result", RandomUtils.randomChoice(context.getArgs()))); 21 | } else { 22 | context.getUiMessaging().replyUsage(); 23 | } 24 | } 25 | 26 | @Override 27 | public String command() { return "choice"; } 28 | 29 | @Override 30 | public String parent() { return "random"; } 31 | 32 | @Override 33 | public CascadePermission permission() { return null; } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/org/cascadebot/cascadebot/commands/fun/RandomColorSubCommand.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019 CascadeBot. All rights reserved. 3 | * Licensed under the MIT license. 4 | */ 5 | 6 | 7 | package org.cascadebot.cascadebot.commands.fun; 8 | 9 | import net.dv8tion.jda.api.entities.Member; 10 | import org.cascadebot.cascadebot.commandmeta.CommandContext; 11 | import org.cascadebot.cascadebot.commandmeta.SubCommand; 12 | import org.cascadebot.cascadebot.permissions.CascadePermission; 13 | import org.cascadebot.cascadebot.utils.ColorUtils; 14 | import org.cascadebot.cascadebot.utils.RandomUtils; 15 | 16 | public class RandomColorSubCommand extends SubCommand { 17 | 18 | @Override 19 | public void onCommand(Member sender, CommandContext context) { 20 | context.reply(ColorUtils.getColorEmbed(RandomUtils.randomColor(), context)); 21 | } 22 | 23 | @Override 24 | public String command() { return "color"; } 25 | 26 | @Override 27 | public String parent() { return "random"; } 28 | 29 | @Override 30 | public CascadePermission permission() { return null; } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/org/cascadebot/cascadebot/commands/informational/RolesCommand.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019 CascadeBot. All rights reserved. 3 | * Licensed under the MIT license. 4 | */ 5 | 6 | package org.cascadebot.cascadebot.commands.informational; 7 | 8 | import net.dv8tion.jda.api.entities.Member; 9 | import net.dv8tion.jda.api.entities.Role; 10 | import org.cascadebot.cascadebot.commandmeta.CommandContext; 11 | import org.cascadebot.cascadebot.commandmeta.MainCommand; 12 | import org.cascadebot.cascadebot.commandmeta.Module; 13 | import org.cascadebot.cascadebot.permissions.CascadePermission; 14 | import org.cascadebot.cascadebot.utils.Table; 15 | import org.cascadebot.cascadebot.utils.pagination.PageUtils; 16 | 17 | public class RolesCommand extends MainCommand { 18 | 19 | @Override 20 | public void onCommand(Member sender, CommandContext context) { 21 | Table.TableBuilder builder = new Table.TableBuilder(context.i18n("commands.roles.header_id"), 22 | context.i18n("commands.roles.header_name"), 23 | context.i18n("commands.roles.header_members"), 24 | context.i18n("commands.roles.header_color")); 25 | 26 | for (Role role : context.getGuild().getRoles()) { 27 | if (role.getName().equals("@everyone")) { 28 | continue; 29 | } 30 | builder.addRow(role.getId(), role.getName(), String.valueOf(context.getGuild() 31 | .getMembers() 32 | .stream() 33 | .filter(member -> member.getRoles().contains(role)) 34 | .count()), 35 | role.getColor() == null ? context.i18n("words.default") : "#" + Integer.toHexString(role.getColor().getRGB())); 36 | } 37 | 38 | context.getUiMessaging().sendPagedMessage(PageUtils.splitTableDataToCharWithMaxRows(builder.build(), 1800, 20)); 39 | } 40 | 41 | @Override 42 | public String command() { 43 | return "roles"; 44 | } 45 | 46 | @Override 47 | public Module module() { 48 | return Module.INFORMATIONAL; 49 | } 50 | 51 | @Override 52 | public CascadePermission permission() { 53 | return CascadePermission.of("roles", false); 54 | } 55 | 56 | } 57 | -------------------------------------------------------------------------------- /src/main/java/org/cascadebot/cascadebot/commands/management/FlagsCommand.java: -------------------------------------------------------------------------------- 1 | package org.cascadebot.cascadebot.commands.management; 2 | 3 | import net.dv8tion.jda.api.EmbedBuilder; 4 | import net.dv8tion.jda.api.entities.Guild; 5 | import net.dv8tion.jda.api.entities.Member; 6 | import org.apache.commons.lang3.StringUtils; 7 | import org.cascadebot.cascadebot.UnicodeConstants; 8 | import org.cascadebot.cascadebot.commandmeta.CommandContext; 9 | import org.cascadebot.cascadebot.commandmeta.MainCommand; 10 | import org.cascadebot.cascadebot.commandmeta.Module; 11 | import org.cascadebot.cascadebot.data.objects.Flag; 12 | import org.cascadebot.cascadebot.data.objects.GuildData; 13 | import org.cascadebot.cascadebot.messaging.MessagingObjects; 14 | import org.cascadebot.cascadebot.permissions.CascadePermission; 15 | import org.cascadebot.cascadebot.utils.FormatUtils; 16 | 17 | import java.util.Arrays; 18 | import java.util.stream.Collectors; 19 | 20 | public class FlagsCommand extends MainCommand { 21 | 22 | @Override 23 | public void onCommand(Member sender, CommandContext context) { 24 | GuildData dataForList = context.getData(); 25 | Guild guildForList = context.getGuild(); 26 | 27 | String flags = Arrays.stream(Flag.values()) 28 | .map(flag -> StringUtils.capitalize(FormatUtils.formatEnum(flag, context.getLocale())) + " - " + 29 | (dataForList.isFlagEnabled(flag) ? UnicodeConstants.TICK : UnicodeConstants.RED_CROSS)) 30 | .collect(Collectors.joining("\n")); 31 | 32 | EmbedBuilder builder = MessagingObjects.getClearThreadLocalEmbedBuilder(); 33 | builder.setTitle(guildForList.getName()); 34 | builder.setThumbnail(guildForList.getIconUrl()); 35 | 36 | builder.addField(context.i18n("words.flags"), flags, false); 37 | 38 | context.getTypedMessaging().replyInfo(builder); 39 | } 40 | 41 | @Override 42 | public Module module() { 43 | return Module.MANAGEMENT; 44 | } 45 | 46 | @Override 47 | public String command() { 48 | return "flags"; 49 | } 50 | 51 | @Override 52 | public CascadePermission permission() { 53 | return CascadePermission.of("flags", false); 54 | } 55 | 56 | } 57 | -------------------------------------------------------------------------------- /src/main/java/org/cascadebot/cascadebot/commands/management/module/ModuleCommand.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019 CascadeBot. All rights reserved. 3 | * Licensed under the MIT license. 4 | */ 5 | 6 | package org.cascadebot.cascadebot.commands.management.module; 7 | 8 | import net.dv8tion.jda.api.Permission; 9 | import net.dv8tion.jda.api.entities.Member; 10 | import org.cascadebot.cascadebot.commandmeta.CommandContext; 11 | import org.cascadebot.cascadebot.commandmeta.MainCommand; 12 | import org.cascadebot.cascadebot.commandmeta.Module; 13 | import org.cascadebot.cascadebot.commandmeta.SubCommand; 14 | import org.cascadebot.cascadebot.permissions.CascadePermission; 15 | 16 | import java.util.Set; 17 | 18 | public class ModuleCommand extends MainCommand { 19 | 20 | @Override 21 | public void onCommand(Member sender, CommandContext context) { 22 | context.getUiMessaging().replyUsage(); 23 | } 24 | 25 | @Override 26 | public String command() { 27 | return "module"; 28 | } 29 | 30 | @Override 31 | public Module module() { 32 | return Module.MANAGEMENT; 33 | } 34 | 35 | @Override 36 | public Set subCommands() { 37 | return Set.of(new ModuleDisableSubCommand(), new ModuleEnableSubCommand(), new ModuleListSubCommand()); 38 | } 39 | 40 | @Override 41 | public CascadePermission permission() { 42 | return CascadePermission.of("module", false, Permission.MANAGE_SERVER); 43 | } 44 | 45 | } 46 | -------------------------------------------------------------------------------- /src/main/java/org/cascadebot/cascadebot/commands/management/module/ModuleListSubCommand.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019 CascadeBot. All rights reserved. 3 | * Licensed under the MIT license. 4 | */ 5 | 6 | package org.cascadebot.cascadebot.commands.management.module; 7 | 8 | import net.dv8tion.jda.api.Permission; 9 | import net.dv8tion.jda.api.entities.Member; 10 | import org.cascadebot.cascadebot.commandmeta.CommandContext; 11 | import org.cascadebot.cascadebot.commandmeta.Module; 12 | import org.cascadebot.cascadebot.commandmeta.SubCommand; 13 | import org.cascadebot.cascadebot.messaging.MessagingObjects; 14 | import org.cascadebot.cascadebot.permissions.CascadePermission; 15 | import org.cascadebot.cascadebot.utils.ExtensionsKt; 16 | import org.cascadebot.cascadebot.utils.FormatUtils; 17 | 18 | import java.util.Arrays; 19 | import java.util.stream.Collectors; 20 | 21 | public class ModuleListSubCommand extends SubCommand { 22 | 23 | @Override 24 | public void onCommand(Member sender, CommandContext context) { 25 | String moduleList = Arrays.stream(Module.values()) 26 | .filter(module -> !module.isPrivate()) 27 | .map(module -> (context.getData().getCore().isModuleEnabled(module) ? context.globalEmote("tick") : context.globalEmote("cross")) + 28 | ExtensionsKt.toCapitalized(FormatUtils.formatEnum(module, context.getLocale()))) 29 | .collect(Collectors.joining("\n")); 30 | 31 | context.getTypedMessaging().replyInfo( 32 | MessagingObjects.getStandardMessageEmbed( 33 | moduleList, 34 | context.getUser(), context.getLocale()).setTitle(ExtensionsKt.toCapitalized(context.i18n("words.modules")) 35 | ) 36 | ); 37 | } 38 | 39 | @Override 40 | public String command() { 41 | return "list"; 42 | } 43 | 44 | @Override 45 | public String parent() { 46 | return "module"; 47 | } 48 | 49 | @Override 50 | public CascadePermission permission() { 51 | return CascadePermission.of("module.list", false, Permission.MANAGE_SERVER); 52 | } 53 | 54 | } 55 | -------------------------------------------------------------------------------- /src/main/java/org/cascadebot/cascadebot/commands/management/permission/GroupPermissionAddSubCommand.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019 CascadeBot. All rights reserved. 3 | * Licensed under the MIT license. 4 | */ 5 | 6 | package org.cascadebot.cascadebot.commands.management.permission; 7 | 8 | import net.dv8tion.jda.api.entities.Member; 9 | import org.cascadebot.cascadebot.commandmeta.CommandContext; 10 | import org.cascadebot.cascadebot.commandmeta.Module; 11 | import org.cascadebot.cascadebot.commandmeta.SubCommand; 12 | import org.cascadebot.cascadebot.permissions.CascadePermission; 13 | import org.cascadebot.cascadebot.utils.PermissionCommandUtils; 14 | 15 | public class GroupPermissionAddSubCommand extends SubCommand { 16 | 17 | @Override 18 | public void onCommand(Member sender, CommandContext context) { 19 | if (context.getArgs().length < 2) { 20 | context.getUiMessaging().replyUsage(); 21 | return; 22 | } 23 | 24 | if (!context.getData().getPermissionsManager().isValidPermission(context.getArg(1))) { 25 | context.getTypedMessaging().replyDanger(context.i18n("responses.permission_not_exist", context.getArg(1))); 26 | return; 27 | } 28 | 29 | PermissionCommandUtils.tryGetGroupFromString(context, context.getArg(0), group -> { 30 | if (group.addPermission(context.getArg(1))) { 31 | context.getTypedMessaging().replySuccess(context.i18n("commands.groupperms.add.success", context.getArg(1), group.getName() + "(" + group.getId() + ")")); 32 | } else { 33 | context.getTypedMessaging().replyWarning(context.i18n("commands.groupperms.add.fail", context.getArg(1), group.getName() + "(" + group.getId() + ")")); 34 | } 35 | }, sender.getIdLong()); 36 | } 37 | 38 | @Override 39 | public String command() { 40 | return "add"; 41 | } 42 | 43 | @Override 44 | public String parent() { 45 | return "groupperms"; 46 | } 47 | 48 | @Override 49 | public CascadePermission permission() { 50 | return CascadePermission.of("permissions.group.add", false, Module.MANAGEMENT); 51 | } 52 | 53 | @Override 54 | public String description() { 55 | return null; 56 | } 57 | 58 | } 59 | -------------------------------------------------------------------------------- /src/main/java/org/cascadebot/cascadebot/commands/management/permission/GroupPermissionCreateSubCommand.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019 CascadeBot. All rights reserved. 3 | * Licensed under the MIT license. 4 | */ 5 | 6 | package org.cascadebot.cascadebot.commands.management.permission; 7 | 8 | import net.dv8tion.jda.api.entities.Member; 9 | import org.cascadebot.cascadebot.commandmeta.CommandContext; 10 | import org.cascadebot.cascadebot.commandmeta.Module; 11 | import org.cascadebot.cascadebot.commandmeta.SubCommand; 12 | import org.cascadebot.cascadebot.permissions.CascadePermission; 13 | import org.cascadebot.cascadebot.permissions.objects.Group; 14 | 15 | public class GroupPermissionCreateSubCommand extends SubCommand { 16 | 17 | @Override 18 | public void onCommand(Member sender, CommandContext context) { 19 | if (context.getArgs().length < 1) { 20 | context.getUiMessaging().replyUsage(); 21 | return; 22 | } 23 | 24 | Group group = context.getData().getManagement().getPermissions().createGroup(context.getArg(0)); 25 | context.getTypedMessaging().replySuccess(context.i18n("commands.groupperms.create.success", context.getArg(0), group.getId())); 26 | } 27 | 28 | @Override 29 | public String command() { 30 | return "create"; 31 | } 32 | 33 | @Override 34 | public String parent() { 35 | return "groupperms"; 36 | } 37 | 38 | @Override 39 | public CascadePermission permission() { 40 | return CascadePermission.of("permissions.group.create", false, Module.MANAGEMENT); 41 | } 42 | 43 | @Override 44 | public String description() { 45 | return null; 46 | } 47 | 48 | } 49 | -------------------------------------------------------------------------------- /src/main/java/org/cascadebot/cascadebot/commands/management/permission/GroupPermissionDeleteSubCommand.java: -------------------------------------------------------------------------------- 1 | package org.cascadebot.cascadebot.commands.management.permission; 2 | 3 | import net.dv8tion.jda.api.entities.Member; 4 | import org.cascadebot.cascadebot.commandmeta.CommandContext; 5 | import org.cascadebot.cascadebot.commandmeta.Module; 6 | import org.cascadebot.cascadebot.commandmeta.SubCommand; 7 | import org.cascadebot.cascadebot.permissions.CascadePermission; 8 | import org.cascadebot.cascadebot.utils.PermissionCommandUtils; 9 | 10 | public class GroupPermissionDeleteSubCommand extends SubCommand { 11 | 12 | @Override 13 | public void onCommand(Member sender, CommandContext context) { 14 | if (context.getArgs().length < 1) { 15 | context.getUiMessaging().replyUsage(); 16 | return; 17 | } 18 | 19 | PermissionCommandUtils.tryGetGroupFromString(context, context.getArg(0), group -> { 20 | if (context.getData().getManagement().getPermissions().deleteGroup(group.getId())) { 21 | // If the group existed to delete and has been successfully deleted. 22 | context.getTypedMessaging().replySuccess(context.i18n("commands.groupperms.delete.success", group.getName(), group.getId())); 23 | } else { 24 | // Throwing an exception here because this *should* never happen 25 | throw new IllegalStateException("Couldn't delete group!"); 26 | } 27 | }, sender.getIdLong()); 28 | } 29 | 30 | @Override 31 | public String parent() { 32 | return "groupperms"; 33 | } 34 | 35 | @Override 36 | public String command() { 37 | return "delete"; 38 | } 39 | 40 | @Override 41 | public CascadePermission permission() { 42 | return CascadePermission.of("permissions.group.delete", false, Module.MANAGEMENT); 43 | } 44 | 45 | } 46 | -------------------------------------------------------------------------------- /src/main/java/org/cascadebot/cascadebot/commands/management/permission/GroupPermissionLinkRoleSubCommand.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019 CascadeBot. All rights reserved. 3 | * Licensed under the MIT license. 4 | */ 5 | 6 | package org.cascadebot.cascadebot.commands.management.permission; 7 | 8 | import net.dv8tion.jda.api.entities.Member; 9 | import net.dv8tion.jda.api.entities.Role; 10 | import org.cascadebot.cascadebot.commandmeta.CommandContext; 11 | import org.cascadebot.cascadebot.commandmeta.Module; 12 | import org.cascadebot.cascadebot.commandmeta.SubCommand; 13 | import org.cascadebot.cascadebot.permissions.CascadePermission; 14 | import org.cascadebot.cascadebot.utils.DiscordUtils; 15 | import org.cascadebot.cascadebot.utils.PermissionCommandUtils; 16 | 17 | public class GroupPermissionLinkRoleSubCommand extends SubCommand { 18 | 19 | @Override 20 | public void onCommand(Member sender, CommandContext context) { 21 | if (context.getArgs().length < 2) { 22 | context.getUiMessaging().replyUsage(); 23 | return; 24 | } 25 | 26 | Role role = DiscordUtils.getRole(context.getArg(1), context.getGuild()); 27 | if (role == null) { 28 | context.getTypedMessaging().replyDanger(context.i18n("responses.cannot_find_role_matching", context.getArg(1))); 29 | return; 30 | } 31 | 32 | PermissionCommandUtils.tryGetGroupFromString(context, context.getArg(0), group -> { 33 | if (group.linkRole(role.getIdLong())) { 34 | context.getTypedMessaging().replySuccess(context.i18n("commands.groupperms.link.success", group.getName(), role.getName())); 35 | } else { 36 | context.getTypedMessaging().replyWarning(context.i18n("commands.groupperms.link.fail", group.getName(), role.getName())); 37 | } 38 | }, sender.getIdLong()); 39 | } 40 | 41 | @Override 42 | public String command() { 43 | return "link"; 44 | } 45 | 46 | @Override 47 | public String parent() { 48 | return "groupperms"; 49 | } 50 | 51 | @Override 52 | public CascadePermission permission() { 53 | return CascadePermission.of("permissions.group.link", false, Module.MANAGEMENT); 54 | } 55 | 56 | @Override 57 | public String description() { 58 | return null; 59 | } 60 | 61 | } 62 | -------------------------------------------------------------------------------- /src/main/java/org/cascadebot/cascadebot/commands/management/permission/GroupPermissionRemoveSubCommand.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019 CascadeBot. All rights reserved. 3 | * Licensed under the MIT license. 4 | */ 5 | 6 | package org.cascadebot.cascadebot.commands.management.permission; 7 | 8 | import net.dv8tion.jda.api.entities.Member; 9 | import org.cascadebot.cascadebot.commandmeta.CommandContext; 10 | import org.cascadebot.cascadebot.commandmeta.Module; 11 | import org.cascadebot.cascadebot.commandmeta.SubCommand; 12 | import org.cascadebot.cascadebot.permissions.CascadePermission; 13 | import org.cascadebot.cascadebot.utils.PermissionCommandUtils; 14 | 15 | public class GroupPermissionRemoveSubCommand extends SubCommand { 16 | 17 | @Override 18 | public void onCommand(Member sender, CommandContext context) { 19 | if (context.getArgs().length < 2) { 20 | context.getUiMessaging().replyUsage(); 21 | return; 22 | } 23 | 24 | if (!context.getData().getPermissionsManager().isValidPermission(context.getArg(1))) { 25 | context.getTypedMessaging().replyDanger(context.i18n("responses.permission_not_exist", context.getArg(1))); 26 | return; 27 | } 28 | 29 | PermissionCommandUtils.tryGetGroupFromString(context, context.getArg(0), group -> { 30 | if (group.removePermission(context.getArg(1))) { 31 | context.getTypedMessaging().replySuccess(context.i18n("commands.groupperms.remove.success", context.getArg(1), group.getName() + "(" + group.getId() + ")")); 32 | } else { 33 | context.getTypedMessaging().replyWarning(context.i18n("commands.groupperms.remove.fail", context.getArg(1), group.getName() + "(" + group.getId() + ")")); 34 | } 35 | }, sender.getIdLong()); 36 | } 37 | 38 | @Override 39 | public String command() { 40 | return "remove"; 41 | } 42 | 43 | @Override 44 | public String parent() { 45 | return "groupperms"; 46 | } 47 | 48 | @Override 49 | public CascadePermission permission() { 50 | return CascadePermission.of("permissions.group.remove", false, Module.MANAGEMENT); 51 | } 52 | 53 | @Override 54 | public String description() { 55 | return null; 56 | } 57 | 58 | } 59 | -------------------------------------------------------------------------------- /src/main/java/org/cascadebot/cascadebot/commands/management/permission/GroupPermissionUnlinkRoleSubCommand.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019 CascadeBot. All rights reserved. 3 | * Licensed under the MIT license. 4 | */ 5 | 6 | package org.cascadebot.cascadebot.commands.management.permission; 7 | 8 | import net.dv8tion.jda.api.entities.Member; 9 | import net.dv8tion.jda.api.entities.Role; 10 | import org.cascadebot.cascadebot.commandmeta.CommandContext; 11 | import org.cascadebot.cascadebot.commandmeta.Module; 12 | import org.cascadebot.cascadebot.commandmeta.SubCommand; 13 | import org.cascadebot.cascadebot.permissions.CascadePermission; 14 | import org.cascadebot.cascadebot.utils.DiscordUtils; 15 | import org.cascadebot.cascadebot.utils.PermissionCommandUtils; 16 | 17 | public class GroupPermissionUnlinkRoleSubCommand extends SubCommand { 18 | 19 | @Override 20 | public void onCommand(Member sender, CommandContext context) { 21 | if (context.getArgs().length < 2) { 22 | context.getUiMessaging().replyUsage(); 23 | return; 24 | } 25 | 26 | Role role = DiscordUtils.getRole(context.getArg(1), context.getGuild()); 27 | if (role == null) { 28 | context.getTypedMessaging().replyDanger(context.i18n("responses.cannot_find_role_matching", context.getArg(1))); 29 | return; 30 | } 31 | 32 | PermissionCommandUtils.tryGetGroupFromString(context, context.getArg(0), group -> { 33 | if (group.unlinkRole(role.getIdLong())) { 34 | context.getTypedMessaging().replySuccess(context.i18n("commands.groupperms.unlink.success", group.getName(), role.getName())); 35 | } else { 36 | context.getTypedMessaging().replyWarning(context.i18n("commands.groupperms.unlink.fail", group.getName(), role.getName())); 37 | } 38 | }, sender.getIdLong()); 39 | } 40 | 41 | @Override 42 | public String command() { 43 | return "unlink"; 44 | } 45 | 46 | @Override 47 | public String parent() { 48 | return "groupperms"; 49 | } 50 | 51 | @Override 52 | public CascadePermission permission() { 53 | return CascadePermission.of("permissions.group.unlink", false, Module.MANAGEMENT); 54 | } 55 | 56 | @Override 57 | public String description() { 58 | return null; 59 | } 60 | 61 | } 62 | -------------------------------------------------------------------------------- /src/main/java/org/cascadebot/cascadebot/commands/management/permission/UserPermissionCommand.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019 CascadeBot. All rights reserved. 3 | * Licensed under the MIT license. 4 | */ 5 | 6 | package org.cascadebot.cascadebot.commands.management.permission; 7 | 8 | import net.dv8tion.jda.api.entities.Member; 9 | import org.cascadebot.cascadebot.commandmeta.CommandContext; 10 | import org.cascadebot.cascadebot.commandmeta.MainCommand; 11 | import org.cascadebot.cascadebot.commandmeta.Module; 12 | import org.cascadebot.cascadebot.commandmeta.SubCommand; 13 | import org.cascadebot.cascadebot.permissions.CascadePermission; 14 | 15 | import java.util.Set; 16 | 17 | public class UserPermissionCommand extends MainCommand { 18 | 19 | @Override 20 | public void onCommand(Member sender, CommandContext context) { 21 | context.getUiMessaging().replyUsage(); 22 | } 23 | 24 | @Override 25 | public String command() { 26 | return "userperms"; 27 | } 28 | 29 | @Override 30 | public CascadePermission permission() { 31 | return CascadePermission.of("permissions.user", false, Module.MANAGEMENT); 32 | } 33 | 34 | @Override 35 | public Set subCommands() { 36 | return Set.of(new UserPermissionAddSubCommand(), new UserPermissionRemoveSubCommand(), new UserPermissionGroupSubCommand(), 37 | new UserPermissionListSubCommand(), new UserPermissionTestSubCommand()); 38 | } 39 | 40 | @Override 41 | public String description() { 42 | return null; 43 | } 44 | 45 | @Override 46 | public Module module() { 47 | return Module.MANAGEMENT; 48 | } 49 | 50 | } 51 | -------------------------------------------------------------------------------- /src/main/java/org/cascadebot/cascadebot/commands/management/permission/UserPermissionRemoveSubCommand.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019 CascadeBot. All rights reserved. 3 | * Licensed under the MIT license. 4 | */ 5 | 6 | package org.cascadebot.cascadebot.commands.management.permission; 7 | 8 | import net.dv8tion.jda.api.entities.Member; 9 | import org.cascadebot.cascadebot.commandmeta.CommandContext; 10 | import org.cascadebot.cascadebot.commandmeta.Module; 11 | import org.cascadebot.cascadebot.commandmeta.SubCommand; 12 | import org.cascadebot.cascadebot.permissions.CascadePermission; 13 | import org.cascadebot.cascadebot.permissions.objects.User; 14 | import org.cascadebot.cascadebot.utils.DiscordUtils; 15 | 16 | public class UserPermissionRemoveSubCommand extends SubCommand { 17 | 18 | @Override 19 | public void onCommand(Member sender, CommandContext context) { 20 | if (context.getArgs().length < 2) { 21 | context.getUiMessaging().replyUsage(); 22 | return; 23 | } 24 | 25 | Member member = DiscordUtils.getMember(context.getGuild(), context.getArg(0)); 26 | if (member == null) { 27 | context.getTypedMessaging().replyDanger(context.i18n("responses.permission_not_exist", context.getArg(1))); 28 | return; 29 | } 30 | 31 | User user = context.getData().getManagement().getPermissions().getPermissionUser(member); 32 | 33 | if (user.removePermission(context.getArg(1))) { 34 | context.getTypedMessaging().replySuccess(context.i18n("commands.userperms.remove.success", context.getArg(1), member.getUser().getAsTag())); 35 | } else { 36 | context.getTypedMessaging().replyWarning(context.i18n("commands.userperms.remove.fail", context.getArg(1), member.getUser().getAsTag())); 37 | } 38 | } 39 | 40 | @Override 41 | public String command() { 42 | return "remove"; 43 | } 44 | 45 | @Override 46 | public String parent() { 47 | return "userperms"; 48 | } 49 | 50 | @Override 51 | public CascadePermission permission() { 52 | return CascadePermission.of("permissions.user.remove", false, Module.MANAGEMENT); 53 | } 54 | 55 | @Override 56 | public String description() { 57 | return null; 58 | } 59 | 60 | } 61 | -------------------------------------------------------------------------------- /src/main/java/org/cascadebot/cascadebot/commands/management/tag/TagCategorySubCommand.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019 CascadeBot. All rights reserved. 3 | * Licensed under the MIT license. 4 | */ 5 | 6 | package org.cascadebot.cascadebot.commands.management.tag; 7 | 8 | import net.dv8tion.jda.api.entities.Member; 9 | import org.cascadebot.cascadebot.commandmeta.CommandContext; 10 | import org.cascadebot.cascadebot.commandmeta.SubCommand; 11 | import org.cascadebot.cascadebot.data.objects.Tag; 12 | import org.cascadebot.cascadebot.permissions.CascadePermission; 13 | 14 | public class TagCategorySubCommand extends SubCommand { 15 | 16 | @Override 17 | public void onCommand(Member sender, CommandContext context) { 18 | if (context.getArgs().length < 2) { 19 | context.getUiMessaging().replyUsage(); 20 | return; 21 | } 22 | 23 | Tag tag = context.getData().getManagement().getTag(context.getArg(0)); 24 | 25 | String tagName = context.getArg(0).toLowerCase(); 26 | String category = context.getArg(1).toLowerCase(); 27 | 28 | if (tag == null) { 29 | context.getTypedMessaging().replyDanger(context.i18n("commands.tag.cannot_find_tag", tagName)); 30 | return; 31 | } 32 | 33 | tag.setCategory(category); 34 | context.getTypedMessaging().replySuccess(context.i18n("commands.tag.category.successfully_set_tag", tagName, category)); 35 | } 36 | 37 | @Override 38 | public String command() { 39 | return "category"; 40 | } 41 | 42 | @Override 43 | public String parent() { 44 | return "tag"; 45 | } 46 | 47 | @Override 48 | public CascadePermission permission() { 49 | return CascadePermission.of("tag.category", false); 50 | } 51 | 52 | } 53 | -------------------------------------------------------------------------------- /src/main/java/org/cascadebot/cascadebot/commands/management/tag/TagCreateSubCommand.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019 CascadeBot. All rights reserved. 3 | * Licensed under the MIT license. 4 | */ 5 | 6 | package org.cascadebot.cascadebot.commands.management.tag; 7 | 8 | import net.dv8tion.jda.api.entities.Member; 9 | import org.cascadebot.cascadebot.commandmeta.CommandContext; 10 | import org.cascadebot.cascadebot.commandmeta.SubCommand; 11 | import org.cascadebot.cascadebot.data.objects.Tag; 12 | import org.cascadebot.cascadebot.permissions.CascadePermission; 13 | 14 | public class TagCreateSubCommand extends SubCommand { 15 | 16 | @Override 17 | public void onCommand(Member sender, CommandContext context) { 18 | if (context.getArgs().length < 2) { 19 | context.getUiMessaging().replyUsage(); 20 | return; 21 | } 22 | 23 | // Warn if the original argument contains uppercase letters 24 | boolean warnUppercase = !context.getArg(0).equals(context.getArg(0).toLowerCase()); 25 | String tagName = context.getArg(0).toLowerCase(); 26 | 27 | if (context.getData().getManagement().hasTag(tagName)) { 28 | context.getTypedMessaging().replyDanger(context.i18n("commands.tag.create.tag_already_exists", tagName)); 29 | return; 30 | } 31 | 32 | String message = context.i18n("commands.tag.create.successfully_created_tag", tagName); 33 | 34 | if (warnUppercase) { 35 | message += "\n\n" + context.i18n("commands.tag.create.warn_uppercase"); 36 | } 37 | 38 | Tag tag = new Tag(context.getArg(0), context.getMessage(1), "tag"); 39 | context.getData().getManagement().addTag(context.getArg(0), tag); 40 | context.getData().getPermissionsManager().registerGuildPermission(tag.getInternalPermission()); 41 | context.getTypedMessaging().replySuccess(message); 42 | } 43 | 44 | @Override 45 | public String command() { 46 | return "create"; 47 | } 48 | 49 | @Override 50 | public String parent() { 51 | return "tag"; 52 | } 53 | 54 | @Override 55 | public CascadePermission permission() { 56 | return CascadePermission.of("tag.create", false); 57 | } 58 | 59 | } 60 | -------------------------------------------------------------------------------- /src/main/java/org/cascadebot/cascadebot/commands/management/tag/TagDeleteSubCommand.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019 CascadeBot. All rights reserved. 3 | * Licensed under the MIT license. 4 | */ 5 | 6 | package org.cascadebot.cascadebot.commands.management.tag; 7 | 8 | import net.dv8tion.jda.api.entities.Member; 9 | import org.cascadebot.cascadebot.commandmeta.CommandContext; 10 | import org.cascadebot.cascadebot.commandmeta.SubCommand; 11 | import org.cascadebot.cascadebot.permissions.CascadePermission; 12 | 13 | public class TagDeleteSubCommand extends SubCommand { 14 | 15 | @Override 16 | public void onCommand(Member sender, CommandContext context) { 17 | if (context.getArgs().length < 1) { 18 | context.getUiMessaging().replyUsage(); 19 | return; 20 | } 21 | 22 | String tagName = context.getArg(0).toLowerCase(); 23 | 24 | if (context.getData().getManagement().removeTag(tagName)) { 25 | context.getTypedMessaging().replySuccess(context.i18n("commands.tag.delete.successfully_deleted_tag")); 26 | } else { 27 | context.getTypedMessaging().replyDanger(context.i18n("commands.tag.delete.tag_doesnt_exist", tagName)); 28 | } 29 | } 30 | 31 | @Override 32 | public String command() { 33 | return "delete"; 34 | } 35 | 36 | @Override 37 | public String parent() { 38 | return "tag"; 39 | } 40 | 41 | @Override 42 | public CascadePermission permission() { 43 | return CascadePermission.of("tag.delete", false); 44 | } 45 | 46 | } 47 | -------------------------------------------------------------------------------- /src/main/java/org/cascadebot/cascadebot/commands/management/tag/TagEditSubCommand.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019 CascadeBot. All rights reserved. 3 | * Licensed under the MIT license. 4 | */ 5 | 6 | package org.cascadebot.cascadebot.commands.management.tag; 7 | 8 | import net.dv8tion.jda.api.entities.Member; 9 | import org.cascadebot.cascadebot.commandmeta.CommandContext; 10 | import org.cascadebot.cascadebot.commandmeta.SubCommand; 11 | import org.cascadebot.cascadebot.data.objects.Tag; 12 | import org.cascadebot.cascadebot.permissions.CascadePermission; 13 | 14 | public class TagEditSubCommand extends SubCommand { 15 | 16 | @Override 17 | public void onCommand(Member sender, CommandContext context) { 18 | if (context.getArgs().length < 2) { 19 | context.getUiMessaging().replyUsage(); 20 | return; 21 | } 22 | 23 | String tagName = context.getArg(0).toLowerCase(); 24 | 25 | Tag tag = context.getData().getManagement().getTag(tagName); 26 | if (tag == null) { 27 | context.getTypedMessaging().replyDanger(context.i18n("commands.tag.cannot_find_tag", tagName)); 28 | return; 29 | } 30 | 31 | tag.setContent(context.getMessage(1)); 32 | context.getTypedMessaging().replySuccess(context.i18n("commands.tag.edit.successfully_edited_tag", tagName)); 33 | } 34 | 35 | @Override 36 | public String command() { 37 | return "edit"; 38 | } 39 | 40 | @Override 41 | public String parent() { 42 | return "tag"; 43 | } 44 | 45 | @Override 46 | public CascadePermission permission() { 47 | return CascadePermission.of("tag.edit", false); 48 | } 49 | 50 | } 51 | -------------------------------------------------------------------------------- /src/main/java/org/cascadebot/cascadebot/commands/management/tag/TagListSubCommand.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019 CascadeBot. All rights reserved. 3 | * Licensed under the MIT license. 4 | */ 5 | 6 | package org.cascadebot.cascadebot.commands.management.tag; 7 | 8 | import net.dv8tion.jda.api.entities.Member; 9 | import org.cascadebot.cascadebot.commandmeta.CommandContext; 10 | import org.cascadebot.cascadebot.commandmeta.SubCommand; 11 | import org.cascadebot.cascadebot.data.objects.Tag; 12 | import org.cascadebot.cascadebot.permissions.CascadePermission; 13 | 14 | import java.util.Map; 15 | 16 | public class TagListSubCommand extends SubCommand { 17 | 18 | @Override 19 | public void onCommand(Member sender, CommandContext context) { 20 | Map tags = context.getData().getManagement().getTags(); 21 | 22 | if (tags.size() == 0) { 23 | context.getTypedMessaging().replyWarning(context.i18n("commands.tag.list.no_tags_found")); 24 | return; 25 | } 26 | 27 | StringBuilder builder = new StringBuilder(); 28 | for (Map.Entry tagEntry : tags.entrySet()) { 29 | builder.append(tagEntry.getKey()).append('\n'); 30 | } 31 | context.reply(builder.toString()); 32 | } 33 | 34 | @Override 35 | public String command() { 36 | return "list"; 37 | } 38 | 39 | @Override 40 | public String parent() { 41 | return "tag"; 42 | } 43 | 44 | @Override 45 | public CascadePermission permission() { 46 | return CascadePermission.of("tag.list", false); 47 | } 48 | 49 | } 50 | -------------------------------------------------------------------------------- /src/main/java/org/cascadebot/cascadebot/commands/management/tag/TagRawSubCommand.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019 CascadeBot. All rights reserved. 3 | * Licensed under the MIT license. 4 | */ 5 | 6 | package org.cascadebot.cascadebot.commands.management.tag; 7 | 8 | import net.dv8tion.jda.api.EmbedBuilder; 9 | import net.dv8tion.jda.api.entities.Member; 10 | import org.cascadebot.cascadebot.commandmeta.CommandContext; 11 | import org.cascadebot.cascadebot.commandmeta.SubCommand; 12 | import org.cascadebot.cascadebot.data.objects.Tag; 13 | import org.cascadebot.cascadebot.messaging.MessagingObjects; 14 | import org.cascadebot.cascadebot.permissions.CascadePermission; 15 | 16 | public class TagRawSubCommand extends SubCommand { 17 | 18 | @Override 19 | public void onCommand(Member sender, CommandContext context) { 20 | if (context.getArgs().length < 1) { 21 | context.getUiMessaging().replyUsage(); 22 | return; 23 | } 24 | 25 | String tagName = context.getArg(0).toLowerCase(); 26 | 27 | if (!context.getData().getManagement().hasTag(tagName)) { 28 | context.getTypedMessaging().replyDanger(context.i18n("commands.tag.cannot_find_tag", tagName)); 29 | return; 30 | } 31 | 32 | Tag tag = context.getData().getManagement().getTag(tagName); 33 | EmbedBuilder builder = MessagingObjects.getClearThreadLocalEmbedBuilder(); 34 | builder.setTitle(context.i18n("words.tag") + ": " + tagName); 35 | builder.setDescription("```" + tag.getContent() + "```"); 36 | builder.addField(context.i18n("words.category"), tag.getCategory(), true); 37 | 38 | context.getTypedMessaging().replyInfo(builder); 39 | } 40 | 41 | @Override 42 | public String command() { 43 | return "raw"; 44 | } 45 | 46 | @Override 47 | public String parent() { 48 | return "tag"; 49 | } 50 | 51 | @Override 52 | public CascadePermission permission() { 53 | return CascadePermission.of("tag.raw", false); 54 | } 55 | 56 | } 57 | -------------------------------------------------------------------------------- /src/main/java/org/cascadebot/cascadebot/commands/moderation/KickCommand.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019 CascadeBot. All rights reserved. 3 | * Licensed under the MIT license. 4 | */ 5 | 6 | package org.cascadebot.cascadebot.commands.moderation; 7 | 8 | import net.dv8tion.jda.api.Permission; 9 | import net.dv8tion.jda.api.entities.Member; 10 | import org.cascadebot.cascadebot.CascadeBot; 11 | import org.cascadebot.cascadebot.commandmeta.CommandContext; 12 | import org.cascadebot.cascadebot.commandmeta.MainCommand; 13 | import org.cascadebot.cascadebot.commandmeta.Module; 14 | import org.cascadebot.cascadebot.messaging.MessagingObjects; 15 | import org.cascadebot.cascadebot.permissions.CascadePermission; 16 | import org.cascadebot.cascadebot.utils.DiscordUtils; 17 | 18 | public class KickCommand extends MainCommand { 19 | 20 | @Override 21 | public void onCommand(Member sender, CommandContext context) { 22 | if (context.getArgs().length == 0) { 23 | context.getUiMessaging().replyUsage(); 24 | return; 25 | } 26 | 27 | Member targetMember = DiscordUtils.getMember(context.getGuild(), context.getArg(0)); 28 | 29 | if (targetMember == null) { 30 | context.getTypedMessaging().replyDanger(MessagingObjects.getStandardMessageEmbed(context.i18n("responses.cannot_find_user"), context.getUser(), context.getLocale())); 31 | return; 32 | } 33 | 34 | String reason = null; 35 | if (context.getArgs().length > 1) { 36 | reason = context.getMessage(1); 37 | } 38 | 39 | CascadeBot.INS.getModerationManager().kick( 40 | context, 41 | targetMember, 42 | sender, 43 | reason 44 | ); 45 | } 46 | 47 | @Override 48 | public String command() { 49 | return "kick"; 50 | } 51 | 52 | @Override 53 | public CascadePermission permission() { 54 | return CascadePermission.of("kick", false, Permission.KICK_MEMBERS); 55 | } 56 | 57 | @Override 58 | public Module module() { 59 | return Module.MODERATION; 60 | } 61 | 62 | } 63 | -------------------------------------------------------------------------------- /src/main/java/org/cascadebot/cascadebot/commands/moderation/PurgeAttachmentSubCommand.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019 CascadeBot. All rights reserved. 3 | * Licensed under the MIT license. 4 | */ 5 | 6 | package org.cascadebot.cascadebot.commands.moderation; 7 | 8 | import net.dv8tion.jda.api.entities.Member; 9 | import org.cascadebot.cascadebot.commandmeta.CommandContext; 10 | import org.cascadebot.cascadebot.commandmeta.SubCommand; 11 | import org.cascadebot.cascadebot.data.objects.PurgeCriteria; 12 | import org.cascadebot.cascadebot.permissions.CascadePermission; 13 | import org.cascadebot.cascadebot.utils.PurgeUtils; 14 | 15 | 16 | public class PurgeAttachmentSubCommand extends SubCommand { 17 | 18 | @Override 19 | public void onCommand(Member sender, CommandContext context) { 20 | if (context.getArgs().length < 1) { 21 | context.getUiMessaging().replyUsage(); 22 | return; 23 | } 24 | 25 | if (!context.isArgInteger(0)) { 26 | context.getUiMessaging().replyUsage(); 27 | return; 28 | } 29 | 30 | PurgeUtils.purge(context, PurgeCriteria.ATTACHMENT, context.getArgAsInteger(0), null); 31 | } 32 | 33 | @Override 34 | public String command() { 35 | return "attachment"; 36 | } 37 | 38 | @Override 39 | public String parent() { return "purge"; } 40 | 41 | @Override 42 | public CascadePermission permission() { return null; } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /src/main/java/org/cascadebot/cascadebot/commands/moderation/PurgeBotSubCommand.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019 CascadeBot. All rights reserved. 3 | * Licensed under the MIT license. 4 | */ 5 | 6 | package org.cascadebot.cascadebot.commands.moderation; 7 | 8 | import net.dv8tion.jda.api.entities.Member; 9 | import org.cascadebot.cascadebot.commandmeta.CommandContext; 10 | import org.cascadebot.cascadebot.commandmeta.SubCommand; 11 | import org.cascadebot.cascadebot.data.objects.PurgeCriteria; 12 | import org.cascadebot.cascadebot.permissions.CascadePermission; 13 | import org.cascadebot.cascadebot.utils.PurgeUtils; 14 | 15 | public class PurgeBotSubCommand extends SubCommand { 16 | 17 | @Override 18 | public void onCommand(Member sender, CommandContext context) { 19 | if (context.getArgs().length < 1) { 20 | context.getUiMessaging().replyUsage(); 21 | return; 22 | } 23 | 24 | if (!context.isArgInteger(0)) { 25 | context.getUiMessaging().replyUsage(); 26 | return; 27 | } 28 | 29 | PurgeUtils.purge(context, PurgeCriteria.BOT, context.getArgAsInteger(0), null); 30 | } 31 | 32 | @Override 33 | public String command() { 34 | return "bot"; 35 | } 36 | 37 | @Override 38 | public String parent() { return "purge"; } 39 | 40 | @Override 41 | public CascadePermission permission() { return null; } 42 | 43 | } 44 | -------------------------------------------------------------------------------- /src/main/java/org/cascadebot/cascadebot/commands/moderation/PurgeCommand.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019 CascadeBot. All rights reserved. 3 | * Licensed under the MIT license. 4 | */ 5 | 6 | package org.cascadebot.cascadebot.commands.moderation; 7 | 8 | import net.dv8tion.jda.api.Permission; 9 | import net.dv8tion.jda.api.entities.Member; 10 | import org.cascadebot.cascadebot.commandmeta.CommandContext; 11 | import org.cascadebot.cascadebot.commandmeta.MainCommand; 12 | import org.cascadebot.cascadebot.commandmeta.Module; 13 | import org.cascadebot.cascadebot.commandmeta.SubCommand; 14 | import org.cascadebot.cascadebot.data.objects.PurgeCriteria; 15 | import org.cascadebot.cascadebot.permissions.CascadePermission; 16 | import org.cascadebot.cascadebot.utils.PurgeUtils; 17 | 18 | import java.util.Set; 19 | 20 | public class PurgeCommand extends MainCommand { 21 | 22 | @Override 23 | public void onCommand(Member sender, CommandContext context) { 24 | if (context.getArgs().length < 1) { 25 | context.getUiMessaging().replyUsage(); 26 | return; 27 | } 28 | 29 | if (!context.isArgInteger(0)) { 30 | context.getUiMessaging().replyUsage(); 31 | return; 32 | } 33 | 34 | PurgeUtils.purge(context, PurgeCriteria.ALL, context.getArgAsInteger(0), null); 35 | } 36 | 37 | @Override 38 | public Module module() { 39 | return Module.MODERATION; 40 | } 41 | 42 | @Override 43 | public String command() { 44 | return "purge"; 45 | } 46 | 47 | @Override 48 | public Set subCommands() { 49 | return Set.of(new PurgeContainSubCommand(), new PurgeBotSubCommand(), new PurgeAttachmentSubCommand(), new PurgeLinkSubCommand(), new PurgeUserSubCommand()); 50 | } 51 | 52 | @Override 53 | public CascadePermission permission() { 54 | return CascadePermission.of("purge", false, Permission.MESSAGE_MANAGE); 55 | } 56 | 57 | } 58 | -------------------------------------------------------------------------------- /src/main/java/org/cascadebot/cascadebot/commands/moderation/PurgeContainSubCommand.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019 CascadeBot. All rights reserved. 3 | * Licensed under the MIT license. 4 | */ 5 | 6 | package org.cascadebot.cascadebot.commands.moderation; 7 | 8 | import net.dv8tion.jda.api.entities.Member; 9 | import org.cascadebot.cascadebot.commandmeta.CommandContext; 10 | import org.cascadebot.cascadebot.commandmeta.SubCommand; 11 | import org.cascadebot.cascadebot.data.objects.PurgeCriteria; 12 | import org.cascadebot.cascadebot.permissions.CascadePermission; 13 | import org.cascadebot.cascadebot.utils.PurgeUtils; 14 | 15 | 16 | public class PurgeContainSubCommand extends SubCommand { 17 | 18 | @Override 19 | public void onCommand(Member sender, CommandContext context) { 20 | if (context.getArgs().length < 2) { 21 | context.getUiMessaging().replyUsage(); 22 | return; 23 | } 24 | 25 | if (!context.isArgInteger(0)) { 26 | context.getUiMessaging().replyUsage(); 27 | return; 28 | } 29 | 30 | PurgeUtils.purge(context, PurgeCriteria.TOKEN, context.getArgAsInteger(0), context.getMessage(1)); 31 | } 32 | 33 | @Override 34 | public String command() { 35 | return "contains"; 36 | } 37 | 38 | @Override 39 | public String parent() { return "purge"; } 40 | 41 | @Override 42 | public CascadePermission permission() { return null; } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /src/main/java/org/cascadebot/cascadebot/commands/moderation/PurgeLinkSubCommand.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019 CascadeBot. All rights reserved. 3 | * Licensed under the MIT license. 4 | */ 5 | 6 | package org.cascadebot.cascadebot.commands.moderation; 7 | 8 | import net.dv8tion.jda.api.entities.Member; 9 | import org.cascadebot.cascadebot.commandmeta.CommandContext; 10 | import org.cascadebot.cascadebot.commandmeta.SubCommand; 11 | import org.cascadebot.cascadebot.data.objects.PurgeCriteria; 12 | import org.cascadebot.cascadebot.permissions.CascadePermission; 13 | import org.cascadebot.cascadebot.utils.PurgeUtils; 14 | 15 | 16 | public class PurgeLinkSubCommand extends SubCommand { 17 | 18 | @Override 19 | public void onCommand(Member sender, CommandContext context) { 20 | if (context.getArgs().length < 1) { 21 | context.getUiMessaging().replyUsage(); 22 | return; 23 | } 24 | 25 | if (!context.isArgInteger(0)) { 26 | context.getUiMessaging().replyUsage(); 27 | return; 28 | } 29 | 30 | PurgeUtils.purge(context, PurgeCriteria.LINK, context.getArgAsInteger(0), null); 31 | } 32 | 33 | @Override 34 | public String command() { 35 | return "link"; 36 | } 37 | 38 | @Override 39 | public String parent() { return "purge"; } 40 | 41 | @Override 42 | public CascadePermission permission() { return null; } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /src/main/java/org/cascadebot/cascadebot/commands/moderation/PurgeUserSubCommand.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019 CascadeBot. All rights reserved. 3 | * Licensed under the MIT license. 4 | */ 5 | 6 | package org.cascadebot.cascadebot.commands.moderation; 7 | 8 | import net.dv8tion.jda.api.entities.Member; 9 | import org.cascadebot.cascadebot.commandmeta.CommandContext; 10 | import org.cascadebot.cascadebot.commandmeta.SubCommand; 11 | import org.cascadebot.cascadebot.data.objects.PurgeCriteria; 12 | import org.cascadebot.cascadebot.permissions.CascadePermission; 13 | import org.cascadebot.cascadebot.utils.DiscordUtils; 14 | import org.cascadebot.cascadebot.utils.PurgeUtils; 15 | 16 | import java.util.ArrayList; 17 | import java.util.List; 18 | import java.util.stream.Collectors; 19 | 20 | 21 | public class PurgeUserSubCommand extends SubCommand { 22 | 23 | @Override 24 | public void onCommand(Member sender, CommandContext context) { 25 | if (context.getArgs().length < 2) { 26 | context.getUiMessaging().replyUsage(); 27 | return; 28 | } 29 | 30 | if (!context.isArgInteger(0)) { 31 | context.getUiMessaging().replyUsage(); 32 | return; 33 | } 34 | 35 | List members = new ArrayList<>(); 36 | 37 | for (int i = 0; i < context.getArgs().length; i++) { 38 | if (i < 1) continue; 39 | Member targetMember = null; 40 | targetMember = DiscordUtils.getMember(context.getGuild(), context.getArg(i)); 41 | if (targetMember == null) { 42 | continue; 43 | } 44 | members.add(targetMember); 45 | } 46 | 47 | if (members.isEmpty()) { 48 | context.getTypedMessaging().replyDanger(context.i18n("response.cannot_find_user")); 49 | return; 50 | } 51 | 52 | PurgeUtils.purge(context, PurgeCriteria.USER, context.getArgAsInteger(0), members.stream().map(Member::getId).collect(Collectors.joining(" "))); 53 | } 54 | 55 | @Override 56 | public String command() { 57 | return "user"; 58 | } 59 | 60 | @Override 61 | public String parent() { return "purge"; } 62 | 63 | @Override 64 | public CascadePermission permission() { return null; } 65 | 66 | } 67 | -------------------------------------------------------------------------------- /src/main/java/org/cascadebot/cascadebot/commands/moderation/SoftBanCommand.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019 CascadeBot. All rights reserved. 3 | * Licensed under the MIT license. 4 | */ 5 | 6 | package org.cascadebot.cascadebot.commands.moderation; 7 | 8 | import net.dv8tion.jda.api.Permission; 9 | import net.dv8tion.jda.api.entities.Member; 10 | import org.cascadebot.cascadebot.CascadeBot; 11 | import org.cascadebot.cascadebot.commandmeta.CommandContext; 12 | import org.cascadebot.cascadebot.commandmeta.MainCommand; 13 | import org.cascadebot.cascadebot.commandmeta.Module; 14 | import org.cascadebot.cascadebot.messaging.MessagingObjects; 15 | import org.cascadebot.cascadebot.permissions.CascadePermission; 16 | import org.cascadebot.cascadebot.utils.DiscordUtils; 17 | 18 | public class SoftBanCommand extends MainCommand { 19 | 20 | @Override 21 | public void onCommand(Member sender, CommandContext context) { 22 | if (context.getArgs().length == 0) { 23 | context.getTypedMessaging().replyDanger(context.i18n("responses.no_specified_user")); 24 | return; 25 | } 26 | 27 | Member targetMember = DiscordUtils.getMember(context.getGuild(), context.getArg(0)); 28 | if (targetMember == null) { 29 | context.getTypedMessaging().replyDanger(MessagingObjects.getStandardMessageEmbed(context.i18n("responses.cannot_find_user"), context.getUser(), context.getLocale())); 30 | return; 31 | } 32 | 33 | String reason = null; 34 | 35 | if (context.getArgs().length >= 2) { 36 | reason = context.getMessage(1); 37 | } 38 | 39 | CascadeBot.INS.getModerationManager().softBan( 40 | context, 41 | targetMember.getUser(), 42 | sender, 43 | reason, 44 | 7 // TODO 45 | ); 46 | 47 | } 48 | 49 | @Override 50 | public String command() { 51 | return "softban"; 52 | } 53 | 54 | @Override 55 | public CascadePermission permission() { 56 | return CascadePermission.of("softban", 57 | false, Permission.BAN_MEMBERS); 58 | } 59 | 60 | @Override 61 | public Module module() { 62 | return Module.MODERATION; 63 | } 64 | 65 | } 66 | -------------------------------------------------------------------------------- /src/main/java/org/cascadebot/cascadebot/commands/music/EqualizerResetSubCommand.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020 CascadeBot. All rights reserved. 3 | * Licensed under the MIT license. 4 | */ 5 | 6 | package org.cascadebot.cascadebot.commands.music; 7 | 8 | import com.sedmelluq.discord.lavaplayer.filter.equalizer.Equalizer; 9 | import net.dv8tion.jda.api.entities.Member; 10 | import org.cascadebot.cascadebot.CascadeBot; 11 | import org.cascadebot.cascadebot.commandmeta.CommandContext; 12 | import org.cascadebot.cascadebot.commandmeta.SubCommand; 13 | import org.cascadebot.cascadebot.music.CascadeLavalinkPlayer; 14 | import org.cascadebot.cascadebot.permissions.CascadePermission; 15 | 16 | import java.util.HashMap; 17 | import java.util.Map; 18 | 19 | public class EqualizerResetSubCommand extends SubCommand { 20 | 21 | @Override 22 | public void onCommand(Member sender, CommandContext context) { 23 | if (!CascadeBot.INS.getMusicHandler().getLavalinkEnabled()) { 24 | context.getTypedMessaging().replyDanger(context.i18n("commands.equalizer.not_lavalink")); 25 | return; 26 | } 27 | 28 | if (!(context.getMusicPlayer() instanceof CascadeLavalinkPlayer)) { 29 | context.getTypedMessaging().replyDanger(context.i18n("commands.equalizer.not_lavalink")); 30 | return; 31 | } 32 | 33 | Map bands = new HashMap<>(); 34 | for (int i = 0; i < Equalizer.BAND_COUNT; i++) { 35 | bands.put(i, 0.0f); 36 | } 37 | 38 | ((CascadeLavalinkPlayer) context.getMusicPlayer()).setBands(bands); 39 | context.getTypedMessaging().replySuccess(context.i18n("commands.equalizer.reset.success")); 40 | } 41 | 42 | @Override 43 | public String parent() { 44 | return "equalizer"; 45 | } 46 | 47 | @Override 48 | public String command() { 49 | return "reset"; 50 | } 51 | 52 | @Override 53 | public CascadePermission permission() { 54 | return CascadePermission.of("equalizer.reset", true); 55 | } 56 | 57 | } 58 | -------------------------------------------------------------------------------- /src/main/java/org/cascadebot/cascadebot/commands/music/LeaveCommand.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019 CascadeBot. All rights reserved. 3 | * Licensed under the MIT license. 4 | */ 5 | 6 | package org.cascadebot.cascadebot.commands.music; 7 | 8 | import net.dv8tion.jda.api.entities.Member; 9 | import net.dv8tion.jda.api.entities.VoiceChannel; 10 | import org.cascadebot.cascadebot.commandmeta.CommandContext; 11 | import org.cascadebot.cascadebot.commandmeta.MainCommand; 12 | import org.cascadebot.cascadebot.commandmeta.Module; 13 | import org.cascadebot.cascadebot.permissions.CascadePermission; 14 | 15 | public class LeaveCommand extends MainCommand { 16 | 17 | @Override 18 | public void onCommand(Member sender, CommandContext context) { 19 | VoiceChannel voiceChannel = context.getMusicPlayer().getConnectedChannel(); 20 | if (voiceChannel == null) { 21 | context.getTypedMessaging().replyDanger(context.i18n("responses.voice_not_connected")); 22 | return; 23 | } 24 | 25 | if (!sender.getVoiceState().inVoiceChannel() || !sender.getVoiceState().getChannel().equals(voiceChannel)) { 26 | if (!context.hasPermission("leave.other")) { 27 | context.getUiMessaging().sendPermissionError("leave.other"); 28 | return; 29 | } 30 | } 31 | context.getMusicPlayer().leave(); 32 | context.getTypedMessaging().replySuccess(context.i18n("commands.leave.successfully_left", voiceChannel.getName())); 33 | } 34 | 35 | @Override 36 | public Module module() { 37 | return Module.MUSIC; 38 | } 39 | 40 | @Override 41 | public String command() { 42 | return "leave"; 43 | } 44 | 45 | @Override 46 | public CascadePermission permission() { 47 | return CascadePermission.of("leave", true); 48 | } 49 | 50 | } 51 | -------------------------------------------------------------------------------- /src/main/java/org/cascadebot/cascadebot/commands/music/PauseCommand.java: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * * Copyright (c) 2019 CascadeBot. All rights reserved. 4 | * * Licensed under the MIT license. 5 | * 6 | */ 7 | 8 | package org.cascadebot.cascadebot.commands.music; 9 | 10 | import net.dv8tion.jda.api.entities.Member; 11 | import org.cascadebot.cascadebot.commandmeta.CommandContext; 12 | import org.cascadebot.cascadebot.commandmeta.MainCommand; 13 | import org.cascadebot.cascadebot.commandmeta.Module; 14 | import org.cascadebot.cascadebot.permissions.CascadePermission; 15 | 16 | public class PauseCommand extends MainCommand { 17 | 18 | @Override 19 | public void onCommand(Member sender, CommandContext context) { 20 | if (context.getMusicPlayer().isPaused()) { 21 | context.getTypedMessaging().replyDanger(context.i18n("commands.pause.already_paused", context.getCoreSettings().getPrefix())); 22 | } else { 23 | context.getMusicPlayer().setPaused(true); 24 | context.getTypedMessaging().replySuccess(context.i18n("commands.pause.successfully_paused", context.getCoreSettings().getPrefix())); 25 | } 26 | } 27 | 28 | @Override 29 | public Module module() { 30 | return Module.MUSIC; 31 | } 32 | 33 | @Override 34 | public String command() { 35 | return "pause"; 36 | } 37 | 38 | @Override 39 | public CascadePermission permission() { 40 | return CascadePermission.of("pause", true); 41 | } 42 | 43 | } 44 | -------------------------------------------------------------------------------- /src/main/java/org/cascadebot/cascadebot/commands/music/QueueRemoveSubCommand.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020 CascadeBot. All rights reserved. 3 | * Licensed under the MIT license. 4 | */ 5 | 6 | package org.cascadebot.cascadebot.commands.music; 7 | 8 | import net.dv8tion.jda.api.entities.Member; 9 | import org.cascadebot.cascadebot.commandmeta.CommandContext; 10 | import org.cascadebot.cascadebot.commandmeta.SubCommand; 11 | import org.cascadebot.cascadebot.permissions.CascadePermission; 12 | 13 | public class QueueRemoveSubCommand extends SubCommand { 14 | 15 | @Override 16 | public void onCommand(Member sender, CommandContext context) { 17 | if (context.getArgs().length == 0) { 18 | context.getUiMessaging().replyUsage(); 19 | return; 20 | } 21 | 22 | if (!context.isArgInteger(0)) { 23 | context.getTypedMessaging().replyDanger(context.i18n("commands.queue.remove.invalid_number", context.getArg(0))); 24 | return; 25 | } 26 | 27 | int index = context.getArgAsInteger(0) - 1; 28 | if (index < 0 || index >= context.getMusicPlayer().getQueue().size()) { 29 | context.getTypedMessaging().replyDanger(context.i18n("commands.queue.track_number", index + 1)); 30 | return; 31 | } 32 | 33 | context.getMusicPlayer().removeTrack(index); 34 | context.getTypedMessaging().replySuccess(context.i18n("commands.queue.remove.removed", index + 1)); 35 | } 36 | 37 | @Override 38 | public String command() { 39 | return "remove"; 40 | } 41 | 42 | @Override 43 | public CascadePermission permission() { 44 | return CascadePermission.of("queue.remove", false); 45 | } 46 | 47 | @Override 48 | public String parent() { 49 | return "queue"; 50 | } 51 | 52 | } 53 | -------------------------------------------------------------------------------- /src/main/java/org/cascadebot/cascadebot/commands/music/ResumeCommand.java: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * * Copyright (c) 2019 CascadeBot. All rights reserved. 4 | * * Licensed under the MIT license. 5 | * 6 | */ 7 | 8 | package org.cascadebot.cascadebot.commands.music; 9 | 10 | import net.dv8tion.jda.api.entities.Member; 11 | import org.cascadebot.cascadebot.commandmeta.CommandContext; 12 | import org.cascadebot.cascadebot.commandmeta.MainCommand; 13 | import org.cascadebot.cascadebot.commandmeta.Module; 14 | import org.cascadebot.cascadebot.permissions.CascadePermission; 15 | 16 | public class ResumeCommand extends MainCommand { 17 | 18 | @Override 19 | public void onCommand(Member sender, CommandContext context) { 20 | if (context.getMusicPlayer().isPaused()) { 21 | context.getMusicPlayer().setPaused(false); 22 | context.getTypedMessaging().replySuccess(context.i18n("commands.resume.successfully_resumed")); 23 | } else { 24 | context.getTypedMessaging().replyDanger(context.i18n("commands.resume.already_resumed", context.getCoreSettings().getPrefix())); 25 | } 26 | } 27 | 28 | @Override 29 | public Module module() { 30 | return Module.MUSIC; 31 | } 32 | 33 | @Override 34 | public String command() { 35 | return "resume"; 36 | } 37 | 38 | @Override 39 | public CascadePermission permission() { 40 | return CascadePermission.of("resume", true); 41 | } 42 | 43 | } 44 | -------------------------------------------------------------------------------- /src/main/java/org/cascadebot/cascadebot/commands/music/ShuffleCommand.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019 CascadeBot. All rights reserved. 3 | * Licensed under the MIT license. 4 | */ 5 | 6 | package org.cascadebot.cascadebot.commands.music; 7 | 8 | import net.dv8tion.jda.api.entities.Member; 9 | import org.cascadebot.cascadebot.commandmeta.CommandContext; 10 | import org.cascadebot.cascadebot.commandmeta.MainCommand; 11 | import org.cascadebot.cascadebot.commandmeta.Module; 12 | import org.cascadebot.cascadebot.permissions.CascadePermission; 13 | 14 | public class ShuffleCommand extends MainCommand { 15 | 16 | @Override 17 | public void onCommand(Member sender, CommandContext context) { 18 | if (context.getMusicPlayer().toggleShuffleOnRepeat()) { 19 | context.getMusicPlayer().shuffle(); 20 | context.getTypedMessaging().replySuccess(context.i18n("commands.shuffle.enabled")); 21 | } else { 22 | context.getTypedMessaging().replySuccess(context.i18n("commands.shuffle.disabled")); 23 | } 24 | } 25 | 26 | @Override 27 | public Module module() { 28 | return Module.MUSIC; 29 | } 30 | 31 | @Override 32 | public String command() { 33 | return "shuffle"; 34 | } 35 | 36 | @Override 37 | public CascadePermission permission() { 38 | return CascadePermission.of("shuffle", true); 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/org/cascadebot/cascadebot/commands/music/StopCommand.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019 CascadeBot. All rights reserved. 3 | * Licensed under the MIT license. 4 | */ 5 | 6 | package org.cascadebot.cascadebot.commands.music; 7 | 8 | import net.dv8tion.jda.api.entities.Member; 9 | import org.cascadebot.cascadebot.commandmeta.CommandContext; 10 | import org.cascadebot.cascadebot.commandmeta.MainCommand; 11 | import org.cascadebot.cascadebot.commandmeta.Module; 12 | import org.cascadebot.cascadebot.permissions.CascadePermission; 13 | 14 | public class StopCommand extends MainCommand { 15 | 16 | @Override 17 | public void onCommand(Member sender, CommandContext context) { 18 | if (context.getMusicPlayer().getPlayingTrack() != null) { // If the playing track isn't null, and the bot isn't paused 19 | context.getMusicPlayer().stop(); 20 | context.getTypedMessaging().replySuccess(context.i18n("commands.stop.stopped")); 21 | } else { 22 | context.getTypedMessaging().replyDanger(context.i18n("commands.stop.not_stopped")); 23 | } 24 | } 25 | 26 | @Override 27 | public Module module() { 28 | return Module.MUSIC; 29 | } 30 | 31 | @Override 32 | public String command() { 33 | return "stop"; 34 | } 35 | 36 | @Override 37 | public CascadePermission permission() { 38 | return CascadePermission.of("stop", false); 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/org/cascadebot/cascadebot/commands/useful/TodoAddUserSubCommand.java: -------------------------------------------------------------------------------- 1 | package org.cascadebot.cascadebot.commands.useful; 2 | 3 | import net.dv8tion.jda.api.entities.Member; 4 | import org.cascadebot.cascadebot.commandmeta.CommandContext; 5 | import org.cascadebot.cascadebot.commandmeta.SubCommand; 6 | import org.cascadebot.cascadebot.data.objects.TodoList; 7 | import org.cascadebot.cascadebot.permissions.CascadePermission; 8 | import org.cascadebot.cascadebot.utils.DiscordUtils; 9 | 10 | public class TodoAddUserSubCommand extends SubCommand { 11 | 12 | @Override 13 | public void onCommand(Member sender, CommandContext context) { 14 | if (context.getArgs().length < 2) { 15 | context.getUiMessaging().replyUsage(); 16 | return; 17 | } 18 | 19 | String todoName = context.getArg(0).toLowerCase(); 20 | TodoList todoList = context.getData().getUseful().getTodoList(todoName); 21 | 22 | if (todoList == null) { 23 | context.getTypedMessaging().replyDanger(context.i18n("commands.todo.list_does_not_exist", todoName)); 24 | return; 25 | } 26 | 27 | if (todoList.getOwnerId() != context.getMember().getIdLong()) { 28 | context.getTypedMessaging().replyDanger(context.i18n("commands.todo.owner_only")); 29 | return; 30 | } 31 | 32 | //TODO allow multiple users to be added/removed at once 33 | Member target = DiscordUtils.getMember(context.getGuild(), context.getArg(1)); 34 | 35 | if (target == null) { 36 | context.getTypedMessaging().replyDanger(context.i18n("commands.todo.user_not_found", context.getArg(1))); 37 | return; 38 | } 39 | 40 | todoList.addEditUser(target); 41 | 42 | context.getTypedMessaging().replySuccess(context.i18n("commands.todo.adduser.added", target.getUser().getAsTag(), todoName)); 43 | 44 | } 45 | 46 | @Override 47 | public String command() { 48 | return "adduser"; 49 | } 50 | 51 | @Override 52 | public CascadePermission permission() { 53 | return CascadePermission.of("todo.add.user", true); 54 | } 55 | 56 | @Override 57 | public String parent() { 58 | return "todo"; 59 | } 60 | 61 | } 62 | -------------------------------------------------------------------------------- /src/main/java/org/cascadebot/cascadebot/commands/useful/TodoCommand.java: -------------------------------------------------------------------------------- 1 | package org.cascadebot.cascadebot.commands.useful; 2 | 3 | import net.dv8tion.jda.api.entities.Member; 4 | import org.cascadebot.cascadebot.commandmeta.CommandContext; 5 | import org.cascadebot.cascadebot.commandmeta.MainCommand; 6 | import org.cascadebot.cascadebot.commandmeta.Module; 7 | import org.cascadebot.cascadebot.commandmeta.SubCommand; 8 | import org.cascadebot.cascadebot.permissions.CascadePermission; 9 | 10 | import java.util.Set; 11 | 12 | public class TodoCommand extends MainCommand { 13 | 14 | @Override 15 | public void onCommand(Member sender, CommandContext context) { 16 | context.getUiMessaging().replyUsage(); 17 | } 18 | 19 | @Override 20 | public String command() { 21 | return "todo"; 22 | } 23 | 24 | @Override 25 | public Module module() { 26 | return Module.USEFUL; 27 | } 28 | 29 | @Override 30 | public CascadePermission permission() { 31 | return CascadePermission.of("todo", true); 32 | } 33 | 34 | @Override 35 | public Set subCommands() { 36 | return Set.of(new TodoCreateSubCommand(), new TodoAddSubCommand(), new TodoRemoveSubCommand(), new TodoAddUserSubCommand(), new TodoRemoveUserSubCommand(), new TodoViewSubCommand(), new TodoSendSubCommand()); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/org/cascadebot/cascadebot/commands/useful/TodoCreateSubCommand.java: -------------------------------------------------------------------------------- 1 | package org.cascadebot.cascadebot.commands.useful; 2 | 3 | import net.dv8tion.jda.api.entities.Member; 4 | import org.cascadebot.cascadebot.commandmeta.CommandContext; 5 | import org.cascadebot.cascadebot.commandmeta.SubCommand; 6 | import org.cascadebot.cascadebot.data.objects.TodoList; 7 | import org.cascadebot.cascadebot.permissions.CascadePermission; 8 | 9 | public class TodoCreateSubCommand extends SubCommand { 10 | 11 | @Override 12 | public void onCommand(Member sender, CommandContext context) { 13 | if (context.getArgs().length == 0) { 14 | context.getUiMessaging().replyUsage(); 15 | return; 16 | } 17 | 18 | // Warn if the original argument contains uppercase letters 19 | boolean warnUppercase = !context.getArg(0).equals(context.getArg(0).toLowerCase()); 20 | String todoName = context.getArg(0).toLowerCase(); 21 | TodoList todoList = context.getData().getUseful().createTodoList(todoName, context.getMember().getIdLong()); 22 | 23 | if (todoList == null) { 24 | context.getTypedMessaging().replyDanger(context.i18n("commands.todo.create.list_exists")); 25 | return; 26 | } 27 | 28 | String message = context.i18n("commands.todo.create.created", todoName); 29 | 30 | if (warnUppercase) { 31 | message += "\n\n" + context.i18n("commands.todo.create.warn_uppercase", todoName); 32 | } 33 | 34 | context.getTypedMessaging().replySuccess(message); 35 | } 36 | 37 | @Override 38 | public String command() { 39 | return "create"; 40 | } 41 | 42 | @Override 43 | public String parent() { 44 | return "todo"; 45 | } 46 | 47 | @Override 48 | public CascadePermission permission() { 49 | return CascadePermission.of("todo.create", true); 50 | } 51 | 52 | } 53 | -------------------------------------------------------------------------------- /src/main/java/org/cascadebot/cascadebot/commands/useful/TodoRemoveUserSubCommand.java: -------------------------------------------------------------------------------- 1 | package org.cascadebot.cascadebot.commands.useful; 2 | 3 | import net.dv8tion.jda.api.entities.Member; 4 | import org.cascadebot.cascadebot.commandmeta.CommandContext; 5 | import org.cascadebot.cascadebot.commandmeta.SubCommand; 6 | import org.cascadebot.cascadebot.data.objects.TodoList; 7 | import org.cascadebot.cascadebot.permissions.CascadePermission; 8 | import org.cascadebot.cascadebot.utils.DiscordUtils; 9 | 10 | public class TodoRemoveUserSubCommand extends SubCommand { 11 | 12 | @Override 13 | public void onCommand(Member sender, CommandContext context) { 14 | if (context.getArgs().length < 2) { 15 | context.getUiMessaging().replyUsage(); 16 | return; 17 | } 18 | 19 | String todoName = context.getArg(0).toLowerCase(); 20 | TodoList todoList = context.getData().getUseful().getTodoList(todoName); 21 | 22 | if (todoList == null) { 23 | context.getTypedMessaging().replyDanger(context.i18n("commands.todo.list_does_not_exist", todoName)); 24 | return; 25 | } 26 | 27 | if (todoList.getOwnerId() != context.getMember().getIdLong()) { 28 | context.getTypedMessaging().replyDanger(context.i18n("commands.todo.owner_only")); 29 | return; 30 | } 31 | 32 | //TODO allow multiple users to be added/removed at once 33 | Member target = DiscordUtils.getMember(context.getGuild(), context.getArg(1)); 34 | 35 | if (target == null) { 36 | context.getTypedMessaging().replyDanger(context.i18n("commands.todo.user_not_found", context.getArg(1))); 37 | return; 38 | } 39 | 40 | todoList.removeEditUser(target); 41 | 42 | context.getTypedMessaging().replySuccess(context.i18n("commands.todo.removeuser.removed", target.getUser().getAsTag(), todoName)); 43 | 44 | } 45 | 46 | @Override 47 | public String command() { 48 | return "removeuser"; 49 | } 50 | 51 | @Override 52 | public CascadePermission permission() { 53 | return CascadePermission.of("todo.remove.user", true); 54 | } 55 | 56 | @Override 57 | public String parent() { 58 | return "todo"; 59 | } 60 | 61 | } 62 | -------------------------------------------------------------------------------- /src/main/java/org/cascadebot/cascadebot/data/database/DebugLogCallback.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019 CascadeBot. All rights reserved. 3 | * Licensed under the MIT license. 4 | */ 5 | 6 | package org.cascadebot.cascadebot.data.database; 7 | 8 | import com.mongodb.async.SingleResultCallback; 9 | import org.slf4j.LoggerFactory; 10 | import org.slf4j.event.Level; 11 | 12 | public class DebugLogCallback implements SingleResultCallback { 13 | 14 | private final Level LEVEL = Level.DEBUG; 15 | private final Object OBJECT_TO_LOG; 16 | private final String MESSAGE; 17 | 18 | public DebugLogCallback(Object toLog) { 19 | this.OBJECT_TO_LOG = toLog; 20 | this.MESSAGE = ""; 21 | } 22 | 23 | public DebugLogCallback(String message, Object toLog) { 24 | this.OBJECT_TO_LOG = toLog; 25 | this.MESSAGE = message; 26 | } 27 | 28 | @Override 29 | public void onResult(T result, Throwable t) { 30 | if (t != null) { 31 | LoggerFactory.getLogger(DebugLogCallback.class).error("Error in a Mongo callback", t); 32 | } else if (OBJECT_TO_LOG != null) { 33 | LoggerFactory.getLogger(DebugLogCallback.class).debug(MESSAGE + ": " + OBJECT_TO_LOG.toString().replace("\n", "")); 34 | } 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/org/cascadebot/cascadebot/data/database/IAsyncMongoTask.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019 CascadeBot. All rights reserved. 3 | * Licensed under the MIT license. 4 | */ 5 | 6 | package org.cascadebot.cascadebot.data.database; 7 | 8 | import com.mongodb.async.client.MongoDatabase; 9 | 10 | @FunctionalInterface 11 | public interface IAsyncMongoTask { 12 | 13 | public void run(MongoDatabase database); 14 | 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/org/cascadebot/cascadebot/data/database/IMongoTask.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019 CascadeBot. All rights reserved. 3 | * Licensed under the MIT license. 4 | */ 5 | 6 | package org.cascadebot.cascadebot.data.database; 7 | 8 | import com.mongodb.client.MongoDatabase; 9 | 10 | @FunctionalInterface 11 | public interface IMongoTask { 12 | 13 | public void run(MongoDatabase database); 14 | 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/org/cascadebot/cascadebot/data/language/Locale.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019 CascadeBot. All rights reserved. 3 | * Licensed under the MIT license. 4 | */ 5 | 6 | package org.cascadebot.cascadebot.data.language; 7 | 8 | import com.ibm.icu.util.ULocale; 9 | import org.cascadebot.cascadebot.CascadeBot; 10 | 11 | import java.io.InputStream; 12 | 13 | public enum Locale { 14 | 15 | ENGLISH_UK(ULocale.UK), 16 | ENGLISH_US(ULocale.US); 17 | 18 | private ULocale locale; 19 | 20 | Locale(ULocale locale) { 21 | this.locale = locale; 22 | } 23 | 24 | public String getDisplayName() { 25 | return getDisplayName(false); 26 | } 27 | 28 | public String getDisplayName(boolean localised) { 29 | if (localised) return locale.getDisplayName(locale); 30 | return locale.getDisplayName(); 31 | } 32 | 33 | public String getLanguageCode() { 34 | return locale.toLanguageTag(); 35 | } 36 | 37 | public String getLanguage() { 38 | return locale.getLanguage(); 39 | } 40 | 41 | public String getLanguageFileName() { 42 | return getLanguageCode() + ".json"; 43 | } 44 | 45 | public InputStream getLanguageFile() { 46 | return CascadeBot.class.getClassLoader().getResourceAsStream("lang/" + getLanguageFileName()); 47 | } 48 | 49 | public String i18n(String path, Object... objects) { 50 | return Language.i18n(this, path, objects); 51 | } 52 | 53 | public static Locale getDefaultLocale() { 54 | return ENGLISH_UK; 55 | } 56 | 57 | public ULocale getULocale() { 58 | return locale; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/main/java/org/cascadebot/cascadebot/data/objects/Flag.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019 CascadeBot. All rights reserved. 3 | * Licensed under the MIT license. 4 | */ 5 | 6 | package org.cascadebot.cascadebot.data.objects; 7 | 8 | public enum Flag { 9 | 10 | BETA, 11 | SPOTIFY, 12 | MUSIC_SERVICES 13 | 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/org/cascadebot/cascadebot/data/objects/GuildModeration.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019 CascadeBot. All rights reserved. 3 | * Licensed under the MIT license. 4 | */ 5 | 6 | package org.cascadebot.cascadebot.data.objects; 7 | 8 | public class GuildModeration { 9 | 10 | 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/org/cascadebot/cascadebot/data/objects/GuildSettingsUseful.java: -------------------------------------------------------------------------------- 1 | package org.cascadebot.cascadebot.data.objects; 2 | 3 | import org.cascadebot.cascadebot.commandmeta.Module; 4 | 5 | import java.util.Map; 6 | import java.util.concurrent.ConcurrentHashMap; 7 | 8 | @SettingsContainer(module = Module.USEFUL) 9 | public class GuildSettingsUseful { 10 | 11 | private Map todoLists = new ConcurrentHashMap<>(); 12 | 13 | //region todo list stuff 14 | public TodoList getTodoList(String name) { 15 | return todoLists.get(name); 16 | } 17 | 18 | public TodoList createTodoList(String name, long owner) { 19 | if (todoLists.containsKey(name)) { 20 | return null; 21 | } 22 | TodoList todoList = new TodoList(owner); 23 | todoLists.put(name, todoList); 24 | return todoList; 25 | } 26 | 27 | public void deleteTodoList(String name) { 28 | todoLists.remove(name); 29 | } 30 | 31 | public TodoList getTodoListByMessage(long messageId) { 32 | TodoList list = null; 33 | for (Map.Entry listEntry : todoLists.entrySet()) { 34 | if (listEntry.getValue().getMessageId() == messageId) { 35 | list = listEntry.getValue(); 36 | } 37 | } 38 | 39 | return list; 40 | } 41 | //endregion 42 | 43 | } 44 | -------------------------------------------------------------------------------- /src/main/java/org/cascadebot/cascadebot/data/objects/PermissionObject.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020 CascadeBot. All rights reserved. 3 | * Licensed under the MIT license. 4 | */ 5 | 6 | package org.cascadebot.cascadebot.data.objects; 7 | 8 | import org.cascadebot.cascadebot.commandmeta.Module; 9 | import org.cascadebot.cascadebot.permissions.CascadePermission; 10 | 11 | /** 12 | * Represents a data object that contains a per guild permission 13 | */ 14 | public abstract class PermissionObject { 15 | abstract String getPermission(); 16 | 17 | abstract String getParent(); 18 | 19 | abstract Module cascadeModule(); 20 | 21 | public CascadePermission getInternalPermission() { 22 | return CascadePermission.of(getParent() + "." + getPermission(), false, cascadeModule()); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/org/cascadebot/cascadebot/data/objects/Playlist.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019 CascadeBot. All rights reserved. 3 | * Licensed under the MIT license. 4 | */ 5 | 6 | package org.cascadebot.cascadebot.data.objects; 7 | 8 | import de.bild.codec.annotations.Id; 9 | import lombok.AccessLevel; 10 | import lombok.Getter; 11 | import lombok.NoArgsConstructor; 12 | import lombok.Setter; 13 | import org.bson.types.ObjectId; 14 | 15 | import java.util.List; 16 | 17 | @Getter 18 | @NoArgsConstructor(access = AccessLevel.PRIVATE) 19 | public class Playlist { 20 | 21 | @Id 22 | private ObjectId playlistId = ObjectId.get(); 23 | 24 | private String name; 25 | private long ownerId; 26 | private PlaylistType scope; 27 | 28 | @Setter 29 | private List tracks; 30 | 31 | public Playlist(long ownerId, String name, PlaylistType scope, List tracks) { 32 | this.ownerId = ownerId; 33 | this.name = name; 34 | this.scope = scope; 35 | this.tracks = tracks; 36 | } 37 | 38 | public void addTrack(String url) { 39 | tracks.add(url); 40 | } 41 | 42 | public void removeTrack(String url) { 43 | tracks.remove(url); 44 | } 45 | 46 | } 47 | -------------------------------------------------------------------------------- /src/main/java/org/cascadebot/cascadebot/data/objects/Setting.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019 CascadeBot. All rights reserved. 3 | * Licensed under the MIT license. 4 | */ 5 | 6 | package org.cascadebot.cascadebot.data.objects; 7 | 8 | import java.lang.annotation.ElementType; 9 | import java.lang.annotation.Retention; 10 | import java.lang.annotation.RetentionPolicy; 11 | import java.lang.annotation.Target; 12 | 13 | @Target({ElementType.FIELD}) 14 | @Retention(RetentionPolicy.RUNTIME) 15 | public @interface Setting { 16 | 17 | 18 | /** 19 | * The flag(s) required to have access to change this setting. 20 | */ 21 | Flag[] flagRequired() default {}; 22 | 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/org/cascadebot/cascadebot/data/objects/SettingsContainer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019 CascadeBot. All rights reserved. 3 | * Licensed under the MIT license. 4 | */ 5 | 6 | package org.cascadebot.cascadebot.data.objects; 7 | 8 | import org.cascadebot.cascadebot.commandmeta.Module; 9 | 10 | import java.lang.annotation.ElementType; 11 | import java.lang.annotation.Retention; 12 | import java.lang.annotation.RetentionPolicy; 13 | import java.lang.annotation.Target; 14 | 15 | @Target(ElementType.TYPE) 16 | @Retention(RetentionPolicy.RUNTIME) 17 | public @interface SettingsContainer { 18 | 19 | Module module(); 20 | 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/org/cascadebot/cascadebot/data/objects/Tag.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019 CascadeBot. All rights reserved. 3 | * Licensed under the MIT license. 4 | */ 5 | 6 | package org.cascadebot.cascadebot.data.objects; 7 | 8 | import lombok.AccessLevel; 9 | import lombok.AllArgsConstructor; 10 | import lombok.Getter; 11 | import lombok.NoArgsConstructor; 12 | import lombok.Setter; 13 | import org.cascadebot.cascadebot.commandmeta.CommandContext; 14 | import org.cascadebot.cascadebot.commandmeta.Module; 15 | import org.cascadebot.cascadebot.utils.placeholders.PlaceholderObjects; 16 | 17 | import java.util.regex.Pattern; 18 | 19 | @Setter 20 | @Getter 21 | @NoArgsConstructor(access = AccessLevel.PRIVATE) 22 | @AllArgsConstructor 23 | public class Tag extends PermissionObject { 24 | 25 | // https://regex101.com/r/hlsgVW/1 26 | private static final Pattern TAG_PATTERN = Pattern.compile("\\{([A-z]+)(?::((?:,?\\w+)+))?}"); 27 | 28 | private String name; 29 | private String content; 30 | private String category; 31 | 32 | public String formatTag(CommandContext commandContext) { 33 | return PlaceholderObjects.getTags().formatMessage(commandContext.getLocale(), content, commandContext); 34 | } 35 | 36 | @Override 37 | public String getPermission() { 38 | return category + "." + name; 39 | } 40 | 41 | @Override 42 | public String getParent() { 43 | return "tag"; 44 | } 45 | 46 | @Override 47 | public Module cascadeModule() { 48 | return Module.MANAGEMENT; 49 | } 50 | } -------------------------------------------------------------------------------- /src/main/java/org/cascadebot/cascadebot/events/GuildSaveListener.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019 CascadeBot. All rights reserved. 3 | * Licensed under the MIT license. 4 | */ 5 | 6 | package org.cascadebot.cascadebot.events; 7 | 8 | import com.github.benmanes.caffeine.cache.RemovalCause; 9 | import com.github.benmanes.caffeine.cache.RemovalListener; 10 | import org.cascadebot.cascadebot.CascadeBot; 11 | import org.cascadebot.cascadebot.data.managers.GuildDataManager; 12 | import org.cascadebot.cascadebot.data.objects.GuildData; 13 | 14 | import javax.annotation.Nonnull; 15 | import javax.annotation.Nullable; 16 | 17 | public class GuildSaveListener implements RemovalListener { 18 | 19 | @Override 20 | public void onRemoval(@Nullable Long aLong, @Nullable GuildData data, @Nonnull RemovalCause removalCause) { 21 | if (aLong == null) return; 22 | GuildDataManager.replace(aLong, data); 23 | CascadeBot.LOGGER.debug("Guild with ID: {} was saved to the database as it was removed from the map due to: {}", aLong, removalCause.toString()); 24 | // TODO: FUTURE: Use this for statistics? 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/org/cascadebot/cascadebot/events/JDAEventMetricsListener.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019 CascadeBot. All rights reserved. 3 | * Licensed under the MIT license. 4 | */ 5 | 6 | package org.cascadebot.cascadebot.events; 7 | 8 | import net.dv8tion.jda.api.events.GenericEvent; 9 | import net.dv8tion.jda.api.hooks.EventListener; 10 | import org.cascadebot.cascadebot.metrics.Metrics; 11 | 12 | public class JDAEventMetricsListener implements EventListener { 13 | 14 | @Override 15 | public void onEvent(GenericEvent event) { 16 | Metrics.INS.jdaEvents.labels(event.getClass().getSimpleName()).inc(); 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/org/cascadebot/cascadebot/messaging/MessagingTimed.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019 CascadeBot. All rights reserved. 3 | * Licensed under the MIT license. 4 | */ 5 | 6 | package org.cascadebot.cascadebot.messaging; 7 | 8 | import net.dv8tion.jda.api.entities.Message; 9 | import net.dv8tion.jda.api.entities.MessageEmbed; 10 | import net.dv8tion.jda.internal.utils.Checks; 11 | import org.cascadebot.cascadebot.commandmeta.CommandContext; 12 | 13 | public class MessagingTimed { 14 | 15 | private CommandContext context; 16 | 17 | public MessagingTimed(CommandContext context) { 18 | this.context = context; 19 | } 20 | 21 | /** 22 | * Sends a message that auto deletes itself after the specified delay (in milliseconds). 23 | * 24 | * @param message The string message to send which cannot be blank. 25 | * @param delay The amount of time to wait before it deletes itself. 26 | * @throws IllegalArgumentException if message is blank. 27 | */ 28 | public void sendAutoDeleteMessage(String message, long delay) { 29 | Checks.notBlank(message, "message"); 30 | Messaging.sendAutoDeleteMessage(context.getChannel(), message, delay); 31 | } 32 | 33 | /** 34 | * Sends a message that auto deletes itself after the specified delay (in milliseconds). 35 | * 36 | * @param embed The non-null {@link MessageEmbed} object to send. 37 | * @param delay The amount of time to wait before it deletes itself. 38 | */ 39 | public void sendAutoDeleteMessage(MessageEmbed embed, long delay) { 40 | Checks.notNull(embed, "embed"); 41 | Messaging.sendAutoDeleteMessage(context.getChannel(), embed, delay); 42 | } 43 | 44 | /** 45 | * Sends a message that auto deletes itself after the specified delay (in milliseconds). 46 | * 47 | * @param message The non-null {@link Message} object to send. 48 | * @param delay The amount of time to wait before it deletes itself. 49 | * @throws IllegalArgumentException if message is null. 50 | */ 51 | public void sendAutoDeleteMessage(Message message, long delay) { 52 | Checks.notNull(message, "message"); 53 | Messaging.sendAutoDeleteMessage(context.getChannel(), message, delay); 54 | } 55 | 56 | } 57 | -------------------------------------------------------------------------------- /src/main/java/org/cascadebot/cascadebot/messaging/NoOpWebhookClient.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019 CascadeBot. All rights reserved. 3 | * Licensed under the MIT license. 4 | */ 5 | 6 | package org.cascadebot.cascadebot.messaging; 7 | 8 | import club.minnced.discord.webhook.WebhookClient; 9 | import club.minnced.discord.webhook.receive.ReadonlyMessage; 10 | import club.minnced.discord.webhook.send.WebhookEmbed; 11 | import club.minnced.discord.webhook.send.WebhookMessage; 12 | import org.jetbrains.annotations.NotNull; 13 | 14 | import java.io.File; 15 | import java.io.InputStream; 16 | import java.util.Collection; 17 | import java.util.concurrent.CompletableFuture; 18 | 19 | public class NoOpWebhookClient extends WebhookClient { 20 | 21 | public NoOpWebhookClient() { 22 | super(-1, null, true, null, null); 23 | } 24 | 25 | @NotNull 26 | public CompletableFuture send(@NotNull WebhookMessage message) { 27 | return CompletableFuture.completedFuture(null); 28 | } 29 | 30 | @NotNull 31 | public CompletableFuture send(@NotNull File file) { 32 | return CompletableFuture.completedFuture(null); 33 | } 34 | 35 | @NotNull 36 | public CompletableFuture send(@NotNull File file, @NotNull String fileName) { 37 | return CompletableFuture.completedFuture(null); 38 | } 39 | 40 | @NotNull 41 | public CompletableFuture send(@NotNull byte[] data, @NotNull String fileName) { 42 | return CompletableFuture.completedFuture(null); 43 | } 44 | 45 | @NotNull 46 | public CompletableFuture send(@NotNull InputStream data, @NotNull String fileName) { 47 | return CompletableFuture.completedFuture(null); 48 | } 49 | 50 | @NotNull 51 | public CompletableFuture send(@NotNull WebhookEmbed first, @NotNull WebhookEmbed... embeds) { 52 | return CompletableFuture.completedFuture(null); 53 | } 54 | 55 | @NotNull 56 | public CompletableFuture send(@NotNull Collection embeds) { 57 | return CompletableFuture.completedFuture(null); 58 | } 59 | 60 | @NotNull 61 | public CompletableFuture send(@NotNull String content) { 62 | return CompletableFuture.completedFuture(null); 63 | } 64 | 65 | } 66 | -------------------------------------------------------------------------------- /src/main/java/org/cascadebot/cascadebot/moderation/ModAction.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019 CascadeBot. All rights reserved. 3 | * Licensed under the MIT license. 4 | */ 5 | 6 | package org.cascadebot.cascadebot.moderation; 7 | 8 | import lombok.AllArgsConstructor; 9 | import org.cascadebot.cascadebot.data.language.Language; 10 | import org.cascadebot.cascadebot.data.language.Locale; 11 | 12 | @AllArgsConstructor 13 | public enum ModAction { 14 | 15 | BAN("banned", true), // Bans a user 16 | UNBAN("unbanned", false), // Unbans a user 17 | SOFT_BAN("soft-banned", true), // Bans a user then unbans them, clears messages without actually banning them 18 | FORCE_BAN("forcefully banned", false), // Bans a user in a guild, even if the user isn't in the guild 19 | KICK("kicked", true), // Kicks a user from a guild 20 | MUTE("muted", true), // Mutes a user in a guild 21 | WARN("warned", true), // Warns a user in a guild 22 | TEMP_MUTE("temporarily muted", true), 23 | TEMP_BAN("temporarily banned", true); 24 | // TODO: Temp command ban? 25 | 26 | private String verb; 27 | private boolean requiresMember; 28 | 29 | // Only the localised version should be used 30 | private String getVerb() { 31 | return verb; 32 | } 33 | 34 | public String getVerb(Locale locale) { 35 | String path = "mod_actions." + name().toLowerCase() + ".verb"; 36 | if (!Language.hasLanguageEntry(locale, path)) { 37 | return getVerb(); 38 | } 39 | return Language.i18n(locale, path); 40 | } 41 | 42 | // Only the localised version should be used 43 | private String getName() { 44 | return name().toLowerCase().replace("_", "-"); 45 | } 46 | 47 | public String getName(Locale locale) { 48 | String path = "mod_actions." + name().toLowerCase() + ".name"; 49 | if (!Language.hasLanguageEntry(locale, path)) { 50 | return getName(); 51 | } 52 | return Language.i18n(locale, path); 53 | } 54 | 55 | public boolean doesRequireMember() { 56 | return requiresMember; 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/main/java/org/cascadebot/cascadebot/music/Captions.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020 CascadeBot. All rights reserved. 3 | * Licensed under the MIT license. 4 | */ 5 | 6 | package org.cascadebot.cascadebot.music; 7 | 8 | import lombok.AllArgsConstructor; 9 | import lombok.EqualsAndHashCode; 10 | import lombok.Getter; 11 | import lombok.ToString; 12 | 13 | import java.util.ArrayList; 14 | import java.util.Comparator; 15 | import java.util.List; 16 | import java.util.TreeSet; 17 | 18 | @ToString 19 | public class Captions { 20 | 21 | private static final int CAPTION_RANGE = 15; 22 | 23 | private TreeSet captionSet = new TreeSet<>(Comparator.comparing(Caption::getStart)); 24 | 25 | public List getCaptions(double position) { 26 | List captions = new ArrayList<>(); 27 | for (Caption caption : captionSet) { 28 | if (caption.start >= position && (caption.start + caption.duration) < (position + CAPTION_RANGE)) { 29 | captions.add(caption.text); 30 | } 31 | } 32 | return captions; 33 | } 34 | 35 | public void addCaption(String text, double start, double duration) { 36 | captionSet.add(new Caption(text, start, duration)); 37 | } 38 | 39 | @AllArgsConstructor 40 | @Getter 41 | @ToString 42 | @EqualsAndHashCode 43 | public class Caption { 44 | 45 | private final String text; 46 | private final double start; 47 | private final double duration; 48 | 49 | } 50 | 51 | } 52 | -------------------------------------------------------------------------------- /src/main/java/org/cascadebot/cascadebot/music/CaptionsTask.java: -------------------------------------------------------------------------------- 1 | package org.cascadebot.cascadebot.music; 2 | 3 | import lavalink.client.player.IPlayer; 4 | import net.dv8tion.jda.api.EmbedBuilder; 5 | import net.dv8tion.jda.api.entities.TextChannel; 6 | import org.cascadebot.cascadebot.CascadeBot; 7 | import org.cascadebot.cascadebot.data.language.Language; 8 | import org.cascadebot.cascadebot.messaging.MessageType; 9 | import org.cascadebot.cascadebot.messaging.MessagingObjects; 10 | import org.cascadebot.cascadebot.tasks.Task; 11 | 12 | import java.util.List; 13 | 14 | public class CaptionsTask extends Task { 15 | 16 | private final long guildId; 17 | private long channelId; 18 | private final long messageId; 19 | private final Captions captions; 20 | 21 | public CaptionsTask(long guildId, long channelId, long messageId, Captions captions) { 22 | super("captions-" + guildId); 23 | this.guildId = guildId; 24 | this.channelId = channelId; 25 | this.messageId = messageId; 26 | this.captions = captions; 27 | } 28 | 29 | @Override 30 | protected void execute() { 31 | 32 | IPlayer player = CascadeBot.INS.getMusicHandler().getPlayer(this.guildId); 33 | if (player.getPlayingTrack() == null) this.cancel(); 34 | 35 | List captionSet = this.captions.getCaptions((player.getPlayingTrack().getPosition() / 1000D)); 36 | EmbedBuilder embedBuilder = MessagingObjects.getMessageTypeEmbedBuilder(MessageType.INFO); 37 | if (!captionSet.isEmpty()) { 38 | embedBuilder.setDescription(String.join("\n", captionSet)); 39 | } else { 40 | embedBuilder.setDescription(Language.i18n(guildId, "commands.karaoke.no_lyrics_atm")); 41 | } 42 | 43 | TextChannel channel = CascadeBot.INS.getShardManager().getTextChannelById(this.channelId); 44 | if (channel != null) { 45 | channel.retrieveMessageById(this.messageId).queue(message -> { 46 | message.editMessage(embedBuilder.build()).override(true).queue(); 47 | }, error -> this.cancel()); 48 | } else { 49 | this.cancel(); 50 | } 51 | 52 | if (player.getPlayingTrack().getPosition() >= (player.getPlayingTrack().getDuration() - 15)) { 53 | this.cancel(); 54 | } 55 | 56 | } 57 | 58 | } 59 | -------------------------------------------------------------------------------- /src/main/java/org/cascadebot/cascadebot/music/LavaPlayerAudioSendHandler.java: -------------------------------------------------------------------------------- 1 | package org.cascadebot.cascadebot.music; 2 | 3 | import com.sedmelluq.discord.lavaplayer.player.AudioPlayer; 4 | import com.sedmelluq.discord.lavaplayer.track.playback.AudioFrame; 5 | import net.dv8tion.jda.api.audio.AudioSendHandler; 6 | 7 | import java.nio.ByteBuffer; 8 | 9 | 10 | /** 11 | * Taken from https://git.io/fjkTK 12 | */ 13 | public class LavaPlayerAudioSendHandler implements AudioSendHandler { 14 | 15 | private final AudioPlayer audioPlayer; 16 | private AudioFrame lastFrame; 17 | 18 | public LavaPlayerAudioSendHandler(AudioPlayer audioPlayer) { 19 | this.audioPlayer = audioPlayer; 20 | } 21 | 22 | @Override 23 | public boolean canProvide() { 24 | if (lastFrame == null) { 25 | lastFrame = audioPlayer.provide(); 26 | } 27 | 28 | return lastFrame != null; 29 | } 30 | 31 | @Override 32 | public ByteBuffer provide20MsAudio() { 33 | if (lastFrame == null) { 34 | lastFrame = audioPlayer.provide(); 35 | } 36 | 37 | byte[] data = lastFrame != null ? lastFrame.getData() : null; 38 | lastFrame = null; 39 | 40 | return data != null ? ByteBuffer.wrap(data) : null; 41 | } 42 | 43 | @Override 44 | public boolean isOpus() { 45 | return true; 46 | } 47 | 48 | } -------------------------------------------------------------------------------- /src/main/java/org/cascadebot/cascadebot/music/MovableAudioTrack.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020 CascadeBot. All rights reserved. 3 | * Licensed under the MIT license. 4 | */ 5 | 6 | package org.cascadebot.cascadebot.music; 7 | 8 | import com.sedmelluq.discord.lavaplayer.track.AudioTrack; 9 | import lombok.Getter; 10 | import org.cascadebot.cascadebot.utils.move.MovableItem; 11 | 12 | public class MovableAudioTrack implements MovableItem { 13 | 14 | @Getter 15 | private AudioTrack track; 16 | 17 | public MovableAudioTrack(AudioTrack track) { 18 | this.track = track; 19 | } 20 | 21 | @Override 22 | public String getItemText() { 23 | return track.getInfo().title; 24 | } 25 | 26 | @Override 27 | public boolean equals(Object obj) { // I need to override the equals operator so its checking if the audi tracks are equal, not if the movable one is 28 | if (obj instanceof MovableAudioTrack) { 29 | return track.equals(((MovableAudioTrack) obj).getTrack()); 30 | } 31 | return false; 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/org/cascadebot/cascadebot/music/TrackData.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020 CascadeBot. All rights reserved. 3 | * Licensed under the MIT license. 4 | */ 5 | 6 | package org.cascadebot.cascadebot.music; 7 | 8 | import lombok.AllArgsConstructor; 9 | import lombok.Getter; 10 | 11 | @Getter 12 | @AllArgsConstructor 13 | public class TrackData { 14 | 15 | private long userId; 16 | private long errorChannelId; 17 | private long guildId; 18 | 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/org/cascadebot/cascadebot/permissions/PermissionNode.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019 CascadeBot. All rights reserved. 3 | * Licensed under the MIT license. 4 | */ 5 | 6 | package org.cascadebot.cascadebot.permissions; 7 | 8 | import lombok.AllArgsConstructor; 9 | import lombok.Getter; 10 | 11 | import java.util.Arrays; 12 | import java.util.function.Predicate; 13 | import java.util.regex.Pattern; 14 | import java.util.stream.Collectors; 15 | 16 | // All credit to the FlareBot project for this file 17 | // https://github.com/FlareBot/FlareBot/blob/master/src/main/java/stream/flarebot/flarebot/permissions/PermissionNode.java 18 | @AllArgsConstructor 19 | @Getter 20 | public class PermissionNode implements Predicate { 21 | 22 | private final String node; 23 | 24 | @Override 25 | public boolean test(String permission) { 26 | if (getNode().equals("*")) 27 | return true; 28 | // It splits by a `*` that's on a start of a string or has . around them 29 | String textNode = Arrays.stream(getNode().split("(?:^\\*(\\.))|(?:(?<=\\.)\\*(?=\\.))|(?:(?<=\\.)\\*$)")) 30 | // Then it escapes all of that so its not regexps 31 | .map(Pattern::quote) 32 | // And then it joins them with a match all regexp 33 | .collect(Collectors.joining(".+")) + (getNode().endsWith("*") ? ".+" : ""); 34 | // And then it lets Java REGEXP compare them. Ty @I-Al-Istannen for making me do this comment 35 | return permission.matches(textNode); 36 | } 37 | 38 | } -------------------------------------------------------------------------------- /src/main/java/org/cascadebot/cascadebot/permissions/objects/Group.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019 CascadeBot. All rights reserved. 3 | * Licensed under the MIT license. 4 | */ 5 | 6 | package org.cascadebot.cascadebot.permissions.objects; 7 | 8 | import com.google.common.collect.Sets; 9 | import lombok.AccessLevel; 10 | import lombok.EqualsAndHashCode; 11 | import lombok.Getter; 12 | import lombok.NoArgsConstructor; 13 | import lombok.Setter; 14 | import lombok.ToString; 15 | import org.apache.commons.lang3.RandomStringUtils; 16 | 17 | import java.util.Set; 18 | 19 | @ToString(callSuper = true) 20 | @EqualsAndHashCode(callSuper = true) 21 | @NoArgsConstructor(access = AccessLevel.PRIVATE) 22 | public class Group extends PermissionHolder { 23 | 24 | // Base 55 with 5 chars gives 503284375 combinations, we should be ok for uniqueness 25 | // This is normal alphanumeric with similar characters removed for less errors when inputting 26 | @Getter 27 | private String id = RandomStringUtils.random(5, "abcdefghijkmnopqrstuvwxyzACDEFHJKLMNPRSTUVWXYZ123467890"); 28 | 29 | @Getter 30 | @Setter 31 | private String name; 32 | 33 | private Set roleIds = Sets.newConcurrentHashSet(); 34 | 35 | public Group(String name) { 36 | this.name = name; 37 | } 38 | 39 | public boolean linkRole(long roleId) { 40 | return roleIds.add(roleId); 41 | } 42 | 43 | public boolean unlinkRole(long roleId) { 44 | return roleIds.remove(roleId); 45 | } 46 | 47 | public Set getRoleIds() { 48 | return Set.copyOf(roleIds); 49 | } 50 | 51 | @Override 52 | HolderType getType() { 53 | return HolderType.GROUP; 54 | } 55 | 56 | } 57 | -------------------------------------------------------------------------------- /src/main/java/org/cascadebot/cascadebot/permissions/objects/PermissionHolder.java: -------------------------------------------------------------------------------- 1 | package org.cascadebot.cascadebot.permissions.objects; 2 | 3 | import com.google.common.collect.Sets; 4 | import lombok.EqualsAndHashCode; 5 | import lombok.ToString; 6 | import org.cascadebot.cascadebot.data.objects.PermissionAction; 7 | import org.cascadebot.cascadebot.permissions.CascadePermission; 8 | import org.cascadebot.cascadebot.permissions.PermissionNode; 9 | 10 | import java.util.Set; 11 | 12 | @ToString 13 | @EqualsAndHashCode 14 | public abstract class PermissionHolder { 15 | 16 | private Set permissions = Sets.newConcurrentHashSet(); 17 | 18 | abstract HolderType getType(); 19 | 20 | public Set getPermissions() { 21 | return Set.copyOf(permissions); 22 | } 23 | 24 | public boolean addPermission(String permission) { 25 | return permissions.add(permission); 26 | } 27 | 28 | public boolean removePermission(String permission) { 29 | return permissions.remove(permission); 30 | } 31 | 32 | public Result evaluatePermission(CascadePermission permission) { 33 | for (String perm : getPermissions()) { 34 | if (new PermissionNode(perm.substring(perm.startsWith("-") ? 1 : 0)).test(permission.getPermissionRaw())) { 35 | if (perm.startsWith("-")) 36 | return Result.of(PermissionAction.DENY, this); 37 | return Result.of(PermissionAction.ALLOW, this); 38 | } 39 | } 40 | return Result.of(PermissionAction.NEUTRAL, this); 41 | } 42 | 43 | enum HolderType { 44 | GROUP, USER 45 | } 46 | 47 | } 48 | -------------------------------------------------------------------------------- /src/main/java/org/cascadebot/cascadebot/permissions/objects/User.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019 CascadeBot. All rights reserved. 3 | * Licensed under the MIT license. 4 | */ 5 | 6 | package org.cascadebot.cascadebot.permissions.objects; 7 | 8 | import com.google.common.collect.Sets; 9 | import lombok.EqualsAndHashCode; 10 | import lombok.ToString; 11 | 12 | import java.util.Set; 13 | 14 | @ToString(callSuper = true) 15 | @EqualsAndHashCode(callSuper = true) 16 | public class User extends PermissionHolder { 17 | 18 | private final Set groups = Sets.newConcurrentHashSet(); 19 | 20 | public boolean addGroup(Group group) { 21 | return groups.add(group.getId()); 22 | } 23 | 24 | public boolean removeGroup(Group group) { 25 | return groups.remove(group.getId()); 26 | } 27 | 28 | public Set getGroupIds() { 29 | return Set.copyOf(groups); 30 | } 31 | 32 | @Override 33 | HolderType getType() { 34 | return HolderType.USER; 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/org/cascadebot/cascadebot/utils/CollectionUtils.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019 CascadeBot. All rights reserved. 3 | * Licensed under the MIT license. 4 | */ 5 | 6 | package org.cascadebot.cascadebot.utils; 7 | 8 | import lombok.experimental.UtilityClass; 9 | 10 | import java.util.Arrays; 11 | import java.util.Collection; 12 | import java.util.HashMap; 13 | import java.util.HashSet; 14 | import java.util.Map; 15 | import java.util.Set; 16 | import java.util.function.Function; 17 | 18 | @UtilityClass 19 | public class CollectionUtils { 20 | 21 | public static Set hashSet(E... e) { 22 | return new HashSet<>(Arrays.asList(e)); 23 | } 24 | 25 | public static Set hashSet(Collection eCollection) { 26 | return new HashSet<>(eCollection); 27 | } 28 | 29 | /** 30 | * Returns a lookup map for an enum, using the passed transform function. 31 | * 32 | * @param clazz The clazz of the enum 33 | * @param mapper The mapper. Must be bijective as it otherwise overwrites keys/values. 34 | * @param the enum type 35 | * @param the type of map key 36 | * @return a map with the given key and the enum value associated with it 37 | * @apiNote Thanks to I Al Istannen#1564 for this 38 | */ 39 | public static Map getReverseMapping(Class clazz, Function mapper) { 40 | Map result = new HashMap<>(); 41 | 42 | for (T t : clazz.getEnumConstants()) { 43 | result.put(mapper.apply(t), t); 44 | } 45 | 46 | return result; 47 | } 48 | 49 | } 50 | -------------------------------------------------------------------------------- /src/main/java/org/cascadebot/cascadebot/utils/RandomUtils.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019 CascadeBot. All rights reserved. 3 | * Licensed under the MIT license. 4 | */ 5 | 6 | 7 | package org.cascadebot.cascadebot.utils; 8 | 9 | import com.google.gson.JsonElement; 10 | import lombok.Getter; 11 | import lombok.experimental.UtilityClass; 12 | 13 | import java.awt.Color; 14 | import java.io.IOException; 15 | import java.util.Random; 16 | 17 | @UtilityClass 18 | public class RandomUtils { 19 | 20 | @Getter 21 | private static final Random random = new Random(); 22 | 23 | @Getter 24 | private static final String[] characters = {"0","1","2","3","4","5","6","7","8","9","A","B","C","D","E","F"}; 25 | 26 | public static int randomNumber(int min, int max) { 27 | return random.nextInt(max - min) + min; 28 | } 29 | 30 | public static int randomNumber(int max) { 31 | return random.nextInt(max); 32 | } 33 | 34 | public static String randomChoice(String... choices) { 35 | return (choices[random.nextInt(choices.length)]); 36 | } 37 | 38 | public static Color randomColor() { 39 | return Color.getHSBColor(random.nextFloat(), random.nextFloat(), random.nextFloat()); 40 | } 41 | 42 | public String randomJoke() throws IOException, IllegalArgumentException { 43 | JsonElement jsonElement = WebUtils.getJsonFromURL("https://icanhazdadjoke.com/"); 44 | return jsonElement.getAsJsonObject().get("joke").getAsString(); 45 | } 46 | 47 | } 48 | -------------------------------------------------------------------------------- /src/main/java/org/cascadebot/cascadebot/utils/ReflectionUtils.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019 CascadeBot. All rights reserved. 3 | * Licensed under the MIT license. 4 | */ 5 | 6 | package org.cascadebot.cascadebot.utils; 7 | 8 | import com.google.common.reflect.ClassPath; 9 | import lombok.experimental.UtilityClass; 10 | import org.cascadebot.cascadebot.CascadeBot; 11 | 12 | import java.io.IOException; 13 | import java.util.List; 14 | import java.util.stream.Collectors; 15 | 16 | @UtilityClass 17 | public class ReflectionUtils { 18 | 19 | /** 20 | * Scans all classes accessible from the context class loader which belong to the given package and subpackages. 21 | * 22 | * @param packageName The base package 23 | * @return The classes 24 | * @throws ClassNotFoundException Thrown if the loader cannot find the class. 25 | * @throws IOException If something goes badly. 26 | */ 27 | public static List> getClasses(String packageName) throws ClassNotFoundException, IOException { 28 | List classInfos = ClassPath.from(CascadeBot.class.getClassLoader()).getTopLevelClassesRecursive(packageName).asList(); 29 | return classInfos.stream().map(ClassPath.ClassInfo::load).collect(Collectors.toList()); 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/org/cascadebot/cascadebot/utils/WebUtils.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019 CascadeBot. All rights reserved. 3 | * Licensed under the MIT license. 4 | */ 5 | 6 | package org.cascadebot.cascadebot.utils; 7 | 8 | import com.google.gson.JsonElement; 9 | import com.google.gson.JsonParser; 10 | import com.google.gson.JsonSyntaxException; 11 | import lombok.experimental.UtilityClass; 12 | import okhttp3.OkHttpClient; 13 | import okhttp3.Request; 14 | import okhttp3.Response; 15 | import org.cascadebot.cascadebot.CascadeBot; 16 | 17 | import java.io.IOException; 18 | 19 | @UtilityClass 20 | public class WebUtils { 21 | 22 | private static JsonParser parser = new JsonParser(); 23 | 24 | public static JsonElement getJsonFromURL(String url) throws IOException, IllegalArgumentException { 25 | OkHttpClient client = CascadeBot.INS.getHttpClient(); 26 | Request request = new Request.Builder() 27 | .url(url) 28 | .addHeader("Accept", "application/json") 29 | .build(); 30 | 31 | Response response = client.newCall(request).execute(); 32 | if (response.body() == null) { 33 | throw new IllegalArgumentException("Response returned no content"); 34 | } 35 | try { 36 | return parser.parse(response.body().string()); 37 | } catch (JsonSyntaxException e) { 38 | throw new IllegalArgumentException("Response didn't return json!"); 39 | } 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/org/cascadebot/cascadebot/utils/interactions/IButtonRunnable.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019 CascadeBot. All rights reserved. 3 | * Licensed under the MIT license. 4 | */ 5 | 6 | package org.cascadebot.cascadebot.utils.interactions; 7 | 8 | import net.dv8tion.jda.api.entities.Member; 9 | import net.dv8tion.jda.api.entities.Message; 10 | import net.dv8tion.jda.api.entities.TextChannel; 11 | import org.cascadebot.cascadebot.utils.interactions.InteractionMessage; 12 | 13 | @FunctionalInterface 14 | public interface IButtonRunnable { 15 | 16 | void run(Member runner, TextChannel channel, InteractionMessage message); 17 | 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/org/cascadebot/cascadebot/utils/interactions/ISelectionRunnable.java: -------------------------------------------------------------------------------- 1 | package org.cascadebot.cascadebot.utils.interactions; 2 | 3 | import net.dv8tion.jda.api.entities.Member; 4 | import net.dv8tion.jda.api.entities.Message; 5 | import net.dv8tion.jda.api.entities.TextChannel; 6 | import org.cascadebot.cascadebot.utils.interactions.InteractionMessage; 7 | 8 | import java.util.List; 9 | 10 | public interface ISelectionRunnable { 11 | 12 | void run(Member runner, TextChannel channel, InteractionMessage message, List selected); 13 | 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/org/cascadebot/cascadebot/utils/interactions/InteractionCache.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019 CascadeBot. All rights reserved. 3 | * Licensed under the MIT license. 4 | */ 5 | 6 | package org.cascadebot.cascadebot.utils.interactions; 7 | 8 | import org.cascadebot.cascadebot.utils.DiscordUtils; 9 | import org.cascadebot.cascadebot.utils.interactions.ComponentContainer; 10 | 11 | import java.util.HashMap; 12 | import java.util.LinkedHashMap; 13 | import java.util.Map; 14 | 15 | public class InteractionCache extends HashMap> { //Long 1 is channel id. long 2 is message id. This uses a linked hashmap so we can remove the oldest button when we get pasted 5 buttons per channel 16 | 17 | private int maxSize; 18 | 19 | public InteractionCache(int maxSize) { 20 | this.maxSize = maxSize; 21 | } 22 | 23 | public void put(Long channelId, Long messageId, ComponentContainer componentContainer) { 24 | if (containsKey(channelId) && get(channelId) != null) { 25 | get(channelId).put(messageId, componentContainer); 26 | } else { 27 | put(channelId, new LinkedHashMap<>() { 28 | @Override 29 | protected boolean removeEldestEntry(final Map.Entry eldest) { 30 | if (size() > maxSize) { 31 | DiscordUtils.getTextChannelById(channelId).retrieveMessageById(eldest.getKey()).queue(buttonedMessage -> buttonedMessage.clearReactions().queue()); 32 | return true; 33 | } 34 | return false; 35 | } 36 | }); 37 | get(channelId).put(messageId, componentContainer); 38 | } 39 | } 40 | 41 | public boolean remove(Long channelId, Long messageId) { 42 | if (containsKey(channelId)) { 43 | return get(channelId).remove(messageId) != null; // Only return true if there was a previous mapping for the key 44 | } else { 45 | return false; 46 | } 47 | } 48 | 49 | } 50 | -------------------------------------------------------------------------------- /src/main/java/org/cascadebot/cascadebot/utils/move/MovableItem.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020 CascadeBot. All rights reserved. 3 | * Licensed under the MIT license. 4 | */ 5 | 6 | package org.cascadebot.cascadebot.utils.move; 7 | 8 | public interface MovableItem { 9 | 10 | String getItemText(); 11 | 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/org/cascadebot/cascadebot/utils/pagination/Page.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019 CascadeBot. All rights reserved. 3 | * Licensed under the MIT license. 4 | */ 5 | 6 | package org.cascadebot.cascadebot.utils.pagination; 7 | 8 | import net.dv8tion.jda.api.entities.Message; 9 | import org.cascadebot.cascadebot.utils.interactions.InteractionMessage; 10 | 11 | public interface Page { 12 | 13 | /** 14 | * Method that's called when the page is shown 15 | * 16 | * @param message The message to edit with the page 17 | */ 18 | void pageShow(InteractionMessage message, int page, int total); 19 | 20 | String getTitle(); 21 | 22 | //TODO expand this to allow more with more page options 23 | 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/org/cascadebot/cascadebot/utils/pagination/PageCache.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019 CascadeBot. All rights reserved. 3 | * Licensed under the MIT license. 4 | */ 5 | 6 | package org.cascadebot.cascadebot.utils.pagination; 7 | 8 | import org.cascadebot.cascadebot.utils.interactions.CascadeSelectBox; 9 | 10 | import java.util.HashMap; 11 | import java.util.List; 12 | 13 | public class PageCache extends HashMap { 14 | 15 | public void put(long messageId, List pages, CascadeSelectBox selectBox) { 16 | this.put(messageId, new Pages(pages, selectBox)); 17 | } 18 | 19 | public class Pages { 20 | 21 | List pages; 22 | 23 | int currentPage; 24 | 25 | CascadeSelectBox selectBox; 26 | 27 | Pages(List pages, CascadeSelectBox selectBox) { 28 | this.pages = pages; 29 | currentPage = 1; 30 | this.selectBox = selectBox; 31 | } 32 | 33 | public int getCurrentPage() { 34 | return currentPage; 35 | } 36 | 37 | public void setCurrentPage(int currentPage) { 38 | this.currentPage = currentPage; 39 | } 40 | 41 | public Page getPage(int page) { 42 | return pages.get(page - 1); 43 | } 44 | 45 | public int getPageCount() { 46 | return pages.size(); 47 | } 48 | 49 | public List getPages() { 50 | return List.copyOf(pages); 51 | } 52 | 53 | public CascadeSelectBox getSelectBox() { 54 | return selectBox; 55 | } 56 | } 57 | 58 | } 59 | -------------------------------------------------------------------------------- /src/main/java/org/cascadebot/cascadebot/utils/votes/VoteFinishConsumer.java: -------------------------------------------------------------------------------- 1 | package org.cascadebot.cascadebot.utils.votes; 2 | 3 | import net.dv8tion.jda.api.entities.TextChannel; 4 | import org.cascadebot.cascadebot.CascadeBot; 5 | import org.cascadebot.cascadebot.UnicodeConstants; 6 | import org.cascadebot.cascadebot.data.managers.GuildDataManager; 7 | import org.cascadebot.cascadebot.data.objects.GuildData; 8 | import org.cascadebot.cascadebot.messaging.MessageType; 9 | import org.cascadebot.cascadebot.messaging.Messaging; 10 | 11 | import java.util.List; 12 | import java.util.function.BiConsumer; 13 | import java.util.function.Consumer; 14 | 15 | public enum VoteFinishConsumer { 16 | SKIP((channel, results) -> { 17 | GuildData data = GuildDataManager.getGuildData(channel.getGuild().getIdLong()); 18 | if (results.size() != 0 && results.get(0).getVote().equals(UnicodeConstants.TICK)) { 19 | Messaging.sendMessage(MessageType.INFO, channel, data.getLocale().i18n("commands.skip.skipping"), data.getCore().getUseEmbedForMessages()); 20 | CascadeBot.INS.getMusicHandler().getPlayer(channel.getGuild().getIdLong()).skip(); 21 | } else { 22 | Messaging.sendMessage(MessageType.INFO, channel, data.getLocale().i18n("commands.skip.not_skipping"), data.getCore().getUseEmbedForMessages()); 23 | } 24 | }); 25 | 26 | private final BiConsumer> consumer; 27 | VoteFinishConsumer(BiConsumer> consumer) { 28 | this.consumer = consumer; 29 | } 30 | 31 | public BiConsumer> getConsumer() { 32 | return consumer; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/org/cascadebot/cascadebot/utils/votes/VotePeriodicConsumer.java: -------------------------------------------------------------------------------- 1 | package org.cascadebot.cascadebot.utils.votes; 2 | 3 | import net.dv8tion.jda.api.EmbedBuilder; 4 | import net.dv8tion.jda.api.entities.Message; 5 | import org.cascadebot.cascadebot.CascadeBot; 6 | import org.cascadebot.cascadebot.commands.music.SkipCommand; 7 | import org.cascadebot.cascadebot.data.managers.GuildDataManager; 8 | import org.cascadebot.cascadebot.data.objects.GuildData; 9 | import org.cascadebot.cascadebot.messaging.MessageType; 10 | import org.cascadebot.cascadebot.messaging.MessagingObjects; 11 | 12 | import java.util.List; 13 | import java.util.function.BiConsumer; 14 | 15 | public enum VotePeriodicConsumer { 16 | SKIP((results, message) -> { 17 | StringBuilder resultsBuilder = new StringBuilder(); 18 | for (VoteResult result : results) { 19 | resultsBuilder.append(result.getVote()).append(" (").append(result.getAmount()).append(")\n"); 20 | } 21 | GuildData data = GuildDataManager.getGuildData(message.getGuild().getIdLong()); 22 | VoteGroup group = data.getVoteGroups().get("skip"); 23 | CascadeBot.INS.getShardManager().retrieveUserById(group.getOwnerId()).queue(user -> { 24 | EmbedBuilder skipVoteEmbed = MessagingObjects.getMessageTypeEmbedBuilder(MessageType.INFO, user, data.getLocale()) 25 | .setTitle(data.getLocale().i18n("commands.skip.skip_vote_title")); 26 | if (resultsBuilder.length() > 0) { 27 | skipVoteEmbed.setDescription(resultsBuilder.toString()); 28 | } 29 | message.editMessage(skipVoteEmbed.build()).override(true).setActionRows(message.getActionRows()).queue(); 30 | }); 31 | }); 32 | 33 | private final BiConsumer, Message> consumer; 34 | VotePeriodicConsumer(BiConsumer, Message> consumer) { 35 | this.consumer = consumer; 36 | } 37 | 38 | public BiConsumer, Message> getConsumer() { 39 | return consumer; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/org/cascadebot/cascadebot/utils/votes/VoteResult.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019 CascadeBot. All rights reserved. 3 | * Licensed under the MIT license. 4 | */ 5 | 6 | package org.cascadebot.cascadebot.utils.votes; 7 | 8 | public class VoteResult { 9 | 10 | private int amount; 11 | private Object vote; 12 | 13 | public VoteResult(int amount, Object vote) { 14 | this.amount = amount; 15 | this.vote = vote; 16 | } 17 | 18 | /** 19 | * Gets the amount of votes this got. 20 | * 21 | * @return the amount of votes this got. 22 | */ 23 | public int getAmount() { 24 | return amount; 25 | } 26 | 27 | /** 28 | * Gets the unicode or {@link net.dv8tion.jda.core.entities.Emote} that was this vote. 29 | * 30 | * @return the unicode or {@link net.dv8tion.jda.core.entities.Emote} that was this vote. 31 | */ 32 | public Object getVote() { 33 | return vote; 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /src/main/kotlin/org/cascadebot/cascadebot/Exceptions.kt: -------------------------------------------------------------------------------- 1 | package org.cascadebot.cascadebot 2 | 3 | import net.dv8tion.jda.api.Permission 4 | import net.dv8tion.jda.api.exceptions.PermissionException 5 | 6 | // We need this because the permission constructor is protected :( 7 | class DiscordPermissionException(permission: Permission) : PermissionException(permission) -------------------------------------------------------------------------------- /src/main/kotlin/org/cascadebot/cascadebot/commandmeta/CoreCommand.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020 CascadeBot. All rights reserved. 3 | * Licensed under the MIT license. 4 | */ 5 | 6 | package org.cascadebot.cascadebot.commandmeta 7 | 8 | import org.cascadebot.cascadebot.permissions.CascadePermission 9 | 10 | abstract class CoreCommand : MainCommand() { 11 | 12 | override fun module(): Module = Module.CORE 13 | 14 | override fun permission(): CascadePermission? = null 15 | 16 | } -------------------------------------------------------------------------------- /src/main/kotlin/org/cascadebot/cascadebot/commandmeta/ExecutableCommand.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020 CascadeBot. All rights reserved. 3 | * Licensed under the MIT license. 4 | */ 5 | 6 | package org.cascadebot.cascadebot.commandmeta 7 | 8 | import net.dv8tion.jda.api.entities.Member 9 | import org.cascadebot.cascadebot.data.language.Language 10 | import org.cascadebot.cascadebot.data.language.Locale 11 | import org.cascadebot.cascadebot.permissions.CascadePermission 12 | import org.cascadebot.cascadebot.utils.pagination.Page 13 | 14 | abstract class ExecutableCommand { 15 | 16 | val commandPath: String 17 | get() = "commands.$absoluteCommand.command" 18 | 19 | val descriptionPath: String 20 | get() = "commands.$absoluteCommand.description" 21 | 22 | val absoluteCommand: String 23 | get() = when (this) { 24 | is SubCommand -> this.parent() + "." + command() 25 | else -> command() 26 | } 27 | 28 | abstract fun onCommand(sender: Member, context: CommandContext) 29 | 30 | abstract fun command(): String 31 | 32 | abstract fun permission(): CascadePermission? 33 | 34 | open fun description(): String? { 35 | return null 36 | } 37 | 38 | fun command(locale: Locale): String { 39 | if (Language.hasLanguageEntry(locale, commandPath)) { 40 | return Language.i18n(locale, commandPath) 41 | } 42 | return command() 43 | } 44 | 45 | fun fullCommand(locale: Locale): String { 46 | if (this is SubCommand) { 47 | return this.getParent().command(locale) + " " + command(locale) 48 | } 49 | return command(locale) 50 | } 51 | 52 | fun description(locale: Locale): String? { 53 | return if (Language.hasLanguageEntry(locale, descriptionPath) || description() == null) { 54 | Language.i18n(locale, descriptionPath) 55 | } else { 56 | description() 57 | } 58 | } 59 | 60 | open fun deleteMessages(): Boolean = true 61 | 62 | open fun additionalUsagePages(locale: Locale): List = listOf() 63 | 64 | 65 | } -------------------------------------------------------------------------------- /src/main/kotlin/org/cascadebot/cascadebot/commandmeta/MainCommand.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020 CascadeBot. All rights reserved. 3 | * Licensed under the MIT license. 4 | */ 5 | 6 | package org.cascadebot.cascadebot.commandmeta 7 | 8 | import org.cascadebot.cascadebot.data.language.Language 9 | import org.cascadebot.cascadebot.data.language.Locale 10 | 11 | abstract class MainCommand : ExecutableCommand() { 12 | 13 | abstract fun module(): Module 14 | 15 | open fun subCommands(): Set = setOf() 16 | 17 | fun globalAliases(locale: Locale): Set { 18 | val element = Language.getLanguage(locale)!!.getElement("commands.$absoluteCommand.aliases") 19 | if (element.isEmpty || !element.get().isJsonArray) return setOf() 20 | val array = element.get().asJsonArray 21 | val aliases = mutableSetOf() 22 | array.forEach { 23 | if (it.isJsonPrimitive) { 24 | aliases.add(it.asString) 25 | } 26 | } 27 | return aliases.toSet() 28 | } 29 | 30 | } -------------------------------------------------------------------------------- /src/main/kotlin/org/cascadebot/cascadebot/commandmeta/RestrictedCommand.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020 CascadeBot. All rights reserved. 3 | * Licensed under the MIT license. 4 | */ 5 | 6 | package org.cascadebot.cascadebot.commandmeta 7 | 8 | import org.cascadebot.cascadebot.permissions.CascadePermission 9 | import org.cascadebot.shared.SecurityLevel 10 | 11 | abstract class RestrictedCommand : MainCommand() { 12 | 13 | open fun commandLevel(): SecurityLevel = SecurityLevel.STAFF 14 | 15 | override fun permission(): CascadePermission? = null 16 | 17 | } -------------------------------------------------------------------------------- /src/main/kotlin/org/cascadebot/cascadebot/commandmeta/SubCommand.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020 CascadeBot. All rights reserved. 3 | * Licensed under the MIT license. 4 | */ 5 | 6 | package org.cascadebot.cascadebot.commandmeta 7 | 8 | import org.cascadebot.cascadebot.CascadeBot 9 | 10 | abstract class SubCommand : ExecutableCommand() { 11 | 12 | abstract fun parent(): String 13 | 14 | fun getParent() = CascadeBot.INS.commandManager.getCommand(parent()) 15 | 16 | } -------------------------------------------------------------------------------- /src/main/kotlin/org/cascadebot/cascadebot/commands/management/AutoRoleCommand.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020 CascadeBot. All rights reserved. 3 | * Licensed under the MIT license. 4 | */ 5 | 6 | package org.cascadebot.cascadebot.commands.management 7 | 8 | import net.dv8tion.jda.api.entities.Member 9 | import net.dv8tion.jda.api.entities.Role 10 | import org.cascadebot.cascadebot.commandmeta.CommandContext 11 | import org.cascadebot.cascadebot.commandmeta.MainCommand 12 | import org.cascadebot.cascadebot.commandmeta.Module 13 | import org.cascadebot.cascadebot.commandmeta.SubCommand 14 | import org.cascadebot.cascadebot.messaging.MessageType 15 | import org.cascadebot.cascadebot.messaging.MessagingObjects 16 | import org.cascadebot.cascadebot.permissions.CascadePermission 17 | 18 | class AutoRoleCommand : MainCommand() { 19 | 20 | override fun onCommand(sender: Member, context: CommandContext) { 21 | context.uiMessaging.replyUsage() 22 | } 23 | 24 | override fun command(): String = "autorole" 25 | 26 | override fun subCommands(): Set = setOf(AutoRoleAddSubCommand(), AutoRoleRemoveSubCommand(), AutoRoleListSubCommand()) 27 | 28 | override fun module(): Module = Module.MANAGEMENT 29 | 30 | override fun permission(): CascadePermission? = null 31 | 32 | } -------------------------------------------------------------------------------- /src/main/kotlin/org/cascadebot/cascadebot/commands/management/AutoRoleListSubCommand.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020 CascadeBot. All rights reserved. 3 | * Licensed under the MIT license. 4 | */ 5 | 6 | package org.cascadebot.cascadebot.commands.management 7 | 8 | import net.dv8tion.jda.api.entities.Member 9 | import net.dv8tion.jda.api.entities.Role 10 | import org.cascadebot.cascadebot.commandmeta.CommandContext 11 | import org.cascadebot.cascadebot.commandmeta.SubCommand 12 | import org.cascadebot.cascadebot.messaging.MessageType 13 | import org.cascadebot.cascadebot.messaging.MessagingObjects 14 | import org.cascadebot.cascadebot.permissions.CascadePermission 15 | import java.lang.reflect.Field 16 | 17 | class AutoRoleListSubCommand : SubCommand() { 18 | 19 | override fun onCommand(sender: Member, context: CommandContext) { 20 | if (context.args.isNotEmpty()) { 21 | context.uiMessaging.replyUsage() 22 | return 23 | } 24 | val roles = context.data.management.autoRoles.map { context.guild.getRoleById(it) ?: it } 25 | val autoRoles = StringBuilder() 26 | for (role in roles) { 27 | when (role) { 28 | is Role -> autoRoles.append(role.asMention).append(" (${role.id})") 29 | is Long -> autoRoles.append("<@$role>") 30 | } 31 | autoRoles.append("\n") 32 | } 33 | val embedBuilder = MessagingObjects.getMessageTypeEmbedBuilder(MessageType.INFO, context.user, context.locale) 34 | embedBuilder.setTitle(context.i18n("words.autorole")) 35 | embedBuilder.setDescription(context.i18n("commands.autorole.autorole_description")) 36 | embedBuilder.addField(context.i18n("words.roles"), autoRoles.toString(), false) 37 | 38 | context.typedMessaging.replyInfo(embedBuilder) 39 | } 40 | 41 | override fun command(): String = "list" 42 | 43 | override fun parent(): String = "autorole" 44 | 45 | override fun permission(): CascadePermission? = CascadePermission.of("autorole.list", false) 46 | } -------------------------------------------------------------------------------- /src/main/kotlin/org/cascadebot/cascadebot/commands/management/filters/FiltersCommand.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020 CascadeBot. All rights reserved. 3 | * Licensed under the MIT license. 4 | */ 5 | 6 | package org.cascadebot.cascadebot.commands.management.filters 7 | 8 | import net.dv8tion.jda.api.entities.Member 9 | import org.cascadebot.cascadebot.commandmeta.CommandContext 10 | import org.cascadebot.cascadebot.commandmeta.MainCommand 11 | import org.cascadebot.cascadebot.commandmeta.Module 12 | import org.cascadebot.cascadebot.commandmeta.SubCommand 13 | import org.cascadebot.cascadebot.permissions.CascadePermission 14 | 15 | class FiltersCommand : MainCommand() { 16 | 17 | override fun onCommand(sender: Member, context: CommandContext) { 18 | context.uiMessaging.replyUsage() 19 | } 20 | 21 | override fun command(): String = "filters" 22 | 23 | override fun module(): Module = Module.MANAGEMENT 24 | 25 | override fun subCommands(): Set = setOf( 26 | FiltersListSubCommand(), 27 | FiltersCreateSubCommand(), 28 | FiltersDeleteSubCommand(), 29 | FiltersEnableSubCommand(), 30 | FiltersDisableSubCommand(), 31 | FiltersTypeSubCommand(), 32 | FiltersOperatorSubCommand(), 33 | FiltersChannelsSubCommand(), 34 | FiltersUsersSubCommand(), 35 | FiltersRolesSubCommand(), 36 | FiltersCommandsSubCommand() 37 | ) 38 | 39 | override fun permission(): CascadePermission? = null 40 | 41 | } -------------------------------------------------------------------------------- /src/main/kotlin/org/cascadebot/cascadebot/commands/management/filters/FiltersDeleteSubCommand.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020 CascadeBot. All rights reserved. 3 | * Licensed under the MIT license. 4 | */ 5 | 6 | package org.cascadebot.cascadebot.commands.management.filters 7 | 8 | import net.dv8tion.jda.api.entities.Member 9 | import org.cascadebot.cascadebot.commandmeta.CommandContext 10 | import org.cascadebot.cascadebot.commandmeta.SubCommand 11 | import org.cascadebot.cascadebot.permissions.CascadePermission 12 | 13 | class FiltersDeleteSubCommand : SubCommand() { 14 | 15 | override fun onCommand(sender: Member, context: CommandContext) { 16 | if (context.args.isEmpty()) { 17 | context.uiMessaging.replyUsage() 18 | return 19 | } 20 | 21 | val name = context.getArg(0) 22 | 23 | val filter = context.data.management.filters.find { it.name == name } 24 | 25 | if (filter == null) { 26 | context.typedMessaging.replyDanger(context.i18n("commands.filters.doesnt_exist", name)) 27 | return 28 | } 29 | 30 | context.data.management.filters.removeIf { it.name == name } 31 | 32 | context.typedMessaging.replySuccess(context.i18n("commands.filters.delete.success", name)) 33 | } 34 | 35 | override fun command(): String = "delete" 36 | 37 | override fun parent(): String = "filters" 38 | 39 | override fun permission(): CascadePermission = CascadePermission.of("filters.delete", false) 40 | 41 | } -------------------------------------------------------------------------------- /src/main/kotlin/org/cascadebot/cascadebot/commands/management/filters/FiltersDisableSubCommand.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020 CascadeBot. All rights reserved. 3 | * Licensed under the MIT license. 4 | */ 5 | 6 | package org.cascadebot.cascadebot.commands.management.filters 7 | 8 | import net.dv8tion.jda.api.entities.Member 9 | import org.cascadebot.cascadebot.commandmeta.CommandContext 10 | import org.cascadebot.cascadebot.commandmeta.SubCommand 11 | import org.cascadebot.cascadebot.permissions.CascadePermission 12 | 13 | class FiltersDisableSubCommand : SubCommand() { 14 | 15 | override fun onCommand(sender: Member, context: CommandContext) { 16 | if (context.args.isEmpty()) { 17 | context.uiMessaging.replyUsage() 18 | return 19 | } 20 | 21 | val name = context.getArg(0) 22 | val filter = context.data.management.filters.find { it.name == name } 23 | 24 | if (filter == null) { 25 | context.typedMessaging.replyDanger(context.i18n("commands.filters.doesnt_exist", name)) 26 | return 27 | } 28 | 29 | if (filter.enabled) { 30 | filter.enabled = false 31 | context.typedMessaging.replySuccess(context.i18n("commands.filters.disable.success", name)) 32 | } else { 33 | context.typedMessaging.replyInfo(context.i18n("commands.filters.disable.already_disabled", name)) 34 | } 35 | } 36 | 37 | override fun command(): String = "disable" 38 | 39 | override fun parent(): String = "filters" 40 | 41 | override fun permission(): CascadePermission = CascadePermission.of("filters.disable", false) 42 | 43 | } -------------------------------------------------------------------------------- /src/main/kotlin/org/cascadebot/cascadebot/commands/management/filters/FiltersEnableSubCommand.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020 CascadeBot. All rights reserved. 3 | * Licensed under the MIT license. 4 | */ 5 | 6 | package org.cascadebot.cascadebot.commands.management.filters 7 | 8 | import net.dv8tion.jda.api.entities.Member 9 | import org.cascadebot.cascadebot.commandmeta.CommandContext 10 | import org.cascadebot.cascadebot.commandmeta.SubCommand 11 | import org.cascadebot.cascadebot.permissions.CascadePermission 12 | 13 | class FiltersEnableSubCommand : SubCommand() { 14 | 15 | override fun onCommand(sender: Member, context: CommandContext) { 16 | if (context.args.isEmpty()) { 17 | context.uiMessaging.replyUsage() 18 | return 19 | } 20 | 21 | val name = context.getArg(0) 22 | val filter = context.data.management.filters.find { it.name == name } 23 | 24 | if (filter == null) { 25 | context.typedMessaging.replyDanger(context.i18n("commands.filters.doesnt_exist", name)) 26 | return 27 | } 28 | 29 | if (!filter.enabled) { 30 | filter.enabled = true 31 | context.typedMessaging.replySuccess(context.i18n("commands.filters.enable.success", name)) 32 | } else { 33 | context.typedMessaging.replyInfo(context.i18n("commands.filters.enable.already_disabled", name)) 34 | } 35 | } 36 | 37 | override fun command(): String = "enable" 38 | 39 | override fun parent(): String = "filters" 40 | 41 | override fun permission(): CascadePermission = CascadePermission.of("filters.enable", false) 42 | 43 | } -------------------------------------------------------------------------------- /src/main/kotlin/org/cascadebot/cascadebot/commands/management/goodbye/GoodbyeAddSubCommand.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020 CascadeBot. All rights reserved. 3 | * Licensed under the MIT license. 4 | */ 5 | 6 | package org.cascadebot.cascadebot.commands.management.goodbye 7 | 8 | import net.dv8tion.jda.api.entities.Member 9 | import org.cascadebot.cascadebot.commandmeta.CommandContext 10 | import org.cascadebot.cascadebot.commandmeta.SubCommand 11 | import org.cascadebot.cascadebot.messaging.MessageType 12 | import org.cascadebot.cascadebot.messaging.embed 13 | import org.cascadebot.cascadebot.permissions.CascadePermission 14 | import org.cascadebot.cascadebot.utils.FormatUtils 15 | 16 | class GoodbyeAddSubCommand : SubCommand() { 17 | 18 | override fun onCommand(sender: Member, context: CommandContext) { 19 | if (context.args.isEmpty()) { 20 | context.uiMessaging.replyUsage() 21 | return 22 | } 23 | 24 | val message = context.getMessage(0) 25 | 26 | val goodbyeMessages = context.data.management.greetings.goodbyeMessages 27 | goodbyeMessages.add(message) 28 | 29 | val index = goodbyeMessages.indexOf(message) 30 | val proportion = goodbyeMessages.getItemProportion(index) 31 | 32 | context.typedMessaging.replySuccess(embed(MessageType.SUCCESS) { 33 | title { 34 | name = context.i18n("commands.goodbye.add.success_title") 35 | } 36 | description = "${context.i18n("commands.goodbye.add.success_text_1")}\n" + 37 | "```\n$message\n```\n" + 38 | context.i18n("commands.goodbye.add.success_text_2", goodbyeMessages.size, FormatUtils.round(proportion * 100, 0).toInt()) 39 | }) 40 | 41 | } 42 | 43 | override fun command(): String = "add" 44 | 45 | override fun parent(): String = "goodbye" 46 | 47 | override fun permission(): CascadePermission? = CascadePermission.of("goodbye.add", false) 48 | 49 | } -------------------------------------------------------------------------------- /src/main/kotlin/org/cascadebot/cascadebot/commands/management/goodbye/GoodbyeClearSubCommand.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020 CascadeBot. All rights reserved. 3 | * Licensed under the MIT license. 4 | */ 5 | 6 | package org.cascadebot.cascadebot.commands.management.goodbye 7 | 8 | import net.dv8tion.jda.api.entities.Member 9 | import org.cascadebot.cascadebot.commandmeta.CommandContext 10 | import org.cascadebot.cascadebot.commandmeta.SubCommand 11 | import org.cascadebot.cascadebot.messaging.MessageType 12 | import org.cascadebot.cascadebot.permissions.CascadePermission 13 | import org.cascadebot.cascadebot.utils.ConfirmUtils 14 | 15 | class GoodbyeClearSubCommand : SubCommand() { 16 | 17 | private val actionKey = "goodbye-clear" 18 | 19 | override fun onCommand(sender: Member, context: CommandContext) { 20 | if (context.args.isNotEmpty()) { 21 | context.uiMessaging.replyUsage() 22 | return 23 | } 24 | 25 | if (ConfirmUtils.hasRegisteredAction(actionKey, context.user.idLong)) { 26 | ConfirmUtils.confirmAction(actionKey, context.user.idLong) 27 | return 28 | } 29 | 30 | ConfirmUtils.registerForConfirmation(context.user.idLong, 31 | actionKey, 32 | context.channel, 33 | MessageType.WARNING, 34 | context.i18n("commands.goodbye.clear.confirm_warning"), 35 | isCancellable = true, 36 | action = Runnable { 37 | context.data.management.greetings.goodbyeMessages.clear() 38 | context.typedMessaging.replySuccess(context.i18n("commands.goodbye.clear.clear_success")) 39 | } 40 | ) 41 | 42 | } 43 | 44 | override fun command(): String = "clear" 45 | 46 | override fun parent(): String = "goodbye" 47 | 48 | override fun permission(): CascadePermission? = CascadePermission.of("goodbye.clear", false) 49 | 50 | } -------------------------------------------------------------------------------- /src/main/kotlin/org/cascadebot/cascadebot/commands/management/goodbye/GoodbyeCommand.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020 CascadeBot. All rights reserved. 3 | * Licensed under the MIT license. 4 | */ 5 | 6 | package org.cascadebot.cascadebot.commands.management.goodbye 7 | 8 | import net.dv8tion.jda.api.entities.Member 9 | import org.cascadebot.cascadebot.commandmeta.CommandContext 10 | import org.cascadebot.cascadebot.commandmeta.MainCommand 11 | import org.cascadebot.cascadebot.commandmeta.Module 12 | import org.cascadebot.cascadebot.commandmeta.SubCommand 13 | import org.cascadebot.cascadebot.data.language.Language.i18n 14 | import org.cascadebot.cascadebot.data.language.Locale 15 | import org.cascadebot.cascadebot.messaging.MessageType 16 | import org.cascadebot.cascadebot.messaging.embed 17 | import org.cascadebot.cascadebot.permissions.CascadePermission 18 | import org.cascadebot.cascadebot.utils.pagination.Page 19 | import org.cascadebot.cascadebot.utils.pagination.PageObjects 20 | import org.cascadebot.cascadebot.utils.placeholders.PlaceholderObjects 21 | import org.cascadebot.cascadebot.utils.placeholders.PlaceholderObjects.goodbyes 22 | import org.cascadebot.cascadebot.utils.placeholders.PlaceholderObjects.tags 23 | import org.cascadebot.cascadebot.utils.placeholders.getPlaceholderUsagePage 24 | import org.cascadebot.cascadebot.utils.toPercentage 25 | import org.cascadebot.cascadebot.utils.truncate 26 | 27 | class GoodbyeCommand : MainCommand() { 28 | 29 | override fun onCommand(sender: Member, context: CommandContext) { 30 | context.uiMessaging.replyUsage() 31 | } 32 | 33 | override fun command(): String = "goodbye" 34 | 35 | override fun module(): Module = Module.MANAGEMENT 36 | 37 | override fun permission(): CascadePermission? = null 38 | 39 | override fun additionalUsagePages(locale: Locale): List { 40 | return listOf( 41 | getPlaceholderUsagePage( 42 | goodbyes.placeholders, 43 | i18n(locale, "placeholders.goodbyes.title"), 44 | locale 45 | ) 46 | ) 47 | } 48 | 49 | override fun subCommands(): Set = setOf(GoodbyeAddSubCommand(), GoodbyeClearSubCommand(), GoodbyeRemoveSubCommand(), GoodbyeWeightSubCommand(), GoodbyeListSubCommand()) 50 | 51 | } -------------------------------------------------------------------------------- /src/main/kotlin/org/cascadebot/cascadebot/commands/management/goodbye/GoodbyeRemoveSubCommand.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020 CascadeBot. All rights reserved. 3 | * Licensed under the MIT license. 4 | */ 5 | 6 | package org.cascadebot.cascadebot.commands.management.goodbye 7 | 8 | import net.dv8tion.jda.api.entities.Member 9 | import org.cascadebot.cascadebot.commandmeta.CommandContext 10 | import org.cascadebot.cascadebot.commandmeta.SubCommand 11 | import org.cascadebot.cascadebot.messaging.MessageType 12 | import org.cascadebot.cascadebot.messaging.embed 13 | import org.cascadebot.cascadebot.permissions.CascadePermission 14 | 15 | class GoodbyeRemoveSubCommand : SubCommand() { 16 | 17 | override fun onCommand(sender: Member, context: CommandContext) { 18 | if (context.args.size != 1) { 19 | context.uiMessaging.replyUsage() 20 | return 21 | } 22 | 23 | if (!context.isArgInteger(0)) { 24 | context.typedMessaging.replyDanger(context.i18n("commands.goodbye.remove.message_index_number")) 25 | return 26 | } 27 | 28 | val index = context.getArgAsInteger(0)!! - 1 29 | val goodbyeMessages = context.data.management.greetings.goodbyeMessages 30 | if (index < 0 || index >= goodbyeMessages.size) { 31 | context.typedMessaging.replyDanger(context.i18n("commands.goodbye.invalid_message_index", goodbyeMessages.size)) 32 | return 33 | } 34 | 35 | val message = goodbyeMessages.remove(index) 36 | 37 | context.typedMessaging.replySuccess(embed(MessageType.INFO, context.user) { 38 | title { 39 | name = context.i18n("commands.goodbye.remove.remove_success_title") 40 | } 41 | description = context.i18n("commands.goodbye.remove.remove_success_text", message ?: "Message unavailable!") 42 | }) 43 | } 44 | 45 | override fun command(): String = "remove" 46 | 47 | override fun parent(): String = "goodbye" 48 | 49 | override fun permission(): CascadePermission? = CascadePermission.of("goodbye.remove", false) 50 | 51 | } -------------------------------------------------------------------------------- /src/main/kotlin/org/cascadebot/cascadebot/commands/management/welcome/WelcomeAddSubCommand.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020 CascadeBot. All rights reserved. 3 | * Licensed under the MIT license. 4 | */ 5 | 6 | package org.cascadebot.cascadebot.commands.management.welcome 7 | 8 | import net.dv8tion.jda.api.entities.Member 9 | import org.cascadebot.cascadebot.commandmeta.CommandContext 10 | import org.cascadebot.cascadebot.commandmeta.SubCommand 11 | import org.cascadebot.cascadebot.messaging.MessageType 12 | import org.cascadebot.cascadebot.messaging.embed 13 | import org.cascadebot.cascadebot.permissions.CascadePermission 14 | import org.cascadebot.cascadebot.utils.FormatUtils 15 | 16 | class WelcomeAddSubCommand : SubCommand() { 17 | 18 | override fun onCommand(sender: Member, context: CommandContext) { 19 | if (context.args.isEmpty()) { 20 | context.uiMessaging.replyUsage() 21 | return 22 | } 23 | 24 | val message = context.getMessage(0) 25 | 26 | val welcomeMessages = context.data.management.greetings.welcomeMessages 27 | welcomeMessages.add(message) 28 | 29 | val index = welcomeMessages.indexOf(message) 30 | val proportion = welcomeMessages.getItemProportion(index) 31 | 32 | context.typedMessaging.replySuccess(embed(MessageType.SUCCESS) { 33 | title { 34 | name = context.i18n("commands.welcome.add.success_title") 35 | } 36 | description = "${context.i18n("commands.welcome.add.success_text_1")}\n" + 37 | "```\n$message\n```\n" + 38 | context.i18n("commands.welcome.add.success_text_2", welcomeMessages.size, FormatUtils.round(proportion * 100, 0).toInt()) 39 | }) 40 | 41 | } 42 | 43 | override fun command(): String = "add" 44 | 45 | override fun parent(): String = "welcome" 46 | 47 | override fun permission(): CascadePermission? = CascadePermission.of("welcome.add", false) 48 | 49 | } -------------------------------------------------------------------------------- /src/main/kotlin/org/cascadebot/cascadebot/commands/management/welcome/WelcomeChannelSubCommand.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020 CascadeBot. All rights reserved. 3 | * Licensed under the MIT license. 4 | */ 5 | 6 | package org.cascadebot.cascadebot.commands.management.welcome 7 | 8 | import net.dv8tion.jda.api.entities.Member 9 | import org.cascadebot.cascadebot.commandmeta.CommandContext 10 | import org.cascadebot.cascadebot.commandmeta.SubCommand 11 | import org.cascadebot.cascadebot.permissions.CascadePermission 12 | import org.cascadebot.cascadebot.utils.DiscordUtils 13 | 14 | class WelcomeChannelSubCommand : SubCommand() { 15 | 16 | override fun onCommand(sender: Member, context: CommandContext) { 17 | if (context.args.size > 1) { 18 | context.uiMessaging.replyUsage() 19 | return 20 | } 21 | 22 | if (context.args.isEmpty()) { 23 | context.typedMessaging.replyInfo(run { 24 | val greetings = context.data.management.greetings 25 | if (greetings.welcomeChannel != null) { 26 | context.i18n("commands.welcome.current_channel", greetings.welcomeChannel?.asMention!!) 27 | } else { 28 | context.i18n("commands.welcome.no_channel_set") 29 | } 30 | }) 31 | } else { 32 | if (context.testForArg("clear")) { 33 | context.data.management.greetings.welcomeChannel = null 34 | context.typedMessaging.replySuccess(context.i18n("commands.welcome.channel.clear_success")) 35 | return 36 | } 37 | 38 | val channel = DiscordUtils.getTextChannel(context.guild, context.getArg(0)) 39 | if (channel == null) { 40 | context.typedMessaging.replyDanger(context.i18n("commands.welcome.channel.invalid_channel")) 41 | return 42 | } 43 | 44 | context.data.management.greetings.welcomeChannel = channel 45 | 46 | context.typedMessaging.replySuccess(context.i18n("commands.welcome.channel.set_success", channel.asMention)) 47 | } 48 | 49 | } 50 | 51 | override fun command(): String = "channel" 52 | 53 | override fun parent(): String = "welcome" 54 | 55 | override fun permission(): CascadePermission? = CascadePermission.of("welcome.channel", false) 56 | 57 | } -------------------------------------------------------------------------------- /src/main/kotlin/org/cascadebot/cascadebot/commands/management/welcome/WelcomeClearSubCommand.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020 CascadeBot. All rights reserved. 3 | * Licensed under the MIT license. 4 | */ 5 | 6 | package org.cascadebot.cascadebot.commands.management.welcome 7 | 8 | import net.dv8tion.jda.api.entities.Member 9 | import org.cascadebot.cascadebot.commandmeta.CommandContext 10 | import org.cascadebot.cascadebot.commandmeta.SubCommand 11 | import org.cascadebot.cascadebot.messaging.MessageType 12 | import org.cascadebot.cascadebot.permissions.CascadePermission 13 | import org.cascadebot.cascadebot.utils.ConfirmUtils 14 | 15 | class WelcomeClearSubCommand : SubCommand() { 16 | 17 | private val actionKey = "welcome-clear" 18 | 19 | override fun onCommand(sender: Member, context: CommandContext) { 20 | if (context.args.isNotEmpty()) { 21 | context.uiMessaging.replyUsage() 22 | return 23 | } 24 | 25 | if (ConfirmUtils.hasRegisteredAction(actionKey, context.user.idLong)) { 26 | ConfirmUtils.confirmAction(actionKey, context.user.idLong) 27 | return 28 | } 29 | 30 | ConfirmUtils.registerForConfirmation(context.user.idLong, 31 | actionKey, 32 | context.channel, 33 | MessageType.WARNING, 34 | context.i18n("commands.welcome.clear.confirm_warning"), 35 | isCancellable = true, 36 | action = Runnable { 37 | context.data.management.greetings.welcomeMessages.clear() 38 | context.data.management.greetings.welcomeChannel = null 39 | context.typedMessaging.replySuccess(context.i18n("commands.welcome.clear.clear_success")) 40 | } 41 | ) 42 | 43 | } 44 | 45 | override fun command(): String = "clear" 46 | 47 | override fun parent(): String = "welcome" 48 | 49 | override fun permission(): CascadePermission? = CascadePermission.of("welcome.clear", false) 50 | 51 | } -------------------------------------------------------------------------------- /src/main/kotlin/org/cascadebot/cascadebot/commands/management/welcome/WelcomeCommand.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020 CascadeBot. All rights reserved. 3 | * Licensed under the MIT license. 4 | */ 5 | 6 | package org.cascadebot.cascadebot.commands.management.welcome 7 | 8 | import net.dv8tion.jda.api.entities.Member 9 | import org.cascadebot.cascadebot.commandmeta.CommandContext 10 | import org.cascadebot.cascadebot.commandmeta.MainCommand 11 | import org.cascadebot.cascadebot.commandmeta.Module 12 | import org.cascadebot.cascadebot.commandmeta.SubCommand 13 | import org.cascadebot.cascadebot.data.language.Language 14 | import org.cascadebot.cascadebot.data.language.Locale 15 | import org.cascadebot.cascadebot.messaging.MessageType 16 | import org.cascadebot.cascadebot.messaging.embed 17 | import org.cascadebot.cascadebot.permissions.CascadePermission 18 | import org.cascadebot.cascadebot.utils.pagination.Page 19 | import org.cascadebot.cascadebot.utils.pagination.PageObjects 20 | import org.cascadebot.cascadebot.utils.placeholders.PlaceholderObjects 21 | import org.cascadebot.cascadebot.utils.placeholders.getPlaceholderUsagePage 22 | import org.cascadebot.cascadebot.utils.toPercentage 23 | import org.cascadebot.cascadebot.utils.truncate 24 | 25 | class WelcomeCommand : MainCommand() { 26 | 27 | override fun onCommand(sender: Member, context: CommandContext) { 28 | context.uiMessaging.replyUsage() 29 | } 30 | 31 | override fun command(): String = "welcome" 32 | 33 | override fun module(): Module = Module.MANAGEMENT 34 | 35 | override fun permission(): CascadePermission? = null 36 | 37 | override fun additionalUsagePages(locale: Locale): List { 38 | return listOf( 39 | getPlaceholderUsagePage( 40 | PlaceholderObjects.welcomes.placeholders, 41 | Language.i18n(locale, "placeholders.welcomes.title"), 42 | locale 43 | ) 44 | ) 45 | } 46 | 47 | override fun subCommands(): Set = setOf(WelcomeAddSubCommand(), WelcomeChannelSubCommand(), WelcomeClearSubCommand(), WelcomeRemoveSubCommand(), WelcomeWeightSubCommand(), WelcomeListSubCommand()) 48 | 49 | } -------------------------------------------------------------------------------- /src/main/kotlin/org/cascadebot/cascadebot/commands/management/welcome/WelcomeDMAddSubCommand.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020 CascadeBot. All rights reserved. 3 | * Licensed under the MIT license. 4 | */ 5 | 6 | package org.cascadebot.cascadebot.commands.management.welcome 7 | 8 | import net.dv8tion.jda.api.entities.Member 9 | import org.cascadebot.cascadebot.commandmeta.CommandContext 10 | import org.cascadebot.cascadebot.commandmeta.SubCommand 11 | import org.cascadebot.cascadebot.messaging.MessageType 12 | import org.cascadebot.cascadebot.messaging.embed 13 | import org.cascadebot.cascadebot.permissions.CascadePermission 14 | import org.cascadebot.cascadebot.utils.FormatUtils 15 | 16 | class WelcomeDMAddSubCommand : SubCommand() { 17 | 18 | override fun onCommand(sender: Member, context: CommandContext) { 19 | if (context.args.isEmpty()) { 20 | context.uiMessaging.replyUsage() 21 | return 22 | } 23 | 24 | val message = context.getMessage(0) 25 | 26 | val welcomeMessages = context.data.management.greetings.welcomeDMMessages 27 | welcomeMessages.add(message) 28 | 29 | val index = welcomeMessages.indexOf(message) 30 | val proportion = welcomeMessages.getItemProportion(index) 31 | 32 | context.typedMessaging.replySuccess(embed(MessageType.SUCCESS) { 33 | title { 34 | name = context.i18n("commands.welcomedm.add.success_title") 35 | } 36 | description = "${context.i18n("commands.welcomedm.add.success_text_1")}\n" + 37 | "```\n$message\n```\n" + 38 | context.i18n("commands.welcomedm.add.success_text_2", welcomeMessages.size, FormatUtils.round(proportion * 100, 0).toInt()) 39 | }) 40 | } 41 | 42 | override fun command(): String = "add" 43 | 44 | override fun parent(): String = "welcomedm" 45 | 46 | override fun permission(): CascadePermission = CascadePermission.of("welcomedm.add", false) 47 | 48 | } -------------------------------------------------------------------------------- /src/main/kotlin/org/cascadebot/cascadebot/commands/management/welcome/WelcomeDMClearSubCommand.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020 CascadeBot. All rights reserved. 3 | * Licensed under the MIT license. 4 | */ 5 | 6 | package org.cascadebot.cascadebot.commands.management.welcome 7 | 8 | import net.dv8tion.jda.api.entities.Member 9 | import org.cascadebot.cascadebot.commandmeta.CommandContext 10 | import org.cascadebot.cascadebot.commandmeta.SubCommand 11 | import org.cascadebot.cascadebot.messaging.MessageType 12 | import org.cascadebot.cascadebot.permissions.CascadePermission 13 | import org.cascadebot.cascadebot.utils.ConfirmUtils 14 | 15 | class WelcomeDMClearSubCommand : SubCommand() { 16 | 17 | private val actionKey = "dm-welcome-clear" 18 | 19 | override fun onCommand(sender: Member, context: CommandContext) { 20 | if (context.args.isNotEmpty()) { 21 | context.uiMessaging.replyUsage() 22 | return 23 | } 24 | 25 | if (ConfirmUtils.hasRegisteredAction(actionKey, context.user.idLong)) { 26 | ConfirmUtils.confirmAction(actionKey, context.user.idLong) 27 | return 28 | } 29 | 30 | ConfirmUtils.registerForConfirmation(context.user.idLong, 31 | actionKey, 32 | context.channel, 33 | MessageType.WARNING, 34 | context.i18n("commands.welcome.dm.clear.confirm_warning"), 35 | isCancellable = true, 36 | action = Runnable { 37 | context.data.management.greetings.welcomeDMMessages.clear() 38 | context.data.management.greetings.welcomeChannel = null 39 | context.typedMessaging.replySuccess(context.i18n("commands.welcome.dm.clear.clear_success")) 40 | } 41 | ) 42 | } 43 | 44 | override fun command(): String = "clear" 45 | 46 | override fun parent(): String = "welcomedm" 47 | 48 | override fun permission(): CascadePermission = CascadePermission.of("welcomedm.clear", false) 49 | 50 | } -------------------------------------------------------------------------------- /src/main/kotlin/org/cascadebot/cascadebot/commands/management/welcome/WelcomeDMCommand.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020 CascadeBot. All rights reserved. 3 | * Licensed under the MIT license. 4 | */ 5 | 6 | package org.cascadebot.cascadebot.commands.management.welcome 7 | 8 | import net.dv8tion.jda.api.entities.Member 9 | import org.cascadebot.cascadebot.commandmeta.CommandContext 10 | import org.cascadebot.cascadebot.commandmeta.MainCommand 11 | import org.cascadebot.cascadebot.commandmeta.Module 12 | import org.cascadebot.cascadebot.commandmeta.SubCommand 13 | import org.cascadebot.cascadebot.messaging.MessageType 14 | import org.cascadebot.cascadebot.messaging.embed 15 | import org.cascadebot.cascadebot.permissions.CascadePermission 16 | import org.cascadebot.cascadebot.utils.pagination.Page 17 | import org.cascadebot.cascadebot.utils.pagination.PageObjects 18 | import org.cascadebot.cascadebot.utils.placeholders.PlaceholderObjects 19 | import org.cascadebot.cascadebot.utils.toPercentage 20 | import org.cascadebot.cascadebot.utils.truncate 21 | 22 | class WelcomeDMCommand : MainCommand() { 23 | 24 | override fun onCommand(sender: Member, context: CommandContext) { 25 | context.uiMessaging.replyUsage() 26 | } 27 | 28 | override fun command(): String = "welcomedm" 29 | 30 | override fun subCommands(): Set = 31 | setOf( 32 | WelcomeDMAddSubCommand(), 33 | WelcomeDMRemoveSubCommand(), 34 | WelcomeDMClearSubCommand(), 35 | WelcomeDMWeightSubCommand(), 36 | WelcomeDMListSubCommand() 37 | ) 38 | 39 | override fun module(): Module = Module.MANAGEMENT 40 | 41 | override fun permission(): CascadePermission? = null 42 | 43 | } -------------------------------------------------------------------------------- /src/main/kotlin/org/cascadebot/cascadebot/commands/management/welcome/WelcomeDMRemoveSubCommand.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020 CascadeBot. All rights reserved. 3 | * Licensed under the MIT license. 4 | */ 5 | 6 | package org.cascadebot.cascadebot.commands.management.welcome 7 | 8 | import net.dv8tion.jda.api.entities.Member 9 | import org.cascadebot.cascadebot.commandmeta.CommandContext 10 | import org.cascadebot.cascadebot.commandmeta.SubCommand 11 | import org.cascadebot.cascadebot.messaging.MessageType 12 | import org.cascadebot.cascadebot.messaging.embed 13 | import org.cascadebot.cascadebot.permissions.CascadePermission 14 | 15 | class WelcomeDMRemoveSubCommand : SubCommand() { 16 | 17 | override fun onCommand(sender: Member, context: CommandContext) { 18 | if (context.args.size != 1) { 19 | context.uiMessaging.replyUsage() 20 | return 21 | } 22 | 23 | if (!context.isArgInteger(0)) { 24 | context.typedMessaging.replyDanger(context.i18n("commands.welcome.remove.message_index_number")) 25 | return 26 | } 27 | 28 | val index = context.getArgAsInteger(0)!! - 1 29 | val welcomeMessages = context.data.management.greetings.welcomeDMMessages 30 | if (index < 0 || index >= welcomeMessages.size) { 31 | context.typedMessaging.replyDanger(context.i18n("commands.welcome.invalid_message_index", welcomeMessages.size)) 32 | return 33 | } 34 | 35 | val message = welcomeMessages.remove(index) 36 | 37 | context.typedMessaging.replySuccess(embed(MessageType.INFO, context.user) { 38 | title { 39 | name = context.i18n("commands.welcomedm.remove.success_title") 40 | } 41 | description = context.i18n("commands.welcome.remove.success_text", message ?: "Message unavailable!") 42 | }) 43 | } 44 | 45 | override fun command(): String = "remove" 46 | 47 | override fun parent(): String = "welcomedm" 48 | 49 | override fun permission(): CascadePermission = CascadePermission.of("welcomedm.remove", false) 50 | 51 | } -------------------------------------------------------------------------------- /src/main/kotlin/org/cascadebot/cascadebot/commands/management/welcome/WelcomeRemoveSubCommand.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020 CascadeBot. All rights reserved. 3 | * Licensed under the MIT license. 4 | */ 5 | 6 | package org.cascadebot.cascadebot.commands.management.welcome 7 | 8 | import net.dv8tion.jda.api.entities.Member 9 | import org.cascadebot.cascadebot.commandmeta.CommandContext 10 | import org.cascadebot.cascadebot.commandmeta.SubCommand 11 | import org.cascadebot.cascadebot.messaging.MessageType 12 | import org.cascadebot.cascadebot.messaging.embed 13 | import org.cascadebot.cascadebot.permissions.CascadePermission 14 | 15 | class WelcomeRemoveSubCommand : SubCommand() { 16 | 17 | override fun onCommand(sender: Member, context: CommandContext) { 18 | if (context.args.size != 1) { 19 | context.uiMessaging.replyUsage() 20 | return 21 | } 22 | 23 | if (!context.isArgInteger(0)) { 24 | context.typedMessaging.replyDanger(context.i18n("commands.welcome.remove.message_index_number")) 25 | return 26 | } 27 | 28 | val index = context.getArgAsInteger(0)!! - 1 29 | val welcomeMessages = context.data.management.greetings.welcomeMessages 30 | if (index < 0 || index >= welcomeMessages.size) { 31 | context.typedMessaging.replyDanger(context.i18n("commands.welcome.invalid_message_index", welcomeMessages.size)) 32 | return 33 | } 34 | 35 | val message = welcomeMessages.remove(index) 36 | 37 | context.typedMessaging.replySuccess(embed(MessageType.INFO, context.user) { 38 | title { 39 | name = context.i18n("commands.welcome.remove.success_title") 40 | } 41 | description = context.i18n("commands.welcome.remove.success_text", message ?: "Message unavailable!") 42 | }) 43 | } 44 | 45 | override fun command(): String = "remove" 46 | 47 | override fun parent(): String = "welcome" 48 | 49 | override fun permission(): CascadePermission? = CascadePermission.of("welcome.remove", false) 50 | 51 | } -------------------------------------------------------------------------------- /src/main/kotlin/org/cascadebot/cascadebot/commands/moderation/MuteCommand.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020 CascadeBot. All rights reserved. 3 | * Licensed under the MIT license. 4 | */ 5 | 6 | package org.cascadebot.cascadebot.commands.moderation 7 | 8 | import net.dv8tion.jda.api.Permission 9 | import net.dv8tion.jda.api.entities.Member 10 | import org.cascadebot.cascadebot.CascadeBot 11 | import org.cascadebot.cascadebot.commandmeta.CommandContext 12 | import org.cascadebot.cascadebot.commandmeta.MainCommand 13 | import org.cascadebot.cascadebot.commandmeta.Module 14 | import org.cascadebot.cascadebot.commandmeta.SubCommand 15 | import org.cascadebot.cascadebot.messaging.MessagingObjects 16 | import org.cascadebot.cascadebot.permissions.CascadePermission 17 | import org.cascadebot.cascadebot.utils.DiscordUtils 18 | 19 | class MuteCommand : MainCommand() { 20 | 21 | override fun onCommand(sender: Member, context: CommandContext) { 22 | if (context.args.isEmpty()) { 23 | context.uiMessaging.replyUsage() 24 | return 25 | } 26 | 27 | val targetMember = DiscordUtils.getMember(context.guild, context.getArg(0)) 28 | 29 | if (targetMember == null) { 30 | context.typedMessaging.replyDanger(MessagingObjects.getStandardMessageEmbed(context.i18n("responses.cannot_find_user"), context.user, context.locale)) 31 | return 32 | } 33 | 34 | var reason: String? = null 35 | if (context.args.size > 1) { 36 | reason = context.getMessage(1) 37 | } 38 | 39 | CascadeBot.INS.moderationManager.mute( 40 | context, 41 | targetMember, 42 | sender, 43 | reason 44 | ) 45 | } 46 | 47 | override fun command(): String = "mute" 48 | 49 | override fun module(): Module = Module.MODERATION 50 | 51 | override fun subCommands(): Set = setOf(MuteRoleSubCommand(), MuteChannelSetupSubCommand()) 52 | 53 | override fun permission(): CascadePermission = CascadePermission.of("mute", false, Permission.MANAGE_ROLES) 54 | } -------------------------------------------------------------------------------- /src/main/kotlin/org/cascadebot/cascadebot/commands/moderation/MuteRoleSubCommand.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020 CascadeBot. All rights reserved. 3 | * Licensed under the MIT license. 4 | */ 5 | 6 | package org.cascadebot.cascadebot.commands.moderation 7 | 8 | import net.dv8tion.jda.api.entities.Member 9 | import org.cascadebot.cascadebot.commandmeta.CommandContext 10 | import org.cascadebot.cascadebot.commandmeta.SubCommand 11 | import org.cascadebot.cascadebot.permissions.CascadePermission 12 | import org.cascadebot.cascadebot.utils.DiscordUtils 13 | import org.cascadebot.cascadebot.utils.getMutedRole 14 | 15 | class MuteRoleSubCommand : SubCommand() { 16 | 17 | override fun onCommand(sender: Member, context: CommandContext) { 18 | if (context.args.isEmpty()) { 19 | context.typedMessaging.replyInfo(context.i18n( 20 | "commands.mute.role.role_info", 21 | context.guild.getMutedRole().asMention 22 | )) 23 | return 24 | } 25 | 26 | val newRole = DiscordUtils.getRole(context.getArg(0), context.guild) 27 | if (newRole == null) { 28 | context.typedMessaging.replyDanger(context.i18n("responses.cannot_find_role_matching", context.args[0])) 29 | return 30 | } 31 | 32 | context.data.mutedRoleId = newRole.idLong 33 | context.typedMessaging.replySuccess(context.i18n("commands.mute.role.set_role", newRole.asMention)) 34 | } 35 | 36 | override fun command(): String = "role" 37 | 38 | override fun parent(): String = "mute" 39 | 40 | override fun permission(): CascadePermission = CascadePermission.of("mute.role", false) 41 | 42 | } -------------------------------------------------------------------------------- /src/main/kotlin/org/cascadebot/cascadebot/commands/moderation/SlowmodeResetSubCommand.kt: -------------------------------------------------------------------------------- 1 | package org.cascadebot.cascadebot.commands.moderation 2 | 3 | import net.dv8tion.jda.api.Permission 4 | import net.dv8tion.jda.api.entities.Member 5 | import net.dv8tion.jda.api.entities.TextChannel 6 | import net.dv8tion.jda.api.exceptions.PermissionException 7 | import org.cascadebot.cascadebot.commandmeta.CommandContext 8 | import org.cascadebot.cascadebot.commandmeta.SubCommand 9 | import org.cascadebot.cascadebot.permissions.CascadePermission 10 | import org.cascadebot.cascadebot.utils.DiscordUtils 11 | 12 | class SlowmodeResetSubCommand : SubCommand() { 13 | 14 | override fun onCommand(sender: Member, context: CommandContext) { 15 | var channel: TextChannel = context.channel 16 | if (context.args.isNotEmpty()) { 17 | val tempChannel = DiscordUtils.getTextChannel(context.guild, context.getArg(0)) 18 | if (tempChannel != null) { 19 | channel = tempChannel 20 | } else { 21 | context.typedMessaging.replyDanger(context.i18n("responses.cannot_find_channel_matching", context.getArg(0))) 22 | } 23 | } 24 | if (!context.member.hasPermission(channel, Permission.MANAGE_CHANNEL)) { 25 | context.uiMessaging.sendUserDiscordPermError(Permission.MANAGE_CHANNEL) 26 | return 27 | } 28 | if (!context.selfMember.hasPermission(channel, Permission.MANAGE_CHANNEL)) { 29 | context.uiMessaging.sendBotDiscordPermError(Permission.MANAGE_CHANNEL) 30 | return 31 | } 32 | 33 | // Slowmode 0 = off 34 | try { 35 | channel.manager.setSlowmode(0).queue { 36 | context.typedMessaging.replySuccess(context.i18n("commands.slowmode.reset.reset_success", channel.name)) 37 | } 38 | } catch (e: PermissionException) { 39 | context.uiMessaging.sendBotDiscordPermError(e.permission) 40 | } catch (e: Exception) { 41 | context.typedMessaging.replyException("Couldn't change channel permissions", e) 42 | } 43 | 44 | 45 | } 46 | 47 | override fun parent(): String = "slowmode" 48 | 49 | override fun command(): String = "reset" 50 | 51 | override fun permission(): CascadePermission? = CascadePermission.of("slowmode.reset", false, Permission.MANAGE_CHANNEL) 52 | 53 | } -------------------------------------------------------------------------------- /src/main/kotlin/org/cascadebot/cascadebot/commands/moderation/TempBan.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020 CascadeBot. All rights reserved. 3 | * Licensed under the MIT license. 4 | */ 5 | 6 | package org.cascadebot.cascadebot.commands.moderation 7 | 8 | import net.dv8tion.jda.api.entities.Member 9 | import org.cascadebot.cascadebot.CascadeBot 10 | import org.cascadebot.cascadebot.commandmeta.CommandContext 11 | import org.cascadebot.cascadebot.commandmeta.MainCommand 12 | import org.cascadebot.cascadebot.commandmeta.Module 13 | import org.cascadebot.cascadebot.messaging.MessagingObjects 14 | import org.cascadebot.cascadebot.permissions.CascadePermission 15 | import org.cascadebot.cascadebot.utils.DiscordUtils 16 | import org.cascadebot.cascadebot.utils.ParserUtils 17 | 18 | class TempBan : MainCommand() { 19 | 20 | override fun onCommand(sender: Member, context: CommandContext) { 21 | if (context.args.size < 2) { 22 | context.uiMessaging.replyUsage() 23 | return 24 | } 25 | 26 | val targetMember = DiscordUtils.getMember(context.guild, context.getArg(0)) 27 | 28 | if (targetMember == null) { 29 | context.typedMessaging.replyDanger(MessagingObjects.getStandardMessageEmbed(context.i18n("responses.cannot_find_user"), context.user, context.locale)) 30 | return 31 | } 32 | 33 | val duration = ParserUtils.parseTextTime(context.args[1], false) 34 | if (duration <= 0) { 35 | context.typedMessaging.replyDanger(context.i18n("responses.invalid_duration")) 36 | return 37 | } 38 | 39 | var reason: String? = null 40 | if (context.args.size > 2) { 41 | reason = context.getMessage(2) 42 | } 43 | 44 | CascadeBot.INS.moderationManager.tempBan( 45 | context, 46 | targetMember.user, 47 | sender, 48 | reason, 49 | duration 50 | ) 51 | } 52 | 53 | override fun command(): String = "tempban" 54 | 55 | override fun module(): Module = Module.MODERATION 56 | 57 | override fun permission(): CascadePermission = CascadePermission.of("tempban", false) 58 | 59 | } -------------------------------------------------------------------------------- /src/main/kotlin/org/cascadebot/cascadebot/commands/moderation/TempMute.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020 CascadeBot. All rights reserved. 3 | * Licensed under the MIT license. 4 | */ 5 | 6 | package org.cascadebot.cascadebot.commands.moderation 7 | 8 | import net.dv8tion.jda.api.entities.Member 9 | import org.cascadebot.cascadebot.CascadeBot 10 | import org.cascadebot.cascadebot.commandmeta.CommandContext 11 | import org.cascadebot.cascadebot.commandmeta.MainCommand 12 | import org.cascadebot.cascadebot.commandmeta.Module 13 | import org.cascadebot.cascadebot.messaging.MessagingObjects 14 | import org.cascadebot.cascadebot.permissions.CascadePermission 15 | import org.cascadebot.cascadebot.utils.DiscordUtils 16 | import org.cascadebot.cascadebot.utils.ParserUtils 17 | 18 | class TempMute : MainCommand() { 19 | 20 | override fun onCommand(sender: Member, context: CommandContext) { 21 | if (context.args.size < 2) { 22 | context.uiMessaging.replyUsage() 23 | return 24 | } 25 | 26 | val targetMember = DiscordUtils.getMember(context.guild, context.getArg(0)) 27 | 28 | if (targetMember == null) { 29 | context.typedMessaging.replyDanger(MessagingObjects.getStandardMessageEmbed(context.i18n("responses.cannot_find_user"), context.user, context.locale)) 30 | return 31 | } 32 | 33 | val duration = ParserUtils.parseTextTime(context.args[1], false) 34 | if (duration <= 0) { 35 | context.typedMessaging.replyDanger(context.i18n("responses.invalid_duration")) 36 | return 37 | } 38 | 39 | var reason: String? = null 40 | if (context.args.size > 2) { 41 | reason = context.getMessage(2) 42 | } 43 | 44 | CascadeBot.INS.moderationManager.tempMute( 45 | context, 46 | targetMember, 47 | sender, 48 | reason, 49 | duration 50 | ) 51 | } 52 | 53 | override fun command(): String = "tempmute" 54 | 55 | override fun module(): Module = Module.MODERATION 56 | 57 | override fun permission(): CascadePermission = CascadePermission.of("tempmute", false) 58 | 59 | } -------------------------------------------------------------------------------- /src/main/kotlin/org/cascadebot/cascadebot/data/objects/Greetings.kt: -------------------------------------------------------------------------------- 1 | package org.cascadebot.cascadebot.data.objects 2 | 3 | import net.dv8tion.jda.api.entities.TextChannel 4 | import net.dv8tion.jda.api.events.guild.member.GuildMemberJoinEvent 5 | import net.dv8tion.jda.api.events.guild.member.GuildMemberLeaveEvent 6 | import net.dv8tion.jda.api.events.guild.member.GuildMemberRemoveEvent 7 | import org.cascadebot.cascadebot.CascadeBot 8 | import org.cascadebot.cascadebot.data.language.Language 9 | import org.cascadebot.cascadebot.utils.lists.WeightedList 10 | import org.cascadebot.cascadebot.utils.placeholders.PlaceholderObjects 11 | 12 | class Greetings { 13 | 14 | var welcomeMessages: WeightedList = WeightedList() 15 | var welcomeDMMessages: WeightedList = WeightedList() 16 | var goodbyeMessages: WeightedList = WeightedList() 17 | 18 | private var welcomeChannelId: Long? = null 19 | 20 | var welcomeChannel: TextChannel? 21 | get() = welcomeChannelId?.let(CascadeBot.INS.shardManager::getTextChannelById) 22 | set(channel) { 23 | welcomeChannelId = channel?.idLong 24 | } 25 | 26 | val welcomeEnabled: Boolean 27 | get() = welcomeChannelId != null && welcomeMessages.size > 0 28 | 29 | val welcomeDMEnabled: Boolean 30 | get() = welcomeDMMessages.size > 0 31 | 32 | val goodbyeEnabled: Boolean 33 | get() = goodbyeMessages.size > 0 34 | 35 | fun getRandomWelcomeMsg(event: GuildMemberJoinEvent): String? { 36 | return welcomeMessages.randomItem?.let { 37 | PlaceholderObjects.welcomes.formatMessage(Language.getGuildLocale(event.guild.idLong), it, event) 38 | } 39 | } 40 | 41 | fun getRandomWelcomeDMMsg(event: GuildMemberJoinEvent): String? { 42 | return welcomeDMMessages.randomItem?.let { 43 | PlaceholderObjects.welcomes.formatMessage(Language.getGuildLocale(event.guild.idLong), it, event) 44 | } 45 | } 46 | 47 | fun getRandomGoodbyeMsg(event: GuildMemberRemoveEvent): String? { 48 | return goodbyeMessages.randomItem?.let { 49 | PlaceholderObjects.goodbyes.formatMessage(Language.getGuildLocale(event.guild.idLong), it, event) 50 | } 51 | } 52 | 53 | 54 | } -------------------------------------------------------------------------------- /src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildCommandInfo.kt: -------------------------------------------------------------------------------- 1 | package org.cascadebot.cascadebot.data.objects 2 | 3 | import org.cascadebot.cascadebot.commandmeta.MainCommand 4 | import org.cascadebot.cascadebot.data.language.Locale 5 | import org.cascadebot.cascadebot.utils.lists.ChangeList 6 | 7 | class GuildCommandInfo(var enabled: Boolean, 8 | val command: String, 9 | val locale: Locale, 10 | val aliases: ChangeList) { 11 | 12 | // Private constructor for MongoDB 13 | private constructor() : this(true, "", Locale.getDefaultLocale(), ChangeList()) 14 | 15 | constructor(command: MainCommand, locale: Locale) : 16 | this( 17 | true, 18 | command.command(), 19 | locale, 20 | ChangeList() 21 | ) 22 | 23 | } -------------------------------------------------------------------------------- /src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsManagement.kt: -------------------------------------------------------------------------------- 1 | package org.cascadebot.cascadebot.data.objects 2 | 3 | import org.cascadebot.cascadebot.commandmeta.Module 4 | import java.util.concurrent.ConcurrentHashMap 5 | 6 | @SettingsContainer(module = Module.MANAGEMENT) 7 | class GuildSettingsManagement { 8 | 9 | @Setting 10 | var allowTagCommands = true 11 | 12 | @Setting 13 | var displayFilterError = false 14 | 15 | @Setting 16 | var warnOver10Filters = true 17 | 18 | val tags: ConcurrentHashMap = ConcurrentHashMap() 19 | val filters: MutableList = mutableListOf() 20 | val permissions = GuildPermissions() 21 | val greetings = Greetings() 22 | val autoRoles: MutableSet = mutableSetOf() 23 | 24 | fun getTag(key: String): Tag? { 25 | return tags[key] 26 | } 27 | 28 | fun hasTag(key: String): Boolean { 29 | return tags.containsKey(key) 30 | } 31 | 32 | fun addTag(key: String, tag: Tag) { 33 | tags[key] = tag 34 | } 35 | 36 | fun removeTag(key: String): Boolean { 37 | return tags.remove(key) != null 38 | } 39 | 40 | } -------------------------------------------------------------------------------- /src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsModeration.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020 CascadeBot. All rights reserved. 3 | * Licensed under the MIT license. 4 | */ 5 | 6 | package org.cascadebot.cascadebot.data.objects 7 | 8 | import org.cascadebot.cascadebot.commandmeta.Module 9 | 10 | @SettingsContainer(module = Module.MODERATION) 11 | class GuildSettingsModeration { 12 | 13 | @Setting 14 | var purgePinnedMessages = false 15 | 16 | @Setting 17 | var respectBanOrKickHierarchy = true 18 | 19 | @Setting 20 | var muteRoleName = "Muted" 21 | 22 | } 23 | -------------------------------------------------------------------------------- /src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsMusic.kt: -------------------------------------------------------------------------------- 1 | package org.cascadebot.cascadebot.data.objects 2 | 3 | import org.cascadebot.cascadebot.commandmeta.Module 4 | import java.util.concurrent.ConcurrentHashMap 5 | 6 | @SettingsContainer(module = Module.MUSIC) 7 | class GuildSettingsMusic { 8 | 9 | // TODO: Handle reverting tier for preserve settings 10 | @Setting 11 | var preserveVolume = true 12 | 13 | @Setting 14 | var preserveEqualizer = true 15 | 16 | var volume = 100 17 | 18 | var equalizerBands: MutableMap = ConcurrentHashMap(); 19 | 20 | @Setting 21 | var joinOnPlay = true; 22 | 23 | } -------------------------------------------------------------------------------- /src/main/kotlin/org/cascadebot/cascadebot/events/BotEvents.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020 CascadeBot. All rights reserved. 3 | * Licensed under the MIT license. 4 | */ 5 | 6 | package org.cascadebot.cascadebot.events 7 | 8 | import net.dv8tion.jda.api.JDA 9 | import net.dv8tion.jda.api.events.ReadyEvent 10 | import net.dv8tion.jda.api.events.StatusChangeEvent 11 | import net.dv8tion.jda.api.hooks.ListenerAdapter 12 | import org.cascadebot.cascadebot.CascadeBot 13 | import org.cascadebot.cascadebot.UnicodeConstants 14 | import org.cascadebot.cascadebot.data.Config 15 | import org.cascadebot.cascadebot.messaging.MessageType 16 | import org.cascadebot.cascadebot.utils.FormatUtils 17 | 18 | class BotEvents : ListenerAdapter() { 19 | 20 | override fun onReady(event: ReadyEvent) { 21 | val shardManager = CascadeBot.INS.shardManager 22 | if (shardManager.shards.size == shardManager.shardsTotal) { 23 | CascadeBot.INS.run() 24 | Config.INS.eventWebhook.send( 25 | MessageType.SUCCESS.emoji + " All shards ready!" 26 | ) 27 | } 28 | } 29 | 30 | override fun onStatusChange(event: StatusChangeEvent) { 31 | @Suppress("NON_EXHAUSTIVE_WHEN") 32 | when (event.newStatus) { 33 | JDA.Status.CONNECTED, 34 | JDA.Status.DISCONNECTED, 35 | JDA.Status.RECONNECT_QUEUED, 36 | JDA.Status.ATTEMPTING_TO_RECONNECT, 37 | JDA.Status.SHUTTING_DOWN, 38 | JDA.Status.SHUTDOWN, 39 | JDA.Status.FAILED_TO_LOGIN -> Config.INS.eventWebhook.send(String.format( 40 | UnicodeConstants.ROBOT + " Status Update: `%s` to `%s` on shard: `%d`", 41 | FormatUtils.formatEnum(event.oldStatus), 42 | FormatUtils.formatEnum(event.newStatus), 43 | event.jda.shardInfo.shardId 44 | )) 45 | } 46 | } 47 | 48 | } -------------------------------------------------------------------------------- /src/main/kotlin/org/cascadebot/cascadebot/messaging/MessageType.kt: -------------------------------------------------------------------------------- 1 | package org.cascadebot.cascadebot.messaging 2 | 3 | import org.cascadebot.cascadebot.Constants 4 | import org.cascadebot.cascadebot.UnicodeConstants 5 | import java.awt.Color 6 | 7 | enum class MessageType(val color: Color, val emoji: String) { 8 | 9 | INFO(Constants.COLOR_INFO, UnicodeConstants.INFORMATION), 10 | SUCCESS(Constants.COLOR_SUCCESS, UnicodeConstants.TICK), 11 | WARNING(Constants.COLOR_WARNING, UnicodeConstants.WARNING), 12 | MODERATION(Constants.COLOR_MODERATION, UnicodeConstants.POLICE), 13 | DANGER(Constants.COLOR_DANGER, UnicodeConstants.RED_CROSS), 14 | NEUTRAL(Constants.COLOR_NEUTRAL, "") 15 | 16 | } -------------------------------------------------------------------------------- /src/main/kotlin/org/cascadebot/cascadebot/utils/interactions/CascadeComponent.kt: -------------------------------------------------------------------------------- 1 | package org.cascadebot.cascadebot.utils.interactions 2 | 3 | import net.dv8tion.jda.api.interactions.components.Component 4 | 5 | abstract class CascadeComponent(val id: String) { 6 | 7 | abstract val discordComponent : Component 8 | 9 | } -------------------------------------------------------------------------------- /src/main/kotlin/org/cascadebot/cascadebot/utils/interactions/CascadeLinkButton.kt: -------------------------------------------------------------------------------- 1 | package org.cascadebot.cascadebot.utils.interactions 2 | 3 | import net.dv8tion.jda.api.entities.Emoji 4 | import net.dv8tion.jda.api.interactions.components.Button 5 | import net.dv8tion.jda.api.interactions.components.ButtonStyle 6 | import net.dv8tion.jda.api.interactions.components.Component 7 | 8 | class CascadeLinkButton private constructor (val link: String, val label: String?, val emoji: Emoji?) : CascadeComponent(link) { 9 | override val discordComponent: Component = Button.of(ButtonStyle.LINK, link, label, emoji) 10 | 11 | init { 12 | require(label != null || emoji != null) { "Label and emoji cannot both be null" } 13 | } 14 | 15 | companion object { 16 | @JvmStatic 17 | fun of(link: String, label: String) = CascadeLinkButton(link, label, null) 18 | @JvmStatic 19 | fun of(link: String, emoji: Emoji) = CascadeLinkButton(link, null, emoji) 20 | @JvmStatic 21 | fun of(link: String, label: String, emoji: Emoji) = CascadeLinkButton(link, label, emoji) 22 | } 23 | 24 | } -------------------------------------------------------------------------------- /src/main/kotlin/org/cascadebot/cascadebot/utils/interactions/ComponentContainer.kt: -------------------------------------------------------------------------------- 1 | package org.cascadebot.cascadebot.utils.interactions 2 | 3 | class ComponentContainer { 4 | 5 | private val components: MutableList = 6 | mutableListOf() // TODO make this able to contain more then just action rows (will probably do when discord allows more then just action row) 7 | 8 | var persistent = false 9 | private set 10 | 11 | fun addRow(actionRow: CascadeActionRow) { 12 | doChecks(actionRow) 13 | components.add(actionRow) 14 | } 15 | 16 | fun setRow(pos: Int, actionRow: CascadeActionRow) { 17 | doChecks(actionRow) 18 | components[pos] = actionRow 19 | } 20 | 21 | fun getRow(pos: Int): CascadeActionRow { 22 | return components[pos] 23 | } 24 | 25 | private fun doChecks(actionRow: CascadeActionRow) { 26 | if (components.size == 0) { 27 | persistent = actionRow.isPersistent() 28 | } else { 29 | if (persistent && !actionRow.isPersistent()) { 30 | throw UnsupportedOperationException("Cannot add non-persistent rows to persistent containers") 31 | } 32 | } 33 | 34 | if (components.size >= 5) { 35 | throw UnsupportedOperationException("Cannot have more then 5 action rows!") 36 | } 37 | } 38 | 39 | fun getComponents(): List { 40 | return components.toList() 41 | } 42 | 43 | } -------------------------------------------------------------------------------- /src/main/kotlin/org/cascadebot/cascadebot/utils/interactions/InteractionMessage.kt: -------------------------------------------------------------------------------- 1 | package org.cascadebot.cascadebot.utils.interactions 2 | 3 | import net.dv8tion.jda.api.entities.Message 4 | import net.dv8tion.jda.api.entities.MessageEmbed 5 | import net.dv8tion.jda.api.requests.restaction.MessageAction 6 | 7 | class InteractionMessage(val message: Message, val container: ComponentContainer) { 8 | 9 | val idLong: Long = message.idLong 10 | 11 | fun editMessage(content: String): MessageAction { 12 | return message.editMessage(content).override(true).setActionRows(container.getComponents().map { it.toDiscordActionRow() }) 13 | } 14 | 15 | fun editMessage(embed: MessageEmbed): MessageAction { 16 | return message.editMessage(embed).override(true).setActionRows(container.getComponents().map { it.toDiscordActionRow() }) 17 | } 18 | 19 | fun editMessage(message: Message): MessageAction { 20 | return message.editMessage(message).override(true).setActionRows(container.getComponents().map { it.toDiscordActionRow() }) 21 | } 22 | 23 | fun notifyContainerChange(): MessageAction { 24 | return message.editMessageComponents().setActionRows(container.getComponents().map { it.toDiscordActionRow() }) 25 | } 26 | 27 | } -------------------------------------------------------------------------------- /src/main/kotlin/org/cascadebot/cascadebot/utils/lists/ChangeList.kt: -------------------------------------------------------------------------------- 1 | package org.cascadebot.cascadebot.utils.lists 2 | 3 | import java.util.Collections 4 | 5 | class ChangeList() { 6 | 7 | val addedItems 8 | get() = added.toSet() 9 | val removedItems 10 | get() = removed.toSet() 11 | 12 | private val added = Collections.synchronizedSet(HashSet()) 13 | private val removed = Collections.synchronizedSet(HashSet()) 14 | 15 | fun add(element: T): Boolean { 16 | if (!removed.remove(element)) { 17 | return added.add(element) 18 | } 19 | return true 20 | } 21 | 22 | fun remove(element: T): Boolean { 23 | if (!added.remove(element)) { 24 | return removed.add(element) 25 | } 26 | return true 27 | } 28 | 29 | fun applyChanges(baseCollection: Set): Set { 30 | val baseElements = baseCollection.toMutableSet() 31 | baseElements.addAll(added) 32 | baseElements.removeAll(removed) 33 | return baseElements 34 | } 35 | 36 | } -------------------------------------------------------------------------------- /src/main/resources/lang/languagetester/languagetester.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020 CascadeBot. All rights reserved. 3 | * Licensed under the MIT license. 4 | */ 5 | const fs = require("fs") 6 | 7 | const config = require("testerconfig.json") 8 | const file = require(config.sourceFile) 9 | 10 | function redact(object) { 11 | for (let key of Object.keys(object)) { 12 | if (object[key].constructor === Object) { 13 | redact(object[key]) 14 | } else if (config.ignoreArrays && object[key].constructor === Array) { 15 | continue 16 | } else { 17 | if (!config.keyBlacklist.includes(key)) { 18 | object[key] = config.textToReplace 19 | } 20 | } 21 | } 22 | return object 23 | } 24 | 25 | fs.writeFileSync(config.destinationFile, JSON.stringify(redact(file), null, 2)) -------------------------------------------------------------------------------- /src/main/resources/lang/languagetester/testerconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "keyBlacklist": ["command"], 3 | "ignoreArrays": true, 4 | "textToReplace": "dave", 5 | "sourceFile": "en-GB.json", 6 | "destinationFile": "en-GB-redacted.json" 7 | } -------------------------------------------------------------------------------- /src/main/resources/sentry.properties: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (c) 2019 CascadeBot. All rights reserved. 3 | # Licensed under the MIT license. 4 | # 5 | stacktrace.app.packages=com.cascadebot.cascadebot -------------------------------------------------------------------------------- /src/main/resources/version.txt: -------------------------------------------------------------------------------- 1 | ${project.version}_${build.number} -------------------------------------------------------------------------------- /src/test/java/org/cascadebot/cascadebot/move/TestListsObject.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020 CascadeBot. All rights reserved. 3 | * Licensed under the MIT license. 4 | */ 5 | 6 | package org.cascadebot.cascadebot.move; 7 | 8 | import java.util.List; 9 | 10 | public class TestListsObject { 11 | 12 | private List originalList; 13 | private List movedList; 14 | 15 | public TestListsObject(List originalList, List movedList) { 16 | this.originalList = originalList; 17 | this.movedList = movedList; 18 | } 19 | 20 | public List getOriginalList() { 21 | return originalList; 22 | } 23 | 24 | public List getMovedList() { 25 | return movedList; 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /src/test/java/org/cascadebot/cascadebot/move/TestMovableItem.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020 CascadeBot. All rights reserved. 3 | * Licensed under the MIT license. 4 | */ 5 | 6 | package org.cascadebot.cascadebot.move; 7 | 8 | import lombok.Getter; 9 | import org.cascadebot.cascadebot.utils.move.MovableItem; 10 | 11 | public class TestMovableItem implements MovableItem { 12 | 13 | @Getter 14 | private String name; 15 | 16 | TestMovableItem(String name) { 17 | this.name = name; 18 | } 19 | 20 | @Override 21 | public String getItemText() { 22 | return name; 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /src/test/kotlin/org/cascadebot/cascadebot/utils/ChangeListTest.kt: -------------------------------------------------------------------------------- 1 | package org.cascadebot.cascadebot.utils 2 | 3 | import org.cascadebot.cascadebot.utils.lists.ChangeList 4 | import org.junit.jupiter.api.Assertions.assertEquals 5 | import org.junit.jupiter.api.Assertions.assertTrue 6 | import org.junit.jupiter.api.Test 7 | 8 | 9 | class ChangeListTest { 10 | 11 | @Test 12 | fun `remove() removes from added list`() { 13 | val changeList = ChangeList() 14 | changeList.add("element") 15 | changeList.remove("element") 16 | 17 | assertTrue(changeList.addedItems.isEmpty()) 18 | assertTrue(changeList.removedItems.isEmpty()) 19 | } 20 | 21 | @Test 22 | fun `add() adds to removed list`() { 23 | val changeList = ChangeList() 24 | changeList.remove("element") 25 | changeList.add("element") 26 | 27 | assertTrue(changeList.addedItems.isEmpty()) 28 | assertTrue(changeList.removedItems.isEmpty()) 29 | } 30 | 31 | @Test 32 | fun `Remove from base collection`() { 33 | val changeList = ChangeList() 34 | changeList.remove("element") 35 | assertTrue(changeList.removedItems.contains("element")) 36 | assertEquals( 37 | changeList.applyChanges(mutableSetOf("element", "different")), 38 | setOf("different") 39 | ) 40 | } 41 | 42 | @Test 43 | fun `Add to base collection`() { 44 | val changeList = ChangeList() 45 | changeList.add("element") 46 | assertTrue(changeList.addedItems.contains("element")) 47 | assertEquals( 48 | changeList.applyChanges(mutableSetOf("different")), 49 | setOf("element", "different") 50 | ) 51 | } 52 | 53 | 54 | } --------------------------------------------------------------------------------