Skip to content

Commit

Permalink
9anime: automatic keys
Browse files Browse the repository at this point in the history
  • Loading branch information
jmir1 committed Aug 12, 2022
1 parent 263ad88 commit 589bde3
Show file tree
Hide file tree
Showing 3 changed files with 93 additions and 6 deletions.
6 changes: 5 additions & 1 deletion src/en/nineanime/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,12 @@ ext {
extName = '9anime'
pkgNameSuffix = 'en.nineanime'
extClass = '.NineAnime'
extVersionCode = 20
extVersionCode = 21
libVersion = '13'
}

dependencies {
compileOnly libs.bundles.coroutines
}

apply from: "$rootDir/common.gradle"
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package eu.kanade.tachiyomi.animeextension.en.nineanime

import app.cash.quickjs.QuickJs
import kotlinx.serialization.decodeFromString
import kotlinx.serialization.json.Json
import kotlinx.serialization.json.JsonObject
import kotlinx.serialization.json.jsonPrimitive

const val fallbackcipherKey = "xtbmecCv4faAOSLV"
const val fallbackdecipherKey = "hlPeNwkncH0fq9so"

fun getKeys(allJsScript: String, json: Json): Pair<String, String> {
val quickJs = QuickJs.create()
val keys = try {
val scriptResult = quickJs.evaluate(finderScript(allJsScript)).toString()
val returnObject = json.decodeFromString<JsonObject>(scriptResult)
val cipherKey = returnObject["cipher"]!!.jsonPrimitive.content
val decipherKey = returnObject["decipher"]!!.jsonPrimitive.content
Pair(cipherKey, decipherKey)
} catch (t: Throwable) {
Pair(fallbackcipherKey, fallbackdecipherKey)
}
quickJs.close()
return keys
}

private fun finderScript(script: String) = """
let secret0 = "";
let secret1 = "";
const script = String.raw`$script`;
const prefix = `$prefix`;
var newscript = prefix + script;
const fn_regex = /or(?=:function\(.*?\) {var \w=.*?return .;})/gm
let fn_name = script.match(fn_regex);
const regex = RegExp(String.raw`(?<=this\["${'$'}{fn_name}"]\().+?(?=,)`, "gm");
let res = [...script.matchAll(regex)];
for (var index of [1,0]) {
let match = res[index][0];
let varnames = match.split("+");
for (var varnameindex = 0; varnameindex < varnames.length; varnameindex++) {
let varname = varnames[varnameindex];
let search = `${'$'}{varname}=`;
// variables are declared on line 2
let line2index = script.indexOf("\n") + prefix.length;
let line2 = newscript.substring(line2index + 1);
let i = line2index + line2.indexOf(search) + search.length;
let after = newscript.substring(i + 1);
let j = after.indexOf(";") + i + 1;
let before = newscript.substring(0, j + 1);
let after_semicolon = newscript.substring(j + 1);
newscript = before + `secret${'$'}{index}=${'$'}{res[index][0]};` + after_semicolon;
}
};
try { eval(newscript); } catch(e) {}
let return_object = {cipher: secret0, decipher: secret1};
JSON.stringify(return_object);
"""

private const val prefix = """const document = { documentElement: {} };
const jQuery = function () { return { off: function () { return { on: function(e) { return { on: function() { return { on: function() { return { on: function() { return { on: function() { return { }; } }; } }; } }; } }; } }; }, ready: function (e) {} } };
jQuery.fn = { dropdown: {}, extend: {} };
const window = { fn: { extend: {} } };
const navigator = {};
const setTimeout = {};
const clearTimeout = {};
const setInterval = {};
const clearInterval = {};
"""
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,14 @@ import eu.kanade.tachiyomi.animesource.model.Video
import eu.kanade.tachiyomi.animesource.online.ParsedAnimeHttpSource
import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.util.asJsoup
import kotlinx.serialization.ExperimentalSerializationApi
import kotlinx.coroutines.runBlocking
import kotlinx.serialization.decodeFromString
import kotlinx.serialization.json.Json
import kotlinx.serialization.json.JsonObject
import kotlinx.serialization.json.jsonArray
import kotlinx.serialization.json.jsonObject
import kotlinx.serialization.json.jsonPrimitive
import okhttp3.CacheControl
import okhttp3.Headers
import okhttp3.HttpUrl.Companion.toHttpUrl
import okhttp3.OkHttpClient
Expand All @@ -31,7 +32,6 @@ import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
import uy.kohesive.injekt.injectLazy

@ExperimentalSerializationApi
class NineAnime : ConfigurableAnimeSource, ParsedAnimeHttpSource() {

override val name = "9anime"
Expand Down Expand Up @@ -372,9 +372,23 @@ class NineAnime : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
private fun encode(input: String): String = java.net.URLEncoder.encode(input, "utf-8").replace("+", "%20")

private fun decode(input: String): String = java.net.URLDecoder.decode(input, "utf-8")

private val cipherKey: String
private val decipherKey: String

init {
val allJsScript = runBlocking {
client.newCall(
GET(
url = "https://s2.bunnycdn.ru/assets/_9anime/min/all.js",
cache = CacheControl.FORCE_NETWORK
)
).execute().body!!.string()
}
val keys = getKeys(allJsScript, json)
cipherKey = keys.first
decipherKey = keys.second
}
}

private const val nineAnimeKey = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
private const val cipherKey = "Ml6DEBjOkhWXxXg4"
private const val decipherKey = "hlPeNwkncH0fq9so"
// will implement the new algorithm soon (TM)

0 comments on commit 589bde3

Please sign in to comment.