Skip to content

Commit

Permalink
feat(infrastructure): add except BusinessException case for crash han…
Browse files Browse the repository at this point in the history
…dle (#651)
  • Loading branch information
Ashinch committed Mar 18, 2024
1 parent 4413686 commit 69d7124
Show file tree
Hide file tree
Showing 9 changed files with 115 additions and 34 deletions.
19 changes: 9 additions & 10 deletions app/src/main/java/me/ash/reader/domain/service/FeverRssService.kt
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,6 @@ import androidx.work.WorkManager
import com.rometools.rome.feed.synd.SyndFeed
import dagger.hilt.android.qualifiers.ApplicationContext
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
import kotlinx.coroutines.supervisorScope
import kotlinx.coroutines.withContext
import me.ash.reader.R
Expand All @@ -27,6 +25,7 @@ import me.ash.reader.infrastructure.android.NotificationHelper
import me.ash.reader.infrastructure.di.DefaultDispatcher
import me.ash.reader.infrastructure.di.IODispatcher
import me.ash.reader.infrastructure.di.MainDispatcher
import me.ash.reader.infrastructure.exception.FeverAPIException
import me.ash.reader.infrastructure.html.Readability
import me.ash.reader.infrastructure.rss.RssHelper
import me.ash.reader.infrastructure.rss.provider.fever.FeverAPI
Expand Down Expand Up @@ -90,35 +89,35 @@ class FeverRssService @Inject constructor(
feedLink: String, searchedFeed: SyndFeed, groupId: String,
isNotification: Boolean, isFullContent: Boolean,
) {
throw Exception("Unsupported")
throw FeverAPIException("Unsupported")
}

override suspend fun addGroup(destFeed: Feed?, newGroupName: String): String {
throw Exception("Unsupported")
throw FeverAPIException("Unsupported")
}

override suspend fun renameGroup(group: Group) {
throw Exception("Unsupported")
throw FeverAPIException("Unsupported")
}

override suspend fun renameFeed(feed: Feed) {
throw Exception("Unsupported")
throw FeverAPIException("Unsupported")
}

override suspend fun deleteGroup(group: Group, onlyDeleteNoStarred: Boolean?) {
throw Exception("Unsupported")
throw FeverAPIException("Unsupported")
}

override suspend fun deleteFeed(feed: Feed, onlyDeleteNoStarred: Boolean?) {
throw Exception("Unsupported")
throw FeverAPIException("Unsupported")
}

override suspend fun moveFeed(originGroupId: String, feed: Feed) {
throw Exception("Unsupported")
throw FeverAPIException("Unsupported")
}

override suspend fun changeFeedUrl(feed: Feed) {
throw Exception("Unsupported")
throw FeverAPIException("Unsupported")
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import android.content.Context
import android.content.Intent
import android.os.Looper
import android.util.Log
import me.ash.reader.ui.ext.getCurrentVersion
import me.ash.reader.infrastructure.exception.BusinessException
import me.ash.reader.ui.ext.showToastLong
import java.lang.Thread.UncaughtExceptionHandler

Expand All @@ -23,10 +23,21 @@ class CrashHandler(private val context: Context) : UncaughtExceptionHandler {
override fun uncaughtException(p0: Thread, p1: Throwable) {
val causeMessage = getCauseMessage(p1)
Log.e("RLog", "uncaughtException: $causeMessage", p1)
context.startActivity(Intent(context, CrashReportActivity::class.java).apply {
flags = Intent.FLAG_ACTIVITY_NEW_TASK
putExtra(CrashReportActivity.ERROR_REPORT_KEY, p1.stackTraceToString())
})

when (p1) {
is BusinessException -> {
Looper.myLooper() ?: Looper.prepare()
context.showToastLong(causeMessage)
Looper.loop()
}

else -> {
context.startActivity(Intent(context, CrashReportActivity::class.java).apply {
flags = Intent.FLAG_ACTIVITY_NEW_TASK
putExtra(CrashReportActivity.ERROR_REPORT_KEY, p1.stackTraceToString())
})
}
}
}

private fun getCauseMessage(e: Throwable?): String? {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package me.ash.reader.infrastructure.exception

open class BusinessException : Exception {
constructor() : super()
constructor(message: String) : super(message)
constructor(message: String, cause: Throwable) : super(message, cause)
constructor(cause: Throwable) : super(cause)
constructor(
message: String,
cause: Throwable,
enableSuppression: Boolean,
writableStackTrace: Boolean,
) : super(message, cause, enableSuppression, writableStackTrace)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package me.ash.reader.infrastructure.exception

class FeverAPIException : BusinessException {
constructor() : super()
constructor(message: String) : super(message)
constructor(message: String, cause: Throwable) : super(message, cause)
constructor(cause: Throwable) : super(cause)
constructor(
message: String,
cause: Throwable,
enableSuppression: Boolean,
writableStackTrace: Boolean,
) : super(message, cause, enableSuppression, writableStackTrace)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package me.ash.reader.infrastructure.exception

class GoogleReaderAPIException : BusinessException {
constructor() : super()
constructor(message: String) : super(message)
constructor(message: String, cause: Throwable) : super(message, cause)
constructor(cause: Throwable) : super(cause)
constructor(
message: String,
cause: Throwable,
enableSuppression: Boolean,
writableStackTrace: Boolean,
) : super(message, cause, enableSuppression, writableStackTrace)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package me.ash.reader.infrastructure.exception

class RemoteCallException : BusinessException {
constructor() : super()
constructor(message: String) : super(message)
constructor(message: String, cause: Throwable) : super(message, cause)
constructor(cause: Throwable) : super(cause)
constructor(
message: String,
cause: Throwable,
enableSuppression: Boolean,
writableStackTrace: Boolean,
) : super(message, cause, enableSuppression, writableStackTrace)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package me.ash.reader.infrastructure.exception

class RetryException : BusinessException {
constructor() : super()
constructor(message: String) : super(message)
constructor(message: String, cause: Throwable) : super(message, cause)
constructor(cause: Throwable) : super(cause)
constructor(
message: String,
cause: Throwable,
enableSuppression: Boolean,
writableStackTrace: Boolean,
) : super(message, cause, enableSuppression, writableStackTrace)
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package me.ash.reader.infrastructure.rss.provider.fever

import me.ash.reader.infrastructure.exception.FeverAPIException
import me.ash.reader.infrastructure.rss.provider.ProviderAPI
import me.ash.reader.ui.ext.encodeBase64
import me.ash.reader.ui.ext.md5
Expand Down Expand Up @@ -29,23 +30,23 @@ class FeverAPI private constructor(
.executeAsync()

when (response.code) {
401 -> throw Exception("Unauthorized")
!in 200..299 -> throw Exception("Forbidden")
401 -> throw FeverAPIException("Unauthorized")
!in 200..299 -> throw FeverAPIException("Forbidden")
}

return toDTO(response.body.string())
}

private fun checkAuth(authMap: Map<String, Any>): Int = checkAuth(authMap["auth"] as Int?)

private fun checkAuth(auth: Int?): Int = auth?.takeIf { it > 0 } ?: throw Exception("Unauthorized")
private fun checkAuth(auth: Int?): Int = auth?.takeIf { it > 0 } ?: throw FeverAPIException("Unauthorized")

@Throws
suspend fun validCredentials(): Int = checkAuth(postRequest<FeverDTO.Common>(null).auth)

suspend fun getApiVersion(): Long =
postRequest<Map<String, Any>>(null)["api_version"] as Long?
?: throw Exception("Unable to get version")
?: throw FeverAPIException("Unable to get version")

suspend fun getGroups(): FeverDTO.Groups =
postRequest<FeverDTO.Groups>("groups").apply { checkAuth(auth) }
Expand All @@ -66,7 +67,7 @@ class FeverAPI private constructor(
postRequest<FeverDTO.Items>("items&max_id=$id").apply { checkAuth(auth) }

suspend fun getItemsWith(ids: List<String>): FeverDTO.Items =
if (ids.size > 50) throw Exception("Too many ids")
if (ids.size > 50) throw FeverAPIException("Too many ids")
else postRequest<FeverDTO.Items>("items&with_ids=${ids.joinToString(",")}").apply { checkAuth(auth) }

suspend fun getLinks(): FeverDTO.Links =
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package me.ash.reader.infrastructure.rss.provider.greader

import me.ash.reader.infrastructure.di.USER_AGENT_STRING
import me.ash.reader.infrastructure.exception.GoogleReaderAPIException
import me.ash.reader.infrastructure.exception.RetryException
import me.ash.reader.infrastructure.rss.provider.ProviderAPI
import okhttp3.FormBody
import okhttp3.Request
Expand Down Expand Up @@ -32,11 +34,11 @@ class GoogleReaderAPI private constructor(
private val authData = AuthData(null, null)

suspend fun validCredentials(): Boolean {
reauthenticate()
reAuthenticate()
return authData.clientLoginToken?.isNotEmpty() ?: false
}

private suspend fun reauthenticate() {
private suspend fun reAuthenticate() {
// Get client login token
val clResponse = client.newCall(
Request.Builder()
Expand All @@ -55,10 +57,10 @@ class GoogleReaderAPI private constructor(

val clBody = clResponse.body.string()
when (clResponse.code) {
400 -> throw Exception("BadRequest for CL Token")
401 -> throw Exception("Unauthorized for CL Token")
400 -> throw GoogleReaderAPIException("BadRequest for CL Token")
401 -> throw GoogleReaderAPIException("Unauthorized for CL Token")
!in 200..299 -> {
throw Exception(clBody)
throw GoogleReaderAPIException(clBody)
}
}

Expand All @@ -69,7 +71,7 @@ class GoogleReaderAPI private constructor(
.split("\n")
.find { it.startsWith("Auth=") }
?.substring(5)
?: throw Exception("body format error for CL Token:\n$clBody")
?: throw GoogleReaderAPIException("body format error for CL Token:\n$clBody")
}

// Get action token
Expand All @@ -88,8 +90,6 @@ class GoogleReaderAPI private constructor(
authData.actionToken = actBody
}

class RetryException(message: String) : Exception(message)

private suspend inline fun <reified T> retryableGetRequest(
query: String,
params: List<Pair<String, String>>? = null,
Expand Down Expand Up @@ -122,7 +122,7 @@ class GoogleReaderAPI private constructor(
params: List<Pair<String, String>>? = null,
): T {
if (authData.clientLoginToken.isNullOrEmpty()) {
reauthenticate()
reAuthenticate()
}

val response = client.newCall(
Expand All @@ -136,15 +136,15 @@ class GoogleReaderAPI private constructor(

val body = response.body.string()
when (response.code) {
400 -> throw Exception("BadRequest")
400 -> throw GoogleReaderAPIException("BadRequest")
401 -> throw RetryException("Unauthorized")
!in 200..299 -> {
val gReaderError = try {
toDTO<GoogleReaderDTO.GReaderError>(body)
} catch (ignore: Exception) {
GoogleReaderDTO.GReaderError(listOf(body))
}
throw Exception(gReaderError.errors.joinToString(";\n "))
throw GoogleReaderAPIException(gReaderError.errors.joinToString(";\n "))
}
}

Expand All @@ -157,7 +157,7 @@ class GoogleReaderAPI private constructor(
form: List<Pair<String, String>>? = null,
): T {
if (authData.clientLoginToken.isNullOrEmpty()) {
reauthenticate()
reAuthenticate()
}
val response = client.newCall(
Request.Builder()
Expand All @@ -175,10 +175,10 @@ class GoogleReaderAPI private constructor(

val responseBody = response.body.string()
when (response.code) {
400 -> throw Exception("BadRequest")
400 -> throw GoogleReaderAPIException("BadRequest")
401 -> throw RetryException("Unauthorized")
!in 200..299 -> {
throw Exception(responseBody)
throw GoogleReaderAPIException(responseBody)
}
}

Expand Down

0 comments on commit 69d7124

Please sign in to comment.