From d23b11577e3a673ee71cd80b4eb85c0644f81b90 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Mon, 10 Nov 2025 09:59:48 +0000
Subject: [PATCH] Simplify and optimize Ce4Tool and CeTool version detection
logic
Co-authored-by: qaiu <29825328+qaiu@users.noreply.github.com>
---
.../java/cn/qaiu/parser/impl/Ce4Tool.java | 99 ++++---------------
.../main/java/cn/qaiu/parser/impl/CeTool.java | 85 +++++++---------
2 files changed, 53 insertions(+), 131 deletions(-)
diff --git a/parser/src/main/java/cn/qaiu/parser/impl/Ce4Tool.java b/parser/src/main/java/cn/qaiu/parser/impl/Ce4Tool.java
index a9cdae5..baf5a5b 100644
--- a/parser/src/main/java/cn/qaiu/parser/impl/Ce4Tool.java
+++ b/parser/src/main/java/cn/qaiu/parser/impl/Ce4Tool.java
@@ -12,13 +12,12 @@ import java.net.URL;
/**
* Cloudreve 4.x 自建网盘解析
- * Cloudreve 4.x API 版本解析器
+ * Cloudreve 4.x API 版本解析器
+ * 此解析器专门处理Cloudreve 4.x版本的API,使用新的下载流程
*/
public class Ce4Tool extends PanBase {
// Cloudreve 4.x uses /api/v3/ prefix for most APIs
- private static final String PING_API_V3_PATH = "/api/v3/site/ping";
- private static final String PING_API_V4_PATH = "/api/v4/site/ping";
private static final String FILE_URL_API_PATH = "/api/v3/file/url";
private static final String SHARE_API_PATH = "/api/v3/share/info/";
@@ -34,8 +33,8 @@ public class Ce4Tool extends PanBase {
URL url = new URL(shareLinkInfo.getShareUrl());
String baseUrl = url.getProtocol() + "://" + url.getHost();
- // First, detect API version by pinging
- detectVersion(baseUrl, key, pwd);
+ // 获取分享信息
+ getShareInfo(baseUrl, key, pwd);
} catch (Exception e) {
fail(e, "URL解析错误");
}
@@ -43,61 +42,7 @@ public class Ce4Tool extends PanBase {
}
/**
- * Detect Cloudreve version by pinging /api/v3/site/ping or /api/v4/site/ping
- */
- private void detectVersion(String baseUrl, String key, String pwd) {
- String pingUrlV3 = baseUrl + PING_API_V3_PATH;
-
- // Try v3 ping first (which also works for 4.x)
- clientSession.getAbs(pingUrlV3).send().onSuccess(res -> {
- if (res.statusCode() == 200) {
- try {
- JsonObject pingResponse = asJson(res);
- // If we get a valid JSON response, this is a Cloudreve instance
- // Check if it's 4.x by trying the share API
- getShareInfo(baseUrl, key, pwd);
- } catch (Exception e) {
- // Not a valid JSON response, try v4 ping
- tryV4Ping(baseUrl, key, pwd);
- }
- } else if (res.statusCode() == 404) {
- // Try v4 ping
- tryV4Ping(baseUrl, key, pwd);
- } else {
- // Not a Cloudreve instance, try next parser
- nextParser();
- }
- }).onFailure(t -> {
- // Network error or not accessible, try next parser
- nextParser();
- });
- }
-
- private void tryV4Ping(String baseUrl, String key, String pwd) {
- String pingUrlV4 = baseUrl + PING_API_V4_PATH;
-
- clientSession.getAbs(pingUrlV4).send().onSuccess(res -> {
- if (res.statusCode() == 200) {
- try {
- JsonObject pingResponse = asJson(res);
- // Valid v4 response
- getShareInfo(baseUrl, key, pwd);
- } catch (Exception e) {
- // Not a Cloudreve instance
- nextParser();
- }
- } else {
- // Not a Cloudreve instance
- nextParser();
- }
- }).onFailure(t -> {
- // Not accessible, try next parser
- nextParser();
- });
- }
-
- /**
- * Get share information from Cloudreve 4.x
+ * 获取Cloudreve 4.x分享信息
*/
private void getShareInfo(String baseUrl, String key, String pwd) {
String shareApiUrl = baseUrl + SHARE_API_PATH + key;
@@ -114,49 +59,45 @@ public class Ce4Tool extends PanBase {
if (jsonObject.containsKey("code")) {
int code = jsonObject.getInteger("code");
if (code == 0) {
- // Success, get file info and download URL
+ // 成功,获取文件信息和下载链接
JsonObject data = jsonObject.getJsonObject("data");
if (data != null) {
- // Get file path or use default
+ // 获取文件路径,如果没有则使用默认路径
String filePath = "/";
if (data.containsKey("path")) {
filePath = data.getString("path");
}
- // For 4.x, we need to get the download URL via POST /api/v3/file/url
- getDownloadUrl(baseUrl, key, filePath);
+ // 对于4.x,需要通过 POST /api/v3/file/url 获取下载链接
+ getDownloadUrl(baseUrl, filePath);
} else {
fail("分享信息获取失败: data字段为空");
}
} else {
- // Error code, might be wrong password or invalid share
+ // 错误码,可能是密码错误或分享失效
String msg = jsonObject.getString("msg", "未知错误");
fail("分享验证失败: {}", msg);
}
} else {
- // Not a Cloudreve 4.x response, try next parser
- nextParser();
+ // 响应格式不符合预期
+ fail("响应格式不符合Cloudreve 4.x规范");
}
} else {
- // HTTP error, not a valid Cloudreve instance
- nextParser();
+ // HTTP错误
+ fail("获取分享信息失败: HTTP {}", res.statusCode());
}
} catch (Exception e) {
- // JSON parsing error, not a Cloudreve instance
- nextParser();
+ fail(e, "解析分享信息响应失败");
}
- }).onFailure(t -> {
- // Network error, try next parser
- nextParser();
- });
+ }).onFailure(handleFail(shareApiUrl));
}
/**
- * Get download URL via POST /api/v3/file/url (Cloudreve 4.x API)
+ * 通过 POST /api/v3/file/url 获取下载链接 (Cloudreve 4.x API)
*/
- private void getDownloadUrl(String baseUrl, String key, String filePath) {
+ private void getDownloadUrl(String baseUrl, String filePath) {
String fileUrlApi = baseUrl + FILE_URL_API_PATH;
- // Prepare request body for Cloudreve 4.x
+ // 准备Cloudreve 4.x的请求体
JsonObject requestBody = new JsonObject()
.put("uris", new JsonArray().add(filePath))
.put("download", true);
@@ -182,7 +123,7 @@ public class Ce4Tool extends PanBase {
fail("下载链接列表为空");
}
} else {
- fail("响应中不包含urls字段");
+ fail("响应中不包含urls字段: {}", jsonObject.encodePrettily());
}
} else {
fail("获取下载链接失败: HTTP {}", res.statusCode());
diff --git a/parser/src/main/java/cn/qaiu/parser/impl/CeTool.java b/parser/src/main/java/cn/qaiu/parser/impl/CeTool.java
index 460db22..5a6f4b9 100644
--- a/parser/src/main/java/cn/qaiu/parser/impl/CeTool.java
+++ b/parser/src/main/java/cn/qaiu/parser/impl/CeTool.java
@@ -35,13 +35,7 @@ public class CeTool extends PanBase {
public Future parse() {
String key = shareLinkInfo.getShareKey();
String pwd = shareLinkInfo.getSharePassword();
- // 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/pan.huang1111.cn_s_wDz5TK
- // parser接口 -> /parser?url=https://pan.huang1111.cn/s/wDz5TK
try {
-// // 处理URL
URL url = new URL(shareLinkInfo.getShareUrl());
String baseUrl = url.getProtocol() + "://" + url.getHost();
@@ -55,8 +49,8 @@ public class CeTool extends PanBase {
/**
* 检测Cloudreve版本并选择合适的解析器
- * 先调用 /api/v3/site/ping 或 /api/v4/site/ping 判断是哪个版本
- * 如果都返回404说明不是Cloudreve盘,则调用nextParser
+ * 先调用 /api/v3/site/ping 判断哪个API 如果/v3 或者/v4 能查询到json响应,可以判断是哪个版本
+ * 不然返回404说明不是ce盘直接nextParser
*/
private void detectVersionAndParse(String baseUrl, String key, String pwd) {
String pingUrlV3 = baseUrl + PING_API_V3_PATH;
@@ -65,42 +59,43 @@ public class CeTool extends PanBase {
clientSession.getAbs(pingUrlV3).send().onSuccess(res -> {
if (res.statusCode() == 200) {
try {
- JsonObject pingResponse = asJson(res);
- // 获取到JSON响应,检查是否是4.x版本
- // 4.x的ping响应可能有不同的结构,我们通过share API来判断
- checkVersionByShareApi(baseUrl, key, pwd);
+ asJson(res);
+ // v3 ping成功,可能是3.x或4.x,尝试3.x的download API来判断
+ String shareApiUrl = baseUrl + SHARE_API_PATH + key;
+ String downloadApiUrl = baseUrl + DOWNLOAD_API_PATH + key + "?path=undefined/undefined;";
+ checkIfV3(shareApiUrl, downloadApiUrl, pwd);
} catch (Exception e) {
// JSON解析失败,尝试v4 ping
- tryV4PingAndParse(baseUrl, key, pwd);
+ tryV4Ping(baseUrl, key, pwd);
}
} else if (res.statusCode() == 404) {
// v3 ping不存在,尝试v4
- tryV4PingAndParse(baseUrl, key, pwd);
+ tryV4Ping(baseUrl, key, pwd);
} else {
// 其他错误,不是Cloudreve盘
nextParser();
}
}).onFailure(t -> {
- // 网络错误,尝试下一个解析器
- nextParser();
+ // 网络错误或不可达,尝试v4 ping
+ tryV4Ping(baseUrl, key, pwd);
});
}
- private void tryV4PingAndParse(String baseUrl, String key, String pwd) {
+ private void tryV4Ping(String baseUrl, String key, String pwd) {
String pingUrlV4 = baseUrl + PING_API_V4_PATH;
clientSession.getAbs(pingUrlV4).send().onSuccess(res -> {
if (res.statusCode() == 200) {
try {
- JsonObject pingResponse = asJson(res);
+ asJson(res);
// v4 ping成功,使用Ce4Tool
delegateToCe4Tool();
} catch (Exception e) {
- // 不是Cloudreve盘
+ // JSON解析失败,不是Cloudreve盘
nextParser();
}
} else {
- // 不是Cloudreve盘
+ // v4 ping失败,不是Cloudreve盘
nextParser();
}
}).onFailure(t -> {
@@ -110,11 +105,9 @@ public class CeTool extends PanBase {
}
/**
- * 通过Share API的响应来判断版本
- * 3.x和4.x的share API响应格式可能不同
+ * 检查是否是3.x版本,通过尝试调用3.x的API
*/
- private void checkVersionByShareApi(String baseUrl, String key, String pwd) {
- String shareApiUrl = baseUrl + SHARE_API_PATH + key;
+ private void checkIfV3(String shareApiUrl, String downloadApiUrl, String pwd) {
HttpRequest httpRequest = clientSession.getAbs(shareApiUrl);
if (pwd != null) {
httpRequest.addQueryParam("password", pwd);
@@ -123,12 +116,22 @@ public class CeTool extends PanBase {
httpRequest.send().onSuccess(res -> {
try {
if (res.statusCode() == 200 && res.bodyAsJsonObject().containsKey("code")) {
- JsonObject jsonObject = asJson(res);
- // 检查响应结构来判断版本
- // 如果share API成功,但download API返回404,说明是4.x
- // 这里我们先尝试3.x的download API
- String downloadApiUrl = baseUrl + DOWNLOAD_API_PATH + key + "?path=undefined/undefined;";
- checkDownloadApi(downloadApiUrl, baseUrl, key, pwd);
+ // share API成功,尝试download API
+ clientSession.putAbs(downloadApiUrl).send().onSuccess(res2 -> {
+ if (res2.statusCode() == 200 || res2.statusCode() == 400) {
+ // 3.x版本的download API存在
+ getDownURL(downloadApiUrl);
+ } else if (res2.statusCode() == 404 || res2.statusCode() == 405) {
+ // download API不存在,说明是4.x
+ delegateToCe4Tool();
+ } else {
+ // 其他错误,可能是4.x
+ delegateToCe4Tool();
+ }
+ }).onFailure(t -> {
+ // 请求失败,尝试4.x
+ delegateToCe4Tool();
+ });
} else {
nextParser();
}
@@ -140,28 +143,6 @@ public class CeTool extends PanBase {
});
}
- /**
- * 检查3.x的download API是否存在
- * 如果不存在,说明是4.x版本
- */
- private void checkDownloadApi(String downloadApiUrl, String baseUrl, String key, String pwd) {
- clientSession.putAbs(downloadApiUrl).send().onSuccess(res -> {
- if (res.statusCode() == 404 || res.statusCode() == 405) {
- // download API不存在或方法不允许,说明是4.x
- delegateToCe4Tool();
- } else if (res.statusCode() == 200) {
- // 3.x版本,继续使用当前逻辑
- getDownURL(downloadApiUrl);
- } else {
- // 其他错误
- fail("无法确定Cloudreve版本或接口调用失败");
- }
- }).onFailure(t -> {
- // 尝试使用4.x
- delegateToCe4Tool();
- });
- }
-
/**
* 转发到Ce4Tool处理4.x版本
*/