@@ -23,9 +23,7 @@ import kotlin.reflect.KClass
2323class TwitchApiClient (
2424 private val httpClient : OkHttpClient ,
2525 private val objectMapper : ObjectMapper ,
26- private val clientId : String ,
27- private val clientSecret : String ,
28- private val tokenContainer : HelixTokenContainer
26+ private val clientId : String
2927) {
3028
3129 private companion object : KLogging () {
@@ -39,9 +37,9 @@ class TwitchApiClient(
3937 }
4038
4139 // https://dev.twitch.tv/docs/api/reference/#get-users
42- suspend fun getUserId (userName : String ): Long {
40+ suspend fun getUserId (userName : String , token : String ): Long {
4341 val url = usersUrl.newBuilder().addQueryParameter(" login" , userName).build()
44- val response = doRequest(url, UsersResponse ::class )
42+ val response = doRequest(url, token, UsersResponse ::class )
4543
4644 if (response.data.isEmpty()) {
4745 throw ChannelNotFoundException (" Twitch user $userName not found" )
@@ -51,9 +49,9 @@ class TwitchApiClient(
5149 }
5250
5351 // https://dev.twitch.tv/docs/api/reference/#get-streams
54- suspend fun getViewersCount (userName : String ): Int {
52+ suspend fun getViewersCount (userName : String , token : String ): Int {
5553 val url = streamsUrl.newBuilder().addQueryParameter(" user_login" , userName).build()
56- val response = doRequest(url, StreamsResponse ::class )
54+ val response = doRequest(url, token, StreamsResponse ::class )
5755
5856 if (response.data.isEmpty()) {
5957 throw ChannelOfflineException (Origin .TWITCH , userName)
@@ -63,8 +61,8 @@ class TwitchApiClient(
6361 }
6462
6563 // https://dev.twitch.tv/docs/api/reference/#get-global-emotes
66- suspend fun getGlobalEmoticons (): List <TwitchEmoticon > {
67- val response = doRequest(globalEmotesUrl, EmotesResponse ::class )
64+ suspend fun getGlobalEmoticons (token : String ): List <TwitchEmoticon > {
65+ val response = doRequest(globalEmotesUrl, token, EmotesResponse ::class )
6866 return response.data.map {
6967 TwitchEmoticon (
7068 twitchId = it.id,
@@ -74,28 +72,28 @@ class TwitchApiClient(
7472 }
7573
7674 // https://dev.twitch.tv/docs/api/reference/#get-streams
77- suspend fun getFirstLiveChannelName (): String {
75+ suspend fun getFirstLiveChannelName (token : String ): String {
7876 val url = streamsUrl.newBuilder()
7977 .addQueryParameter(" type" , " live" )
8078 .addQueryParameter(" first" , " 1" )
8179 .build()
82- val response = doRequest(url, StreamsResponse ::class )
80+ val response = doRequest(url, token, StreamsResponse ::class )
8381 return response.data.first().userLogin
8482 }
8583
86- suspend fun getGlobalBadges (): Map <TwitchBadgeId , ImageBadge > {
84+ suspend fun getGlobalBadges (token : String ): Map <TwitchBadgeId , ImageBadge > {
8785 // https://dev.twitch.tv/docs/api/reference/#get-global-chat-badges
88- return getBadges(globalBadgesUrl)
86+ return getBadges(globalBadgesUrl, token )
8987 }
9088
91- suspend fun getChannelBadges (channelId : Long ): Map <TwitchBadgeId , ImageBadge > {
89+ suspend fun getChannelBadges (channelId : Long , token : String ): Map <TwitchBadgeId , ImageBadge > {
9290 // https://dev.twitch.tv/docs/api/reference/#get-channel-chat-badges
9391 val url = channelBadgesUrl.newBuilder().addQueryParameter(" broadcaster_id" , channelId.toString()).build()
94- return getBadges(url)
92+ return getBadges(url, token )
9593 }
9694
97- private suspend fun getBadges (url : HttpUrl ): Map <TwitchBadgeId , ImageBadge > {
98- val badgesResponse = doRequest(url, BadgesResponse ::class )
95+ private suspend fun getBadges (url : HttpUrl , token : String ): Map <TwitchBadgeId , ImageBadge > {
96+ val badgesResponse = doRequest(url, token, BadgesResponse ::class )
9997
10098 return badgesResponse.data
10199 .flatMap { data ->
@@ -108,9 +106,7 @@ class TwitchApiClient(
108106 }
109107 }
110108
111- private suspend fun <T : Any > doRequest (url : HttpUrl , responseType : KClass <T >): T {
112- val token = getOrGenerateToken()
113-
109+ private suspend fun <T : Any > doRequest (url : HttpUrl , token : String , responseType : KClass <T >): T {
114110 val request = Request .Builder ()
115111 .get()
116112 .url(url)
@@ -119,27 +115,17 @@ class TwitchApiClient(
119115 .build()
120116
121117 return httpClient.newCall(request).await().use { response ->
118+ if (response.code == 401 ) {
119+ throw InvalidTokenException ()
120+ }
122121 if (! response.isSuccessful) {
123122 throw UnexpectedResponseCodeException (response.code, url.toString())
124123 }
125124 objectMapper.readValue(response.nonNullBody.charStream(), responseType.java)
126125 }
127126 }
128127
129- private suspend fun getOrGenerateToken (): String {
130- val token = tokenContainer.getToken()
131-
132- if (token == null ) {
133- val newToken = generateToken()
134- tokenContainer.setToken(newToken)
135- return newToken.value
136- }
137-
138- logger.info(" Helix token was retrieved from configuration" )
139- return token.value
140- }
141-
142- private suspend fun generateToken (): HelixApiToken {
128+ suspend fun generateToken (clientSecret : String ): HelixApiToken {
143129 val request = Request .Builder ()
144130 .url(oauthUrl)
145131 .post(FormBody .Builder ()
@@ -153,15 +139,15 @@ class TwitchApiClient(
153139
154140 val response = httpClient.newCall(request).await()
155141 if (! response.isSuccessful) {
156- throw UnexpectedResponseCodeException (200 , oauthUrl)
142+ throw UnexpectedResponseCodeException (response.code , oauthUrl)
157143 }
158144
159145 val body = response.nonNullBody.string()
160146 val authResponse = objectMapper.readValue<AuthResponse >(body)
161147
162148 val token = HelixApiToken (
163149 value = authResponse.accessToken,
164- ttl = Instant .now() + Duration .ofSeconds(authResponse.expiresIn) - Duration .ofSeconds(60 )
150+ expiresAt = Instant .now() + Duration .ofSeconds(authResponse.expiresIn) - Duration .ofSeconds(60 )
165151 )
166152 logger.info(" New helix token was generated" )
167153 return token
0 commit comments