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 (cherry picked from commit 4458f74f6c06fb9a2879bd530a20aaec61c06658) # Conflicts: # app/src/main/java/eu/kanade/presentation/extension/ExtensionScreen.kt
This commit is contained in:
parent
9e31806e5c
commit
153022df0a
@ -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 {
|
||||||
.newCall(GET("${REPO_URL_PREFIX}index.min.json"))
|
networkService.client
|
||||||
.await()
|
.newCall(GET("${REPO_URL_PREFIX}index.min.json"))
|
||||||
|
.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(
|
||||||
|
@ -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()
|
||||||
|
|
||||||
|
@ -8,7 +8,6 @@ import coil.load
|
|||||||
import eu.davidea.viewholders.FlexibleViewHolder
|
import eu.davidea.viewholders.FlexibleViewHolder
|
||||||
import eu.kanade.tachiyomi.R
|
import eu.kanade.tachiyomi.R
|
||||||
import eu.kanade.tachiyomi.databinding.ExtensionItemBinding
|
import eu.kanade.tachiyomi.databinding.ExtensionItemBinding
|
||||||
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
|
||||||
@ -57,15 +56,14 @@ class ExtensionHolder(view: View, val adapter: ExtensionAdapter) :
|
|||||||
// SY -->
|
// SY -->
|
||||||
private fun String.plusRepo(extension: Extension): String {
|
private fun String.plusRepo(extension: Extension): String {
|
||||||
return if (extension is Extension.Available) {
|
return if (extension is Extension.Available) {
|
||||||
when (extension.repoUrl) {
|
if (!extension.isRepoSource) {
|
||||||
REPO_URL_PREFIX -> this
|
this
|
||||||
else -> {
|
} else {
|
||||||
if (isEmpty()) {
|
if (isEmpty()) {
|
||||||
this
|
this
|
||||||
} else {
|
} else {
|
||||||
this + " • "
|
"$this • "
|
||||||
} + itemView.context.getString(R.string.repo_source)
|
} + itemView.context.getString(R.string.repo_source)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else this
|
} else this
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user