PixivComic: Use salt from chapter page (#6561)
This commit is contained in:
		
							parent
							
								
									3a05d381e5
								
							
						
					
					
						commit
						3ecfb8529c
					
				| @ -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" | ||||||
|  | |||||||
| @ -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) | ||||||
|  | |||||||
| @ -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 | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 AlphaBoom
						AlphaBoom