mirror of
https://github.com/qaiu/netdisk-fast-download.git
synced 2025-12-16 20:33:03 +00:00
0
This commit is contained in:
@@ -4,16 +4,16 @@ import cn.qaiu.lz.common.parser.impl.*;
|
|||||||
import io.vertx.core.Future;
|
import io.vertx.core.Future;
|
||||||
|
|
||||||
public interface IPanTool {
|
public interface IPanTool {
|
||||||
Future<String> parse(String data, String code);
|
Future<String> parse();
|
||||||
|
|
||||||
static IPanTool typeMatching(String type) {
|
static IPanTool typeMatching(String type, String key, String pwd) {
|
||||||
return switch (type) {
|
return switch (type) {
|
||||||
case "lz" -> new LzTool();
|
case "lz" -> new LzTool();
|
||||||
case "cow" -> new CowTool();
|
case "cow" -> new CowTool();
|
||||||
case "ec" -> new EcTool();
|
case "ec" -> new EcTool();
|
||||||
case "fc" -> new FcTool();
|
case "fc" -> new FcTool();
|
||||||
case "uc" -> new UcTool();
|
case "uc" -> new UcTool();
|
||||||
case "ye" -> new YeTool();
|
case "ye" -> new YeTool(key, pwd);
|
||||||
case "fj" -> new FjTool();
|
case "fj" -> new FjTool();
|
||||||
default -> {
|
default -> {
|
||||||
throw new IllegalArgumentException("未知分享类型");
|
throw new IllegalArgumentException("未知分享类型");
|
||||||
@@ -21,7 +21,7 @@ public interface IPanTool {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
static IPanTool shareURLPrefixMatching(String url) {
|
static IPanTool shareURLPrefixMatching(String url, String pwd) {
|
||||||
|
|
||||||
if (url.startsWith(CowTool.SHARE_URL_PREFIX)) {
|
if (url.startsWith(CowTool.SHARE_URL_PREFIX)) {
|
||||||
return new CowTool();
|
return new CowTool();
|
||||||
@@ -32,7 +32,7 @@ public interface IPanTool {
|
|||||||
} else if (url.startsWith(UcTool.SHARE_URL_PREFIX)) {
|
} else if (url.startsWith(UcTool.SHARE_URL_PREFIX)) {
|
||||||
return new UcTool();
|
return new UcTool();
|
||||||
} else if (url.startsWith(YeTool.SHARE_URL_PREFIX)) {
|
} else if (url.startsWith(YeTool.SHARE_URL_PREFIX)) {
|
||||||
return new YeTool();
|
return new YeTool(url, pwd);
|
||||||
} else if (url.startsWith(FjTool.SHARE_URL_PREFIX)) {
|
} else if (url.startsWith(FjTool.SHARE_URL_PREFIX)) {
|
||||||
return new FjTool();
|
return new FjTool();
|
||||||
} else if (url.contains("lanzou")) {
|
} else if (url.contains("lanzou")) {
|
||||||
|
|||||||
@@ -0,0 +1,37 @@
|
|||||||
|
package cn.qaiu.lz.common.parser;
|
||||||
|
|
||||||
|
import io.vertx.core.Handler;
|
||||||
|
import io.vertx.core.Promise;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
public abstract class PanBase {
|
||||||
|
|
||||||
|
protected Promise<String> promise = Promise.promise();
|
||||||
|
protected Logger log = LoggerFactory.getLogger(this.getClass());
|
||||||
|
|
||||||
|
protected String key;
|
||||||
|
protected String pwd;
|
||||||
|
|
||||||
|
protected PanBase(String key, String pwd) {
|
||||||
|
this.key = key;
|
||||||
|
this.pwd = pwd;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void fail(Throwable t, String errorMsg, Object... args) {
|
||||||
|
String s = String.format(errorMsg.replaceAll("\\{}", "%s"), args);
|
||||||
|
log.error("解析异常: " + s, t.fillInStackTrace());
|
||||||
|
promise.fail(this.getClass().getSimpleName() + ": 解析异常: " + s + " -> " + t);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void fail(String errorMsg, Object... args) {
|
||||||
|
String s = String.format(errorMsg.replaceAll("\\{}", "%s"), args);
|
||||||
|
log.error("解析异常: " + s);
|
||||||
|
promise.fail(this.getClass().getSimpleName() + " - 解析异常: " + s);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Handler<Throwable> handleFail(String errorMsg) {
|
||||||
|
return t -> fail(this.getClass().getSimpleName() + " - 请求异常 {}: -> {}", errorMsg, t.fillInStackTrace());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,22 +1,18 @@
|
|||||||
package cn.qaiu.lz.common.parser.impl;
|
package cn.qaiu.lz.common.parser.impl;
|
||||||
|
|
||||||
import cn.qaiu.lz.common.parser.IPanTool;
|
import cn.qaiu.lz.common.parser.IPanTool;
|
||||||
|
import cn.qaiu.lz.common.parser.PanBase;
|
||||||
import cn.qaiu.lz.common.util.CommonUtils;
|
import cn.qaiu.lz.common.util.CommonUtils;
|
||||||
import cn.qaiu.lz.common.util.JsExecUtils;
|
import cn.qaiu.lz.common.util.JsExecUtils;
|
||||||
import cn.qaiu.lz.common.util.PanExceptionUtils;
|
import cn.qaiu.lz.common.util.PanExceptionUtils;
|
||||||
import cn.qaiu.vx.core.util.VertxHolder;
|
import cn.qaiu.vx.core.util.VertxHolder;
|
||||||
import io.vertx.core.Future;
|
import io.vertx.core.Future;
|
||||||
import io.vertx.core.Promise;
|
|
||||||
import io.vertx.core.json.JsonObject;
|
import io.vertx.core.json.JsonObject;
|
||||||
import io.vertx.ext.web.client.WebClient;
|
import io.vertx.ext.web.client.WebClient;
|
||||||
import io.vertx.uritemplate.UriTemplate;
|
import io.vertx.uritemplate.UriTemplate;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
import org.apache.commons.lang3.ArrayUtils;
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.openjdk.nashorn.api.scripting.ScriptObjectMirror;
|
import org.openjdk.nashorn.api.scripting.ScriptObjectMirror;
|
||||||
|
|
||||||
import javax.script.ScriptException;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.net.MalformedURLException;
|
import java.net.MalformedURLException;
|
||||||
import java.util.Base64;
|
import java.util.Base64;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@@ -26,8 +22,8 @@ import java.util.regex.Pattern;
|
|||||||
/**
|
/**
|
||||||
* 123网盘
|
* 123网盘
|
||||||
*/
|
*/
|
||||||
@Slf4j
|
public class YeTool extends PanBase implements IPanTool {
|
||||||
public class YeTool implements IPanTool {
|
|
||||||
public static final String SHARE_URL_PREFIX = "https://www.123pan.com/s/";
|
public static final String SHARE_URL_PREFIX = "https://www.123pan.com/s/";
|
||||||
public static final String FIRST_REQUEST_URL = SHARE_URL_PREFIX + "{key}.html";
|
public static final String FIRST_REQUEST_URL = SHARE_URL_PREFIX + "{key}.html";
|
||||||
/*
|
/*
|
||||||
@@ -45,10 +41,13 @@ public class YeTool implements IPanTool {
|
|||||||
"&shareKey={shareKey}&SharePwd={pwd}&ParentFileId=0&Page=1&event=homeListFile&operateType=1";
|
"&shareKey={shareKey}&SharePwd={pwd}&ParentFileId=0&Page=1&event=homeListFile&operateType=1";
|
||||||
private static final String DOWNLOAD_API_URL = "https://www.123pan.com/b/api/share/download/info?{authK}={authV}";
|
private static final String DOWNLOAD_API_URL = "https://www.123pan.com/b/api/share/download/info?{authK}={authV}";
|
||||||
|
|
||||||
public Future<String> parse(String data, String code) {
|
public YeTool(String key, String pwd) {
|
||||||
|
super(key, pwd);
|
||||||
|
}
|
||||||
|
|
||||||
String dataKey = CommonUtils.adaptShortPaths(SHARE_URL_PREFIX, data);
|
public Future<String> parse() {
|
||||||
Promise<String> promise = Promise.promise();
|
|
||||||
|
String dataKey = CommonUtils.adaptShortPaths(SHARE_URL_PREFIX, key);
|
||||||
WebClient client = WebClient.create(VertxHolder.getVertxInstance());
|
WebClient client = WebClient.create(VertxHolder.getVertxInstance());
|
||||||
|
|
||||||
client.getAbs(UriTemplate.of(FIRST_REQUEST_URL)).setTemplateParam("key", dataKey).send().onSuccess(res -> {
|
client.getAbs(UriTemplate.of(FIRST_REQUEST_URL)).setTemplateParam("key", dataKey).send().onSuccess(res -> {
|
||||||
@@ -58,7 +57,7 @@ public class YeTool implements IPanTool {
|
|||||||
Matcher matcher = compile.matcher(html);
|
Matcher matcher = compile.matcher(html);
|
||||||
|
|
||||||
if (!matcher.find()) {
|
if (!matcher.find()) {
|
||||||
promise.fail(html + "\n Ye: " + dataKey + " 正则匹配失败");
|
fail(html + "\n Ye: " + dataKey + " 正则匹配失败");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
String fileInfoString = matcher.group(1);
|
String fileInfoString = matcher.group(1);
|
||||||
@@ -67,45 +66,45 @@ public class YeTool implements IPanTool {
|
|||||||
JsonObject resListJson = fileInfoJson.getJsonObject("reslist");
|
JsonObject resListJson = fileInfoJson.getJsonObject("reslist");
|
||||||
|
|
||||||
if (resJson == null || resJson.getInteger("code") != 0) {
|
if (resJson == null || resJson.getInteger("code") != 0) {
|
||||||
promise.fail(dataKey + " 解析到异常JSON: " + resJson);
|
fail(dataKey + " 解析到异常JSON: " + resJson);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
String shareKey = resJson.getJsonObject("data").getString("ShareKey");
|
String shareKey = resJson.getJsonObject("data").getString("ShareKey");
|
||||||
if (resListJson == null || resListJson.getInteger("code") != 0) {
|
if (resListJson == null || resListJson.getInteger("code") != 0) {
|
||||||
// 加密分享
|
// 加密分享
|
||||||
if (StringUtils.isNotEmpty(code)) {
|
if (StringUtils.isNotEmpty(pwd)) {
|
||||||
client.getAbs(UriTemplate.of(GET_FILE_INFO_URL))
|
client.getAbs(UriTemplate.of(GET_FILE_INFO_URL))
|
||||||
.setTemplateParam("shareKey", shareKey)
|
.setTemplateParam("shareKey", shareKey)
|
||||||
.setTemplateParam("pwd", code)
|
.setTemplateParam("pwd", pwd)
|
||||||
// .setTemplateParam("authKey", AESUtils.getAuthKey("/b/api/share/get"))
|
// .setTemplateParam("authKey", AESUtils.getAuthKey("/b/api/share/get"))
|
||||||
.putHeader("Platform", "web")
|
.putHeader("Platform", "web")
|
||||||
.putHeader("App-Version", "3")
|
.putHeader("App-Version", "3")
|
||||||
.send().onSuccess(res2 -> {
|
.send().onSuccess(res2 -> {
|
||||||
JsonObject infoJson = res2.bodyAsJsonObject();
|
JsonObject infoJson = res2.bodyAsJsonObject();
|
||||||
if (infoJson.getInteger("code") != 0) {
|
if (infoJson.getInteger("code") != 0) {
|
||||||
promise.fail("Ye: " + dataKey + " 状态码异常" + infoJson);
|
fail("{} 状态码异常 {}", dataKey, infoJson);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
JsonObject getFileInfoJson =
|
JsonObject getFileInfoJson =
|
||||||
infoJson.getJsonObject("data").getJsonArray("InfoList").getJsonObject(0);
|
infoJson.getJsonObject("data").getJsonArray("InfoList").getJsonObject(0);
|
||||||
getFileInfoJson.put("ShareKey", shareKey);
|
getFileInfoJson.put("ShareKey", shareKey);
|
||||||
getDownUrl(promise, client, getFileInfoJson);
|
getDownUrl(client, getFileInfoJson);
|
||||||
}).onFailure(t -> promise.fail(PanExceptionUtils.fillRunTimeException("Ye", dataKey, t)));
|
}).onFailure(this.handleFail("获取文件信息失败"));
|
||||||
} else {
|
} else {
|
||||||
promise.fail(dataKey + " 该分享需要密码");
|
fail(dataKey + " 该分享需要密码");
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
JsonObject reqBodyJson = resListJson.getJsonObject("data").getJsonArray("InfoList").getJsonObject(0);
|
JsonObject reqBodyJson = resListJson.getJsonObject("data").getJsonArray("InfoList").getJsonObject(0);
|
||||||
reqBodyJson.put("ShareKey", shareKey);
|
reqBodyJson.put("ShareKey", shareKey);
|
||||||
getDownUrl(promise, client, reqBodyJson);
|
getDownUrl(client, reqBodyJson);
|
||||||
}).onFailure(t -> promise.fail(PanExceptionUtils.fillRunTimeException("Ye", dataKey, t)));
|
}).onFailure(this.handleFail(""));
|
||||||
|
|
||||||
return promise.future();
|
return promise.future();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void getDownUrl(Promise<String> promise, WebClient client, JsonObject reqBodyJson) {
|
private void getDownUrl(WebClient client, JsonObject reqBodyJson) {
|
||||||
log.info(reqBodyJson.encodePrettily());
|
log.info(reqBodyJson.encodePrettily());
|
||||||
JsonObject jsonObject = new JsonObject();
|
JsonObject jsonObject = new JsonObject();
|
||||||
// {"ShareKey":"iaKtVv-6OECd","FileID":2193732,"S3keyFlag":"1811834632-0","Size":4203111,
|
// {"ShareKey":"iaKtVv-6OECd","FileID":2193732,"S3keyFlag":"1811834632-0","Size":4203111,
|
||||||
@@ -120,12 +119,8 @@ public class YeTool implements IPanTool {
|
|||||||
ScriptObjectMirror getSign;
|
ScriptObjectMirror getSign;
|
||||||
try {
|
try {
|
||||||
getSign = JsExecUtils.executeJs("getSign", "/b/api/share/download/info");
|
getSign = JsExecUtils.executeJs("getSign", "/b/api/share/download/info");
|
||||||
} catch (ScriptException | IOException | NoSuchMethodException e) {
|
} catch (Exception e) {
|
||||||
promise.fail(e);
|
fail(e, "JS函数执行异常");
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (getSign == null) {
|
|
||||||
promise.fail(ArrayUtils.toString(getSign));
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
log.info("ye getSign: {}={}", getSign.get("0").toString(), getSign.get("1").toString());
|
log.info("ye getSign: {}={}", getSign.get("0").toString(), getSign.get("1").toString());
|
||||||
@@ -140,11 +135,11 @@ public class YeTool implements IPanTool {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
if (downURLJson.getInteger("code") != 0) {
|
if (downURLJson.getInteger("code") != 0) {
|
||||||
promise.fail("Ye: downURLJson返回值异常->" + downURLJson);
|
fail("Ye: downURLJson返回值异常->" + downURLJson);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} catch (Exception ignored) {
|
} catch (Exception ignored) {
|
||||||
promise.fail("Ye: downURLJson格式异常->" + downURLJson);
|
fail("Ye: downURLJson格式异常->" + downURLJson);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
String downURL = downURLJson.getJsonObject("data").getString("DownloadURL");
|
String downURL = downURLJson.getJsonObject("data").getString("DownloadURL");
|
||||||
@@ -159,23 +154,21 @@ public class YeTool implements IPanTool {
|
|||||||
JsonObject res3Json = res3.bodyAsJsonObject();
|
JsonObject res3Json = res3.bodyAsJsonObject();
|
||||||
try {
|
try {
|
||||||
if (res3Json.getInteger("code") != 0) {
|
if (res3Json.getInteger("code") != 0) {
|
||||||
promise.fail("Ye: downUrl2返回值异常->" + res3Json);
|
fail("Ye: downUrl2返回值异常->" + res3Json);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} catch (Exception ignored) {
|
} catch (Exception ignored) {
|
||||||
promise.fail("Ye: downUrl2格式异常->" + downURLJson);
|
fail("Ye: downUrl2格式异常->" + downURLJson);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
promise.complete(res3Json.getJsonObject("data").getString("redirect_url"));
|
promise.complete(res3Json.getJsonObject("data").getString("redirect_url"));
|
||||||
|
|
||||||
}).onFailure(t -> promise.fail(PanExceptionUtils.fillRunTimeException("Ye",
|
}).onFailure(this.handleFail("获取直链失败"));
|
||||||
reqBodyJson.encodePrettily(), t)));
|
|
||||||
|
|
||||||
} catch (MalformedURLException e) {
|
} catch (MalformedURLException e) {
|
||||||
promise.fail("urlParams解析异常" + e.getMessage());
|
fail("urlParams解析异常" + e.getMessage());
|
||||||
}
|
}
|
||||||
}).onFailure(t -> promise.fail(PanExceptionUtils.fillRunTimeException("Ye",
|
}).onFailure(this::handleFail);
|
||||||
reqBodyJson.encodePrettily(), t)));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import javax.script.Invocable;
|
|||||||
import javax.script.ScriptEngine;
|
import javax.script.ScriptEngine;
|
||||||
import javax.script.ScriptEngineManager;
|
import javax.script.ScriptEngineManager;
|
||||||
import javax.script.ScriptException;
|
import javax.script.ScriptException;
|
||||||
|
import java.io.FileNotFoundException;
|
||||||
import java.io.FileReader;
|
import java.io.FileReader;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
@@ -17,26 +18,32 @@ import java.net.URL;
|
|||||||
*/
|
*/
|
||||||
public class JsExecUtils {
|
public class JsExecUtils {
|
||||||
private static final String JS_PATH = "/js/ye123.js";
|
private static final String JS_PATH = "/js/ye123.js";
|
||||||
|
private static Invocable inv;
|
||||||
|
|
||||||
/**
|
// 初始化脚本引擎
|
||||||
* 调用js文件
|
static {
|
||||||
*/
|
|
||||||
public static ScriptObjectMirror executeJs(String functionName, Object... args) throws ScriptException,
|
|
||||||
IOException, NoSuchMethodException {
|
|
||||||
ScriptEngineManager engineManager = new ScriptEngineManager();
|
ScriptEngineManager engineManager = new ScriptEngineManager();
|
||||||
ScriptEngine engine = engineManager.getEngineByName("JavaScript"); // 得到脚本引擎
|
ScriptEngine engine = engineManager.getEngineByName("JavaScript"); // 得到脚本引擎
|
||||||
//获取文件所在的相对路径
|
//获取文件所在的相对路径
|
||||||
URL resource = JsExecUtils.class.getResource("/");
|
URL resource = JsExecUtils.class.getResource("/");
|
||||||
if (resource == null) {
|
if (resource == null) {
|
||||||
throw new ScriptException("js resource path is null");
|
throw new RuntimeException("js resource path is null");
|
||||||
}
|
}
|
||||||
String path = resource.getPath();
|
String path = resource.getPath();
|
||||||
String reader = path + JS_PATH;
|
String reader = path + JS_PATH;
|
||||||
FileReader fReader = new FileReader(reader);
|
try (FileReader fReader = new FileReader(reader)){
|
||||||
engine.eval(fReader);
|
engine.eval(fReader);
|
||||||
fReader.close();
|
fReader.close();
|
||||||
|
inv = (Invocable) engine;
|
||||||
|
} catch (IOException | ScriptException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Invocable inv = (Invocable) engine;
|
/**
|
||||||
|
* 调用js文件
|
||||||
|
*/
|
||||||
|
public static ScriptObjectMirror executeJs(String functionName, Object... args) throws ScriptException, NoSuchMethodException {
|
||||||
//调用js中的方法
|
//调用js中的方法
|
||||||
return (ScriptObjectMirror) inv.invokeFunction(functionName, args);
|
return (ScriptObjectMirror) inv.invokeFunction(functionName, args);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -91,7 +91,7 @@ GET http://127.0.0.1:6400/ye/iaKtVv-qOECd
|
|||||||
|
|
||||||
### 123
|
### 123
|
||||||
# @no-redirect
|
# @no-redirect
|
||||||
GET http://127.0.0.1:6400/parser?url=https://www.123pan.com/s/iaKtVv-6OECd.html&pwd=DcGe
|
GET http://127.0.0.1:6400/parser?url=https://www.123pan.com/s/iaKtVv-6OECd.html&pwd=DcGeasd
|
||||||
|
|
||||||
###
|
###
|
||||||
POST http://127.0.0.1:6400/login1
|
POST http://127.0.0.1:6400/login1
|
||||||
|
|||||||
Reference in New Issue
Block a user