mirror of
https://github.com/qaiu/netdisk-fast-download.git
synced 2026-02-03 03:46:18 +00:00
Compare commits
2 Commits
2f22cb01eb
...
69d5f269bd
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
69d5f269bd | ||
|
|
459c974cb8 |
@@ -5,6 +5,7 @@ import cn.qaiu.entity.ShareLinkInfo;
|
|||||||
import cn.qaiu.parser.PanBase;
|
import cn.qaiu.parser.PanBase;
|
||||||
import cn.qaiu.util.FileSizeConverter;
|
import cn.qaiu.util.FileSizeConverter;
|
||||||
import io.vertx.core.Future;
|
import io.vertx.core.Future;
|
||||||
|
import io.vertx.core.MultiMap;
|
||||||
import io.vertx.core.Promise;
|
import io.vertx.core.Promise;
|
||||||
import io.vertx.core.json.JsonArray;
|
import io.vertx.core.json.JsonArray;
|
||||||
import io.vertx.core.json.JsonObject;
|
import io.vertx.core.json.JsonObject;
|
||||||
@@ -22,17 +23,48 @@ public class LeTool extends PanBase {
|
|||||||
private static final String DEFAULT_FILE_TYPE = "file";
|
private static final String DEFAULT_FILE_TYPE = "file";
|
||||||
private static final int FILE_TYPE_DIRECTORY = 0; // 目录类型
|
private static final int FILE_TYPE_DIRECTORY = 0; // 目录类型
|
||||||
|
|
||||||
|
private static final MultiMap HEADERS;
|
||||||
|
|
||||||
|
static {
|
||||||
|
HEADERS = MultiMap.caseInsensitiveMultiMap();
|
||||||
|
HEADERS.set("Accept", "application/json, text/plain, */*");
|
||||||
|
HEADERS.set("Accept-Language", "zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6");
|
||||||
|
HEADERS.set("Cache-Control", "no-cache");
|
||||||
|
HEADERS.set("Connection", "keep-alive");
|
||||||
|
HEADERS.set("Content-Type", "application/json");
|
||||||
|
HEADERS.set("DNT", "1");
|
||||||
|
HEADERS.set("Origin", "https://lecloud.lenovo.com");
|
||||||
|
HEADERS.set("Pragma", "no-cache");
|
||||||
|
HEADERS.set("Sec-Fetch-Dest", "empty");
|
||||||
|
HEADERS.set("Sec-Fetch-Mode", "cors");
|
||||||
|
HEADERS.set("Sec-Fetch-Site", "same-origin");
|
||||||
|
HEADERS.set("User-Agent", "Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Mobile/15E148 Safari/604.1 Edg/143.0.0.0");
|
||||||
|
}
|
||||||
|
|
||||||
public LeTool(ShareLinkInfo shareLinkInfo) {
|
public LeTool(ShareLinkInfo shareLinkInfo) {
|
||||||
super(shareLinkInfo);
|
super(shareLinkInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取干净的 shareId(去掉可能的查询参数)
|
||||||
|
* URL 如 https://lecloud.lenovo.com/share/5eoN3RA5PLhQcH4zE?path=... 会导致 shareKey 包含查询参数
|
||||||
|
*/
|
||||||
|
private String getCleanShareId() {
|
||||||
|
String shareKey = shareLinkInfo.getShareKey();
|
||||||
|
if (shareKey != null && shareKey.contains("?")) {
|
||||||
|
return shareKey.split("\\?")[0];
|
||||||
|
}
|
||||||
|
return shareKey;
|
||||||
|
}
|
||||||
|
|
||||||
public Future<String> parse() {
|
public Future<String> parse() {
|
||||||
final String dataKey = shareLinkInfo.getShareKey();
|
final String dataKey = getCleanShareId();
|
||||||
final String pwd = shareLinkInfo.getSharePassword();
|
final String pwd = shareLinkInfo.getSharePassword();
|
||||||
// {"shareId":"xxx","password":"xxx","directoryId":"-1"}
|
// {"shareId":"xxx","password":"xxx","directoryId":"-1"}
|
||||||
String apiUrl1 = API_URL_PREFIX + "shareInfo";
|
String apiUrl1 = API_URL_PREFIX + "shareInfo";
|
||||||
client.postAbs(apiUrl1)
|
client.postAbs(apiUrl1)
|
||||||
.sendJsonObject(JsonObject.of("shareId", dataKey, "password", pwd, "directoryId", "-1"))
|
.putHeaders(HEADERS)
|
||||||
|
.sendJsonObject(JsonObject.of("shareId", dataKey, "password", pwd, "directoryId", "-1"))
|
||||||
.onSuccess(res -> {
|
.onSuccess(res -> {
|
||||||
JsonObject resJson = asJson(res);
|
JsonObject resJson = asJson(res);
|
||||||
if (resJson.containsKey("result")) {
|
if (resJson.containsKey("result")) {
|
||||||
@@ -83,28 +115,17 @@ public class LeTool extends PanBase {
|
|||||||
public Future<List<FileInfo>> parseFileList() {
|
public Future<List<FileInfo>> parseFileList() {
|
||||||
Promise<List<FileInfo>> listPromise = Promise.promise();
|
Promise<List<FileInfo>> listPromise = Promise.promise();
|
||||||
|
|
||||||
String dataKey = shareLinkInfo.getShareKey();
|
String dataKey = getCleanShareId();
|
||||||
|
|
||||||
// 如果参数里的目录ID不为空,则直接解析目录
|
// 如果参数里的目录ID不为空,则直接解析目录
|
||||||
String dirId = (String) shareLinkInfo.getOtherParam().get("dirId");
|
String dirId = (String) shareLinkInfo.getOtherParam().get("dirId");
|
||||||
if (dirId != null && !dirId.isEmpty()) {
|
if (dirId == null || dirId.isEmpty()) {
|
||||||
parseDirectory(dirId, dataKey, listPromise);
|
// 如果没有指定目录ID,使用根目录ID "-1"
|
||||||
return listPromise.future();
|
dirId = "-1";
|
||||||
}
|
}
|
||||||
|
|
||||||
// 先解析获取根目录ID
|
// 直接请求shareInfo接口解析目录
|
||||||
parse().onSuccess(id -> {
|
parseDirectory(dirId, dataKey, listPromise);
|
||||||
if (id != null && !id.isEmpty()) {
|
|
||||||
// 解析目录
|
|
||||||
parseDirectory(id, dataKey, listPromise);
|
|
||||||
} else {
|
|
||||||
listPromise.fail("解析目录ID失败");
|
|
||||||
}
|
|
||||||
}).onFailure(failRes -> {
|
|
||||||
log.error("解析目录失败: {}", failRes.getMessage());
|
|
||||||
listPromise.fail(failRes);
|
|
||||||
});
|
|
||||||
|
|
||||||
return listPromise.future();
|
return listPromise.future();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -112,16 +133,18 @@ public class LeTool extends PanBase {
|
|||||||
* 解析目录下的文件列表
|
* 解析目录下的文件列表
|
||||||
*/
|
*/
|
||||||
private void parseDirectory(String directoryId, String shareId, Promise<List<FileInfo>> promise) {
|
private void parseDirectory(String directoryId, String shareId, Promise<List<FileInfo>> promise) {
|
||||||
log.debug("开始解析目录: directoryId={}, shareId={}", directoryId, shareId);
|
|
||||||
|
|
||||||
String pwd = shareLinkInfo.getSharePassword();
|
String pwd = shareLinkInfo.getSharePassword();
|
||||||
if (pwd == null) {
|
if (pwd == null) {
|
||||||
pwd = "";
|
pwd = "";
|
||||||
}
|
}
|
||||||
String apiUrl = API_URL_PREFIX + "shareInfo";
|
String apiUrl = API_URL_PREFIX + "shareInfo";
|
||||||
|
|
||||||
|
JsonObject requestBody = JsonObject.of("shareId", shareId, "password", pwd, "directoryId", directoryId);
|
||||||
|
log.info("解析目录请求: url={}, body={}", apiUrl, requestBody.encode());
|
||||||
|
|
||||||
client.postAbs(apiUrl)
|
client.postAbs(apiUrl)
|
||||||
.sendJsonObject(JsonObject.of("shareId", shareId, "password", pwd, "directoryId", directoryId))
|
.putHeaders(HEADERS)
|
||||||
|
.sendJsonObject(requestBody)
|
||||||
.onSuccess(res -> {
|
.onSuccess(res -> {
|
||||||
JsonObject resJson = asJson(res);
|
JsonObject resJson = asJson(res);
|
||||||
|
|
||||||
@@ -179,21 +202,12 @@ public class LeTool extends PanBase {
|
|||||||
fileInfo.setFileType("folder");
|
fileInfo.setFileType("folder");
|
||||||
fileInfo.setSize(0L);
|
fileInfo.setSize(0L);
|
||||||
fileInfo.setSizeStr("0B");
|
fileInfo.setSizeStr("0B");
|
||||||
// 设置目录解析的URL - 注意:fileId已经是URL编码的,直接使用
|
// 设置目录解析的URL - 注意:从API返回的fileId已经是URL编码的,直接使用
|
||||||
// 使用 URLEncoder 确保特殊字符被正确编码
|
// 不需要再次编码,避免双重编码导致解析失败
|
||||||
try {
|
fileInfo.setParserUrl(String.format("%s/v2/getFileList?url=%s&dirId=%s",
|
||||||
String encodedFileId = java.net.URLEncoder.encode(fileId, "UTF-8");
|
getDomainName(),
|
||||||
fileInfo.setParserUrl(String.format("%s/v2/getFileList?url=%s&dirId=%s",
|
shareLinkInfo.getShareUrl(),
|
||||||
getDomainName(),
|
fileId));
|
||||||
shareLinkInfo.getShareUrl(),
|
|
||||||
encodedFileId));
|
|
||||||
} catch (Exception e) {
|
|
||||||
// 如果编码失败,直接使用原始fileId
|
|
||||||
fileInfo.setParserUrl(String.format("%s/v2/getFileList?url=%s&dirId=%s",
|
|
||||||
getDomainName(),
|
|
||||||
shareLinkInfo.getShareUrl(),
|
|
||||||
fileId));
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
// 文件类型
|
// 文件类型
|
||||||
fileInfo.setFileType(fileType != null ? String.valueOf(fileType) : DEFAULT_FILE_TYPE);
|
fileInfo.setFileType(fileType != null ? String.valueOf(fileType) : DEFAULT_FILE_TYPE);
|
||||||
@@ -211,7 +225,11 @@ public class LeTool extends PanBase {
|
|||||||
fileInfo.setParserUrl(String.format("%s/v2/redirectUrl/%s/%s",
|
fileInfo.setParserUrl(String.format("%s/v2/redirectUrl/%s/%s",
|
||||||
getDomainName(),
|
getDomainName(),
|
||||||
shareLinkInfo.getType(),
|
shareLinkInfo.getType(),
|
||||||
paramBase64));
|
paramBase64))
|
||||||
|
.setPreviewUrl(String.format("%s/v2/viewUrl/%s/%s",
|
||||||
|
getDomainName(),
|
||||||
|
shareLinkInfo.getType(),
|
||||||
|
paramBase64));
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
@@ -250,7 +268,8 @@ public class LeTool extends PanBase {
|
|||||||
String apiUrl = API_URL_PREFIX + "packageDownloadWithFileIds";
|
String apiUrl = API_URL_PREFIX + "packageDownloadWithFileIds";
|
||||||
|
|
||||||
client.postAbs(apiUrl)
|
client.postAbs(apiUrl)
|
||||||
.sendJsonObject(JsonObject.of("fileIds", fileIds, "shareId", shareId, "browserId", uuid))
|
.putHeaders(HEADERS)
|
||||||
|
.sendJsonObject(JsonObject.of("fileIds", fileIds, "shareId", shareId, "browserId", uuid))
|
||||||
.onSuccess(res -> {
|
.onSuccess(res -> {
|
||||||
JsonObject resJson = asJson(res);
|
JsonObject resJson = asJson(res);
|
||||||
if (resJson.containsKey("result")) {
|
if (resJson.containsKey("result")) {
|
||||||
@@ -280,7 +299,8 @@ public class LeTool extends PanBase {
|
|||||||
String apiUrl2 = API_URL_PREFIX + "packageDownloadWithFileIds";
|
String apiUrl2 = API_URL_PREFIX + "packageDownloadWithFileIds";
|
||||||
// {"fileIds":[123],"shareId":"xxx","browserId":"uuid"}
|
// {"fileIds":[123],"shareId":"xxx","browserId":"uuid"}
|
||||||
client.postAbs(apiUrl2)
|
client.postAbs(apiUrl2)
|
||||||
.sendJsonObject(JsonObject.of("fileIds", fileIds, "shareId", key, "browserId", uuid))
|
.putHeaders(HEADERS)
|
||||||
|
.sendJsonObject(JsonObject.of("fileIds", fileIds, "shareId", key, "browserId", uuid))
|
||||||
.onSuccess(res -> {
|
.onSuccess(res -> {
|
||||||
JsonObject resJson = asJson(res);
|
JsonObject resJson = asJson(res);
|
||||||
if (resJson.containsKey("result")) {
|
if (resJson.containsKey("result")) {
|
||||||
@@ -351,4 +371,4 @@ public class LeTool extends PanBase {
|
|||||||
|
|
||||||
return fileInfo;
|
return fileInfo;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user