mirror of
https://github.com/HMCore/Orbot.git
synced 2026-01-21 17:32:48 +00:00
Change CLI to use kordx.commands
This commit is contained in:
2
.gitignore
vendored
2
.gitignore
vendored
@@ -1,5 +1,5 @@
|
|||||||
servers.json
|
servers.json
|
||||||
admin.json
|
config.json
|
||||||
service_channels.json
|
service_channels.json
|
||||||
*.hprof
|
*.hprof
|
||||||
/build
|
/build
|
||||||
|
|||||||
@@ -31,9 +31,9 @@ the bot should message you on Discord.
|
|||||||
|
|
||||||
*Note:* You need to invite the bot into a server before it can message you.
|
*Note:* You need to invite the bot into a server before it can message you.
|
||||||
|
|
||||||
Run it once (it should crash or print an error), so `admin.json`, `servers.json` and `service_channels.json`
|
Run it once (it should crash or print an error), so `config.json`, `servers.json` and `service_channels.json`
|
||||||
are being created.
|
are being created.
|
||||||
Add your Discord ID `adminId` (not name), Bot token `token`, and update frequency `updateMs` to the `admin.json`,
|
Add your Discord ID `adminId` (not name), Bot token `token`, and update frequency `updateMs` to the `config.json`,
|
||||||
optionally you can add your own messages for when the bot is looking and when it can't reach Hytale Servers.
|
optionally you can add your own messages for when the bot is looking and when it can't reach Hytale Servers.
|
||||||
|
|
||||||
If you verified that everything works correctly, you can start the server in the background, on Linux that is
|
If you verified that everything works correctly, you can start the server in the background, on Linux that is
|
||||||
@@ -59,7 +59,7 @@ I developed it under Windows, and had some trouble compiling it on Linux. You mi
|
|||||||
| !help | | Show a help dialog with all these commands |
|
| !help | | Show a help dialog with all these commands |
|
||||||
|
|
||||||
These commands will only work by private messaging the bot (and will be ignored if they don't
|
These commands will only work by private messaging the bot (and will be ignored if they don't
|
||||||
come from the admin registered in the `admin.json`.
|
come from the admin registered in the `config.json`.
|
||||||
|
|
||||||
## TODO
|
## TODO
|
||||||
|
|
||||||
|
|||||||
@@ -1,141 +1,82 @@
|
|||||||
package de.wulkanat
|
package de.wulkanat
|
||||||
|
|
||||||
import kotlinx.serialization.json.Json
|
import com.gitlab.kordlib.common.entity.Snowflake
|
||||||
import kotlinx.serialization.json.JsonConfiguration
|
import com.gitlab.kordlib.core.Kord
|
||||||
import net.dv8tion.jda.api.EmbedBuilder
|
import com.gitlab.kordlib.core.behavior.channel.createEmbed
|
||||||
import net.dv8tion.jda.api.JDA
|
import com.gitlab.kordlib.core.entity.User
|
||||||
import net.dv8tion.jda.api.entities.Activity
|
import com.gitlab.kordlib.rest.builder.message.EmbedBuilder
|
||||||
import net.dv8tion.jda.api.entities.MessageEmbed
|
import de.wulkanat.files.Config
|
||||||
import net.dv8tion.jda.api.entities.User
|
import de.wulkanat.files.ServiceChannels
|
||||||
|
import kotlinx.coroutines.GlobalScope
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
import java.awt.Color
|
import java.awt.Color
|
||||||
|
|
||||||
object Admin {
|
object Admin {
|
||||||
val userId: Long
|
var jda: Kord? = null
|
||||||
val token: String
|
|
||||||
val updateMs: Long
|
|
||||||
val message: String
|
|
||||||
val offlineMessage: String
|
|
||||||
|
|
||||||
init {
|
|
||||||
val admin = Json(JsonConfiguration.Stable).parse(AdminFile.serializer(), ADMIN_FILE.readText())
|
|
||||||
userId = admin.adminId
|
|
||||||
token = admin.token
|
|
||||||
updateMs = admin.updateMs
|
|
||||||
message = admin.watchingMessage
|
|
||||||
offlineMessage = admin.offlineMessage
|
|
||||||
}
|
|
||||||
|
|
||||||
var jda: JDA? = null
|
|
||||||
set(value) {
|
set(value) {
|
||||||
field = value
|
field = value
|
||||||
|
|
||||||
admin = value?.retrieveUserById(userId)?.complete()
|
GlobalScope.launch {
|
||||||
if (admin == null) {
|
admin = value?.getUser(Snowflake(Config.adminId))
|
||||||
kotlin.io.println("Connection to de.wulkanat.Admin failed!")
|
if (admin == null) {
|
||||||
} else {
|
kotlin.io.println("Connection to de.wulkanat.Admin failed!")
|
||||||
kotlin.io.println("Connected to ${admin!!.name}. No further errors will be printed here.")
|
} else {
|
||||||
|
kotlin.io.println("Connected to ${admin!!.username}. No further errors will be printed here.")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var admin: User? = null
|
var admin: User? = null
|
||||||
|
|
||||||
fun println(msg: String) {
|
suspend fun println(msg: String) {
|
||||||
sendDevMessage(
|
sendDevMessage(msg) {
|
||||||
EmbedBuilder()
|
title = msg
|
||||||
.setTitle(msg)
|
color = Color.WHITE
|
||||||
.setColor(Color.WHITE)
|
}
|
||||||
.build(),
|
|
||||||
msg
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun printlnBlocking(msg: String) {
|
suspend fun error(msg: String, error: String, author: User? = null) {
|
||||||
senDevMessageBlocking(
|
sendDevMessage("$msg\n\n$error") {
|
||||||
EmbedBuilder()
|
title = msg
|
||||||
.setTitle(msg)
|
description = error
|
||||||
.setColor(Color.WHITE)
|
color = Color.RED
|
||||||
.build(),
|
author?.let { author {
|
||||||
msg
|
name = it.tag
|
||||||
)
|
icon = it.avatar.url
|
||||||
|
url = it.avatar.url
|
||||||
|
}}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun error(msg: String, error: String, author: User? = null) {
|
suspend fun warning(msg: String) {
|
||||||
sendDevMessage(
|
sendDevMessage(msg) {
|
||||||
EmbedBuilder()
|
title = msg
|
||||||
.setTitle(msg)
|
color = Color.YELLOW
|
||||||
.setDescription(error)
|
}
|
||||||
.setColor(Color.RED)
|
|
||||||
.run {
|
|
||||||
if (author == null) {
|
|
||||||
this
|
|
||||||
} else {
|
|
||||||
this.setAuthor(author.asTag, author.avatarUrl, author.avatarUrl)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.build()
|
|
||||||
, "$msg\n\n${error}"
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun errorBlocking(msg: String, error: Exception) {
|
suspend fun info() {
|
||||||
senDevMessageBlocking(
|
sendDevMessage("Now watching for new Hytale BlogPosts") {
|
||||||
EmbedBuilder()
|
title = "Now watching for new Hytale Blogposts every ${Config.updateMs / 1000}s"
|
||||||
.setTitle(msg)
|
description = """
|
||||||
.setDescription(error.message)
|
${ServiceChannels.getServerNames().joinToString("\n")}
|
||||||
.setColor(Color.RED)
|
|
||||||
.build()
|
**_Service Channels_**
|
||||||
, "$msg\n\n${error.message}"
|
${ServiceChannels.getServiceChannelServers().joinToString("\n")}
|
||||||
)
|
""".trimIndent()
|
||||||
}
|
color = Color.GREEN
|
||||||
|
}
|
||||||
fun warning(msg: String) {
|
|
||||||
sendDevMessage(
|
|
||||||
EmbedBuilder()
|
|
||||||
.setTitle(msg)
|
|
||||||
.setColor(Color.YELLOW)
|
|
||||||
.build(),
|
|
||||||
msg
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun info() {
|
|
||||||
sendDevMessage(
|
|
||||||
EmbedBuilder()
|
|
||||||
.setTitle("Now watching for new Hytale Blogposts every ${updateMs / 1000}s")
|
|
||||||
.setDescription("""
|
|
||||||
${Channels.getServerNames().joinToString("\n")}
|
|
||||||
|
|
||||||
**_Service Channels_**
|
|
||||||
${Channels.getServiceChannelServers().joinToString("\n")}
|
|
||||||
""".trimIndent())
|
|
||||||
.setColor(Color.GREEN)
|
|
||||||
.build(),
|
|
||||||
"Now watching for new Hytale BlogPosts"
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun silent(msg: String) {
|
fun silent(msg: String) {
|
||||||
kotlin.io.println(msg)
|
kotlin.io.println(msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun senDevMessageBlocking(messageEmbed: MessageEmbed, fallback: String) {
|
private suspend inline fun sendDevMessage(fallback: String, crossinline embed: EmbedBuilder.() -> Unit) {
|
||||||
admin = jda!!.retrieveUserById(userId).complete()
|
val devChannel = admin?.getDmChannel() ?: kotlin.run {
|
||||||
val devChannel = admin?.openPrivateChannel() ?: kotlin.run {
|
|
||||||
kotlin.io.println(fallback)
|
kotlin.io.println(fallback)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
devChannel.complete()
|
devChannel.createEmbed(embed)
|
||||||
.sendMessage(messageEmbed).complete()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun sendDevMessage(messageEmbed: MessageEmbed, fallback: String) {
|
|
||||||
val devChannel = admin?.openPrivateChannel() ?: kotlin.run {
|
|
||||||
kotlin.io.println(fallback)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
devChannel.queue {
|
|
||||||
it.sendMessage(messageEmbed).queue()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
package de.wulkanat
|
package de.wulkanat
|
||||||
|
|
||||||
|
import de.wulkanat.files.ServiceChannels
|
||||||
import de.wulkanat.model.BlogPostPreview
|
import de.wulkanat.model.BlogPostPreview
|
||||||
import net.dv8tion.jda.api.hooks.ListenerAdapter
|
import net.dv8tion.jda.api.hooks.ListenerAdapter
|
||||||
import de.wulkanat.web.SiteWatcher
|
import de.wulkanat.web.SiteWatcher
|
||||||
@@ -41,23 +42,23 @@ class AdminCli : ListenerAdapter() {
|
|||||||
if (command.size != 3) {
|
if (command.size != 3) {
|
||||||
Admin.println("Enclose message and title in backticks (`)")
|
Admin.println("Enclose message and title in backticks (`)")
|
||||||
} else {
|
} else {
|
||||||
Channels.sendServiceMessage(command[1].value.trim('`'), command[2].value.trim('`'))
|
ServiceChannels.sendServiceMessage(command[1].value.trim('`'), command[2].value.trim('`'))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
"refreshList" -> {
|
"refreshList" -> {
|
||||||
Channels.channels = Channels.refreshChannelsFromDisk()
|
ServiceChannels.channels = ServiceChannels.refreshChannelsFromDisk()
|
||||||
Channels.serviceChannels = Channels.refreshServiceChannelsFromDisk()
|
ServiceChannels.serviceChannels = ServiceChannels.refreshServiceChannelsFromDisk()
|
||||||
Admin.info()
|
Admin.info()
|
||||||
}
|
}
|
||||||
"removeInactive" -> {
|
"removeInactive" -> {
|
||||||
Channels.channels.removeAll { channel ->
|
ServiceChannels.channels.removeAll { channel ->
|
||||||
Channels.testServerId(channel.id) ?: run {
|
ServiceChannels.testServerId(channel.id) ?: run {
|
||||||
Admin.println("Removed ${channel.id}")
|
Admin.println("Removed ${channel.id}")
|
||||||
null
|
null
|
||||||
} == null
|
} == null
|
||||||
}
|
}
|
||||||
Admin.info()
|
Admin.info()
|
||||||
Channels.saveChannels()
|
ServiceChannels.saveChannels()
|
||||||
}
|
}
|
||||||
"help" -> {
|
"help" -> {
|
||||||
event.message.channel.sendMessage(
|
event.message.channel.sendMessage(
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import java.io.File
|
|||||||
@Serializable
|
@Serializable
|
||||||
data class DiscordChannel(
|
data class DiscordChannel(
|
||||||
val id: Long,
|
val id: Long,
|
||||||
var mentionedRole: String? = null,
|
var mentionedRole: Long? = null,
|
||||||
var autoPublish: Boolean = false,
|
var autoPublish: Boolean = false,
|
||||||
var message: CustomMessage? = null
|
var message: CustomMessage? = null
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package de.wulkanat
|
package de.wulkanat
|
||||||
|
|
||||||
|
import de.wulkanat.files.ServiceChannels
|
||||||
import net.dv8tion.jda.api.JDABuilder
|
import net.dv8tion.jda.api.JDABuilder
|
||||||
import net.dv8tion.jda.api.entities.Activity
|
import net.dv8tion.jda.api.entities.Activity
|
||||||
import net.dv8tion.jda.api.requests.GatewayIntent
|
import net.dv8tion.jda.api.requests.GatewayIntent
|
||||||
@@ -18,7 +19,7 @@ fun main() {
|
|||||||
builder.addEventListener(OwnerCli())
|
builder.addEventListener(OwnerCli())
|
||||||
builder.awaitReady()
|
builder.awaitReady()
|
||||||
|
|
||||||
Channels.jda = builder
|
ServiceChannels.client = builder
|
||||||
Admin.jda = builder
|
Admin.jda = builder
|
||||||
DiscordRpc.jda = builder
|
DiscordRpc.jda = builder
|
||||||
Admin.info()
|
Admin.info()
|
||||||
@@ -34,7 +35,7 @@ fun main() {
|
|||||||
|
|
||||||
timer("Updater", daemon = true, initialDelay = 0L, period = Admin.updateMs) {
|
timer("Updater", daemon = true, initialDelay = 0L, period = Admin.updateMs) {
|
||||||
if (SiteWatcher.hasNewBlogPost()) {
|
if (SiteWatcher.hasNewBlogPost()) {
|
||||||
Channels.sentToAll(SiteWatcher.newestBlog!!.toMessageEmbed())
|
ServiceChannels.sentToAll(SiteWatcher.newestBlog!!.toMessageEmbed())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
package de.wulkanat
|
package de.wulkanat
|
||||||
|
|
||||||
|
import de.wulkanat.files.ServiceChannels
|
||||||
import net.dv8tion.jda.api.EmbedBuilder
|
import net.dv8tion.jda.api.EmbedBuilder
|
||||||
import net.dv8tion.jda.api.Permission
|
import net.dv8tion.jda.api.Permission
|
||||||
import net.dv8tion.jda.api.events.message.MessageReceivedEvent
|
import net.dv8tion.jda.api.events.message.MessageReceivedEvent
|
||||||
@@ -21,7 +22,7 @@ class OwnerCli : ListenerAdapter() {
|
|||||||
|
|
||||||
when (command.first()) {
|
when (command.first()) {
|
||||||
"add" -> {
|
"add" -> {
|
||||||
val result = Channels.addChannel(channelId, null)
|
val result = ServiceChannels.addChannel(channelId, null)
|
||||||
if (result == null) {
|
if (result == null) {
|
||||||
event.message.channel.sendMessage("Already added.").queue()
|
event.message.channel.sendMessage("Already added.").queue()
|
||||||
} else {
|
} else {
|
||||||
@@ -30,8 +31,8 @@ class OwnerCli : ListenerAdapter() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
"remove" -> {
|
"remove" -> {
|
||||||
val result = Channels.channels.removeAll { it.id == channelId }
|
val result = ServiceChannels.channels.removeAll { it.id == channelId }
|
||||||
Channels.saveChannels()
|
ServiceChannels.saveChannels()
|
||||||
if (result) {
|
if (result) {
|
||||||
event.message.channel.sendMessage("Removed.").queue()
|
event.message.channel.sendMessage("Removed.").queue()
|
||||||
} else {
|
} else {
|
||||||
@@ -39,11 +40,11 @@ class OwnerCli : ListenerAdapter() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
"publish" -> {
|
"publish" -> {
|
||||||
val result = Channels.channels.find { it.id == channelId }
|
val result = ServiceChannels.channels.find { it.id == channelId }
|
||||||
if (result != null) {
|
if (result != null) {
|
||||||
if (command.size > 1 && listOf("on", "off").contains(command[1])) {
|
if (command.size > 1 && listOf("on", "off").contains(command[1])) {
|
||||||
result.autoPublish = command[1] == "on"
|
result.autoPublish = command[1] == "on"
|
||||||
Channels.saveChannels()
|
ServiceChannels.saveChannels()
|
||||||
|
|
||||||
event.message.channel.sendMessage("Auto publish is now ${command[1]}").queue()
|
event.message.channel.sendMessage("Auto publish is now ${command[1]}").queue()
|
||||||
} else {
|
} else {
|
||||||
@@ -54,7 +55,7 @@ class OwnerCli : ListenerAdapter() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
"ping" -> {
|
"ping" -> {
|
||||||
val result = Channels.channels.find { it.id == channelId }
|
val result = ServiceChannels.channels.find { it.id == channelId }
|
||||||
if (result != null) {
|
if (result != null) {
|
||||||
if (command.size > 1) {
|
if (command.size > 1) {
|
||||||
val roles = event.message.guild.getRolesByName(command[1], false)
|
val roles = event.message.guild.getRolesByName(command[1], false)
|
||||||
@@ -76,7 +77,7 @@ class OwnerCli : ListenerAdapter() {
|
|||||||
result.mentionedRole
|
result.mentionedRole
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Channels.saveChannels()
|
ServiceChannels.saveChannels()
|
||||||
} else {
|
} else {
|
||||||
event.message.channel.sendMessage("Usage: `${prefix}ping [everyone|none|roleName]`")
|
event.message.channel.sendMessage("Usage: `${prefix}ping [everyone|none|roleName]`")
|
||||||
}
|
}
|
||||||
@@ -85,12 +86,12 @@ class OwnerCli : ListenerAdapter() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
"setMessage" -> {
|
"setMessage" -> {
|
||||||
val result = Channels.channels.find { it.id == channelId }
|
val result = ServiceChannels.channels.find { it.id == channelId }
|
||||||
if (result != null) {
|
if (result != null) {
|
||||||
if (command.size > 1) {
|
if (command.size > 1) {
|
||||||
val message = event.message.contentRaw.removePrefix("${prefix}setMessage").trim()
|
val message = event.message.contentRaw.removePrefix("${prefix}setMessage").trim()
|
||||||
result.message = CustomMessage(message)
|
result.message = CustomMessage(message)
|
||||||
Channels.saveChannels()
|
ServiceChannels.saveChannels()
|
||||||
event.message.channel.sendMessage("Set `$message` as message.").queue()
|
event.message.channel.sendMessage("Set `$message` as message.").queue()
|
||||||
} else {
|
} else {
|
||||||
event.message.channel.sendMessage("Usage: `${prefix}setMessage [message]`")
|
event.message.channel.sendMessage("Usage: `${prefix}setMessage [message]`")
|
||||||
@@ -100,10 +101,10 @@ class OwnerCli : ListenerAdapter() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
"resetMessage" -> {
|
"resetMessage" -> {
|
||||||
val result = Channels.channels.find { it.id == channelId }
|
val result = ServiceChannels.channels.find { it.id == channelId }
|
||||||
if (result != null) {
|
if (result != null) {
|
||||||
result.message = null
|
result.message = null
|
||||||
Channels.saveChannels()
|
ServiceChannels.saveChannels()
|
||||||
event.message.channel.sendMessage("Reset to no message.").queue()
|
event.message.channel.sendMessage("Reset to no message.").queue()
|
||||||
} else {
|
} else {
|
||||||
event.message.channel.sendMessage("Channel is not registered.").queue()
|
event.message.channel.sendMessage("Channel is not registered.").queue()
|
||||||
@@ -112,32 +113,32 @@ class OwnerCli : ListenerAdapter() {
|
|||||||
"serviceChannel" -> {
|
"serviceChannel" -> {
|
||||||
if (command.size > 1 && listOf("add", "remove").contains(command[1])) {
|
if (command.size > 1 && listOf("add", "remove").contains(command[1])) {
|
||||||
if (command[1] == "add") {
|
if (command[1] == "add") {
|
||||||
if (Channels.serviceChannels.find { it.id == channelId } != null) {
|
if (ServiceChannels.serviceChannels.find { it.id == channelId } != null) {
|
||||||
event.message.channel.sendMessage("Already a service channel.").queue()
|
event.message.channel.sendMessage("Already a service channel.").queue()
|
||||||
} else {
|
} else {
|
||||||
Channels.serviceChannels.add(ServiceChannel(channelId))
|
ServiceChannels.serviceChannels.add(ServiceChannel(channelId))
|
||||||
Channels.saveChannels()
|
ServiceChannels.saveChannels()
|
||||||
event.message.channel.sendMessage("Added as service channel.").queue()
|
event.message.channel.sendMessage("Added as service channel.").queue()
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
event.message.channel.sendMessage(
|
event.message.channel.sendMessage(
|
||||||
if (Channels.serviceChannels.removeAll { it.id == channelId }) "Channel removed."
|
if (ServiceChannels.serviceChannels.removeAll { it.id == channelId }) "Channel removed."
|
||||||
else "Not a service channel."
|
else "Not a service channel."
|
||||||
).queue()
|
).queue()
|
||||||
}
|
}
|
||||||
Channels.saveChannels()
|
ServiceChannels.saveChannels()
|
||||||
} else {
|
} else {
|
||||||
event.message.channel.sendMessage("Usage: `${prefix}serviceChannel [add|remove]`")
|
event.message.channel.sendMessage("Usage: `${prefix}serviceChannel [add|remove]`")
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
"publishMessage" -> {
|
"publishMessage" -> {
|
||||||
val result = Channels.channels.find { it.id == channelId }
|
val result = ServiceChannels.channels.find { it.id == channelId }
|
||||||
if (result != null) {
|
if (result != null) {
|
||||||
if (result.message != null) {
|
if (result.message != null) {
|
||||||
if (command.size > 1 && listOf("on", "off").contains(command[1])) {
|
if (command.size > 1 && listOf("on", "off").contains(command[1])) {
|
||||||
result.message?.pushAnnouncement = command[1] == "on"
|
result.message?.pushAnnouncement = command[1] == "on"
|
||||||
Channels.saveChannels()
|
ServiceChannels.saveChannels()
|
||||||
|
|
||||||
event.message.channel.sendMessage("Auto publish (message) is now ${command[1]}").queue()
|
event.message.channel.sendMessage("Auto publish (message) is now ${command[1]}").queue()
|
||||||
} else {
|
} else {
|
||||||
@@ -156,10 +157,10 @@ class OwnerCli : ListenerAdapter() {
|
|||||||
.setTitle("Server overview")
|
.setTitle("Server overview")
|
||||||
.setColor(Color.GREEN)
|
.setColor(Color.GREEN)
|
||||||
.setDescription("""
|
.setDescription("""
|
||||||
${Channels.getServerNames(event.message.guild.idLong).joinToString("\n")}
|
${ServiceChannels.getServerNames(event.message.guild.idLong).joinToString("\n")}
|
||||||
|
|
||||||
**_Service Channels_**
|
**_Service Channels_**
|
||||||
${Channels.getServiceChannelServers(event.message.guild.idLong).joinToString("\n")}
|
${ServiceChannels.getServiceChannelServers(event.message.guild.idLong).joinToString("\n")}
|
||||||
""".trimIndent())
|
""".trimIndent())
|
||||||
.setAuthor(Admin.admin?.name, Admin.admin?.avatarUrl, Admin.admin?.avatarUrl)
|
.setAuthor(Admin.admin?.name, Admin.admin?.avatarUrl, Admin.admin?.avatarUrl)
|
||||||
.build()
|
.build()
|
||||||
|
|||||||
109
src/main/kotlin/de/wulkanat/cli/AdminCli.kt
Normal file
109
src/main/kotlin/de/wulkanat/cli/AdminCli.kt
Normal file
@@ -0,0 +1,109 @@
|
|||||||
|
@file:AutoWired
|
||||||
|
|
||||||
|
package de.wulkanat.cli
|
||||||
|
|
||||||
|
import com.gitlab.kordlib.core.entity.channel.DmChannel
|
||||||
|
import com.gitlab.kordlib.kordx.commands.annotation.AutoWired
|
||||||
|
import com.gitlab.kordlib.kordx.commands.argument.primitive.BooleanArgument
|
||||||
|
import com.gitlab.kordlib.kordx.commands.argument.text.StringArgument
|
||||||
|
import com.gitlab.kordlib.kordx.commands.kord.model.precondition.precondition
|
||||||
|
import com.gitlab.kordlib.kordx.commands.kord.model.prefix.kord
|
||||||
|
import com.gitlab.kordlib.kordx.commands.kord.model.prefix.mention
|
||||||
|
import com.gitlab.kordlib.kordx.commands.kord.model.respondEmbed
|
||||||
|
import com.gitlab.kordlib.kordx.commands.kord.module.module
|
||||||
|
import com.gitlab.kordlib.kordx.commands.model.command.invoke
|
||||||
|
import com.gitlab.kordlib.kordx.commands.model.prefix.literal
|
||||||
|
import com.gitlab.kordlib.kordx.commands.model.prefix.or
|
||||||
|
import com.gitlab.kordlib.kordx.commands.model.prefix.prefix
|
||||||
|
import de.wulkanat.Admin
|
||||||
|
import de.wulkanat.extensions.alsoIf
|
||||||
|
import de.wulkanat.extensions.isBotAdmin
|
||||||
|
import de.wulkanat.files.ServiceChannels
|
||||||
|
import de.wulkanat.model.BlogPostPreview
|
||||||
|
import de.wulkanat.web.SiteWatcher
|
||||||
|
|
||||||
|
val prefixes = prefix {
|
||||||
|
kord { mention() or literal("%!") }
|
||||||
|
}
|
||||||
|
|
||||||
|
fun adminCommands() = module("admin-commands") {
|
||||||
|
precondition { author.isBotAdmin && channel.asChannelOrNull() is DmChannel }
|
||||||
|
|
||||||
|
command("stop") {
|
||||||
|
invoke {
|
||||||
|
respond("Shutting down...")
|
||||||
|
kord.shutdown()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
command("info") {
|
||||||
|
invoke {
|
||||||
|
Admin.info()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
command("fakeUpdate") {
|
||||||
|
invoke {
|
||||||
|
respond("THIS WILL CAUSE A MESSAGE ON **ALL** SERVERS.\nContinue? [y/n]")
|
||||||
|
if (read(BooleanArgument(trueValue = "y", falseValue = "n"))) {
|
||||||
|
respond("Sending fake update on next cycle")
|
||||||
|
|
||||||
|
SiteWatcher.newestBlog = BlogPostPreview(
|
||||||
|
title = "FakePost",
|
||||||
|
imgUrl = "",
|
||||||
|
fullPostUrl = "",
|
||||||
|
author = "wulkanat",
|
||||||
|
date = "now",
|
||||||
|
description = "Lorem Ipsum"
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
respond("Aborting")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
command("serviceMessage") {
|
||||||
|
invoke {
|
||||||
|
respond("What's the title?")
|
||||||
|
val title = read(StringArgument)
|
||||||
|
respond("What's the message?")
|
||||||
|
val message = read(StringArgument)
|
||||||
|
respondEmbed {
|
||||||
|
this.title = title
|
||||||
|
description = message
|
||||||
|
footer {
|
||||||
|
text = "Is that correct? [y/n]"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (read(BooleanArgument(trueValue = "y", falseValue = "n"))) {
|
||||||
|
respond("Sending")
|
||||||
|
ServiceChannels.sendServiceMessage(title, message)
|
||||||
|
} else {
|
||||||
|
respond("Aborting")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
command("refreshList") {
|
||||||
|
invoke {
|
||||||
|
ServiceChannels.channels = ServiceChannels.refreshChannelsFromDisk()
|
||||||
|
ServiceChannels.serviceChannels = ServiceChannels.refreshServiceChannelsFromDisk()
|
||||||
|
Admin.info()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
command("removeInactive") {
|
||||||
|
invoke {
|
||||||
|
respondEmbed {
|
||||||
|
title = "Channels removed"
|
||||||
|
|
||||||
|
ServiceChannels.channels.removeAll { channel ->
|
||||||
|
(ServiceChannels.testServerId(channel.id) == null).alsoIf(true) {
|
||||||
|
field { name = channel.id.toString() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ServiceChannels.saveChannels()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
159
src/main/kotlin/de/wulkanat/cli/OwnerCli.kt
Normal file
159
src/main/kotlin/de/wulkanat/cli/OwnerCli.kt
Normal file
@@ -0,0 +1,159 @@
|
|||||||
|
@file:AutoWired
|
||||||
|
|
||||||
|
package de.wulkanat.cli
|
||||||
|
|
||||||
|
import com.gitlab.kordlib.common.entity.Permission
|
||||||
|
import com.gitlab.kordlib.kordx.commands.annotation.AutoWired
|
||||||
|
import com.gitlab.kordlib.kordx.commands.argument.primitive.BooleanArgument
|
||||||
|
import com.gitlab.kordlib.kordx.commands.argument.text.StringArgument
|
||||||
|
import com.gitlab.kordlib.kordx.commands.kord.argument.RoleArgument
|
||||||
|
import com.gitlab.kordlib.kordx.commands.kord.model.precondition.precondition
|
||||||
|
import com.gitlab.kordlib.kordx.commands.kord.model.respondEmbed
|
||||||
|
import com.gitlab.kordlib.kordx.commands.kord.module.module
|
||||||
|
import com.gitlab.kordlib.kordx.commands.model.command.invoke
|
||||||
|
import de.wulkanat.Admin
|
||||||
|
import de.wulkanat.CustomMessage
|
||||||
|
import de.wulkanat.ServiceChannel
|
||||||
|
import de.wulkanat.files.ServiceChannels
|
||||||
|
import java.awt.Color
|
||||||
|
|
||||||
|
// TODO: channel argument?
|
||||||
|
fun ownerCommands() = module("owner-commands") {
|
||||||
|
precondition {
|
||||||
|
message.getAuthorAsMember()?.getPermissions()?.contains(Permission.Administrator) ?: false
|
||||||
|
}
|
||||||
|
|
||||||
|
command("add") {
|
||||||
|
invoke {
|
||||||
|
if (ServiceChannels.addChannel(channel.id.longValue, null) == null) {
|
||||||
|
respond("Already added.")
|
||||||
|
} else {
|
||||||
|
respond("Added.")
|
||||||
|
Admin.info()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
command("remove") {
|
||||||
|
invoke {
|
||||||
|
val result = ServiceChannels.channels.removeAll { it.id == channel.id.longValue }
|
||||||
|
ServiceChannels.saveChannels()
|
||||||
|
if (result) {
|
||||||
|
respond("Removed.")
|
||||||
|
} else {
|
||||||
|
respond("This channel is not registered.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
command("publish") {
|
||||||
|
invoke(BooleanArgument(trueValue = "on", falseValue = "off")) { doAutoPublish ->
|
||||||
|
ServiceChannels.channels.find { it.id == channel.id.longValue }?.also {
|
||||||
|
it.autoPublish = doAutoPublish
|
||||||
|
ServiceChannels.saveChannels()
|
||||||
|
} ?: respond("Channel not registered")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
command("ping") {
|
||||||
|
invoke(RoleArgument) { role ->
|
||||||
|
ServiceChannels.channels.find { it.id == channel.id.longValue }?.also {
|
||||||
|
// TODO: @everyone
|
||||||
|
it.mentionedRole = role.id.longValue
|
||||||
|
ServiceChannels.saveChannels()
|
||||||
|
} ?: respond("Channel not registered")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
command("setMessage") {
|
||||||
|
invoke(StringArgument) { message ->
|
||||||
|
ServiceChannels.channels.find { it.id == channel.id.longValue}?.also {
|
||||||
|
it.message = CustomMessage(message)
|
||||||
|
respond("Set `$message` as a message.")
|
||||||
|
} ?: respond("Channel not registered!")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
command("resetMessage") {
|
||||||
|
invoke {
|
||||||
|
ServiceChannels.channels.find { it.id == channel.id.longValue }?.also {
|
||||||
|
it.message = null
|
||||||
|
respond("Reset to no message")
|
||||||
|
} ?: respond("Channel not registered!")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
command("serviceChannel") {
|
||||||
|
invoke(BooleanArgument(trueValue = "add", falseValue = "remove")) { addChannel ->
|
||||||
|
if (addChannel) {
|
||||||
|
ServiceChannels.serviceChannels.find { it.id == channel.id.longValue }?.also {
|
||||||
|
respond("Already a service channel")
|
||||||
|
} ?: run {
|
||||||
|
ServiceChannels.serviceChannels.add(ServiceChannel(channel.id.longValue))
|
||||||
|
respond("Added as a service channel")
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
respond(if (ServiceChannels.serviceChannels.removeAll { it.id == channel.id.longValue })
|
||||||
|
"Channel removed" else "Not a service channel")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
command("publishMessage") {
|
||||||
|
invoke(BooleanArgument(trueValue = "on", falseValue = "off")) { doAutoPublish ->
|
||||||
|
ServiceChannels.channels.find { it.id == channel.id.longValue }?.also {
|
||||||
|
it.message?.pushAnnouncement = doAutoPublish
|
||||||
|
ServiceChannels.saveChannels()
|
||||||
|
respond("Auto publish is now ${if (doAutoPublish) "on" else "off"}")
|
||||||
|
} ?: respond("Channel not registered!")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
command("info") {
|
||||||
|
invoke {
|
||||||
|
respondEmbed {
|
||||||
|
title = "Server Overview"
|
||||||
|
color = Color.GREEN
|
||||||
|
description = """
|
||||||
|
${ServiceChannels.getServerNames(guild?.id?.longValue).joinToString("\n")}
|
||||||
|
|
||||||
|
**_Service Channels_**
|
||||||
|
${ServiceChannels.getServiceChannelServers(guild?.id?.longValue).joinToString("\n")}
|
||||||
|
""".trimIndent()
|
||||||
|
Admin.admin?.let {
|
||||||
|
author {
|
||||||
|
name = it.username
|
||||||
|
icon = it.avatar.url
|
||||||
|
url = "https://github.com/wulkanat/BlogShot"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
command("report") {
|
||||||
|
invoke {
|
||||||
|
respond("What is the error you encountered?")
|
||||||
|
val errorReport = read(StringArgument)
|
||||||
|
respondEmbed {
|
||||||
|
title = "Error Report Preview"
|
||||||
|
color = Color.RED
|
||||||
|
description = errorReport
|
||||||
|
message.author?.let {
|
||||||
|
author {
|
||||||
|
name = it.username
|
||||||
|
icon = it.avatar.url
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
respond("Send? [y/n]")
|
||||||
|
if (read(BooleanArgument(trueValue = "y", falseValue = "n"))) {
|
||||||
|
respond("Sent")
|
||||||
|
Admin.error(guild?.asGuildOrNull()?.name ?: "Unknown Guild", errorReport, author)
|
||||||
|
} else {
|
||||||
|
respond("Aborting")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
8
src/main/kotlin/de/wulkanat/extensions/Generic.kt
Normal file
8
src/main/kotlin/de/wulkanat/extensions/Generic.kt
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
package de.wulkanat.extensions
|
||||||
|
|
||||||
|
inline fun <T> Boolean.alsoIf(other: T, body: () -> Unit): Boolean {
|
||||||
|
if (this == other) {
|
||||||
|
body()
|
||||||
|
}
|
||||||
|
return this
|
||||||
|
}
|
||||||
7
src/main/kotlin/de/wulkanat/extensions/User.kt
Normal file
7
src/main/kotlin/de/wulkanat/extensions/User.kt
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
package de.wulkanat.extensions
|
||||||
|
|
||||||
|
import com.gitlab.kordlib.core.entity.User
|
||||||
|
import de.wulkanat.files.Config
|
||||||
|
|
||||||
|
val User.isBotAdmin: Boolean
|
||||||
|
get() = id.longValue == Config.adminId
|
||||||
26
src/main/kotlin/de/wulkanat/files/Config.kt
Normal file
26
src/main/kotlin/de/wulkanat/files/Config.kt
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
package de.wulkanat.files
|
||||||
|
|
||||||
|
import de.wulkanat.files.concept.SerializableObject
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
|
object Config : SerializableObject<Config.Data>("config.json", Data(), Data.serializer()) {
|
||||||
|
val adminId: Long
|
||||||
|
get() = instance.adminId
|
||||||
|
val token: String
|
||||||
|
get() = instance.token
|
||||||
|
val updateMs: Long
|
||||||
|
get() = instance.updateMs
|
||||||
|
val watchingMessage: String
|
||||||
|
get() = instance.watchingMessage
|
||||||
|
val offlineMessage: String
|
||||||
|
get() = instance.offlineMessage
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class Data(
|
||||||
|
val adminId: Long = 12345,
|
||||||
|
val token: String = "12345",
|
||||||
|
val updateMs: Long = 30000,
|
||||||
|
val watchingMessage: String = "for new Blogposts",
|
||||||
|
val offlineMessage: String = "CONNECTION FAILED"
|
||||||
|
)
|
||||||
|
}
|
||||||
4
src/main/kotlin/de/wulkanat/files/Servers.kt
Normal file
4
src/main/kotlin/de/wulkanat/files/Servers.kt
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
package de.wulkanat.files
|
||||||
|
|
||||||
|
object Servers {
|
||||||
|
}
|
||||||
@@ -1,6 +1,9 @@
|
|||||||
package de.wulkanat
|
package de.wulkanat.files
|
||||||
|
|
||||||
import de.wulkanat.extensions.crosspost
|
import com.gitlab.kordlib.core.Kord
|
||||||
|
import com.gitlab.kordlib.core.entity.Embed
|
||||||
|
import com.gitlab.kordlib.rest.builder.message.EmbedBuilder
|
||||||
|
import de.wulkanat.*
|
||||||
import kotlinx.serialization.list
|
import kotlinx.serialization.list
|
||||||
import net.dv8tion.jda.api.EmbedBuilder
|
import net.dv8tion.jda.api.EmbedBuilder
|
||||||
import net.dv8tion.jda.api.JDA
|
import net.dv8tion.jda.api.JDA
|
||||||
@@ -9,8 +12,8 @@ import net.dv8tion.jda.api.entities.MessageEmbed
|
|||||||
import net.dv8tion.jda.api.entities.TextChannel
|
import net.dv8tion.jda.api.entities.TextChannel
|
||||||
import java.awt.Color
|
import java.awt.Color
|
||||||
|
|
||||||
object Channels {
|
object ServiceChannels {
|
||||||
var jda: JDA? = null
|
var client: Kord? = null
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* List of (ServerID, ChannelID)
|
* List of (ServerID, ChannelID)
|
||||||
@@ -18,13 +21,13 @@ object Channels {
|
|||||||
var channels: MutableList<DiscordChannel> = refreshChannelsFromDisk()
|
var channels: MutableList<DiscordChannel> = refreshChannelsFromDisk()
|
||||||
var serviceChannels: MutableList<ServiceChannel> = refreshServiceChannelsFromDisk()
|
var serviceChannels: MutableList<ServiceChannel> = refreshServiceChannelsFromDisk()
|
||||||
|
|
||||||
fun sentToAll(messageEmbed: MessageEmbed) {
|
fun sentToAll(messageEmbed: Embed) {
|
||||||
if (jda == null)
|
if (client == null)
|
||||||
return
|
return
|
||||||
|
|
||||||
for (channel_pair in channels) {
|
for (channel_pair in channels) {
|
||||||
try {
|
try {
|
||||||
val channel = jda!!.getTextChannelById(channel_pair.id) ?: continue
|
val channel = client!!.getTextChannelById(channel_pair.id) ?: continue
|
||||||
val customMessage = channel_pair.message?.message ?: ""
|
val customMessage = channel_pair.message?.message ?: ""
|
||||||
|
|
||||||
if (channel_pair.mentionedRole != null) {
|
if (channel_pair.mentionedRole != null) {
|
||||||
@@ -66,13 +69,14 @@ object Channels {
|
|||||||
.build()
|
.build()
|
||||||
|
|
||||||
for (channelInfo in serviceChannels) {
|
for (channelInfo in serviceChannels) {
|
||||||
val channel = jda!!.getTextChannelById(channelInfo.id)
|
val channel = client!!.getTextChannelById(channelInfo.id)
|
||||||
|
|
||||||
channel?.sendMessage(serviceMessage)?.queue()
|
channel?.sendMessage(serviceMessage)?.queue()
|
||||||
}
|
}
|
||||||
|
|
||||||
Admin.println("Service message distributed to ${serviceChannels.size} channels.")
|
Admin.println("Service message distributed to ${serviceChannels.size} channels.")
|
||||||
Admin.sendDevMessage(serviceMessage, """
|
Admin.sendDevMessage(
|
||||||
|
serviceMessage, """
|
||||||
***************
|
***************
|
||||||
SERVICE MESSAGE
|
SERVICE MESSAGE
|
||||||
|
|
||||||
@@ -80,12 +84,13 @@ object Channels {
|
|||||||
-------
|
-------
|
||||||
$message
|
$message
|
||||||
***************
|
***************
|
||||||
""".trimIndent())
|
""".trimIndent()
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun checkEveryonePermission() {
|
fun checkEveryonePermission() {
|
||||||
for (channel_pair in channels) {
|
for (channel_pair in channels) {
|
||||||
val channel = jda!!.getTextChannelById(channel_pair.id) ?: continue
|
val channel = client!!.getTextChannelById(channel_pair.id) ?: continue
|
||||||
|
|
||||||
if (channel_pair.mentionedRole == "everyone" &&
|
if (channel_pair.mentionedRole == "everyone" &&
|
||||||
channel.guild.selfMember.hasPermission(Permission.MESSAGE_MENTION_EVERYONE)
|
channel.guild.selfMember.hasPermission(Permission.MESSAGE_MENTION_EVERYONE)
|
||||||
@@ -111,11 +116,11 @@ object Channels {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun getServerNames(server: Long? = null): List<String> {
|
fun getServerNames(server: Long? = null): List<String> {
|
||||||
if (jda == null)
|
if (client == null)
|
||||||
return listOf()
|
return listOf()
|
||||||
|
|
||||||
return channels.filter { server == null || (jda!!.getTextChannelById(it.id)?.guild?.idLong == server) }.map {
|
return channels.filter { server == null || (client!!.getTextChannelById(it.id)?.guild?.idLong == server) }.map {
|
||||||
val channel = jda!!.getTextChannelById(it.id)
|
val channel = client!!.getTextChannelById(it.id)
|
||||||
if (channel == null) {
|
if (channel == null) {
|
||||||
Admin.warning("Channel ${it.id} is no longer active!")
|
Admin.warning("Channel ${it.id} is no longer active!")
|
||||||
return@map "**${it.id}** *(inactive)*"
|
return@map "**${it.id}** *(inactive)*"
|
||||||
@@ -137,17 +142,17 @@ object Channels {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun getServiceChannelServers(server: Long? = null): List<String> {
|
fun getServiceChannelServers(server: Long? = null): List<String> {
|
||||||
if (jda == null)
|
if (client == null)
|
||||||
return listOf()
|
return listOf()
|
||||||
|
|
||||||
return serviceChannels.filter { server == null || (jda!!.getTextChannelById(it.id)?.guild?.idLong == server) }.map {
|
return serviceChannels.filter { server == null || (client!!.getTextChannelById(it.id)?.guild?.idLong == server) }.map {
|
||||||
val channel = jda!!.getTextChannelById(it.id)
|
val channel = client!!.getTextChannelById(it.id)
|
||||||
"**${channel?.guild?.name ?: it.id}** #${channel?.name ?: "(inactive)"}"
|
"**${channel?.guild?.name ?: it.id}** #${channel?.name ?: "(inactive)"}"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun testServerId(id: Long): TextChannel? {
|
fun testServerId(id: Long): TextChannel? {
|
||||||
return jda?.getTextChannelById(id)
|
return client?.getTextChannelById(id)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun addChannel(id: Long, role: String?): DiscordChannel? {
|
fun addChannel(id: Long, role: String?): DiscordChannel? {
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
package de.wulkanat.files.concept
|
||||||
|
|
||||||
|
import de.wulkanat.extensions.ensureExists
|
||||||
|
import kotlinx.serialization.KSerializer
|
||||||
|
import kotlinx.serialization.json.Json
|
||||||
|
import java.io.File
|
||||||
|
|
||||||
|
abstract class SerializableObject<T>(
|
||||||
|
fileName: String,
|
||||||
|
defaultText: T? = null,
|
||||||
|
private val childSerializer: KSerializer<T>
|
||||||
|
) {
|
||||||
|
private val json = Json { allowStructuredMapKeys = true }
|
||||||
|
private val file = File(fileName).ensureExists(defaultText?.let { json.encodeToString(childSerializer, it) })
|
||||||
|
var instance: T = json.decodeFromString(childSerializer, file.readText())
|
||||||
|
|
||||||
|
fun refresh() {
|
||||||
|
instance = json.decodeFromString(childSerializer, file.readText())
|
||||||
|
}
|
||||||
|
|
||||||
|
fun save() {
|
||||||
|
file.writeText(json.encodeToString(childSerializer, instance))
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user