GocTruyenTranhVui: Allows getting token for login in webview (#10887)
* GocTruyenTranhVui: Allows to get token. Support login Instead of always saving tokens in code. * Lines 118 to 143 move to getToken(), and not use postDelayed * Support enter token manually Support Suwayomi users who can't log in can still enter token manually
This commit is contained in:
parent
5ef2e36997
commit
a4c4090301
@ -1,7 +1,7 @@
|
||||
ext {
|
||||
extName = 'Goc Truyen Tranh Vui'
|
||||
extClass = '.GocTruyenTranhVui'
|
||||
extVersionCode = 3
|
||||
extVersionCode = 4
|
||||
isNsfw = true
|
||||
}
|
||||
|
||||
|
||||
@ -1,8 +1,18 @@
|
||||
package eu.kanade.tachiyomi.extension.vi.goctruyentranhvui
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.app.Application
|
||||
import android.content.SharedPreferences
|
||||
import android.os.Handler
|
||||
import android.os.Looper
|
||||
import android.webkit.WebView
|
||||
import android.webkit.WebViewClient
|
||||
import androidx.preference.EditTextPreference
|
||||
import androidx.preference.PreferenceScreen
|
||||
import eu.kanade.tachiyomi.network.GET
|
||||
import eu.kanade.tachiyomi.network.POST
|
||||
import eu.kanade.tachiyomi.network.interceptor.rateLimit
|
||||
import eu.kanade.tachiyomi.source.ConfigurableSource
|
||||
import eu.kanade.tachiyomi.source.model.FilterList
|
||||
import eu.kanade.tachiyomi.source.model.MangasPage
|
||||
import eu.kanade.tachiyomi.source.model.Page
|
||||
@ -10,6 +20,7 @@ import eu.kanade.tachiyomi.source.model.SChapter
|
||||
import eu.kanade.tachiyomi.source.model.SManga
|
||||
import eu.kanade.tachiyomi.source.online.HttpSource
|
||||
import eu.kanade.tachiyomi.util.asJsoup
|
||||
import keiyoushi.utils.getPreferences
|
||||
import keiyoushi.utils.parseAs
|
||||
import okhttp3.FormBody
|
||||
import okhttp3.Headers
|
||||
@ -17,8 +28,12 @@ import okhttp3.HttpUrl.Companion.toHttpUrl
|
||||
import okhttp3.OkHttpClient
|
||||
import okhttp3.Request
|
||||
import okhttp3.Response
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
import java.util.concurrent.CountDownLatch
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
class GocTruyenTranhVui : HttpSource() {
|
||||
class GocTruyenTranhVui : HttpSource(), ConfigurableSource {
|
||||
override val lang = "vi"
|
||||
|
||||
override val baseUrl = "https://goctruyentranhvui17.com"
|
||||
@ -29,6 +44,8 @@ class GocTruyenTranhVui : HttpSource() {
|
||||
|
||||
override val supportsLatest: Boolean = true
|
||||
|
||||
private val preferences: SharedPreferences = getPreferences()
|
||||
|
||||
override val client: OkHttpClient = network.cloudflareClient.newBuilder()
|
||||
.rateLimit(3)
|
||||
.build()
|
||||
@ -76,12 +93,12 @@ class GocTruyenTranhVui : HttpSource() {
|
||||
|
||||
override fun mangaDetailsParse(response: Response): SManga = SManga.create().apply {
|
||||
val document = response.asJsoup()
|
||||
title = document.selectFirst(".v-card-title")!!.text()
|
||||
title = document.select(".v-card-title").text()
|
||||
genre = document.select(".group-content > .v-chip-link").joinToString { it.text() }
|
||||
thumbnail_url = document.selectFirst("img.image")!!.absUrl("src")
|
||||
status = parseStatus(document.selectFirst(".mb-1:contains(Trạng thái:) span")!!.text())
|
||||
author = document.selectFirst(".mb-1:contains(Tác giả:) span")!!.text()
|
||||
description = document.selectFirst(".v-card-text")!!.text()
|
||||
thumbnail_url = document.selectFirst("img.image")?.absUrl("src")
|
||||
status = parseStatus(document.selectFirst(".mb-1:contains(Trạng thái:) span")?.text())
|
||||
author = document.selectFirst(".mb-1:contains(Tác giả:) span")?.text()
|
||||
description = document.select(".v-card-text").joinToString { it.wholeText() }
|
||||
}
|
||||
|
||||
private fun parseStatus(status: String?) = when {
|
||||
@ -103,8 +120,11 @@ class GocTruyenTranhVui : HttpSource() {
|
||||
val mangaId = matchId.groups[1]!!.value
|
||||
val nameEn = response.request.url.toString().substringAfter("/truyen/").substringBefore("/")
|
||||
val chapterNumber = response.request.url.toString().substringAfterLast("chuong-")
|
||||
val body = FormBody.Builder().add("comicId", mangaId)
|
||||
.add("chapterNumber", chapterNumber).add("nameEn", nameEn).build()
|
||||
val body = FormBody.Builder()
|
||||
.add("comicId", mangaId)
|
||||
.add("chapterNumber", chapterNumber)
|
||||
.add("nameEn", nameEn)
|
||||
.build()
|
||||
val request = POST("$baseUrl/api/chapter/auth", pageHeaders, body)
|
||||
client.newCall(request).execute().parseAs<ResultDto<ImageListDto>>().result.data
|
||||
} else {
|
||||
@ -116,10 +136,49 @@ class GocTruyenTranhVui : HttpSource() {
|
||||
}
|
||||
}
|
||||
private val pageHeaders by lazy {
|
||||
headersBuilder()
|
||||
.add("X-Requested-With", "XMLHttpRequest")
|
||||
.add("Authorization", TOKEN_KEY)
|
||||
.build()
|
||||
getToken()?.let {
|
||||
headersBuilder()
|
||||
.add("X-Requested-With", "XMLHttpRequest")
|
||||
.add("Authorization", it)
|
||||
.build()
|
||||
} ?: throw Exception("Vui lòng đăng nhập trong WebView")
|
||||
}
|
||||
private var _token: String? = null
|
||||
|
||||
@SuppressLint("SetJavaScriptEnabled")
|
||||
private fun getToken(): String? {
|
||||
_token?.also { return it }
|
||||
val handler = Handler(Looper.getMainLooper())
|
||||
val latch = CountDownLatch(1)
|
||||
val customToken = preferences.getString("custom_token", null)
|
||||
if (!customToken.isNullOrBlank()) {
|
||||
return customToken
|
||||
}
|
||||
if (_token != null) return _token
|
||||
|
||||
handler.post {
|
||||
val webview = WebView(Injekt.get<Application>())
|
||||
with(webview.settings) {
|
||||
javaScriptEnabled = true
|
||||
domStorageEnabled = true
|
||||
databaseEnabled = true
|
||||
blockNetworkImage = true
|
||||
}
|
||||
webview.webViewClient = object : WebViewClient() {
|
||||
override fun onPageFinished(view: WebView?, url: String?) {
|
||||
// Get token
|
||||
view!!.evaluateJavascript("window.localStorage.getItem('Authorization')") { token ->
|
||||
_token = token.takeUnless { it == "null" }?.removeSurrounding("\"")
|
||||
latch.countDown()
|
||||
webview.destroy()
|
||||
}
|
||||
}
|
||||
}
|
||||
webview.loadDataWithBaseURL(baseUrl, " ", "text/html", "UTF-8", null)
|
||||
}
|
||||
|
||||
latch.await(10, TimeUnit.SECONDS)
|
||||
return _token
|
||||
}
|
||||
|
||||
override fun imageUrlParse(response: Response): String = throw UnsupportedOperationException()
|
||||
@ -150,5 +209,15 @@ class GocTruyenTranhVui : HttpSource() {
|
||||
SortByList(getSortByList()),
|
||||
GenreList(getGenreList()),
|
||||
)
|
||||
|
||||
override fun setupPreferenceScreen(screen: PreferenceScreen) {
|
||||
val tokenPref = EditTextPreference(screen.context).apply {
|
||||
key = "custom_token"
|
||||
title = "Authorization Token"
|
||||
summary = "Enter token manually"
|
||||
dialogTitle = "Authorization Token"
|
||||
dialogMessage = "Token: ${getToken()}"
|
||||
}
|
||||
screen.addPreference(tokenPref)
|
||||
}
|
||||
}
|
||||
private const val TOKEN_KEY = "Bearer eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJEcmFrZW4iLCJjb21pY0lkcyI6W10sInJvbGVJZCI6bnVsbCwiZ3JvdXBJZCI6bnVsbCwiYWRtaW4iOmZhbHNlLCJyYW5rIjowLCJwZXJtaXNzaW9uIjpbXSwiaWQiOiIwMDAxMTE1OTg2IiwidGVhbSI6ZmFsc2UsImlhdCI6MTc1NzU5NjQxMSwiZW1haWwiOiJudWxsIn0.VcGDaVQvyowtvja04CTUpfCP5XiC5qIdPmANZL0Gjz2kjz__PJ8LATQ9s44FpNohMpgLgPQO0TVs67D_YFlLNw"
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user