feat: middle save

This commit is contained in:
Project_IO 2024-09-23 16:45:34 +09:00
parent bc4c985735
commit 8c9b4a1112
11 changed files with 68 additions and 38 deletions

View file

@ -8,6 +8,7 @@ import org.slf4j.LoggerFactory
abstract class Plugin { abstract class Plugin {
private val handlerContainer = mutableListOf<ListenerAdapter>() private val handlerContainer = mutableListOf<ListenerAdapter>()
val config = this.javaClass.getResourceAsStream("/plugin.json")!!.let { val config = this.javaClass.getResourceAsStream("/plugin.json")!!.let {
val raw = it.bufferedReader().readText() val raw = it.bufferedReader().readText()
val obj = Json.decodeFromString<PluginConfig>(raw) val obj = Json.decodeFromString<PluginConfig>(raw)

View file

@ -1,5 +1,8 @@
package net.projecttl.p.x32.api.command package net.projecttl.p.x32.api.command
import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking import kotlinx.coroutines.runBlocking
import net.dv8tion.jda.api.JDA import net.dv8tion.jda.api.JDA
import net.dv8tion.jda.api.events.interaction.command.MessageContextInteractionEvent import net.dv8tion.jda.api.events.interaction.command.MessageContextInteractionEvent
@ -15,6 +18,7 @@ fun commandHandler(block: (CommandHandler) -> Unit): CommandHandler {
return handler return handler
} }
@OptIn(DelicateCoroutinesApi::class)
class CommandHandler(val guildId: Long = 0L) : ListenerAdapter() { class CommandHandler(val guildId: Long = 0L) : ListenerAdapter() {
private val commands = mutableListOf<CommandExecutor>() private val commands = mutableListOf<CommandExecutor>()
@ -24,7 +28,7 @@ class CommandHandler(val guildId: Long = 0L) : ListenerAdapter() {
commands.forEach { command -> commands.forEach { command ->
if (command.data.name == name) { if (command.data.name == name) {
if (command is GlobalCommand) { if (command is GlobalCommand) {
runBlocking { GlobalScope.launch {
command.execute(ev) command.execute(ev)
} }
@ -40,7 +44,7 @@ class CommandHandler(val guildId: Long = 0L) : ListenerAdapter() {
commands.forEach { command -> commands.forEach { command ->
if (command.data.name == name) { if (command.data.name == name) {
if (command is UserContext) { if (command is UserContext) {
runBlocking { GlobalScope.launch {
command.execute(ev) command.execute(ev)
} }
@ -56,7 +60,7 @@ class CommandHandler(val guildId: Long = 0L) : ListenerAdapter() {
commands.forEach { command -> commands.forEach { command ->
if (command.data.name == name) { if (command.data.name == name) {
if (command is MessageContext) { if (command is MessageContext) {
runBlocking { GlobalScope.launch {
command.execute(ev) command.execute(ev)
} }

View file

@ -1,9 +0,0 @@
package net.projecttl.p.x32.api.util
import net.dv8tion.jda.api.EmbedBuilder
import kotlin.random.Random
fun EmbedBuilder.colour(): EmbedBuilder {
val rand = Random.nextInt(0x000001, 0xffffff)
return this.setColor(rand)
}

View file

@ -0,0 +1,24 @@
package net.projecttl.p.x32.api.util
import net.dv8tion.jda.api.EmbedBuilder
import net.dv8tion.jda.api.entities.User
import java.time.LocalDate
import java.time.LocalDateTime
import kotlin.random.Random
fun EmbedBuilder.colour(): EmbedBuilder {
val rand = Random.nextInt(0x000001, 0xffffff)
return this.setColor(rand)
}
fun EmbedBuilder.footer(user: User): EmbedBuilder {
val date = LocalDateTime.now()
val mon = if (date.month.value > 9) {
date.month.value
} else {
"0${date.month.value}"
}
val str = "${user.name}${date.year}-${mon}-${date.dayOfMonth} ${date.hour}:${date.minute}"
return this.setFooter(str, "${user.avatarUrl}?size=1024")
}

View file

@ -1,5 +1,8 @@
package net.projecttl.p.x32 package net.projecttl.p.x32
import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import net.dv8tion.jda.api.JDA import net.dv8tion.jda.api.JDA
import net.projecttl.p.x32.command.Info import net.projecttl.p.x32.command.Info
import net.projecttl.p.x32.command.PluginCommand import net.projecttl.p.x32.command.PluginCommand
@ -17,6 +20,7 @@ lateinit var database: Database
val logger: Logger = LoggerFactory.getLogger(Px32::class.java) val logger: Logger = LoggerFactory.getLogger(Px32::class.java)
@OptIn(DelicateCoroutinesApi::class)
fun main() { fun main() {
println("Px32 version v${DefaultConfig.version}") println("Px32 version v${DefaultConfig.version}")
if (Config.owner.isBlank() || Config.owner.isEmpty()) { if (Config.owner.isBlank() || Config.owner.isEmpty()) {
@ -31,6 +35,9 @@ fun main() {
handler.addCommand(PluginCommand) handler.addCommand(PluginCommand)
jda = kernel.build() jda = kernel.build()
GlobalScope.launch {
kernel.register(jda)
}
} }
object Px32 object Px32

View file

@ -7,6 +7,7 @@ import net.dv8tion.jda.api.interactions.commands.build.CommandData
import net.dv8tion.jda.internal.interactions.CommandDataImpl import net.dv8tion.jda.internal.interactions.CommandDataImpl
import net.projecttl.p.x32.api.command.GlobalCommand import net.projecttl.p.x32.api.command.GlobalCommand
import net.projecttl.p.x32.api.util.colour import net.projecttl.p.x32.api.util.colour
import net.projecttl.p.x32.api.util.footer
import net.projecttl.p.x32.kernel.PluginLoader import net.projecttl.p.x32.kernel.PluginLoader
object PluginCommand : GlobalCommand { object PluginCommand : GlobalCommand {
@ -18,6 +19,7 @@ object PluginCommand : GlobalCommand {
setThumbnail(ev.jda.selfUser.avatarUrl) setThumbnail(ev.jda.selfUser.avatarUrl)
colour() colour()
footer(ev.user)
} }
val loader = PluginLoader.getPlugins() val loader = PluginLoader.getPlugins()

View file

@ -11,7 +11,7 @@ object Reload : GlobalCommand {
override val data = CommandData.fromData(CommandDataImpl("reload", "플러그인을 다시 불러 옵니다").toData()) override val data = CommandData.fromData(CommandDataImpl("reload", "플러그인을 다시 불러 옵니다").toData())
override suspend fun execute(ev: SlashCommandInteractionEvent) { override suspend fun execute(ev: SlashCommandInteractionEvent) {
if (kernel.memLock) { if (kernel.memLock.isLocked) {
return return
} }
@ -20,13 +20,13 @@ object Reload : GlobalCommand {
} }
try { try {
kernel.reload() kernel.reload(ev.jda)
} catch (ex: Exception) { } catch (ex: Exception) {
ex.printStackTrace() ex.printStackTrace()
ev.reply(":warning: 플러그인을 다시 불러오는 도중에 오류가 발생 했어요. 자세한 내용은 콘솔을 확인해 주세요!").queue() ev.reply(":warning: 플러그인을 다시 불러오는 도중에 오류가 발생 했어요. 자세한 내용은 콘솔을 확인해 주세요!").queue()
return return
} }
ev.reply(":white_check_mark: 플러그인을 다시 불러 왔어요!\n불러온 플러그인 수: ${kernel.plugins().size}").queue() ev.reply(":white_check_mark: 플러그인을 다시 불러 왔어요!\n불러온 플러그인 수: ${kernel.plugins.size}").queue()
} }
} }

View file

@ -1,19 +1,16 @@
package net.projecttl.p.x32.kernel package net.projecttl.p.x32.kernel
import kotlinx.coroutines.sync.Mutex
import net.dv8tion.jda.api.JDA import net.dv8tion.jda.api.JDA
import net.dv8tion.jda.api.JDABuilder import net.dv8tion.jda.api.JDABuilder
import net.dv8tion.jda.api.hooks.ListenerAdapter import net.dv8tion.jda.api.hooks.ListenerAdapter
import net.dv8tion.jda.api.requests.GatewayIntent import net.dv8tion.jda.api.requests.GatewayIntent
import net.projecttl.p.x32.api.Plugin
import net.projecttl.p.x32.api.command.CommandHandler import net.projecttl.p.x32.api.command.CommandHandler
import net.projecttl.p.x32.config.Config import net.projecttl.p.x32.config.Config
import net.projecttl.p.x32.func.BundleModule import net.projecttl.p.x32.func.BundleModule
import net.projecttl.p.x32.jda
import net.projecttl.p.x32.logger import net.projecttl.p.x32.logger
class CoreKernel(token: String) { class CoreKernel(token: String) {
var memLock = false
private set
private val builder = JDABuilder.createDefault(token, listOf( private val builder = JDABuilder.createDefault(token, listOf(
GatewayIntent.GUILD_PRESENCES, GatewayIntent.GUILD_PRESENCES,
GatewayIntent.GUILD_MEMBERS, GatewayIntent.GUILD_MEMBERS,
@ -25,6 +22,9 @@ class CoreKernel(token: String) {
private val handlers = mutableListOf<ListenerAdapter>() private val handlers = mutableListOf<ListenerAdapter>()
private val commandContainer = CommandHandler() private val commandContainer = CommandHandler()
val memLock = Mutex()
val plugins get() = PluginLoader.getPlugins().map { it.value }
private fun include() { private fun include() {
if (Config.bundle) { if (Config.bundle) {
val b = BundleModule() val b = BundleModule()
@ -44,15 +44,11 @@ class CoreKernel(token: String) {
handlers.remove(handler) handlers.remove(handler)
} }
fun plugins(): List<Plugin> {
return PluginLoader.getPlugins().map { it.value }
}
fun build(): JDA { fun build(): JDA {
include() include()
PluginLoader.load() PluginLoader.load()
plugins().forEach { plugin -> plugins.forEach { plugin ->
plugin.handlers.forEach { handler -> plugin.handlers.forEach { handler ->
handlers.add(handler) handlers.add(handler)
} }
@ -64,7 +60,10 @@ class CoreKernel(token: String) {
} }
builder.addEventListeners(commandContainer) builder.addEventListeners(commandContainer)
val jda = builder.build() return builder.build()
}
fun register(jda: JDA) {
commandContainer.register(jda) commandContainer.register(jda)
handlers.forEach { h -> handlers.forEach { h ->
if (h is CommandHandler) { if (h is CommandHandler) {
@ -75,18 +74,16 @@ class CoreKernel(token: String) {
Runtime.getRuntime().addShutdownHook(Thread { Runtime.getRuntime().addShutdownHook(Thread {
PluginLoader.destroy() PluginLoader.destroy()
}) })
return jda
} }
fun reload() { suspend fun reload(jda: JDA) {
if (!memLock) { if (!memLock.isLocked) {
memLock = true memLock.lock()
} }
val newHandlers = mutableListOf<ListenerAdapter>() val newHandlers = mutableListOf<ListenerAdapter>()
PluginLoader.destroy() PluginLoader.destroy()
plugins().forEach { plugin -> plugins.forEach { plugin ->
plugin.handlers.forEach { handler -> plugin.handlers.forEach { handler ->
if (handlers.contains(handler)) { if (handlers.contains(handler)) {
jda.removeEventListener(handler) jda.removeEventListener(handler)
@ -98,7 +95,7 @@ class CoreKernel(token: String) {
include() include()
PluginLoader.load() PluginLoader.load()
plugins().forEach { plugin -> plugins.forEach { plugin ->
plugin.handlers.forEach { handler -> plugin.handlers.forEach { handler ->
if (!handlers.contains(handler)) { if (!handlers.contains(handler)) {
handlers.add(handler) handlers.add(handler)
@ -108,15 +105,15 @@ class CoreKernel(token: String) {
} }
handlers.map { handlers.map {
builder.addEventListeners(it) jda.addEventListener(it)
} }
newHandlers.forEach { h -> handlers.forEach { h ->
if (h is CommandHandler) { if (h is CommandHandler) {
h.register(jda) h.register(jda)
} }
} }
memLock = false memLock.unlock()
} }
} }

View file

@ -6,6 +6,7 @@ import net.dv8tion.jda.api.interactions.commands.build.CommandData
import net.dv8tion.jda.internal.interactions.CommandDataImpl import net.dv8tion.jda.internal.interactions.CommandDataImpl
import net.projecttl.p.x32.api.command.UserContext import net.projecttl.p.x32.api.command.UserContext
import net.projecttl.p.x32.api.util.colour import net.projecttl.p.x32.api.util.colour
import net.projecttl.p.x32.api.util.footer
object Avatar : UserContext { object Avatar : UserContext {
override val data = CommandData.fromData(CommandDataImpl("avatar", "유저의 프로필 이미지를 가져 옵니다").toData()) override val data = CommandData.fromData(CommandDataImpl("avatar", "유저의 프로필 이미지를 가져 옵니다").toData())
@ -15,6 +16,7 @@ object Avatar : UserContext {
embed.setTitle(":frame_photo: ${ev.target.name}'s Avatar") embed.setTitle(":frame_photo: ${ev.target.name}'s Avatar")
embed.setImage("${ev.target.effectiveAvatarUrl}?size=512") embed.setImage("${ev.target.effectiveAvatarUrl}?size=512")
embed.colour() embed.colour()
embed.footer(ev.user)
ev.replyEmbeds(embed.build()).queue() ev.replyEmbeds(embed.build()).queue()
} }

View file

@ -3,11 +3,13 @@ package net.projecttl.p.x32.func.command
import net.dv8tion.jda.api.EmbedBuilder import net.dv8tion.jda.api.EmbedBuilder
import net.dv8tion.jda.api.JDA import net.dv8tion.jda.api.JDA
import net.dv8tion.jda.api.entities.MessageEmbed import net.dv8tion.jda.api.entities.MessageEmbed
import net.dv8tion.jda.api.entities.User
import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent
import net.dv8tion.jda.api.interactions.commands.build.CommandData import net.dv8tion.jda.api.interactions.commands.build.CommandData
import net.dv8tion.jda.internal.interactions.CommandDataImpl import net.dv8tion.jda.internal.interactions.CommandDataImpl
import net.projecttl.p.x32.api.command.GlobalCommand import net.projecttl.p.x32.api.command.GlobalCommand
import net.projecttl.p.x32.api.util.colour import net.projecttl.p.x32.api.util.colour
import net.projecttl.p.x32.api.util.footer
object Ping : GlobalCommand { object Ping : GlobalCommand {
override val data: CommandData = CommandData.fromData(CommandDataImpl( override val data: CommandData = CommandData.fromData(CommandDataImpl(
@ -25,17 +27,18 @@ object Ping : GlobalCommand {
}.build() }.build()
ev.replyEmbeds(embed).queue { ev.replyEmbeds(embed).queue {
embed = measure(started, ev.jda) embed = measure(started, ev.user, ev.jda)
it.editOriginalEmbeds(embed).queue() it.editOriginalEmbeds(embed).queue()
} }
} }
private fun measure(started: Long, jda: JDA): MessageEmbed { private fun measure(started: Long, user: User, jda: JDA): MessageEmbed {
val embed = EmbedBuilder() val embed = EmbedBuilder()
embed.setTitle(":ping_pong: **Pong!**") embed.setTitle(":ping_pong: **Pong!**")
embed.addField(":electric_plug: **API**", "`${jda.gatewayPing}ms`", true) embed.addField(":electric_plug: **API**", "`${jda.gatewayPing}ms`", true)
embed.addField(":robot: **BOT**", "`${System.currentTimeMillis() - started}ms`", true) embed.addField(":robot: **BOT**", "`${System.currentTimeMillis() - started}ms`", true)
embed.colour() embed.colour()
embed.footer(user)
return embed.build() return embed.build()
} }

View file

@ -10,7 +10,6 @@ class CorePlugin extends Plugin {
logger.info "Hello, World!" logger.info "Hello, World!"
CommandHandler handler = new CommandHandler() CommandHandler handler = new CommandHandler()
handler.addCommand new Greeting() handler.addCommand new Greeting()
addHandler handler addHandler handler
} }