feat(lib): Stole (Js)Unpacker lib from tachiyomi-extensions repo (#1551)
This commit is contained in:
8
lib/unpacker/build.gradle.kts
Normal file
8
lib/unpacker/build.gradle.kts
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
plugins {
|
||||||
|
`java-library`
|
||||||
|
kotlin("jvm")
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
compileOnly(libs.kotlin.stdlib)
|
||||||
|
}
|
@ -0,0 +1,42 @@
|
|||||||
|
package eu.kanade.tachiyomi.lib.unpacker
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (C) The Tachiyomi Open Source Project
|
||||||
|
*
|
||||||
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A helper class to extract substrings efficiently.
|
||||||
|
*
|
||||||
|
* Note that all methods move [startIndex] over the ending delimiter.
|
||||||
|
*/
|
||||||
|
class SubstringExtractor(private val text: String) {
|
||||||
|
private var startIndex = 0
|
||||||
|
|
||||||
|
fun skipOver(str: String) {
|
||||||
|
val index = text.indexOf(str, startIndex)
|
||||||
|
if (index == -1) return
|
||||||
|
startIndex = index + str.length
|
||||||
|
}
|
||||||
|
|
||||||
|
fun substringBefore(str: String): String {
|
||||||
|
val index = text.indexOf(str, startIndex)
|
||||||
|
if (index == -1) return ""
|
||||||
|
val result = text.substring(startIndex, index)
|
||||||
|
startIndex = index + str.length
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
fun substringBetween(left: String, right: String): String {
|
||||||
|
val index = text.indexOf(left, startIndex)
|
||||||
|
if (index == -1) return ""
|
||||||
|
val leftIndex = index + left.length
|
||||||
|
val rightIndex = text.indexOf(right, leftIndex)
|
||||||
|
if (rightIndex == -1) return ""
|
||||||
|
startIndex = rightIndex + right.length
|
||||||
|
return text.substring(leftIndex, rightIndex)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,84 @@
|
|||||||
|
package eu.kanade.tachiyomi.lib.unpacker
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (C) The Tachiyomi Open Source Project
|
||||||
|
*
|
||||||
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper class to unpack JavaScript code compressed by [packer](http://dean.edwards.name/packer/).
|
||||||
|
*
|
||||||
|
* Source code of packer can be found [here](https://github.com/evanw/packer/blob/master/packer.js).
|
||||||
|
*/
|
||||||
|
object Unpacker {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unpacks JavaScript code compressed by packer.
|
||||||
|
*
|
||||||
|
* Specify [left] and [right] to unpack only the data between them.
|
||||||
|
*
|
||||||
|
* Note: single quotes `\'` in the data will be replaced with double quotes `"`.
|
||||||
|
*/
|
||||||
|
fun unpack(script: String, left: String? = null, right: String? = null): String =
|
||||||
|
unpack(SubstringExtractor(script), left, right)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unpacks JavaScript code compressed by packer.
|
||||||
|
*
|
||||||
|
* Specify [left] and [right] to unpack only the data between them.
|
||||||
|
*
|
||||||
|
* Note: single quotes `\'` in the data will be replaced with double quotes `"`.
|
||||||
|
*/
|
||||||
|
fun unpack(script: SubstringExtractor, left: String? = null, right: String? = null): String {
|
||||||
|
val packed = script
|
||||||
|
.substringBetween("}('", ".split('|'),0,{}))")
|
||||||
|
.replace("\\'", "\"")
|
||||||
|
|
||||||
|
val parser = SubstringExtractor(packed)
|
||||||
|
val data: String
|
||||||
|
if (left != null && right != null) {
|
||||||
|
data = parser.substringBetween(left, right)
|
||||||
|
parser.skipOver("',")
|
||||||
|
} else {
|
||||||
|
data = parser.substringBefore("',")
|
||||||
|
}
|
||||||
|
if (data.isEmpty()) return ""
|
||||||
|
|
||||||
|
val dictionary = parser.substringBetween("'", "'").split("|")
|
||||||
|
val size = dictionary.size
|
||||||
|
|
||||||
|
return wordRegex.replace(data) {
|
||||||
|
val key = it.value
|
||||||
|
val index = parseRadix62(key)
|
||||||
|
if (index >= size) return@replace key
|
||||||
|
dictionary[index].ifEmpty { key }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private val wordRegex by lazy { Regex("""\w+""") }
|
||||||
|
|
||||||
|
private fun parseRadix62(str: String): Int {
|
||||||
|
var result = 0
|
||||||
|
for (ch in str.toCharArray()) {
|
||||||
|
result = result * 62 + when {
|
||||||
|
ch.code <= '9'.code -> { // 0-9
|
||||||
|
ch.code - '0'.code
|
||||||
|
}
|
||||||
|
|
||||||
|
ch.code >= 'a'.code -> { // a-z
|
||||||
|
// ch - 'a' + 10
|
||||||
|
ch.code - ('a'.code - 10)
|
||||||
|
}
|
||||||
|
|
||||||
|
else -> { // A-Z
|
||||||
|
// ch - 'A' + 36
|
||||||
|
ch.code - ('A'.code - 36)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
}
|
Reference in New Issue
Block a user