package nl.voidcorp.discord.command import net.dv8tion.jda.api.Permission import net.dv8tion.jda.api.entities.ChannelType import net.dv8tion.jda.api.events.message.MessageReceivedEvent import java.util.* abstract class Command( val name: String, val helpMesage: String = "", val usage: String = "", val aliases: List = emptyList(), val location: CommandSource = CommandSource.BOTH, val permissions: Set = emptySet() ) { fun onCommand(event: MessageReceivedEvent, prefix: String): CommandResult { val starts = event.message.contentRaw.drop(prefix.length).trim() .startsWith(name) or aliases.any { event.message.contentRaw.drop(prefix.length).trim().startsWith( it ) } return if (!starts) CommandResult.NOPE else when (location) { CommandSource.PRIVATE -> if (event.channelType == ChannelType.PRIVATE) guildStuff( event, event.message.contentRaw.drop(prefix.length).trim() ) else CommandResult.NOPE CommandSource.GUILD -> if (event.channelType == ChannelType.TEXT) privateStuff( event, event.message.contentRaw.drop(prefix.length).trim() ) else CommandResult.NOPE CommandSource.BOTH -> if (event.channelType == ChannelType.PRIVATE) guildStuff( event, event.message.contentRaw.drop(prefix.length).trim() ) else privateStuff(event, event.message.contentRaw.drop(prefix.length).trim()) } } private fun guildStuff(event: MessageReceivedEvent, str: String): CommandResult { val intersect = permissions.intersect(event.member?.permissions as Iterable) return if ((intersect.isNotEmpty() or permissions.isEmpty())) { handle(CommandMessage(event, translateCommandline(str))) } else CommandResult.PERMISSIONS } private fun privateStuff(event: MessageReceivedEvent, str: String): CommandResult { return handle(CommandMessage(event, translateCommandline(str))) } abstract fun handle(event: CommandMessage): CommandResult companion object { var settings = CommandSettings() /** * [code borrowed from ant.jar] * Crack a command line. * @param toProcess the command line to process. * @return the command line broken into strings. * An empty or null toProcess parameter results in a zero sized array. */ private fun translateCommandline(toProcess: String): List { if (toProcess.isEmpty()) { //no command? no string return emptyList() } // parse with a simple finite state machine val normal = 0 val inQuote = 1 val inDoubleQuote = 2 var state = normal val tok = StringTokenizer(toProcess, "\"\' ", true) val result = mutableListOf() val current = StringBuilder() var lastTokenHasBeenQuoted = false while (tok.hasMoreTokens()) { val nextTok = tok.nextToken() when (state) { inQuote -> if ("\'" == nextTok) { lastTokenHasBeenQuoted = true state = normal } else { current.append(nextTok) } inDoubleQuote -> if ("\"" == nextTok) { lastTokenHasBeenQuoted = true state = normal } else { current.append(nextTok) } else -> { if ("\'" == nextTok) { state = inQuote } else if ("\"" == nextTok) { state = inDoubleQuote } else if (" " == nextTok) { if (lastTokenHasBeenQuoted || current.isNotEmpty()) { result.add(current.toString()) current.setLength(0) } } else { current.append(nextTok) } lastTokenHasBeenQuoted = false } } } if (lastTokenHasBeenQuoted || current.isNotEmpty()) { result.add(current.toString()) } return result } } }