From 153022df0a3f323189bc36270b4d6790b6500d4b Mon Sep 17 00:00:00 2001 From: arkon Date: Sun, 15 May 2022 16:51:52 -0400 Subject: [PATCH] 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 --- .../extension/api/ExtensionGithubApi.kt | 51 ++++++++++++++++--- .../tachiyomi/extension/model/Extension.kt | 1 + .../ui/browse/extension/ExtensionHolder.kt | 18 +++---- 3 files changed, 52 insertions(+), 18 deletions(-) diff --git a/app/src/main/java/eu/kanade/tachiyomi/extension/api/ExtensionGithubApi.kt b/app/src/main/java/eu/kanade/tachiyomi/extension/api/ExtensionGithubApi.kt index d24170239..e7b29e25e 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/extension/api/ExtensionGithubApi.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/extension/api/ExtensionGithubApi.kt @@ -12,7 +12,9 @@ import eu.kanade.tachiyomi.network.await import eu.kanade.tachiyomi.network.parseAs import eu.kanade.tachiyomi.util.lang.withIOContext import exh.source.BlacklistedSources +import eu.kanade.tachiyomi.util.system.logcat import kotlinx.serialization.Serializable +import logcat.LogPriority import uy.kohesive.injekt.injectLazy import java.util.Date import java.util.concurrent.TimeUnit @@ -22,21 +24,38 @@ internal class ExtensionGithubApi { private val networkService: NetworkHelper by injectLazy() private val preferences: PreferencesHelper by injectLazy() + private var requiresFallbackSource = false + suspend fun findExtensions(): List { return withIOContext { - val extensions = networkService.client - .newCall(GET("${REPO_URL_PREFIX}index.min.json")) - .await() + val response = try { + networkService.client + .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>() .toExtensions() /* SY --> */ + preferences.extensionRepos() .get() .flatMap { repoPath -> - val url = "$BASE_URL$repoPath/repo/" + val url = if (requiresFallbackSource) { + "$FALLBACK_BASE_URL$repoPath@repo/" + } else { + "$BASE_URL$repoPath/repo/" + } networkService.client .newCall(GET("${url}index.min.json")) .await() .parseAs>() - .toExtensions(url) + .toExtensions(url, repoSource = true) } // SY <-- @@ -85,7 +104,12 @@ internal class ExtensionGithubApi { return extensionsWithUpdate } - private fun List.toExtensions(/* SY --> */ repoUrl: String = REPO_URL_PREFIX /* SY <-- */): List { + private fun List.toExtensions( + // SY --> + repoUrl: String = getUrlPrefix(), + repoSource: Boolean = false + // SY <-- + ): List { return this .filter { val libVersion = it.version.substringBeforeLast('.').toDouble() @@ -106,6 +130,7 @@ internal class ExtensionGithubApi { iconUrl = "${/* SY --> */ repoUrl /* SY <-- */}icon/${it.apk.replace(".apk", ".png")}", // SY --> repoUrl = repoUrl, + isRepoSource = repoSource // SY <-- ) } @@ -125,6 +150,14 @@ internal class ExtensionGithubApi { return /* SY --> */ "${extension.repoUrl}/apk/${extension.apkName}" // SY <-- } + private fun getUrlPrefix(): String { + return if (requiresFallbackSource) { + FALLBACK_REPO_URL_PREFIX + } else { + REPO_URL_PREFIX + } + } + // SY --> private fun Extension.isBlacklisted( blacklistEnabled: Boolean = preferences.enableSourceBlacklist().get(), @@ -134,8 +167,10 @@ internal class ExtensionGithubApi { // SY <-- } -const val BASE_URL = "https://raw.githubusercontent.com/" -const val REPO_URL_PREFIX = "${BASE_URL}tachiyomiorg/tachiyomi-extensions/repo/" +private const val BASE_URL = "https://raw.githubusercontent.com/" +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 private data class ExtensionJsonObject( diff --git a/app/src/main/java/eu/kanade/tachiyomi/extension/model/Extension.kt b/app/src/main/java/eu/kanade/tachiyomi/extension/model/Extension.kt index c93bf8987..09830001f 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/extension/model/Extension.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/extension/model/Extension.kt @@ -48,6 +48,7 @@ sealed class Extension { val iconUrl: String, // SY --> val repoUrl: String, + val isRepoSource: Boolean, // SY <-- ) : Extension() diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/extension/ExtensionHolder.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/extension/ExtensionHolder.kt index 33209ecfd..db5eadd01 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/extension/ExtensionHolder.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/extension/ExtensionHolder.kt @@ -8,7 +8,6 @@ import coil.load import eu.davidea.viewholders.FlexibleViewHolder import eu.kanade.tachiyomi.R 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.InstallStep import eu.kanade.tachiyomi.source.ConfigurableSource @@ -57,15 +56,14 @@ class ExtensionHolder(view: View, val adapter: ExtensionAdapter) : // SY --> private fun String.plusRepo(extension: Extension): String { return if (extension is Extension.Available) { - when (extension.repoUrl) { - REPO_URL_PREFIX -> this - else -> { - if (isEmpty()) { - this - } else { - this + " • " - } + itemView.context.getString(R.string.repo_source) - } + if (!extension.isRepoSource) { + this + } else { + if (isEmpty()) { + this + } else { + "$this • " + } + itemView.context.getString(R.string.repo_source) } } else this }