diff --git a/chatbot/src/main/kotlin/space/mori/chzzk_bot/chatbot/chzzk/ChzzkHandler.kt b/chatbot/src/main/kotlin/space/mori/chzzk_bot/chatbot/chzzk/ChzzkHandler.kt index cdaf73c..3e1521b 100644 --- a/chatbot/src/main/kotlin/space/mori/chzzk_bot/chatbot/chzzk/ChzzkHandler.kt +++ b/chatbot/src/main/kotlin/space/mori/chzzk_bot/chatbot/chzzk/ChzzkHandler.kt @@ -206,6 +206,7 @@ class UserHandler( var messageHandler: MessageHandler var client: ChzzkClient var listener: ChzzkUserSession + var chatChannelId: String? private val dispatcher: CoroutinesEventBus by inject(CoroutinesEventBus::class.java) private var _isActive: Boolean @@ -221,18 +222,14 @@ class UserHandler( throw RuntimeException("AccessToken or RefreshToken is not valid.") } try { - - client = Connector.getClient(user.accessToken!!, user.refreshToken!!) + val tokens = Connector.client.refreshAccessToken(user.refreshToken!!) + client = Connector.getClient(tokens.first, tokens.second) + UserService.setRefreshToken(user, tokens.first, tokens.second) + chatChannelId = getChzzkChannelId(channel.channelId) client.loginAsync().join() - client.refreshTokenAsync().join() - - UserService.setRefreshToken(user, client.loginResult.accessToken(), client.loginResult.refreshToken()) - listener = ChzzkSessionBuilder(client).buildUserSession() - listener.createAndConnectAsync().join() - messageHandler = MessageHandler(this@UserHandler) listener.on(SessionChatMessageEvent::class.java) { diff --git a/chatbot/src/main/kotlin/space/mori/chzzk_bot/chatbot/chzzk/MessageHandler.kt b/chatbot/src/main/kotlin/space/mori/chzzk_bot/chatbot/chzzk/MessageHandler.kt index aa2e092..f107646 100644 --- a/chatbot/src/main/kotlin/space/mori/chzzk_bot/chatbot/chzzk/MessageHandler.kt +++ b/chatbot/src/main/kotlin/space/mori/chzzk_bot/chatbot/chzzk/MessageHandler.kt @@ -353,15 +353,15 @@ class MessageHandler( // Replace followPattern result = followPattern.replace(result) { _ -> try { - val followingDate = getFollowDate(channel.channelId, msg.senderChannelId) - .content?.streamingProperty?.following?.followDate + val followingDate = handler.chatChannelId?.let { getFollowDate(it, msg.senderChannelId) } + ?.content?.streamingProperty?.following?.followDate ?: LocalDateTime.now().minusDays(1).toString() - val period = followingDate?.let { + val period = followingDate.let { val formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss") val pastDate = LocalDateTime.parse(it, formatter) val today = LocalDateTime.now() ChronoUnit.DAYS.between(pastDate, today) - } ?: 0 + } + 1 period.toString() } catch (e: Exception) { diff --git a/chatbot/src/main/kotlin/space/mori/chzzk_bot/chatbot/utils/accessTokenRefresh.kt b/chatbot/src/main/kotlin/space/mori/chzzk_bot/chatbot/utils/accessTokenRefresh.kt new file mode 100644 index 0000000..4355427 --- /dev/null +++ b/chatbot/src/main/kotlin/space/mori/chzzk_bot/chatbot/utils/accessTokenRefresh.kt @@ -0,0 +1,55 @@ +package space.mori.chzzk_bot.chatbot.utils + +import com.google.gson.Gson +import okhttp3.OkHttpClient +import okhttp3.Request +import okhttp3.RequestBody.Companion.toRequestBody +import space.mori.chzzk_bot.common.utils.client +import xyz.r2turntrue.chzzk4j.ChzzkClient +import java.io.IOException + +val client = OkHttpClient.Builder() + .addNetworkInterceptor { chain -> + chain.proceed( + chain.request() + .newBuilder() + .header("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36") + .build() + ) + } + .build() +val gson = Gson() + +data class RefreshTokenResponse( + val accessToken: String, + val refreshToken: String, + val expiresIn: Int, + val tokenType: String = "Bearer", + val scope: String +) + +fun ChzzkClient.refreshAccessToken(refreshToken: String): Pair { + val url = "https://chzzk.naver.com/auth/v1/token" + val request = Request.Builder() + .url(url) + .header("Content-Type", "application/json") + .post(gson.toJson(mapOf( + "grantType" to "refresh_token", + "refreshToken" to refreshToken, + "clientId" to this.apiClientId, + "clientSecret" to this.apiSecret + )).toRequestBody()) + .build() + + client.newCall(request).execute().use { response -> + try { + if(!response.isSuccessful) throw IOException("Unexpected code ${response.code}") + val body = response.body?.string() + val data = gson.fromJson(body, RefreshTokenResponse::class.java) + + return Pair(data.accessToken, data.refreshToken) + } catch(e: Exception) { + throw e + } + } +} \ No newline at end of file diff --git a/common/src/main/kotlin/space/mori/chzzk_bot/common/utils/ChzzkApis.kt b/common/src/main/kotlin/space/mori/chzzk_bot/common/utils/ChzzkApis.kt index 04da4ab..d1449ca 100644 --- a/common/src/main/kotlin/space/mori/chzzk_bot/common/utils/ChzzkApis.kt +++ b/common/src/main/kotlin/space/mori/chzzk_bot/common/utils/ChzzkApis.kt @@ -52,6 +52,20 @@ data class NicknameColor( val colorCode: String = "" ) +data class LiveStatus( + val liveTitle: String, + val status: String, + val concurrentUserCount: Int, + val accumulateCount: Int, + val paidPromotion: Boolean, + val adult: Boolean, + val krOnlyViewing: Boolean, + val openDate: String, + val closeDate: String?, + val clipActive: Boolean, + val chatChannelId: String +) + // OkHttpClient에 Interceptor 추가 val client = OkHttpClient.Builder() .addNetworkInterceptor { chain -> @@ -84,3 +98,24 @@ fun getFollowDate(chatID: String, userId: String) : IData { } } } + +fun getChzzkChannelId(channelId: String): String? { + val url = "https://api.chzzk.naver.com/polling/v3/channels/$channelId/live-status?includePlayerRecommendContent=false" + val request = Request.Builder() + .url(url) + .header("Content-Type", "application/json") + .get() + .build() + + client.newCall(request).execute().use { response -> + try { + if(!response.isSuccessful) throw IOException("Unexpected code ${response.code}") + val body = response.body?.string() + val data = gson.fromJson(body, object: TypeToken>() {}) + + return data.content?.chatChannelId + } catch(e: Exception) { + throw e + } + } +} \ No newline at end of file