mirror of https://github.com/FongMi/TV.git
parent
0365d9b361
commit
3bfa6559cb
@ -1,107 +1,34 @@ |
||||
package com.hiker.drpy; |
||||
|
||||
import android.content.Context; |
||||
import android.content.SharedPreferences; |
||||
import android.util.Base64; |
||||
import android.util.Log; |
||||
|
||||
import com.hiker.drpy.net.OkHttp; |
||||
import com.whl.quickjs.wrapper.JSArray; |
||||
import com.whl.quickjs.wrapper.JSObject; |
||||
import com.whl.quickjs.wrapper.QuickJSContext; |
||||
|
||||
import org.json.JSONObject; |
||||
|
||||
import java.io.IOException; |
||||
|
||||
import okhttp3.Response; |
||||
import com.github.tvbox.quickjs.JSModule; |
||||
import com.github.tvbox.quickjs.QuickJSContext; |
||||
import com.hiker.drpy.method.Console; |
||||
import com.hiker.drpy.method.Global; |
||||
import com.hiker.drpy.method.Local; |
||||
|
||||
public class Loader { |
||||
|
||||
private final String TAG = Loader.class.getSimpleName(); |
||||
private QuickJSContext jsContext; |
||||
private Context context; |
||||
|
||||
private void init(Context context) { |
||||
System.loadLibrary("quickjs-android-wrapper"); |
||||
this.jsContext = QuickJSContext.create(); |
||||
this.context = context; |
||||
initConsole(); |
||||
initLocal(); |
||||
initReq(); |
||||
} |
||||
|
||||
public Spider spider(Context context, String name, String ext) { |
||||
if (jsContext == null) init(context); |
||||
return new Spider(); |
||||
} |
||||
|
||||
private void initConsole() { |
||||
jsContext.evaluate("var console = {};"); |
||||
JSObject console = (JSObject) jsContext.getGlobalObject().getProperty("console"); |
||||
console.setProperty("log", args -> { |
||||
StringBuilder b = new StringBuilder(); |
||||
for (Object o : args) b.append(o == null ? "null" : o.toString()); |
||||
Log.e(TAG, b.toString()); |
||||
return null; |
||||
}); |
||||
} |
||||
private QuickJSContext ctx; |
||||
|
||||
private void initLocal() { |
||||
jsContext.evaluate("var local = {};"); |
||||
JSObject local = (JSObject) jsContext.getGlobalObject().getProperty("local"); |
||||
local.setProperty("get", args -> { |
||||
SharedPreferences pref = context.getSharedPreferences("js_engine_" + args[0].toString(), Context.MODE_PRIVATE); |
||||
return pref.getString(args[1].toString(), ""); |
||||
}); |
||||
local.setProperty("set", args -> { |
||||
SharedPreferences pref = context.getSharedPreferences("js_engine_" + args[0].toString(), Context.MODE_PRIVATE); |
||||
pref.edit().putString(args[1].toString(), args[2].toString()).apply(); |
||||
return null; |
||||
}); |
||||
local.setProperty("delete", args -> { |
||||
SharedPreferences pref = context.getSharedPreferences("js_engine_" + args[0].toString(), Context.MODE_PRIVATE); |
||||
pref.edit().remove(args[1].toString()).apply(); |
||||
return null; |
||||
}); |
||||
static { |
||||
System.loadLibrary("quickjs"); |
||||
} |
||||
|
||||
private void initReq() { |
||||
jsContext.getGlobalObject().setProperty("req", args -> { |
||||
JSObject jsObject = jsContext.createNewJSObject(); |
||||
JSObject jsHeader = jsContext.createNewJSObject(); |
||||
setReqObject(jsObject, jsHeader, args); |
||||
return jsObject; |
||||
public Loader() { |
||||
Worker.submit(() -> { |
||||
JSModule.setModuleLoader(name -> Module.get().load(name)); |
||||
initCtx(); |
||||
}); |
||||
} |
||||
|
||||
private void setReqObject(JSObject jsObject, JSObject jsHeader, Object... args) { |
||||
try { |
||||
JSONObject obj = new JSONObject(jsContext.stringify((JSObject) args[1])); |
||||
Response response = OkHttp.get().newCall(args[0].toString(), obj).execute(); |
||||
for (String name : response.headers().names()) jsHeader.setProperty(name, response.header(name)); |
||||
jsObject.setProperty("headers", jsHeader); |
||||
setReqContent(jsObject, obj, response); |
||||
} catch (Throwable e) { |
||||
jsObject.setProperty("headers", jsHeader); |
||||
jsObject.setProperty("content", ""); |
||||
} |
||||
private void initCtx() { |
||||
ctx = QuickJSContext.create(); |
||||
ctx.getGlobalObject().setProperty("console", Console.class); |
||||
ctx.getGlobalObject().setProperty("local", Local.class); |
||||
Global.create(ctx).setProperty(); |
||||
} |
||||
|
||||
private void setReqContent(JSObject jsObject, JSONObject obj, Response response) throws IOException { |
||||
switch (obj.optInt("buffer")) { |
||||
case 1: |
||||
byte[] bytes = response.body().bytes(); |
||||
JSArray array = jsContext.createNewJSArray(); |
||||
for (int i = 0; i < bytes.length; i++) array.set(bytes[i], i); |
||||
jsObject.setProperty("content", array); |
||||
break; |
||||
case 2: |
||||
jsObject.setProperty("content", Base64.encodeToString(response.body().bytes(), Base64.DEFAULT)); |
||||
break; |
||||
default: |
||||
jsObject.setProperty("content", response.body().string()); |
||||
break; |
||||
} |
||||
public Spider spider(String api, String ext) { |
||||
return new Spider(ctx, api, ext); |
||||
} |
||||
} |
||||
|
||||
@ -0,0 +1,29 @@ |
||||
package com.hiker.drpy; |
||||
|
||||
import com.hiker.drpy.net.OkHttp; |
||||
|
||||
import java.util.concurrent.ConcurrentHashMap; |
||||
|
||||
public class Module { |
||||
|
||||
private final ConcurrentHashMap<String, String> cache; |
||||
|
||||
private static class Loader { |
||||
static volatile Module INSTANCE = new Module(); |
||||
} |
||||
|
||||
public static Module get() { |
||||
return Loader.INSTANCE; |
||||
} |
||||
|
||||
public Module() { |
||||
this.cache = new ConcurrentHashMap<>(); |
||||
} |
||||
|
||||
public String load(String name) { |
||||
if (cache.contains(name)) return cache.get(name); |
||||
String content = OkHttp.get().module(name); |
||||
cache.put(name, content); |
||||
return content; |
||||
} |
||||
} |
||||
@ -1,6 +1,78 @@ |
||||
package com.hiker.drpy; |
||||
|
||||
import android.content.Context; |
||||
|
||||
import com.github.tvbox.quickjs.JSObject; |
||||
import com.github.tvbox.quickjs.QuickJSContext; |
||||
|
||||
import java.util.HashMap; |
||||
import java.util.List; |
||||
import java.util.UUID; |
||||
import java.util.concurrent.ExecutionException; |
||||
|
||||
public class Spider extends com.github.catvod.crawler.Spider { |
||||
|
||||
private QuickJSContext ctx; |
||||
private JSObject jsObject; |
||||
private String api; |
||||
private String ext; |
||||
private String key; |
||||
|
||||
public Spider(QuickJSContext ctx, String api, String ext) { |
||||
this.key = "__" + UUID.randomUUID().toString().replace("-", "") + "__"; |
||||
this.ctx = ctx; |
||||
this.api = api; |
||||
this.ext = ext; |
||||
} |
||||
|
||||
private String getContent() { |
||||
return Module.get().load(api) |
||||
.replace("export default{", "globalThis." + key + " ={") |
||||
.replace("export default {", "globalThis." + key + " ={") |
||||
.replace("__JS_SPIDER__", "globalThis." + key); |
||||
} |
||||
|
||||
@Override |
||||
public void init(Context context, String extend) throws Exception { |
||||
super.init(context, extend); |
||||
Worker.submit(() -> { |
||||
ctx.evaluateModule(getContent(), api); |
||||
jsObject = (JSObject) ctx.getProperty(ctx.getGlobalObject(), key); |
||||
jsObject.getJSFunction("init").call(ext); |
||||
}); |
||||
} |
||||
|
||||
private String post(String func, Object... args) throws ExecutionException, InterruptedException { |
||||
return (String) Worker.submit(() -> (String) jsObject.getJSFunction(func).call(args)).get(); |
||||
} |
||||
|
||||
@Override |
||||
public String homeContent(boolean filter) throws Exception { |
||||
return post("home", filter); |
||||
} |
||||
|
||||
@Override |
||||
public String homeVideoContent() throws Exception { |
||||
return post("homeVod"); |
||||
} |
||||
|
||||
@Override |
||||
public String categoryContent(String tid, String pg, boolean filter, HashMap<String, String> extend) throws Exception { |
||||
return post("category", tid, pg, filter, null); |
||||
} |
||||
|
||||
@Override |
||||
public String detailContent(List<String> ids) throws Exception { |
||||
return post("detail", ids.get(0)); |
||||
} |
||||
|
||||
@Override |
||||
public String searchContent(String key, boolean quick) throws Exception { |
||||
return post("search", key, quick); |
||||
} |
||||
|
||||
@Override |
||||
public String playerContent(String flag, String id, List<String> vipFlags) throws Exception { |
||||
return post("play", flag, id, null); |
||||
} |
||||
} |
||||
|
||||
@ -0,0 +1,31 @@ |
||||
package com.hiker.drpy; |
||||
|
||||
import java.util.concurrent.Callable; |
||||
import java.util.concurrent.ExecutorService; |
||||
import java.util.concurrent.Executors; |
||||
import java.util.concurrent.Future; |
||||
|
||||
public class Worker { |
||||
|
||||
private final ExecutorService executor; |
||||
|
||||
private static class Loader { |
||||
static volatile Worker INSTANCE = new Worker(); |
||||
} |
||||
|
||||
private static Worker get() { |
||||
return Loader.INSTANCE; |
||||
} |
||||
|
||||
public Worker() { |
||||
executor = Executors.newSingleThreadExecutor(); |
||||
} |
||||
|
||||
public static void submit(Runnable runnable) { |
||||
get().executor.submit(runnable); |
||||
} |
||||
|
||||
public static Future<?> submit(Callable<String> callable) { |
||||
return get().executor.submit(callable); |
||||
} |
||||
} |
||||
@ -0,0 +1,15 @@ |
||||
package com.hiker.drpy.method; |
||||
|
||||
import android.util.Log; |
||||
|
||||
import com.github.tvbox.quickjs.JSMethod; |
||||
|
||||
public class Console { |
||||
|
||||
private final String TAG = Console.class.getSimpleName(); |
||||
|
||||
@JSMethod |
||||
public void log(String msg) { |
||||
Log.d(TAG, msg); |
||||
} |
||||
} |
||||
@ -0,0 +1,126 @@ |
||||
package com.hiker.drpy.method; |
||||
|
||||
import android.text.TextUtils; |
||||
import android.util.Base64; |
||||
|
||||
import com.github.tvbox.quickjs.JSArray; |
||||
import com.github.tvbox.quickjs.JSMethod; |
||||
import com.github.tvbox.quickjs.JSObject; |
||||
import com.github.tvbox.quickjs.QuickJSContext; |
||||
import com.google.gson.Gson; |
||||
import com.hiker.drpy.Parser; |
||||
import com.hiker.drpy.net.OkHttp; |
||||
|
||||
import org.json.JSONObject; |
||||
|
||||
import java.io.IOException; |
||||
import java.lang.reflect.InvocationTargetException; |
||||
import java.lang.reflect.Method; |
||||
import java.net.URL; |
||||
|
||||
import okhttp3.Response; |
||||
|
||||
public class Global { |
||||
|
||||
private final QuickJSContext ctx; |
||||
|
||||
public static Global create(QuickJSContext jsContext) { |
||||
return new Global(jsContext); |
||||
} |
||||
|
||||
private Global(QuickJSContext ctx) { |
||||
this.ctx = ctx; |
||||
} |
||||
|
||||
public void setProperty() { |
||||
for (Method method : getClass().getMethods()) { |
||||
if (!method.isAnnotationPresent(JSMethod.class)) continue; |
||||
ctx.getGlobalObject().setProperty(method.getName(), args -> { |
||||
try { |
||||
return method.invoke(this, args); |
||||
} catch (IllegalAccessException | InvocationTargetException e) { |
||||
return null; |
||||
} |
||||
}); |
||||
} |
||||
} |
||||
|
||||
@JSMethod |
||||
public JSObject req(String url, JSObject object) { |
||||
try { |
||||
JSObject jsObject = ctx.createNewJSObject(); |
||||
JSObject jsHeader = ctx.createNewJSObject(); |
||||
JSONObject obj = new JSONObject(ctx.stringify(object)); |
||||
Response response = OkHttp.get().newCall(url, obj).execute(); |
||||
for (String name : response.headers().names()) jsHeader.setProperty(name, response.header(name)); |
||||
jsObject.setProperty("headers", jsHeader); |
||||
setReqContent(jsObject, obj, response); |
||||
return jsObject; |
||||
} catch (Throwable e) { |
||||
return null; |
||||
} |
||||
} |
||||
|
||||
@JSMethod |
||||
public String pd(String html, String rule, String urlKey) { |
||||
try { |
||||
return Parser.parseDomForUrl(html, rule, urlKey); |
||||
} catch (Throwable e) { |
||||
e.printStackTrace(); |
||||
return ""; |
||||
} |
||||
} |
||||
|
||||
@JSMethod |
||||
public JSObject pdfa(String html, String rule) { |
||||
try { |
||||
return ctx.parseJSON(new Gson().toJson(Parser.parseDomForList(html, rule))); |
||||
} catch (Throwable e) { |
||||
e.printStackTrace(); |
||||
return null; |
||||
} |
||||
} |
||||
|
||||
@JSMethod |
||||
public String pdfh(String html, String rule) { |
||||
try { |
||||
return Parser.parseDomForUrl(html, rule, ""); |
||||
} catch (Throwable e) { |
||||
e.printStackTrace(); |
||||
return ""; |
||||
} |
||||
} |
||||
|
||||
@JSMethod |
||||
public JSObject pdfl(String html, String p1, String list_text, String list_url, String urlKey) { |
||||
return null; |
||||
} |
||||
|
||||
@JSMethod |
||||
public String joinUrl(String parent, String child) { |
||||
try { |
||||
if (TextUtils.isEmpty(parent)) return child; |
||||
return new URL(new URL(parent), child).toString(); |
||||
} catch (Throwable e) { |
||||
e.printStackTrace(); |
||||
return ""; |
||||
} |
||||
} |
||||
|
||||
private void setReqContent(JSObject jsObject, JSONObject obj, Response response) throws IOException { |
||||
switch (obj.optInt("buffer")) { |
||||
case 1: |
||||
byte[] bytes = response.body().bytes(); |
||||
JSArray array = ctx.createNewJSArray(); |
||||
for (int i = 0; i < bytes.length; i++) array.set(bytes[i], i); |
||||
jsObject.setProperty("content", array); |
||||
break; |
||||
case 2: |
||||
jsObject.setProperty("content", Base64.encodeToString(response.body().bytes(), Base64.DEFAULT)); |
||||
break; |
||||
default: |
||||
jsObject.setProperty("content", response.body().string()); |
||||
break; |
||||
} |
||||
} |
||||
} |
||||
@ -0,0 +1,26 @@ |
||||
package com.hiker.drpy.method; |
||||
|
||||
import com.github.tvbox.quickjs.JSMethod; |
||||
|
||||
import java.util.HashMap; |
||||
import java.util.Map; |
||||
|
||||
public class Local { |
||||
|
||||
private final Map<String, String> maps = new HashMap<>(); |
||||
|
||||
@JSMethod |
||||
public String get(String R_KEY, String k) { |
||||
return maps.get("js_engine_" + R_KEY + "_" + k); |
||||
} |
||||
|
||||
@JSMethod |
||||
public void set(String R_KEY, String k, String v) { |
||||
maps.put("js_engine_" + R_KEY + "_" + k, v); |
||||
} |
||||
|
||||
@JSMethod |
||||
public void delete(String R_KEY, String k) { |
||||
maps.remove("js_engine_" + R_KEY + "_" + k); |
||||
} |
||||
} |
||||
Loading…
Reference in new issue