diff --git a/.gitignore b/.gitignore index a01c2fd..0f43b23 100644 --- a/.gitignore +++ b/.gitignore @@ -47,3 +47,6 @@ gradle-app.setting **/build/ # End of https://www.toptal.com/developers/gitignore/api/kotlin,gradle + + +.env \ No newline at end of file diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml new file mode 100644 index 0000000..1bec35e --- /dev/null +++ b/.idea/codeStyles/Project.xml @@ -0,0 +1,10 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/codeStyles/codeStyleConfig.xml b/.idea/codeStyles/codeStyleConfig.xml new file mode 100644 index 0000000..79ee123 --- /dev/null +++ b/.idea/codeStyles/codeStyleConfig.xml @@ -0,0 +1,5 @@ + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..a2e2410 --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/votebot.iml b/.idea/votebot.iml new file mode 100644 index 0000000..f100729 --- /dev/null +++ b/.idea/votebot.iml @@ -0,0 +1,12 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/kotlin/dev/schlaubi/votebot/commands/ClaimPermissionsCommand.kt b/src/main/kotlin/dev/schlaubi/votebot/commands/ClaimPermissionsCommand.kt index 10c248e..4aae022 100644 --- a/src/main/kotlin/dev/schlaubi/votebot/commands/ClaimPermissionsCommand.kt +++ b/src/main/kotlin/dev/schlaubi/votebot/commands/ClaimPermissionsCommand.kt @@ -23,6 +23,7 @@ import dev.kord.common.entity.Permission import dev.schlaubi.votebot.command.SingleCommand import dev.schlaubi.votebot.command.context.Context import dev.schlaubi.votebot.command.context.response.respond +import dev.schlaubi.votebot.util.Embeds import dev.schlaubi.votebot.util.appendPermission import dev.schlaubi.votebot.util.getCommands import kotlinx.coroutines.flow.first @@ -35,7 +36,7 @@ object ClaimPermissionsCommand : SingleCommand() { override suspend fun execute(context: Context) { if (Permission.Administrator !in context.executor.asMember().getPermissions()) { - context.respond("You need the `ADMINISTRATOR` permission to execute this command") + context.respond(Embeds.error("You need the `ADMINISTRATOR` permission to execute this command")) return } @@ -49,6 +50,6 @@ object ClaimPermissionsCommand : SingleCommand() { user(context.executor.id, true) } - context.respond("You now have access to /permissions") + context.respond(Embeds.info("You now have access to /permissions")) } } diff --git a/src/main/kotlin/dev/schlaubi/votebot/commands/InfoCommand.kt b/src/main/kotlin/dev/schlaubi/votebot/commands/InfoCommand.kt index 1f38e48..434204e 100644 --- a/src/main/kotlin/dev/schlaubi/votebot/commands/InfoCommand.kt +++ b/src/main/kotlin/dev/schlaubi/votebot/commands/InfoCommand.kt @@ -22,6 +22,7 @@ package dev.schlaubi.votebot.commands import dev.schlaubi.votebot.command.SingleCommand import dev.schlaubi.votebot.command.context.Context import dev.schlaubi.votebot.command.context.response.respond +import dev.schlaubi.votebot.util.Embeds object InfoCommand : SingleCommand() { override val description: String = "Displays basic information about the bot" @@ -29,6 +30,6 @@ object InfoCommand : SingleCommand() { override val useEphemeral: Boolean = true override suspend fun execute(context: Context) { - context.respond("Coming soon :tm:") + context.respond(Embeds.info("Coming soon :tm:")) } } diff --git a/src/main/kotlin/dev/schlaubi/votebot/commands/PermissionCommand.kt b/src/main/kotlin/dev/schlaubi/votebot/commands/PermissionCommand.kt index 7537702..25f0a58 100644 --- a/src/main/kotlin/dev/schlaubi/votebot/commands/PermissionCommand.kt +++ b/src/main/kotlin/dev/schlaubi/votebot/commands/PermissionCommand.kt @@ -26,6 +26,7 @@ import dev.schlaubi.votebot.command.SubCommand import dev.schlaubi.votebot.command.context.Context import dev.schlaubi.votebot.command.context.response.respond import dev.schlaubi.votebot.config.Config +import dev.schlaubi.votebot.util.Embeds import dev.schlaubi.votebot.util.addCommand import dev.schlaubi.votebot.util.appendPermission import dev.schlaubi.votebot.util.buildCommands @@ -107,7 +108,7 @@ suspend fun doPermissions( val command = commands.firstOrNull { it.name == commandName } if (command == null) { - context.respond("Unknown command") + context.respond(Embeds.error("Unknown command")) return } @@ -119,5 +120,5 @@ suspend fun doPermissions( addPermission(context.boolean("permission")) } - context.respond("Permission was updated!") + context.respond(Embeds.success("Permission was updated!")) } diff --git a/src/main/kotlin/dev/schlaubi/votebot/util/Colors.kt b/src/main/kotlin/dev/schlaubi/votebot/util/Colors.kt new file mode 100644 index 0000000..3c7f8eb --- /dev/null +++ b/src/main/kotlin/dev/schlaubi/votebot/util/Colors.kt @@ -0,0 +1,49 @@ +/* + * Votebot - A feature-rich bot to create votes on Discord guilds. + * + * Copyright (C) 2019-2021 Michael Rittmeister & Yannick Seeger + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see https://www.gnu.org/licenses/. + */ + +package dev.schlaubi.votebot.util + +import dev.kord.common.Color + +/** + * Wrapper for [Discordapp.com/branding][https://discordapp.com/branding] colors and some other colors: + */ +@Suppress("KDocMissingDocumentation", "unused", "MagicNumber") +object Colors { + // Discord + val BLURLPLE: Color = Color(88, 101, 242) + val GREEN: Color = Color(87, 242, 135) + val YELLOW: Color = Color(254, 231, 92) + val FUCHSIA: Color = Color(235, 69, 158) + val RED: Color = Color(237, 66, 69) + val WHITE: Color = Color(255, 255, 255) + val BLACK: Color = Color(0, 0, 0) + + // Old Discord Branding Colors + val GREYPLE: Color = Color(153, 170, 181) + val DARK_BUT_NOT_BLACK: Color = Color(44, 47, 51) + val NOT_QUITE_BLACK: Color = Color(33, 39, 42) + + // Other colors + val LIGHT_RED: Color = Color(231, 76, 60) + val DARK_RED: Color = Color(192, 57, 43) + val LIGHT_GREEN: Color = Color(46, 204, 113) + val DARK_GREEN: Color = Color(39, 174, 96) + val BLUE: Color = Color(52, 152, 219) +} diff --git a/src/main/kotlin/dev/schlaubi/votebot/util/Embeds.kt b/src/main/kotlin/dev/schlaubi/votebot/util/Embeds.kt new file mode 100644 index 0000000..30b5242 --- /dev/null +++ b/src/main/kotlin/dev/schlaubi/votebot/util/Embeds.kt @@ -0,0 +1,145 @@ +/* + * Votebot - A feature-rich bot to create votes on Discord guilds. + * + * Copyright (C) 2019-2021 Michael Rittmeister & Yannick Seeger + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see https://www.gnu.org/licenses/. + */ + +package dev.schlaubi.votebot.util + +import dev.kord.core.behavior.MessageBehavior +import dev.kord.core.behavior.channel.MessageChannelBehavior +import dev.kord.core.behavior.channel.createMessage +import dev.kord.core.behavior.edit +import dev.kord.core.entity.Message +import dev.kord.rest.builder.message.EmbedBuilder + +/** + * Defines a creator of an embed. + */ +typealias EmbedCreator = EmbedBuilder.() -> Unit + +/** + * Some presets for frequently used embeds. + */ +@Suppress("unused", "TooManyFunctions") +object Embeds { + + /** + * Creates a info embed with the given [title] and [description] and applies the [builder] to it. + * @see EmbedCreator + * @see EmbedBuilder + */ + fun info(title: String, description: String? = null, builder: EmbedCreator = {}): EmbedBuilder = + embed { + title(Emotes.INFO, title) + this.description = description + color = Colors.BLUE + }.apply(builder) + + /** + * Creates a success embed with the given [title] and [description] and applies the [builder] to it. + * @see EmbedCreator + * @see EmbedBuilder + */ + fun success( + title: String, + description: String? = null, + builder: EmbedCreator = {} + ): EmbedBuilder = + embed { + title(Emotes.SUCCESS, title) + this.description = description + color = Colors.GREEN + }.apply(builder) + + /** + * Creates a error embed with the given [title] and [description] and applies the [builder] to it. + * @see EmbedCreator + * @see EmbedBuilder + */ + fun error( + title: String, + description: String? = null, + builder: EmbedCreator = {} + ): EmbedBuilder = + embed { + title(Emotes.ERROR, title) + this.description = description + color = Colors.RED + }.apply(builder) + + /** + * Creates a warning embed with the given [title] and [description] and applies the [builder] to it. + * @see EmbedCreator + * @see EmbedBuilder + */ + fun warn( + title: String, + description: String? = null, + builder: EmbedCreator = {} + ): EmbedBuilder = + embed { + title(Emotes.WARN, title) + this.description = description + color = Colors.YELLOW + }.apply(builder) + + /** + * Creates a loading embed with the given [title] and [description] and applies the [builder] to it. + * @see EmbedCreator + * @see EmbedBuilder + */ + fun loading( + title: String, + description: String?, + builder: EmbedCreator = {} + ): EmbedBuilder = + embed { + title(Emotes.LOADING, title) + this.description = description + color = Colors.DARK_BUT_NOT_BLACK + }.apply(builder) + + private fun EmbedBuilder.title(emote: String, title: String) { + this.title = "$emote $title" + } + + /** + * Sends a new message in this channel containing the embed provided by [base] and applies [creator] to it + */ + suspend fun MessageChannelBehavior.createEmbed( + base: EmbedBuilder, + creator: suspend EmbedBuilder.() -> Unit = {} + ): Message { + return createMessage { + creator(base) + embed = base + } + } + + /** + * Sends a new message in this channel containing the embed provided by [base] and applies [creator] to it + */ + suspend fun MessageBehavior.editEmbed( + base: EmbedBuilder, + creator: suspend EmbedBuilder.() -> Unit = {} + ): Message { + return edit { + creator(base) + embed = base + } + } +} diff --git a/src/main/kotlin/dev/schlaubi/votebot/util/Emotes.kt b/src/main/kotlin/dev/schlaubi/votebot/util/Emotes.kt new file mode 100644 index 0000000..ae86d26 --- /dev/null +++ b/src/main/kotlin/dev/schlaubi/votebot/util/Emotes.kt @@ -0,0 +1,36 @@ +/* + * Votebot - A feature-rich bot to create votes on Discord guilds. + * + * Copyright (C) 2019-2021 Michael Rittmeister & Yannick Seeger + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see https://www.gnu.org/licenses/. + */ + +package dev.schlaubi.votebot.util + +/** + * Useful collection of Discord emotes. + * + * + * Designed by [Rxsto#1337](https://rxsto.me) + * Bot needs to be on [https://discord.gg/8phqcej](https://discord.gg/8phqcej) + */ +@Suppress("KDocMissingDocumentation") +object Emotes { + const val LOADING: String = "" + const val ERROR: String = "<:error:535827110489620500>" + const val WARN: String = "<:warn:535832532365737987>" + const val INFO: String = "<:info:535828529573789696>" + const val SUCCESS: String = "<:success:535827110552666112>" +}