ottobotv2/src/main/kotlin/nl/voidcorp/discord/command/Command.kt

125 lines
4.6 KiB
Kotlin

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<String> = emptyList(),
val location: CommandSource = CommandSource.BOTH,
val permissions: Set<Permission> = 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<Permission>)
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<String> {
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<String>()
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
}
}
}