mirror of
https://github.com/dalbodeule/chibot-chzzk-bot.git
synced 2025-06-09 07:18:22 +00:00
add counter, counter handlers
This commit is contained in:
parent
4da72f194e
commit
20f6d84040
@ -66,9 +66,9 @@ dependencies {
|
|||||||
// https://mvnrepository.com/artifact/org.jetbrains.exposed/exposed-dao
|
// https://mvnrepository.com/artifact/org.jetbrains.exposed/exposed-dao
|
||||||
implementation("org.jetbrains.exposed:exposed-dao:0.51.1")
|
implementation("org.jetbrains.exposed:exposed-dao:0.51.1")
|
||||||
// https://mvnrepository.com/artifact/org.jetbrains.exposed/exposed-jdbc
|
// https://mvnrepository.com/artifact/org.jetbrains.exposed/exposed-jdbc
|
||||||
runtimeOnly("org.jetbrains.exposed:exposed-jdbc:0.51.1")
|
implementation("org.jetbrains.exposed:exposed-jdbc:0.51.1")
|
||||||
// https://mvnrepository.com/artifact/org.jetbrains.exposed/exposed-kotlin-datetime
|
// https://mvnrepository.com/artifact/org.jetbrains.exposed/exposed-kotlin-datetime
|
||||||
runtimeOnly("org.jetbrains.exposed:exposed-kotlin-datetime:0.51.1")
|
implementation("org.jetbrains.exposed:exposed-java-time:0.51.1")
|
||||||
|
|
||||||
// https://mvnrepository.com/artifact/com.zaxxer/HikariCP
|
// https://mvnrepository.com/artifact/com.zaxxer/HikariCP
|
||||||
implementation("com.zaxxer:HikariCP:5.1.0")
|
implementation("com.zaxxer:HikariCP:5.1.0")
|
||||||
|
@ -7,13 +7,12 @@ import org.jetbrains.exposed.sql.Database
|
|||||||
import org.jetbrains.exposed.sql.SchemaUtils
|
import org.jetbrains.exposed.sql.SchemaUtils
|
||||||
import org.jetbrains.exposed.sql.transactions.transaction
|
import org.jetbrains.exposed.sql.transactions.transaction
|
||||||
import org.slf4j.LoggerFactory
|
import org.slf4j.LoggerFactory
|
||||||
import space.mori.chzzk_bot.models.Commands
|
import space.mori.chzzk_bot.models.*
|
||||||
import space.mori.chzzk_bot.models.Users
|
|
||||||
|
|
||||||
object Connector {
|
object Connector {
|
||||||
private val dotenv = dotenv()
|
private val dotenv = dotenv()
|
||||||
|
|
||||||
val hikariConfig = HikariConfig().apply {
|
private val hikariConfig = HikariConfig().apply {
|
||||||
jdbcUrl = dotenv["DB_URL"]
|
jdbcUrl = dotenv["DB_URL"]
|
||||||
driverClassName = "org.mariadb.jdbc.Driver"
|
driverClassName = "org.mariadb.jdbc.Driver"
|
||||||
username = dotenv["DB_USER"]
|
username = dotenv["DB_USER"]
|
||||||
@ -24,12 +23,10 @@ object Connector {
|
|||||||
|
|
||||||
init {
|
init {
|
||||||
Database.connect(dataSource)
|
Database.connect(dataSource)
|
||||||
val tables = listOf(Users, Commands)
|
val tables = listOf(Users, Commands, Counters, DailyCounters, PersonalCounters)
|
||||||
|
|
||||||
transaction {
|
transaction {
|
||||||
tables.forEach { table ->
|
SchemaUtils.createMissingTablesAndColumns(* tables.toTypedArray())
|
||||||
SchemaUtils.createMissingTablesAndColumns(table)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -9,6 +9,7 @@ import space.mori.chzzk_bot.chzzk.ChzzkHandler
|
|||||||
import space.mori.chzzk_bot.discord.Discord
|
import space.mori.chzzk_bot.discord.Discord
|
||||||
import space.mori.chzzk_bot.chzzk.Connector as ChzzkConnector
|
import space.mori.chzzk_bot.chzzk.Connector as ChzzkConnector
|
||||||
import java.util.concurrent.TimeUnit
|
import java.util.concurrent.TimeUnit
|
||||||
|
import kotlin.system.exitProcess
|
||||||
|
|
||||||
val dotenv = dotenv()
|
val dotenv = dotenv()
|
||||||
val logger: Logger = LoggerFactory.getLogger("main")
|
val logger: Logger = LoggerFactory.getLogger("main")
|
||||||
@ -26,7 +27,7 @@ fun main(args: Array<String>) {
|
|||||||
if(dotenv.get("RUN_AGENT", "false").toBoolean()) {
|
if(dotenv.get("RUN_AGENT", "false").toBoolean()) {
|
||||||
runBlocking {
|
runBlocking {
|
||||||
delay(TimeUnit.MINUTES.toMillis(1))
|
delay(TimeUnit.MINUTES.toMillis(1))
|
||||||
discord.disable()
|
exitProcess(0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,6 +3,7 @@ package space.mori.chzzk_bot.chzzk
|
|||||||
import org.slf4j.Logger
|
import org.slf4j.Logger
|
||||||
import org.slf4j.LoggerFactory
|
import org.slf4j.LoggerFactory
|
||||||
import space.mori.chzzk_bot.chzzk.Connector.chzzk
|
import space.mori.chzzk_bot.chzzk.Connector.chzzk
|
||||||
|
import space.mori.chzzk_bot.models.User
|
||||||
import space.mori.chzzk_bot.services.UserService
|
import space.mori.chzzk_bot.services.UserService
|
||||||
import xyz.r2turntrue.chzzk4j.chat.ChatEventListener
|
import xyz.r2turntrue.chzzk4j.chat.ChatEventListener
|
||||||
import xyz.r2turntrue.chzzk4j.chat.ChatMessage
|
import xyz.r2turntrue.chzzk4j.chat.ChatMessage
|
||||||
@ -14,13 +15,13 @@ object ChzzkHandler {
|
|||||||
private val handlers = mutableListOf<UserHandler>()
|
private val handlers = mutableListOf<UserHandler>()
|
||||||
private val logger = LoggerFactory.getLogger(this::class.java)
|
private val logger = LoggerFactory.getLogger(this::class.java)
|
||||||
|
|
||||||
internal fun addUser(chzzkChannel: ChzzkChannel) {
|
internal fun addUser(chzzkChannel: ChzzkChannel, user: User) {
|
||||||
handlers.add(UserHandler(chzzkChannel, logger))
|
handlers.add(UserHandler(chzzkChannel, logger, user))
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun enable() {
|
internal fun enable() {
|
||||||
UserService.getAllUsers().map {
|
UserService.getAllUsers().map {
|
||||||
chzzk.getChannel(it.token)?.let { token -> addUser(token)}
|
chzzk.getChannel(it.token)?.let { token -> addUser(token, it)}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -31,7 +32,7 @@ object ChzzkHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
internal fun reloadCommand(chzzkChannel: ChzzkChannel) {
|
internal fun reloadCommand(chzzkChannel: ChzzkChannel) {
|
||||||
val handler = handlers.firstOrNull { it.channel == chzzkChannel }
|
val handler = handlers.firstOrNull { it.channel.channelId == chzzkChannel.channelId }
|
||||||
if (handler != null)
|
if (handler != null)
|
||||||
handler.reloadCommand()
|
handler.reloadCommand()
|
||||||
else
|
else
|
||||||
@ -39,7 +40,9 @@ object ChzzkHandler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class UserHandler(val channel: ChzzkChannel, private val logger: Logger) {
|
class UserHandler(
|
||||||
|
val channel: ChzzkChannel, private val logger: Logger, private val user: User
|
||||||
|
) {
|
||||||
private lateinit var messageHandler: MessageHandler
|
private lateinit var messageHandler: MessageHandler
|
||||||
|
|
||||||
private var listener: ChzzkChat = chzzk.chat(channel.channelId)
|
private var listener: ChzzkChat = chzzk.chat(channel.channelId)
|
||||||
@ -56,7 +59,7 @@ class UserHandler(val channel: ChzzkChannel, private val logger: Logger) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun onChat(msg: ChatMessage) {
|
override fun onChat(msg: ChatMessage) {
|
||||||
messageHandler.handle(msg)
|
messageHandler.handle(msg, user)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onConnectionClosed(code: Int, reason: String?, remote: Boolean, tryingToReconnect: Boolean) {
|
override fun onConnectionClosed(code: Int, reason: String?, remote: Boolean, tryingToReconnect: Boolean) {
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
package space.mori.chzzk_bot.chzzk
|
package space.mori.chzzk_bot.chzzk
|
||||||
|
|
||||||
import org.slf4j.Logger
|
import org.slf4j.Logger
|
||||||
|
import space.mori.chzzk_bot.models.User
|
||||||
import space.mori.chzzk_bot.services.CommandService
|
import space.mori.chzzk_bot.services.CommandService
|
||||||
|
import space.mori.chzzk_bot.services.CounterService
|
||||||
import space.mori.chzzk_bot.services.UserService
|
import space.mori.chzzk_bot.services.UserService
|
||||||
import xyz.r2turntrue.chzzk4j.chat.ChatMessage
|
import xyz.r2turntrue.chzzk4j.chat.ChatMessage
|
||||||
import xyz.r2turntrue.chzzk4j.chat.ChzzkChat
|
import xyz.r2turntrue.chzzk4j.chat.ChzzkChat
|
||||||
@ -12,7 +14,12 @@ class MessageHandler(
|
|||||||
private val logger: Logger,
|
private val logger: Logger,
|
||||||
private val listener: ChzzkChat
|
private val listener: ChzzkChat
|
||||||
) {
|
) {
|
||||||
private val commands = mutableMapOf<String, () -> Unit>()
|
private val commands = mutableMapOf<String, (msg: ChatMessage, user: User) -> Unit>()
|
||||||
|
|
||||||
|
private val counterPattern = Regex("<counter:([^>]+)>")
|
||||||
|
private val personalCounterPattern = Regex("<counter_personal:([^>]+)>")
|
||||||
|
private val dailyCounterPattern = Regex("<daily_counter:([^>]+)>")
|
||||||
|
private val namePattern = Regex("<name>")
|
||||||
|
|
||||||
init {
|
init {
|
||||||
reloadCommand()
|
reloadCommand()
|
||||||
@ -24,16 +31,59 @@ class MessageHandler(
|
|||||||
val commands = CommandService.getCommands(user)
|
val commands = CommandService.getCommands(user)
|
||||||
|
|
||||||
commands.map {
|
commands.map {
|
||||||
this.commands.put(it.command.lowercase()) {
|
this.commands.put(it.command.lowercase()) { msg, user ->
|
||||||
logger.debug("${channel.channelName} - ${it.command} - ${it.content}")
|
logger.debug("${channel.channelName} - ${it.command} - ${it.content}/${it.failContent}")
|
||||||
listener.sendChat(it.content)
|
|
||||||
|
val result = replaceCounters(Pair(it.content, it.failContent), user, msg.userId, msg.profile?.nickname ?: "")
|
||||||
|
listener.sendChat(result)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun handle(msg: ChatMessage) {
|
internal fun handle(msg: ChatMessage, user: User) {
|
||||||
val commandKey = msg.content.split(' ')[0]
|
val commandKey = msg.content.split(' ')[0]
|
||||||
|
|
||||||
commands[commandKey.lowercase()]?.let { it() }
|
commands[commandKey.lowercase()]?.let { it(msg, user) }
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun replaceCounters(chat: Pair<String, String>, user: User, userId: String, userName: String): String {
|
||||||
|
var result = chat.first
|
||||||
|
var isFail = false
|
||||||
|
|
||||||
|
result = counterPattern.replace(result) {
|
||||||
|
val name = it.groupValues[1]
|
||||||
|
CounterService.updateCounterValue(name, 1, user).toString()
|
||||||
|
}
|
||||||
|
|
||||||
|
result = personalCounterPattern.replace(result) {
|
||||||
|
val name = it.groupValues[1]
|
||||||
|
CounterService.updatePersonalCounterValue(name, userId, 1, user).toString()
|
||||||
|
}
|
||||||
|
|
||||||
|
result = dailyCounterPattern.replace(result) {
|
||||||
|
val name = it.groupValues[1]
|
||||||
|
val dailyCounter = CounterService.getDailyCounterValue(name, userId, user)
|
||||||
|
|
||||||
|
return@replace if(dailyCounter.second)
|
||||||
|
CounterService.updateDailyCounterValue(name, userId, 1, user).first.toString()
|
||||||
|
else {
|
||||||
|
isFail = true
|
||||||
|
dailyCounter.first.toString()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(isFail) {
|
||||||
|
result = chat.second
|
||||||
|
result = dailyCounterPattern.replace(result) {
|
||||||
|
val name = it.groupValues[1]
|
||||||
|
val dailyCounter = CounterService.getDailyCounterValue(name, userId, user)
|
||||||
|
|
||||||
|
dailyCounter.first.toString()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
result = namePattern.replace(result, userName)
|
||||||
|
|
||||||
|
return result
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -20,10 +20,12 @@ object AddCommand : CommandInterface {
|
|||||||
override val command = Commands.slash(name, "명령어를 추가합니다.")
|
override val command = Commands.slash(name, "명령어를 추가합니다.")
|
||||||
.addOptions(OptionData(OptionType.STRING, "label", "작동할 명령어를 입력하세요.", true))
|
.addOptions(OptionData(OptionType.STRING, "label", "작동할 명령어를 입력하세요.", true))
|
||||||
.addOptions(OptionData(OptionType.STRING, "content", "표시될 텍스트를 입력하세요.", true))
|
.addOptions(OptionData(OptionType.STRING, "content", "표시될 텍스트를 입력하세요.", true))
|
||||||
|
.addOptions(OptionData(OptionType.STRING, "fail_content", "카운터 업데이트 실패시 표시될 텍스트를 입력하세요.", false))
|
||||||
|
|
||||||
override fun run(event: SlashCommandInteractionEvent, bot: JDA) {
|
override fun run(event: SlashCommandInteractionEvent, bot: JDA) {
|
||||||
val label = event.getOption("label")?.asString
|
val label = event.getOption("label")?.asString
|
||||||
val content = event.getOption("content")?.asString
|
val content = event.getOption("content")?.asString
|
||||||
|
val failContent = event.getOption("fail_content")?.asString
|
||||||
|
|
||||||
if(label == null || content == null) {
|
if(label == null || content == null) {
|
||||||
event.hook.sendMessage("명령어와 텍스트는 필수 입력입니다.").queue()
|
event.hook.sendMessage("명령어와 텍스트는 필수 입력입니다.").queue()
|
||||||
@ -35,14 +37,21 @@ object AddCommand : CommandInterface {
|
|||||||
event.hook.sendMessage("치지직 계정을 찾을 수 없습니다.").queue()
|
event.hook.sendMessage("치지직 계정을 찾을 수 없습니다.").queue()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val commands = CommandService.getCommands(user)
|
||||||
|
if (commands.any { it.command == label }) {
|
||||||
|
event.hook.sendMessage("$label 명령어는 이미 있습니다! 업데이트 명령어를 써주세요.").queue()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
val chzzkChannel = Connector.getChannel(user.token)
|
val chzzkChannel = Connector.getChannel(user.token)
|
||||||
|
|
||||||
try {
|
try {
|
||||||
CommandService.saveCommand(user, label, content)
|
CommandService.saveCommand(user, label, content, failContent ?: "")
|
||||||
try {
|
try {
|
||||||
ChzzkHandler.reloadCommand(chzzkChannel!!)
|
ChzzkHandler.reloadCommand(chzzkChannel!!)
|
||||||
} catch (_: Exception) {}
|
} catch (_: Exception) {}
|
||||||
event.hook.sendMessage("등록이 완료되었습니다. $label = $content").queue()
|
event.hook.sendMessage("등록이 완료되었습니다. $label = $content/$failContent").queue()
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
event.hook.sendMessage("에러가 발생했습니다.").queue()
|
event.hook.sendMessage("에러가 발생했습니다.").queue()
|
||||||
logger.debug(e.stackTraceToString())
|
logger.debug(e.stackTraceToString())
|
||||||
|
@ -40,8 +40,8 @@ object Register: CommandInterface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
UserService.saveUser(chzzkChannel.channelName, chzzkChannel.channelId, event.user.idLong)
|
val user = UserService.saveUser(chzzkChannel.channelName, chzzkChannel.channelId, event.user.idLong)
|
||||||
ChzzkHandler.addUser(chzzkChannel)
|
ChzzkHandler.addUser(chzzkChannel, user)
|
||||||
event.hook.sendMessage("등록이 완료되었습니다. `${chzzkChannel.channelId}` - `${chzzkChannel.channelName}`")
|
event.hook.sendMessage("등록이 완료되었습니다. `${chzzkChannel.channelId}` - `${chzzkChannel.channelName}`")
|
||||||
} catch(e: Exception) {
|
} catch(e: Exception) {
|
||||||
event.hook.sendMessage("에러가 발생했습니다.").queue()
|
event.hook.sendMessage("에러가 발생했습니다.").queue()
|
||||||
|
@ -21,10 +21,12 @@ object UpdateCommand : CommandInterface {
|
|||||||
override val command = Commands.slash(name, "명령어를 수정합니다.")
|
override val command = Commands.slash(name, "명령어를 수정합니다.")
|
||||||
.addOptions(OptionData(OptionType.STRING, "label", "수정할 명령어를 입력하세요.", true))
|
.addOptions(OptionData(OptionType.STRING, "label", "수정할 명령어를 입력하세요.", true))
|
||||||
.addOptions(OptionData(OptionType.STRING, "content", "표시될 텍스트를 입력하세요.", true))
|
.addOptions(OptionData(OptionType.STRING, "content", "표시될 텍스트를 입력하세요.", true))
|
||||||
|
.addOptions(OptionData(OptionType.STRING, "fail_content", "카운터 업데이트 실패시 표시될 텍스트를 입력하세요.", false))
|
||||||
|
|
||||||
override fun run(event: SlashCommandInteractionEvent, bot: JDA) {
|
override fun run(event: SlashCommandInteractionEvent, bot: JDA) {
|
||||||
val label = event.getOption("label")?.asString
|
val label = event.getOption("label")?.asString
|
||||||
val content = event.getOption("content")?.asString
|
val content = event.getOption("content")?.asString
|
||||||
|
val failContent = event.getOption("fail_content")?.asString
|
||||||
|
|
||||||
if(label == null || content == null) {
|
if(label == null || content == null) {
|
||||||
event.hook.sendMessage("명령어와 텍스트는 필수 입력입니다.").queue()
|
event.hook.sendMessage("명령어와 텍스트는 필수 입력입니다.").queue()
|
||||||
@ -39,10 +41,8 @@ object UpdateCommand : CommandInterface {
|
|||||||
val chzzkChannel = Connector.getChannel(user.token)
|
val chzzkChannel = Connector.getChannel(user.token)
|
||||||
|
|
||||||
try {
|
try {
|
||||||
CommandService.updateCommand(user, label, content)
|
CommandService.updateCommand(user, label, content, failContent ?: "")
|
||||||
try {
|
chzzkChannel?.let { ChzzkHandler.reloadCommand(it) }
|
||||||
ChzzkHandler.reloadCommand(chzzkChannel!!)
|
|
||||||
} catch (_: Exception) {}
|
|
||||||
event.hook.sendMessage("등록이 완료되었습니다. $label = $content").queue()
|
event.hook.sendMessage("등록이 완료되었습니다. $label = $content").queue()
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
event.hook.sendMessage("에러가 발생했습니다.").queue()
|
event.hook.sendMessage("에러가 발생했습니다.").queue()
|
||||||
|
@ -10,6 +10,7 @@ object Commands: IntIdTable("commands") {
|
|||||||
val user = reference("user", Users, onDelete = ReferenceOption.CASCADE)
|
val user = reference("user", Users, onDelete = ReferenceOption.CASCADE)
|
||||||
val command = varchar("command", 255)
|
val command = varchar("command", 255)
|
||||||
val content = text("content")
|
val content = text("content")
|
||||||
|
val failContent = text("fail_content")
|
||||||
}
|
}
|
||||||
|
|
||||||
class Command(id: EntityID<Int>) : IntEntity(id) {
|
class Command(id: EntityID<Int>) : IntEntity(id) {
|
||||||
@ -18,4 +19,5 @@ class Command(id: EntityID<Int>) : IntEntity(id) {
|
|||||||
var user by User referencedOn Commands.user
|
var user by User referencedOn Commands.user
|
||||||
var command by Commands.command
|
var command by Commands.command
|
||||||
var content by Commands.content
|
var content by Commands.content
|
||||||
|
var failContent by Commands.failContent
|
||||||
}
|
}
|
20
src/main/kotlin/space/mori/chzzk_bot/models/Counter.kt
Normal file
20
src/main/kotlin/space/mori/chzzk_bot/models/Counter.kt
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
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 Counters: IntIdTable("counters") {
|
||||||
|
val name = varchar("name", 255)
|
||||||
|
val value = integer("value")
|
||||||
|
val user = reference("streamer", Users)
|
||||||
|
}
|
||||||
|
|
||||||
|
class Counter(id: EntityID<Int>) : IntEntity(id) {
|
||||||
|
companion object : IntEntityClass<Counter>(Counters)
|
||||||
|
|
||||||
|
var name by Counters.name
|
||||||
|
var value by Counters.value
|
||||||
|
var user by User referencedOn Counters.user
|
||||||
|
}
|
25
src/main/kotlin/space/mori/chzzk_bot/models/DailyCounters.kt
Normal file
25
src/main/kotlin/space/mori/chzzk_bot/models/DailyCounters.kt
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
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
|
||||||
|
import org.jetbrains.exposed.sql.javatime.date
|
||||||
|
|
||||||
|
object DailyCounters: IntIdTable("daily_counters") {
|
||||||
|
val name = varchar("name", 255)
|
||||||
|
val userId = varchar("user_id", 64)
|
||||||
|
val value = integer("value")
|
||||||
|
val updatedAt = date("updated_at")
|
||||||
|
val user = reference("streamer", Users)
|
||||||
|
}
|
||||||
|
|
||||||
|
class DailyCounter(id: EntityID<Int>) : IntEntity(id) {
|
||||||
|
companion object : IntEntityClass<DailyCounter>(DailyCounters)
|
||||||
|
|
||||||
|
var name by DailyCounters.name
|
||||||
|
var userId by DailyCounters.userId
|
||||||
|
var value by DailyCounters.value
|
||||||
|
var updatedAt by DailyCounters.updatedAt
|
||||||
|
var user by User referencedOn DailyCounters.user
|
||||||
|
}
|
@ -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 PersonalCounters: IntIdTable("personal_counters") {
|
||||||
|
val name = varchar("name", 255)
|
||||||
|
val userId = varchar("user_id", 64)
|
||||||
|
val value = integer("value")
|
||||||
|
val user = reference("streamer", Users)
|
||||||
|
}
|
||||||
|
|
||||||
|
class PersonalCounter(id: EntityID<Int>) : IntEntity(id) {
|
||||||
|
companion object : IntEntityClass<PersonalCounter>(PersonalCounters)
|
||||||
|
|
||||||
|
var name by PersonalCounters.name
|
||||||
|
var userId by PersonalCounters.userId
|
||||||
|
var value by PersonalCounters.value
|
||||||
|
var user by User referencedOn PersonalCounters.user
|
||||||
|
}
|
@ -9,12 +9,13 @@ import space.mori.chzzk_bot.models.Commands
|
|||||||
import space.mori.chzzk_bot.models.User
|
import space.mori.chzzk_bot.models.User
|
||||||
|
|
||||||
object CommandService {
|
object CommandService {
|
||||||
fun saveCommand(user: User, command: String, content: String): Command {
|
fun saveCommand(user: User, command: String, content: String, failContent: String): Command {
|
||||||
return transaction {
|
return transaction {
|
||||||
return@transaction Command.new {
|
return@transaction Command.new {
|
||||||
this.user = user
|
this.user = user
|
||||||
this.command = command
|
this.command = command
|
||||||
this.content = content
|
this.content = content
|
||||||
|
this.failContent = failContent
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -26,31 +27,32 @@ object CommandService {
|
|||||||
commandRow ?: throw RuntimeException("Command not found! $command")
|
commandRow ?: throw RuntimeException("Command not found! $command")
|
||||||
commandRow.delete()
|
commandRow.delete()
|
||||||
|
|
||||||
return@transaction commandRow
|
commandRow
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun updateCommand(user: User, command: String, content: String): Command {
|
fun updateCommand(user: User, command: String, content: String, failContent: String): Command {
|
||||||
return transaction {
|
return transaction {
|
||||||
val updated = Commands.update({Commands.user eq user.id and(Commands.command eq command)}) {
|
val updated = Commands.update({Commands.user eq user.id and(Commands.command eq command)}) {
|
||||||
it[Commands.content] = content
|
it[Commands.content] = content
|
||||||
|
it[Commands.failContent] = failContent
|
||||||
}
|
}
|
||||||
|
|
||||||
if(updated == 0) throw RuntimeException("Command not found! $command")
|
if(updated == 0) throw RuntimeException("Command not found! $command")
|
||||||
|
|
||||||
return@transaction Command.find(Commands.user eq user.id and(Commands.command eq command)).first()
|
Command.find(Commands.user eq user.id and(Commands.command eq command)).first()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getCommand(id: Int): Command? {
|
fun getCommand(id: Int): Command? {
|
||||||
return transaction {
|
return transaction {
|
||||||
return@transaction Command.findById(id)
|
Command.findById(id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getCommands(user: User): List<Command> {
|
fun getCommands(user: User): List<Command> {
|
||||||
return transaction {
|
return transaction {
|
||||||
return@transaction Command.find(Commands.user eq user.id)
|
Command.find(Commands.user eq user.id)
|
||||||
.toList()
|
.toList()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
105
src/main/kotlin/space/mori/chzzk_bot/services/CounterService.kt
Normal file
105
src/main/kotlin/space/mori/chzzk_bot/services/CounterService.kt
Normal file
@ -0,0 +1,105 @@
|
|||||||
|
package space.mori.chzzk_bot.services
|
||||||
|
|
||||||
|
import org.jetbrains.exposed.sql.and
|
||||||
|
import org.jetbrains.exposed.sql.transactions.transaction
|
||||||
|
import space.mori.chzzk_bot.models.*
|
||||||
|
import java.time.LocalDate
|
||||||
|
|
||||||
|
object CounterService {
|
||||||
|
fun getCounterValue(name: String, user: User): Int {
|
||||||
|
return transaction {
|
||||||
|
Counter.find {
|
||||||
|
(Counters.name eq name) and (Counters.user eq user.id)
|
||||||
|
}.singleOrNull()?.value ?: 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun updateCounterValue(name: String, increment: Int, user: User): Int {
|
||||||
|
return transaction {
|
||||||
|
val counter = Counter.find {
|
||||||
|
(Counters.name eq name) and (Counters.user eq user.id) }.singleOrNull()
|
||||||
|
return@transaction if (counter != null) {
|
||||||
|
counter.value += increment
|
||||||
|
counter.value
|
||||||
|
} else {
|
||||||
|
val newCounter = Counter.new {
|
||||||
|
this.name = name
|
||||||
|
this.value = increment
|
||||||
|
this.user = user
|
||||||
|
}
|
||||||
|
newCounter.value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getPersonalCounterValue(name: String, userId: String, user: User): Int {
|
||||||
|
return transaction {
|
||||||
|
PersonalCounter.find {
|
||||||
|
(PersonalCounters.name eq name) and (PersonalCounters.userId eq userId) and (PersonalCounters.user eq user.id)
|
||||||
|
}.singleOrNull()?.value ?: 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun updatePersonalCounterValue(name: String, userId: String, increment: Int, user: User): Int {
|
||||||
|
return transaction {
|
||||||
|
val counter = PersonalCounter.find {
|
||||||
|
(PersonalCounters.name eq name) and (PersonalCounters.userId eq userId) and (PersonalCounters.user eq user.id)
|
||||||
|
}.singleOrNull()
|
||||||
|
|
||||||
|
return@transaction if (counter != null) {
|
||||||
|
counter.value += increment
|
||||||
|
counter.value
|
||||||
|
} else {
|
||||||
|
val newCounter = PersonalCounter.new {
|
||||||
|
this.name = name
|
||||||
|
this.value = increment
|
||||||
|
this.userId = userId
|
||||||
|
this.user = user
|
||||||
|
}
|
||||||
|
newCounter.value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getDailyCounterValue(name: String, userId: String, user: User): Pair<Int, Boolean> {
|
||||||
|
val today = LocalDate.now()
|
||||||
|
|
||||||
|
return transaction {
|
||||||
|
val counter = DailyCounter.find {
|
||||||
|
(DailyCounters.name eq name) and (DailyCounters.userId eq userId) and (DailyCounters.user eq user.id)
|
||||||
|
}.singleOrNull()
|
||||||
|
|
||||||
|
Pair(counter?.value ?: 0, counter?.updatedAt != today)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun updateDailyCounterValue(name: String, userId: String, increment: Int, user: User): Pair<Int, Boolean> {
|
||||||
|
val today = LocalDate.now()
|
||||||
|
|
||||||
|
return transaction {
|
||||||
|
val counter = DailyCounter.find {
|
||||||
|
(DailyCounters.name eq name) and (DailyCounters.userId eq userId) and (DailyCounters.user eq user.id)
|
||||||
|
}.singleOrNull()
|
||||||
|
|
||||||
|
println("$counter")
|
||||||
|
|
||||||
|
if(counter == null) {
|
||||||
|
val newCounter = DailyCounter.new {
|
||||||
|
this.name = name
|
||||||
|
this.value = increment
|
||||||
|
this.userId = userId
|
||||||
|
this.updatedAt = today
|
||||||
|
this.user = user
|
||||||
|
}
|
||||||
|
return@transaction Pair(newCounter.value, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
return@transaction if(counter.updatedAt == today)
|
||||||
|
Pair(counter.value, false)
|
||||||
|
else {
|
||||||
|
counter.value += increment
|
||||||
|
Pair(counter.value, true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -8,7 +8,7 @@ import space.mori.chzzk_bot.models.Users
|
|||||||
object UserService {
|
object UserService {
|
||||||
fun saveUser(username: String, token: String, discordID: Long): User {
|
fun saveUser(username: String, token: String, discordID: Long): User {
|
||||||
return transaction {
|
return transaction {
|
||||||
return@transaction User.new {
|
User.new {
|
||||||
this.username = username
|
this.username = username
|
||||||
this.token = token
|
this.token = token
|
||||||
this.discord = discordID
|
this.discord = discordID
|
||||||
@ -18,7 +18,7 @@ object UserService {
|
|||||||
|
|
||||||
fun getUser(id: Int): User? {
|
fun getUser(id: Int): User? {
|
||||||
return transaction {
|
return transaction {
|
||||||
return@transaction User.findById(id)
|
User.findById(id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -26,7 +26,7 @@ object UserService {
|
|||||||
return transaction {
|
return transaction {
|
||||||
val users = User.find(Users.discord eq discordID)
|
val users = User.find(Users.discord eq discordID)
|
||||||
|
|
||||||
return@transaction users.firstOrNull()
|
users.firstOrNull()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -34,13 +34,13 @@ object UserService {
|
|||||||
return transaction {
|
return transaction {
|
||||||
val users = User.find(Users.token eq chzzkID)
|
val users = User.find(Users.token eq chzzkID)
|
||||||
|
|
||||||
return@transaction users.firstOrNull()
|
users.firstOrNull()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getAllUsers(): List<User> {
|
fun getAllUsers(): List<User> {
|
||||||
return transaction {
|
return transaction {
|
||||||
return@transaction User.all().toList()
|
User.all().toList()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -380,6 +380,10 @@
|
|||||||
"name":"kotlinx.coroutines.CancellableContinuationImpl",
|
"name":"kotlinx.coroutines.CancellableContinuationImpl",
|
||||||
"fields":[{"name":"_decisionAndIndex$volatile"}, {"name":"_parentHandle$volatile"}, {"name":"_state$volatile"}]
|
"fields":[{"name":"_decisionAndIndex$volatile"}, {"name":"_parentHandle$volatile"}, {"name":"_state$volatile"}]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name":"kotlinx.coroutines.CompletedExceptionally",
|
||||||
|
"fields":[{"name":"_handled$volatile"}]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name":"kotlinx.coroutines.EventLoopImplBase",
|
"name":"kotlinx.coroutines.EventLoopImplBase",
|
||||||
"fields":[{"name":"_delayed$volatile"}, {"name":"_isCompleted$volatile"}, {"name":"_queue$volatile"}]
|
"fields":[{"name":"_delayed$volatile"}, {"name":"_isCompleted$volatile"}, {"name":"_queue$volatile"}]
|
||||||
@ -388,6 +392,10 @@
|
|||||||
"name":"kotlinx.coroutines.JobSupport",
|
"name":"kotlinx.coroutines.JobSupport",
|
||||||
"fields":[{"name":"_parentHandle$volatile"}, {"name":"_state$volatile"}]
|
"fields":[{"name":"_parentHandle$volatile"}, {"name":"_state$volatile"}]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name":"kotlinx.coroutines.JobSupport$Finishing",
|
||||||
|
"fields":[{"name":"_exceptionsHolder$volatile"}, {"name":"_isCompleting$volatile"}, {"name":"_rootCause$volatile"}]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name":"kotlinx.coroutines.internal.DispatchedContinuation",
|
"name":"kotlinx.coroutines.internal.DispatchedContinuation",
|
||||||
"fields":[{"name":"_reusableCancellableContinuation$volatile"}]
|
"fields":[{"name":"_reusableCancellableContinuation$volatile"}]
|
||||||
|
Loading…
x
Reference in New Issue
Block a user