Skip to content

Commit

Permalink
update: refactor code & captcha validate
Browse files Browse the repository at this point in the history
  • Loading branch information
muedsa committed Aug 14, 2024
1 parent d7bfa8f commit 938a42b
Show file tree
Hide file tree
Showing 67 changed files with 4,387 additions and 3,622 deletions.
4 changes: 2 additions & 2 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@ android {
applicationId = "com.muedsa.jcytv"
minSdk = 24
targetSdk = 34
versionCode = 12
versionName = "1.0.0-rc01"
versionCode = 13
versionName = "1.0.0-rc02"
vectorDrawables {
useSupportLibrary = true
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import androidx.compose.foundation.layout.padding
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.outlined.Refresh
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
Expand Down Expand Up @@ -41,7 +42,10 @@ fun EmptyDataScreen(model: Boolean = false) {


@Composable
fun ErrorScreen(onRefresh: (() -> Unit)? = null) {
fun ErrorScreen(
onError: (() -> Unit)? = null,
onRefresh: (() -> Unit)? = null
) {
Column(
modifier = Modifier
.fillMaxSize()
Expand All @@ -57,6 +61,12 @@ fun ErrorScreen(onRefresh: (() -> Unit)? = null) {
}
}
}

if (onError != null) {
LaunchedEffect(key1 = Unit) {
onError.invoke()
}
}
}


Expand Down
32 changes: 32 additions & 0 deletions app/src/main/kotlin/com/muedsa/jcytv/AppModule.kt
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
package com.muedsa.jcytv

import android.content.Context
import androidx.room.Room
import com.jakewharton.retrofit2.converter.kotlinx.serialization.asConverterFactory
import com.muedsa.jcytv.repository.DataStoreRepo
import com.muedsa.jcytv.repository.JcyRepo
import com.muedsa.jcytv.room.AppDatabase
import com.muedsa.jcytv.service.DanDanPlayApiService
import com.muedsa.uitl.LenientJson
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.android.qualifiers.ApplicationContext
import dagger.hilt.components.SingletonComponent
import okhttp3.MediaType.Companion.toMediaType
import okhttp3.OkHttpClient
Expand All @@ -17,6 +23,32 @@ import javax.inject.Singleton
@InstallIn(SingletonComponent::class)
internal object AppModule {

@Singleton
@Provides
fun provideDataStoreRepository(@ApplicationContext app: Context) = DataStoreRepo(app)

@Provides
@Singleton
fun provideAppDatabase(@ApplicationContext appContext: Context): AppDatabase {
return Room.databaseBuilder(
appContext,
AppDatabase::class.java,
"JCYTV"
).build()
}

@Provides
@Singleton
fun provideFavoriteAnimeDao(appDatabase: AppDatabase) = appDatabase.favoriteAnimeDao()

@Provides
@Singleton
fun provideEpisodeProgressDao(appDatabase: AppDatabase) = appDatabase.episodeProgressDao()

@Provides
@Singleton
fun provideJcyRepository(dataStoreRepo: DataStoreRepo): JcyRepo = JcyRepo(dataStoreRepo)

@Provides
@Singleton
fun provideDanDanPlayApiService(): DanDanPlayApiService {
Expand Down
34 changes: 0 additions & 34 deletions app/src/main/kotlin/com/muedsa/jcytv/DatabaseModule.kt

This file was deleted.

19 changes: 0 additions & 19 deletions app/src/main/kotlin/com/muedsa/jcytv/DateStoreModule.kt

This file was deleted.

12 changes: 6 additions & 6 deletions app/src/main/kotlin/com/muedsa/jcytv/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -7,21 +7,21 @@ import androidx.activity.viewModels
import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen
import com.muedsa.compose.tv.theme.TvTheme
import com.muedsa.compose.tv.widget.Scaffold
import com.muedsa.jcytv.ui.nav.AppNavigation
import com.muedsa.jcytv.viewmodel.HomePageViewModel
import com.muedsa.model.LazyType
import com.muedsa.jcytv.screens.AppNavigation
import com.muedsa.jcytv.screens.home.main.MainScreenUiState
import com.muedsa.jcytv.screens.home.main.MainScreenViewModel
import dagger.hilt.android.AndroidEntryPoint

@AndroidEntryPoint
class MainActivity : ComponentActivity() {

private val homePageViewModel: HomePageViewModel by viewModels()
private val mainScreenViewModel: MainScreenViewModel by viewModels()

override fun onCreate(savedInstanceState: Bundle?) {
val splashScreen = installSplashScreen()
super.onCreate(savedInstanceState)
val splashScreen = installSplashScreen()
splashScreen.setKeepOnScreenCondition {
homePageViewModel.homeRowsSF.value.type == LazyType.LOADING
mainScreenViewModel.uiState.value is MainScreenUiState.Loading
}
setContent {
TvTheme {
Expand Down
5 changes: 4 additions & 1 deletion app/src/main/kotlin/com/muedsa/jcytv/Perfs.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package com.muedsa.jcytv

import androidx.datastore.preferences.core.booleanPreferencesKey
import androidx.datastore.preferences.core.intPreferencesKey
import androidx.datastore.preferences.core.stringPreferencesKey

val KEY_DANMAKU_ENABLE = booleanPreferencesKey("danmaku_enable")

Expand All @@ -11,4 +12,6 @@ val KEY_DANMAKU_SIZE_SCALE = intPreferencesKey("danmaku_size_scale")

val KEY_DANMAKU_ALPHA = intPreferencesKey("danmaku_alpha")

val KEY_DANMAKU_SCREEN_PART = intPreferencesKey("danmaku_size_part")
val KEY_DANMAKU_SCREEN_PART = intPreferencesKey("danmaku_size_part")

val KEY_CAPTCHA_GUARD_OK = stringPreferencesKey("captcha_guard_ok")
2 changes: 1 addition & 1 deletion app/src/main/kotlin/com/muedsa/jcytv/PlaybackActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import com.muedsa.compose.tv.useLocalErrorMsgBoxController
import com.muedsa.compose.tv.widget.AppBackHandler
import com.muedsa.compose.tv.widget.FillTextScreen
import com.muedsa.compose.tv.widget.Scaffold
import com.muedsa.jcytv.ui.features.playback.PlaybackScreen
import com.muedsa.jcytv.screens.playback.PlaybackScreen
import dagger.hilt.android.AndroidEntryPoint

@AndroidEntryPoint
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
package com.muedsa.jcytv.exception

class NeedValidateCaptchaException : RuntimeException()
3 changes: 3 additions & 0 deletions app/src/main/kotlin/com/muedsa/jcytv/model/AppSettingModel.kt
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.muedsa.jcytv.model

import androidx.datastore.preferences.core.Preferences
import com.muedsa.jcytv.KEY_CAPTCHA_GUARD_OK
import com.muedsa.jcytv.KEY_DANMAKU_ALPHA
import com.muedsa.jcytv.KEY_DANMAKU_ENABLE
import com.muedsa.jcytv.KEY_DANMAKU_MERGE_ENABLE
Expand All @@ -13,6 +14,7 @@ data class AppSettingModel(
val danmakuSizeScale: Int,
val danmakuAlpha: Int,
val danmakuScreenPart: Int,
val captchaGuardOk: String,
) {

companion object {
Expand All @@ -24,6 +26,7 @@ data class AppSettingModel(
danmakuSizeScale = prefs[KEY_DANMAKU_SIZE_SCALE] ?: 140,
danmakuAlpha = prefs[KEY_DANMAKU_ALPHA] ?: 100,
danmakuScreenPart = prefs[KEY_DANMAKU_SCREEN_PART] ?: 100,
captchaGuardOk = prefs[KEY_CAPTCHA_GUARD_OK] ?: "",
)

}
Expand Down
6 changes: 0 additions & 6 deletions app/src/main/kotlin/com/muedsa/jcytv/model/JcyHomeData.kt

This file was deleted.

6 changes: 6 additions & 0 deletions app/src/main/kotlin/com/muedsa/jcytv/model/JcyRankList.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package com.muedsa.jcytv.model

class JcyRankList(
val title: String,
val list: List<JcyRankVideoInfo>
)
6 changes: 6 additions & 0 deletions app/src/main/kotlin/com/muedsa/jcytv/model/JcyVideoRow.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package com.muedsa.jcytv.model

class JcyVideoRow(
val title: String,
val list: List<JcySimpleVideoInfo>
)

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,6 @@ private const val PREFS_NAME = "setting"

private val Context.dataStore: DataStore<Preferences> by preferencesDataStore(name = PREFS_NAME)

class DataStoreRepo @Inject constructor(private val context: Context) {
class DataStoreRepo @Inject constructor(context: Context) {
val dataStore: DataStore<Preferences> = context.dataStore
}
89 changes: 89 additions & 0 deletions app/src/main/kotlin/com/muedsa/jcytv/repository/JcyRepo.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
package com.muedsa.jcytv.repository

import com.google.common.net.HttpHeaders
import com.muedsa.jcytv.KEY_CAPTCHA_GUARD_OK
import com.muedsa.jcytv.exception.NeedValidateCaptchaException
import com.muedsa.jcytv.model.JcyRankList
import com.muedsa.jcytv.model.JcySimpleVideoInfo
import com.muedsa.jcytv.model.JcyVideoDetail
import com.muedsa.jcytv.model.JcyVideoRow
import com.muedsa.jcytv.util.JcyConst
import com.muedsa.jcytv.util.JcyHtmlParserTool
import com.muedsa.jcytv.util.JcyPlaySourceTool.CHROME_USER_AGENT
import com.muedsa.jcytv.util.JcyRotateCaptchaTool
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.firstOrNull
import kotlinx.coroutines.flow.map
import org.jsoup.Jsoup
import org.jsoup.nodes.Document
import org.jsoup.nodes.Element
import javax.inject.Inject

class JcyRepo @Inject constructor(dataStoreRepo: DataStoreRepo) {

private val guardOkFlow: Flow<String> = dataStoreRepo.dataStore.data
.map { it[KEY_CAPTCHA_GUARD_OK] ?: "" }

private suspend fun getGuardOk(): String = guardOkFlow.firstOrNull() ?: ""

suspend fun fetchHomeVideoRows(): List<JcyVideoRow> {
val doc: Document = Jsoup.connect(JcyConst.HOME_URL)
.header(HttpHeaders.REFERER, JcyConst.HOME_URL)
.header(HttpHeaders.USER_AGENT, JcyConst.CHROME_USER_AGENT)
.cookie(JcyRotateCaptchaTool.COOKIE_GUARD_OK, getGuardOk())
.get()
checkIfNeedValidateCaptcha(doc.head())
return JcyHtmlParserTool.parseHomVideoRows(doc.body())
}

suspend fun fetchRankList(): List<JcyRankList> {
val doc: Document = Jsoup.connect(JcyConst.RANK_URL)
.header(HttpHeaders.REFERER, JcyConst.RANK_URL)
.header(HttpHeaders.USER_AGENT, JcyConst.CHROME_USER_AGENT)
.cookie(JcyRotateCaptchaTool.COOKIE_GUARD_OK, getGuardOk())
.get()
checkIfNeedValidateCaptcha(doc.head())
return JcyHtmlParserTool.parseRankList(doc.body())
}

suspend fun searchVideos(query: String): List<JcySimpleVideoInfo> {
val doc: Document = Jsoup.connect("${JcyConst.SEARCH_URL}$query")
.header(HttpHeaders.REFERER, JcyConst.RANK_URL)
.header(HttpHeaders.USER_AGENT, JcyConst.CHROME_USER_AGENT)
.cookie(JcyRotateCaptchaTool.COOKIE_GUARD_OK, getGuardOk())
.get()
checkIfNeedValidateCaptcha(doc.head())
val vodListEl = doc.body().selectFirst(".vod-list")!!
return JcyHtmlParserTool.parseVideoRow(vodListEl).list
}

suspend fun catalog(queryMap: Map<String, String>): List<JcySimpleVideoInfo> {
val query = queryMap.toSortedMap().map {
"/${it.key}/${it.value}"
}.joinToString("")
val doc: Document = Jsoup.connect(JcyConst.CATALOG_URL.replace("{query}", query))
.header(HttpHeaders.REFERER, JcyConst.RANK_URL)
.header(HttpHeaders.USER_AGENT, JcyConst.CHROME_USER_AGENT)
.cookie(JcyRotateCaptchaTool.COOKIE_GUARD_OK, getGuardOk())
.get()
checkIfNeedValidateCaptcha(doc.head())
val vodListEl = doc.body().selectFirst(".vod-list")!!
return JcyHtmlParserTool.parseVideoRow(vodListEl).list
}

suspend fun fetchVideoDetail(id: Long): JcyVideoDetail {
val url = JcyConst.DETAIL_URL.replace("{id}", id.toString())
val doc: Document = Jsoup.connect(url)
.header(HttpHeaders.REFERER, url)
.header(HttpHeaders.USER_AGENT, CHROME_USER_AGENT)
.cookie(JcyRotateCaptchaTool.COOKIE_GUARD_OK, getGuardOk())
.get()
checkIfNeedValidateCaptcha(doc.head())
return JcyHtmlParserTool.parseVideoDetail(doc.body())
}

private fun checkIfNeedValidateCaptcha(body: Element) {
if (JcyRotateCaptchaTool.checkIfNeedValidateCaptcha(body))
throw NeedValidateCaptchaException()
}
}
Loading

0 comments on commit 938a42b

Please sign in to comment.