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 }