Merge pull request #20 from dalbodeule/develop

add TimerType.STREAM_OFF status.
This commit is contained in:
JinU Choi 2024-08-02 15:08:37 +09:00 committed by GitHub
commit 01778b801a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 48 additions and 14 deletions

View File

@ -4,12 +4,17 @@ import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay import kotlinx.coroutines.delay
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import org.koin.java.KoinJavaComponent.inject
import org.slf4j.Logger import org.slf4j.Logger
import org.slf4j.LoggerFactory import org.slf4j.LoggerFactory
import space.mori.chzzk_bot.chatbot.chzzk.Connector.chzzk import space.mori.chzzk_bot.chatbot.chzzk.Connector.chzzk
import space.mori.chzzk_bot.chatbot.discord.Discord 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.models.User
import space.mori.chzzk_bot.common.services.UserService 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.ChatEventListener
import xyz.r2turntrue.chzzk4j.chat.ChatMessage import xyz.r2turntrue.chzzk4j.chat.ChatMessage
import xyz.r2turntrue.chzzk4j.chat.ChzzkChat import xyz.r2turntrue.chzzk4j.chat.ChzzkChat
@ -93,6 +98,7 @@ class UserHandler(
var streamStartTime: LocalDateTime?, var streamStartTime: LocalDateTime?,
) { ) {
private lateinit var messageHandler: MessageHandler private lateinit var messageHandler: MessageHandler
private val dispatcher: CoroutinesEventBus by inject(CoroutinesEventBus::class.java)
var listener: ChzzkChat = chzzk.chat(channel.channelId) var listener: ChzzkChat = chzzk.chat(channel.channelId)
.withAutoReconnect(true) .withAutoReconnect(true)
@ -144,16 +150,28 @@ class UserHandler(
streamStartTime = LocalDateTime.now() streamStartTime = LocalDateTime.now()
listener.sendChat("${user.username} 님의 방송이 감지되었습니다.")
CoroutineScope(Dispatchers.Default).launch { CoroutineScope(Dispatchers.Default).launch {
dispatcher.post(TimerEvent(
channel.channelId,
TimerType.UPTIME,
getUptime(streamStartTime!!)
))
delay(5000L) delay(5000L)
listener.sendChat("${user.username} 님! 오늘도 열심히 방송하세요!")
Discord.sendDiscord(user, status) Discord.sendDiscord(user, status)
} }
} else { } else {
logger.info("${user.username} is offline.") logger.info("${user.username} is offline.")
streamStartTime = null streamStartTime = null
listener.closeAsync() listener.closeAsync()
CoroutineScope(Dispatchers.Default).launch {
dispatcher.post(TimerEvent(
channel.channelId,
TimerType.STREAM_OFF,
""
))
}
} }
} }
} }

View File

@ -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.CommandService
import space.mori.chzzk_bot.common.services.CounterService import space.mori.chzzk_bot.common.services.CounterService
import space.mori.chzzk_bot.common.services.UserService 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.ChatMessage
import xyz.r2turntrue.chzzk4j.chat.ChzzkChat import xyz.r2turntrue.chzzk4j.chat.ChzzkChat
import java.time.LocalDateTime import java.time.LocalDateTime
@ -134,19 +135,13 @@ class MessageHandler(
when (parts[1]) { when (parts[1]) {
"업타임" -> { "업타임" -> {
logger.debug("${user.token} / 업타임") 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 { CoroutineScope(Dispatchers.Default).launch {
dispatcher.post( dispatcher.post(
TimerEvent( TimerEvent(
user.token, user.token,
TimerType.UPTIME, TimerType.UPTIME,
String.format("%02d:%02d:%02d", hours, minutes, seconds) getUptime(handler.streamStartTime!!)
) )
) )
} }

View File

@ -3,7 +3,9 @@ package space.mori.chzzk_bot.common.events
enum class TimerType(var value: Int) { enum class TimerType(var value: Int) {
UPTIME(0), UPTIME(0),
TIMER(1), TIMER(1),
REMOVE(2) REMOVE(2),
STREAM_OFF(50)
} }
class TimerEvent( class TimerEvent(

View File

@ -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)
}

View File

@ -6,21 +6,20 @@ import io.ktor.websocket.*
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.channels.ClosedReceiveChannelException import kotlinx.coroutines.channels.ClosedReceiveChannelException
import kotlinx.coroutines.flow.forEach
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
import org.koin.java.KoinJavaComponent.inject import org.koin.java.KoinJavaComponent.inject
import org.slf4j.Logger
import org.slf4j.LoggerFactory import org.slf4j.LoggerFactory
import space.mori.chzzk_bot.common.events.* import space.mori.chzzk_bot.common.events.*
import space.mori.chzzk_bot.common.events.TimerType
import space.mori.chzzk_bot.common.services.UserService import space.mori.chzzk_bot.common.services.UserService
import java.util.concurrent.ConcurrentHashMap import java.util.concurrent.ConcurrentHashMap
val logger = LoggerFactory.getLogger("WSTimerRoutes") val logger: Logger = LoggerFactory.getLogger("WSTimerRoutes")
fun Routing.wsTimerRoutes() { fun Routing.wsTimerRoutes() {
val sessions = ConcurrentHashMap<String, WebSocketServerSession>() val sessions = ConcurrentHashMap<String, WebSocketServerSession>()
val status = ConcurrentHashMap<String, TimerType>()
webSocket("/timer/{uid}") { webSocket("/timer/{uid}") {
val uid = call.parameters["uid"] val uid = call.parameters["uid"]
@ -35,6 +34,11 @@ fun Routing.wsTimerRoutes() {
} }
sessions[uid] = this sessions[uid] = this
if(status[uid] == TimerType.STREAM_OFF) {
CoroutineScope(Dispatchers.Default).launch {
sendSerialized(TimerResponse(TimerType.STREAM_OFF.value, ""))
}
}
try { try {
for (frame in incoming) { for (frame in incoming) {
@ -59,6 +63,7 @@ fun Routing.wsTimerRoutes() {
dispatcher.subscribe(TimerEvent::class) { dispatcher.subscribe(TimerEvent::class) {
logger.debug("TimerEvent: {} / {}", it.uid, it.type) logger.debug("TimerEvent: {} / {}", it.uid, it.type)
status[it.uid] = it.type
CoroutineScope(Dispatchers.Default).launch { CoroutineScope(Dispatchers.Default).launch {
sessions[it.uid]?.sendSerialized(TimerResponse(it.type.value, it.time ?: "")) sessions[it.uid]?.sendSerialized(TimerResponse(it.type.value, it.time ?: ""))
} }