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("-", "")
SongConfigService.updateSession(user, session)
bot.retrieveUserById(user.discord).queue { discordUser ->
discordUser?.openPrivateChannel()?.queue { channel ->
channel.sendMessage("여기로 접속해주세요! ||https://nabot.mori.space/songlist/${session}||.\n주소가 노출될 경우 방송을 다시 켜셔야 합니다!")
channel.sendMessage("여기로 접속해주세요! ||https://nabot.mori.space/songlist||.")
.queue()
}
}

View File

@ -10,6 +10,7 @@ object Users: IntIdTable("users") {
val username = varchar("username", 255)
val token = varchar("token", 64)
val discord = long("discord")
val naverId = long("naver_id")
val liveAlertGuild = long("live_alert_guild").nullable()
val liveAlertChannel = long("live_alert_channel").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 token by Users.token
var discord by Users.discord
var naverId by Users.naverId
var liveAlertGuild by Users.liveAlertGuild
var liveAlertChannel by Users.liveAlertChannel
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 {
return transaction {
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 {
return transaction {
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> {
return transaction {
User.all().toList()

View File

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

View File

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