Update check update logic

This commit is contained in:
topjohnwu 2025-06-04 12:50:19 -07:00
parent 0e86d4dbcb
commit 83426f7f36
2 changed files with 41 additions and 19 deletions

View File

@ -38,18 +38,13 @@ data class ReleaseAssets(
@Json(name = "browser_download_url") val url: String,
)
@Retention(AnnotationRetention.RUNTIME)
@JsonQualifier
annotation class DateTime
class DateTimeAdapter {
@ToJson
fun toJson(@DateTime date: LocalDateTime): String {
fun toJson(date: LocalDateTime): String {
return date.toString()
}
@FromJson
@DateTime
fun fromJson(date: String): LocalDateTime {
return LocalDateTime.parse(date, ISO_OFFSET_DATE_TIME)
}
@ -62,5 +57,13 @@ data class Release(
val prerelease: Boolean,
val assets: List<ReleaseAssets>,
val body: String,
@Json(name = "created_at") @DateTime val createdTime: LocalDateTime,
)
@Json(name = "created_at") val createdTime: LocalDateTime,
) {
val versionCode: Int get() {
return if (tag[0] == 'v') {
(tag.drop(1).toFloat() * 1000).toInt()
} else {
tag.drop(7).toInt()
}
}
}

View File

@ -11,6 +11,7 @@ import com.topjohnwu.magisk.core.Info
import com.topjohnwu.magisk.core.data.GithubApiServices
import com.topjohnwu.magisk.core.data.RawUrl
import com.topjohnwu.magisk.core.model.Release
import com.topjohnwu.magisk.core.model.ReleaseAssets
import com.topjohnwu.magisk.core.model.UpdateInfo
import retrofit2.HttpException
import timber.log.Timber
@ -44,6 +45,8 @@ class NetworkService(
while (true) {
val response = api.fetchReleases(page = page)
val releases = response.body() ?: throw HttpException(response)
// Remove all non Magisk releases
releases.removeAll { it.tag[0] != 'v' && !it.tag.startsWith("canary") }
// Make sure it's sorted correctly
releases.sortByDescending { it.createdTime }
releases.find(predicate)?.let { return it }
@ -55,35 +58,51 @@ class NetworkService(
}
}
private fun Release.asPublicInfo(): UpdateInfo {
suspend fun fetchUpdate(version: Int) = findRelease { it.versionCode == version }?.asInfo()
private inline fun Release.asInfo(
selector: (ReleaseAssets) -> Boolean = {
// Default selector picks the non-debug APK
it.name.run { endsWith(".apk") && !contains("debug") }
}): UpdateInfo {
return if (tag[0] == 'v') asPublicInfo(selector)
else asCanaryInfo(selector)
}
private inline fun Release.asPublicInfo(selector: (ReleaseAssets) -> Boolean): UpdateInfo {
val version = tag.drop(1)
val date = createdTime.format(DateTimeFormatter.ofPattern("yyyy.M.d"))
return UpdateInfo(
version = version,
versionCode = (version.toFloat() * 1000).toInt(),
link = assets[0].url,
versionCode = versionCode,
link = assets.find(selector)!!.url,
note = "## $date $name\n\n$body"
)
}
private fun Release.asCanaryInfo(assetSelector: String): UpdateInfo {
private inline fun Release.asCanaryInfo(selector: (ReleaseAssets) -> Boolean): UpdateInfo {
return UpdateInfo(
version = name.substring(8, 16),
versionCode = tag.drop(7).toInt(),
link = assets.find { it.name == assetSelector }!!.url,
versionCode = versionCode,
link = assets.find(selector)!!.url,
note = "## $name\n\n$body"
)
}
private suspend fun fetchStableUpdate() = api.fetchLatestRelease().asPublicInfo()
// Version number: canary == debug >= beta >= stable
private suspend fun fetchBetaUpdate() = findRelease { it.tag[0] == 'v' }!!.asPublicInfo()
// Find the latest non-prerelease
private suspend fun fetchStableUpdate() = api.fetchLatestRelease().asInfo()
private suspend fun fetchCanary() = findRelease { it.tag.startsWith("canary-") }!!
// Find the latest non-canary release
private suspend fun fetchBetaUpdate() = findRelease { it.tag[0] == 'v' }!!.asInfo()
private suspend fun fetchCanaryUpdate() = fetchCanary().asCanaryInfo("app-release.apk")
// Find the latest release, regardless whether it's prerelease
private suspend fun fetchCanary() = findRelease { true }!!
private suspend fun fetchDebugUpdate() = fetchCanary().asCanaryInfo("app-debug.apk")
private suspend fun fetchCanaryUpdate() = fetchCanary().asInfo()
private suspend fun fetchDebugUpdate() = fetchCanary().asInfo { it.name == "app-debug.apk" }
private suspend fun fetchCustomUpdate(url: String): UpdateInfo {
val info = raw.fetchUpdateJson(url).magisk