From 8e9382cb3ac6f9345fb101168fd9e778eb2c2423 Mon Sep 17 00:00:00 2001 From: dalbodeule <11470513+dalbodeule@users.noreply.github.com> Date: Fri, 2 Aug 2024 14:52:28 +0900 Subject: [PATCH] add TimerType.STREAM_OFF status. - if connected on stream off status, TimerType.STREAM_OFF message sent. - if stream on, default type is TimerType.UPTIME --- .../chzzk_bot/chatbot/chzzk/ChzzkHandler.kt | 22 +++++++++++++++++-- .../chzzk_bot/chatbot/chzzk/MessageHandler.kt | 9 ++------ .../chzzk_bot/common/events/TimerEvents.kt | 4 +++- .../mori/chzzk_bot/common/utils/getUptime.kt | 14 ++++++++++++ .../webserver/routes/WSTimerRoutes.kt | 13 +++++++---- 5 files changed, 48 insertions(+), 14 deletions(-) create mode 100644 common/src/main/kotlin/space/mori/chzzk_bot/common/utils/getUptime.kt diff --git a/chatbot/src/main/kotlin/space/mori/chzzk_bot/chatbot/chzzk/ChzzkHandler.kt b/chatbot/src/main/kotlin/space/mori/chzzk_bot/chatbot/chzzk/ChzzkHandler.kt index 745ab5d..cadb032 100644 --- a/chatbot/src/main/kotlin/space/mori/chzzk_bot/chatbot/chzzk/ChzzkHandler.kt +++ b/chatbot/src/main/kotlin/space/mori/chzzk_bot/chatbot/chzzk/ChzzkHandler.kt @@ -4,12 +4,17 @@ import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.delay import kotlinx.coroutines.launch +import org.koin.java.KoinJavaComponent.inject import org.slf4j.Logger import org.slf4j.LoggerFactory import space.mori.chzzk_bot.chatbot.chzzk.Connector.chzzk import space.mori.chzzk_bot.chatbot.discord.Discord +import space.mori.chzzk_bot.common.events.CoroutinesEventBus +import space.mori.chzzk_bot.common.events.TimerEvent +import space.mori.chzzk_bot.common.events.TimerType import space.mori.chzzk_bot.common.models.User import space.mori.chzzk_bot.common.services.UserService +import space.mori.chzzk_bot.common.utils.getUptime import xyz.r2turntrue.chzzk4j.chat.ChatEventListener import xyz.r2turntrue.chzzk4j.chat.ChatMessage import xyz.r2turntrue.chzzk4j.chat.ChzzkChat @@ -93,6 +98,7 @@ class UserHandler( var streamStartTime: LocalDateTime?, ) { private lateinit var messageHandler: MessageHandler + private val dispatcher: CoroutinesEventBus by inject(CoroutinesEventBus::class.java) var listener: ChzzkChat = chzzk.chat(channel.channelId) .withAutoReconnect(true) @@ -144,16 +150,28 @@ class UserHandler( streamStartTime = LocalDateTime.now() - listener.sendChat("${user.username} 님의 방송이 감지되었습니다.") - CoroutineScope(Dispatchers.Default).launch { + dispatcher.post(TimerEvent( + channel.channelId, + TimerType.UPTIME, + getUptime(streamStartTime!!) + )) delay(5000L) + listener.sendChat("${user.username} 님! 오늘도 열심히 방송하세요!") Discord.sendDiscord(user, status) } } else { logger.info("${user.username} is offline.") streamStartTime = null listener.closeAsync() + + CoroutineScope(Dispatchers.Default).launch { + dispatcher.post(TimerEvent( + channel.channelId, + TimerType.STREAM_OFF, + "" + )) + } } } } \ No newline at end of file diff --git a/chatbot/src/main/kotlin/space/mori/chzzk_bot/chatbot/chzzk/MessageHandler.kt b/chatbot/src/main/kotlin/space/mori/chzzk_bot/chatbot/chzzk/MessageHandler.kt index 18c0a8c..86e3d38 100644 --- a/chatbot/src/main/kotlin/space/mori/chzzk_bot/chatbot/chzzk/MessageHandler.kt +++ b/chatbot/src/main/kotlin/space/mori/chzzk_bot/chatbot/chzzk/MessageHandler.kt @@ -11,6 +11,7 @@ import space.mori.chzzk_bot.common.models.User import space.mori.chzzk_bot.common.services.CommandService import space.mori.chzzk_bot.common.services.CounterService import space.mori.chzzk_bot.common.services.UserService +import space.mori.chzzk_bot.common.utils.getUptime import xyz.r2turntrue.chzzk4j.chat.ChatMessage import xyz.r2turntrue.chzzk4j.chat.ChzzkChat import java.time.LocalDateTime @@ -134,19 +135,13 @@ class MessageHandler( when (parts[1]) { "업타임" -> { logger.debug("${user.token} / 업타임") - val currentTime = LocalDateTime.now() - val streamOnTime = handler.streamStartTime - - val hours = ChronoUnit.HOURS.between(streamOnTime, currentTime) - val minutes = ChronoUnit.MINUTES.between(streamOnTime?.plusHours(hours), currentTime) - val seconds = ChronoUnit.SECONDS.between(streamOnTime?.plusHours(hours)?.plusMinutes(minutes), currentTime) CoroutineScope(Dispatchers.Default).launch { dispatcher.post( TimerEvent( user.token, TimerType.UPTIME, - String.format("%02d:%02d:%02d", hours, minutes, seconds) + getUptime(handler.streamStartTime!!) ) ) } diff --git a/common/src/main/kotlin/space/mori/chzzk_bot/common/events/TimerEvents.kt b/common/src/main/kotlin/space/mori/chzzk_bot/common/events/TimerEvents.kt index b999dc8..64db082 100644 --- a/common/src/main/kotlin/space/mori/chzzk_bot/common/events/TimerEvents.kt +++ b/common/src/main/kotlin/space/mori/chzzk_bot/common/events/TimerEvents.kt @@ -3,7 +3,9 @@ package space.mori.chzzk_bot.common.events enum class TimerType(var value: Int) { UPTIME(0), TIMER(1), - REMOVE(2) + REMOVE(2), + + STREAM_OFF(50) } class TimerEvent( diff --git a/common/src/main/kotlin/space/mori/chzzk_bot/common/utils/getUptime.kt b/common/src/main/kotlin/space/mori/chzzk_bot/common/utils/getUptime.kt new file mode 100644 index 0000000..714ac3a --- /dev/null +++ b/common/src/main/kotlin/space/mori/chzzk_bot/common/utils/getUptime.kt @@ -0,0 +1,14 @@ +package space.mori.chzzk_bot.common.utils + +import java.time.LocalDateTime +import java.time.temporal.ChronoUnit + +fun getUptime(streamOnTime: LocalDateTime): String { + val currentTime = LocalDateTime.now() + + val hours = ChronoUnit.HOURS.between(streamOnTime, currentTime) + val minutes = ChronoUnit.MINUTES.between(streamOnTime?.plusHours(hours), currentTime) + val seconds = ChronoUnit.SECONDS.between(streamOnTime?.plusHours(hours)?.plusMinutes(minutes), currentTime) + + return String.format("%02d:%02d:%02d", hours, minutes, seconds) +} \ No newline at end of file diff --git a/webserver/src/main/kotlin/space/mori/chzzk_bot/webserver/routes/WSTimerRoutes.kt b/webserver/src/main/kotlin/space/mori/chzzk_bot/webserver/routes/WSTimerRoutes.kt index 0127291..1d7c3cb 100644 --- a/webserver/src/main/kotlin/space/mori/chzzk_bot/webserver/routes/WSTimerRoutes.kt +++ b/webserver/src/main/kotlin/space/mori/chzzk_bot/webserver/routes/WSTimerRoutes.kt @@ -6,21 +6,20 @@ import io.ktor.websocket.* import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.channels.ClosedReceiveChannelException -import kotlinx.coroutines.flow.forEach -import kotlinx.coroutines.flow.map import kotlinx.coroutines.launch import kotlinx.serialization.Serializable import org.koin.java.KoinJavaComponent.inject +import org.slf4j.Logger import org.slf4j.LoggerFactory import space.mori.chzzk_bot.common.events.* -import space.mori.chzzk_bot.common.events.TimerType import space.mori.chzzk_bot.common.services.UserService import java.util.concurrent.ConcurrentHashMap -val logger = LoggerFactory.getLogger("WSTimerRoutes") +val logger: Logger = LoggerFactory.getLogger("WSTimerRoutes") fun Routing.wsTimerRoutes() { val sessions = ConcurrentHashMap() + val status = ConcurrentHashMap() webSocket("/timer/{uid}") { val uid = call.parameters["uid"] @@ -35,6 +34,11 @@ fun Routing.wsTimerRoutes() { } sessions[uid] = this + if(status[uid] == TimerType.STREAM_OFF) { + CoroutineScope(Dispatchers.Default).launch { + sendSerialized(TimerResponse(TimerType.STREAM_OFF.value, "")) + } + } try { for (frame in incoming) { @@ -59,6 +63,7 @@ fun Routing.wsTimerRoutes() { dispatcher.subscribe(TimerEvent::class) { logger.debug("TimerEvent: {} / {}", it.uid, it.type) + status[it.uid] = it.type CoroutineScope(Dispatchers.Default).launch { sessions[it.uid]?.sendSerialized(TimerResponse(it.type.value, it.time ?: "")) }