diff --git a/app/src/main/java/chat/revolt/activities/MainActivity.kt b/app/src/main/java/chat/revolt/activities/MainActivity.kt
index 5a94b959..f8ff6e2b 100644
--- a/app/src/main/java/chat/revolt/activities/MainActivity.kt
+++ b/app/src/main/java/chat/revolt/activities/MainActivity.kt
@@ -39,6 +39,7 @@ import androidx.navigation.compose.rememberNavController
import chat.revolt.BuildConfig
import chat.revolt.R
import chat.revolt.RevoltApplication
+import chat.revolt.api.HitRateLimitException
import chat.revolt.api.RevoltAPI
import chat.revolt.api.RevoltHttp
import chat.revolt.api.routes.onboard.needsOnboarding
@@ -170,6 +171,14 @@ class MainActivityViewModel @Inject constructor(
startWithDestination("register/onboarding")
return@launch
}
+ } catch (e: HitRateLimitException) {
+ Log.e("MainActivity", "Rate limited while checking onboarding state", e)
+ Toast.makeText(
+ context,
+ context.getString(R.string.rate_limit_toast),
+ Toast.LENGTH_SHORT
+ ).show()
+ return@launch startWithoutDestination()
} catch (e: Exception) {
Log.e("MainActivity", "Failed to check onboarding state, clearing session", e)
kvStorage.remove("sessionToken")
diff --git a/app/src/main/java/chat/revolt/api/RevoltAPI.kt b/app/src/main/java/chat/revolt/api/RevoltAPI.kt
index 86216d6a..fff3032e 100644
--- a/app/src/main/java/chat/revolt/api/RevoltAPI.kt
+++ b/app/src/main/java/chat/revolt/api/RevoltAPI.kt
@@ -41,6 +41,7 @@ import kotlinx.coroutines.newSingleThreadContext
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.withContext
import kotlinx.serialization.ExperimentalSerializationApi
+import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import kotlinx.serialization.cbor.Cbor
import kotlinx.serialization.json.Json
@@ -349,3 +350,13 @@ object RevoltAPI {
@Serializable
data class RevoltError(val type: String)
+
+@Serializable
+data class RateLimitResponse(@SerialName("retry_after") val retryAfter: Int) {
+ fun toException(): HitRateLimitException {
+ return HitRateLimitException(retryAfter)
+ }
+}
+
+class HitRateLimitException(retryAfter: Int) :
+ Exception("Hit rate limit, retry after ${retryAfter}ms")
\ No newline at end of file
diff --git a/app/src/main/java/chat/revolt/api/routes/onboard/Onboarding.kt b/app/src/main/java/chat/revolt/api/routes/onboard/Onboarding.kt
index e32b4dd2..37d3c7c7 100644
--- a/app/src/main/java/chat/revolt/api/routes/onboard/Onboarding.kt
+++ b/app/src/main/java/chat/revolt/api/routes/onboard/Onboarding.kt
@@ -1,5 +1,6 @@
package chat.revolt.api.routes.onboard
+import chat.revolt.api.RateLimitResponse
import chat.revolt.api.RevoltAPI
import chat.revolt.api.RevoltError
import chat.revolt.api.RevoltHttp
@@ -28,6 +29,14 @@ suspend fun needsOnboarding(sessionToken: String = RevoltAPI.sessionToken): Bool
val responseContent = response.bodyAsText()
+ try {
+ val rateLimitResponse =
+ RevoltJson.decodeFromString(RateLimitResponse.serializer(), responseContent)
+ throw rateLimitResponse.toException()
+ } catch (e: SerializationException) {
+ // good path
+ }
+
return RevoltJson.decodeFromString(OnboardingResponse.serializer(), responseContent).onboarding
}
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 628e153a..8363520c 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -8,6 +8,7 @@
Share
Let\'s go
Fetching some info, hang in thereā¦
+ Hold your horses! You\'re doing that too often in a short amount of time.
Terms of Service
Privacy Policy