Fix GitHub authorization and clean up code

This commit is contained in:
FooIbar committed 2024-08-07 18:37:51 +08:00
1 parent b1afe9bcd1
commit fded0fd08d
20 files changed
+33 -125

No files matched your search

@@ -55,11 +55,12 @@ import com.hippo.ehviewer.dailycheck.showEventNotification
import com.hippo.ehviewer.dailycheck.today
import com.hippo.ehviewer.util.AppConfig
import com.hippo.ehviewer.util.ReadableTime
import com.hippo.ehviewer.util.StatusCodeException
import com.hippo.ehviewer.util.bodyAsUtf8Text
import com.hippo.ehviewer.util.ensureSuccess
import eu.kanade.tachiyomi.util.system.logcat
import io.ktor.client.statement.HttpStatement
import io.ktor.client.statement.bodyAsChannel
import io.ktor.http.HttpStatusCode
import io.ktor.utils.io.pool.DirectByteBufferPool
import io.ktor.utils.io.pool.useInstance
import java.io.File
@@ -96,7 +97,7 @@ fun Either<String, ByteBuffer>.saveParseError(e: Throwable) {
}
}
fun rethrowExactly(code: Int, body: Either<String, ByteBuffer>, e: Throwable): Nothing {
fun rethrowExactly(status: HttpStatusCode, body: Either<String, ByteBuffer>, e: Throwable): Nothing {
// Don't translate coroutine cancellation
if (e is CancellationException) throw e
@@ -124,9 +125,7 @@ fun rethrowExactly(code: Int, body: Either<String, ByteBuffer>, e: Throwable): N
}
// Check bad response code
if (code >= 400) {
throw StatusCodeException(code)
}
status.ensureSuccess()
if (e is ParseException || e is SerializationException) {
body.onLeft { if ("<" !in it) throw EhException(it) }
@@ -151,7 +150,7 @@ suspend inline fun <T> HttpStatement.fetchUsingAsText(crossinline block: suspend
runSuspendCatching {
block(body)
}.onFailure {
rethrowExactly(response.status.value, body.left(), it)
rethrowExactly(response.status, body.left(), it)
}.getOrThrow()
}
@@ -163,7 +162,7 @@ suspend inline fun <T> HttpStatement.fetchUsingAsByteBuffer(crossinline block: s
block(buffer)
}.onFailure {
buffer.rewind()
rethrowExactly(response.status.value, buffer.right(), it)
rethrowExactly(response.status, buffer.right(), it)
}.getOrThrow()
}
}
@@ -20,6 +20,7 @@ import com.hippo.ehviewer.EhApplication.Companion.ktorClient
import com.hippo.ehviewer.EhApplication.Companion.noRedirectKtorClient
import com.hippo.ehviewer.Settings
import com.hippo.ehviewer.util.bodyAsUtf8Text
import com.hippo.ehviewer.util.ensureSuccess
import eu.kanade.tachiyomi.util.system.logcat
import io.ktor.client.request.HttpRequestBuilder
import io.ktor.client.request.forms.FormDataContent
@@ -45,7 +46,11 @@ import okio.BufferedSource
inline fun JsonObjectBuilder.array(name: String, builder: JsonArrayBuilder.() -> Unit) = put(name, buildJsonArray(builder))
suspend inline fun <reified T> HttpStatement.executeAndParseAs() = executeSafely { it.bodyAsUtf8Text().parseAs<T>() }
suspend inline fun <reified T> HttpStatement.executeAndParseAs() = executeSafely {
it.status.ensureSuccess()
it.bodyAsUtf8Text().parseAs<T>()
}
inline fun <reified T> BufferedSource.parseAs(): T = json.decodeFromBufferedSource(this)
inline fun <reified T> String.parseAs(): T = json.decodeFromString(this)
@@ -24,14 +24,13 @@ import com.hippo.ehviewer.R
import com.hippo.ehviewer.client.data.TagNamespace
import com.hippo.ehviewer.util.AppConfig
import com.hippo.ehviewer.util.FileUtils
import com.hippo.ehviewer.util.StatusCodeException
import com.hippo.ehviewer.util.copyTo
import com.hippo.ehviewer.util.ensureSuccess
import com.hippo.ehviewer.util.sha1
import eu.kanade.tachiyomi.util.system.logcat
import io.ktor.client.HttpClient
import io.ktor.client.request.prepareGet
import io.ktor.client.statement.bodyAsChannel
import io.ktor.http.isSuccess
import java.io.File
import java.nio.charset.StandardCharsets
import kotlinx.coroutines.CoroutineScope
@@ -143,11 +142,8 @@ object EhTagDatabase : CoroutineScope {
private suspend fun save(client: HttpClient, url: String, file: File) {
runCatching {
client.prepareGet(url).executeSafely {
if (it.status.isSuccess()) {
it.bodyAsChannel().copyTo(file)
} else {
throw StatusCodeException(it.status.value)
}
it.status.ensureSuccess()
it.bodyAsChannel().copyTo(file)
}
}.onFailure {
file.delete()
@@ -6,10 +6,10 @@ import com.hippo.ehviewer.Settings
import com.hippo.ehviewer.client.executeAndParseAs
import com.hippo.ehviewer.client.executeSafely
import com.hippo.ehviewer.util.copyTo
import com.hippo.ehviewer.util.ensureSuccess
import io.ktor.client.request.header
import io.ktor.client.request.prepareGet
import io.ktor.client.statement.bodyAsChannel
import io.ktor.client.statement.bodyAsText
import io.ktor.utils.io.jvm.javaio.toInputStream
import java.io.File
import java.util.zip.ZipInputStream
@@ -17,10 +17,10 @@ import kotlin.time.Duration.Companion.days
import kotlinx.datetime.Clock
import kotlinx.datetime.Instant
import moe.tarsin.coroutines.runSuspendCatching
import org.json.JSONObject
import tachiyomi.data.release.GithubArtifacts
import tachiyomi.data.release.GithubCommitComparison
import tachiyomi.data.release.GithubRelease
import tachiyomi.data.release.GithubRepo
import tachiyomi.data.release.GithubWorkflowRuns
private const val API_URL = "https://api.github.com/repos/${BuildConfig.REPO_NAME}"
@@ -35,7 +35,7 @@ object AppUpdater {
Settings.lastUpdateTime = now.epochSeconds
if (Settings.useCIUpdateChannel) {
val curSha = BuildConfig.COMMIT_SHA
val branch = ghStatement(API_URL).executeSafely { JSONObject(it.bodyAsText()).getString("default_branch") }
val branch = ghStatement(API_URL).executeAndParseAs<GithubRepo>().defaultBranch
val workflowRunsUrl = "$API_URL/actions/workflows/ci.yml/runs?branch=$branch&event=push&status=success&per_page=1"
val workflowRun = ghStatement(workflowRunsUrl).executeAndParseAs<GithubWorkflowRuns>().workflowRuns[0]
val shortSha = workflowRun.headSha.take(7)
@@ -68,6 +68,7 @@ object AppUpdater {
suspend fun downloadUpdate(url: String, file: File) =
ghStatement(url).executeSafely { response ->
response.status.ensureSuccess()
if (url.endsWith("zip")) {
response.bodyAsChannel().toInputStream().use { stream ->
ZipInputStream(stream).use { zip ->
@@ -84,14 +85,14 @@ object AppUpdater {
}
private suspend inline fun ghStatement(url: String) = ktorClient.prepareGet(url) {
header("Authorization", GithubTokenParts.joinToString("_"))
header("Authorization", GithubTokenParts.joinToString("_", prefix = "Bearer "))
}
private val GithubTokenParts = arrayOf(
"github",
"pat",
"11A4H2ACI04oacouUsibSx",
"QYqH5WhdRjJUSmezj3vex9sQLZC8vSrL4VXPxDcwfhcWLQFH6H3L0tDYupr",
"11A4H2ACI0XXTRsYkt1Mps",
"uJ5n8UbLv20j6Ue4k1x25Z7u63EaCdDNYooxSeI4GJaQYKXWDZEtTmDVwnh",
)
data class Release(
@@ -39,12 +39,6 @@ private fun getReadableStringInternal(e: Throwable) = when (e) {
is MalformedURLException -> appCtx.getString(R.string.error_invalid_url)
is SocketTimeoutException -> appCtx.getString(R.string.error_timeout)
is UnknownHostException -> appCtx.getString(R.string.error_unknown_host)
is StatusCodeException -> buildString {
append(appCtx.getString(R.string.error_bad_status_code, e.responseCode))
if (e.isIdentifiedResponseCode) {
append(", ").append(e.message)
}
}
is ProtocolException -> if (e.message!!.startsWith("Too many follow-up requests:")) {
appCtx.getString(R.string.error_redirection)
} else {
@@ -2,6 +2,8 @@ package com.hippo.ehviewer.util
import io.ktor.client.call.body
import io.ktor.client.statement.HttpResponse
import io.ktor.http.HttpStatusCode
import io.ktor.http.isSuccess
import io.ktor.utils.io.charsets.decode
import io.ktor.utils.io.core.ByteReadPacket
import java.nio.charset.CodingErrorAction
@@ -15,3 +17,7 @@ suspend fun HttpResponse.bodyAsUtf8Text(): String {
return decoder.decode(input)
}
fun HttpStatusCode.ensureSuccess() {
if (!isSuccess()) throw Exception(toString())
}
@@ -1,62 +0,0 @@
/*
* Copyright 2016 Hippo Seven
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.hippo.ehviewer.util
import android.util.SparseArray
import com.hippo.ehviewer.R
import splitties.init.appCtx
class StatusCodeException(val responseCode: Int) : Exception() {
override val message: String = ERROR_MESSAGE_ARRAY[responseCode, DEFAULT_ERROR_MESSAGE]
val isIdentifiedResponseCode: Boolean
get() = DEFAULT_ERROR_MESSAGE != message
override fun getLocalizedMessage(): String = message
companion object {
private val ERROR_MESSAGE_ARRAY = SparseArray<String>(24)
private const val DEFAULT_ERROR_MESSAGE = "Error response code"
init {
val resources = appCtx.resources
ERROR_MESSAGE_ARRAY.append(400, resources.getString(R.string.error_status_code_400))
ERROR_MESSAGE_ARRAY.append(401, resources.getString(R.string.error_status_code_401))
ERROR_MESSAGE_ARRAY.append(402, resources.getString(R.string.error_status_code_402))
ERROR_MESSAGE_ARRAY.append(403, resources.getString(R.string.error_status_code_403))
ERROR_MESSAGE_ARRAY.append(404, resources.getString(R.string.error_status_code_404))
ERROR_MESSAGE_ARRAY.append(405, resources.getString(R.string.error_status_code_405))
ERROR_MESSAGE_ARRAY.append(406, resources.getString(R.string.error_status_code_406))
ERROR_MESSAGE_ARRAY.append(407, resources.getString(R.string.error_status_code_407))
ERROR_MESSAGE_ARRAY.append(408, resources.getString(R.string.error_status_code_408))
ERROR_MESSAGE_ARRAY.append(409, resources.getString(R.string.error_status_code_409))
ERROR_MESSAGE_ARRAY.append(410, resources.getString(R.string.error_status_code_410))
ERROR_MESSAGE_ARRAY.append(411, resources.getString(R.string.error_status_code_411))
ERROR_MESSAGE_ARRAY.append(412, resources.getString(R.string.error_status_code_412))
ERROR_MESSAGE_ARRAY.append(413, resources.getString(R.string.error_status_code_413))
ERROR_MESSAGE_ARRAY.append(414, resources.getString(R.string.error_status_code_414))
ERROR_MESSAGE_ARRAY.append(415, resources.getString(R.string.error_status_code_415))
ERROR_MESSAGE_ARRAY.append(416, resources.getString(R.string.error_status_code_416))
ERROR_MESSAGE_ARRAY.append(417, resources.getString(R.string.error_status_code_417))
ERROR_MESSAGE_ARRAY.append(500, resources.getString(R.string.error_status_code_500))
ERROR_MESSAGE_ARRAY.append(501, resources.getString(R.string.error_status_code_501))
ERROR_MESSAGE_ARRAY.append(502, resources.getString(R.string.error_status_code_502))
ERROR_MESSAGE_ARRAY.append(503, resources.getString(R.string.error_status_code_503))
ERROR_MESSAGE_ARRAY.append(504, resources.getString(R.string.error_status_code_504))
ERROR_MESSAGE_ARRAY.append(505, resources.getString(R.string.error_status_code_505))
}
}
}
@@ -4,6 +4,11 @@ import com.hippo.ehviewer.util.AppConfig
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
@Serializable
data class GithubRepo(
@SerialName("default_branch") val defaultBranch: String,
)
@Serializable
data class GithubWorkflowRuns(
@SerialName("workflow_runs") val workflowRuns: List<GithubWorkflowRun>,
-1
View File
@@ -32,7 +32,6 @@
<string name="text_is_empty">Der Text wird nicht eingegeben</string>
<string name="waring">Achtung</string>
<string name="invalid_download_location">Der Downloadpfad ist nicht verfügbar. Geh zu die Einstellungen und stelle einen neue Pfad fest.</string>
<string name="error_bad_status_code">Inkorrekter Statuscode: %d</string>
<string name="error_timeout">Timeout</string>
<string name="error_unknown_host">Unbekannter Hostcomputer</string>
<string name="error_redirection">Zu viele Umleitungen</string>
-1
View File
@@ -39,7 +39,6 @@
<string name="invalid_download_location">Parece que la ubicación de descarga no está disponible. Establece la ubicación en Configuración.</string>
<string name="error_bad_status_code">Bad status code: %d</string>
<string name="error_timeout">Sin tiempo</string>
<string name="error_unknown_host">Host desconocido</string>
<string name="error_redirection">Demasiadas redirecciones</string>
-1
View File
@@ -39,7 +39,6 @@
<string name="invalid_download_location">La location de téléchargement actuelle n\'est pas disponible. Choissez-en une à nouveau dans les Paramétres.</string>
<string name="error_bad_status_code">Code d\'état inconnu : %d</string>
<string name="error_timeout">Time-out</string>
<string name="error_unknown_host">Hôte inconnu</string>
<string name="error_redirection">Trop de redirections</string>
-1
View File
@@ -37,7 +37,6 @@
<string name="invalid_download_location">ダウンロードパスは現在利用できません。ダウンロードパスを設定してください。</string>
<string name="error_bad_status_code">無効なステータスコード:%d</string>
<string name="error_timeout">タイムアウト</string>
<string name="error_unknown_host">不明なホスト</string>
<string name="error_redirection">リダイレクトが多すぎます</string>
-1
View File
@@ -41,7 +41,6 @@
<string name="clipboard_gallery_url_snack_message">클립보드에 갤러리 주소가 있습니다.</string>
<string name="clipboard_gallery_url_snack_action">보기</string>
<string name="error_bad_status_code">비정상 상태 코드: %d</string>
<string name="error_timeout">시간 초과</string>
<string name="error_unknown_host">알 수 없는 호스트</string>
<string name="error_redirection">너무 많은 서버 리디렉션</string>
@@ -3,7 +3,6 @@
<string name="text_is_empty">Tekst tom</string>
<string name="waring">Advarsel</string>
<string name="clipboard_gallery_url_snack_action">Vis</string>
<string name="error_bad_status_code">Feil statuskode: %d</string>
<string name="error_timeout">Tidsavbrudd</string>
<string name="error_unknown_host">Ukjent vert</string>
<string name="error_redirection">For mange videresendinger</string>
-1
View File
@@ -41,7 +41,6 @@
<string name="clipboard_gallery_url_snack_message">มีลิงค์ของเว็บแกลเลอรี่อยู่ในคลิปบอร์ด</string>
<string name="clipboard_gallery_url_snack_action">ดู</string>
<string name="error_bad_status_code">รหัสข้อผิดพลาด: %d</string>
<string name="error_timeout">หมดเวลา</string>
<string name="error_unknown_host">ไม่รู้จักโฮสต์</string>
<string name="error_redirection">มีการเปลี่ยนทางเยอะเกินไป</string>
-1
View File
@@ -64,7 +64,6 @@
<string name="image_search_not_quick_search">Görsel arama, hızlı arama olarak eklenemez</string>
<string name="duplicate_name">Ad zaten kullanımda.</string>
<string name="text_is_empty">Yazı boş</string>
<string name="error_bad_status_code">Kötü durum kodu: %d</string>
<string name="error_unknown_host">Bilinmeyen host</string>
<string name="app_waring">Bu uygulamadaki içerikler internetten alınmaktadır. Bazı içerikler fiziksel veya zihinsel olarak size zararlı gelebilir.Yukarıda, riskleri öğrendiniz ve üstleneceksiniz.
\nKullanmaya devam ederek, yukarıdaki koşulları kabul edersiniz.</string>
@@ -33,7 +33,6 @@
<string name="invalid_download_location">似乎下载路径不可用。请到重新设置下载路径。</string>
<string name="clipboard_gallery_url_snack_message">剪切板里有画廊链接</string>
<string name="clipboard_gallery_url_snack_action">查看</string>
<string name="error_bad_status_code">错误状态码:%d</string>
<string name="error_timeout">超时</string>
<string name="error_unknown_host">未知主机</string>
<string name="error_redirection">太多重定向</string>
@@ -42,7 +42,6 @@
<string name="clipboard_gallery_url_snack_message">剪切板裏有畫廊鏈接</string>
<string name="clipboard_gallery_url_snack_action">查看</string>
<string name="error_bad_status_code">錯誤狀態碼:%d</string>
<string name="error_timeout">超時</string>
<string name="error_unknown_host">未知主機</string>
<string name="error_redirection">太多重定向</string>
@@ -33,7 +33,6 @@
<string name="invalid_download_location">看來下載路徑似乎沒辦法使用。請至設定重新設定下載路徑。</string>
<string name="clipboard_gallery_url_snack_message">剪貼簿裡有圖庫連結</string>
<string name="clipboard_gallery_url_snack_action">檢視</string>
<string name="error_bad_status_code">錯誤狀態碼:%d</string>
<string name="error_timeout">逾時</string>
<string name="error_unknown_host">未知的主機</string>
<string name="error_redirection">重新導向迴圈</string>
-25
View File
@@ -47,31 +47,6 @@
<string name="invalid_download_location">It seems download location is not available. Please set it in Settings.</string>
<string name="clipboard_gallery_url_snack_message">There is a gallery URL in the clipboard</string>
<string name="clipboard_gallery_url_snack_action">View</string>
<string name="error_status_code_400" translatable="false">Bad Request</string>
<string name="error_status_code_401" translatable="false">Unauthorized</string>
<string name="error_status_code_402" translatable="false">Payment Required</string>
<string name="error_status_code_403" translatable="false">Forbidden</string>
<string name="error_status_code_404" translatable="false">Not Found</string>
<string name="error_status_code_405" translatable="false">Method Not Allowed</string>
<string name="error_status_code_406" translatable="false">Not Acceptable</string>
<string name="error_status_code_407" translatable="false">Proxy Authentication Required</string>
<string name="error_status_code_408" translatable="false">Request Timeout</string>
<string name="error_status_code_409" translatable="false">Conflict</string>
<string name="error_status_code_410" translatable="false">Gone</string>
<string name="error_status_code_411" translatable="false">Length Required</string>
<string name="error_status_code_412" translatable="false">Precondition Failed</string>
<string name="error_status_code_413" translatable="false">Request Entity Too Large</string>
<string name="error_status_code_414" translatable="false">Request-URI Too Long</string>
<string name="error_status_code_415" translatable="false">Unsupported Media Type</string>
<string name="error_status_code_416" translatable="false">Requested Range Not Satisfiable</string>
<string name="error_status_code_417" translatable="false">Expectation Failed</string>
<string name="error_status_code_500" translatable="false">Internal Server Error</string>
<string name="error_status_code_501" translatable="false">Not Implemented</string>
<string name="error_status_code_502" translatable="false">Bad Gateway</string>
<string name="error_status_code_503" translatable="false">Service Unavailable</string>
<string name="error_status_code_504" translatable="false">Gateway Timeout</string>
<string name="error_status_code_505" translatable="false">HTTP Version Not Supported</string>
<string name="error_bad_status_code">Bad status code: %d</string>
<string name="error_timeout">Timeout</string>
<string name="error_unknown_host">Unknown host</string>
<string name="error_redirection">Too many redirections</string>