diff --git a/.idea/dataSources.xml b/.idea/dataSources.xml index 651da45..34f9355 100644 --- a/.idea/dataSources.xml +++ b/.idea/dataSources.xml @@ -1,7 +1,7 @@ - + mariadb true org.mariadb.jdbc.Driver diff --git a/build.gradle.kts b/build.gradle.kts index 98ce8af..7f7685f 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -77,4 +77,8 @@ tasks.withType { }) duplicatesStrategy = DuplicatesStrategy.EXCLUDE +} + +tasks.named("run") { + systemProperty("logback.configurationFile", "logback-debug.xml") } \ No newline at end of file diff --git a/src/main/kotlin/space/mori/chzzk_bot/Connector.kt b/src/main/kotlin/space/mori/chzzk_bot/Connector.kt index 4c035f9..bd763ef 100644 --- a/src/main/kotlin/space/mori/chzzk_bot/Connector.kt +++ b/src/main/kotlin/space/mori/chzzk_bot/Connector.kt @@ -19,7 +19,7 @@ object Connector { init { Database.connect(dataSource) - val tables = listOf(Users, Commands, Counters, DailyCounters, PersonalCounters) + val tables = listOf(Users, Commands, Counters, DailyCounters, PersonalCounters, Managers) transaction { SchemaUtils.createMissingTablesAndColumns(* tables.toTypedArray()) diff --git a/src/main/kotlin/space/mori/chzzk_bot/discord/Discord.kt b/src/main/kotlin/space/mori/chzzk_bot/discord/Discord.kt index ab4416e..4667f05 100644 --- a/src/main/kotlin/space/mori/chzzk_bot/discord/Discord.kt +++ b/src/main/kotlin/space/mori/chzzk_bot/discord/Discord.kt @@ -4,11 +4,13 @@ import net.dv8tion.jda.api.JDA import net.dv8tion.jda.api.JDABuilder import net.dv8tion.jda.api.entities.Activity import net.dv8tion.jda.api.entities.Guild +import net.dv8tion.jda.api.events.guild.member.GuildMemberRemoveEvent import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent import net.dv8tion.jda.api.hooks.ListenerAdapter import space.mori.chzzk_bot.dotenv import org.slf4j.LoggerFactory import space.mori.chzzk_bot.discord.commands.* +import space.mori.chzzk_bot.services.ManagerService class Discord: ListenerAdapter() { private lateinit var bot: JDA @@ -22,6 +24,9 @@ class Discord: ListenerAdapter() { RegisterCommand, RemoveCommand, UpdateCommand, + AddManagerCommand, + ListManagerCommand, + RemoveManagerCommand, ) override fun onSlashCommandInteraction(event: SlashCommandInteractionEvent) { @@ -31,6 +36,10 @@ class Discord: ListenerAdapter() { handler?.run(event, bot) } + override fun onGuildMemberRemove(event: GuildMemberRemoveEvent) { + event.member?.let { ManagerService.deleteManager(event.guild.idLong, it.idLong) } + } + internal fun enable() { val thread = Thread { try { diff --git a/src/main/kotlin/space/mori/chzzk_bot/discord/commands/AddManagerCommand.kt b/src/main/kotlin/space/mori/chzzk_bot/discord/commands/AddManagerCommand.kt new file mode 100644 index 0000000..e2cbdb3 --- /dev/null +++ b/src/main/kotlin/space/mori/chzzk_bot/discord/commands/AddManagerCommand.kt @@ -0,0 +1,45 @@ +package space.mori.chzzk_bot.discord.commands + +import net.dv8tion.jda.api.JDA +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.Commands +import net.dv8tion.jda.api.interactions.commands.build.OptionData +import org.slf4j.LoggerFactory +import space.mori.chzzk_bot.discord.CommandInterface +import space.mori.chzzk_bot.services.ManagerService +import space.mori.chzzk_bot.services.UserService + +object AddManagerCommand : CommandInterface { + private val logger = LoggerFactory.getLogger(this::class.java) + override val name: String = "addmanager" + override val command = Commands.slash(name, "매니저를 추가합니다.") + .addOptions(OptionData(OptionType.USER, "user", "추가할 유저를 선택하세요.", true)) + + override fun run(event: SlashCommandInteractionEvent, bot: JDA) { + val manager = event.getOption("user")?.asUser + + if(manager == null) { + event.hook.sendMessage("유저는 필수사항입니다.").queue() + return + } + if(manager.idLong == event.user.idLong) { + event.hook.sendMessage("자신은 매니저로 설정할 수 없습니다.").queue() + return + } + + val user = UserService.getUser(event.user.idLong) + if(user == null) { + event.hook.sendMessage("치지직 계정을 찾을 수 없습니다.").queue() + return + } + + try { + ManagerService.saveManager(user, manager.idLong, manager.effectiveName) + event.hook.sendMessage("등록이 완료되었습니다. ${manager.effectiveName}").queue() + } catch (e: Exception) { + event.hook.sendMessage("에러가 발생했습니다.").queue() + logger.debug(e.stackTraceToString()) + } + } +} \ No newline at end of file diff --git a/src/main/kotlin/space/mori/chzzk_bot/discord/commands/ListManagerCommand.kt b/src/main/kotlin/space/mori/chzzk_bot/discord/commands/ListManagerCommand.kt new file mode 100644 index 0000000..509bd6b --- /dev/null +++ b/src/main/kotlin/space/mori/chzzk_bot/discord/commands/ListManagerCommand.kt @@ -0,0 +1,44 @@ +package space.mori.chzzk_bot.discord.commands + +import net.dv8tion.jda.api.EmbedBuilder +import net.dv8tion.jda.api.JDA +import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent +import net.dv8tion.jda.api.interactions.commands.build.Commands +import org.slf4j.LoggerFactory +import space.mori.chzzk_bot.discord.CommandInterface +import space.mori.chzzk_bot.services.ManagerService +import space.mori.chzzk_bot.services.UserService + +object ListManagerCommand : CommandInterface { + private val logger = LoggerFactory.getLogger(this::class.java) + override val name: String = "listmanager" + override val command = Commands.slash(name, "매니저 목록을 확인합니다.") + + override fun run(event: SlashCommandInteractionEvent, bot: JDA) { + try { + val managers = event.guild?.idLong?.let { ManagerService.getAllUsers(it) } + + if(managers == null) { + event.channel.sendMessage("여기에서는 사용할 수 없습니다.") + return + } + + val user = UserService.getUserWithGuildId(event.guild!!.idLong) + + val embed = EmbedBuilder() + embed.setTitle("${user!!.username} 매니저 목록") + embed.setDescription("매니저 목록입니다.") + + var idx = 1 + + managers.forEach { + embed.addField("${idx++}", it.lastUserName ?: it.managerId.toString(), true) + } + + event.channel.sendMessageEmbeds(embed.build()).queue() + } catch (e: Exception) { + event.hook.sendMessage("에러가 발생했습니다.").queue() + logger.debug(e.stackTraceToString()) + } + } +} \ No newline at end of file diff --git a/src/main/kotlin/space/mori/chzzk_bot/discord/commands/RemoveManagerCommand.kt b/src/main/kotlin/space/mori/chzzk_bot/discord/commands/RemoveManagerCommand.kt new file mode 100644 index 0000000..143e9ca --- /dev/null +++ b/src/main/kotlin/space/mori/chzzk_bot/discord/commands/RemoveManagerCommand.kt @@ -0,0 +1,49 @@ +package space.mori.chzzk_bot.discord.commands + +import net.dv8tion.jda.api.JDA +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.Commands +import net.dv8tion.jda.api.interactions.commands.build.OptionData +import org.slf4j.LoggerFactory +import space.mori.chzzk_bot.discord.CommandInterface +import space.mori.chzzk_bot.services.ManagerService +import space.mori.chzzk_bot.services.UserService + +object RemoveManagerCommand : CommandInterface { + private val logger = LoggerFactory.getLogger(this::class.java) + override val name: String = "removemanager" + override val command = Commands.slash(name, "매니저를 삭제합니다.") + .addOptions(OptionData(OptionType.USER, "user", "삭제할 유저를 선택하세요.", true)) + + override fun run(event: SlashCommandInteractionEvent, bot: JDA) { + val manager = event.getOption("user")?.asUser + + if(manager == null) { + event.hook.sendMessage("유저는 필수사항입니다.").queue() + return + } + if(manager.idLong == event.user.idLong) { + event.hook.sendMessage("자신은 매니저로 설정할 수 없습니다.").queue() + return + } + + val user = UserService.getUser(event.user.idLong) + if(user == null) { + event.hook.sendMessage("치지직 계정을 찾을 수 없습니다.").queue() + return + } + + if(ManagerService.getUser(user.liveAlertGuild ?: 0L, manager.idLong) == null) { + event.hook.sendMessage("${manager.name}은 매니저가 아닙니다.") + } + + try { + ManagerService.deleteManager(user, manager.idLong) + event.hook.sendMessage("삭제가 완료되었습니다. ${manager.effectiveName}").queue() + } catch (e: Exception) { + event.hook.sendMessage("에러가 발생했습니다.").queue() + logger.debug(e.stackTraceToString()) + } + } +} \ No newline at end of file diff --git a/src/main/kotlin/space/mori/chzzk_bot/models/Manager.kt b/src/main/kotlin/space/mori/chzzk_bot/models/Manager.kt new file mode 100644 index 0000000..238a1f6 --- /dev/null +++ b/src/main/kotlin/space/mori/chzzk_bot/models/Manager.kt @@ -0,0 +1,22 @@ +package space.mori.chzzk_bot.models + +import org.jetbrains.exposed.dao.IntEntity +import org.jetbrains.exposed.dao.IntEntityClass +import org.jetbrains.exposed.dao.id.EntityID +import org.jetbrains.exposed.dao.id.IntIdTable + +object Managers: IntIdTable("manager") { + val user = reference("user", Users) + val managerId = long("manager_id") + val discordGuildId = long("discord_guild_id") + var lastUserName = varchar("last_user_name", 255).nullable() +} + +class Manager(id: EntityID) : IntEntity(id) { + companion object : IntEntityClass(Managers) + + var user by User referencedOn Managers.user + var managerId by Managers.managerId + var discordGuildId by Managers.discordGuildId + var lastUserName by Managers.lastUserName +} \ No newline at end of file diff --git a/src/main/kotlin/space/mori/chzzk_bot/services/ManagerService.kt b/src/main/kotlin/space/mori/chzzk_bot/services/ManagerService.kt new file mode 100644 index 0000000..b049c9f --- /dev/null +++ b/src/main/kotlin/space/mori/chzzk_bot/services/ManagerService.kt @@ -0,0 +1,70 @@ +package space.mori.chzzk_bot.services + +import org.jetbrains.exposed.sql.SqlExpressionBuilder.eq +import org.jetbrains.exposed.sql.and +import org.jetbrains.exposed.sql.transactions.transaction +import space.mori.chzzk_bot.models.Manager +import space.mori.chzzk_bot.models.Managers +import space.mori.chzzk_bot.models.User + +object ManagerService { + fun saveManager(user: User, discordId: Long, name: String): Manager { + if (user.liveAlertGuild == null) + throw RuntimeException("${user.username} has no liveAlertGuild") + + return transaction { + Manager.new { + this.user = user + this.discordGuildId = user.liveAlertGuild!! + this.managerId = discordId + this.lastUserName = name + } + } + } + + fun updateManager(user: User, discordId: Long, name: String): Manager { + if (user.liveAlertGuild == null) + throw RuntimeException("${user.username} has no liveAlertGuild") + + val manager = getUser(user.liveAlertGuild!!, discordId) + + if (manager == null) + throw RuntimeException("$name isn't manager.") + manager.lastUserName = name + + return manager + } + + fun getUser(guildId: Long, discordId: Long): Manager? { + return transaction { + val manager = Manager.find( + (Managers.discordGuildId eq guildId) and (Managers.managerId eq discordId) + ) + + manager.firstOrNull() + } + } + + fun getAllUsers(guildId: Long): List { + return transaction { + Manager.find(Managers.discordGuildId eq guildId).toList() + } + } + + fun deleteManager(user: User, discordId: Long): Manager { + if (user.liveAlertGuild == null) + throw RuntimeException("${user.username} has no liveAlertGuild") + return deleteManager(user.liveAlertGuild!!, discordId) + } + + fun deleteManager(guildId: Long, discordId: Long): Manager { + return transaction { + val managerRow = Manager.find((Managers.discordGuildId eq guildId) and (Managers.managerId eq discordId)).firstOrNull() + + managerRow ?: throw RuntimeException("Manager not found! $discordId") + managerRow.delete() + + managerRow + } + } +} \ No newline at end of file diff --git a/src/main/kotlin/space/mori/chzzk_bot/services/UserService.kt b/src/main/kotlin/space/mori/chzzk_bot/services/UserService.kt index a9a5bb8..ee83679 100644 --- a/src/main/kotlin/space/mori/chzzk_bot/services/UserService.kt +++ b/src/main/kotlin/space/mori/chzzk_bot/services/UserService.kt @@ -39,6 +39,14 @@ object UserService { } } + fun getUserWithGuildId(discordGuildId: Long): User? { + return transaction { + val users = User.find(Users.liveAlertGuild eq discordGuildId) + + users.firstOrNull() + } + } + fun getAllUsers(): List { return transaction { User.all().toList() diff --git a/src/main/resources/logback-debug.xml b/src/main/resources/logback-debug.xml new file mode 100644 index 0000000..f049712 --- /dev/null +++ b/src/main/resources/logback-debug.xml @@ -0,0 +1,35 @@ + + + + + + DEBUG + + + %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file