Extension repo fixes and improvements (#811)
This commit is contained in:
@@ -61,7 +61,11 @@ object Extension {
|
||||
val extensionRecord = extensionTableAsDataClass().first { it.pkgName == pkgName }
|
||||
|
||||
return installAPK {
|
||||
val apkURL = ExtensionGithubApi.getApkUrl(extensionRecord)
|
||||
val apkURL =
|
||||
ExtensionGithubApi.getApkUrl(
|
||||
extensionRecord.repo ?: throw NullPointerException("Could not find extension repo"),
|
||||
extensionRecord.apkName,
|
||||
)
|
||||
val apkName = Uri.parse(apkURL).lastPathSegment!!
|
||||
val apkSavePath = "${applicationDirs.extensionsRoot}/$apkName"
|
||||
// download apk file
|
||||
|
||||
@@ -36,9 +36,9 @@ object ExtensionsList {
|
||||
suspend fun fetchExtensions() {
|
||||
// update if 60 seconds has passed or requested offline and database is empty
|
||||
val extensions =
|
||||
(listOf(ExtensionGithubApi.REPO_URL_PREFIX) + serverConfig.extensionRepos.value).map { repo ->
|
||||
serverConfig.extensionRepos.value.map { repo ->
|
||||
kotlin.runCatching {
|
||||
ExtensionGithubApi.findExtensions(repo)
|
||||
ExtensionGithubApi.findExtensions(repo.repoUrlReplace())
|
||||
}.onFailure {
|
||||
logger.warn(it) {
|
||||
"Failed to fetch extensions for repo: $repo"
|
||||
@@ -119,8 +119,9 @@ object ExtensionsList {
|
||||
BatchUpdateStatement(ExtensionTable).apply {
|
||||
installedExtensionsToUpdate.forEach { (foundExtension, extensionRecord) ->
|
||||
addBatch(EntityID(extensionRecord[ExtensionTable.id].value, ExtensionTable))
|
||||
// Always update icon url
|
||||
// Always update icon url and repo
|
||||
this[ExtensionTable.iconUrl] = foundExtension.iconUrl
|
||||
this[ExtensionTable.repo] = foundExtension.repo
|
||||
|
||||
// add these because batch updates need matching columns
|
||||
this[ExtensionTable.hasUpdate] = extensionRecord[ExtensionTable.hasUpdate]
|
||||
@@ -199,4 +200,23 @@ object ExtensionsList {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun String.repoUrlReplace(): String {
|
||||
return if (contains("github")) {
|
||||
replace(repoMatchRegex) {
|
||||
"https://raw.githubusercontent.com/${it.groupValues[2]}/${it.groupValues[3]}/" +
|
||||
(it.groupValues.getOrNull(4)?.ifBlank { null } ?: "repo") +
|
||||
"/" +
|
||||
(it.groupValues.getOrNull(5)?.ifBlank { null } ?: "index.min.json")
|
||||
}
|
||||
} else {
|
||||
this
|
||||
}
|
||||
}
|
||||
|
||||
private val repoMatchRegex =
|
||||
(
|
||||
"https:\\/\\/(?>www\\.|raw\\.)?(github|githubusercontent)\\.com" +
|
||||
"\\/([^\\/]+)\\/([^\\/]+)(?>(?>\\/tree|\\/blob)?\\/([^\\/\\n]*))?(?>\\/([^\\/\\n]*\\.json)?)?"
|
||||
).toRegex()
|
||||
}
|
||||
|
||||
+7
-42
@@ -16,12 +16,9 @@ import kotlinx.serialization.json.Json
|
||||
import mu.KotlinLogging
|
||||
import suwayomi.tachidesk.manga.impl.util.PackageTools.LIB_VERSION_MAX
|
||||
import suwayomi.tachidesk.manga.impl.util.PackageTools.LIB_VERSION_MIN
|
||||
import suwayomi.tachidesk.manga.model.dataclass.ExtensionDataClass
|
||||
import uy.kohesive.injekt.injectLazy
|
||||
|
||||
object ExtensionGithubApi {
|
||||
const val REPO_URL_PREFIX = "https://raw.githubusercontent.com/tachiyomiorg/tachiyomi-extensions/repo/"
|
||||
private const val FALLBACK_REPO_URL_PREFIX = "https://gcore.jsdelivr.net/gh/tachiyomiorg/tachiyomi-extensions@repo/"
|
||||
private val logger = KotlinLogging.logger {}
|
||||
private val json: Json by injectLazy()
|
||||
|
||||
@@ -47,36 +44,22 @@ object ExtensionGithubApi {
|
||||
val baseUrl: String,
|
||||
)
|
||||
|
||||
private var requiresFallbackSource = false
|
||||
|
||||
suspend fun findExtensions(repo: String): List<OnlineExtension> {
|
||||
val githubResponse =
|
||||
if (requiresFallbackSource) {
|
||||
null
|
||||
} else {
|
||||
try {
|
||||
client.newCall(GET("${repo.repoUrlReplace()}index.min.json")).awaitSuccess()
|
||||
} catch (e: Throwable) {
|
||||
logger.error(e) { "Failed to get extensions from GitHub" }
|
||||
requiresFallbackSource = true
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
val response =
|
||||
githubResponse ?: run {
|
||||
client.newCall(GET("${repo.fallbackRepoUrlReplace()}index.min.json")).awaitSuccess()
|
||||
}
|
||||
client.newCall(GET(repo)).awaitSuccess()
|
||||
|
||||
return with(json) {
|
||||
response
|
||||
.parseAs<List<ExtensionJsonObject>>()
|
||||
.toExtensions(repo.repoUrlReplace())
|
||||
.toExtensions(repo.substringBeforeLast('/') + '/')
|
||||
}
|
||||
}
|
||||
|
||||
fun getApkUrl(extension: ExtensionDataClass): String {
|
||||
return "${extension.repo!!.repoUrlReplace()}/apk/${extension.apkName}"
|
||||
fun getApkUrl(
|
||||
repo: String,
|
||||
apkName: String,
|
||||
): String {
|
||||
return "${repo}apk/$apkName"
|
||||
}
|
||||
|
||||
private val client by lazy {
|
||||
@@ -125,22 +108,4 @@ object ExtensionGithubApi {
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun String.repoUrlReplace() =
|
||||
replace(repoMatchRegex) {
|
||||
"https://raw.githubusercontent.com/${it.groupValues[1]}/${it.groupValues[2]}/" +
|
||||
"${it.groupValues.getOrNull(3)?.ifBlank { null } ?: "repo"}/"
|
||||
}
|
||||
|
||||
private fun String.fallbackRepoUrlReplace() =
|
||||
replace(repoMatchRegex) {
|
||||
"https://gcore.jsdelivr.net/gh/${it.groupValues[1]}/${it.groupValues[2]}@" +
|
||||
"${it.groupValues.getOrNull(3)?.ifBlank { null } ?: "repo"}/"
|
||||
}
|
||||
|
||||
private val repoMatchRegex =
|
||||
(
|
||||
"https:\\/\\/(?:www|raw)?(?:github|githubusercontent)\\.com" +
|
||||
"\\/([^\\/]+)\\/([^\\/]+)(?:\\/(?:tree|blob)\\/(.*))?\\/?"
|
||||
).toRegex()
|
||||
}
|
||||
|
||||
@@ -43,9 +43,6 @@ object PackageTools {
|
||||
const val LIB_VERSION_MIN = 1.3
|
||||
const val LIB_VERSION_MAX = 1.5
|
||||
|
||||
private const val OFFICIAL_SIGNATURE = "7ce04da7773d41b489f4693a366c36bcd0a11fc39b547168553c285bd7348e23" // inorichi's key
|
||||
val trustedSignatures = setOf(OFFICIAL_SIGNATURE)
|
||||
|
||||
/**
|
||||
* Convert dex to jar, a wrapper for the dex2jar library
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user