update 支持Cloudreve任意https的80端口的域名, 修复因json异常解析导致的解析时间超时的问题

This commit is contained in:
QAIU
2024-09-25 20:01:10 +08:00
parent 1019f24f1d
commit 1f825db261
16 changed files with 87 additions and 52 deletions

View File

@@ -4,6 +4,9 @@ import cn.qaiu.WebClientVertxInit;
import cn.qaiu.entity.ShareLinkInfo;
import io.vertx.core.Handler;
import io.vertx.core.Promise;
import io.vertx.core.json.DecodeException;
import io.vertx.core.json.JsonObject;
import io.vertx.ext.web.client.HttpResponse;
import io.vertx.ext.web.client.WebClient;
import io.vertx.ext.web.client.WebClientOptions;
import io.vertx.ext.web.client.WebClientSession;
@@ -98,4 +101,19 @@ public abstract class PanBase {
return t -> fail(this.getClass().getSimpleName() + " - 请求异常 {}: -> {}", errorMsg, t.fillInStackTrace());
}
/**
* bodyAsJsonObject的封装, 会自动处理异常
* @param res HttpResponse
* @return JsonObject
*/
protected JsonObject asJson(HttpResponse<?> res) {
try {
return res.bodyAsJsonObject();
} catch (DecodeException e) {
fail("解析失败: json格式异常: {}", res.bodyAsString());
throw new RuntimeException("解析失败: json格式异常");
}
}
}

View File

@@ -71,10 +71,11 @@ public enum PanDomainTemplate {
"https://(.*)cowtransfer\\.com/s/(.+)",
"https://cowtransfer.com/s/{shareKey}",
CowTool.class),
// https://pan.huang1111.cn/s/
CE("huang1111",
"https://pan\\.huang1111\\.cn/s/(.+)",
"https://pan.huang1111.cn/s/{shareKey}",
// https://pan.huang1111.cn/s/xxx
// 通用域名([a-z0-9]+(-[a-z0-9]+)*\.)+[a-z]{2,}
CE("Cloudreve",
"https://([a-z0-9]+(-[a-z0-9]+)*\\.)+[a-z]{2,}/s/(.+)",
"https://{CloudreveName}/s/{shareKey}",
CeTool.class);

View File

@@ -66,8 +66,17 @@ public class ParserCreate {
// set share key
public ParserCreate shareKey(String shareKey) {
shareLinkInfo.setShareKey(shareKey);
shareLinkInfo.setStandardUrl(panDomainTemplate.getStandardUrlTemplate().replace("{shareKey}", shareKey));
if (panDomainTemplate == PanDomainTemplate.CE) {
// 处理Cloudreve(ce)类: pan.huang1111.cn_s_wDz5TK _ -> /
String[] s = shareKey.split("_");
String standardUrl = "https://" + String.join("/", s);
shareLinkInfo.setShareKey(s[s.length - 1]);
shareLinkInfo.setStandardUrl(standardUrl);
shareLinkInfo.setShareUrl(standardUrl);
} else {
shareLinkInfo.setShareKey(shareKey);
shareLinkInfo.setStandardUrl(panDomainTemplate.getStandardUrlTemplate().replace("{shareKey}", shareKey));
}
return this;
}

View File

@@ -8,17 +8,21 @@ import io.vertx.core.buffer.Buffer;
import io.vertx.core.json.JsonObject;
import io.vertx.ext.web.client.HttpRequest;
import java.net.URL;
/**
* <a href="https://github.com/cloudreve/Cloudreve">Cloudreve网盘解析</a> <br>
* <a href="https://github.com/cloudreve/Cloudreve">Cloudreve自建网盘解析</a> <br>
* <a href="https://pan.xiaomuxi.cn">暮希云盘</a> <br>
* <a href="https://pan.huang1111.cn">huang1111</a> <br>
* <a href="https://pan.seeoss.com">看见存储</a> <br>
* <a href="https://dav.yiandrive.com">亿安云盘</a> <br>
*/
public class CeTool extends PanBase implements IPanTool {
private static final String DOWNLOAD_API_PATH = "https://pan.huang1111.cn/api/v3/share/download/";
private static final String DOWNLOAD_API_PATH = "/api/v3/share/download/";
// api/v3/share/info/g31PcQ?password=qaiu
private static final String SHARE_API_PATH = "https://pan.huang1111.cn/api/v3/share/info/";
private static final String SHARE_API_PATH = "/api/v3/share/info/";
public CeTool(ShareLinkInfo shareLinkInfo) {
super(shareLinkInfo);
@@ -31,24 +35,14 @@ public class CeTool extends PanBase implements IPanTool {
// https://pan.huang1111.cn/s/wDz5TK
// https://pan.huang1111.cn/s/y12bI6 -> https://pan.huang1111
// .cn/api/v3/share/download/y12bI6?path=undefined%2Fundefined;
// 类型解析 -> /ce/https_pan.huang1111.cn_s_wDz5TK
// 类型解析 -> /ce/pan.huang1111.cn_s_wDz5TK
// parser接口 -> /parser?url=https://pan.huang1111.cn/s/wDz5TK
try {
// if (key.startsWith("https_") || key.startsWith("http_")) {
// key = key.replace("https_", "https://")
// .replace("http_", "http://")
// .replace("_", "/");
// }
// // 处理URL
// URL url = new URL(key);
// String path = url.getPath();
// String shareKey = path.substring(3);
// String downloadApiUrl = url.getProtocol() + "://" + url.getHost() + DOWNLOAD_API_PATH + shareKey + "?path" +
// "=undefined/undefined;";
// String shareApiUrl = url.getProtocol() + "://" + url.getHost() + SHARE_API_PATH + shareKey;
var shareApiUrl = SHARE_API_PATH;
var downloadApiUrl = DOWNLOAD_API_PATH;
URL url = new URL(shareLinkInfo.getShareUrl());
String downloadApiUrl = url.getProtocol() + "://" + url.getHost() + DOWNLOAD_API_PATH + key + "?path" +
"=undefined/undefined;";
String shareApiUrl = url.getProtocol() + "://" + url.getHost() + SHARE_API_PATH + key;
// 设置cookie
HttpRequest<Buffer> httpRequest = clientSession.getAbs(shareApiUrl);
@@ -65,7 +59,7 @@ public class CeTool extends PanBase implements IPanTool {
private void getDownURL(String apiUrl) {
clientSession.putAbs(apiUrl).send().onSuccess(res -> {
JsonObject jsonObject = res.bodyAsJsonObject();
JsonObject jsonObject = asJson(res);
System.out.println(jsonObject.encodePrettily());
if (jsonObject.containsKey("code") && jsonObject.getInteger("code") == 0) {
promise.complete(jsonObject.getString("data"));

View File

@@ -26,7 +26,7 @@ public class CowTool extends PanBase implements IPanTool {
final String key = shareLinkInfo.getShareKey();
String url = API_REQUEST_URL + "?uniqueUrl=" + key;
client.getAbs(url).send().onSuccess(res -> {
JsonObject resJson = res.bodyAsJsonObject();
JsonObject resJson = asJson(res);
if ("success".equals(resJson.getString("message")) && resJson.containsKey("data")) {
JsonObject dataJson = resJson.getJsonObject("data");
String guid = dataJson.getString("guid");
@@ -41,7 +41,7 @@ public class CowTool extends PanBase implements IPanTool {
}
String url2 = url2Build.toString();
client.getAbs(url2).send().onSuccess(res2 -> {
JsonObject res2Json = res2.bodyAsJsonObject();
JsonObject res2Json = asJson(res2);
if ("success".equals(res2Json.getString("message")) && res2Json.containsKey("data")) {
JsonObject data2 = res2Json.getJsonObject("data");
String downloadUrl = data2.getString("downloadUrl");

View File

@@ -34,7 +34,7 @@ public class EcTool extends PanBase implements IPanTool {
.setTemplateParam("extractionCode", pwd == null ? "" : pwd)
.send()
.onSuccess(res -> {
JsonObject jsonObject = res.bodyAsJsonObject();
JsonObject jsonObject = asJson(res);
log.debug("ecPan get file info -> {}", jsonObject);
JsonObject fileInfo = jsonObject
.getJsonObject("var")
@@ -59,7 +59,7 @@ public class EcTool extends PanBase implements IPanTool {
// 第二次请求 获取下载链接
client.postAbs(DOWNLOAD_REQUEST_URL).sendJsonObject(requestBodyJson).onSuccess(res2 -> {
JsonObject jsonRes = res2.bodyAsJsonObject();
JsonObject jsonRes = asJson(res2);
log.debug("ecPan get download url -> {}", res2.body().toString());
promise.complete(jsonRes.getJsonObject("var").getString("downloadUrl"));
}).onFailure(handleFail(""));

View File

@@ -88,7 +88,7 @@ public class FcTool extends PanBase implements IPanTool {
.setTemplateParam("unique_name", dataKey).send().onSuccess(res2 -> {
JsonObject resJson;
try {
resJson = res2.bodyAsJsonObject();
resJson = asJson(res2);
} catch (Exception e) {
fail(e, DOWN_REQUEST_URL + " 第二次请求没有返回JSON, 可能下载受限");
return;

View File

@@ -63,7 +63,7 @@ public class FjTool extends PanBase implements IPanTool {
.setTemplateParam("uuid", uuid)
.setTemplateParam("ts", tsEncode0)
.send().onSuccess(res -> {
JsonObject resJson = res.bodyAsJsonObject();
JsonObject resJson = asJson(res);
if (resJson.getInteger("code") != 200) {
fail(FIRST_REQUEST_URL + " 返回异常: " + resJson);
return;

View File

@@ -39,7 +39,7 @@ public class IzTool extends PanBase implements IPanTool {
// 第一次请求 获取文件信息
// POST https://api.feijipan.com/ws/recommend/list?devType=6&devModel=Chrome&extra=2&shareId=146731&type=0&offset=1&limit=60
client.postAbs(UriTemplate.of(FIRST_REQUEST_URL)).setTemplateParam("shareId", dataKey).send().onSuccess(res -> {
JsonObject resJson = res.bodyAsJsonObject();
JsonObject resJson = asJson(res);
if (resJson.getInteger("code") != 200) {
fail(FIRST_REQUEST_URL + " 返回异常: " + resJson);
return;

View File

@@ -27,7 +27,7 @@ public class LeTool extends PanBase implements IPanTool {
client.postAbs(apiUrl1)
.sendJsonObject(JsonObject.of("shareId", dataKey, "password", pwd, "directoryId", -1))
.onSuccess(res -> {
JsonObject resJson = res.bodyAsJsonObject();
JsonObject resJson = asJson(res);
if (resJson.containsKey("result")) {
if (resJson.getBoolean("result")) {
JsonObject dataJson = resJson.getJsonObject("data");
@@ -68,7 +68,7 @@ public class LeTool extends PanBase implements IPanTool {
client.postAbs(apiUrl2)
.sendJsonObject(JsonObject.of("fileIds", fileIds, "shareId", key, "browserId", uuid))
.onSuccess(res -> {
JsonObject resJson = res.bodyAsJsonObject();
JsonObject resJson = asJson(res);
if (resJson.containsKey("result")) {
if (resJson.getBoolean("result")) {
JsonObject dataJson = resJson.getJsonObject("data");

View File

@@ -115,7 +115,7 @@ public class LzTool extends PanBase implements IPanTool {
String url = SHARE_URL_PREFIX + "/ajaxm.php";
client.postAbs(url).putHeaders(headers).sendForm(map).onSuccess(res2 -> {
JsonObject urlJson = res2.bodyAsJsonObject();
JsonObject urlJson = asJson(res2);
if (urlJson.getInteger("zt") != 1) {
fail(urlJson.getString("inf"));
return;

View File

@@ -50,7 +50,7 @@ public class WsTool extends PanBase implements IPanTool {
if (res.statusCode() == 200) {
try {
// 设置匿名登录token
String token = res.bodyAsJsonObject().getJsonObject("data").getString("token");
String token = asJson(res).getJsonObject("data").getString("token");
headers.set("X-Token", token);
// 获取文件夹信息
@@ -63,10 +63,10 @@ public class WsTool extends PanBase implements IPanTool {
if (res2.statusCode() == 200) {
try {
// 获取文件夹信息
String filetime = res2.bodyAsJsonObject().getJsonObject("data").getString("expire"); // 文件夹剩余时间
String filesize = res2.bodyAsJsonObject().getJsonObject("data").getString("file_size"); // 文件夹大小
String filepid = res2.bodyAsJsonObject().getJsonObject("data").getString("ufileid"); // 文件夹pid
String filebid = res2.bodyAsJsonObject().getJsonObject("data").getString("boxid"); // 文件夹bid
String filetime = asJson(res2).getJsonObject("data").getString("expire"); // 文件夹剩余时间
String filesize = asJson(res2).getJsonObject("data").getString("file_size"); // 文件夹大小
String filepid = asJson(res2).getJsonObject("data").getString("ufileid"); // 文件夹pid
String filebid = asJson(res2).getJsonObject("data").getString("boxid"); // 文件夹bid
// 调试输出文件夹信息
System.out.println("文件夹期限: " + filetime);
@@ -93,9 +93,9 @@ public class WsTool extends PanBase implements IPanTool {
if (res3.statusCode() == 200) {
try {
// 获取文件信息
String filename = res3.bodyAsJsonObject().getJsonObject("data")
String filename = asJson(res3).getJsonObject("data")
.getJsonArray("fileList").getJsonObject(0).getString("fname"); // 文件名称
String filefid = res3.bodyAsJsonObject().getJsonObject("data")
String filefid = asJson(res3).getJsonObject("data")
.getJsonArray("fileList").getJsonObject(0).getString("fid"); // 文件fid
// 调试输出文件信息
@@ -113,7 +113,7 @@ public class WsTool extends PanBase implements IPanTool {
if (res4.statusCode() == 200) {
try {
// 获取直链
String fileurl = res4.bodyAsJsonObject().getJsonObject("data").getString("url");
String fileurl = asJson(res4).getJsonObject("data").getString("url");
// 调试输出文件直链
System.out.println("文件直链: " + fileurl);

View File

@@ -70,7 +70,7 @@ public class YeTool extends PanBase implements IPanTool {
.putHeader("Platform", "web")
.putHeader("App-Version", "3")
.send().onSuccess(res2 -> {
JsonObject infoJson = res2.bodyAsJsonObject();
JsonObject infoJson = asJson(res2);
if (infoJson.getInteger("code") != 0) {
fail("{} 状态码异常 {}", dataKey, infoJson);
return;
@@ -121,7 +121,7 @@ public class YeTool extends PanBase implements IPanTool {
.putHeader("Platform", "web")
.putHeader("App-Version", "3")
.sendJsonObject(jsonObject).onSuccess(res2 -> {
JsonObject downURLJson = res2.bodyAsJsonObject();
JsonObject downURLJson = asJson(res2);
try {
if (downURLJson.getInteger("code") != 0) {
@@ -141,7 +141,7 @@ public class YeTool extends PanBase implements IPanTool {
// 获取直链
client.getAbs(downUrl2).send().onSuccess(res3 -> {
JsonObject res3Json = res3.bodyAsJsonObject();
JsonObject res3Json = asJson(res3);
try {
if (res3Json.getInteger("code") != 0) {
fail("Ye: downUrl2返回值异常->" + res3Json);

View File

@@ -25,7 +25,6 @@
<packageDirectory>${project.basedir}/web-service/target/package</packageDirectory>
<slf4j.version>2.0.5</slf4j.version>
<vertx.version>4.5.6</vertx.version>
<org.reflections.version>0.10.2</org.reflections.version>
<lombok.version>1.18.30</lombok.version>

View File

@@ -9,7 +9,10 @@
content="Netdisk fast download,网盘直链解析工具">
<meta name="description"
content="Netdisk fast download 网盘直链解析工具">
<script charset="UTF-8" id="LA_COLLECT" src="//sdk.51.la/js-sdk-pro.min.js"></script>
<script>LA.init({id:"K8zkCkZMgFA6ShZK",ck:"K8zkCkZMgFA6ShZK"})</script>
<script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-9851170484804006"
crossorigin="anonymous"></script>
<style>
.page-loading-wrap {
padding: 120px;

View File

@@ -133,15 +133,26 @@ GET http://127.0.0.1:6400/le/2RkKbLP9BrppS9b43@ex2b
GET http://127.0.0.1:6400/json/le/2RkKbLP9BrppS9b43@ex2b
### PASS 文叔叔
GET http://127.0.0.1:6400/parser?url=https://f.ws59.cn/f/f25625rv6p6
GET http://127.0.0.1:6400/json/parser?url=https://f.ws28.cn/f/f5wtc2iwxtk
###
https://f.wss.cc/f/f25625rv6p6
### TODO Cloudreve
GET http://127.0.0.1:6400/json/ce/https_pan.huang1111.cn_s_wDz5TK
GET http://127.0.0.1:6400/json/ce/pan.huang1111.cn_s_wDz5TK
### TODO Cloudreve2
GET http://127.0.0.1:6400/json/ce/pan.huang1111.cn_s_g31PcQ@qaiu
### Cloudreve类 PASS
### https://pan.huang1111.cn/s/g31PcQ
### 看见存储 https://pan.seeoss.com/s/nLNsQ
### 亿安云盘 https://dav.yiandrive.com/s/xxx
#GET http://127.0.0.1:6400/parser?url=https://pan.huang1111.cn/s/g31PcQ&pwd=qaiu
# @no-redirect
GET http://127.0.0.1:6400/v2/linkInfo?url=https://pan.seeoss.com/s/nLNsQ
### Cloudreve https://pan.huang1111.cn/s/g31PcQ
GET http://127.0.0.1:6400/parser?url=https://pan.huang1111.cn/s/g31PcQ&pwd=qaiu
### PASS QQ
# @no-redirect