implemented jankson loading for commands and permissions

This commit is contained in:
nikky 2018-06-24 13:58:38 +02:00
parent 240bff1677
commit f24ba763ac
3 changed files with 132 additions and 71 deletions

View File

@ -88,6 +88,7 @@ data class CustomCommand(
} }
companion object { companion object {
val DEFAULT = CustomCommand()
fun getReplacements(user: String, userId: String, server: String, args: String): Map<String, () -> String> = mapOf( fun getReplacements(user: String, userId: String, server: String, args: String): Map<String, () -> String> = mapOf(
"{uptime}" to instance::getUptimeAsString, "{uptime}" to instance::getUptimeAsString,

View File

@ -1,60 +1,64 @@
package matterlink.config package matterlink.config
import com.google.gson.Gson import blue.endless.jankson.Jankson
import com.google.gson.GsonBuilder import blue.endless.jankson.JsonObject
import com.google.gson.JsonSyntaxException import blue.endless.jankson.JsonPrimitive
import com.google.gson.reflect.TypeToken import blue.endless.jankson.impl.Marshaller
import matterlink.RegexDeSerializer import blue.endless.jankson.impl.SyntaxError
import matterlink.bridge.command.CommandType import matterlink.bridge.command.CommandType
import matterlink.bridge.command.CustomCommand import matterlink.bridge.command.CustomCommand
import matterlink.instance import matterlink.instance
import matterlink.stackTraceString
import java.io.File import java.io.File
import java.util.regex.PatternSyntaxException import java.io.FileNotFoundException
typealias CommandMap = MutableMap<String, CustomCommand> typealias CommandMap = MutableMap<String, CustomCommand>
typealias DefaultCommands = Map<String, Pair<String, CustomCommand>>
object CommandConfig { object CommandConfig {
private val gson: Gson = GsonBuilder()
.registerTypeAdapter(Regex::class.java, RegexDeSerializer)
.setPrettyPrinting()
.create()
private val configFile: File = cfg.cfgDirectory.resolve("commands.json") private val configFile: File = cfg.cfgDirectory.resolve("commands.json")
private val default = hashMapOf( private val default: DefaultCommands = mapOf(
"tps" to CustomCommand( "tps" to ("""Your run off the mill tps commands, change it to /sampler tps or /cofh tps if you like
|make sure to disable defaultCommand if you want your edits to have any effect
""".trimMargin()
to CustomCommand(
type = CommandType.EXECUTE, type = CommandType.EXECUTE,
execute = "forge tps", execute = "forge tps",
help = "Print server tps", help = "Print server tps",
timeout = 200, timeout = 200,
defaultCommand = true defaultCommand = true
), )),
"list" to CustomCommand( "list" to ("lists all the players, this is just a straight pass-through"
to CustomCommand(
type = CommandType.EXECUTE, type = CommandType.EXECUTE,
execute = "list", execute = "list",
help = "List online players", help = "List online players",
defaultCommand = true defaultCommand = true
), )),
"seed" to CustomCommand( "seed" to ("another straight pass-through"
to CustomCommand(
type = CommandType.EXECUTE, type = CommandType.EXECUTE,
execute = "seed", execute = "seed",
help = "Print server world seed", help = "Print server world seed",
defaultCommand = true defaultCommand = true
), )),
"uptime" to CustomCommand( "uptime" to ("this is a reponse command, it uses the uptime function, time since the mod was first loaded"
to CustomCommand(
type = CommandType.RESPONSE, type = CommandType.RESPONSE,
response = "{uptime}", response = "{uptime}",
help = "Print server uptime", help = "Print server uptime",
defaultCommand = true defaultCommand = true
), )),
"whoami" to CustomCommand( "whoami" to ("this shows you some of the other response macros"
to CustomCommand(
type = CommandType.RESPONSE, type = CommandType.RESPONSE,
response = "server: `{server}` userid: `{userid}` user: `{user}`", response = "server: `{server}` userid: `{userid}` user: `{user}`",
help = "Print debug user data", help = "Print debug user data",
timeout = 200, timeout = 200,
defaultCommand = true defaultCommand = true
), )),
"exec" to CustomCommand( "exec" to ("this uses arguments in a passed-through command, you could restrict the arguments with a regex"
to CustomCommand(
type = CommandType.EXECUTE, type = CommandType.EXECUTE,
execute = "{args}", execute = "{args}",
argumentsRegex = ".*".toRegex(), argumentsRegex = ".*".toRegex(),
@ -62,40 +66,73 @@ object CommandConfig {
help = "Execute any command as OP, be careful with this one", help = "Execute any command as OP, be careful with this one",
execOp = true, execOp = true,
defaultCommand = true defaultCommand = true
) ))
) )
var commands: CommandMap = default val commands: CommandMap = hashMapOf()
private set
fun readConfig(): Boolean { fun readConfig(): Boolean {
if (!configFile.exists() || configFile.readText().isBlank()) { val jankson = Jankson
configFile.createNewFile() .builder()
configFile.writeText(gson.toJson(default)) .registerTypeAdapter(CustomCommand::class.java) { jsonObj ->
commands = default with(CustomCommand.DEFAULT) {
return true CustomCommand(
} type = jsonObj.get(String::class.java, "type")?.let { CommandType.valueOf(it) }
?: type,
execute = jsonObj.get(String::class.java, "execute") ?: execute,
response = jsonObj.get(String::class.java, "response") ?: response,
permLevel = jsonObj.get(Double::class.java, "permLevel") ?: permLevel,
help = jsonObj.get(String::class.java, "help") ?: help,
timeout = jsonObj.get(Int::class.java, "timeout") ?: timeout,
defaultCommand = jsonObj.get(Boolean::class.java, "defaultCommand") ?: defaultCommand,
execOp = jsonObj.get(Boolean::class.java, "execOp") ?: execOp,
argumentsRegex = jsonObj.get(String::class.java, "argumentsRegex")?.toRegex()
?: argumentsRegex
)
}
try {
commands = gson.fromJson(configFile.readText(), object : TypeToken<CommandMap>() {}.type)
commands.filterValues { it.defaultCommand ?: false }.forEach { commands.remove(it.key) }
default.forEach { k, v ->
if (!commands.containsKey(k)) {
commands[k] = v
} }
} .build()
configFile.writeText(gson.toJson(commands))
} catch (e: JsonSyntaxException) {
instance.fatal(e.stackTraceString)
instance.fatal("failed to parse $configFile, using last good values as fallback")
return false Marshaller.getFallback().registerSerializer(Regex::class.java) {
} catch (e: PatternSyntaxException) { JsonPrimitive(it.pattern)
instance.fatal(e.stackTraceString)
instance.fatal("failed to parse regex in $configFile, using last good values as fallback")
return false
} }
Marshaller.getFallback().registerSerializer(CommandType::class.java) {
JsonPrimitive(it.name)
}
val jsonObject = try {
jankson.load(configFile)
} catch (e: SyntaxError) {
instance.error("error parsing config: ${e.completeMessage}")
JsonObject()
} catch (e: FileNotFoundException) {
configFile.createNewFile()
JsonObject()
}
// clear commands
commands.clear()
jsonObject.forEach { key, element ->
instance.trace("loading command '$key'")
val command = jankson.fromJson(element.toJson(), CustomCommand::class.java)
commands[key] = command
}
//apply defaults
default.forEach { k, (comment, defCommand) ->
val command = commands[k]
if (command == null || command.defaultCommand == true) {
commands[k] = defCommand
val element = Marshaller.getFallback().serialize(defCommand)
jsonObject.putDefault(k, element, comment)
}
}
instance.debug("loaded jsonObj: $jsonObject")
instance.debug("loaded commandMap: $commands")
configFile.writeText(jsonObject.toJson(true, true))
return true return true
} }

View File

@ -1,46 +1,69 @@
package matterlink.config package matterlink.config
import com.google.gson.Gson import blue.endless.jankson.Jankson
import com.google.gson.GsonBuilder import blue.endless.jankson.JsonObject
import com.google.gson.JsonSyntaxException import blue.endless.jankson.impl.Marshaller
import com.google.gson.reflect.TypeToken import blue.endless.jankson.impl.SyntaxError
import matterlink.instance import matterlink.instance
import matterlink.stackTraceString
import java.io.File import java.io.File
import java.io.FileNotFoundException
typealias PermissionMap = Map<String, Map<String, Double>> typealias PermissionMap = MutableMap<String, MutableMap<String, Double>>
object PermissionConfig { object PermissionConfig {
private val gson: Gson = GsonBuilder().setPrettyPrinting().create() private val jankson = Jankson
.builder()
.build()
private val configFile: File = cfg.cfgDirectory.resolve("permissions.json") private val configFile: File = cfg.cfgDirectory.resolve("permissions.json")
private val default = mapOf( private val default = mapOf(
"irc.esper" to mapOf( "irc.esper" to mapOf(
"~nikky@nikky.moe" to 0.0, "~nikky@nikky.moe" to (0.0 to "IRC users are identified by their username and hostmask"),
"user@example." to 0.0 "user@example.com" to (0.0 to "")
), ),
"discord.game" to mapOf( "discord.game" to mapOf(
"112228624366575616" to 0.0 "112228624366575616" to (0.0 to "thats a discord user id")
) )
) )
var perms: PermissionMap = default var perms: PermissionMap = mutableMapOf()
private var jsonObject: JsonObject = JsonObject()
fun loadPermFile(): Boolean { fun loadPermFile(): Boolean {
if (!configFile.exists() || configFile.readText().isBlank()) { jsonObject = try {
jankson.load(configFile)
} catch (e: SyntaxError) {
instance.error("error parsing config: ${e.completeMessage}")
JsonObject()
} catch (e: FileNotFoundException) {
configFile.createNewFile() configFile.createNewFile()
configFile.writeText(gson.toJson(default)) JsonObject()
return true
} }
try { default.forEach { platform, userMap ->
perms =gson.fromJson(configFile.readText(), object : TypeToken<PermissionMap>() {}.type) val jsonUserMap = jsonObject.getOrDefault(platform, JsonObject()) as JsonObject
} catch (e: JsonSyntaxException) { userMap.forEach { user, (powerlevel, comment) ->
instance.fatal(e.stackTraceString) instance.trace("loading platform: $platform user: $user powwerlevel: $powerlevel")
instance.fatal("failed to parse $configFile using last good values as fallback") val element = Marshaller.getFallback().serialize(powerlevel)
jsonUserMap.putDefault(user, element, comment.takeUnless { it.isBlank() })
return true }
jsonObject[platform] = jsonUserMap
} }
return false
jsonObject.forEach { platform, jsonUserMap ->
val userMap = perms[platform] ?: mutableMapOf()
if (jsonUserMap is JsonObject) {
jsonUserMap.forEach { user, powerlevel ->
instance.info("$platform $user $powerlevel")
userMap[user] = jsonUserMap.get(Double::class.java, user) ?: 0.0
}
}
perms[platform] = userMap
}
configFile.writeText(jsonObject.toJson(true, true))
return true
} }
} }