Introduce <T> Request.executeAndParseAs()

This commit is contained in:
FooIbar authored and tarsin committed 2023-07-06 06:22:46 +08:00
1 parent 5a6a01f813
commit ca21b5e713
4 files changed
+83 -20

No files matched your search

@@ -21,10 +21,12 @@ import com.hippo.ehviewer.EhApplication.Companion.okHttpClient
import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.launch
import kotlinx.coroutines.suspendCancellableCoroutine
import kotlinx.serialization.json.Json
import kotlinx.serialization.json.JsonArrayBuilder
import kotlinx.serialization.json.JsonObjectBuilder
import kotlinx.serialization.json.buildJsonArray
import kotlinx.serialization.json.buildJsonObject
import kotlinx.serialization.json.okio.decodeFromBufferedSource
import okhttp3.Call
import okhttp3.FormBody
import okhttp3.MediaType
@@ -103,6 +105,12 @@ suspend inline fun <R> Call.usingCancellable(crossinline block: suspend Response
suspend inline fun <R> Request.execute(block: Response.() -> R) = okHttpClient.newCall(this).executeAsync().use(block)
suspend inline fun <R> Request.executeNonCache(crossinline block: suspend Response.() -> R) = nonCacheOkHttpClient.newCall(this).usingCancellable(block)
suspend inline fun <reified T> Request.executeAndParseAs() = execute { parseAs<T>() }
inline fun <reified T> Response.parseAs(): T = json.decodeFromBufferedSource(body.source())
val json = Json { ignoreUnknownKeys = true }
const val CHROME_USER_AGENT = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36"
const val CHROME_ACCEPT = "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9"
const val CHROME_ACCEPT_LANGUAGE = "en-US,en;q=0.5"
@@ -30,6 +30,7 @@ import com.hippo.ehviewer.BuildConfig
import com.hippo.ehviewer.R
import com.hippo.ehviewer.Settings
import com.hippo.ehviewer.client.execute
import com.hippo.ehviewer.client.executeAndParseAs
import com.hippo.ehviewer.ui.LICENSE_SCREEN
import com.hippo.ehviewer.ui.LocalNavController
import com.hippo.ehviewer.ui.tools.DialogState
@@ -37,7 +38,6 @@ import com.hippo.ehviewer.ui.tools.rememberDialogState
import com.hippo.ehviewer.ui.tools.toAnnotatedString
import com.hippo.ehviewer.util.ExceptionUtils
import com.hippo.ehviewer.util.installPackage
import com.hippo.ehviewer.util.iter
import eu.kanade.tachiyomi.util.lang.withUIContext
import eu.kanade.tachiyomi.util.system.logcat
import io.ktor.util.encodeBase64
@@ -47,6 +47,9 @@ import moe.tarsin.coroutines.runSuspendCatching
import okhttp3.Request
import okio.sink
import org.json.JSONObject
import tachiyomi.data.release.GithubArtifacts
import tachiyomi.data.release.GithubRelease
import tachiyomi.data.release.GithubWorkflowRuns
import java.io.File
import java.util.zip.ZipInputStream
@@ -146,21 +149,15 @@ fun AboutScreen() {
val branch = ghRequest(API_URL).execute {
JSONObject(body.string()).getString("default_branch")
}
val branchUrl = "$API_URL/branches/$branch"
val commitSha = ghRequest(branchUrl).execute {
JSONObject(body.string()).getJSONObject("commit").getString("sha")
}
val shortSha = commitSha.take(7)
val workflowRunsUrl = "$API_URL/actions/workflows/ci.yml/runs?branch=$branch&per_page=1"
val workflowRun = ghRequest(workflowRunsUrl).executeAndParseAs<GithubWorkflowRuns>().workflowRuns[0]
val shortSha = workflowRun.headSha.take(7)
if (shortSha != curSha) {
val archiveUrl = ghRequest("$API_URL/actions/artifacts").execute {
JSONObject(body.string()).getJSONArray("artifacts").iter<JSONObject>().find {
val wf = it.getJSONObject("workflow_run")
it.getString("name").startsWith("arm64-v8a") && wf.getString("head_sha") == commitSha
}
}?.getString("archive_download_url")
if (archiveUrl != null) {
val artifacts = ghRequest(workflowRun.artifactsUrl).executeAndParseAs<GithubArtifacts>()
if (artifacts.artifacts.isNotEmpty()) {
val archiveUrl = artifacts.getDownloadLink()
// TODO: Show changelog
dialogState.showNewVersion(shortSha, "") { file ->
dialogState.showNewVersion(shortSha, workflowRun.title) { file ->
ghRequest(archiveUrl).execute {
ZipInputStream(body.byteStream()).use { zip ->
zip.nextEntry
@@ -179,12 +176,10 @@ fun AboutScreen() {
} else {
val curVersion = BuildConfig.VERSION_NAME
val releaseUrl = "$API_URL/releases/latest"
val release = ghRequest(releaseUrl).execute {
JSONObject(body.string())
}
val latestVersion = release.getString("name")
val description = release.getString("body")
val downloadUrl = (release.getJSONArray("assets")[0] as JSONObject).getString("browser_download_url")
val release = ghRequest(releaseUrl).executeAndParseAs<GithubRelease>()
val latestVersion = release.version
val description = release.info
val downloadUrl = release.getDownloadLink()
if (latestVersion != curVersion) {
dialogState.showNewVersion(latestVersion, description) { file ->
ghRequest(downloadUrl).execute {
@@ -0,0 +1,27 @@
package tachiyomi.data.release
import android.os.Build
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
/**
* Contains information about the latest release from GitHub.
*/
@Serializable
data class GithubRelease(
@SerialName("tag_name") val version: String,
@SerialName("body") val info: String,
@SerialName("html_url") val releaseLink: String,
@SerialName("assets") val assets: List<GitHubAssets>,
) {
fun getDownloadLink(): String {
val apkVariant = Build.SUPPORTED_ABIS[0]
return (assets.find { it.downloadLink.contains(apkVariant) } ?: assets.find { it.downloadLink.contains("universal") } ?: assets[0]).downloadLink
}
}
/**
* Assets class containing download url.
*/
@Serializable
data class GitHubAssets(@SerialName("browser_download_url") val downloadLink: String)
@@ -0,0 +1,33 @@
package tachiyomi.data.release
import android.os.Build
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
@Serializable
data class GithubWorkflowRuns(
@SerialName("workflow_runs") val workflowRuns: List<GithubWorkflowRun>,
)
@Serializable
data class GithubWorkflowRun(
@SerialName("head_sha") val headSha: String,
@SerialName("display_title") val title: String,
@SerialName("artifacts_url") val artifactsUrl: String,
)
@Serializable
data class GithubArtifacts(
@SerialName("artifacts") val artifacts: List<GithubArtifact>,
) {
fun getDownloadLink(): String {
val apkVariant = Build.SUPPORTED_ABIS[0]
return (artifacts.find { it.name.contains(apkVariant) } ?: artifacts[0]).downloadLink
}
}
@Serializable
data class GithubArtifact(
val name: String,
@SerialName("archive_download_url") val downloadLink: String,
)