Change CLI to use kordx.commands

This commit is contained in:
Wieland Schöbl
2021-01-08 17:40:46 +01:00
parent a8ec59c7ca
commit 69220fba32
15 changed files with 448 additions and 162 deletions

2
.gitignore vendored
View File

@@ -1,5 +1,5 @@
servers.json servers.json
admin.json config.json
service_channels.json service_channels.json
*.hprof *.hprof
/build /build

View File

@@ -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

View File

@@ -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()
}
} }
} }

View File

@@ -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(

View File

@@ -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
) )

View File

@@ -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())
} }
} }
} }

View File

@@ -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()

View 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()
}
}
}

View 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")
}
}
}
}

View 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
}

View 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

View 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"
)
}

View File

@@ -0,0 +1,4 @@
package de.wulkanat.files
object Servers {
}

View File

@@ -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? {

View File

@@ -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))
}
}