Roumanwu: chapter upload date logic and cleanup (#12169)
This commit is contained in:
parent
4ed2c3d31e
commit
cff72ef4ce
|
@ -6,7 +6,7 @@ ext {
|
||||||
extName = 'Roumanwu'
|
extName = 'Roumanwu'
|
||||||
pkgNameSuffix = 'zh.roumanwu'
|
pkgNameSuffix = 'zh.roumanwu'
|
||||||
extClass = '.Roumanwu'
|
extClass = '.Roumanwu'
|
||||||
extVersionCode = 1
|
extVersionCode = 2
|
||||||
isNsfw = true
|
isNsfw = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,6 +12,7 @@ import eu.kanade.tachiyomi.source.online.HttpSource
|
||||||
import eu.kanade.tachiyomi.util.asJsoup
|
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.decodeFromStream
|
||||||
import okhttp3.Response
|
import okhttp3.Response
|
||||||
import uy.kohesive.injekt.Injekt
|
import uy.kohesive.injekt.Injekt
|
||||||
import uy.kohesive.injekt.api.get
|
import uy.kohesive.injekt.api.get
|
||||||
|
@ -23,15 +24,14 @@ class Roumanwu : HttpSource(), ConfigurableSource {
|
||||||
override val lang = "zh"
|
override val lang = "zh"
|
||||||
override val supportsLatest = true
|
override val supportsLatest = true
|
||||||
|
|
||||||
private val preferences: SharedPreferences by lazy {
|
private val preferences: SharedPreferences =
|
||||||
Injekt.get<Application>().getSharedPreferences("source_$id", 0x0000)
|
Injekt.get<Application>().getSharedPreferences("source_$id", 0x0000)
|
||||||
}
|
|
||||||
|
|
||||||
override val baseUrl = MIRRORS[
|
override val baseUrl = MIRRORS[
|
||||||
max(MIRRORS.size - 1, preferences.getString(MIRROR_PREF, MIRROR_DEFAULT)!!.toInt())
|
max(MIRRORS.size - 1, preferences.getString(MIRROR_PREF, MIRROR_DEFAULT)!!.toInt())
|
||||||
]
|
]
|
||||||
|
|
||||||
override val client = network.client.newBuilder().addInterceptor(ScrambledImageInterceptor()).build()
|
override val client = network.client.newBuilder().addInterceptor(ScrambledImageInterceptor).build()
|
||||||
|
|
||||||
private val json: Json by injectLazy()
|
private val json: Json by injectLazy()
|
||||||
|
|
||||||
|
@ -60,9 +60,10 @@ class Roumanwu : HttpSource(), ConfigurableSource {
|
||||||
return if (chapter.images != null) {
|
return if (chapter.images != null) {
|
||||||
chapter.getPageList()
|
chapter.getPageList()
|
||||||
} else {
|
} else {
|
||||||
|
@Suppress("NAME_SHADOWING")
|
||||||
val response = client.newCall(GET(baseUrl + chapter.chapterAPIPath!!, headers)).execute()
|
val response = client.newCall(GET(baseUrl + chapter.chapterAPIPath!!, headers)).execute()
|
||||||
if (!response.isSuccessful) throw Exception("服务器错误: ${response.code}")
|
if (!response.isSuccessful) throw Exception("服务器错误: ${response.code}")
|
||||||
json.decodeFromString<ChapterWrapper>(response.body!!.string()).chapter.getPageList()
|
response.parseAs<ChapterWrapper>().chapter.getPageList()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -125,6 +126,8 @@ class Roumanwu : HttpSource(), ConfigurableSource {
|
||||||
private val TAGS = arrayOf("全部", "正妹", "恋爱", "出版漫画", "肉慾", "浪漫", "大尺度", "巨乳", "有夫之婦", "女大生", "狗血劇", "同居", "好友", "調教", "动作", "後宮", "不倫")
|
private val TAGS = arrayOf("全部", "正妹", "恋爱", "出版漫画", "肉慾", "浪漫", "大尺度", "巨乳", "有夫之婦", "女大生", "狗血劇", "同居", "好友", "調教", "动作", "後宮", "不倫")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private inline fun <reified T> Response.parseAs(): T = json.decodeFromStream(this.body!!.byteStream())
|
||||||
|
|
||||||
private inline fun <reified T> Response.nextjsData() =
|
private inline fun <reified T> Response.nextjsData() =
|
||||||
json.decodeFromString<NextData<T>>(this.asJsoup().select("#__NEXT_DATA__").html()).props.pageProps
|
json.decodeFromString<NextData<T>>(this.asJsoup().select("#__NEXT_DATA__").html()).props.pageProps
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,13 @@
|
||||||
package eu.kanade.tachiyomi.extension.zh.roumanwu
|
package eu.kanade.tachiyomi.extension.zh.roumanwu
|
||||||
|
|
||||||
|
import eu.kanade.tachiyomi.AppInfo
|
||||||
import eu.kanade.tachiyomi.source.model.MangasPage
|
import eu.kanade.tachiyomi.source.model.MangasPage
|
||||||
import eu.kanade.tachiyomi.source.model.Page
|
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 kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
|
import java.text.SimpleDateFormat
|
||||||
|
import java.util.Locale
|
||||||
import java.util.UUID
|
import java.util.UUID
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
|
@ -23,7 +26,7 @@ data class Book(
|
||||||
val author: String,
|
val author: String,
|
||||||
val continued: Boolean,
|
val continued: Boolean,
|
||||||
val tags: List<String>,
|
val tags: List<String>,
|
||||||
val updatedAt: String? = null, // TODO: 2022-06-02T00:00:00.000Z
|
val updatedAt: String? = null,
|
||||||
val activeResource: Resource? = null,
|
val activeResource: Resource? = null,
|
||||||
) {
|
) {
|
||||||
fun toSManga() = SManga.create().apply {
|
fun toSManga() = SManga.create().apply {
|
||||||
|
@ -42,11 +45,26 @@ data class Book(
|
||||||
url = "/books/$id/$i"
|
url = "/books/$id/$i"
|
||||||
name = it
|
name = it
|
||||||
}
|
}
|
||||||
|
}.apply {
|
||||||
|
if (isNewDateLogic && !updatedAt.isNullOrBlank()) {
|
||||||
|
this[lastIndex].date_upload = DATE_FORMAT.parse(updatedAt)?.time ?: 0L
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private val uuid by lazy { UUID.fromString(id) }
|
private val uuid by lazy { UUID.fromString(id) }
|
||||||
override fun hashCode() = uuid.hashCode()
|
override fun hashCode() = uuid.hashCode()
|
||||||
override fun equals(other: Any?) = other is Book && uuid == other.uuid
|
override fun equals(other: Any?) = other is Book && uuid == other.uuid
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private val DATE_FORMAT = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.ENGLISH)
|
||||||
|
private val isNewDateLogic = run {
|
||||||
|
val commitCount = AppInfo.getVersionName().substringAfter('-', "")
|
||||||
|
if (commitCount.isNotEmpty()) // Preview
|
||||||
|
commitCount.toInt() >= 4442
|
||||||
|
else // Stable
|
||||||
|
AppInfo.getVersionCode() >= 81
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
|
@ -81,7 +99,7 @@ data class Chapter(
|
||||||
val chapterAPIPath: String? = null,
|
val chapterAPIPath: String? = null,
|
||||||
) {
|
) {
|
||||||
fun getPageList() = images!!.mapIndexed { i, it ->
|
fun getPageList() = images!!.mapIndexed { i, it ->
|
||||||
Page(i, imageUrl = it.src + if (it.scramble) SCRAMBLED_SUFFIX else "")
|
Page(i, imageUrl = it.src + if (it.scramble) ScrambledImageInterceptor.SCRAMBLED_SUFFIX else "")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -90,5 +108,3 @@ data class ChapterWrapper(val chapter: Chapter)
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
data class Image(val src: String, val scramble: Boolean)
|
data class Image(val src: String, val scramble: Boolean)
|
||||||
|
|
||||||
const val SCRAMBLED_SUFFIX = "?scrambled"
|
|
||||||
|
|
|
@ -12,7 +12,7 @@ import okhttp3.ResponseBody.Companion.toResponseBody
|
||||||
import java.io.ByteArrayOutputStream
|
import java.io.ByteArrayOutputStream
|
||||||
import java.security.MessageDigest
|
import java.security.MessageDigest
|
||||||
|
|
||||||
class ScrambledImageInterceptor : Interceptor {
|
object ScrambledImageInterceptor : Interceptor {
|
||||||
override fun intercept(chain: Interceptor.Chain): Response {
|
override fun intercept(chain: Interceptor.Chain): Response {
|
||||||
val request = chain.request()
|
val request = chain.request()
|
||||||
val response = chain.proceed(request)
|
val response = chain.proceed(request)
|
||||||
|
@ -48,8 +48,7 @@ class ScrambledImageInterceptor : Interceptor {
|
||||||
return response.newBuilder().body(responseBody).build()
|
return response.newBuilder().body(responseBody).build()
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
private val jpegMediaType = "image/jpeg".toMediaType()
|
||||||
private val jpegMediaType = "image/jpeg".toMediaType()
|
private fun Byte.toPositiveInt() = toInt() and 0xFF
|
||||||
private fun Byte.toPositiveInt() = toInt() and 0xFF
|
const val SCRAMBLED_SUFFIX = "#scrambled"
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue