add Session flows

- songlist page to changed.
This commit is contained in:
dalbodeule 2024-08-08 14:53:37 +09:00
parent a828e23767
commit 8dde66c069
No known key found for this signature in database
GPG Key ID: EFA860D069C9FA65
6 changed files with 51 additions and 75 deletions

View File

@ -285,12 +285,10 @@ class MessageHandler(
val session = "${UUID.randomUUID()}${UUID.randomUUID()}".replace("-", "") val session = "${UUID.randomUUID()}${UUID.randomUUID()}".replace("-", "")
SongConfigService.updateSession(user, session)
bot.retrieveUserById(user.discord).queue { discordUser -> bot.retrieveUserById(user.discord).queue { discordUser ->
discordUser?.openPrivateChannel()?.queue { channel -> discordUser?.openPrivateChannel()?.queue { channel ->
channel.sendMessage("여기로 접속해주세요! ||https://nabot.mori.space/songlist/${session}||.\n주소가 노출될 경우 방송을 다시 켜셔야 합니다!") channel.sendMessage("여기로 접속해주세요! ||https://nabot.mori.space/songlist||.")
.queue() .queue()
} }
} }

View File

@ -10,6 +10,7 @@ object Users: IntIdTable("users") {
val username = varchar("username", 255) val username = varchar("username", 255)
val token = varchar("token", 64) val token = varchar("token", 64)
val discord = long("discord") val discord = long("discord")
val naverId = long("naver_id")
val liveAlertGuild = long("live_alert_guild").nullable() val liveAlertGuild = long("live_alert_guild").nullable()
val liveAlertChannel = long("live_alert_channel").nullable() val liveAlertChannel = long("live_alert_channel").nullable()
val liveAlertMessage = text("live_alert_message").nullable() val liveAlertMessage = text("live_alert_message").nullable()
@ -21,6 +22,7 @@ class User(id: EntityID<Int>) : IntEntity(id) {
var username by Users.username var username by Users.username
var token by Users.token var token by Users.token
var discord by Users.discord var discord by Users.discord
var naverId by Users.naverId
var liveAlertGuild by Users.liveAlertGuild var liveAlertGuild by Users.liveAlertGuild
var liveAlertChannel by Users.liveAlertChannel var liveAlertChannel by Users.liveAlertChannel
var liveAlertMessage by Users.liveAlertMessage var liveAlertMessage by Users.liveAlertMessage

View File

@ -26,19 +26,6 @@ object SongConfigService {
} }
fun getConfig(token: String): SongConfig? {
return transaction {
SongConfig.find(SongConfigs.token eq token).firstOrNull()
}
}
fun getUserByToken(token: String): User? {
return transaction {
val songConfig = SongConfig.find(SongConfigs.token eq token).firstOrNull()
if(songConfig == null) null
else UserService.getUser(songConfig.user.discord)
}
}
fun updatePersonalLimit(user: User, limit: Int): SongConfig { fun updatePersonalLimit(user: User, limit: Int): SongConfig {
return transaction { return transaction {
var songConfig = SongConfig.find(SongConfigs.user eq user.id).firstOrNull() var songConfig = SongConfig.find(SongConfigs.user eq user.id).firstOrNull()
@ -60,18 +47,6 @@ object SongConfigService {
} }
} }
fun updateSession(user: User, token: String?): SongConfig {
return transaction {
var songConfig = SongConfig.find(SongConfigs.user eq user.id).firstOrNull()
if (songConfig == null) {
songConfig = initConfig(user)
}
songConfig.token = token
songConfig
}
}
fun updateStreamerOnly(user: User, config: Boolean): SongConfig { fun updateStreamerOnly(user: User, config: Boolean): SongConfig {
return transaction { return transaction {
var songConfig = SongConfig.find(SongConfigs.user eq user.id).firstOrNull() var songConfig = SongConfig.find(SongConfigs.user eq user.id).firstOrNull()

View File

@ -47,6 +47,14 @@ object UserService {
} }
} }
fun getUserWithNaverId(naverId: Long): User? {
return transaction {
val users = User.find(Users.naverId eq naverId)
users.firstOrNull()
}
}
fun getAllUsers(): List<User> { fun getAllUsers(): List<User> {
return transaction { return transaction {
User.all().toList() User.all().toList()

View File

@ -4,9 +4,12 @@ import io.ktor.http.*
import io.ktor.server.application.* import io.ktor.server.application.*
import io.ktor.server.response.* import io.ktor.server.response.*
import io.ktor.server.routing.* import io.ktor.server.routing.*
import io.ktor.server.sessions.*
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
import space.mori.chzzk_bot.common.services.SongConfigService import space.mori.chzzk_bot.common.services.SongConfigService
import space.mori.chzzk_bot.common.services.UserService
import space.mori.chzzk_bot.common.utils.getStreamInfo import space.mori.chzzk_bot.common.utils.getStreamInfo
import space.mori.chzzk_bot.webserver.UserSession
@Serializable @Serializable
data class GetUserDTO( data class GetUserDTO(
@ -63,38 +66,29 @@ fun Routing.apiRoutes() {
} }
route("/user") { route("/user") {
get { get {
call.respondText("Require UID", status = HttpStatusCode.NotFound) val session = call.sessions.get<UserSession>()
}
} if(session == null) {
route("/session/{sid}") { call.respondText("No session found", status = HttpStatusCode.NotFound)
get {
val sid = call.parameters["sid"]
if(sid == null) {
call.respondText("Require SID", status = HttpStatusCode.NotFound)
return@get return@get
} }
val user = SongConfigService.getUserByToken(sid) val user = UserService.getUserWithNaverId(session.id.toLong())
val session = SongConfigService.getConfig(sid)
if(user == null) { if(user == null) {
call.respondText("User not found", status = HttpStatusCode.NotFound) call.respondText("No session found", status = HttpStatusCode.NotFound)
return@get return@get
} else { }
val chzzkUser = getStreamInfo(user.token) val songConfig = SongConfigService.getConfig(user)
val status = getStreamInfo(user.token)
call.respond(HttpStatusCode.OK, GetSessionDTO( call.respond(HttpStatusCode.OK, GetSessionDTO(
chzzkUser.content!!.channel.channelId, status.content!!.channel.channelId,
chzzkUser.content!!.channel.channelName, status.content!!.channel.channelName,
chzzkUser.content!!.status == "OPEN", status.content!!.status == "OPEN",
chzzkUser.content!!.channel.channelImageUrl, status.content!!.channel.channelImageUrl,
session!!.queueLimit, songConfig.queueLimit,
session.personalLimit, songConfig.personalLimit,
session.streamerOnly songConfig.streamerOnly
)) ))
} }
} }
}
route("/session") {
get {
call.respondText("Require SID", status = HttpStatusCode.NotFound)
}
}
} }

View File

@ -1,6 +1,7 @@
package space.mori.chzzk_bot.webserver.routes package space.mori.chzzk_bot.webserver.routes
import io.ktor.server.routing.* import io.ktor.server.routing.*
import io.ktor.server.sessions.*
import io.ktor.server.websocket.* import io.ktor.server.websocket.*
import io.ktor.websocket.* import io.ktor.websocket.*
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
@ -17,6 +18,7 @@ import space.mori.chzzk_bot.common.services.SongConfigService
import space.mori.chzzk_bot.common.services.SongListService import space.mori.chzzk_bot.common.services.SongListService
import space.mori.chzzk_bot.common.services.UserService import space.mori.chzzk_bot.common.services.UserService
import space.mori.chzzk_bot.common.utils.getYoutubeVideo import space.mori.chzzk_bot.common.utils.getYoutubeVideo
import space.mori.chzzk_bot.webserver.UserSession
import java.util.concurrent.ConcurrentHashMap import java.util.concurrent.ConcurrentHashMap
import java.util.concurrent.ConcurrentLinkedQueue import java.util.concurrent.ConcurrentLinkedQueue
@ -27,33 +29,30 @@ fun Routing.wsSongListRoutes() {
val dispatcher: CoroutinesEventBus by inject(CoroutinesEventBus::class.java) val dispatcher: CoroutinesEventBus by inject(CoroutinesEventBus::class.java)
fun addSession(sid: String, session: WebSocketServerSession) { fun addSession(uid: String, session: WebSocketServerSession) {
sessions.computeIfAbsent(sid) { ConcurrentLinkedQueue() }.add(session) sessions.computeIfAbsent(uid) { ConcurrentLinkedQueue() }.add(session)
} }
fun removeSession(sid: String, session: WebSocketServerSession) { fun removeSession(uid: String, session: WebSocketServerSession) {
sessions[sid]?.remove(session) sessions[uid]?.remove(session)
if(sessions[sid]?.isEmpty() == true) { if(sessions[uid]?.isEmpty() == true) {
sessions.remove(sid) sessions.remove(uid)
} }
} }
webSocket("/songlist/{sid}") { webSocket("/songlist") {
val sid = call.parameters["sid"] val session = call.sessions.get<UserSession>()
val session = sid?.let { SongConfigService.getConfig(it) } val user = session?.id?.let { UserService.getUserWithNaverId( it.toLong() ) }
val user = sid?.let {SongConfigService.getUserByToken(sid) } if (user == null) {
if (sid == null) {
close(CloseReason(CloseReason.Codes.CANNOT_ACCEPT, "Invalid SID"))
return@webSocket
}
if (user == null || session == null) {
close(CloseReason(CloseReason.Codes.CANNOT_ACCEPT, "Invalid SID")) close(CloseReason(CloseReason.Codes.CANNOT_ACCEPT, "Invalid SID"))
return@webSocket return@webSocket
} }
addSession(sid, this) val uid = user.token
if(status[sid] == SongType.STREAM_OFF) { addSession(uid, this)
if(status[uid] == SongType.STREAM_OFF) {
CoroutineScope(Dispatchers.Default).launch { CoroutineScope(Dispatchers.Default).launch {
sendSerialized(SongResponse( sendSerialized(SongResponse(
SongType.STREAM_OFF.value, SongType.STREAM_OFF.value,
@ -65,7 +64,7 @@ fun Routing.wsSongListRoutes() {
null null
)) ))
} }
removeSession(sid, this) removeSession(uid, this)
} }
try { try {
@ -107,7 +106,7 @@ fun Routing.wsSongListRoutes() {
} }
} }
} catch(e: Exception) { } catch(e: Exception) {
logger.debug("SongType.ADD Error: {} / {}", session.token, e) logger.debug("SongType.ADD Error: {} / {}", uid, e)
} }
} }
else if(data.type == SongType.REMOVE.value && data.url != null) { else if(data.type == SongType.REMOVE.value && data.url != null) {
@ -145,7 +144,7 @@ fun Routing.wsSongListRoutes() {
} catch(e: ClosedReceiveChannelException) { } catch(e: ClosedReceiveChannelException) {
logger.error("Error in WebSocket: ${e.message}") logger.error("Error in WebSocket: ${e.message}")
} finally { } finally {
removeSession(sid, this) removeSession(uid, this)
} }
} }