1. 缓存优化

This commit is contained in:
qaiu
2024-09-18 13:24:33 +08:00
parent a0fe702c10
commit 59d2fb3010
24 changed files with 370 additions and 263 deletions

View File

@@ -66,7 +66,7 @@ public class ShareLinkInfo {
// 建造者类
public static class Builder {
private String shareKey; // 分享键
private String type; // 分享类型
private String type; // 分享类型 (网盘模板枚举的小写)
private String sharePassword = ""; // 分享密码(如果存在)
private String shareUrl; // 原始分享链接
private String standardUrl; // 规范化的标准链接

View File

@@ -4,28 +4,4 @@ import io.vertx.core.Future;
public interface IPanTool {
Future<String> parse();
// 基于枚举PanDomainTemplate匹配分享链接类型
static IPanTool typeMatching(String type, String key, String pwd) {
try {
return PanDomainTemplate
.fromShortName(type)
.generateShareLink(key)
.setShareLinkInfoPwd(pwd)
.createTool();
} catch (Exception e) {
throw new UnsupportedOperationException("未知分享类型", e);
}
}
static IPanTool shareURLPrefixMatching(String url, String pwd) {
try {
return PanDomainTemplate
.fromShareUrl(url)
.setShareLinkInfoPwd(pwd)
.createTool();
} catch (Exception e) {
throw new UnsupportedOperationException("未知分享类型", e);
}
}
}

View File

@@ -1,23 +1,15 @@
package cn.qaiu.parser;
import cn.qaiu.entity.ShareLinkInfo;
import cn.qaiu.parser.impl.*;
import org.apache.commons.lang3.StringUtils;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* 枚举类 PanDomainTemplate 定义了不同网盘服务的模板信息,包括:
* <ul>
* <li>displayName: 网盘服务的显示名称,用于用户界面展示。</li>
* <li>shortName: 网盘服务的简称用于内部逻辑处理例如API路径。</li>
* <li>regexPattern: 用于匹配和解析分享链接的正则表达式。</li>
* <li>standardUrlTemplate: 网盘服务的标准URL模板用于规范化分享链接。</li>
* <li>toolClass: 网盘解析工具实现类。</li>
* </ul>
* 该类提供方法来解析和规范化不同来源的分享链接,确保它们可以转换为统一的标准链接格式。
* 通过这种方式,应用程序可以更容易地处理和识别不同网盘服务的分享链接.
*
* @author <a href="https://qaiu.top">QAIU</a>
* at 2023/6/13 4:26
@@ -26,7 +18,6 @@ public enum PanDomainTemplate {
// 网盘定义
LZ("蓝奏云",
"lz",
"https://([a-z]+)?\\.?lanzou[a-z]\\.com/(.+/)?(.+)",
"https://lanzoux.com/{shareKey}",
LzTool.class),
@@ -34,64 +25,54 @@ public enum PanDomainTemplate {
// https://www.feijix.com/s/
// https://share.feijipan.com/s/
FJ("小飞机网盘",
"fj",
"https://(share\\.feijipan\\.com|www\\.feijix\\.com)/s/(.+)",
"https://www.feijix.com/s/{shareKey}",
FjTool.class),
// https://lecloud.lenovo.com/share/
LE("联想乐云",
"le",
"https://lecloud?\\.lenovo\\.com/share/(.+)",
"https://lecloud.lenovo.com/share/{shareKey}",
LeTool.class),
// https://v2.fangcloud.com/s/
FC("亿方云",
"fc",
"https://v2\\.fangcloud\\.(com|cn)/(s|sharing)/([^/]+)",
"https://v2.fangcloud.com/s/{shareKey}",
FcTool.class),
// https://www.ilanzou.com/s/
IZ("蓝奏云优享",
"iz",
"https://www\\.ilanzou\\.com/s/(.+)",
"https://www.ilanzou.com/s/{shareKey}",
IzTool.class),
// https://wx.mail.qq.com/ftn/download?
QQ("QQ邮箱中转站",
"qq",
"https://i?wx\\.mail\\.qq\\.com/ftn/download\\?(.+)",
"https://iwx.mail.qq.com/ftn/download/{shareKey}",
QQTool.class),
// https://f.ws59.cn/f/或者https://www.wenshushu.cn/f/
WS("文叔叔",
"ws",
"https://(f\\.ws59\\.cn|www\\.wenshushu\\.cn)/f/(.+)",
"https://f.ws59.cn/f/{shareKey}",
WsTool.class),
// https://www.123pan.com/s/
YE("123网盘",
"ye",
"https://www\\.123pan\\.com/s/(.+)\\.html",
"https://www.123pan.com/s/{shareKey}.html",
YeTool.class),
// https://www.ecpan.cn/web/#/yunpanProxy?path=%2F%23%2Fdrive%2Foutside&data={code}&isShare=1
EC("移动云空间",
"ec",
"https://www\\.ecpan\\.cn/web(/%23|/#)?/yunpanProxy\\?path=.*&data=" +
"([^&]+)&isShare=1",
"https://www.ecpan.cn/web/#/yunpanProxy?path=%2F%23%2Fdrive%2Foutside&data={shareKey}&isShare=1",
EcTool.class),
// https://cowtransfer.com/s/
COW("奶牛快传",
"cow",
"https://(.*)cowtransfer\\.com/s/(.+)",
"https://cowtransfer.com/s/{shareKey}",
CowTool.class),
// https://pan.huang1111.cn/s/
CE("huang1111",
"ce",
"https://pan\\.huang1111\\.cn/s/(.+)",
"https://pan.huang1111.cn/s/{shareKey}",
CeTool.class);
@@ -100,79 +81,25 @@ public enum PanDomainTemplate {
// 网盘的显示名称,用于用户界面显示
private final String displayName;
// 网盘的简短名称用于内部逻辑处理如REST API路径
private final String shortName;
// 用于匹配和解析分享链接的正则表达式
private final String regexPattern;
// 网盘的标准链接模板,不含占位符,用于规范化分享链接
private final String standardUrlTemplate;
private final ShareLinkInfo shareLinkInfo;
// 指向IPanTool实现类
// 指向解析工具IPanTool实现类
private final Class<? extends IPanTool> toolClass;
PanDomainTemplate(String displayName, String shortName, String regexPattern,
String standardUrlTemplate, Class<? extends IPanTool> toolClass) {
PanDomainTemplate(String displayName, String regexPattern, String standardUrlTemplate,
Class<? extends IPanTool> toolClass) {
this.displayName = displayName;
this.shortName = shortName;
this.regexPattern = regexPattern;
this.standardUrlTemplate = standardUrlTemplate;
this.toolClass = toolClass;
this.shareLinkInfo = ShareLinkInfo.newBuilder().type(shortName).build();
}
// 解析并规范化分享链接
synchronized public PanDomainTemplate normalizeShareLink() {
if (shareLinkInfo == null) {
throw new IllegalArgumentException("ShareLinkInfo not init");
}
// 匹配并提取shareKey
String shareUrl = shareLinkInfo.getShareUrl();
if (StringUtils.isEmpty(shareUrl)) {
throw new IllegalArgumentException("ShareLinkInfo shareUrl is empty");
}
Pattern pattern = Pattern.compile(regexPattern);
Matcher matcher = pattern.matcher(shareUrl);
if (matcher.find()) {
String shareKey = matcher.group(matcher.groupCount());
// 返回规范化的标准链接
String standardUrl = standardUrlTemplate.replace("{shareKey}", shareKey);
shareLinkInfo.setShareUrl(shareUrl);
shareLinkInfo.setShareKey(shareKey);
shareLinkInfo.setStandardUrl(standardUrl);
return this;
}
throw new IllegalArgumentException("Invalid share URL for " + displayName);
}
public IPanTool createTool() {
if (shareLinkInfo == null || StringUtils.isEmpty(shareLinkInfo.getType())) {
throw new IllegalArgumentException("ShareLinkInfo not init or type is empty");
}
if (StringUtils.isEmpty(shareLinkInfo.getShareKey())) {
this.normalizeShareLink();
}
try {
return toolClass
.getDeclaredConstructor(ShareLinkInfo.class)
.newInstance(shareLinkInfo);
} catch (Exception e) {
throw new RuntimeException("无法创建工具实例: " + toolClass.getName(), e);
}
}
// 生成分享链接的方法
synchronized public PanDomainTemplate generateShareLink(String shareKey) {
shareLinkInfo.setShareKey(shareKey);
shareLinkInfo.setStandardUrl(standardUrlTemplate.replace("{shareKey}", shareKey));
return this;
}
public String getDisplayName() {
return this.displayName;
return displayName;
}
public String getRegexPattern() {
@@ -183,43 +110,7 @@ public enum PanDomainTemplate {
return standardUrlTemplate;
}
public ShareLinkInfo getShareLinkInfo() {
return shareLinkInfo;
}
synchronized public PanDomainTemplate setShareLinkInfoPwd(String pwd) {
shareLinkInfo.setSharePassword(pwd);
return this;
}
synchronized public PanDomainTemplate setShareLinkInfoUrl(String pwd) {
shareLinkInfo.setSharePassword(pwd);
return this;
}
// 根据分享链接获取PanDomainTemplate实例
synchronized public static PanDomainTemplate fromShareUrl(String shareUrl) {
for (PanDomainTemplate template : values()) {
if (shareUrl.matches(template.regexPattern)) {
template.getShareLinkInfo().setShareUrl(shareUrl);
return template.normalizeShareLink();
}
}
throw new IllegalArgumentException("Unsupported share URL");
}
// 根据shortName获取枚举实例
public static PanDomainTemplate fromShortName(String shortName) {
try {
return Enum.valueOf(PanDomainTemplate.class, shortName.toUpperCase());
} catch (IllegalArgumentException ignore) {
// 如果没有找到对应的枚举实例,抛出异常
throw new IllegalArgumentException("No enum constant for short name: " + shortName);
}
}
public String getShortName() {
return shortName;
public Class<? extends IPanTool> getToolClass() {
return toolClass;
}
}

View File

@@ -0,0 +1,113 @@
package cn.qaiu.parser;
import cn.qaiu.entity.ShareLinkInfo;
import org.apache.commons.lang3.StringUtils;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* 该类提供方法来解析和规范化不同来源的分享链接,确保它们可以转换为统一的标准链接格式。
* 通过这种方式,应用程序可以更容易地处理和识别不同网盘服务的分享链接。
*
* @author <a href="https://qaiu.top">QAIU</a>
* @date 2024/9/15 14:10
*/
public class ParserCreate {
private final PanDomainTemplate panDomainTemplate;
private final ShareLinkInfo shareLinkInfo;
public ParserCreate(PanDomainTemplate panDomainTemplate, ShareLinkInfo shareLinkInfo) {
this.panDomainTemplate = panDomainTemplate;
this.shareLinkInfo = shareLinkInfo;
}
// 解析并规范化分享链接
public ParserCreate normalizeShareLink() {
if (shareLinkInfo == null) {
throw new IllegalArgumentException("ShareLinkInfo not init");
}
// 匹配并提取shareKey
String shareUrl = shareLinkInfo.getShareUrl();
if (StringUtils.isEmpty(shareUrl)) {
throw new IllegalArgumentException("ShareLinkInfo shareUrl is empty");
}
Pattern pattern = Pattern.compile(this.panDomainTemplate.getRegexPattern());
Matcher matcher = pattern.matcher(shareUrl);
if (matcher.find()) {
String shareKey = matcher.group(matcher.groupCount());
// 返回规范化的标准链接
String standardUrl = getStandardUrlTemplate().replace("{shareKey}", shareKey);
shareLinkInfo.setShareUrl(shareUrl);
shareLinkInfo.setShareKey(shareKey);
shareLinkInfo.setStandardUrl(standardUrl);
return this;
}
throw new IllegalArgumentException("Invalid share URL for " + this.panDomainTemplate.getDisplayName());
}
public IPanTool createTool() {
if (shareLinkInfo == null || StringUtils.isEmpty(shareLinkInfo.getType())) {
throw new IllegalArgumentException("ShareLinkInfo not init or type is empty");
}
if (StringUtils.isEmpty(shareLinkInfo.getShareKey())) {
this.normalizeShareLink();
}
try {
return this.panDomainTemplate.getToolClass()
.getDeclaredConstructor(ShareLinkInfo.class)
.newInstance(shareLinkInfo);
} catch (Exception e) {
throw new RuntimeException("无法创建工具实例: " + panDomainTemplate.getToolClass().getName(), e);
}
}
// set share key
public ParserCreate shareKey(String shareKey) {
shareLinkInfo.setShareKey(shareKey);
shareLinkInfo.setStandardUrl(panDomainTemplate.getStandardUrlTemplate().replace("{shareKey}", shareKey));
return this;
}
public String getStandardUrlTemplate() {
return this.panDomainTemplate.getStandardUrlTemplate();
}
public ShareLinkInfo getShareLinkInfo() {
return shareLinkInfo;
}
public ParserCreate setShareLinkInfoPwd(String pwd) {
shareLinkInfo.setSharePassword(pwd);
return this;
}
// 根据分享链接获取PanDomainTemplate实例
public synchronized static ParserCreate fromShareUrl(String shareUrl) {
for (PanDomainTemplate panDomainTemplate : PanDomainTemplate.values()) {
if (shareUrl.matches(panDomainTemplate.getRegexPattern())) {
ShareLinkInfo shareLinkInfo = ShareLinkInfo.newBuilder()
.type(panDomainTemplate.name().toLowerCase())
.shareUrl(shareUrl).build();
ParserCreate parserCreate = new ParserCreate(panDomainTemplate, shareLinkInfo);
return parserCreate.normalizeShareLink();
}
}
throw new IllegalArgumentException("Unsupported share URL");
}
// 根据type获取枚举实例
public synchronized static ParserCreate fromType(String type) {
try {
PanDomainTemplate panDomainTemplate = Enum.valueOf(PanDomainTemplate.class, type.toUpperCase());
ShareLinkInfo shareLinkInfo = ShareLinkInfo.newBuilder()
.type(type.toLowerCase()).build();
return new ParserCreate(panDomainTemplate, shareLinkInfo);
} catch (IllegalArgumentException ignore) {
// 如果没有找到对应的枚举实例,抛出异常
throw new IllegalArgumentException("No enum constant for type name: " + type);
}
}
}

View File

@@ -19,15 +19,15 @@ public class PanDomainTemplateTest {
// 准备测试数据
String testShareUrl = "https://test.lanzoux.com/s/someShareKey";
PanDomainTemplate template = PanDomainTemplate.fromShareUrl(testShareUrl); // 假设使用LZ网盘模板
ParserCreate parserCreate = ParserCreate.fromShareUrl(testShareUrl); // 假设使用LZ网盘模板
// 调用normalizeShareLink方法
ShareLinkInfo result = template.getShareLinkInfo();
ShareLinkInfo result = parserCreate.getShareLinkInfo();
System.out.println(result);
// 断言结果是否符合预期
assertNotNull("Result should not be null", result);
assertEquals("Share key should match", "someShareKey", result.getShareKey());
assertEquals("Standard URL should be generated correctly", template.getStandardUrlTemplate().replace("{shareKey}", "someShareKey"), result.getStandardUrl());
assertEquals("Standard URL should be generated correctly", parserCreate.getStandardUrlTemplate().replace("{shareKey}", "someShareKey"), result.getStandardUrl());
// 可以添加更多的断言来验证其他字段
}
@@ -38,25 +38,25 @@ public class PanDomainTemplateTest {
String cowUrl = "https://cowtransfer.com/s/9a644fe3e3a748";
String ceUrl = "https://pan.huang1111.cn/s/g31PcQ";
String wsUrl = "https://f.ws59.cn/f/f25625rv6p6";
PanDomainTemplate.fromShareUrl(wsUrl).createTool()
.parse().onSuccess(System.out::println);
PanDomainTemplate.fromShareUrl(lzUrl).createTool()
.parse().onSuccess(System.out::println);
PanDomainTemplate.fromShareUrl(cowUrl).createTool()
.parse().onSuccess(System.out::println);
PanDomainTemplate.fromShareUrl(lzUrl).createTool()
// ParserCreate.fromShareUrl(wsUrl).createTool()
// .parse().onSuccess(System.out::println);
// ParserCreate.fromShareUrl(lzUrl).createTool()
// .parse().onSuccess(System.out::println);
// ParserCreate.fromShareUrl(cowUrl).createTool()
// .parse().onSuccess(System.out::println);
ParserCreate.fromShareUrl(lzUrl).createTool()
.parse().onSuccess(System.out::println);
// PanDomainTemplate.fromShortName("lz").generateShareLink("ihLkw1gezutg")
// ParserCreate.fromType("lz").shareKey("ihLkw1gezutg")
// .createTool().parse().onSuccess(System.out::println);
// PanDomainTemplate.LZ.generateShareLink("ihLkw1gezutg")
// ParserCreate.LZ.shareKey("ihLkw1gezutg")
// .createTool().parse().onSuccess(System.out::println);
// 调用fromShareUrl方法
// PanDomainTemplate resultTemplate = PanDomainTemplate.fromShareUrl(testShareUrl);
// PanDomainTemplate resultTemplate = ParserCreate.fromShareUrl(testShareUrl);
// System.out.println(resultTemplate.normalizeShareLink(testShareUrl));
// System.out.println(resultTemplate.generateShareLink("xxx"));
// System.out.println(resultTemplate.shareKey("xxx"));
// System.out.println(resultTemplate.createTool("xxx",null).parse()
// .onSuccess(System.out::println));
// System.out.println(resultTemplate.getDisplayName());
@@ -65,7 +65,7 @@ public class PanDomainTemplateTest {
//
// // 断言结果是否符合预期
// assertNotNull("Result should not be null", resultTemplate);
// assertEquals("Should return the correct template", PanDomainTemplate.LZ, resultTemplate);
// assertEquals("Should return the correct template", ParserCreate.LZ, resultTemplate);
// // 可以添加更多的断言来验证正则表达式匹配逻辑
// new Scanner(System.in).nextLine();
TimeUnit.SECONDS.sleep(5);