From 167278e5cff79d47d07ee14676bfd0e5d17c523d Mon Sep 17 00:00:00 2001 From: dalbodeule <11470513+dalbodeule@users.noreply.github.com> Date: Wed, 14 Aug 2024 10:44:15 +0900 Subject: [PATCH 1/2] add DiscordGuildCache - add DiscordGuildCache - GET /discord endpoint, return guild information. --- .../webserver/routes/ApiDiscordRoutes.kt | 4 +- .../webserver/utils/DiscordGuildCache.kt | 75 +++++++++++++++++++ 2 files changed, 78 insertions(+), 1 deletion(-) create mode 100644 webserver/src/main/kotlin/space/mori/chzzk_bot/webserver/utils/DiscordGuildCache.kt diff --git a/webserver/src/main/kotlin/space/mori/chzzk_bot/webserver/routes/ApiDiscordRoutes.kt b/webserver/src/main/kotlin/space/mori/chzzk_bot/webserver/routes/ApiDiscordRoutes.kt index d84c717..c3f11d3 100644 --- a/webserver/src/main/kotlin/space/mori/chzzk_bot/webserver/routes/ApiDiscordRoutes.kt +++ b/webserver/src/main/kotlin/space/mori/chzzk_bot/webserver/routes/ApiDiscordRoutes.kt @@ -15,6 +15,7 @@ import space.mori.chzzk_bot.common.events.DiscordRegisterEvent 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.utils.DiscordGuildCache fun Route.apiDiscordRoutes() { val dispatcher: CoroutinesEventBus by inject(CoroutinesEventBus::class.java) @@ -63,7 +64,8 @@ fun Route.apiDiscordRoutes() { call.respond(HttpStatusCode.BadRequest, "User does not exist") return@get } - call.respond(HttpStatusCode.OK, session.discordGuildList) + + call.respond(HttpStatusCode.OK, DiscordGuildCache.getCachedGuilds(session.discordGuildList)) return@get } } diff --git a/webserver/src/main/kotlin/space/mori/chzzk_bot/webserver/utils/DiscordGuildCache.kt b/webserver/src/main/kotlin/space/mori/chzzk_bot/webserver/utils/DiscordGuildCache.kt new file mode 100644 index 0000000..b55db0e --- /dev/null +++ b/webserver/src/main/kotlin/space/mori/chzzk_bot/webserver/utils/DiscordGuildCache.kt @@ -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() + 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): List { + return guildId.mapNotNull { getCachedGuilds(it) } + } + + private suspend fun fetchGuilds(beforeGuildId: String? = null, limit: Int = 100): List { + 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>() + } + + 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?, +) \ No newline at end of file From c1553fd47a8c4750020ee873b912360b0375c26d Mon Sep 17 00:00:00 2001 From: dalbodeule <11470513+dalbodeule@users.noreply.github.com> Date: Wed, 14 Aug 2024 16:56:25 +0900 Subject: [PATCH 2/2] add DiscordGuildCache - GET /discord endpoint, return guild information. - GET /discord/{uid} to return null(404) --- .../webserver/routes/ApiDiscordRoutes.kt | 29 ++----------------- 1 file changed, 3 insertions(+), 26 deletions(-) diff --git a/webserver/src/main/kotlin/space/mori/chzzk_bot/webserver/routes/ApiDiscordRoutes.kt b/webserver/src/main/kotlin/space/mori/chzzk_bot/webserver/routes/ApiDiscordRoutes.kt index c3f11d3..3a82c5c 100644 --- a/webserver/src/main/kotlin/space/mori/chzzk_bot/webserver/routes/ApiDiscordRoutes.kt +++ b/webserver/src/main/kotlin/space/mori/chzzk_bot/webserver/routes/ApiDiscordRoutes.kt @@ -5,15 +5,9 @@ import io.ktor.server.application.* import io.ktor.server.response.* import io.ktor.server.routing.* 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 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.utils.getRandomString import space.mori.chzzk_bot.webserver.UserSession import space.mori.chzzk_bot.webserver.utils.DiscordGuildCache @@ -35,23 +29,12 @@ fun Route.apiDiscordRoutes() { } if (user.discord == null) { - val randomString = getRandomString(8) - - CoroutineScope(Dispatchers.Default).launch { - dispatcher.post(DiscordRegisterEvent( - user.token!!, - randomString - )) - } - - call.respond(HttpStatusCode.NotFound, DiscordRequireRegisterDTO( - user.token!!, - randomString - )) + call.respond(HttpStatusCode.NotFound) return@get } call.respond(HttpStatusCode.OK) + return@get } get { val session = call.sessions.get() @@ -69,10 +52,4 @@ fun Route.apiDiscordRoutes() { return@get } } -} - -@Serializable -data class DiscordRequireRegisterDTO( - val user: String, - val token: String -) \ No newline at end of file +} \ No newline at end of file