Handle 401 on Remanga

pull/6/head
Koitharu 4 years ago
parent e15dbf2a4b
commit 1ba2bba12e
No known key found for this signature in database
GPG Key ID: 8E861F8CE6E7CE27

@ -1,13 +1,16 @@
package org.koitharu.kotatsu.parsers.site
import okhttp3.Headers
import okhttp3.Response
import org.json.JSONArray
import org.json.JSONException
import org.json.JSONObject
import org.jsoup.HttpStatusException
import org.koitharu.kotatsu.parsers.MangaLoaderContext
import org.koitharu.kotatsu.parsers.MangaParser
import org.koitharu.kotatsu.parsers.MangaParserAuthProvider
import org.koitharu.kotatsu.parsers.config.ConfigKey
import org.koitharu.kotatsu.parsers.exception.AuthRequiredException
import org.koitharu.kotatsu.parsers.exception.ParseException
import org.koitharu.kotatsu.parsers.model.*
import org.koitharu.kotatsu.parsers.util.*
@ -15,6 +18,7 @@ import org.koitharu.kotatsu.parsers.util.json.getStringOrNull
import org.koitharu.kotatsu.parsers.util.json.mapJSON
import org.koitharu.kotatsu.parsers.util.json.mapJSONTo
import org.koitharu.kotatsu.parsers.util.json.mapJSONToSet
import java.net.HttpURLConnection
import java.net.URLDecoder
import java.text.DateFormat
import java.text.SimpleDateFormat
@ -109,10 +113,12 @@ internal class RemangaParser(
val domain = getDomain()
val slug = manga.url.find(regexLastUrlPath)
?: throw ParseException("Cannot obtain slug from ${manga.url}")
val data = context.httpGet(
val data = catch401 {
context.httpGet(
url = "https://api.$domain/api/titles/$slug/",
headers = getApiHeaders(),
).parseJson()
)
}.parseJson()
val content = try {
data.getJSONObject("content")
} catch (e: JSONException) {
@ -166,7 +172,9 @@ internal class RemangaParser(
override suspend fun getPages(chapter: MangaChapter): List<MangaPage> {
val referer = "https://${getDomain()}/"
val content = context.httpGet(chapter.url.withDomain(subdomain = "api"), getApiHeaders()).parseJson()
val content = catch401 {
context.httpGet(chapter.url.withDomain(subdomain = "api"), getApiHeaders())
}.parseJson()
.getJSONObject("content")
val pages = content.optJSONArray("pages")
if (pages == null) {
@ -205,10 +213,12 @@ internal class RemangaParser(
}
override suspend fun getUsername(): String {
val jo = context.httpGet(
val jo = catch401 {
context.httpGet(
url = "https://api.${getDomain()}/api/users/current/",
headers = getApiHeaders(),
).parseJson()
)
}.parseJson()
return jo.getJSONObject("content").getString("username")
}
@ -246,10 +256,12 @@ internal class RemangaParser(
val result = ArrayList<JSONObject>(100)
var page = 1
while (true) {
val content = context.httpGet(
val content = catch401 {
context.httpGet(
url = "https://api.$domain/api/titles/chapters/?branch_id=$branchId&page=$page&count=100",
headers = getApiHeaders(),
).parseJson().getJSONArray("content")
)
}.parseJson().getJSONArray("content")
val len = content.length()
if (len == 0) {
break
@ -262,4 +274,14 @@ internal class RemangaParser(
}
return result
}
private inline fun catch401(block: () -> Response): Response = try {
block()
} catch (e: HttpStatusException) {
if (e.statusCode == HttpURLConnection.HTTP_UNAUTHORIZED) {
throw AuthRequiredException(source)
} else {
throw e
}
}
}

@ -0,0 +1,36 @@
package org.koitharu.kotatsu.parsers.util
import kotlinx.coroutines.CancellableContinuation
import kotlinx.coroutines.CompletionHandler
import okhttp3.Call
import okhttp3.Callback
import okhttp3.Response
import java.io.IOException
import kotlin.coroutines.resume
import kotlin.coroutines.resumeWithException
internal class ContinuationCallCallback(
private val call: Call,
private val continuation: CancellableContinuation<Response>,
) : Callback, CompletionHandler {
override fun onResponse(call: Call, response: Response) {
if (continuation.isActive) {
continuation.resume(response)
}
}
override fun onFailure(call: Call, e: IOException) {
if (!call.isCanceled() && continuation.isActive) {
continuation.resumeWithException(e)
}
}
override fun invoke(cause: Throwable?) {
runCatching {
call.cancel()
}.onFailure { e ->
cause?.addSuppressed(e)
}
}
}

@ -2,31 +2,12 @@ package org.koitharu.kotatsu.parsers.util
import kotlinx.coroutines.suspendCancellableCoroutine
import okhttp3.Call
import okhttp3.Callback
import okhttp3.Response
import java.io.IOException
import kotlin.coroutines.resume
import kotlin.coroutines.resumeWithException
suspend fun Call.await() = suspendCancellableCoroutine<Response> { cont ->
this.enqueue(
object : Callback {
override fun onFailure(call: Call, e: IOException) {
if (cont.isActive) {
cont.resumeWithException(e)
}
}
override fun onResponse(call: Call, response: Response) {
if (cont.isActive) {
cont.resume(response)
}
}
},
)
cont.invokeOnCancellation {
this.cancel()
}
suspend fun Call.await(): Response = suspendCancellableCoroutine { continuation ->
val callback = ContinuationCallCallback(this, continuation)
enqueue(callback)
continuation.invokeOnCancellation(callback)
}
val Response.mimeType: String?

Loading…
Cancel
Save