mirror of
https://git.mihon.tech/mihonapp/mihon
synced 2024-11-25 06:36:00 +03:00
Don't throw MALTokenExpired
whenever we fail to refresh MAL token
Also cleanup
This commit is contained in:
parent
ddbe8efbc5
commit
0f4de03d7a
2 changed files with 34 additions and 38 deletions
|
@ -21,9 +21,8 @@ class MyAnimeListInterceptor(private val myanimelist: MyAnimeList) : Interceptor
|
||||||
}
|
}
|
||||||
val originalRequest = chain.request()
|
val originalRequest = chain.request()
|
||||||
|
|
||||||
// Refresh access token if expired
|
if (oauth?.isExpired() == true) {
|
||||||
if (oauth != null && oauth!!.isExpired()) {
|
refreshToken(chain)
|
||||||
setAuth(refreshToken(chain))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (oauth == null) {
|
if (oauth == null) {
|
||||||
|
@ -36,27 +35,7 @@ class MyAnimeListInterceptor(private val myanimelist: MyAnimeList) : Interceptor
|
||||||
.header("User-Agent", "Mihon v${BuildConfig.VERSION_NAME} (${BuildConfig.APPLICATION_ID})")
|
.header("User-Agent", "Mihon v${BuildConfig.VERSION_NAME} (${BuildConfig.APPLICATION_ID})")
|
||||||
.build()
|
.build()
|
||||||
|
|
||||||
val response = chain.proceed(authRequest)
|
return chain.proceed(authRequest)
|
||||||
val tokenIsExpired = response.headers["www-authenticate"]
|
|
||||||
?.contains("The access token expired") ?: false
|
|
||||||
|
|
||||||
// Retry the request once with a new token in case it was not already refreshed
|
|
||||||
// by the is expired check before.
|
|
||||||
if (response.code == 401 && tokenIsExpired) {
|
|
||||||
response.close()
|
|
||||||
|
|
||||||
val newToken = refreshToken(chain)
|
|
||||||
setAuth(newToken)
|
|
||||||
|
|
||||||
val newRequest = originalRequest.newBuilder()
|
|
||||||
.addHeader("Authorization", "Bearer ${newToken.access_token}")
|
|
||||||
.header("User-Agent", "Mihon v${BuildConfig.VERSION_NAME} (${BuildConfig.APPLICATION_ID})")
|
|
||||||
.build()
|
|
||||||
|
|
||||||
return chain.proceed(newRequest)
|
|
||||||
}
|
|
||||||
|
|
||||||
return response
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -68,22 +47,37 @@ class MyAnimeListInterceptor(private val myanimelist: MyAnimeList) : Interceptor
|
||||||
myanimelist.saveOAuth(oauth)
|
myanimelist.saveOAuth(oauth)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun refreshToken(chain: Interceptor.Chain): OAuth {
|
private fun refreshToken(chain: Interceptor.Chain): OAuth = synchronized(this) {
|
||||||
|
if (tokenExpired) throw MALTokenExpired()
|
||||||
|
oauth?.takeUnless { it.isExpired() }?.let { return@synchronized it }
|
||||||
|
|
||||||
|
val response = try {
|
||||||
|
chain.proceed(MyAnimeListApi.refreshTokenRequest(oauth!!))
|
||||||
|
} catch (_: Throwable) {
|
||||||
|
throw MALTokenRefreshFailed()
|
||||||
|
}
|
||||||
|
|
||||||
|
if (response.code == 401) {
|
||||||
|
myanimelist.setAuthExpired()
|
||||||
|
throw MALTokenExpired()
|
||||||
|
}
|
||||||
|
|
||||||
return runCatching {
|
return runCatching {
|
||||||
val oauthResponse = chain.proceed(MyAnimeListApi.refreshTokenRequest(oauth!!))
|
if (response.isSuccessful) {
|
||||||
if (oauthResponse.code == 401) {
|
with(json) { response.parseAs<OAuth>() }
|
||||||
myanimelist.setAuthExpired()
|
|
||||||
}
|
|
||||||
if (oauthResponse.isSuccessful) {
|
|
||||||
with(json) { oauthResponse.parseAs<OAuth>() }
|
|
||||||
} else {
|
} else {
|
||||||
oauthResponse.close()
|
response.close()
|
||||||
null
|
null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.getOrNull()
|
.getOrNull()
|
||||||
?: throw MALTokenExpired()
|
?.also {
|
||||||
|
this.oauth = it
|
||||||
|
myanimelist.saveOAuth(it)
|
||||||
|
}
|
||||||
|
?: throw MALTokenRefreshFailed()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class MALTokenRefreshFailed : IOException("MAL: Failed to refresh account token")
|
||||||
class MALTokenExpired : IOException("MAL: Login has expired")
|
class MALTokenExpired : IOException("MAL: Login has expired")
|
||||||
|
|
|
@ -5,14 +5,16 @@ import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
data class OAuth(
|
data class OAuth(
|
||||||
|
val token_type: String,
|
||||||
val refresh_token: String,
|
val refresh_token: String,
|
||||||
val access_token: String,
|
val access_token: String,
|
||||||
val token_type: String,
|
|
||||||
val created_at: Long = System.currentTimeMillis(),
|
|
||||||
val expires_in: Long,
|
val expires_in: Long,
|
||||||
)
|
val created_at: Long = System.currentTimeMillis(),
|
||||||
|
) {
|
||||||
fun OAuth.isExpired() = System.currentTimeMillis() > created_at + (expires_in * 1000)
|
// Assumes expired a minute earlier
|
||||||
|
private val adjustedExpiresIn: Long = (expires_in - 60) * 1000
|
||||||
|
fun isExpired() = created_at + adjustedExpiresIn < System.currentTimeMillis()
|
||||||
|
}
|
||||||
|
|
||||||
fun Track.toMyAnimeListStatus() = when (status) {
|
fun Track.toMyAnimeListStatus() = when (status) {
|
||||||
MyAnimeList.READING -> "reading"
|
MyAnimeList.READING -> "reading"
|
||||||
|
|
Loading…
Reference in a new issue