Merge branch 'kmmiio99o:main' into main

This commit is contained in:
OTKUSteyler 2026-01-10 16:32:35 +00:00 • committed by GitHub
commit d07c8e953d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 112 additions and 46 deletions

View file

@ -25,7 +25,7 @@ android {
defaultConfig { defaultConfig {
minSdk = 28 minSdk = 28
targetSdk = 36 targetSdk = 36
versionCode = 10_11_00 versionCode = 10_11_01
versionName = "1.1.1" versionName = "1.1.1"
vectorDrawables { vectorDrawables {
useSupportLibrary = true useSupportLibrary = true

View file

@ -16,11 +16,13 @@ import io.ktor.client.request.prepareGet
import io.ktor.client.statement.bodyAsChannel import io.ktor.client.statement.bodyAsChannel
import io.ktor.http.HttpHeaders import io.ktor.http.HttpHeaders
import io.ktor.http.contentLength import io.ktor.http.contentLength
import io.ktor.http.isSuccess
import io.ktor.utils.io.readAvailable import io.ktor.utils.io.readAvailable
import kotlinx.coroutines.CancellationException import kotlinx.coroutines.CancellationException
import java.io.File import java.io.File
import java.io.IOException import java.io.IOException
import java.net.SocketTimeoutException import java.net.SocketTimeoutException
import java.net.URI
/** /**
* Handle downloading remote urls to a path with Ktor. * Handle downloading remote urls to a path with Ktor.
@ -39,7 +41,38 @@ class KtorDownloadManager(
.apply { exists() || createNewFile() } .apply { exists() || createNewFile() }
try { try {
val httpStmt = http.prepareGet(url) { val downloadUrl = rewriteRawGithubUrl(url)
// Try the CDN first (jsDelivr), then an alternate raw proxy (raw.githack.com), and finally
// fall back to the original URL if all CDN attempts fail.
val rawGithack = try {
when {
// direct raw.githubusercontent.com -> raw.githack.com
url.contains("raw.githubusercontent.com", ignoreCase = true) ->
url.replace("raw.githubusercontent.com", "raw.githack.com")
// github.com/.../raw/... -> convert to raw.githack.com/ORG/REPO/BRANCH/path
url.contains("/raw/", ignoreCase = true) && url.contains("github.com", ignoreCase = true) -> {
try {
val u = URI(url)
val segs = u.path.trimStart('/').split('/', limit = 6)
if (segs.size >= 5 && segs[2].equals("raw", ignoreCase = true)) {
"https://raw.githack.com/${segs[0]}/${segs[1]}/${segs.subList(3, segs.size).joinToString("/")}"
} else url
} catch (_: Throwable) {
url
}
}
else -> url
}
} catch (_: Throwable) {
url
}
val attempts = listOf(downloadUrl, rawGithack, url).distinct()
var lastException: Throwable? = null
var downloaded = false
for (attemptUrl in attempts) {
val httpStmt = http.prepareGet(attemptUrl) {
header(HttpHeaders.CacheControl, "no-cache, no-store") header(HttpHeaders.CacheControl, "no-cache, no-store")
// Disable compression due to bug on emulators // Disable compression due to bug on emulators
@ -49,7 +82,12 @@ class KtorDownloadManager(
} }
} }
try {
httpStmt.execute { resp -> httpStmt.execute { resp ->
if (!resp.status.isSuccess()) {
throw IOException("HTTP error ${resp.status.value} for $attemptUrl")
}
val channel = resp.bodyAsChannel() val channel = resp.bodyAsChannel()
val total = resp.contentLength() ?: 0 val total = resp.contentLength() ?: 0
var retrieved = 0L var retrieved = 0L
@ -89,6 +127,23 @@ class KtorDownloadManager(
} }
} }
} }
// If we reach here, the attempt succeeded
downloaded = true
break
} catch (e: CancellationException) {
// Propagate cancellations immediately
throw e
} catch (t: Throwable) {
// Record the last exception and try the next URL (if any)
lastException = t
}
}
if (!downloaded) {
// No attempt succeeded, throw the last failure to be handled by outer catch blocks
throw lastException ?: IOException("Failed to download resource from $url")
}
} catch (_: CancellationException) { } catch (_: CancellationException) {
tmpOut.delete() tmpOut.delete()
return Result.Cancelled(systemTriggered = false) return Result.Cancelled(systemTriggered = false)
@ -107,6 +162,17 @@ class KtorDownloadManager(
return Result.Success(out) return Result.Success(out)
} }
private fun rewriteRawGithubUrl(url: String): String {
val regex = Regex("^https?://raw\\.githubusercontent\\.com/([^/]+)/([^/]+)/([^/]+)/(.*)$", RegexOption.IGNORE_CASE)
val match = regex.matchEntire(url)
return if (match != null) {
val (org, repo, branch, path) = match.destructured
"https://cdn.jsdelivr.net/gh/$org/$repo@$branch/$path"
} else {
url
}
}
/** /**
* Wrapper around an exception that occurred from invoking Ktor * Wrapper around an exception that occurred from invoking Ktor
*/ */