Add service announcement channel

This commit is contained in:
Wieland Schöbl
2020-08-19 14:25:54 +02:00
parent 490a5dcd41
commit a78c2343da
13 changed files with 247 additions and 135 deletions

View File

@@ -14,23 +14,7 @@ object Admin {
val token: String
val updateMs: Long
val message: String
var testModeEnabled: Boolean = false
set(value) {
if (field == value)
return
field = value
if (value) {
jda?.presence?.setPresence(Activity.of(Activity.ActivityType.DEFAULT, "Testing mode, hold on..."), true)
} else {
jda?.presence?.setPresence(Activity.watching("for new Blogposts"), false)
}
Channels.channels = Channels.refreshFromDisk()
Admin.info()
}
val offlineMessage: String
init {
val admin = Json(JsonConfiguration.Stable).parse(AdminFile.serializer(), ADMIN_FILE.readText())
@@ -38,6 +22,7 @@ object Admin {
token = admin.token
updateMs = admin.updateMs
message = admin.watchingMessage
offlineMessage = admin.offlineMessage
}
var jda: JDA? = null
@@ -116,7 +101,12 @@ object Admin {
sendDevMessage(
EmbedBuilder()
.setTitle("Now watching for new Hytale Blogposts every ${updateMs / 1000}s")
.setDescription(Channels.getServerNames().joinToString("\n"))
.setDescription("""
${Channels.getServerNames().joinToString("\n")}
**_Service Channels_**
${Channels.getServiceChannelServers().joinToString("\n")}
""".trimIndent())
.setColor(Color.GREEN)
.build(),
"Now watching for new Hytale BlogPosts"
@@ -138,7 +128,7 @@ object Admin {
.sendMessage(messageEmbed).complete()
}
private fun sendDevMessage(messageEmbed: MessageEmbed, fallback: String) {
fun sendDevMessage(messageEmbed: MessageEmbed, fallback: String) {
val devChannel = admin?.openPrivateChannel() ?: kotlin.run {
kotlin.io.println(fallback)
return

View File

@@ -1,10 +1,8 @@
package de.wulkanat
import de.wulkanat.model.BlogPostPreview
import net.dv8tion.jda.api.events.message.MessageReceivedEvent
import net.dv8tion.jda.api.hooks.ListenerAdapter
import de.wulkanat.web.SiteWatcher
import net.dv8tion.jda.api.events.ExceptionEvent
import net.dv8tion.jda.api.events.message.priv.PrivateMessageReceivedEvent
import kotlin.system.exitProcess
@@ -16,9 +14,9 @@ class AdminCli : ListenerAdapter() {
) {
return
}
val command = msg.removePrefix("!").split(Regex("\\s+"))
val command = Regex("[^\\s`]+|`[^`]*`").findAll(msg.removePrefix("!")).toList()
when (command[0]) {
when (command[0].value) {
"stop" -> exitProcess(1)
"fakeUpdate" -> {
SiteWatcher.newestBlog = BlogPostPreview(
@@ -35,16 +33,18 @@ class AdminCli : ListenerAdapter() {
"info" -> {
Admin.info()
}
"serviceMessage" -> {
if (command.size != 3) {
Admin.println("Enclose message and title in backticks (`)")
} else {
Channels.sendServiceMessage(command[1].value.trim('`'), command[2].value.trim('`'))
}
}
"refreshList" -> {
Channels.channels = Channels.refreshFromDisk()
Channels.channels = Channels.refreshChannelsFromDisk()
Channels.serviceChannels = Channels.refreshServiceChannelsFromDisk()
Admin.info()
}
"testMode" -> {
Admin.testModeEnabled = true
}
"productionMode" -> {
Admin.testModeEnabled = false
}
}
}
}

View File

@@ -4,20 +4,22 @@ import de.wulkanat.extensions.crosspost
import kotlinx.serialization.json.Json
import kotlinx.serialization.json.JsonConfiguration
import kotlinx.serialization.list
import net.dv8tion.jda.api.EmbedBuilder
import net.dv8tion.jda.api.JDA
import net.dv8tion.jda.api.Permission
import net.dv8tion.jda.api.entities.MessageEmbed
import net.dv8tion.jda.api.entities.TextChannel
import net.dv8tion.jda.api.exceptions.ErrorResponseException
import java.awt.Color
object Channels {
var jda: JDA? = null
val json = Json(JsonConfiguration.Stable)
/**
* List of (ServerID, ChannelID)
*/
var channels: MutableList<DiscordChannel> = refreshFromDisk()
var channels: MutableList<DiscordChannel> = refreshChannelsFromDisk()
var serviceChannels: MutableList<ServiceChannel> = refreshServiceChannelsFromDisk()
fun sentToAll(messageEmbed: MessageEmbed) {
if (jda == null)
@@ -57,6 +59,33 @@ object Channels {
}
}
fun sendServiceMessage(title: String, message: String) {
val serviceMessage = EmbedBuilder()
.setTitle(title)
.setDescription(message)
.setColor(Color.WHITE)
.setAuthor(Admin.admin?.name, Admin.admin?.avatarUrl, Admin.admin?.avatarUrl)
.setFooter("This was sent by a human.")
.build()
for (channelInfo in serviceChannels) {
val channel = jda!!.getTextChannelById(channelInfo.id)
channel?.sendMessage(serviceMessage)?.queue()
}
Admin.println("Service message distributed to ${serviceChannels.size} channels.")
Admin.sendDevMessage(serviceMessage, """
***************
SERVICE MESSAGE
$title
-------
$message
***************
""".trimIndent())
}
fun checkEveryonePermission() {
for (channel_pair in channels) {
val channel = jda!!.getTextChannelById(channel_pair.id) ?: continue
@@ -72,13 +101,15 @@ object Channels {
}
}
fun refreshFromDisk(): MutableList<DiscordChannel> {
fun refreshChannelsFromDisk(): MutableList<DiscordChannel> {
return json.parse(
DiscordChannel.serializer().list, (if (Admin.testModeEnabled) {
TEST_FILE
} else {
SERVERS_FILE
}).readText()
DiscordChannel.serializer().list, (SERVERS_FILE).readText()
).toMutableList()
}
fun refreshServiceChannelsFromDisk(): MutableList<ServiceChannel> {
return json.parse(
ServiceChannel.serializer().list, (SERVICE_CHANNELS_FILE).readText()
).toMutableList()
}
@@ -99,7 +130,7 @@ object Channels {
else -> " @${channel.guild.getRoleById(it.mentionedRole ?: "")?.name}"
}
val publish = if (it.autoPublish) " (publish)" else ""
"**${channel.guild.name}**\n#${channel.name}${role}${publish}${if (it.message == null) {
"**${channel.guild.name}** #${channel.name}${role}${publish}${if (it.message == null) {
""
} else {
"\n*${it.message!!.message}*${if (it.message!!.pushAnnouncement) " (publish)" else ""}"
@@ -108,6 +139,16 @@ object Channels {
}
}
fun getServiceChannelServers(server: Long? = null): List<String> {
if (jda == null)
return listOf()
return serviceChannels.filter { server == null || (jda!!.getTextChannelById(it.id)?.guild?.idLong == server) }.map {
val channel = jda!!.getTextChannelById(it.id)
"**${channel?.guild?.name ?: it.id}** #${channel?.name ?: "(inactive)"}"
}
}
fun testServerId(id: Long): TextChannel? {
return jda?.getTextChannelById(id)
}
@@ -129,5 +170,11 @@ object Channels {
channels
)
)
SERVICE_CHANNELS_FILE.writeText(
json.stringify(
ServiceChannel.serializer().list,
serviceChannels
)
)
}
}

View File

@@ -1,6 +1,10 @@
package de.wulkanat
import de.wulkanat.extensions.ensureExists
import kotlinx.serialization.Serializable
import kotlinx.serialization.json.Json
import kotlinx.serialization.json.JsonConfiguration
import kotlinx.serialization.list
import java.io.File
@Serializable
@@ -11,6 +15,11 @@ data class DiscordChannel(
var message: CustomMessage? = null
)
@Serializable
data class ServiceChannel(
val id: Long
)
@Serializable
data class CustomMessage(
var message: String,
@@ -19,12 +28,16 @@ data class CustomMessage(
@Serializable
data class AdminFile(
val adminId: Long,
val token: String,
val updateMs: Long,
val watchingMessage: String
val adminId: Long = 12345,
val token: String = "12345",
val updateMs: Long = 30000,
val watchingMessage: String = "for new Blogposts",
val offlineMessage: String = "CONNECTION FAILED"
)
val SERVERS_FILE = File("servers.json")
val TEST_FILE = File("test.json")
val ADMIN_FILE = File("admin.json")
val json = Json(JsonConfiguration.Stable)
val SERVERS_FILE = File("servers.json").ensureExists(json.stringify(DiscordChannel.serializer().list, listOf()))
val SERVICE_CHANNELS_FILE =
File("service_channels.json").ensureExists(json.stringify(ServiceChannel.serializer().list, listOf()))
val ADMIN_FILE = File("admin.json").ensureExists(json.stringify(AdminFile.serializer(), AdminFile()))

View File

@@ -0,0 +1,15 @@
package de.wulkanat
import net.dv8tion.jda.api.JDA
import net.dv8tion.jda.api.entities.Activity
object DiscordRpc {
var jda: JDA? = null
fun updatePresence(available: Boolean) {
jda ?: return
jda!!.presence.activity = Activity.watching(if (available) Admin.message else Admin.offlineMessage)
jda!!.presence.isIdle = !available
}
}

View File

@@ -20,6 +20,7 @@ fun main() {
Channels.jda = builder
Admin.jda = builder
DiscordRpc.jda = builder
Admin.info()
Runtime.getRuntime().addShutdownHook(object : Thread() {

View File

@@ -109,6 +109,28 @@ class OwnerCli : ListenerAdapter() {
event.message.channel.sendMessage("Channel is not registered.").queue()
}
}
"serviceChannel" -> {
if (command.size > 1 && listOf("add", "remove").contains(command[1])) {
if (command[1] == "add") {
if (Channels.serviceChannels.find { it.id == channelId } != null) {
event.message.channel.sendMessage("Already a service channel.").queue()
} else {
Channels.serviceChannels.add(ServiceChannel(channelId))
Channels.saveChannels()
event.message.channel.sendMessage("Added as service channel.").queue()
}
} else {
event.message.channel.sendMessage(
if (Channels.serviceChannels.removeAll { it.id == channelId }) "Channel removed."
else "Not a service channel."
).queue()
}
Channels.saveChannels()
} else {
event.message.channel.sendMessage("Usage: `${prefix}serviceChannel [add|remove]`")
}
}
"publishMessage" -> {
val result = Channels.channels.find { it.id == channelId }
if (result != null) {
@@ -133,7 +155,12 @@ class OwnerCli : ListenerAdapter() {
EmbedBuilder()
.setTitle("Server overview")
.setColor(Color.GREEN)
.setDescription(Channels.getServerNames(event.message.guild.idLong).joinToString("\n"))
.setDescription("""
${Channels.getServerNames(event.message.guild.idLong).joinToString("\n")}
**_Service Channels_**
${Channels.getServiceChannelServers(event.message.guild.idLong).joinToString("\n")}
""".trimIndent())
.setAuthor(Admin.admin?.name, Admin.admin?.avatarUrl, Admin.admin?.avatarUrl)
.build()
).queue()
@@ -160,6 +187,8 @@ class OwnerCli : ListenerAdapter() {
"""
**${prefix}add**
Add this channel to the notified list
**${prefix}serviceChannel [add|remove]**
Add or remove this channel to receive service message from the bot developer (recommended)
**${prefix}remove**
Remove this channel to the notified list
**${prefix}publish [on|off]**

View File

@@ -0,0 +1,11 @@
package de.wulkanat.extensions
import java.io.File
fun File.ensureExists(defaultText: String? = null): File {
if (!this.exists()) {
this.createNewFile()
this.writeText(defaultText ?: return this)
}
return this
}

View File

@@ -1,6 +1,7 @@
package de.wulkanat.web
import de.wulkanat.Admin
import de.wulkanat.DiscordRpc
import de.wulkanat.model.BlogPostPreview
import org.jsoup.Jsoup
import java.io.IOException
@@ -8,6 +9,7 @@ import java.io.IOException
object SiteWatcher {
private const val BLOG_INDEX_URL = "https://www.hytale.com/news"
var newestBlog: BlogPostPreview? = null
private var siteOnline = false
fun hasNewBlogPost(): Boolean {
try {
@@ -26,10 +28,17 @@ object SiteWatcher {
}
} catch (e: IOException) {
Admin.error("Connection to Hytale Server failed", e.message ?: e.localizedMessage)
siteOnline = false
DiscordRpc.updatePresence(siteOnline)
return false
}
if (siteOnline) {
siteOnline = true
DiscordRpc.updatePresence(siteOnline)
}
return true
}
}