Fix kotlinx.serialization issue on MANGA Plus (#4775)

* Fix kotlinx.serialization issue on MANGA Plus.

* Fix typo.

* Downgrade kotlinx.serialization version to match main repo.
This commit is contained in:
Alessandro Jean 2020-11-03 15:53:51 -03:00 committed by GitHub
parent 2d3f3c1a24
commit df7978bbd9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 17 additions and 31 deletions

View File

@ -6,12 +6,12 @@ ext {
extName = 'MANGA Plus by SHUEISHA' extName = 'MANGA Plus by SHUEISHA'
pkgNameSuffix = 'all.mangaplus' pkgNameSuffix = 'all.mangaplus'
extClass = '.MangaPlusFactory' extClass = '.MangaPlusFactory'
extVersionCode = 13 extVersionCode = 14
libVersion = '1.2' libVersion = '1.2'
} }
dependencies { dependencies {
final serialization_version = '1.0.0-RC' final serialization_version = '1.0.0'
implementation "org.jetbrains.kotlinx:kotlinx-serialization-core:$serialization_version" implementation "org.jetbrains.kotlinx:kotlinx-serialization-core:$serialization_version"
implementation "org.jetbrains.kotlinx:kotlinx-serialization-protobuf:$serialization_version" implementation "org.jetbrains.kotlinx:kotlinx-serialization-protobuf:$serialization_version"
} }

View File

@ -58,7 +58,8 @@ abstract class MangaPlus(
.build() .build()
private val protobufJs: String by lazy { private val protobufJs: String by lazy {
client.newCall(GET(PROTOBUFJS_CDN, headers)).execute().body()!!.string() val request = GET(PROTOBUFJS_CDN, headers)
client.newCall(request).execute().body()!!.string()
} }
private val gson: Gson by lazy { Gson() } private val gson: Gson by lazy { Gson() }
@ -427,44 +428,35 @@ abstract class MangaPlus(
} }
private fun Response.asProto(): MangaPlusResponse { private fun Response.asProto(): MangaPlusResponse {
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.KITKAT) if (Build.VERSION.SDK_INT > Build.VERSION_CODES.M)
return ProtoBuf.decodeFromByteArray(MangaPlusSerializer, body()!!.bytes()) return ProtoBuf.decodeFromByteArray(MangaPlusSerializer, body()!!.bytes())
// Apparently, the version used of Kotlinx Serialization lib causes a crash // The kotlinx.serialization library eventually always have some issues with
// on KitKat devices (see #1678). So, if the device is running KitKat or lower, // devices with Android version below Nougat. So, if the device is running Marshmallow
// we use the old method of parsing their API -- using ProtobufJS + Duktape + Gson. // or lower, the deserialization is done using ProtobufJS + Duktape + Gson.
val bytes = body()!!.bytes() val bytes = body()!!.bytes()
val messageBytes = "var BYTE_ARR = new Uint8Array([${bytes.joinToString()}]);" val messageBytes = "var BYTE_ARR = new Uint8Array([${bytes.joinToString()}]);"
val res = Duktape.create().use { val res = Duktape.create().use {
it.set( // The current Kotlin version brokes Duktape's module feature,
"helper", // so we need to provide an workaround to prevent the usage of 'require'.
DuktapeHelper::class.java, it.evaluate("var module = { exports: true };")
object : DuktapeHelper { it.evaluate(protobufJs)
override fun getProtobuf(): String = protobufJs
}
)
it.evaluate(messageBytes + DECODE_SCRIPT) as String it.evaluate(messageBytes + DECODE_SCRIPT) as String
} }
// The Json.parse method of the Kotlinx Serialization causes the app to crash too,
// so unfortunately we have to use Gson to deserialize.
return gson.fromJson(res, MangaPlusResponse::class.java) return gson.fromJson(res, MangaPlusResponse::class.java)
} }
private interface DuktapeHelper {
@Suppress("unused")
fun getProtobuf(): String
}
companion object { companion object {
private const val API_URL = "https://jumpg-webapi.tokyo-cdn.com/api" private const val API_URL = "https://jumpg-webapi.tokyo-cdn.com/api"
private const val USER_AGENT = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.92 Safari/537.36" private const val USER_AGENT = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) " +
"AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.183 Safari/537.36"
private val HEX_GROUP = "(.{1,2})".toRegex() private val HEX_GROUP = "(.{1,2})".toRegex()
private const val PROTOBUFJS_CDN = "https://cdn.rawgit.com/dcodeIO/protobuf.js/6.8.8/dist/light/protobuf.min.js" private const val PROTOBUFJS_CDN = "https://cdn.jsdelivr.net/npm/protobufjs@6.10.1/dist/light/protobuf.js"
private const val RESOLUTION_PREF_KEY = "imageResolution" private const val RESOLUTION_PREF_KEY = "imageResolution"
private const val RESOLUTION_PREF_TITLE = "Image resolution" private const val RESOLUTION_PREF_TITLE = "Image resolution"

View File

@ -123,16 +123,10 @@ data class MangaPage(
@ProtoNumber(5) val encryptionKey: String? = null @ProtoNumber(5) val encryptionKey: String? = null
) )
// Used for the deserialization on KitKat devices. // Used for the deserialization on older devices.
const val DECODE_SCRIPT: String = const val DECODE_SCRIPT: String =
""" """
Duktape.modSearch = function(id) { var protobuf = module.exports;
if (id == "protobufjs")
return helper.getProtobuf();
throw new Error("Cannot find module: " + id);
}
var protobuf = require("protobufjs");
var Root = protobuf.Root; var Root = protobuf.Root;
var Type = protobuf.Type; var Type = protobuf.Type;