Use jsDelivr as fallback when GitHub can't be reached for extensions (closes #5517)

Re-implementation of 24bb2f02dce135e0ceb2856618ecfc0e30dce875

(cherry picked from commit d61bfd7cafa09ff6c5f159c945984f2e8d9904b9)

# Conflicts:
#	app/src/main/java/eu/kanade/tachiyomi/extension/api/ExtensionGithubApi.kt
This commit is contained in:
arkon 2022-05-15 16:51:52 -04:00 committed by Jobobby04
parent 6fc99bef25
commit 4458f74f6c
3 changed files with 46 additions and 11 deletions

View File

@ -46,7 +46,6 @@ import eu.kanade.presentation.util.horizontalPadding
import eu.kanade.presentation.util.plus import eu.kanade.presentation.util.plus
import eu.kanade.presentation.util.topPaddingValues import eu.kanade.presentation.util.topPaddingValues
import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.extension.api.REPO_URL_PREFIX
import eu.kanade.tachiyomi.extension.model.Extension import eu.kanade.tachiyomi.extension.model.Extension
import eu.kanade.tachiyomi.extension.model.InstallStep import eu.kanade.tachiyomi.extension.model.InstallStep
import eu.kanade.tachiyomi.source.ConfigurableSource import eu.kanade.tachiyomi.source.ConfigurableSource
@ -307,7 +306,7 @@ fun ExtensionItemContent(
color = MaterialTheme.colorScheme.error, color = MaterialTheme.colorScheme.error,
), ),
) )
} /* SY --> */ else if (extension is Extension.Available && extension.repoUrl != REPO_URL_PREFIX) { } /* SY --> */ else if (extension is Extension.Available && extension.isRepoSource) {
Text( Text(
text = stringResource(R.string.repo_source).uppercase(), text = stringResource(R.string.repo_source).uppercase(),
style = MaterialTheme.typography.bodySmall.copy( style = MaterialTheme.typography.bodySmall.copy(
@ -324,7 +323,7 @@ fun ExtensionItemContent(
private infix fun String.plusRepo(extension: Extension): String { private infix fun String.plusRepo(extension: Extension): String {
val context = LocalContext.current val context = LocalContext.current
return remember(this, extension, context) { return remember(this, extension, context) {
if (extension is Extension.Available && extension.repoUrl != REPO_URL_PREFIX) { if (extension is Extension.Available && extension.isRepoSource) {
if (isNullOrEmpty()) { if (isNullOrEmpty()) {
"" ""
} else { } else {

View File

@ -12,7 +12,9 @@ import eu.kanade.tachiyomi.network.await
import eu.kanade.tachiyomi.network.parseAs import eu.kanade.tachiyomi.network.parseAs
import eu.kanade.tachiyomi.util.lang.withIOContext import eu.kanade.tachiyomi.util.lang.withIOContext
import exh.source.BlacklistedSources import exh.source.BlacklistedSources
import eu.kanade.tachiyomi.util.system.logcat
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
import logcat.LogPriority
import uy.kohesive.injekt.injectLazy import uy.kohesive.injekt.injectLazy
import java.util.Date import java.util.Date
import java.util.concurrent.TimeUnit import java.util.concurrent.TimeUnit
@ -22,21 +24,38 @@ internal class ExtensionGithubApi {
private val networkService: NetworkHelper by injectLazy() private val networkService: NetworkHelper by injectLazy()
private val preferences: PreferencesHelper by injectLazy() private val preferences: PreferencesHelper by injectLazy()
private var requiresFallbackSource = false
suspend fun findExtensions(): List<Extension.Available> { suspend fun findExtensions(): List<Extension.Available> {
return withIOContext { return withIOContext {
val extensions = networkService.client val response = try {
networkService.client
.newCall(GET("${REPO_URL_PREFIX}index.min.json")) .newCall(GET("${REPO_URL_PREFIX}index.min.json"))
.await() .await()
} catch (e: Throwable) {
logcat(LogPriority.ERROR, e) { "Failed to get extensions from GitHub" }
requiresFallbackSource = true
networkService.client
.newCall(GET("${FALLBACK_REPO_URL_PREFIX}index.min.json"))
.await()
}
val extensions = response
.parseAs<List<ExtensionJsonObject>>() .parseAs<List<ExtensionJsonObject>>()
.toExtensions() /* SY --> */ + preferences.extensionRepos() .toExtensions() /* SY --> */ + preferences.extensionRepos()
.get() .get()
.flatMap { repoPath -> .flatMap { repoPath ->
val url = "$BASE_URL$repoPath/repo/" val url = if (requiresFallbackSource) {
"$FALLBACK_BASE_URL$repoPath@repo/"
} else {
"$BASE_URL$repoPath/repo/"
}
networkService.client networkService.client
.newCall(GET("${url}index.min.json")) .newCall(GET("${url}index.min.json"))
.await() .await()
.parseAs<List<ExtensionJsonObject>>() .parseAs<List<ExtensionJsonObject>>()
.toExtensions(url) .toExtensions(url, repoSource = true)
} }
// SY <-- // SY <--
@ -85,7 +104,12 @@ internal class ExtensionGithubApi {
return extensionsWithUpdate return extensionsWithUpdate
} }
private fun List<ExtensionJsonObject>.toExtensions(/* SY --> */ repoUrl: String = REPO_URL_PREFIX /* SY <-- */): List<Extension.Available> { private fun List<ExtensionJsonObject>.toExtensions(
// SY -->
repoUrl: String = getUrlPrefix(),
repoSource: Boolean = false
// SY <--
): List<Extension.Available> {
return this return this
.filter { .filter {
val libVersion = it.version.substringBeforeLast('.').toDouble() val libVersion = it.version.substringBeforeLast('.').toDouble()
@ -106,6 +130,7 @@ internal class ExtensionGithubApi {
iconUrl = "${/* SY --> */ repoUrl /* SY <-- */}icon/${it.apk.replace(".apk", ".png")}", iconUrl = "${/* SY --> */ repoUrl /* SY <-- */}icon/${it.apk.replace(".apk", ".png")}",
// SY --> // SY -->
repoUrl = repoUrl, repoUrl = repoUrl,
isRepoSource = repoSource
// SY <-- // SY <--
) )
} }
@ -125,6 +150,14 @@ internal class ExtensionGithubApi {
return /* SY --> */ "${extension.repoUrl}/apk/${extension.apkName}" // SY <-- return /* SY --> */ "${extension.repoUrl}/apk/${extension.apkName}" // SY <--
} }
private fun getUrlPrefix(): String {
return if (requiresFallbackSource) {
FALLBACK_REPO_URL_PREFIX
} else {
REPO_URL_PREFIX
}
}
// SY --> // SY -->
private fun Extension.isBlacklisted( private fun Extension.isBlacklisted(
blacklistEnabled: Boolean = preferences.enableSourceBlacklist().get(), blacklistEnabled: Boolean = preferences.enableSourceBlacklist().get(),
@ -134,8 +167,10 @@ internal class ExtensionGithubApi {
// SY <-- // SY <--
} }
const val BASE_URL = "https://raw.githubusercontent.com/" private const val BASE_URL = "https://raw.githubusercontent.com/"
const val REPO_URL_PREFIX = "${BASE_URL}tachiyomiorg/tachiyomi-extensions/repo/" private const val REPO_URL_PREFIX = "${BASE_URL}tachiyomiorg/tachiyomi-extensions/repo/"
private const val FALLBACK_BASE_URL = "https://cdn.jsdelivr.net/gh/"
private const val FALLBACK_REPO_URL_PREFIX = "${FALLBACK_BASE_URL}tachiyomiorg/tachiyomi-extensions@repo/"
@Serializable @Serializable
private data class ExtensionJsonObject( private data class ExtensionJsonObject(

View File

@ -48,6 +48,7 @@ sealed class Extension {
val iconUrl: String, val iconUrl: String,
// SY --> // SY -->
val repoUrl: String, val repoUrl: String,
val isRepoSource: Boolean,
// SY <-- // SY <--
) : Extension() ) : Extension()