diff --git a/px32-bot-api/src/main/kotlin/net/projecttl/p/x32/api/command/CommandObj.kt b/px32-bot-api/src/main/kotlin/net/projecttl/p/x32/api/command/CommandObj.kt new file mode 100644 index 0000000..ac5068d --- /dev/null +++ b/px32-bot-api/src/main/kotlin/net/projecttl/p/x32/api/command/CommandObj.kt @@ -0,0 +1,128 @@ +package net.projecttl.p.x32.api.command + +import net.dv8tion.jda.api.interactions.commands.OptionType +import net.dv8tion.jda.api.interactions.commands.build.CommandData +import net.dv8tion.jda.api.interactions.commands.build.OptionData +import net.dv8tion.jda.api.interactions.commands.build.SubcommandData +import net.dv8tion.jda.api.interactions.commands.build.SubcommandGroupData +import net.dv8tion.jda.internal.interactions.CommandDataImpl + +fun useCommand(init: CommandObj.() -> Unit): CommandData { + val obj = CommandObj() + init.invoke(obj) + + return obj.build() +} + +class CommandObj { + var name: String = "" + var description: String = "" + + val subcommands = mutableListOf() + val subcommandGroups = mutableListOf() + val options = mutableListOf() + + fun subcommand(sub: SubcommandObj.() -> Unit) { + val obj = SubcommandObj() + sub.invoke(obj) + + subcommands += obj.build() + } + + fun subcommandGroup(group: SubcommandGroupObj.() -> Unit) { + val obj = SubcommandGroupObj() + group.invoke(obj) + + subcommandGroups += obj.build() + } + + fun option(opt: OptionObj.() -> Unit) { + val obj = OptionObj() + opt.invoke(obj) + + options += obj.build() + } + + fun build(): CommandData { + val obj = CommandDataImpl(name, description) + if (subcommands.isNotEmpty()) { + subcommands.forEach { + obj.addSubcommands(it) + } + } + + if (subcommandGroups.isNotEmpty()) { + subcommandGroups.forEach { + obj.addSubcommandGroups(it) + } + } + + if (options.isNotEmpty()) { + options.forEach { + obj.addOptions(it) + } + } + + return CommandData.fromData(obj.toData()) + } +} + +class SubcommandObj { + var name: String = "" + var description: String = "" + val options = mutableListOf() + + fun option(opt: OptionObj.() -> Unit) { + val obj = OptionObj() + opt.invoke(obj) + + options += obj.build() + } + + fun build(): SubcommandData { + val obj = SubcommandData(name, description) + if (options.isNotEmpty()) { + options.forEach { + obj.addOptions(it) + } + } + + return obj + } +} + +class SubcommandGroupObj { + var name: String = "" + var description: String = "" + val subcommands = mutableListOf() + + fun subcommand(opt: SubcommandObj.() -> Unit) { + val obj = SubcommandObj() + opt.invoke(obj) + + subcommands += obj.build() + } + + fun build(): SubcommandGroupData { + val obj = SubcommandGroupData(name, description) + if (subcommands.isNotEmpty()) { + subcommands.forEach { + obj.addSubcommands(it) + } + } + + return obj + } +} + +class OptionObj { + lateinit var type: OptionType + var name: String = "" + var description: String = "" + var required: Boolean = false + var autoComplete: Boolean = false + + fun build(): OptionData { + return OptionData(type, name, description, required, autoComplete) + } +} diff --git a/px32-bot-core/src/main/kotlin/net/projecttl/p/x32/Px32.kt b/px32-bot-core/src/main/kotlin/net/projecttl/p/x32/Px32.kt index 595c921..72a3e60 100644 --- a/px32-bot-core/src/main/kotlin/net/projecttl/p/x32/Px32.kt +++ b/px32-bot-core/src/main/kotlin/net/projecttl/p/x32/Px32.kt @@ -4,10 +4,10 @@ import kotlinx.coroutines.DelicateCoroutinesApi import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.launch import net.dv8tion.jda.api.JDA +import net.projecttl.p.x32.api.BotConfig import net.projecttl.p.x32.command.Info import net.projecttl.p.x32.command.PluginCommand import net.projecttl.p.x32.command.Reload -import net.projecttl.p.x32.api.BotConfig import net.projecttl.p.x32.config.DefaultConfig import net.projecttl.p.x32.kernel.CoreKernel import org.slf4j.Logger @@ -21,7 +21,7 @@ lateinit var kernel: CoreKernel val logger: Logger = LoggerFactory.getLogger(Px32::class.java) @OptIn(DelicateCoroutinesApi::class) -fun main() { +fun main(args: Array) { println("Px32 version v${DefaultConfig.version}") if (BotConfig.owner.isBlank() || BotConfig.owner.isEmpty()) { logger.warn("owner option is blank or empty!") @@ -30,6 +30,27 @@ fun main() { kernel = CoreKernel(BotConfig.token) val handler = kernel.commandContainer + if (args.contains("--remove-cmd")) { + jda = kernel.build() + try { + jda.retrieveCommands().queue { + if (it == null) { + return@queue + } + + it.forEach { command -> + logger.info("unregister command: /${command.name}") + command.jda.deleteCommandById(command.id).queue() + } + } + } catch (ex: Exception) { + ex.printStackTrace() + } + + kernel.kill() + return + } + handler.addCommand(Info) handler.addCommand(Reload) handler.addCommand(PluginCommand) diff --git a/px32-bot-core/src/main/kotlin/net/projecttl/p/x32/command/Info.kt b/px32-bot-core/src/main/kotlin/net/projecttl/p/x32/command/Info.kt index eeb7c2a..b8598e5 100644 --- a/px32-bot-core/src/main/kotlin/net/projecttl/p/x32/command/Info.kt +++ b/px32-bot-core/src/main/kotlin/net/projecttl/p/x32/command/Info.kt @@ -3,16 +3,17 @@ package net.projecttl.p.x32.command import net.dv8tion.jda.api.JDAInfo import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent import net.dv8tion.jda.api.interactions.commands.build.CommandData -import net.dv8tion.jda.internal.interactions.CommandDataImpl import net.projecttl.p.x32.api.command.GlobalCommand +import net.projecttl.p.x32.api.command.useCommand import net.projecttl.p.x32.config.DefaultConfig import net.projecttl.p.x32.kernel import java.lang.management.ManagementFactory object Info : GlobalCommand { - override val data: CommandData = CommandData.fromData( - CommandDataImpl("info","봇의 정보를 표시 합니다").toData() - ) + override val data: CommandData = useCommand { + name = "info" + description = "봇의 정보를 표시 합니다" + } override suspend fun execute(ev: SlashCommandInteractionEvent) { val rb = ManagementFactory.getRuntimeMXBean() diff --git a/px32-bot-core/src/main/kotlin/net/projecttl/p/x32/command/PluginCommand.kt b/px32-bot-core/src/main/kotlin/net/projecttl/p/x32/command/PluginCommand.kt index 2af47c7..b1e02a6 100644 --- a/px32-bot-core/src/main/kotlin/net/projecttl/p/x32/command/PluginCommand.kt +++ b/px32-bot-core/src/main/kotlin/net/projecttl/p/x32/command/PluginCommand.kt @@ -3,15 +3,17 @@ package net.projecttl.p.x32.command import net.dv8tion.jda.api.EmbedBuilder import net.dv8tion.jda.api.entities.MessageEmbed import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent -import net.dv8tion.jda.api.interactions.commands.build.CommandData -import net.dv8tion.jda.internal.interactions.CommandDataImpl import net.projecttl.p.x32.api.command.GlobalCommand +import net.projecttl.p.x32.api.command.useCommand import net.projecttl.p.x32.api.util.colour import net.projecttl.p.x32.api.util.footer import net.projecttl.p.x32.kernel object PluginCommand : GlobalCommand { - override val data = CommandData.fromData(CommandDataImpl("plugins", "봇에 불러온 플러그인을 확인 합니다").toData()) + override val data = useCommand { + name = "plugins" + description = "봇에 불러온 플러그인을 확인 합니다" + } override suspend fun execute(ev: SlashCommandInteractionEvent) { val embed = EmbedBuilder().apply { diff --git a/px32-bot-core/src/main/kotlin/net/projecttl/p/x32/command/Reload.kt b/px32-bot-core/src/main/kotlin/net/projecttl/p/x32/command/Reload.kt index 991f5cc..54e056f 100644 --- a/px32-bot-core/src/main/kotlin/net/projecttl/p/x32/command/Reload.kt +++ b/px32-bot-core/src/main/kotlin/net/projecttl/p/x32/command/Reload.kt @@ -1,14 +1,16 @@ package net.projecttl.p.x32.command import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent -import net.dv8tion.jda.api.interactions.commands.build.CommandData -import net.dv8tion.jda.internal.interactions.CommandDataImpl -import net.projecttl.p.x32.api.command.GlobalCommand import net.projecttl.p.x32.api.BotConfig +import net.projecttl.p.x32.api.command.GlobalCommand +import net.projecttl.p.x32.api.command.useCommand import net.projecttl.p.x32.kernel object Reload : GlobalCommand { - override val data = CommandData.fromData(CommandDataImpl("reload", "플러그인을 다시 불러 옵니다").toData()) + override val data = useCommand { + name = "reload" + description = "플러그인을 다시 불러 옵니다" + } override suspend fun execute(ev: SlashCommandInteractionEvent) { if (kernel.memLock.isLocked) { diff --git a/px32-bot-core/src/main/kotlin/net/projecttl/p/x32/kernel/CoreKernel.kt b/px32-bot-core/src/main/kotlin/net/projecttl/p/x32/kernel/CoreKernel.kt index e203025..2e60ee1 100644 --- a/px32-bot-core/src/main/kotlin/net/projecttl/p/x32/kernel/CoreKernel.kt +++ b/px32-bot-core/src/main/kotlin/net/projecttl/p/x32/kernel/CoreKernel.kt @@ -98,6 +98,11 @@ class CoreKernel(token: String) { memLock.unlock() } + fun kill() { + destroy() + jda.shutdownNow() + } + private fun load() { if (BotConfig.bundle) { val b = BundleModule() diff --git a/px32-bot-module/src/main/kotlin/net/projecttl/p/x32/func/command/Avatar.kt b/px32-bot-module/src/main/kotlin/net/projecttl/p/x32/func/command/Avatar.kt index 3da4daa..6bcad24 100644 --- a/px32-bot-module/src/main/kotlin/net/projecttl/p/x32/func/command/Avatar.kt +++ b/px32-bot-module/src/main/kotlin/net/projecttl/p/x32/func/command/Avatar.kt @@ -2,14 +2,16 @@ package net.projecttl.p.x32.func.command import net.dv8tion.jda.api.EmbedBuilder import net.dv8tion.jda.api.events.interaction.command.UserContextInteractionEvent -import net.dv8tion.jda.api.interactions.commands.build.CommandData -import net.dv8tion.jda.internal.interactions.CommandDataImpl import net.projecttl.p.x32.api.command.UserContext +import net.projecttl.p.x32.api.command.useCommand import net.projecttl.p.x32.api.util.colour import net.projecttl.p.x32.api.util.footer object Avatar : UserContext { - override val data = CommandData.fromData(CommandDataImpl("avatar", "유저의 프로필 이미지를 가져 옵니다").toData()) + override val data = useCommand { + name = "avatar" + description = "유저의 프로필 이미지를 가져 옵니다" + } override suspend fun execute(ev: UserContextInteractionEvent) { val embed = EmbedBuilder() diff --git a/px32-bot-module/src/main/kotlin/net/projecttl/p/x32/func/command/Bmi.kt b/px32-bot-module/src/main/kotlin/net/projecttl/p/x32/func/command/Bmi.kt index 46ba33d..73dba7e 100644 --- a/px32-bot-module/src/main/kotlin/net/projecttl/p/x32/func/command/Bmi.kt +++ b/px32-bot-module/src/main/kotlin/net/projecttl/p/x32/func/command/Bmi.kt @@ -3,9 +3,8 @@ package net.projecttl.p.x32.func.command import net.dv8tion.jda.api.EmbedBuilder import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent import net.dv8tion.jda.api.interactions.commands.OptionType -import net.dv8tion.jda.api.interactions.commands.build.CommandData -import net.dv8tion.jda.internal.interactions.CommandDataImpl import net.projecttl.p.x32.api.command.GlobalCommand +import net.projecttl.p.x32.api.command.useCommand import net.projecttl.p.x32.api.util.colour import net.projecttl.p.x32.api.util.footer import java.math.RoundingMode @@ -13,10 +12,24 @@ import java.text.DecimalFormat import kotlin.math.pow object Bmi : GlobalCommand { - override val data = CommandData.fromData(CommandDataImpl("bmi", "키와 몸무게 기반으로 bmi지수를 계산할 수 있어요").apply { - addOption(OptionType.NUMBER, "height", "신장 길이를 적어 주세요 (cm)", true) - addOption(OptionType.NUMBER, "weight", "몸무게를 적어 주세요 (kg)", true) - }.toData()) + override val data = useCommand { + name = "bmi" + description = "키와 몸무게 기반으로 bmi 지수를 계산해요" + + option { + type = OptionType.NUMBER + name = "height" + description = "신장 길이를 적어 주세요 (cm)" + required = true + } + + option { + type = OptionType.NUMBER + name = "weight" + description = "몸무게를 적어 주세요 (kg)" + required = true + } + } override suspend fun execute(ev: SlashCommandInteractionEvent) { val height = ev.getOption("height")!!.asDouble @@ -30,9 +43,9 @@ object Bmi : GlobalCommand { val bmi = weight / (height / 100).pow(2) fun result(bmi: Double): String { return when { - bmi < 18.5 -> "**저체중**" + bmi < 18.5 -> "**저체중**" bmi in 18.5..24.9 -> "**정상 체중**" - bmi in 25.0.. 29.9 -> "**과체중**" + bmi in 25.0..29.9 -> "**과체중**" else -> "**비만**" } } diff --git a/px32-bot-module/src/main/kotlin/net/projecttl/p/x32/func/command/Dice.kt b/px32-bot-module/src/main/kotlin/net/projecttl/p/x32/func/command/Dice.kt index 692ddcd..cfa9bd8 100644 --- a/px32-bot-module/src/main/kotlin/net/projecttl/p/x32/func/command/Dice.kt +++ b/px32-bot-module/src/main/kotlin/net/projecttl/p/x32/func/command/Dice.kt @@ -1,14 +1,16 @@ package net.projecttl.p.x32.func.command import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent -import net.dv8tion.jda.api.interactions.commands.build.CommandData -import net.dv8tion.jda.internal.interactions.CommandDataImpl import net.projecttl.p.x32.api.command.GlobalCommand +import net.projecttl.p.x32.api.command.useCommand import kotlin.random.Random import kotlin.random.nextInt object Dice : GlobalCommand { - override val data = CommandData.fromData(CommandDataImpl("dice", "랜덤으로 주사위를 굴립니다").toData()) + override val data = useCommand { + name = "dice" + description = "랜덤으로 주사위를 굴립니다" + } override suspend fun execute(ev: SlashCommandInteractionEvent) { val rand = Random.nextInt(1..6) diff --git a/px32-bot-module/src/main/kotlin/net/projecttl/p/x32/func/command/MsgLength.kt b/px32-bot-module/src/main/kotlin/net/projecttl/p/x32/func/command/MsgLength.kt index 973cbbc..fadedbb 100644 --- a/px32-bot-module/src/main/kotlin/net/projecttl/p/x32/func/command/MsgLength.kt +++ b/px32-bot-module/src/main/kotlin/net/projecttl/p/x32/func/command/MsgLength.kt @@ -1,12 +1,14 @@ package net.projecttl.p.x32.func.command import net.dv8tion.jda.api.events.interaction.command.MessageContextInteractionEvent -import net.dv8tion.jda.api.interactions.commands.build.CommandData -import net.dv8tion.jda.internal.interactions.CommandDataImpl import net.projecttl.p.x32.api.command.MessageContext +import net.projecttl.p.x32.api.command.useCommand object MsgLength : MessageContext { - override val data = CommandData.fromData(CommandDataImpl("length", "메시지의 길이를 확인 합니다.").toData()) + override val data = useCommand { + name = "length" + description = "메시지의 길이를 확인 합니다." + } override suspend fun execute(ev: MessageContextInteractionEvent) { val target = ev.target diff --git a/px32-bot-module/src/main/kotlin/net/projecttl/p/x32/func/command/MsgPurge.kt b/px32-bot-module/src/main/kotlin/net/projecttl/p/x32/func/command/MsgPurge.kt index a5374b8..2aca0f5 100644 --- a/px32-bot-module/src/main/kotlin/net/projecttl/p/x32/func/command/MsgPurge.kt +++ b/px32-bot-module/src/main/kotlin/net/projecttl/p/x32/func/command/MsgPurge.kt @@ -2,17 +2,21 @@ package net.projecttl.p.x32.func.command import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent import net.dv8tion.jda.api.interactions.commands.OptionType -import net.dv8tion.jda.api.interactions.commands.build.CommandData -import net.dv8tion.jda.internal.interactions.CommandDataImpl import net.projecttl.p.x32.api.command.GlobalCommand +import net.projecttl.p.x32.api.command.useCommand import net.projecttl.p.x32.func.Conf object MsgPurge : GlobalCommand { - override val data = CommandData.fromData( - CommandDataImpl("purge", "n개의 메시지를 채널에서 삭제해요").apply { - addOption(OptionType.INTEGER, "n", "n개만큼 메시지가 삭제 됩니다", true) - }.toData() - ) + override val data = useCommand { + name = "purge" + description = "n개의 메시지를 채널에서 삭제해요" + option { + type = OptionType.INTEGER + name = "n" + description = "n개만큼 메시지가 삭제 됩니다" + required = true + } + } override suspend fun execute(ev: SlashCommandInteractionEvent) { val n = ev.getOption("n")!!.asInt diff --git a/px32-bot-module/src/main/kotlin/net/projecttl/p/x32/func/command/Ping.kt b/px32-bot-module/src/main/kotlin/net/projecttl/p/x32/func/command/Ping.kt index cfe18e7..cdbdabf 100644 --- a/px32-bot-module/src/main/kotlin/net/projecttl/p/x32/func/command/Ping.kt +++ b/px32-bot-module/src/main/kotlin/net/projecttl/p/x32/func/command/Ping.kt @@ -6,16 +6,16 @@ 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.interactions.commands.build.CommandData -import net.dv8tion.jda.internal.interactions.CommandDataImpl import net.projecttl.p.x32.api.command.GlobalCommand +import net.projecttl.p.x32.api.command.useCommand import net.projecttl.p.x32.api.util.colour import net.projecttl.p.x32.api.util.footer object Ping : GlobalCommand { - override val data: CommandData = CommandData.fromData(CommandDataImpl( - "ping", - "Discord API 레이턴시 확인 합니다" - ).toData()) + override val data: CommandData = useCommand { + name = "ping" + description = "Discord API 레이턴시 확인 합니다" + } override suspend fun execute(ev: SlashCommandInteractionEvent) { val started = System.currentTimeMillis() diff --git a/wh64@192.168.10.12 b/wh64@192.168.10.12 deleted file mode 100644 index b97c2a9..0000000 Binary files a/wh64@192.168.10.12 and /dev/null differ