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 {
val DEFAULT = CustomCommand()
fun getReplacements(user: String, userId: String, server: String, args: String): Map<String, () -> String> = mapOf(
"{uptime}" to instance::getUptimeAsString,

View File

@ -1,60 +1,64 @@
package matterlink.config
import com.google.gson.Gson
import com.google.gson.GsonBuilder
import com.google.gson.JsonSyntaxException
import com.google.gson.reflect.TypeToken
import matterlink.RegexDeSerializer
import blue.endless.jankson.Jankson
import blue.endless.jankson.JsonObject
import blue.endless.jankson.JsonPrimitive
import blue.endless.jankson.impl.Marshaller
import blue.endless.jankson.impl.SyntaxError
import matterlink.bridge.command.CommandType
import matterlink.bridge.command.CustomCommand
import matterlink.instance
import matterlink.stackTraceString
import java.io.File
import java.util.regex.PatternSyntaxException
import java.io.FileNotFoundException
typealias CommandMap = MutableMap<String, CustomCommand>
typealias DefaultCommands = Map<String, Pair<String, CustomCommand>>
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 default = hashMapOf(
"tps" to CustomCommand(
private val default: DefaultCommands = mapOf(
"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,
execute = "forge tps",
help = "Print server tps",
timeout = 200,
defaultCommand = true
),
"list" to CustomCommand(
)),
"list" to ("lists all the players, this is just a straight pass-through"
to CustomCommand(
type = CommandType.EXECUTE,
execute = "list",
help = "List online players",
defaultCommand = true
),
"seed" to CustomCommand(
)),
"seed" to ("another straight pass-through"
to CustomCommand(
type = CommandType.EXECUTE,
execute = "seed",
help = "Print server world seed",
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,
response = "{uptime}",
help = "Print server uptime",
defaultCommand = true
),
"whoami" to CustomCommand(
)),
"whoami" to ("this shows you some of the other response macros"
to CustomCommand(
type = CommandType.RESPONSE,
response = "server: `{server}` userid: `{userid}` user: `{user}`",
help = "Print debug user data",
timeout = 200,
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,
execute = "{args}",
argumentsRegex = ".*".toRegex(),
@ -62,40 +66,73 @@ object CommandConfig {
help = "Execute any command as OP, be careful with this one",
execOp = true,
defaultCommand = true
)
))
)
var commands: CommandMap = default
private set
val commands: CommandMap = hashMapOf()
fun readConfig(): Boolean {
if (!configFile.exists() || configFile.readText().isBlank()) {
configFile.createNewFile()
configFile.writeText(gson.toJson(default))
commands = default
return true
}
val jankson = Jankson
.builder()
.registerTypeAdapter(CustomCommand::class.java) { jsonObj ->
with(CustomCommand.DEFAULT) {
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
}
}
configFile.writeText(gson.toJson(commands))
} catch (e: JsonSyntaxException) {
instance.fatal(e.stackTraceString)
instance.fatal("failed to parse $configFile, using last good values as fallback")
.build()
return false
} catch (e: PatternSyntaxException) {
instance.fatal(e.stackTraceString)
instance.fatal("failed to parse regex in $configFile, using last good values as fallback")
return false
Marshaller.getFallback().registerSerializer(Regex::class.java) {
JsonPrimitive(it.pattern)
}
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
}

View File

@ -1,46 +1,69 @@
package matterlink.config
import com.google.gson.Gson
import com.google.gson.GsonBuilder
import com.google.gson.JsonSyntaxException
import com.google.gson.reflect.TypeToken
import blue.endless.jankson.Jankson
import blue.endless.jankson.JsonObject
import blue.endless.jankson.impl.Marshaller
import blue.endless.jankson.impl.SyntaxError
import matterlink.instance
import matterlink.stackTraceString
import java.io.File
import java.io.FileNotFoundException
typealias PermissionMap = Map<String, Map<String, Double>>
typealias PermissionMap = MutableMap<String, MutableMap<String, Double>>
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 default = mapOf(
"irc.esper" to mapOf(
"~nikky@nikky.moe" to 0.0,
"user@example." to 0.0
"~nikky@nikky.moe" to (0.0 to "IRC users are identified by their username and hostmask"),
"user@example.com" to (0.0 to "")
),
"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 {
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.writeText(gson.toJson(default))
return true
JsonObject()
}
try {
perms =gson.fromJson(configFile.readText(), object : TypeToken<PermissionMap>() {}.type)
} catch (e: JsonSyntaxException) {
instance.fatal(e.stackTraceString)
instance.fatal("failed to parse $configFile using last good values as fallback")
return true
default.forEach { platform, userMap ->
val jsonUserMap = jsonObject.getOrDefault(platform, JsonObject()) as JsonObject
userMap.forEach { user, (powerlevel, comment) ->
instance.trace("loading platform: $platform user: $user powwerlevel: $powerlevel")
val element = Marshaller.getFallback().serialize(powerlevel)
jsonUserMap.putDefault(user, element, comment.takeUnless { it.isBlank() })
}
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
}
}