Loading app/src/main/java/foundation/e/apps/AppLoungeApplication.kt +6 −0 Original line number Diff line number Diff line Loading @@ -30,6 +30,7 @@ import foundation.e.apps.data.Constants.TAG_APP_INSTALL_STATE import foundation.e.apps.data.Constants.TAG_AUTHDATA_DUMP import foundation.e.apps.data.preference.AppLoungeDataStore import foundation.e.apps.data.preference.AppLoungePreference import foundation.e.apps.domain.usecases.ReportFaultyGPlayUser import foundation.e.apps.install.pkg.AppLoungePackageManager import foundation.e.apps.install.pkg.PkgManagerBR import foundation.e.apps.install.updates.UpdatesWorkManager Loading Loading @@ -66,6 +67,9 @@ class AppLoungeApplication : Application(), Configuration.Provider { @Inject lateinit var uncaughtExceptionHandler: CustomUncaughtExceptionHandler @Inject lateinit var reportFaultyGPlayUser: ReportFaultyGPlayUser @RequiresApi(Build.VERSION_CODES.TIRAMISU) override fun onCreate() { super.onCreate() Loading Loading @@ -109,6 +113,8 @@ class AppLoungeApplication : Application(), Configuration.Provider { appLoungePreference.getUpdateInterval(), ExistingPeriodicWorkPolicy.KEEP ) reportFaultyGPlayUser.listen() } override val workManagerConfiguration: Configuration Loading app/src/main/java/foundation/e/apps/data/login/AuthObject.kt +1 −0 Original line number Diff line number Diff line Loading @@ -42,6 +42,7 @@ sealed class AuthObject { abstract fun createInvalidAuthObject(): AuthObject class GPlayAuth(override val result: ResultSupreme<AuthData?>, override val user: User) : AuthObject() { // Seule création de GPlayValidationException override fun createInvalidAuthObject(): AuthObject { val message = "Validating AuthData failed.\nNetwork code: 401" Loading app/src/main/java/foundation/e/apps/data/playstore/PlayStoreRepository.kt +21 −1 Original line number Diff line number Diff line Loading @@ -57,6 +57,8 @@ import foundation.e.apps.utils.exponentialBackoffRetry import kotlinx.coroutines.CancellationException import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.catch import kotlinx.coroutines.flow.first Loading Loading @@ -89,6 +91,9 @@ class PlayStoreRepository @Inject constructor( private val gPlayHttpClientPukedExceptionWaitDuration: Duration = 10.milliseconds } private val _faultyEmail = MutableSharedFlow<String>() val faultyEmail: Flow<String> = _faultyEmail suspend fun updateToken(): AuthData { val userType = appLoungeDataStore.getUser() Loading Loading @@ -409,13 +414,28 @@ class PlayStoreRepository @Inject constructor( } private suspend fun <T> doAuthenticatedRequest(request: suspend (AuthData) -> T): T { val authData = appLoungeDataStore.getAuthData() return try { gPlayRequestWithUnswallowedException { request(authData) } } catch(e: HttpUnauthorizedException) { _faultyEmail.emit(authData.email) throw e } } private suspend fun <T> doAuthenticatedRequestAutoRefreshToken(request: suspend (AuthData) -> T): T { return exponentialBackoffRetry( initialDelay = 100.milliseconds, maxDelay = 15.seconds, // exp: 0,2, 0,4, 0,8, 1,6, 3,2, 6,4 ; 12,8 . work = { gPlayRequestWithUnswallowedException { request(appLoungeDataStore.getAuthData()) } }, predicate = { exception -> exception is HttpUnauthorizedException }, predicate = { exception -> if (exception is HttpUnauthorizedException) { _faultyEmail.emit(appLoungeDataStore.getAuthData().email) true } else false }, doBeforeRetry = { refreshPlayStoreAuthentication() } ) } Loading app/src/main/java/foundation/e/apps/domain/usecases/LoginUseCase.kt +0 −1 Original line number Diff line number Diff line Loading @@ -74,7 +74,6 @@ class LoginUseCase @Inject constructor( status = ResultStatus.OK, data = gPlayloginResult.getOrNull() ) result.otherPayload = gPlayloginResult.getOrNull()?.email } else { result = ResultSupreme.create( status = ResultStatus.UNKNOWN, Loading app/src/main/java/foundation/e/apps/domain/usecases/ReportFaultyGPlayUser.kt 0 → 100644 +38 −0 Original line number Diff line number Diff line package foundation.e.apps.domain.usecases import foundation.e.apps.data.ecloud.EcloudRepository import foundation.e.apps.data.enums.User import foundation.e.apps.data.playstore.PlayStoreRepository import foundation.e.apps.data.preference.AppLoungeDataStore import foundation.e.apps.di.qualifiers.IoCoroutineScope import foundation.e.apps.utils.SystemInfoProvider import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.map import timber.log.Timber import javax.inject.Inject import javax.inject.Singleton @Singleton class ReportFaultyGPlayUser @Inject constructor( private val playStoreRepository: PlayStoreRepository, private val ecloudRepository: EcloudRepository, private val appLoungeDataStore: AppLoungeDataStore, @IoCoroutineScope private val ioCoroutineScope: CoroutineScope ) { fun listen() { playStoreRepository.faultyEmail.map(::report).launchIn(ioCoroutineScope) } private suspend fun report(email: String) { if (appLoungeDataStore.getUser() != User.ANONYMOUS) { return } runCatching { ecloudRepository.uploadFaultyEmail(email,SystemInfoProvider.getAppBuildInfo()) }.onFailure { Timber.w(it, "Can't report faulty anonymous email: $email") } } } Loading
app/src/main/java/foundation/e/apps/AppLoungeApplication.kt +6 −0 Original line number Diff line number Diff line Loading @@ -30,6 +30,7 @@ import foundation.e.apps.data.Constants.TAG_APP_INSTALL_STATE import foundation.e.apps.data.Constants.TAG_AUTHDATA_DUMP import foundation.e.apps.data.preference.AppLoungeDataStore import foundation.e.apps.data.preference.AppLoungePreference import foundation.e.apps.domain.usecases.ReportFaultyGPlayUser import foundation.e.apps.install.pkg.AppLoungePackageManager import foundation.e.apps.install.pkg.PkgManagerBR import foundation.e.apps.install.updates.UpdatesWorkManager Loading Loading @@ -66,6 +67,9 @@ class AppLoungeApplication : Application(), Configuration.Provider { @Inject lateinit var uncaughtExceptionHandler: CustomUncaughtExceptionHandler @Inject lateinit var reportFaultyGPlayUser: ReportFaultyGPlayUser @RequiresApi(Build.VERSION_CODES.TIRAMISU) override fun onCreate() { super.onCreate() Loading Loading @@ -109,6 +113,8 @@ class AppLoungeApplication : Application(), Configuration.Provider { appLoungePreference.getUpdateInterval(), ExistingPeriodicWorkPolicy.KEEP ) reportFaultyGPlayUser.listen() } override val workManagerConfiguration: Configuration Loading
app/src/main/java/foundation/e/apps/data/login/AuthObject.kt +1 −0 Original line number Diff line number Diff line Loading @@ -42,6 +42,7 @@ sealed class AuthObject { abstract fun createInvalidAuthObject(): AuthObject class GPlayAuth(override val result: ResultSupreme<AuthData?>, override val user: User) : AuthObject() { // Seule création de GPlayValidationException override fun createInvalidAuthObject(): AuthObject { val message = "Validating AuthData failed.\nNetwork code: 401" Loading
app/src/main/java/foundation/e/apps/data/playstore/PlayStoreRepository.kt +21 −1 Original line number Diff line number Diff line Loading @@ -57,6 +57,8 @@ import foundation.e.apps.utils.exponentialBackoffRetry import kotlinx.coroutines.CancellationException import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.catch import kotlinx.coroutines.flow.first Loading Loading @@ -89,6 +91,9 @@ class PlayStoreRepository @Inject constructor( private val gPlayHttpClientPukedExceptionWaitDuration: Duration = 10.milliseconds } private val _faultyEmail = MutableSharedFlow<String>() val faultyEmail: Flow<String> = _faultyEmail suspend fun updateToken(): AuthData { val userType = appLoungeDataStore.getUser() Loading Loading @@ -409,13 +414,28 @@ class PlayStoreRepository @Inject constructor( } private suspend fun <T> doAuthenticatedRequest(request: suspend (AuthData) -> T): T { val authData = appLoungeDataStore.getAuthData() return try { gPlayRequestWithUnswallowedException { request(authData) } } catch(e: HttpUnauthorizedException) { _faultyEmail.emit(authData.email) throw e } } private suspend fun <T> doAuthenticatedRequestAutoRefreshToken(request: suspend (AuthData) -> T): T { return exponentialBackoffRetry( initialDelay = 100.milliseconds, maxDelay = 15.seconds, // exp: 0,2, 0,4, 0,8, 1,6, 3,2, 6,4 ; 12,8 . work = { gPlayRequestWithUnswallowedException { request(appLoungeDataStore.getAuthData()) } }, predicate = { exception -> exception is HttpUnauthorizedException }, predicate = { exception -> if (exception is HttpUnauthorizedException) { _faultyEmail.emit(appLoungeDataStore.getAuthData().email) true } else false }, doBeforeRetry = { refreshPlayStoreAuthentication() } ) } Loading
app/src/main/java/foundation/e/apps/domain/usecases/LoginUseCase.kt +0 −1 Original line number Diff line number Diff line Loading @@ -74,7 +74,6 @@ class LoginUseCase @Inject constructor( status = ResultStatus.OK, data = gPlayloginResult.getOrNull() ) result.otherPayload = gPlayloginResult.getOrNull()?.email } else { result = ResultSupreme.create( status = ResultStatus.UNKNOWN, Loading
app/src/main/java/foundation/e/apps/domain/usecases/ReportFaultyGPlayUser.kt 0 → 100644 +38 −0 Original line number Diff line number Diff line package foundation.e.apps.domain.usecases import foundation.e.apps.data.ecloud.EcloudRepository import foundation.e.apps.data.enums.User import foundation.e.apps.data.playstore.PlayStoreRepository import foundation.e.apps.data.preference.AppLoungeDataStore import foundation.e.apps.di.qualifiers.IoCoroutineScope import foundation.e.apps.utils.SystemInfoProvider import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.map import timber.log.Timber import javax.inject.Inject import javax.inject.Singleton @Singleton class ReportFaultyGPlayUser @Inject constructor( private val playStoreRepository: PlayStoreRepository, private val ecloudRepository: EcloudRepository, private val appLoungeDataStore: AppLoungeDataStore, @IoCoroutineScope private val ioCoroutineScope: CoroutineScope ) { fun listen() { playStoreRepository.faultyEmail.map(::report).launchIn(ioCoroutineScope) } private suspend fun report(email: String) { if (appLoungeDataStore.getUser() != User.ANONYMOUS) { return } runCatching { ecloudRepository.uploadFaultyEmail(email,SystemInfoProvider.getAppBuildInfo()) }.onFailure { Timber.w(it, "Can't report faulty anonymous email: $email") } } }