Quotes!
parent
2b2228cfa2
commit
b7eaead4a5
|
@ -1,6 +1,9 @@
|
||||||
# Don't leak secrets
|
# Don't leak secrets
|
||||||
config.json
|
config.json
|
||||||
|
|
||||||
|
# And no test data either
|
||||||
|
quotes.json
|
||||||
|
|
||||||
.gradle
|
.gradle
|
||||||
build/
|
build/
|
||||||
!gradle/wrapper/gradle-wrapper.jar
|
!gradle/wrapper/gradle-wrapper.jar
|
||||||
|
|
|
@ -7,22 +7,38 @@ import dev.kord.core.behavior.channel.createMessage
|
||||||
import dev.kord.core.behavior.interaction.response.respond
|
import dev.kord.core.behavior.interaction.response.respond
|
||||||
import dev.kord.core.builder.components.emoji
|
import dev.kord.core.builder.components.emoji
|
||||||
import dev.kord.core.entity.channel.TextChannel
|
import dev.kord.core.entity.channel.TextChannel
|
||||||
|
import dev.kord.core.entity.interaction.GuildChatInputCommandInteraction
|
||||||
|
import dev.kord.core.entity.interaction.InteractionCommand
|
||||||
import dev.kord.core.event.interaction.GuildButtonInteractionCreateEvent
|
import dev.kord.core.event.interaction.GuildButtonInteractionCreateEvent
|
||||||
|
import dev.kord.core.event.interaction.GuildChatInputCommandInteractionCreateEvent
|
||||||
import dev.kord.core.on
|
import dev.kord.core.on
|
||||||
|
import dev.kord.rest.builder.interaction.string
|
||||||
import dev.kord.rest.builder.message.create.actionRow
|
import dev.kord.rest.builder.message.create.actionRow
|
||||||
import kotlinx.coroutines.flow.*
|
import kotlinx.coroutines.flow.*
|
||||||
import kotlinx.serialization.decodeFromString
|
import kotlinx.serialization.decodeFromString
|
||||||
|
import kotlinx.serialization.encodeToString
|
||||||
import kotlinx.serialization.json.Json
|
import kotlinx.serialization.json.Json
|
||||||
import nl.kallestruik.discordbot.config.Config
|
import nl.kallestruik.discordbot.config.Config
|
||||||
|
import nl.kallestruik.discordbot.data.quotes.QuoteData
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
|
val prettyJson = Json {
|
||||||
|
prettyPrint = true
|
||||||
|
}
|
||||||
|
|
||||||
suspend fun main() {
|
suspend fun main() {
|
||||||
|
val quoteFile = File("quotes.json")
|
||||||
|
if (!quoteFile.exists())
|
||||||
|
quoteFile.writeText("[]") // Write an empty array if the file does not exist.
|
||||||
|
|
||||||
val config: Config = Json.decodeFromString(File("config.json").readText())
|
val config: Config = Json.decodeFromString(File("config.json").readText())
|
||||||
|
val quotes: MutableList<QuoteData> = Json.decodeFromString(quoteFile.readText())
|
||||||
|
|
||||||
val kord = Kord(config.token)
|
val kord = Kord(config.token)
|
||||||
|
|
||||||
val channel = kord.getChannel(Snowflake(config.roleChannelID)) as? TextChannel ?: return
|
val channel = kord.getChannel(Snowflake(config.roleChannelID)) as? TextChannel ?: return
|
||||||
|
|
||||||
|
// Delete old role selection messages
|
||||||
val oldMessages = mutableSetOf<Snowflake>()
|
val oldMessages = mutableSetOf<Snowflake>()
|
||||||
channel.messages
|
channel.messages
|
||||||
.filter { it.author == kord.getSelf() }
|
.filter { it.author == kord.getSelf() }
|
||||||
|
@ -30,6 +46,7 @@ suspend fun main() {
|
||||||
.toSet(oldMessages)
|
.toSet(oldMessages)
|
||||||
channel.bulkDelete(oldMessages)
|
channel.bulkDelete(oldMessages)
|
||||||
|
|
||||||
|
// Send the role selection message
|
||||||
channel.createMessage {
|
channel.createMessage {
|
||||||
actionRow {
|
actionRow {
|
||||||
for (role in config.roles) {
|
for (role in config.roles) {
|
||||||
|
@ -43,6 +60,32 @@ suspend fun main() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Create the quotes command. Does discord get mad if this gets done on every startup?
|
||||||
|
kord.createGuildChatInputCommand(Snowflake(config.guildID), "quotes", "Get a quote") {
|
||||||
|
string("query", "What to search for.")
|
||||||
|
}
|
||||||
|
|
||||||
|
kord.createGuildChatInputCommand(Snowflake(config.guildID), "quote", "Add a new quote") {
|
||||||
|
string("author", "The author of the quote.") {
|
||||||
|
required = true
|
||||||
|
}
|
||||||
|
|
||||||
|
string("quote", "The quote.") {
|
||||||
|
required = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle guild chat commands
|
||||||
|
kord.on<GuildChatInputCommandInteractionCreateEvent> {
|
||||||
|
val command = interaction.command
|
||||||
|
if (command.rootName == "quotes")
|
||||||
|
quotesCommandHandler(interaction, command, quotes)
|
||||||
|
|
||||||
|
if (command.rootName == "quote")
|
||||||
|
quoteCommandHandler(interaction, command, quotes, quoteFile)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle guild chat buttons
|
||||||
kord.on<GuildButtonInteractionCreateEvent> {
|
kord.on<GuildButtonInteractionCreateEvent> {
|
||||||
val response = interaction.deferEphemeralResponse()
|
val response = interaction.deferEphemeralResponse()
|
||||||
val roleConfig = config.roles[interaction.data.data.customId.value]
|
val roleConfig = config.roles[interaction.data.data.customId.value]
|
||||||
|
@ -68,5 +111,69 @@ suspend fun main() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Start the bot
|
||||||
kord.login()
|
kord.login()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
suspend fun quoteCommandHandler(
|
||||||
|
interaction: GuildChatInputCommandInteraction,
|
||||||
|
command: InteractionCommand,
|
||||||
|
quotes: MutableList<QuoteData>,
|
||||||
|
quoteFile: File
|
||||||
|
) {
|
||||||
|
val response = interaction.deferEphemeralResponse()
|
||||||
|
|
||||||
|
val author = command.strings["author"]!! // These are required so they can't be null
|
||||||
|
val quote = command.strings["quote"]!!.replace("\\n", "\n")
|
||||||
|
quotes.add(QuoteData(author, quote))
|
||||||
|
|
||||||
|
quoteFile.writeText(prettyJson.encodeToString(quotes))
|
||||||
|
|
||||||
|
response.respond {
|
||||||
|
content = "Added quote successfully!"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun quotesCommandHandler(
|
||||||
|
interaction: GuildChatInputCommandInteraction,
|
||||||
|
command: InteractionCommand,
|
||||||
|
quotes: MutableList<QuoteData>
|
||||||
|
) {
|
||||||
|
val response = interaction.deferPublicResponse()
|
||||||
|
|
||||||
|
val query = Regex(command.strings["query"] ?: "", RegexOption.IGNORE_CASE)
|
||||||
|
|
||||||
|
val quotes = quotes.filter {
|
||||||
|
it.quote.contains(query) || it.author.contains(query)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (quotes.isEmpty()) {
|
||||||
|
response.respond {
|
||||||
|
content = "No quotes found!"
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
response.respond {
|
||||||
|
content = "Search results for: $query"
|
||||||
|
}
|
||||||
|
|
||||||
|
var content = ""
|
||||||
|
for (quote in quotes) {
|
||||||
|
val quoteString = "**${quote.author}:** ${quote.quote}\n"
|
||||||
|
if (content.length + quoteString.length >= 2000) {
|
||||||
|
interaction.channel.createMessage {
|
||||||
|
this.content = content
|
||||||
|
}
|
||||||
|
content = quoteString
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
content += quoteString
|
||||||
|
}
|
||||||
|
|
||||||
|
interaction.channel.createMessage {
|
||||||
|
this.content = content
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
package nl.kallestruik.discordbot.data.quotes
|
||||||
|
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class QuoteData(
|
||||||
|
val author: String,
|
||||||
|
val quote: String,
|
||||||
|
)
|
Loading…
Reference in New Issue