diff --git a/README.md b/README.md index f44929d..495ec00 100644 --- a/README.md +++ b/README.md @@ -203,9 +203,9 @@ bash service-install.sh ## 0.1.8 开发计划 - Docker部署 -- 联想乐云解析 -- 直链缓存 -- 日志优化 +- 联想乐云解析 √ +- 直链缓存 √ +- 日志优化 √ **技术栈:** diff --git a/parser/src/main/java/cn/qaiu/entity/ShareLinkInfo.java b/parser/src/main/java/cn/qaiu/entity/ShareLinkInfo.java index 7601475..c1217cf 100644 --- a/parser/src/main/java/cn/qaiu/entity/ShareLinkInfo.java +++ b/parser/src/main/java/cn/qaiu/entity/ShareLinkInfo.java @@ -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; // 规范化的标准链接 diff --git a/parser/src/main/java/cn/qaiu/parser/IPanTool.java b/parser/src/main/java/cn/qaiu/parser/IPanTool.java index 376f3a3..e9385c1 100644 --- a/parser/src/main/java/cn/qaiu/parser/IPanTool.java +++ b/parser/src/main/java/cn/qaiu/parser/IPanTool.java @@ -4,28 +4,4 @@ import io.vertx.core.Future; public interface IPanTool { Future 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); - } - } - } diff --git a/parser/src/main/java/cn/qaiu/parser/PanDomainTemplate.java b/parser/src/main/java/cn/qaiu/parser/PanDomainTemplate.java index 6ec85ea..e1c87bb 100644 --- a/parser/src/main/java/cn/qaiu/parser/PanDomainTemplate.java +++ b/parser/src/main/java/cn/qaiu/parser/PanDomainTemplate.java @@ -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 定义了不同网盘服务的模板信息,包括: * - * 该类提供方法来解析和规范化不同来源的分享链接,确保它们可以转换为统一的标准链接格式。 - * 通过这种方式,应用程序可以更容易地处理和识别不同网盘服务的分享链接. * * @author QAIU * 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 toolClass; - PanDomainTemplate(String displayName, String shortName, String regexPattern, - String standardUrlTemplate, Class toolClass) { + PanDomainTemplate(String displayName, String regexPattern, String standardUrlTemplate, + Class 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 getToolClass() { + return toolClass; } } diff --git a/parser/src/main/java/cn/qaiu/parser/ParserCreate.java b/parser/src/main/java/cn/qaiu/parser/ParserCreate.java new file mode 100644 index 0000000..525af60 --- /dev/null +++ b/parser/src/main/java/cn/qaiu/parser/ParserCreate.java @@ -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 QAIU + * @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); + } + } +} diff --git a/parser/src/test/java/cn/qaiu/parser/PanDomainTemplateTest.java b/parser/src/test/java/cn/qaiu/parser/PanDomainTemplateTest.java index 99953aa..eaa0df8 100644 --- a/parser/src/test/java/cn/qaiu/parser/PanDomainTemplateTest.java +++ b/parser/src/test/java/cn/qaiu/parser/PanDomainTemplateTest.java @@ -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); diff --git a/web-front/public/index.html b/web-front/public/index.html index f8ea513..e5d2978 100644 --- a/web-front/public/index.html +++ b/web-front/public/index.html @@ -11,7 +11,8 @@ content="Netdisk fast download 网盘直链解析工具"> - +