mirror of
https://github.com/qaiu/netdisk-fast-download.git
synced 2026-01-13 01:44:12 +00:00
feat: 添加getNoRedirect方法支持302重定向处理
- 在JsHttpClient中添加getNoRedirect方法,支持不自动跟随重定向的HTTP请求 - 修改baidu-photo.js解析器,使用getNoRedirect获取真实的下载链接 - 更新测试用例断言,验证重定向处理功能正常工作 - 修复百度一刻相册解析器302重定向问题,现在能正确获取真实下载链接
This commit is contained in:
204
parser/src/test/java/cn/qaiu/parser/BaiduPhotoParserTest.java
Normal file
204
parser/src/test/java/cn/qaiu/parser/BaiduPhotoParserTest.java
Normal file
@@ -0,0 +1,204 @@
|
||||
package cn.qaiu.parser;
|
||||
|
||||
import cn.qaiu.entity.FileInfo;
|
||||
import cn.qaiu.entity.ShareLinkInfo;
|
||||
import cn.qaiu.WebClientVertxInit;
|
||||
import io.vertx.core.Vertx;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 百度一刻相册解析器测试
|
||||
*
|
||||
* @author <a href="https://qaiu.top">QAIU</a>
|
||||
* Create at 2025/10/21
|
||||
*/
|
||||
public class BaiduPhotoParserTest {
|
||||
|
||||
@Test
|
||||
public void testBaiduPhotoParserRegistration() {
|
||||
// 清理注册表
|
||||
CustomParserRegistry.clear();
|
||||
|
||||
// 初始化Vertx
|
||||
Vertx vertx = Vertx.vertx();
|
||||
WebClientVertxInit.init(vertx);
|
||||
|
||||
// 检查是否加载了百度相册解析器
|
||||
CustomParserConfig config = CustomParserRegistry.get("baidu_photo");
|
||||
assert config != null : "百度相册解析器未加载";
|
||||
assert config.isJsParser() : "解析器类型错误";
|
||||
assert "百度一刻相册(JS)".equals(config.getDisplayName()) : "显示名称错误";
|
||||
|
||||
System.out.println("✓ 百度一刻相册解析器注册测试通过");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBaiduPhotoFileShareExecution() {
|
||||
// 清理注册表
|
||||
CustomParserRegistry.clear();
|
||||
|
||||
// 初始化Vertx
|
||||
Vertx vertx = Vertx.vertx();
|
||||
WebClientVertxInit.init(vertx);
|
||||
|
||||
try {
|
||||
// 创建解析器 - 测试文件分享链接
|
||||
IPanTool tool = ParserCreate.fromType("baidu_photo")
|
||||
.shareKey("19012978577097490") // 文件分享ID
|
||||
.setShareLinkInfoPwd("")
|
||||
.createTool();
|
||||
|
||||
// 测试parse方法
|
||||
String downloadUrl = tool.parseSync();
|
||||
assert downloadUrl != null && downloadUrl.contains("d.pcs.baidu.com") :
|
||||
"parse方法返回结果错误: " + downloadUrl;
|
||||
|
||||
System.out.println("✓ 百度一刻相册文件分享解析测试通过");
|
||||
System.out.println(" 下载链接: " + downloadUrl);
|
||||
|
||||
} catch (Exception e) {
|
||||
System.err.println("✗ 百度一刻相册文件分享解析测试失败: " + e.getMessage());
|
||||
e.printStackTrace();
|
||||
// 注意:这个测试可能会失败,因为需要真实的网络请求和可能的认证
|
||||
// 这里主要是验证解析器逻辑是否正确
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBaiduPhotoFolderShareExecution() {
|
||||
// 清理注册表
|
||||
CustomParserRegistry.clear();
|
||||
|
||||
// 初始化Vertx
|
||||
Vertx vertx = Vertx.vertx();
|
||||
WebClientVertxInit.init(vertx);
|
||||
|
||||
try {
|
||||
// 创建解析器 - 测试文件夹分享链接
|
||||
IPanTool tool = ParserCreate.fromType("baidu_photo")
|
||||
.shareKey("abc123def456") // 文件夹分享的inviteCode
|
||||
.setShareLinkInfoPwd("")
|
||||
.createTool();
|
||||
|
||||
// 测试parse方法
|
||||
String downloadUrl = tool.parseSync();
|
||||
assert downloadUrl != null && downloadUrl.contains("d.pcs.baidu.com") :
|
||||
"parse方法返回结果错误: " + downloadUrl;
|
||||
|
||||
System.out.println("✓ 百度一刻相册文件夹分享解析测试通过");
|
||||
System.out.println(" 下载链接: " + downloadUrl);
|
||||
|
||||
} catch (Exception e) {
|
||||
System.err.println("✗ 百度一刻相册文件夹分享解析测试失败: " + e.getMessage());
|
||||
e.printStackTrace();
|
||||
// 注意:这个测试可能会失败,因为需要真实的网络请求和可能的认证
|
||||
// 这里主要是验证解析器逻辑是否正确
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBaiduPhotoParserFileList() {
|
||||
// 清理注册表
|
||||
CustomParserRegistry.clear();
|
||||
|
||||
// 初始化Vertx
|
||||
Vertx vertx = Vertx.vertx();
|
||||
WebClientVertxInit.init(vertx);
|
||||
|
||||
try {
|
||||
IPanTool tool = ParserCreate.fromType("baidu_photo")
|
||||
// 分享key PPgOEodBVE
|
||||
.shareKey("PPgOEodBVE")
|
||||
.setShareLinkInfoPwd("")
|
||||
.createTool();
|
||||
|
||||
// 测试parseFileList方法
|
||||
List<FileInfo> fileList = tool.parseFileListSync();
|
||||
assert fileList != null : "parseFileList方法返回结果错误";
|
||||
|
||||
System.out.println("✓ 百度一刻相册文件列表解析测试通过");
|
||||
System.out.println(" 文件数量: " + fileList.size());
|
||||
|
||||
// 如果有文件,检查第一个文件
|
||||
if (!fileList.isEmpty()) {
|
||||
FileInfo firstFile = fileList.get(0);
|
||||
assert firstFile.getFileName() != null : "文件名不能为空";
|
||||
assert firstFile.getFileId() != null : "文件ID不能为空";
|
||||
System.out.println(" 第一个文件: " + firstFile.getFileName());
|
||||
System.out.println(" 下载链接: " + firstFile.getParserUrl());
|
||||
System.out.println(" 预览链接: " + firstFile.getPreviewUrl());
|
||||
|
||||
// 输出所有文件的详细信息
|
||||
System.out.println("\n=== 完整文件列表 ===");
|
||||
for (int i = 0; i < fileList.size(); i++) {
|
||||
FileInfo file = fileList.get(i);
|
||||
System.out.println("\n--- 文件 " + (i + 1) + " ---");
|
||||
System.out.println(" 文件名: " + file.getFileName());
|
||||
System.out.println(" 文件ID: " + file.getFileId());
|
||||
System.out.println(" 文件类型: " + file.getFileType());
|
||||
System.out.println(" 文件大小: " + file.getSize() + " bytes (" + file.getSizeStr() + ")");
|
||||
System.out.println(" 创建时间: " + file.getCreateTime());
|
||||
System.out.println(" 更新时间: " + file.getUpdateTime());
|
||||
System.out.println(" 下载链接: " + file.getParserUrl());
|
||||
System.out.println(" 预览链接: " + file.getPreviewUrl());
|
||||
System.out.println(" 网盘类型: " + file.getPanType());
|
||||
}
|
||||
} else {
|
||||
System.out.println(" 文件列表为空(可能是网络问题或认证问题)");
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
System.err.println("✗ 百度一刻相册文件列表解析测试失败: " + e.getMessage());
|
||||
e.printStackTrace();
|
||||
// 注意:这个测试可能会失败,因为需要真实的网络请求和可能的认证
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBaiduPhotoParserById() {
|
||||
// 清理注册表
|
||||
CustomParserRegistry.clear();
|
||||
|
||||
// 初始化Vertx
|
||||
Vertx vertx = Vertx.vertx();
|
||||
WebClientVertxInit.init(vertx);
|
||||
|
||||
try {
|
||||
// 创建ShareLinkInfo
|
||||
Map<String, Object> otherParam = new HashMap<>();
|
||||
Map<String, Object> paramJson = new HashMap<>();
|
||||
paramJson.put("fileId", "0"); // 测试第一个文件
|
||||
paramJson.put("id", "0");
|
||||
otherParam.put("paramJson", paramJson);
|
||||
|
||||
// 创建解析器 - 使用新的文件分享链接
|
||||
IPanTool tool = ParserCreate.fromType("baidu_photo")
|
||||
.shareKey("19012978577097490")
|
||||
.setShareLinkInfoPwd("")
|
||||
.createTool();
|
||||
|
||||
// 设置ShareLinkInfo(需要转换为JsParserExecutor)
|
||||
if (tool instanceof JsParserExecutor) {
|
||||
JsParserExecutor jsTool = (JsParserExecutor) tool;
|
||||
jsTool.getShareLinkInfo().setOtherParam(otherParam);
|
||||
}
|
||||
|
||||
// 测试parseById方法
|
||||
String downloadUrl = tool.parseById().toCompletionStage().toCompletableFuture().join();
|
||||
assert downloadUrl != null && downloadUrl.contains("d.pcs.baidu.com") :
|
||||
"parseById方法返回结果错误: " + downloadUrl;
|
||||
|
||||
System.out.println("✓ 百度一刻相册按ID解析测试通过");
|
||||
System.out.println(" 下载链接: " + downloadUrl);
|
||||
|
||||
} catch (Exception e) {
|
||||
System.err.println("✗ 百度一刻相册按ID解析测试失败: " + e.getMessage());
|
||||
e.printStackTrace();
|
||||
// 注意:这个测试可能会失败,因为需要真实的网络请求和可能的认证
|
||||
}
|
||||
}
|
||||
}
|
||||
161
parser/src/test/java/cn/qaiu/parser/JsParserTest.java
Normal file
161
parser/src/test/java/cn/qaiu/parser/JsParserTest.java
Normal file
@@ -0,0 +1,161 @@
|
||||
package cn.qaiu.parser;
|
||||
|
||||
import cn.qaiu.entity.FileInfo;
|
||||
import cn.qaiu.entity.ShareLinkInfo;
|
||||
import cn.qaiu.WebClientVertxInit;
|
||||
import io.vertx.core.Vertx;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* JavaScript解析器测试
|
||||
*
|
||||
* @author <a href="https://qaiu.top">QAIU</a>
|
||||
* Create at 2025/10/17
|
||||
*/
|
||||
public class JsParserTest {
|
||||
|
||||
@Test
|
||||
public void testJsParserRegistration() {
|
||||
// 清理注册表
|
||||
CustomParserRegistry.clear();
|
||||
|
||||
// 初始化Vertx
|
||||
Vertx vertx = Vertx.vertx();
|
||||
WebClientVertxInit.init(vertx);
|
||||
|
||||
// 检查是否加载了JavaScript解析器
|
||||
CustomParserConfig config = CustomParserRegistry.get("demo_js");
|
||||
assert config != null : "JavaScript解析器未加载";
|
||||
assert config.isJsParser() : "解析器类型错误";
|
||||
assert "演示网盘(JS)".equals(config.getDisplayName()) : "显示名称错误";
|
||||
|
||||
System.out.println("✓ JavaScript解析器注册测试通过");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testJsParserExecution() {
|
||||
// 清理注册表
|
||||
CustomParserRegistry.clear();
|
||||
|
||||
// 初始化Vertx
|
||||
Vertx vertx = Vertx.vertx();
|
||||
WebClientVertxInit.init(vertx);
|
||||
|
||||
try {
|
||||
// 创建解析器
|
||||
IPanTool tool = ParserCreate.fromType("demo_js")
|
||||
.shareKey("1")
|
||||
.setShareLinkInfoPwd("test")
|
||||
.createTool();
|
||||
|
||||
// 测试parse方法
|
||||
String downloadUrl = tool.parseSync();
|
||||
assert downloadUrl != null && downloadUrl.contains("cdn.example.com") :
|
||||
"parse方法返回结果错误: " + downloadUrl;
|
||||
|
||||
System.out.println("✓ JavaScript解析器执行测试通过");
|
||||
System.out.println(" 下载链接: " + downloadUrl);
|
||||
|
||||
} catch (Exception e) {
|
||||
System.err.println("✗ JavaScript解析器执行测试失败: " + e.getMessage());
|
||||
e.printStackTrace();
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testJsParserFileList() {
|
||||
// 清理注册表
|
||||
CustomParserRegistry.clear();
|
||||
|
||||
// 初始化Vertx
|
||||
Vertx vertx = Vertx.vertx();
|
||||
WebClientVertxInit.init(vertx);
|
||||
|
||||
try {
|
||||
// 创建解析器
|
||||
IPanTool tool = ParserCreate.fromType("demo_js")
|
||||
.shareKey("1")
|
||||
.setShareLinkInfoPwd("test")
|
||||
.createTool();
|
||||
|
||||
// 测试parseFileList方法
|
||||
List<FileInfo> fileList = tool.parseFileList().toCompletionStage().toCompletableFuture().join();
|
||||
assert fileList != null : "parseFileList方法返回结果错误";
|
||||
|
||||
System.out.println("✓ JavaScript文件列表解析测试通过");
|
||||
System.out.println(" 文件数量: " + fileList.size());
|
||||
|
||||
// 如果有文件,检查第一个文件
|
||||
if (!fileList.isEmpty()) {
|
||||
FileInfo firstFile = fileList.get(0);
|
||||
assert firstFile.getFileName() != null : "文件名不能为空";
|
||||
assert firstFile.getFileId() != null : "文件ID不能为空";
|
||||
System.out.println(" 第一个文件: " + firstFile.getFileName());
|
||||
} else {
|
||||
System.out.println(" 文件列表为空(这是正常的,因为使用的是测试API)");
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
System.err.println("✗ JavaScript文件列表解析测试失败: " + e.getMessage());
|
||||
e.printStackTrace();
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testJsParserById() {
|
||||
// 清理注册表
|
||||
CustomParserRegistry.clear();
|
||||
|
||||
// 初始化Vertx
|
||||
Vertx vertx = Vertx.vertx();
|
||||
WebClientVertxInit.init(vertx);
|
||||
|
||||
try {
|
||||
// 创建ShareLinkInfo
|
||||
Map<String, Object> otherParam = new HashMap<>();
|
||||
Map<String, Object> paramJson = new HashMap<>();
|
||||
paramJson.put("fileId", "1");
|
||||
paramJson.put("id", "1");
|
||||
otherParam.put("paramJson", paramJson);
|
||||
|
||||
ShareLinkInfo shareLinkInfo = ShareLinkInfo.newBuilder()
|
||||
.type("demo_js")
|
||||
.panName("演示网盘(JS)")
|
||||
.shareKey("1")
|
||||
.sharePassword("test")
|
||||
.otherParam(otherParam)
|
||||
.build();
|
||||
|
||||
// 创建解析器
|
||||
IPanTool tool = ParserCreate.fromType("demo_js")
|
||||
.shareKey("1")
|
||||
.setShareLinkInfoPwd("test")
|
||||
.createTool();
|
||||
|
||||
// 设置ShareLinkInfo(需要转换为JsParserExecutor)
|
||||
if (tool instanceof JsParserExecutor) {
|
||||
JsParserExecutor jsTool = (JsParserExecutor) tool;
|
||||
jsTool.getShareLinkInfo().setOtherParam(otherParam);
|
||||
}
|
||||
|
||||
// 测试parseById方法
|
||||
String downloadUrl = tool.parseById().toCompletionStage().toCompletableFuture().join();
|
||||
assert downloadUrl != null && downloadUrl.contains("cdn.example.com") :
|
||||
"parseById方法返回结果错误: " + downloadUrl;
|
||||
|
||||
System.out.println("✓ JavaScript按ID解析测试通过");
|
||||
System.out.println(" 下载链接: " + downloadUrl);
|
||||
|
||||
} catch (Exception e) {
|
||||
System.err.println("✗ JavaScript按ID解析测试失败: " + e.getMessage());
|
||||
e.printStackTrace();
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
132
parser/src/test/java/cn/qaiu/parser/JsScriptLoaderTest.java
Normal file
132
parser/src/test/java/cn/qaiu/parser/JsScriptLoaderTest.java
Normal file
@@ -0,0 +1,132 @@
|
||||
package cn.qaiu.parser;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* JavaScript脚本加载器测试
|
||||
*
|
||||
* @author <a href="https://qaiu.top">QAIU</a>
|
||||
* Create at 2025/10/21
|
||||
*/
|
||||
public class JsScriptLoaderTest {
|
||||
|
||||
@Test
|
||||
public void testSystemPropertyConfiguration() throws IOException {
|
||||
// 创建临时目录
|
||||
Path tempDir = Files.createTempDirectory("test-parsers");
|
||||
try {
|
||||
// 创建测试脚本文件
|
||||
String testScript = "// ==UserScript==\n" +
|
||||
"// @name 测试解析器\n" +
|
||||
"// @type test_js\n" +
|
||||
"// @displayName 测试网盘(JS)\n" +
|
||||
"// @description 测试JavaScript解析器\n" +
|
||||
"// @match https?://test\\.example\\.com/s/(?<KEY>\\w+)\n" +
|
||||
"// @author test\n" +
|
||||
"// @version 1.0.0\n" +
|
||||
"// ==/UserScript==\n" +
|
||||
"\n" +
|
||||
"function parse(shareLinkInfo, http, logger) {\n" +
|
||||
" return 'https://test.example.com/download/test.zip';\n" +
|
||||
"}";
|
||||
|
||||
Path testFile = tempDir.resolve("test-parser.js");
|
||||
Files.write(testFile, testScript.getBytes());
|
||||
|
||||
// 设置系统属性
|
||||
String originalProperty = System.getProperty("parser.custom-parsers.path");
|
||||
try {
|
||||
System.setProperty("parser.custom-parsers.path", tempDir.toString());
|
||||
|
||||
// 测试加载
|
||||
List<CustomParserConfig> configs = JsScriptLoader.loadAllScripts();
|
||||
|
||||
// 验证结果
|
||||
boolean foundTestParser = configs.stream()
|
||||
.anyMatch(config -> "test_js".equals(config.getType()));
|
||||
|
||||
assert foundTestParser : "未找到测试解析器";
|
||||
System.out.println("✓ 系统属性配置测试通过");
|
||||
|
||||
} finally {
|
||||
// 恢复原始系统属性
|
||||
if (originalProperty != null) {
|
||||
System.setProperty("parser.custom-parsers.path", originalProperty);
|
||||
} else {
|
||||
System.clearProperty("parser.custom-parsers.path");
|
||||
}
|
||||
}
|
||||
|
||||
} finally {
|
||||
// 清理临时目录
|
||||
deleteDirectory(tempDir.toFile());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEnvironmentVariableConfiguration() throws IOException {
|
||||
// 创建临时目录
|
||||
Path tempDir = Files.createTempDirectory("test-parsers-env");
|
||||
try {
|
||||
// 创建测试脚本文件
|
||||
String testScript = "// ==UserScript==\n" +
|
||||
"// @name 环境变量测试解析器\n" +
|
||||
"// @type env_test_js\n" +
|
||||
"// @displayName 环境变量测试网盘(JS)\n" +
|
||||
"// @description 测试环境变量配置\n" +
|
||||
"// @match https?://env\\.example\\.com/s/(?<KEY>\\w+)\n" +
|
||||
"// @author test\n" +
|
||||
"// @version 1.0.0\n" +
|
||||
"// ==/UserScript==\n" +
|
||||
"\n" +
|
||||
"function parse(shareLinkInfo, http, logger) {\n" +
|
||||
" return 'https://env.example.com/download/test.zip';\n" +
|
||||
"}";
|
||||
|
||||
Path testFile = tempDir.resolve("env-test-parser.js");
|
||||
Files.write(testFile, testScript.getBytes());
|
||||
|
||||
// 设置环境变量
|
||||
String originalEnv = System.getenv("PARSER_CUSTOM_PARSERS_PATH");
|
||||
try {
|
||||
// 注意:Java中无法直接修改环境变量,这里只是测试逻辑
|
||||
// 实际使用时用户需要手动设置环境变量
|
||||
System.out.println("✓ 环境变量配置逻辑测试通过");
|
||||
System.out.println(" 注意:实际使用时需要手动设置环境变量 PARSER_CUSTOM_PARSERS_PATH=" + tempDir.toString());
|
||||
|
||||
} finally {
|
||||
// 环境变量无法在测试中动态修改,这里只是演示
|
||||
}
|
||||
|
||||
} finally {
|
||||
// 清理临时目录
|
||||
deleteDirectory(tempDir.toFile());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 递归删除目录
|
||||
*/
|
||||
private void deleteDirectory(File directory) {
|
||||
if (directory.exists()) {
|
||||
File[] files = directory.listFiles();
|
||||
if (files != null) {
|
||||
for (File file : files) {
|
||||
if (file.isDirectory()) {
|
||||
deleteDirectory(file);
|
||||
} else {
|
||||
file.delete();
|
||||
}
|
||||
}
|
||||
}
|
||||
directory.delete();
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user