From 713fb6dca92d1356386a56c0b860d9496ab34d3b Mon Sep 17 00:00:00 2001 From: joeloewi7178 Date: Sat, 20 Apr 2024 16:27:09 +0900 Subject: [PATCH 1/2] fix: star rail's redeem code source html path mod: mod html parsing logic to data module --- app/build.gradle.kts | 3 - .../viewmodel/RedemptionCodesViewModel.kt | 64 ++----------------- data/build.gradle.kts | 3 + .../repository/ArcaLiveAppRepositoryImpl.kt | 10 ++- .../remote/ArcaLiveAppDataSource.kt | 7 +- .../remote/impl/ArcaLiveAppDataSourceImpl.kt | 59 ++++++++++++++--- .../repository/ArcaLiveAppRepository.kt | 7 +- .../domain/usecase/ArcaLiveAppUseCase.kt | 9 +-- 8 files changed, 72 insertions(+), 90 deletions(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 07edca29..18bfef7a 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -134,9 +134,6 @@ dependencies { //paging implementation(libs.androidx.paging.compose) - //html parsing - implementation(libs.jsoup) - //in-app update implementation(libs.android.play.app.update.ktx) diff --git a/app/src/main/kotlin/com/joeloewi/croissant/viewmodel/RedemptionCodesViewModel.kt b/app/src/main/kotlin/com/joeloewi/croissant/viewmodel/RedemptionCodesViewModel.kt index fdcf7c6d..0701bf58 100644 --- a/app/src/main/kotlin/com/joeloewi/croissant/viewmodel/RedemptionCodesViewModel.kt +++ b/app/src/main/kotlin/com/joeloewi/croissant/viewmodel/RedemptionCodesViewModel.kt @@ -20,13 +20,11 @@ import kotlinx.coroutines.awaitAll import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.launch -import kotlinx.coroutines.withContext -import org.jsoup.Jsoup import javax.inject.Inject @HiltViewModel class RedemptionCodesViewModel @Inject constructor( - private val getArticleArcaLiveAppUseCase: ArcaLiveAppUseCase.GetArticle + private val getRedeemCodeUseCase: ArcaLiveAppUseCase.GetRedeemCode ) : ViewModel() { private val _hoYoLABGameRedemptionCodesState = MutableStateFlow>>>(LCE.Loading) @@ -42,71 +40,17 @@ class RedemptionCodesViewModel @Inject constructor( _hoYoLABGameRedemptionCodesState.value = LCE.Loading viewModelScope.launch(Dispatchers.IO) { _hoYoLABGameRedemptionCodesState.value = HoYoLABGame.entries.filter { - !listOf(HoYoLABGame.Unknown, HoYoLABGame.TearsOfThemis).contains(it) + it !in listOf(HoYoLABGame.Unknown, HoYoLABGame.TearsOfThemis) }.runCatching { map { async(SupervisorJob() + Dispatchers.IO) { it to HtmlCompat.fromHtml( - getRedemptionCodesFromHtml(it).getOrThrow(), + getRedeemCodeUseCase(it).getOrThrow(), HtmlCompat.FROM_HTML_MODE_COMPACT ).toAnnotatedString() } - } - }.mapCatching { - it.awaitAll().toImmutableList() + }.awaitAll().toImmutableList() }.foldAsLce() } } - - private suspend fun getRedemptionCodesFromHtml(hoYoLABGame: HoYoLABGame): Result = - withContext(Dispatchers.IO) { - //Jsoup's nth-child works differently than expected - when (hoYoLABGame) { - HoYoLABGame.HonkaiImpact3rd -> { - getArticleArcaLiveAppUseCase( - slug = "hk3rd", - articleId = 85815048 - ).mapCatching { content -> - Jsoup.parse(content).apply { - select("*:has(> img)").remove() - repeat(5) { - select("body > p:last-child").remove() - } - }.html() - } - } - - HoYoLABGame.GenshinImpact -> { - getArticleArcaLiveAppUseCase( - slug = "genshin", - articleId = 95519559 - ).mapCatching { content -> - Jsoup.parse(content).apply { - select("img").remove() - }.select("table:first-of-type").apply { - select("tr:last-child").remove() - }.html().replace("https://oo.pe/", "") - } - } - - HoYoLABGame.HonkaiStarRail -> { - getArticleArcaLiveAppUseCase( - slug = "hkstarrail", - articleId = 69911111 - ).mapCatching { content -> - Jsoup.parse(content).apply { - repeat(9) { - select("p:last-child").remove() - } - }.select("p:nth-child(n+47)").html().replace("https://oo.pe/", "") - } - } - - else -> { - runCatching { - "" - } - } - } - } } \ No newline at end of file diff --git a/data/build.gradle.kts b/data/build.gradle.kts index 1e35e354..e2e4d475 100644 --- a/data/build.gradle.kts +++ b/data/build.gradle.kts @@ -62,6 +62,9 @@ dependencies { implementation(libs.androidx.startup) implementation(libs.androidx.lifecycle.process) + + //html parsing + implementation(libs.jsoup) } protobuf { diff --git a/data/src/main/kotlin/com/joeloewi/croissant/data/repository/ArcaLiveAppRepositoryImpl.kt b/data/src/main/kotlin/com/joeloewi/croissant/data/repository/ArcaLiveAppRepositoryImpl.kt index 132ab17e..00017239 100644 --- a/data/src/main/kotlin/com/joeloewi/croissant/data/repository/ArcaLiveAppRepositoryImpl.kt +++ b/data/src/main/kotlin/com/joeloewi/croissant/data/repository/ArcaLiveAppRepositoryImpl.kt @@ -17,6 +17,7 @@ package com.joeloewi.croissant.data.repository import com.joeloewi.croissant.data.repository.remote.ArcaLiveAppDataSource +import com.joeloewi.croissant.domain.common.HoYoLABGame import com.joeloewi.croissant.domain.repository.ArcaLiveAppRepository import com.skydoves.sandwich.getOrThrow import javax.inject.Inject @@ -24,10 +25,7 @@ import javax.inject.Inject class ArcaLiveAppRepositoryImpl @Inject constructor( private val arcaLiveAppDataSource: ArcaLiveAppDataSource ) : ArcaLiveAppRepository { - override suspend fun getArticle(slug: String, articleId: Long): Result = - arcaLiveAppDataSource.runCatching { - getArticle(slug, articleId).getOrThrow() - }.mapCatching { articleResponse -> - articleResponse.content - } + override suspend fun getRedeemCode( + game: HoYoLABGame + ): Result = arcaLiveAppDataSource.runCatching { getRedeemCode(game).getOrThrow() } } \ No newline at end of file diff --git a/data/src/main/kotlin/com/joeloewi/croissant/data/repository/remote/ArcaLiveAppDataSource.kt b/data/src/main/kotlin/com/joeloewi/croissant/data/repository/remote/ArcaLiveAppDataSource.kt index cb1b568c..94d20ca8 100644 --- a/data/src/main/kotlin/com/joeloewi/croissant/data/repository/remote/ArcaLiveAppDataSource.kt +++ b/data/src/main/kotlin/com/joeloewi/croissant/data/repository/remote/ArcaLiveAppDataSource.kt @@ -16,12 +16,9 @@ package com.joeloewi.croissant.data.repository.remote -import com.joeloewi.croissant.data.api.model.response.ArticleResponse +import com.joeloewi.croissant.domain.common.HoYoLABGame import com.skydoves.sandwich.ApiResponse interface ArcaLiveAppDataSource { - suspend fun getArticle( - slug: String, - articleId: Long - ): ApiResponse + suspend fun getRedeemCode(game: HoYoLABGame): ApiResponse } \ No newline at end of file diff --git a/data/src/main/kotlin/com/joeloewi/croissant/data/repository/remote/impl/ArcaLiveAppDataSourceImpl.kt b/data/src/main/kotlin/com/joeloewi/croissant/data/repository/remote/impl/ArcaLiveAppDataSourceImpl.kt index 2530ae76..5fb8a164 100644 --- a/data/src/main/kotlin/com/joeloewi/croissant/data/repository/remote/impl/ArcaLiveAppDataSourceImpl.kt +++ b/data/src/main/kotlin/com/joeloewi/croissant/data/repository/remote/impl/ArcaLiveAppDataSourceImpl.kt @@ -17,24 +17,67 @@ package com.joeloewi.croissant.data.repository.remote.impl import com.joeloewi.croissant.data.api.dao.ArcaLiveAppService -import com.joeloewi.croissant.data.api.model.response.ArticleResponse import com.joeloewi.croissant.data.repository.remote.ArcaLiveAppDataSource import com.joeloewi.croissant.data.util.runAndRetryWithExponentialBackOff +import com.joeloewi.croissant.domain.common.HoYoLABGame import com.skydoves.sandwich.ApiResponse +import com.skydoves.sandwich.mapSuccess import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext +import org.jsoup.Jsoup import javax.inject.Inject class ArcaLiveAppDataSourceImpl @Inject constructor( private val arcaLiveAppService: ArcaLiveAppService, ) : ArcaLiveAppDataSource { - override suspend fun getArticle(slug: String, articleId: Long): ApiResponse = - withContext(Dispatchers.IO) { - runAndRetryWithExponentialBackOff { - arcaLiveAppService.getArticle( - slug = slug, - articleId = articleId - ) + + override suspend fun getRedeemCode( + game: HoYoLABGame + ): ApiResponse = withContext(Dispatchers.IO) { + runAndRetryWithExponentialBackOff { + when (game) { + HoYoLABGame.HonkaiImpact3rd -> { + arcaLiveAppService.getArticle( + slug = "hk3rd", + articleId = 85815048 + ).mapSuccess { + Jsoup.parse(content).apply { + select("*:has(> img)").remove() + repeat(5) { + select("body > p:last-child").remove() + } + }.html() + } + } + + HoYoLABGame.GenshinImpact -> { + arcaLiveAppService.getArticle( + slug = "genshin", + articleId = 95519559 + ).mapSuccess { + Jsoup.parse(content).apply { + select("img").remove() + }.select("table:first-of-type").apply { + select("tr:last-child").remove() + }.html().replace("https://oo.pe/", "") + } + } + + HoYoLABGame.HonkaiStarRail -> { + arcaLiveAppService.getArticle( + slug = "hkstarrail", + articleId = 72618649 + ).mapSuccess { + Jsoup.parse(content) + .apply { select("img").remove() } + .select("td:first-of-type") + .html() + .replace("https://oo.pe/", "") + } + } + + HoYoLABGame.TearsOfThemis, HoYoLABGame.Unknown -> throw IllegalStateException() } } + } } \ No newline at end of file diff --git a/domain/src/main/kotlin/com/joeloewi/croissant/domain/repository/ArcaLiveAppRepository.kt b/domain/src/main/kotlin/com/joeloewi/croissant/domain/repository/ArcaLiveAppRepository.kt index ec94ed0d..b406ac2b 100644 --- a/domain/src/main/kotlin/com/joeloewi/croissant/domain/repository/ArcaLiveAppRepository.kt +++ b/domain/src/main/kotlin/com/joeloewi/croissant/domain/repository/ArcaLiveAppRepository.kt @@ -1,8 +1,7 @@ package com.joeloewi.croissant.domain.repository +import com.joeloewi.croissant.domain.common.HoYoLABGame + interface ArcaLiveAppRepository { - suspend fun getArticle( - slug: String, - articleId: Long - ): Result + suspend fun getRedeemCode(game: HoYoLABGame): Result } \ No newline at end of file diff --git a/domain/src/main/kotlin/com/joeloewi/croissant/domain/usecase/ArcaLiveAppUseCase.kt b/domain/src/main/kotlin/com/joeloewi/croissant/domain/usecase/ArcaLiveAppUseCase.kt index a0275750..0222b017 100644 --- a/domain/src/main/kotlin/com/joeloewi/croissant/domain/usecase/ArcaLiveAppUseCase.kt +++ b/domain/src/main/kotlin/com/joeloewi/croissant/domain/usecase/ArcaLiveAppUseCase.kt @@ -16,16 +16,17 @@ package com.joeloewi.croissant.domain.usecase +import com.joeloewi.croissant.domain.common.HoYoLABGame import com.joeloewi.croissant.domain.repository.ArcaLiveAppRepository import javax.inject.Inject sealed class ArcaLiveAppUseCase { - class GetArticle @Inject constructor( + class GetRedeemCode @Inject constructor( private val arcaLiveAppRepository: ArcaLiveAppRepository ) : ArcaLiveAppUseCase() { + suspend operator fun invoke( - slug: String, - articleId: Long - ) = arcaLiveAppRepository.getArticle(slug, articleId) + game: HoYoLABGame + ) = arcaLiveAppRepository.getRedeemCode(game) } } \ No newline at end of file From 64920e859a646ff481ae0198ea3c7be947fc1e99 Mon Sep 17 00:00:00 2001 From: joeloewi7178 Date: Sat, 20 Apr 2024 16:36:07 +0900 Subject: [PATCH 2/2] versionCode 61 versionName 1.3.0 --- app/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 18bfef7a..fb00091e 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -21,7 +21,7 @@ android { defaultConfig { applicationId = "com.joeloewi.croissant" - versionCode = 60 + versionCode = 61 versionName = "1.3.0" targetSdk = 34