PixivComic: Use salt from chapter page (#6561)

This commit is contained in:
AlphaBoom 2024-12-10 22:28:10 +08:00 committed by Draff
parent 3a05d381e5
commit 3ecfb8529c
No known key found for this signature in database
GPG Key ID: E8A89F3211677653
3 changed files with 15 additions and 10 deletions

View File

@ -1,7 +1,7 @@
ext { ext {
extName = 'Pixiv Comic' extName = 'Pixiv Comic'
extClass = '.PixivComic' extClass = '.PixivComic'
extVersionCode = 2 extVersionCode = 3
} }
apply from: "$rootDir/common.gradle" apply from: "$rootDir/common.gradle"

View File

@ -8,8 +8,12 @@ import eu.kanade.tachiyomi.source.model.Page
import eu.kanade.tachiyomi.source.model.SChapter import eu.kanade.tachiyomi.source.model.SChapter
import eu.kanade.tachiyomi.source.model.SManga import eu.kanade.tachiyomi.source.model.SManga
import eu.kanade.tachiyomi.source.online.HttpSource import eu.kanade.tachiyomi.source.online.HttpSource
import eu.kanade.tachiyomi.util.asJsoup
import kotlinx.serialization.decodeFromString import kotlinx.serialization.decodeFromString
import kotlinx.serialization.json.Json import kotlinx.serialization.json.Json
import kotlinx.serialization.json.JsonElement
import kotlinx.serialization.json.jsonObject
import kotlinx.serialization.json.jsonPrimitive
import okhttp3.HttpUrl import okhttp3.HttpUrl
import okhttp3.HttpUrl.Companion.toHttpUrl import okhttp3.HttpUrl.Companion.toHttpUrl
import okhttp3.Request import okhttp3.Request
@ -39,10 +43,6 @@ class PixivComic : HttpSource() {
randomString() randomString()
} }
private val timeAndHash by lazy {
getTimeAndHash()
}
override val client = network.cloudflareClient.newBuilder() override val client = network.cloudflareClient.newBuilder()
.addInterceptor(ShuffledImageInterceptor(key)) .addInterceptor(ShuffledImageInterceptor(key))
.addNetworkInterceptor(::tagInterceptor) .addNetworkInterceptor(::tagInterceptor)
@ -244,12 +244,17 @@ class PixivComic : HttpSource() {
} }
override fun pageListRequest(chapter: SChapter): Request { override fun pageListRequest(chapter: SChapter): Request {
val doc = client.newCall(GET(getChapterUrl(chapter), headers)).execute().asJsoup()
val salt = doc.selectFirst("script#__NEXT_DATA__")!!.data().let {
json.decodeFromString<JsonElement>(it).jsonObject["props"]!!.jsonObject["pageProps"]!!
.jsonObject["salt"]!!.jsonPrimitive.content
}
val url = apiBuilder() val url = apiBuilder()
.addPathSegment("episodes") .addPathSegment("episodes")
.addPathSegment(chapter.url) .addPathSegment(chapter.url)
.addPathSegment("read_v4") .addPathSegment("read_v4")
.build() .build()
val timeAndHash = getTimeAndHash(salt)
val header = headers.newBuilder() val header = headers.newBuilder()
.add("X-Client-Time", timeAndHash.first) .add("X-Client-Time", timeAndHash.first)
.add("X-Client-Hash", timeAndHash.second) .add("X-Client-Hash", timeAndHash.second)

View File

@ -1,5 +1,6 @@
package eu.kanade.tachiyomi.extension.ja.pixivcomic package eu.kanade.tachiyomi.extension.ja.pixivcomic
import android.annotation.SuppressLint
import android.os.Build import android.os.Build
import okhttp3.Interceptor import okhttp3.Interceptor
import okhttp3.Response import okhttp3.Response
@ -10,8 +11,6 @@ import java.util.Locale
import java.util.TimeZone import java.util.TimeZone
import kotlin.math.abs import kotlin.math.abs
private const val TIME_SALT = "M7w5HORvvX-VP4tRj2CFQOQFPocBqLvHTIbhTU36UCo"
private class NoSuchTagException(message: String) : Exception(message) private class NoSuchTagException(message: String) : Exception(message)
internal fun tagInterceptor(chain: Interceptor.Chain): Response { internal fun tagInterceptor(chain: Interceptor.Chain): Response {
@ -38,7 +37,7 @@ internal fun randomString(): String {
} }
@OptIn(ExperimentalUnsignedTypes::class) @OptIn(ExperimentalUnsignedTypes::class)
internal fun getTimeAndHash(): Pair<String, String> { internal fun getTimeAndHash(salt: String): Pair<String, String> {
val timeFormatted = if (Build.VERSION.SDK_INT < 24) { val timeFormatted = if (Build.VERSION.SDK_INT < 24) {
SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss", Locale.ENGLISH).format(Date()) SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss", Locale.ENGLISH).format(Date())
.plus(getCurrentTimeZoneOffsetString()) .plus(getCurrentTimeZoneOffsetString())
@ -46,7 +45,7 @@ internal fun getTimeAndHash(): Pair<String, String> {
SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX", Locale.ENGLISH).format(Date()) SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX", Locale.ENGLISH).format(Date())
} }
val saltedTimeArray = timeFormatted.plus(TIME_SALT).toByteArray() val saltedTimeArray = timeFormatted.plus(salt).toByteArray()
val saltedTimeHash = MessageDigest.getInstance("SHA-256") val saltedTimeHash = MessageDigest.getInstance("SHA-256")
.digest(saltedTimeArray).toUByteArray() .digest(saltedTimeArray).toUByteArray()
val hexadecimalTimeHash = saltedTimeHash.joinToString("") { val hexadecimalTimeHash = saltedTimeHash.joinToString("") {
@ -63,6 +62,7 @@ internal fun getTimeAndHash(): Pair<String, String> {
/** /**
* workaround to retrieve time zone offset for android with version lower than 24 * workaround to retrieve time zone offset for android with version lower than 24
*/ */
@SuppressLint("DefaultLocale")
private fun getCurrentTimeZoneOffsetString(): String { private fun getCurrentTimeZoneOffsetString(): String {
val timeZone = TimeZone.getDefault() val timeZone = TimeZone.getDefault()
val offsetInMillis = timeZone.rawOffset val offsetInMillis = timeZone.rawOffset