Updater.kt (2875B) - raw
1 package me.rhunk.snapenhance.ui.manager.data 2 3 import com.google.gson.JsonParser 4 import me.rhunk.snapenhance.common.BuildConfig 5 import me.rhunk.snapenhance.common.logger.AbstractLogger 6 import okhttp3.OkHttpClient 7 import okhttp3.Request 8 9 10 object Updater { 11 data class LatestRelease( 12 val versionName: String, 13 val releaseUrl: String 14 ) 15 16 private fun fetchLatestRelease() = runCatching { 17 val endpoint = Request.Builder().url("https://api.github.com/repos/rhunk/SnapEnhance/releases").build() 18 val response = OkHttpClient().newCall(endpoint).execute() 19 20 if (!response.isSuccessful) throw Throwable("Failed to fetch releases: ${response.code}") 21 22 val releases = JsonParser.parseString(response.body.string()).asJsonArray.also { 23 if (it.size() == 0) throw Throwable("No releases found") 24 } 25 26 val latestRelease = releases.get(0).asJsonObject 27 val latestVersion = latestRelease.getAsJsonPrimitive("tag_name").asString 28 if (latestVersion.removePrefix("v") == BuildConfig.VERSION_NAME) return@runCatching null 29 30 LatestRelease( 31 versionName = latestVersion, 32 releaseUrl = endpoint.url.toString().replace("api.", "").replace("repos/", "") 33 ) 34 }.onFailure { 35 AbstractLogger.directError("Failed to fetch latest release", it) 36 }.getOrNull() 37 38 private fun fetchLatestDebugCI() = runCatching { 39 val actionRuns = OkHttpClient().newCall(Request.Builder().url("https://api.github.com/repos/rhunk/SnapEnhance/actions/runs?event=workflow_dispatch").build()).execute().use { 40 if (!it.isSuccessful) throw Throwable("Failed to fetch CI runs: ${it.code}") 41 JsonParser.parseString(it.body.string()).asJsonObject 42 } 43 val debugRuns = actionRuns.getAsJsonArray("workflow_runs")?.mapNotNull { it.asJsonObject }?.filter { run -> 44 run.get("conclusion")?.takeIf { it.isJsonPrimitive }?.asString == "success" && run.getAsJsonPrimitive("path")?.asString == ".github/workflows/debug.yml" 45 } ?: throw Throwable("No debug CI runs found") 46 47 val latestRun = debugRuns.firstOrNull() ?: throw Throwable("No debug CI runs found") 48 val headSha = latestRun.getAsJsonPrimitive("head_sha")?.asString ?: throw Throwable("No head sha found") 49 50 if (headSha == BuildConfig.GIT_HASH) return@runCatching null 51 52 LatestRelease( 53 versionName = headSha.substring(0, headSha.length.coerceAtMost(7)) + "-debug", 54 releaseUrl = latestRun.getAsJsonPrimitive("html_url")?.asString?.replace("github.com", "nightly.link") ?: return@runCatching null 55 ) 56 }.onFailure { 57 AbstractLogger.directError("Failed to fetch latest debug CI", it) 58 }.getOrNull() 59 60 val latestRelease by lazy { 61 if (BuildConfig.DEBUG) fetchLatestDebugCI() else fetchLatestRelease() 62 } 63 }