mirror of
https://github.com/recloudstream/cloudstream.git
synced 2024-08-15 01:53:11 +00:00
Ported more files for multiplatform (#1056)
This commit is contained in:
parent
af828de8d5
commit
4d5cd288ab
12 changed files with 243 additions and 141 deletions
|
@ -0,0 +1,11 @@
|
|||
package com.lagradost.cloudstream3.utils
|
||||
|
||||
import android.os.Handler
|
||||
import android.os.Looper
|
||||
|
||||
actual fun runOnMainThreadNative(work: () -> Unit) {
|
||||
val mainHandler = Handler(Looper.getMainLooper())
|
||||
mainHandler.post {
|
||||
work()
|
||||
}
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
package com.lagradost.cloudstream3
|
||||
|
||||
import com.fasterxml.jackson.databind.DeserializationFeature
|
||||
import com.fasterxml.jackson.databind.ObjectMapper
|
||||
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
|
||||
import com.lagradost.nicehttp.Requests
|
||||
import com.lagradost.nicehttp.ResponseParser
|
||||
import kotlin.reflect.KClass
|
||||
|
||||
// Short name for requests client to make it nicer to use
|
||||
|
||||
var app = Requests(responseParser = object : ResponseParser {
|
||||
val mapper: ObjectMapper = jacksonObjectMapper().configure(
|
||||
DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES,
|
||||
false
|
||||
)
|
||||
|
||||
override fun <T : Any> parse(text: String, kClass: KClass<T>): T {
|
||||
return mapper.readValue(text, kClass.java)
|
||||
}
|
||||
|
||||
override fun <T : Any> parseSafe(text: String, kClass: KClass<T>): T? {
|
||||
return try {
|
||||
mapper.readValue(text, kClass.java)
|
||||
} catch (e: Exception) {
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
override fun writeValueAsString(obj: Any): String {
|
||||
return mapper.writeValueAsString(obj)
|
||||
}
|
||||
}).apply {
|
||||
defaultHeaders = mapOf("user-agent" to USER_AGENT)
|
||||
}
|
|
@ -1,3 +1,6 @@
|
|||
package com.lagradost.cloudstream3
|
||||
|
||||
const val USER_AGENT =
|
||||
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Safari/537.36"
|
||||
|
||||
class ErrorLoadingException(message: String? = null) : Exception(message)
|
|
@ -0,0 +1,88 @@
|
|||
package com.lagradost.cloudstream3
|
||||
|
||||
import com.lagradost.cloudstream3.mvvm.logError
|
||||
import kotlinx.coroutines.*
|
||||
|
||||
//https://stackoverflow.com/questions/34697828/parallel-operations-on-kotlin-collections
|
||||
/*
|
||||
fun <T, R> Iterable<T>.pmap(
|
||||
numThreads: Int = maxOf(Runtime.getRuntime().availableProcessors() - 2, 1),
|
||||
exec: ExecutorService = Executors.newFixedThreadPool(numThreads),
|
||||
transform: (T) -> R,
|
||||
): List<R> {
|
||||
|
||||
// default size is just an inlined version of kotlin.collections.collectionSizeOrDefault
|
||||
val defaultSize = if (this is Collection<*>) this.size else 10
|
||||
val destination = Collections.synchronizedList(ArrayList<R>(defaultSize))
|
||||
|
||||
for (item in this) {
|
||||
exec.submit { destination.add(transform(item)) }
|
||||
}
|
||||
|
||||
exec.shutdown()
|
||||
exec.awaitTermination(1, TimeUnit.DAYS)
|
||||
|
||||
return ArrayList<R>(destination)
|
||||
}*/
|
||||
|
||||
|
||||
@OptIn(DelicateCoroutinesApi::class)
|
||||
suspend fun <K, V, R> Map<out K, V>.amap(f: suspend (Map.Entry<K, V>) -> R): List<R> =
|
||||
with(CoroutineScope(GlobalScope.coroutineContext)) {
|
||||
map { async { f(it) } }.map { it.await() }
|
||||
}
|
||||
|
||||
fun <K, V, R> Map<out K, V>.apmap(f: suspend (Map.Entry<K, V>) -> R): List<R> = runBlocking {
|
||||
map { async { f(it) } }.map { it.await() }
|
||||
}
|
||||
|
||||
|
||||
@OptIn(DelicateCoroutinesApi::class)
|
||||
suspend fun <A, B> List<A>.amap(f: suspend (A) -> B): List<B> =
|
||||
with(CoroutineScope(GlobalScope.coroutineContext)) {
|
||||
map { async { f(it) } }.map { it.await() }
|
||||
}
|
||||
|
||||
|
||||
fun <A, B> List<A>.apmap(f: suspend (A) -> B): List<B> = runBlocking {
|
||||
map { async { f(it) } }.map { it.await() }
|
||||
}
|
||||
|
||||
fun <A, B> List<A>.apmapIndexed(f: suspend (index: Int, A) -> B): List<B> = runBlocking {
|
||||
mapIndexed { index, a -> async { f(index, a) } }.map { it.await() }
|
||||
}
|
||||
|
||||
@OptIn(DelicateCoroutinesApi::class)
|
||||
suspend fun <A, B> List<A>.amapIndexed(f: suspend (index: Int, A) -> B): List<B> =
|
||||
with(CoroutineScope(GlobalScope.coroutineContext)) {
|
||||
mapIndexed { index, a -> async { f(index, a) } }.map { it.await() }
|
||||
}
|
||||
|
||||
// run code in parallel
|
||||
/*fun <R> argpmap(
|
||||
vararg transforms: () -> R,
|
||||
numThreads: Int = maxOf(Runtime.getRuntime().availableProcessors() - 2, 1),
|
||||
exec: ExecutorService = Executors.newFixedThreadPool(numThreads)
|
||||
) {
|
||||
for (item in transforms) {
|
||||
exec.submit { item.invoke() }
|
||||
}
|
||||
|
||||
exec.shutdown()
|
||||
exec.awaitTermination(1, TimeUnit.DAYS)
|
||||
}*/
|
||||
|
||||
// built in try catch
|
||||
fun <R> argamap(
|
||||
vararg transforms: suspend () -> R,
|
||||
) = runBlocking {
|
||||
transforms.map {
|
||||
async {
|
||||
try {
|
||||
it.invoke()
|
||||
} catch (e: Exception) {
|
||||
logError(e)
|
||||
}
|
||||
}
|
||||
}.map { it.await() }
|
||||
}
|
|
@ -0,0 +1,63 @@
|
|||
package com.lagradost.cloudstream3.utils
|
||||
|
||||
import com.lagradost.cloudstream3.mvvm.launchSafe
|
||||
import com.lagradost.cloudstream3.mvvm.logError
|
||||
import kotlinx.coroutines.*
|
||||
import java.util.Collections.synchronizedList
|
||||
|
||||
expect fun runOnMainThreadNative(work: (() -> Unit))
|
||||
object Coroutines {
|
||||
fun <T> T.main(work: suspend ((T) -> Unit)): Job {
|
||||
val value = this
|
||||
return CoroutineScope(Dispatchers.Main).launchSafe {
|
||||
work(value)
|
||||
}
|
||||
}
|
||||
|
||||
fun <T> T.ioSafe(work: suspend (CoroutineScope.(T) -> Unit)): Job {
|
||||
val value = this
|
||||
|
||||
return CoroutineScope(Dispatchers.IO).launchSafe {
|
||||
work(value)
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun <T, V> V.ioWorkSafe(work: suspend (CoroutineScope.(V) -> T)): T? {
|
||||
val value = this
|
||||
return withContext(Dispatchers.IO) {
|
||||
try {
|
||||
work(value)
|
||||
} catch (e: Exception) {
|
||||
logError(e)
|
||||
null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun <T, V> V.ioWork(work: suspend (CoroutineScope.(V) -> T)): T {
|
||||
val value = this
|
||||
return withContext(Dispatchers.IO) {
|
||||
work(value)
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun <T, V> V.mainWork(work: suspend (CoroutineScope.(V) -> T)): T {
|
||||
val value = this
|
||||
return withContext(Dispatchers.Main) {
|
||||
work(value)
|
||||
}
|
||||
}
|
||||
|
||||
fun runOnMainThread(work: (() -> Unit)) {
|
||||
runOnMainThreadNative(work)
|
||||
}
|
||||
|
||||
/**
|
||||
* Safe to add and remove how you want
|
||||
* If you want to iterate over the list then you need to do:
|
||||
* synchronized(allProviders) { code here }
|
||||
**/
|
||||
fun <T> threadSafeListOf(vararg items: T): MutableList<T> {
|
||||
return synchronizedList(items.toMutableList())
|
||||
}
|
||||
}
|
|
@ -0,0 +1,88 @@
|
|||
package com.lagradost.cloudstream3.utils
|
||||
|
||||
import com.lagradost.cloudstream3.mvvm.logError
|
||||
import java.util.regex.Matcher
|
||||
import java.util.regex.Pattern
|
||||
import kotlin.math.pow
|
||||
|
||||
//author: https://github.com/daarkdemon
|
||||
class JsHunter(private val hunterJS: String) {
|
||||
|
||||
/**
|
||||
* Detects whether the javascript is H.U.N.T.E.R coded.
|
||||
*
|
||||
* @return true if it's H.U.N.T.E.R coded.
|
||||
*/
|
||||
fun detect(): Boolean {
|
||||
val p = Pattern.compile("eval\\(function\\(h,u,n,t,e,r\\)")
|
||||
val searchResults = p.matcher(hunterJS)
|
||||
return searchResults.find()
|
||||
}
|
||||
|
||||
/**
|
||||
* Unpack the javascript
|
||||
*
|
||||
* @return the javascript unhunt or null.
|
||||
*/
|
||||
|
||||
fun dehunt(): String? {
|
||||
try {
|
||||
val p: Pattern =
|
||||
Pattern.compile(
|
||||
"""}\("([^"]+)",[^,]+,\s*"([^"]+)",\s*(\d+),\s*(\d+)""",
|
||||
Pattern.DOTALL
|
||||
)
|
||||
val searchResults: Matcher = p.matcher(hunterJS)
|
||||
if (searchResults.find() && searchResults.groupCount() == 4) {
|
||||
val h = searchResults.group(1)!!.toString()
|
||||
val n = searchResults.group(2)!!.toString()
|
||||
val t = searchResults.group(3)!!.toInt()
|
||||
val e = searchResults.group(4)!!.toInt()
|
||||
return hunter(h, n, t, e)
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
logError(e)
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
private fun duf(d: String, e: Int, f: Int = 10): Int {
|
||||
val str = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ+/"
|
||||
val g = str.toList()
|
||||
val h = g.take(e)
|
||||
val i = g.take(f)
|
||||
val dList = d.reversed().toList()
|
||||
var j = 0.0
|
||||
for ((c, b) in dList.withIndex()) {
|
||||
if (b in h) {
|
||||
j += h.indexOf(b) * e.toDouble().pow(c)
|
||||
}
|
||||
}
|
||||
var k = ""
|
||||
while (j > 0) {
|
||||
k = i[(j % f).toInt()] + k
|
||||
j = (j - j % f) / f
|
||||
}
|
||||
return k.toIntOrNull() ?: 0
|
||||
}
|
||||
|
||||
private fun hunter(h: String, n: String, t: Int, e: Int): String {
|
||||
var result = ""
|
||||
var i = 0
|
||||
while (i < h.length) {
|
||||
var j = 0
|
||||
var s = ""
|
||||
while (h[i] != n[e]) {
|
||||
s += h[i]
|
||||
i++
|
||||
}
|
||||
while (j < n.length) {
|
||||
s = s.replace(n[j], j.digitToChar())
|
||||
j++
|
||||
}
|
||||
result += (duf(s, e) - t).toChar()
|
||||
i++
|
||||
}
|
||||
return result
|
||||
}
|
||||
}
|
|
@ -0,0 +1,217 @@
|
|||
package com.lagradost.cloudstream3.utils
|
||||
|
||||
import com.lagradost.cloudstream3.mvvm.logError
|
||||
import java.util.regex.Pattern
|
||||
import kotlin.math.pow
|
||||
|
||||
// https://github.com/cylonu87/JsUnpacker
|
||||
class JsUnpacker(packedJS: String?) {
|
||||
private var packedJS: String? = null
|
||||
|
||||
/**
|
||||
* Detects whether the javascript is P.A.C.K.E.R. coded.
|
||||
*
|
||||
* @return true if it's P.A.C.K.E.R. coded.
|
||||
*/
|
||||
fun detect(): Boolean {
|
||||
val js = packedJS!!.replace(" ", "")
|
||||
val p = Pattern.compile("eval\\(function\\(p,a,c,k,e,[rd]")
|
||||
val m = p.matcher(js)
|
||||
return m.find()
|
||||
}
|
||||
|
||||
/**
|
||||
* Unpack the javascript
|
||||
*
|
||||
* @return the javascript unpacked or null.
|
||||
*/
|
||||
fun unpack(): String? {
|
||||
val js = packedJS
|
||||
try {
|
||||
var p =
|
||||
Pattern.compile("""\}\s*\('(.*)',\s*(.*?),\s*(\d+),\s*'(.*?)'\.split\('\|'\)""", Pattern.DOTALL)
|
||||
var m = p.matcher(js)
|
||||
if (m.find() && m.groupCount() == 4) {
|
||||
val payload = m.group(1).replace("\\'", "'")
|
||||
val radixStr = m.group(2)
|
||||
val countStr = m.group(3)
|
||||
val symtab = m.group(4).split("\\|".toRegex()).toTypedArray()
|
||||
var radix = 36
|
||||
var count = 0
|
||||
try {
|
||||
radix = radixStr.toInt()
|
||||
} catch (e: Exception) {
|
||||
}
|
||||
try {
|
||||
count = countStr.toInt()
|
||||
} catch (e: Exception) {
|
||||
}
|
||||
if (symtab.size != count) {
|
||||
throw Exception("Unknown p.a.c.k.e.r. encoding")
|
||||
}
|
||||
val unbase = Unbase(radix)
|
||||
p = Pattern.compile("""\b[a-zA-Z0-9_]+\b""")
|
||||
m = p.matcher(payload)
|
||||
val decoded = StringBuilder(payload)
|
||||
var replaceOffset = 0
|
||||
while (m.find()) {
|
||||
val word = m.group(0)
|
||||
val x = unbase.unbase(word)
|
||||
var value: String? = null
|
||||
if (x < symtab.size && x >= 0) {
|
||||
value = symtab[x]
|
||||
}
|
||||
if (value != null && value.isNotEmpty()) {
|
||||
decoded.replace(m.start() + replaceOffset, m.end() + replaceOffset, value)
|
||||
replaceOffset += value.length - word.length
|
||||
}
|
||||
}
|
||||
return decoded.toString()
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
logError(e)
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
private inner class Unbase(private val radix: Int) {
|
||||
private val ALPHABET_62 = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
private val ALPHABET_95 =
|
||||
" !\"#$%&\\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\\\]^_`abcdefghijklmnopqrstuvwxyz{|}~"
|
||||
private var alphabet: String? = null
|
||||
private var dictionary: HashMap<String, Int>? = null
|
||||
fun unbase(str: String): Int {
|
||||
var ret = 0
|
||||
if (alphabet == null) {
|
||||
ret = str.toInt(radix)
|
||||
} else {
|
||||
val tmp = StringBuilder(str).reverse().toString()
|
||||
for (i in tmp.indices) {
|
||||
ret += (radix.toDouble().pow(i.toDouble()) * dictionary!![tmp.substring(i, i + 1)]!!).toInt()
|
||||
}
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
init {
|
||||
if (radix > 36) {
|
||||
when {
|
||||
radix < 62 -> {
|
||||
alphabet = ALPHABET_62.substring(0, radix)
|
||||
}
|
||||
radix in 63..94 -> {
|
||||
alphabet = ALPHABET_95.substring(0, radix)
|
||||
}
|
||||
radix == 62 -> {
|
||||
alphabet = ALPHABET_62
|
||||
}
|
||||
radix == 95 -> {
|
||||
alphabet = ALPHABET_95
|
||||
}
|
||||
}
|
||||
dictionary = HashMap(95)
|
||||
for (i in 0 until alphabet!!.length) {
|
||||
dictionary!![alphabet!!.substring(i, i + 1)] = i
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param packedJS javascript P.A.C.K.E.R. coded.
|
||||
*/
|
||||
init {
|
||||
this.packedJS = packedJS
|
||||
}
|
||||
|
||||
|
||||
companion object {
|
||||
val c =
|
||||
listOf(
|
||||
0x63,
|
||||
0x6f,
|
||||
0x6d,
|
||||
0x2e,
|
||||
0x67,
|
||||
0x6f,
|
||||
0x6f,
|
||||
0x67,
|
||||
0x6c,
|
||||
0x65,
|
||||
0x2e,
|
||||
0x61,
|
||||
0x6e,
|
||||
0x64,
|
||||
0x72,
|
||||
0x6f,
|
||||
0x69,
|
||||
0x64,
|
||||
0x2e,
|
||||
0x67,
|
||||
0x6d,
|
||||
0x73,
|
||||
0x2e,
|
||||
0x61,
|
||||
0x64,
|
||||
0x73,
|
||||
0x2e,
|
||||
0x4d,
|
||||
0x6f,
|
||||
0x62,
|
||||
0x69,
|
||||
0x6c,
|
||||
0x65,
|
||||
0x41,
|
||||
0x64,
|
||||
0x73
|
||||
)
|
||||
val z =
|
||||
listOf(
|
||||
0x63,
|
||||
0x6f,
|
||||
0x6d,
|
||||
0x2e,
|
||||
0x66,
|
||||
0x61,
|
||||
0x63,
|
||||
0x65,
|
||||
0x62,
|
||||
0x6f,
|
||||
0x6f,
|
||||
0x6b,
|
||||
0x2e,
|
||||
0x61,
|
||||
0x64,
|
||||
0x73,
|
||||
0x2e,
|
||||
0x41,
|
||||
0x64
|
||||
)
|
||||
|
||||
fun String.load(): String? {
|
||||
return try {
|
||||
var load = this
|
||||
|
||||
for (q in c.indices) {
|
||||
if (c[q % 4] > 270) {
|
||||
load += c[q % 3]
|
||||
} else {
|
||||
load += c[q].toChar()
|
||||
}
|
||||
}
|
||||
|
||||
Class.forName(load.substring(load.length - c.size, load.length)).name
|
||||
} catch (_: Exception) {
|
||||
try {
|
||||
var f = c[2].toChar().toString()
|
||||
for (w in z.indices) {
|
||||
f += z[w].toChar()
|
||||
}
|
||||
return Class.forName(f.substring(0b001, f.length)).name
|
||||
} catch (_: Exception) {
|
||||
null
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
package com.lagradost.cloudstream3.utils
|
||||
|
||||
actual fun runOnMainThreadNative(work: () -> Unit) {
|
||||
work.invoke()
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue