Taiyo: Fix token (#6045)

Fix token
This commit is contained in:
Chopper 2024-11-14 03:37:26 -03:00 committed by Draff
parent dbfe27e7a3
commit f84ec7c418
No known key found for this signature in database
GPG Key ID: E8A89F3211677653
2 changed files with 74 additions and 26 deletions

View File

@ -1,7 +1,7 @@
ext {
extName = 'Taiyō'
extClass = '.Taiyo'
extVersionCode = 2
extVersionCode = 3
isNsfw = true
}

View File

@ -1,5 +1,7 @@
package eu.kanade.tachiyomi.extension.pt.taiyo
import android.app.Application
import android.content.SharedPreferences
import eu.kanade.tachiyomi.extension.pt.taiyo.dto.AdditionalInfoDto
import eu.kanade.tachiyomi.extension.pt.taiyo.dto.ChapterListDto
import eu.kanade.tachiyomi.extension.pt.taiyo.dto.MediaChapterDto
@ -25,13 +27,19 @@ import kotlinx.serialization.json.decodeFromStream
import kotlinx.serialization.json.put
import kotlinx.serialization.json.putJsonObject
import okhttp3.HttpUrl.Companion.toHttpUrl
import okhttp3.Interceptor
import okhttp3.MediaType.Companion.toMediaType
import okhttp3.Request
import okhttp3.RequestBody.Companion.toRequestBody
import okhttp3.Response
import okhttp3.internal.http.HTTP_FORBIDDEN
import okhttp3.internal.http.HTTP_UNAUTHORIZED
import org.jsoup.nodes.Document
import org.jsoup.nodes.Element
import org.jsoup.select.Elements
import rx.Observable
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
import uy.kohesive.injekt.injectLazy
import java.text.SimpleDateFormat
import java.util.Locale
@ -47,41 +55,28 @@ class Taiyo : ParsedHttpSource() {
// The source doesn't show the title on the home page
override val supportsLatest = false
private val preferences: SharedPreferences =
Injekt.get<Application>().getSharedPreferences("source_$id", 0x0000)
private var bearerToken: String = preferences.getString(BEARER_TOKEN_PREF, "").toString()
override val client = network.client.newBuilder()
.rateLimitHost(baseUrl.toHttpUrl(), 2)
.rateLimitHost(IMG_CDN.toHttpUrl(), 2)
.addInterceptor(::authorizationInterceptor)
.build()
private val json: Json by injectLazy()
// ============================== Popular ===============================
var bearerToken = ""
override fun popularMangaRequest(page: Int): Request {
if (bearerToken.isBlank()) {
getBearerToken()
}
return searchMangaRequest(page, "", FilterList())
}
override fun popularMangaRequest(page: Int) = searchMangaRequest(page, "", FilterList())
override fun popularMangaParse(response: Response) = searchMangaParse(response)
override fun popularMangaSelector() = throw UnsupportedOperationException()
override fun popularMangaFromElement(element: Element) = throw UnsupportedOperationException()
override fun popularMangaNextPageSelector() = null
private fun getBearerToken() {
val scriptUrl = client.newCall(GET(baseUrl, headers))
.execute().asJsoup()
.selectFirst("script[src*=ee07d8437723d9f5]")
?.attr("src") ?: throw Exception("Não foi possivel localizar o token")
val script = client.newCall(GET("$baseUrl$scriptUrl", headers))
.execute().body.string()
bearerToken = TOKEN_REGEX.find(script)?.groups?.get("token")?.value
?: throw Exception("Não foi possivel extrair o token")
}
// =============================== Latest ===============================
override fun latestUpdatesRequest(page: Int) = throw UnsupportedOperationException()
override fun latestUpdatesSelector() = throw UnsupportedOperationException()
@ -128,13 +123,13 @@ class Taiyo : ParsedHttpSource() {
val requestBody = json.encodeToString(jsonObj).toRequestBody(MEDIA_TYPE)
val apiHeaders = headers.newBuilder()
.set("Authorization", "Bearer $bearerToken")
.build()
return POST("https://meilisearch.${baseUrl.substringAfterLast("/")}/multi-search", apiHeaders, requestBody)
return POST("https://meilisearch.${baseUrl.substringAfterLast("/")}/multi-search", getApiHeaders(), requestBody)
}
private fun getApiHeaders() = headers.newBuilder()
.set("Authorization", "Bearer $bearerToken")
.build()
override fun searchMangaParse(response: Response): MangasPage {
val obj = response.parseAs<SearchResultDto>()
val mangas = obj.mangas.map { item ->
@ -290,10 +285,63 @@ class Taiyo : ParsedHttpSource() {
}.onFailure { it.printStackTrace() }.getOrNull()
}
// ============================= Authorization ========================
private fun authorizationInterceptor(chain: Interceptor.Chain): Response {
val request = chain.request()
val response = chain.proceed(request)
return when (response.code) {
in arrayOf(HTTP_UNAUTHORIZED, HTTP_FORBIDDEN) -> updateTokenAndContinueRequest(request, chain)
else -> response
}
}
private fun updateTokenAndContinueRequest(request: Request, chain: Interceptor.Chain): Response {
bearerToken = getToken()
val req = request.newBuilder()
.headers(getApiHeaders())
.build()
return chain.proceed(req)
}
private fun getToken(): String {
return fetchBearerToken().also {
preferences.edit()
.putString(BEARER_TOKEN_PREF, it)
.apply()
}
}
private fun fetchBearerToken(): String {
val scripts = client.newCall(GET(baseUrl, headers))
.execute().asJsoup()
.select("script[src*=next]:not([nomodule]):not([src*=app])")
val script = getScriptContainingToken(scripts)
?: throw Exception("Não foi possivel localizar o token")
return TOKEN_REGEX.find(script)?.groups?.get("token")?.value
?: throw Exception("Não foi possivel extrair o token")
}
private fun getScriptContainingToken(scripts: Elements): String? {
val elements = scripts.toList().reversed()
for (element in elements) {
val scriptUrl = element.attr("src")
val script = client.newCall(GET("$baseUrl$scriptUrl", headers))
.execute().body.string()
if (TOKEN_REGEX.containsMatchIn(script)) {
return script
}
}
return null
}
companion object {
const val PREFIX_SEARCH = "id:"
val CHAPTER_REGEX = """(?<chapters>\{"chapters".+"totalPages":\d+\})""".toRegex()
val TOKEN_REGEX = """NEXT_PUBLIC_MEILISEARCH_PUBLIC_KEY:(\s+)?"(?<token>[^"]+)""".toRegex()
const val BEARER_TOKEN_PREF = "TAIYO_BEARER_TOKEN"
private const val IMG_CDN = "https://cdn.taiyo.moe/medias"