Merge pull request #66 from dalbodeule/develop

Develop
This commit is contained in:
JinU Choi 2024-08-14 17:00:03 +09:00 committed by GitHub
commit 8aab3aa15b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 81 additions and 27 deletions

View File

@ -5,16 +5,11 @@ 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 io.ktor.server.sessions.*
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.serialization.Serializable
import org.koin.java.KoinJavaComponent.inject import org.koin.java.KoinJavaComponent.inject
import space.mori.chzzk_bot.common.events.CoroutinesEventBus import space.mori.chzzk_bot.common.events.CoroutinesEventBus
import space.mori.chzzk_bot.common.events.DiscordRegisterEvent
import space.mori.chzzk_bot.common.services.UserService import space.mori.chzzk_bot.common.services.UserService
import space.mori.chzzk_bot.common.utils.getRandomString
import space.mori.chzzk_bot.webserver.UserSession import space.mori.chzzk_bot.webserver.UserSession
import space.mori.chzzk_bot.webserver.utils.DiscordGuildCache
fun Route.apiDiscordRoutes() { fun Route.apiDiscordRoutes() {
val dispatcher: CoroutinesEventBus by inject(CoroutinesEventBus::class.java) val dispatcher: CoroutinesEventBus by inject(CoroutinesEventBus::class.java)
@ -34,23 +29,12 @@ fun Route.apiDiscordRoutes() {
} }
if (user.discord == null) { if (user.discord == null) {
val randomString = getRandomString(8) call.respond(HttpStatusCode.NotFound)
CoroutineScope(Dispatchers.Default).launch {
dispatcher.post(DiscordRegisterEvent(
user.token!!,
randomString
))
}
call.respond(HttpStatusCode.NotFound, DiscordRequireRegisterDTO(
user.token!!,
randomString
))
return@get return@get
} }
call.respond(HttpStatusCode.OK) call.respond(HttpStatusCode.OK)
return@get
} }
get { get {
val session = call.sessions.get<UserSession>() val session = call.sessions.get<UserSession>()
@ -63,14 +47,9 @@ fun Route.apiDiscordRoutes() {
call.respond(HttpStatusCode.BadRequest, "User does not exist") call.respond(HttpStatusCode.BadRequest, "User does not exist")
return@get return@get
} }
call.respond(HttpStatusCode.OK, session.discordGuildList)
call.respond(HttpStatusCode.OK, DiscordGuildCache.getCachedGuilds(session.discordGuildList))
return@get return@get
} }
} }
} }
@Serializable
data class DiscordRequireRegisterDTO(
val user: String,
val token: String
)

View File

@ -0,0 +1,75 @@
package space.mori.chzzk_bot.webserver.utils
import applicationHttpClient
import io.ktor.client.call.*
import io.ktor.client.request.*
import io.ktor.http.*
import kotlinx.serialization.Serializable
import space.mori.chzzk_bot.webserver.DiscordGuildListAPI
import space.mori.chzzk_bot.webserver.dotenv
import java.time.Instant
import java.util.concurrent.ConcurrentHashMap
object DiscordGuildCache {
private val cache = ConcurrentHashMap<String, CachedGuilds>()
private const val EXP_SECONDS = 600L
suspend fun getCachedGuilds(guildId: String): Guild? {
val now = Instant.now()
return if(cache.isNotEmpty() && cache[guildId]?.timestamp?.plusSeconds(EXP_SECONDS)?.isAfter(now) == true) {
cache[guildId]?.guild
} else {
fetchAllGuilds()
cache[guildId]?.guild
}
}
suspend fun getCachedGuilds(guildId: List<String>): List<Guild> {
return guildId.mapNotNull { getCachedGuilds(it) }
}
private suspend fun fetchGuilds(beforeGuildId: String? = null, limit: Int = 100): List<DiscordGuildListAPI> {
val result = applicationHttpClient.get("https://discord.com/api/users/@me/guilds") {
headers {
append(HttpHeaders.Authorization, "Bot ${dotenv["DISCORD_TOKEN"]}")
}
parameter("limit", limit)
if (beforeGuildId != null) {
parameter("before", beforeGuildId)
}
}
return result.body<List<DiscordGuildListAPI>>()
}
private suspend fun fetchAllGuilds() {
var lastGuildId: String? = null
while (true) {
val guilds = fetchGuilds(lastGuildId)
if (guilds.isEmpty()) {
break
}
guilds.forEach {
cache[it.id] = CachedGuilds(
Guild(it.id, it.name, it.icon, it.banner)
)
}
lastGuildId = guilds.last().id
}
}
}
data class CachedGuilds(
val guild: Guild,
val timestamp: Instant = Instant.now()
)
@Serializable
data class Guild(
val id: String,
val name: String,
val icon: String?,
val banner: String?,
)