improved geode version selection

This commit is contained in:
qimiko committed 2024-06-19 20:14:59 -07:00
1 parent a562f5ec75
commit bdce61d160
6 files changed
+118 -13

No files matched your search

@@ -4,6 +4,7 @@ import android.content.Context
import android.util.Log
import com.geode.launcher.BuildConfig
import com.geode.launcher.utils.DownloadUtils
import com.geode.launcher.utils.GamePackageUtils
import com.geode.launcher.utils.LaunchUtils
import com.geode.launcher.utils.PreferenceUtils
import kotlinx.coroutines.CancellationException
@@ -22,6 +23,9 @@ import okio.source
import java.io.File
import java.io.InterruptedIOException
private const val TAG_LATEST = "latest"
private const val TAG_BETA = "prerelease"
/**
* Singleton to manage Geode updates, from update checking to downloading.
*/
@@ -91,11 +95,36 @@ class ReleaseManager private constructor(
}
}
private fun getBestReleaseForGameVersion(): String? {
if (!GamePackageUtils.isGameInstalled(applicationContext.packageManager)) {
return null
}
val gameVersion = GamePackageUtils.getGameVersionCode(applicationContext.packageManager)
return when {
gameVersion >= 39L -> TAG_LATEST
gameVersion == 38L -> "v2.0.0-beta.27"
gameVersion == 37L -> "v2.0.0-beta.5"
else -> null
}
}
private suspend fun getLatestRelease(): Release? {
val sharedPreferences = PreferenceUtils.get(applicationContext)
val useNightly = sharedPreferences.getBoolean(PreferenceUtils.Key.RELEASE_CHANNEL)
val releaseChannel = sharedPreferences.getInt(PreferenceUtils.Key.RELEASE_CHANNEL_TAG)
return releaseRepository.getLatestGeodeRelease(useNightly)
val targetTag = when (releaseChannel) {
2 -> "nightly"
1 -> TAG_BETA
else -> getBestReleaseForGameVersion()
} ?: return null
return when (targetTag) {
TAG_LATEST -> releaseRepository.getLatestGeodeRelease()
TAG_BETA -> releaseRepository.getLatestGeodePreRelease()
else -> releaseRepository.getReleaseByTag(targetTag)
}
}
private suspend fun performUpdate(release: Release) {
@@ -32,16 +32,74 @@ class ReleaseRepository(private val httpClient: OkHttpClient) {
return getReleaseByUrl(url)
}
suspend fun getLatestGeodeRelease(isNightly: Boolean = false): Release? {
val geodeBaseUrl = "$GITHUB_API_BASE/repos/geode-sdk/geode/releases"
val releasePath = if (isNightly) "$geodeBaseUrl/tags/nightly"
else "$geodeBaseUrl/latest"
suspend fun getLatestGeodeRelease(): Release? {
val releasePath = "$GITHUB_API_BASE/repos/geode-sdk/geode/releases/latest"
val url = URL(releasePath)
return getReleaseByUrl(url)
}
suspend fun getReleaseByTag(tag: String): Release? {
val releasePath = "$GITHUB_API_BASE/repos/geode-sdk/geode/releases/tags/$tag"
val url = URL(releasePath)
return getReleaseByUrl(url)
}
@OptIn(ExperimentalSerializationApi::class)
suspend fun getLatestGeodePreRelease(): Release? {
val releasesUrl = "$GITHUB_API_BASE/repos/geode-sdk/geode/releases?per_page=2"
val url = URL(releasesUrl)
val request = Request.Builder()
.url(url)
.addHeader("Accept", "application/json")
.addHeader(GITHUB_API_HEADER, GITHUB_API_VERSION)
.build()
val call = httpClient.newCall(request)
val response = call.executeCoroutine()
return when (response.code) {
200 -> {
val format = Json {
namingStrategy = JsonNamingStrategy.SnakeCase
ignoreUnknownKeys = true
}
val release = format.decodeFromBufferedSource<List<Release>>(
response.body!!.source()
)
release.find { it.tagName != "nightly" }
}
403 -> {
// determine if the error code is a ratelimit
// (github docs say it sends 429 too, but haven't seen that)
val limitRemaining = response.headers.get(GITHUB_RATELIMIT_REMAINING)?.toInt()
val limitReset = response.headers.get(GITHUB_RATELIMIT_RESET)?.toLong()
if (limitRemaining == 0 && limitReset != null) {
// handle ratelimit with a custom error
// there's also a retry-after header but again, haven't seen
val resetTime = Instant.fromEpochSeconds(limitReset, 0L)
val msg = generateRateLimitMessage(resetTime)
throw IOException(msg)
}
throw IOException("response 403: ${response.body!!.string()}")
}
404 -> {
null
}
else -> {
throw IOException("unknown response ${response.code}")
}
}
}
private fun generateRateLimitMessage(resetTime: Instant): String {
val currentTime = Clock.System.now()
val resetDelay = currentTime.until(resetTime, DateTimeUnit.SECOND)