里程碑版本前奏: 1. 添加google云盘解析(需要联网), 2. web页面人工智障自动解析URL, 3. 优化一堆细节问题, 4: git换行配置(待验证), 5. 酷我解析可用

This commit is contained in:
qaiu
2024-11-02 18:58:15 +08:00
parent f07800985d
commit ca98cc8708
18 changed files with 691 additions and 13034 deletions

8
.gitattributes vendored Normal file
View File

@@ -0,0 +1,8 @@
# 文本文件使用 LF 换行符,适用于 Linux 和 macOS
*.sh text eol=lf
*.service text eol=lf
# Windows 执行的文件使用 CRLF 换行符
*.bat text eol=crlf
*.cmd text eol=crlf
bin/nfd-service-template.xml text eol=crlf

View File

@@ -1,5 +1,6 @@
package cn.qaiu.entity;
import java.util.HashMap;
import java.util.Map;
public class ShareLinkInfo {
@@ -101,7 +102,7 @@ public class ShareLinkInfo {
private String sharePassword = ""; // 分享密码(如果存在)
private String shareUrl; // 原始分享链接
private String standardUrl; // 规范化的标准链接
private Map<String, Object> otherParam; // 其他参数
private Map<String, Object> otherParam = new HashMap<>(); // 其他参数
public Builder shareKey(String shareKey) {
this.shareKey = shareKey;

View File

@@ -2,11 +2,9 @@ package cn.qaiu.parser;
import cn.qaiu.parser.impl.*;
import java.util.Arrays;
import java.util.Set;
import java.util.regex.Matcher;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import static java.util.regex.Pattern.compile;
@@ -27,7 +25,7 @@ public enum PanDomainTemplate {
// 网盘定义
LZ("蓝奏云",
compile("https://([a-z0-9-]+)?\\.?lanzou[a-z]\\.com/(.+/)?(?<KEY>.+)"),
compile("https://(?:[a-zA-Z\\d-]+\\.)?lanzou[a-z]\\.com/(.+/)?(?<KEY>.+)"),
"https://lanzoux.com/{shareKey}",
LzTool.class),
@@ -48,6 +46,7 @@ public enum PanDomainTemplate {
FC("亿方云",
compile("https://v2\\.fangcloud\\.(com|cn)/(s|sharing)/(?<KEY>.+)"),
"https://v2.fangcloud.com/s/{shareKey}",
"https://www.fangcloud.com/",
FcTool.class),
// https://www.ilanzou.com/s/
IZ("蓝奏云优享",
@@ -58,10 +57,11 @@ public enum PanDomainTemplate {
QQ("QQ邮箱中转站",
compile("https://i?wx\\.mail\\.qq\\.com/ftn/download\\?(?<KEY>.+)"),
"https://iwx.mail.qq.com/ftn/download/{shareKey}",
"https://mail.qq.com",
QQTool.class),
// https://f.ws59.cn/f/或者https://www.wenshushu.cn/f/
WS("文叔叔",
compile("https://(f\\.ws([0-9]{2})\\.cn|www\\.wenshushu\\.cn)/f/(?<KEY>.+)"),
compile("https://(f\\.ws(\\d{2})\\.cn|www\\.wenshushu\\.cn)/f/(?<KEY>.+)"),
"https://www.wenshushu.cn/f/{shareKey}",
WsTool.class),
// https://www.123pan.com/s/
@@ -81,25 +81,29 @@ public enum PanDomainTemplate {
"https://cowtransfer.com/s/{shareKey}",
CowTool.class),
CT("城通网盘",
compile("https://474b\\.com/file/(?<KEY>.+)"),
compile("https://(?:[a-zA-Z\\d-]+\\.)?(ctfile|545c|u062|ghpym|474b)\\.com/file/(?<KEY>.+)"),
"https://474b.com/file/{shareKey}",
CtTool.class),
// https://xxx.118pan.com/bxxx
P118("118网盘",
compile("https://((.*)\\.)?118pan\\.com/b(?<KEY>.+)"),
compile("https://(?:[a-zA-Z\\d-]+\\.)?118pan\\.com/b(?<KEY>.+)"),
"https://qaiu.118pan.com/b{shareKey}",
P118Tool.class),
// https://www.vyuyun.com/s/QMa6ie?password=I4KG7H
PVYY("微雨云存储",
compile("https://www\\.vyuyun\\.com/s/(?<KEY>[a-zA-Z0-9-]+)(\\?password=.*)?"),
compile("https://www\\.vyuyun\\.com/s/(?<KEY>[a-zA-Z\\d-]+)(\\?password=.*)?"),
"https://www.vyuyun.com/s/{shareKey}",
PvyyTool.class),
// https://1drv.ms/w/s!Alg0feQmCv2rnRFd60DQOmMa-Oh_?e=buaRtp
//
POD("OneCloud",
POD("OneDrive",
compile("https://1drv\\.ms/[uw]/s!(?<KEY>.+)"),
"https://1drv.ms/w/s!{shareKey}",
"https://onedrive.live.com/",
PodTool.class),
// 404网盘 https://drive.google.com/file/d/xxx/view?usp=sharing
PGD("GoogleDrive",
compile("https://drive\\.google\\.com/file/d/(?<KEY>.+)/view(\\?usp=(sharing|drive_link))?"),
"https://drive.google.com/file/d/{shareKey}/view?usp=sharing",
PgdTool.class),
// =====================音乐类解析 分享链接标志->MxxS (单歌曲/普通音质)==========================
// http://163cn.tv/xxx
@@ -114,7 +118,7 @@ public enum PanDomainTemplate {
MnesTool.MneTool.class),
// https://c6.y.qq.com/base/fcgi-bin/u?__=xxx
MQQS("QQ音乐分享",
compile("https://(.+)\\.y\\.qq\\.com/base/fcgi-bin/u\\?__=(?<KEY>.+)"),
compile("https://(?:[a-zA-Z\\d-]+\\.)?y\\.qq\\.com/base/fcgi-bin/u\\?__=(?<KEY>.+)"),
"https://c6.y.qq.com/base/fcgi-bin/u?__={shareKey}",
MqqsTool.class),
// https://y.qq.com/n/ryqq/songDetail/000XjcLg0fbRjv?songtype=0
@@ -125,17 +129,17 @@ public enum PanDomainTemplate {
// https://t1.kugou.com/song.html?id=xxx
MKGS("酷狗音乐分享",
compile("https://(.+)\\.kugou\\.com/song\\.html\\?id=(?<KEY>.+)"),
compile("https://(?:[a-zA-Z\\d-]+\\.)?kugou\\.com/song\\.html\\?id=(?<KEY>.+)"),
"https://t1.kugou.com/song.html?id={shareKey}",
MkgsTool.class),
// https://www.kugou.com/share/2bi8Fe9CSV3.html?id=2bi8Fe9CSV3#6ed9gna4"
MKGS2("酷狗音乐分享2",
compile("https://(.+)\\.kugou\\.com/share/(?<KEY>.+).html.*"),
compile("https://(?:[a-zA-Z\\d-]+\\.)?kugou\\.com/share/(?<KEY>.+).html.*"),
"https://www.kugou.com/share/{shareKey}.html",
MkgsTool.Mkgs2Tool.class),
// https://www.kugou.com/mixsong/2bi8Fe9CSV3
MKG("酷狗音乐歌曲详情",
compile("https://(.+)\\.kugou\\.com/mixsong/(?<KEY>.+)\\.html.*"),
compile("https://(?:[a-zA-Z\\d-]+\\.)?kugou\\.com/mixsong/(?<KEY>.+)\\.html.*"),
"https://www.kugou.com/mixsong/{shareKey}.html",
MkgsTool.MkgTool.class),
// https://kuwo.cn/play_detail/395500809
@@ -154,19 +158,21 @@ public enum PanDomainTemplate {
// Cloudreve自定义域名解析, 解析器CeTool兜底策略, 即任意域名如果匹配不到对应的规则, 则由CeTool统一处理,
// 如果不属于Cloudreve盘 则调用下一个自定义域名解析器, 若都处理不了则抛出异常, 这种匹配模式类似责任链
// https://pan.huang1111.cn/s/xxx
// 通用域名([a-z0-9]+(-[a-z0-9]+)*\.)+[a-z]{2,}
// 通用域名([a-z\\d]+(-[a-z\\d]+)*\.)+[a-z]{2,}
CE("Cloudreve",
compile("http(s)?://([a-zA-Z0-9]+(-[a-zA-Z0-9]+)*\\.)+[a-zA-Z]{2,}(/s)?/(?<KEY>.+)"),
compile("http(s)?://([a-zA-Z\\d]+(-[a-zA-Z\\d]+)*\\.)+[a-zA-Z]{2,}(/s)?/(?<KEY>.+)"),
"https://{any}/s/{shareKey}",
"https://cloudreve.org/",
CeTool.class),
// 可道云自定义域名解析
KD("可道云",
compile("http(s)?://([a-zA-Z0-9]+(-[a-zA-Z0-9]+)*\\.)+[a-zA-Z]{2,}(/#s)?/(?<KEY>.+)"),
compile("http(s)?://([a-zA-Z\\d]+(-[a-zA-Z\\d]+)*\\.)+[a-zA-Z]{2,}(/#s)?/(?<KEY>.+)"),
"https://{any}/#s/{shareKey}",
"https://kodcloud.com/",
KdTool.class),
// 其他自定义域名解析
OTHER("其他网盘",
compile("http(s)?://([a-zA-Z0-9]+(-[a-zA-Z0-9]+)*\\.)+[a-zA-Z]{2,}/(?<KEY>.+)"),
compile("http(s)?://([a-zA-Z\\d]+(-[a-zA-Z\\d]+)*\\.)+[a-zA-Z]{2,}/(?<KEY>.+)"),
"https://{any}/{shareKey}",
OtherTool.class);
@@ -183,6 +189,9 @@ public enum PanDomainTemplate {
// 网盘的标准链接模板,不含占位符,用于规范化分享链接
private final String standardUrlTemplate;
// 网盘的域名, 如果在分享链接里能提取到, 则可不写
private String panDomain;
// 指向解析工具IPanTool实现类
private final Class<? extends IPanTool> toolClass;
@@ -195,6 +204,16 @@ public enum PanDomainTemplate {
this.toolClass = toolClass;
}
PanDomainTemplate(String displayName, Pattern pattern, String standardUrlTemplate, String panDomain,
Class<? extends IPanTool> toolClass) {
this.displayName = displayName;
this.pattern = pattern;
this.regex = pattern.pattern();
this.standardUrlTemplate = standardUrlTemplate;
this.panDomain = panDomain;
this.toolClass = toolClass;
}
public String getDisplayName() {
return displayName;
}
@@ -215,27 +234,17 @@ public enum PanDomainTemplate {
return toolClass;
}
public static void main(String[] args) {
public String getPanDomain() {
if (panDomain == null) {
String url = standardUrlTemplate
.replace("{shareKey}", "");
URL panDomainUrl = null;
try {
panDomainUrl = new URL(url);
} catch (MalformedURLException ignored) {}
Matcher matcher = compile("https://1drv\\.ms/[uw]/s!(?<KEY>.+)")
.matcher("https://1drv.ms/u/s!Alg0feQmCv2rpFvu444hg5yVqDcK?e=OggA4s");
if (matcher.find()) {
System.out.println(matcher.group());
return panDomainUrl != null ? (panDomainUrl.getProtocol() + "://" + panDomainUrl.getHost()) : "";
}
// 校验重复
Set<String> collect =
Arrays.stream(PanDomainTemplate.values()).map(PanDomainTemplate::getRegex).collect(Collectors.toSet());
if (collect.size()<PanDomainTemplate.values().length) {
System.out.println("有重复枚举正则");
}
Set<String> collect2 =
Arrays.stream(PanDomainTemplate.values()).map(PanDomainTemplate::getStandardUrlTemplate).collect(Collectors.toSet());
if (collect2.size()<PanDomainTemplate.values().length) {
System.out.println("有重复枚举标准链接");
}
// System.out.println(collect);
// System.out.println(collect2);
return panDomain;
}
}

View File

@@ -25,8 +25,7 @@ public class MkwTool extends PanBase {
}
public Future<String> parse() {
// String shareUrl = shareLinkInfo.getStandardUrl();
String shareUrl = "https://kuwo.cn/play_detail/395500809";
String shareUrl = shareLinkInfo.getStandardUrl();
clientSession.getAbs(shareUrl).send().onSuccess(result -> {
String cookie = result.headers().get("set-cookie");
@@ -43,7 +42,7 @@ public class MkwTool extends PanBase {
var token = matcher.group(2);
String sign = JsExecUtils.getKwSign(token, key);
System.out.println(sign);
clientSession.getAbs(UriTemplate.of(API_URL)).setTemplateParam("mid", "395500809")
clientSession.getAbs(UriTemplate.of(API_URL)).setTemplateParam("mid", shareLinkInfo.getShareKey())
.putHeader("Secret", sign).send().onSuccess(res -> {
JsonObject json = asJson(res);
log.debug(json.encodePrettily());
@@ -51,7 +50,7 @@ public class MkwTool extends PanBase {
if (json.getInteger("code") == 200) {
complete(json.getJsonObject("data").getString("url"));
} else {
fail("链接已失效");
fail("链接已失效/需要VIP");
}
} catch (Exception e) {
@@ -66,11 +65,4 @@ public class MkwTool extends PanBase {
return promise.future();
}
MkwTool() {
}
public static void main(String[] args) {
new MkwTool().parse();
}
}

View File

@@ -0,0 +1,109 @@
package cn.qaiu.parser.impl;
import cn.qaiu.entity.ShareLinkInfo;
import cn.qaiu.parser.IPanTool;
import cn.qaiu.parser.PanBase;
import io.vertx.core.Future;
import io.vertx.core.buffer.Buffer;
import io.vertx.core.net.ProxyOptions;
import io.vertx.ext.web.client.HttpRequest;
import io.vertx.ext.web.client.HttpResponse;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* <a href="https://drive.google.com/">GoogleDrive</a>
* Google Drive文件解析工具.
*/
public class PgdTool extends PanBase implements IPanTool {
private static final String DOWN_URL_TEMPLATE =
"https://drive.usercontent.google.com/download";
private String downloadUrl;
public PgdTool(ShareLinkInfo shareLinkInfo) {
super(shareLinkInfo);
}
@Override
public Future<String> parse() {
downloadUrl = DOWN_URL_TEMPLATE + "?id=" + shareLinkInfo.getShareKey() + "&export=download";
if (true) {
// if (shareLinkInfo.getOtherParam().containsKey("bypassCheck")
// && "true".equalsIgnoreCase(shareLinkInfo.getOtherParam().get("bypassCheck").toString())) {
// 发起请求但不真正下载文件, 只检查响应头
HttpRequest<Buffer> clientAbs = client.headAbs(downloadUrl);
// TODO 判断是否需要代理
if (true) {
clientAbs.proxy(new ProxyOptions().setHost("127.0.0.1").setPort(7890));
}
clientAbs
.send()
.onSuccess(this::handleResponse)
.onFailure(handleFail("请求下载链接失败"));
return future();
}
complete(downloadUrl);
return future();
}
/**
* 处理下载链接的响应.
*/
private void handleResponse(HttpResponse<Buffer> response) {
String contentType = response.getHeader("Content-Type");
if (contentType != null && !contentType.contains("text/html")) {
complete(downloadUrl);
} else {
// 如果不是文件流类型,从 HTML 中解析出真实下载链接
HttpRequest<Buffer> clientAbs = client.getAbs(downloadUrl);
// TODO 判断是否需要代理
if (true) {
clientAbs.proxy(new ProxyOptions().setHost("127.0.0.1").setPort(7890));
}
clientAbs
.send()
.onSuccess(res0 -> {
parseHtmlForRealLink(res0.bodyAsString());
})
.onFailure(handleFail("请求下载链接失败"));
}
}
/**
* 从HTML内容中解析真实下载链接.
*/
private void parseHtmlForRealLink(String html) {
// 使用正则表达式匹配 id、export、confirm、uuid、at 等参数
String id = extractHiddenInputValue(html, "id");
String confirm = extractHiddenInputValue(html, "confirm");
String uuid = extractHiddenInputValue(html, "uuid");
String at = extractHiddenInputValue(html, "at");
if (id != null && confirm != null && uuid != null) {
String realDownloadLink = DOWN_URL_TEMPLATE +
"?id=" + id +
"&export=download" +
"&confirm=" + confirm +
"&uuid=" + uuid;
if (at != null) {
realDownloadLink += ( "&at=" + at);
}
complete(realDownloadLink);
} else {
fail("无法找到完整的下载链接参数");
}
}
/**
* 辅助方法: 从HTML中提取指定name的input隐藏字段的value
*/
private String extractHiddenInputValue(String html, String name) {
Pattern pattern = Pattern.compile("<input[^>]*name=\"" + name + "\"[^>]*value=\"([^\"]*)\"");
Matcher matcher = pattern.matcher(html);
return matcher.find() ? matcher.group(1) : null;
}
}

View File

@@ -3,8 +3,13 @@ package cn.qaiu.parser;
import cn.qaiu.entity.ShareLinkInfo;
import org.junit.Test;
import java.util.Arrays;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.regex.Matcher;
import java.util.stream.Collectors;
import static java.util.regex.Pattern.compile;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
@@ -70,4 +75,32 @@ public class PanDomainTemplateTest {
// new Scanner(System.in).nextLine();
TimeUnit.SECONDS.sleep(5);
}
@Test
public void verifyDuplicates() {
Matcher matcher = compile("https://(?:[a-zA-Z\\d-]+\\.)?drive\\.google\\.com/file/d/(?<KEY>.+)/view(\\?usp=(sharing|drive_link))?")
.matcher("https://adsd.drive.google.com/file/d/151bR-nk-tOBm9QAFaozJIVt2WYyCMkoz/view");
if (matcher.find()) {
System.out.println(matcher.group());
System.out.println(matcher.group("KEY"));
}
// 校验重复
Set<String> collect =
Arrays.stream(PanDomainTemplate.values()).map(PanDomainTemplate::getRegex).collect(Collectors.toSet());
if (collect.size()<PanDomainTemplate.values().length) {
System.out.println("有重复枚举正则");
} else {
System.out.println("正则无重复");
}
Set<String> collect2 =
Arrays.stream(PanDomainTemplate.values()).map(PanDomainTemplate::getStandardUrlTemplate).collect(Collectors.toSet());
if (collect2.size()<PanDomainTemplate.values().length) {
System.out.println("有重复枚举标准链接");
} else {
System.out.println("标准链接无重复");
}
}
}

View File

@@ -1,5 +1,7 @@
# nfd-web
解析服务的前端页面, 提供API测试, 统计查询, 二维码生成等
解析服务的前端页面, 提供API测试, 统计查询, 二维码生成等;
20241101 支持剪切板链接自动识别解析, 一键生成短链
![img_2.png](img/img_2.png)
![img.png](img/img.png)
![img_1.png](img/img_1.png)
@@ -41,3 +43,8 @@ npm run lint
### Customize configuration
See [Configuration Reference](https://cli.vuejs.org/config/).
## 参考项目
- https://github.com/HurryBy/CloudDiskAnalysis
- https://github.com/syhyz1990/panAI

12186
web-front/package-lock.json generated

File diff suppressed because it is too large Load Diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 KiB

View File

@@ -33,13 +33,24 @@
<hr>
<div class="main" v-loading="isLoading">
<div class="grid-content">
<!-- 开关按钮控制是否自动读取剪切板 -->
<el-switch
v-model="autoReadClipboard"
active-text="自动识别剪切板"
></el-switch>
<!-- 手动触发按钮 -->
<el-button style="margin-left: 20px;margin-bottom: 20px" @click="() => getPaste(1)">读取剪切板</el-button>
<el-input placeholder="请粘贴分享链接" v-model="link" id="url" lass="input-with-select">
<strong slot="prepend">分享链接</strong>
</el-input>
<el-input placeholder="请输入密码" v-model="password" id="url" lass="input-with-select">
<strong slot="prepend">分享密码</strong>
</el-input>
<el-input v-show="respData.data" placeholder="解析地址" :value="getLink2" id="url" lass="input-with-select">
<el-input v-show="getLink2" placeholder="解析地址" :value="getLink2" id="url" lass="input-with-select">
<strong slot="prepend">智能直链</strong>
<el-button slot="append" v-clipboard:copy="getLink2"
v-clipboard:success="onCopy"
v-clipboard:error="onError">点我复制
@@ -110,34 +121,16 @@
<script>
import axios from 'axios'
import QRCode from 'qrcode'
/*
蓝奏云 (lz)
登录, 上传, 下载, 分享
直链解析
奶牛快传 (cow)
登录, 上传, 下载, 分享
直链解析
移动云空间 (ec)
登录, 上传, 下载, 分享
直链解析
UC网盘 (uc)似乎已经失效,需要登录
登录, 上传, 下载, 分享
直链解析
小飞机网盘 (fj)
登录, 上传, 下载, 分享
直链解析
亿方云 (fc)
登录, 上传, 下载, 分享
直链解析
123云盘 (ye)
登录, 上传, 下载,, 分享
*/
import parserUrl from './parserUrl1'
export default {
name: 'App',
data() {
return {
// baseAPI: `${location.protocol}//${location.hostname}:6400`,
baseAPI: `${location.protocol}//${location.host}`,
autoReadClipboard: true, // 开关状态,默认为自动读取
current: {}, // 当前分享
showQrc: false,
codeUrl: '',
@@ -313,16 +306,44 @@ export default {
}
});
},
async getPaste() {
async getPaste(v) {
const text = await navigator.clipboard.readText();
console.log('获取到的文本内容是:', text)
console.log('获取到的文本内容是:', text);
let linkInfo = parserUrl.parseLink(text);
let pwd = parserUrl.parsePwd(text) || '';
if (linkInfo.link) {
if(linkInfo.link !== this.link || pwd !== this.password ) {
this.password = pwd;
this.link = linkInfo.link;
this.getLink2 = `${this.baseAPI}/parser?url=${this.link}`
if (this.link) this.$message.success(`自动识别分享成功, 网盘类型: ${linkInfo.name}; 分享URL ${this.link}; 分享密码: ${this.password || '空'}`);
} else {
v || this.$message.warning(`[${linkInfo.name}]分享信息无变化`)
}
} else {
this.$message.warning("未能提取到分享链接, 该分享可能尚未支持, 你可以复制任意网盘/音乐App的分享到该页面, 系统智能识别")
}
},
},
mounted() {
this.getLinkInfo = `${this.baseAPI}/v2/linkInfo`
this.getLink = `${this.baseAPI}/json/parser`
this.getLink = `${this.baseAPI}/json/parser`
this.getInfo()
this.getPaste()
// 页面首次加载时,根据开关状态判断是否读取剪切板
if (this.autoReadClipboard) {
this.getPaste()
}
// 当文档获得焦点时触发
window.addEventListener('focus', () => {
console.log('文档获得了焦点');
if (this.autoReadClipboard) {
this.getPaste()
}
});
// this.getPaste()
},
}

View File

@@ -1,762 +0,0 @@
// ==UserScript==
// @name 网盘智能识别助手
// @namespace https://github.com/syhyz1990/panAI
// @version 2.0.2
// @author YouXiaoHou,52fisher
// @description 智能识别选中文字中的🔗网盘链接和🔑提取码,识别成功打开网盘链接并自动填写提取码,省去手动复制提取码在输入的烦恼。支持识别 ✅百度网盘 ✅阿里云盘 ✅腾讯微云 ✅蓝奏云 ✅天翼云盘 ✅移动云盘 ✅迅雷云盘 ✅123云盘 ✅360云盘 ✅115网盘 ✅奶牛快传 ✅城通网盘 ✅夸克网盘 ✅FlowUs息流 ✅Chrome 扩展商店 ✅Edge 扩展商店 ✅Firefox 扩展商店 ✅Windows 应用商店。
// @license AGPL-3.0-or-later
// @homepage https://www.youxiaohou.com/tool/install-panai.html
// @supportURL https://github.com/syhyz1990/panAI
// @updateURL https://www.youxiaohou.com/panai.user.js
// @downloadURL https://www.youxiaohou.com/panai.user.js
// @match *://*/*
// @require https://unpkg.com/sweetalert2@10.16.6/dist/sweetalert2.min.js
// @require https://unpkg.com/hotkeys-js@3.13.3/dist/hotkeys.min.js
// @resource swalStyle https://unpkg.com/sweetalert2@10.16.6/dist/sweetalert2.min.css
// @run-at document-idle
// @grant GM_openInTab
// @grant GM_setValue
// @grant GM_getValue
// @grant GM_registerMenuCommand
// @grant GM_getResourceText
// @grant GM_info
// @icon data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxMjggMTI4Ij48cGF0aCBkPSJNMTAzLjYgMTA3LjRjMy41LTIuMiA4LjktNi4xIDEzLjgtMTIuNXM3LjMtMTIuNSA4LjUtMTYuNWMuNS0xLjcgMi4yLTcuNSAyLjItMTQuNyAwLTEwLjEtMy4zLTI1LjEtMTUuNC0zNi44LTE0LjUtMTQtMzIuMS0xNC4zLTM1LjctMTQuMy04IDAtMTUuNyAxLjktMjIuNiA1LjJDNDQgMjMgMzUuNyAzMS40IDMwLjggNDEuN2MtMS4zIDIuOC00IDQuNy03LjEgNS00IC4zLTcuNSA0LjQtOC45IDkuNi0uNSAxLjktMS42IDMuNS0zLjEgNC43QzQuNCA2Ni44IDAgNzUuNyAwIDg1YzAgNi44IDIuMyAxMy4xIDYuMSAxOC4yIDUuNSA3LjQgMTQuMiAxMi4yIDI0IDEyLjJoNDcuMWM0LjQgMCAxMS0uNSAxOC4zLTMuNSAzLjItMS40IDUuOS0zIDguMS00LjV6IiBmaWxsPSIjNDQ0Ii8+PHBhdGggZD0iTTExOS44IDY0LjNjLjEtMTcuMS0xMC40LTI4LTEyLjUtMzAuMUM5NSAyMi4xIDc5LjkgMjEuOCA3Ni45IDIxLjhjLTE3LjYgMC0zMy4zIDEwLjUtMzkuOSAyNi43LS42IDEuMy0xLjggMi4zLTMuNCAyLjNoLS40Yy01LjggMC0xMC42IDQuOC0xMC42IDEwLjd2LjVjMCAxLjQtLjggMi42LTEuOSAzLjNDMTMuNCA2OSA4LjggNzYuOCA4LjggODVjMCAxMi4yIDkuOSAyMi4zIDIyLjIgMjIuM2g0NS4yYzMuNi0uMSAxNy42LS45IDI5LjYtMTIgMi45LTIuOCAxMy45LTEzLjcgMTQtMzF6IiBmaWxsPSIjZGI4NDEyIi8+PHBhdGggZD0iTTExMC44IDU3LjRsLjIgMy4zYzAgMS4zLTEuMSAyLjQtMi4zIDIuNC0xLjMgMC0yLjMtMS4xLTIuMy0yLjRsLS4xLTIuOHYtLjNjMC0xLjIuOS0yLjIgMi4xLTIuM2guM2MuNyAwIDEuMy4zIDEuNy43LS4yLjEuMy41LjQgMS40em0tMy4zLTEwLjNjMCAxLjItMSAyLjMtMi4yIDIuM2gtLjFjLS44IDAtMS42LS41LTItMS4yLTQuNi04LjMtMTMuMy0xMy41LTIyLjgtMTMuNS0xLjIgMC0yLjMtMS0yLjMtMi4ydi0uMWMwLTEuMiAxLTIuMyAyLjItMi4zaC4xYTMwLjM3IDMwLjM3IDAgMCAxIDE1LjggNC40YzQuNiAyLjggOC40IDYuOCAxMS4xIDExLjUuMS4zLjIuNy4yIDEuMXpNNjkuMiA0OWwxOS40IDE0LjhjMS45IDEuNSAzLjEgMy41IDMuNSA1Ljd2LjJjLjEuNC4xLjguMSAxLjIgMCAuNi0uMSAxLjEtLjIgMS42LS40IDIuMi0xLjcgNC4yLTMuNSA1LjZMNjkuMyA5M2MtMi42IDItNS40IDIuNS03LjcgMS40LS4xLS4xLS4yLS4xLS4yLS4yLTItMS4yLTMuMi0zLjUtMy4yLTYuNHYtNi42aC01LjdjLTYuOCAwLTEyLTQuNy0xMi0xMC45IDAtNC44IDIuNi04LjUgNy4yLTEwLjMgMS4zLS41IDIuNy4yIDMuMiAxLjVzLS4xIDIuOC0xLjQgMy4zYy0yLjcgMS4xLTQgMi45LTQgNS41IDAgMy41IDMgNiA3IDZoOC4xYy41IDAgMSAuMiAxLjQuNi43LjYgMS4xIDEuNyAxLjEgMi42djguNGMwIDEuMy40IDIgLjcgMi4xLjQuMiAxLjMgMCAyLjQtLjlsMTkuMi0xNC45YzEuMi0uOSAxLjgtMi4xIDEuOC0zLjNzLS42LTIuMy0xLjctMy4xTDY2LjIgNTNjLTEuMS0uOS0yLTEuMS0yLjQtLjktLjMuMi0uNy45LS43IDIuMXY3LjZjMCAuOS0uNSAxLjctMS4yIDIuMS0uNC4zLS44LjQtMS4zLjQtMS40IDAtMi41LTEuMS0yLjUtMi41di03LjZjMC0zLjEgMS4zLTUuNSAzLjUtNi42bC43LS4zYzIuMS0uNyA0LjYtLjEgNi45IDEuN3oiIGZpbGw9IiM0NDQiLz48L3N2Zz4=
// ==/UserScript==
(function () {
'use strict';
const customClass = {
container: 'panai-container',
popup: 'panai-popup',
};
let toast = Swal.mixin({
toast: true,
position: 'top',
showConfirmButton: false,
timer: 3500,
timerProgressBar: false,
didOpen: (toast) => {
toast.addEventListener('mouseenter', Swal.stopTimer);
toast.addEventListener('mouseleave', Swal.resumeTimer);
}
});
let util = {
clog(c) {
console.group("%c %c [网盘智能识别助手]", `background:url(${GM_info.script.icon}) center center no-repeat;background-size:12px;padding:3px`, "");
console.log(c);
console.groupEnd();
},
parseQuery(name) {
let reg = new RegExp(`(?<=(?:${name})\\=)(?:wss:[a-zA-Z0-9]+|[\\w-]+)`, "i")
let pd = location.href.replace(/%3A/g, ":").match(reg);
if (pd) {
return pd[0];
}
return null;
},
getValue(name) {
return GM_getValue(name);
},
setValue(name, value) {
GM_setValue(name, value);
},
sleep(time) {
return new Promise((resolve) => setTimeout(resolve, time));
},
addStyle(id, tag, css) {
tag = tag || 'style';
let doc = document, styleDom = doc.getElementById(id);
if (styleDom) return;
let style = doc.createElement(tag);
style.rel = 'stylesheet';
style.id = id;
tag === 'style' ? style.innerHTML = css : style.href = css;
document.head.appendChild(style);
},
isHidden(el) {
try {
return el.offsetParent === null;
} catch (e) {
return false;
}
},
isMobile: (() => !!navigator.userAgent.match(/(phone|pad|pod|iPhone|iPod|ios|iPad|Android|Mobile|BlackBerry|IEMobile|MQQBrowser|JUC|Fennec|wOSBrowser|BrowserNG|WebOS|Symbian|Windows Phone|HarmonyOS|MicroMessenger)/i))(),
query(selector) {
if (Array.isArray(selector)) {
let obj = null;
for (let i = 0; i < selector.length; i++) {
let o = document.querySelector(selector[i]);
if (o) {
obj = o;
break;
}
}
return obj;
}
return document.querySelector(selector);
}
};
let opt = {
'baidu': {
reg: /((?:https?:\/\/)?(?:e?yun|pan)\.baidu\.com\/(doc\/|enterprise\/)?(?:s\/[\w~]*(((-)?\w*)*)?|share\/\S{4,}))/,
host: /(pan|e?yun)\.baidu\.com/,
input: ['#accessCode', '.share-access-code', '#wpdoc-share-page > .u-dialog__wrapper .u-input__inner'],
button: ['#submitBtn', '.share-access .g-button', '#wpdoc-share-page > .u-dialog__wrapper .u-btn--primary'],
name: '百度网盘',
storage: 'hash'
},
'aliyun': {
reg: /((?:https?:\/\/)?(?:(?:www\.)?(?:aliyundrive|alipan)\.com\/s|alywp\.net)\/[a-zA-Z\d]+)/,
host: /www\.(aliyundrive|alipan)\.com|alywp\.net/,
input: ['form .ant-input', 'form input[type="text"]', 'input[name="pwd"]'],
button: ['form .button--fep7l', 'form button[type="submit"]'],
name: '阿里云盘',
storage: 'hash'
},
'weiyun': {
reg: /((?:https?:\/\/)?share\.weiyun\.com\/[a-zA-Z\d]+)/,
host: /share\.weiyun\.com/,
input: ['.mod-card-s input[type=password]', 'input.pw-input'],
button: ['.mod-card-s .btn-main', ".pw-btn-wrap button.btn"],
name: '微云',
storage: 'hash'
},
'lanzou': {
reg: /((?:https?:\/\/)?(?:[a-zA-Z0-9\-.]+)?(?:lanzou[a-z]|lanzn)\.com\/[a-zA-Z\d_\-]+(?:\/[\w-]+)?)/,
host: /(?:[a-zA-Z\d-.]+)?(?:lanzou[a-z]|lanzn)\.com/,
input: ['#pwd'],
button: ['.passwddiv-btn', '#sub'],
name: '蓝奏云',
storage: 'hash'
},
'tianyi': {
reg: /((?:https?:\/\/)?cloud\.189\.cn\/(?:t\/|web\/share\?code=)?[a-zA-Z\d]+)/,
host: /cloud\.189\.cn/,
input: ['.access-code-item #code_txt', "input.access-code-input"],
button: ['.access-code-item .visit', ".button"],
name: '天翼云盘',
storage: (() => util.isMobile === true ? 'local' : 'hash')(),
storagePwdName: 'tmp_tianyi_pwd'
},
'caiyun': {
reg: /((?:https?:\/\/)?caiyun\.139\.com\/(?:m\/i|w\/i\/|web\/|front\/#\/detail)\??(?:linkID=)?[a-zA-Z\d]+)/,
host: /(?:cai)?yun\.139\.com/,
input: ['.token-form input[type=text]'],
button: ['.token-form .btn-token'],
name: '移动云盘',
storage: 'local',
storagePwdName: 'tmp_caiyun_pwd'
},
'xunlei': {
reg: /((?:https?:\/\/)?pan\.xunlei\.com\/s\/[\w-]{10,})/,
host: /pan\.xunlei\.com/,
input: ['.pass-input-wrap .td-input__inner'],
button: ['.pass-input-wrap .td-button'],
name: '迅雷云盘',
storage: 'hash'
},
'123pan': {
reg: /((?:https?:\/\/)?www\.123pan\.com\/s\/[\w-]{6,})/,
host: /www\.123pan\.com/,
input: ['.ca-fot input', ".appinput .appinput"],
button: ['.ca-fot button', ".appinput button"],
name: '123云盘',
storage: 'hash'
},
'360': {
reg: /((?:https?:\/\/)?(?:[a-zA-Z\d\-.]+)?(?:yunpan\.360\.cn|yunpan\.com)(\/lk)?\/surl_\w{6,})/,
host: /[\w.]+?yunpan\.com/,
input: ['.pwd-input'],
button: ['.submit-btn'],
name: '360云盘',
storage: 'local',
storagePwdName: 'tmp_360_pwd'
},
'115': {
reg: /((?:https?:\/\/)?115\.com\/s\/[a-zA-Z\d]+)/,
host: /115\.com/,
input: ['.form-decode input'],
button: ['.form-decode .submit a'],
name: '115网盘',
storage: 'hash'
},
'cowtransfer': {
reg: /((?:https?:\/\/)?(?:[a-zA-Z\d-.]+)?cowtransfer\.com\/s\/[a-zA-Z\d]+)/,
host: /(?:[a-zA-Z\d-.]+)?cowtransfer\.com/,
input: ['.receive-code-input input'],
button: ['.open-button'],
name: '奶牛快传',
storage: 'hash'
},
'ctfile': {
reg: /((?:https?:\/\/)?(?:[a-zA-Z\d-.]+)?(?:ctfile|545c|u062|ghpym)\.com\/\w+\/[a-zA-Z\d-]+)/,
host: /(?:[a-zA-Z\d-.]+)?(?:ctfile|545c|u062)\.com/,
input: ['#passcode'],
button: ['.card-body button'],
name: '城通网盘',
storage: 'hash'
},
'quark': {
reg: /((?:https?:\/\/)?pan\.quark\.cn\/s\/[a-zA-Z\d-]+)/,
host: /pan\.quark\.cn/,
input: ['.ant-input'],
button: ['.ant-btn-primary'],
name: '夸克网盘',
storage: 'local',
storagePwdName: 'tmp_quark_pwd'
},
'vdisk': {
reg: /(?:https?:\/\/)?vdisk.weibo.com\/lc\/\w+/,
host: /vdisk\.weibo\.com/,
input: ['#keypass', "#access_code"],
button: ['.search_btn_wrap a', "#linkcommon_btn"],
name: '微盘',
storage: 'hash',
},
'wenshushu': {
reg: /((?:https?:\/\/)?(?:www\.wenshushu|ws28)\.cn\/(?:k|box|f)\/\w+)/,
host: /www\.wenshushu\.cn/,
input: ['.pwd-inp .ivu-input'],
button: ['.pwd-inp .ivu-btn'],
name: '文叔叔网盘',
storage: 'hash'
},
'uc': {
reg: /(?:https?:\/\/)?drive\.uc\.cn\/s\/[a-zA-Z\d]+/,
host: /drive\.uc\.cn/,
input: ["input[class*='ShareReceivePC--input']", '.input-wrap input'],
button: ["button[class*='ShareReceivePC--submit-btn'", '.input-wrap button'],
name: 'UC云盘',
storage: 'hash'
},
'jianguoyun': {
reg: /((?:https?:\/\/)?www\.jianguoyun\.com\/p\/[\w-]+)/,
host: /www\.jianguoyun\.com/,
input: ['input[type=password]'],
button: ['.ok-button', '.confirm-button'],
name: '坚果云',
storage: 'hash'
},
'wo': {
reg: /(?:https?:\/\/)?pan\.wo\.cn\/s\/[\w_]+/,
host: /(pan\.wo\.cn|panservice\.mail\.wo\.cn)/,
input: ['input.el-input__inner', ".van-field__control"],
button: ['.s-button', ".share-code button"],
name: '联通云盘',
storage: (() => util.isMobile === true ? 'local' : 'hash')(),
storagePwdName: 'tmp_wo_pwd'
},
'mega': {
reg: /((?:https?:\/\/)?(?:mega\.nz|mega\.co\.nz)\/#F?![\w!-]+)/,
host: /(?:mega\.nz|mega\.co\.nz)/,
input: ['.dlkey-dialog input'],
button: ['.dlkey-dialog .fm-dialog-new-folder-button'],
name: 'Mega',
storage: 'local'
},
'520vip': {
reg: /((?:https?:\/\/)?www\.(?:520-vip|eos-53)\.com\/file-\d+\.html)/,
host: /www\.520-vip\.com/,
name: '520云盘',
},
'567pan': {
reg: /((?:https?:\/\/)?www\.567(?:pan|yun|file|inc)\.(?:com|cn)\/file-\d+\.html)/,
host: /www\.567inc\.cn/,
name: '567盘',
replaceHost: "www.567inc.com",
},
'ayunpan': {
reg: /((?:https?:\/\/)?www\.ayunpan\.com\/file-\d+\.html)/,
host: /www\.ayunpan\.com/,
name: 'AYunPan',
},
'iycdn.com': {
reg: /((?:https?:\/\/)?www\.iycdn\.com\/file-\d+\.html)/,
host: /www\.iycdn\.com/,
name: '爱优网盘',
},
'feimaoyun': {
reg: /((?:https?:\/\/)?www\.feimaoyun\.com\/s\/[0-9a-zA-Z]+)/,
host: /www\.feimaoyun\.com/,
name: '飞猫盘',
},
'uyunp.com': {
reg: /((?:https?:\/\/)?download\.uyunp\.com\/share\/s\/short\/\?surl=[0-9a-zA-Z]+)/,
host: /download\.uyunp\.com/,
name: '优云下载',
},
'dudujb': {
reg: /(?:https?:\/\/)?www\.dudujb\.com\/file-\d+\.html/,
host: /www\.dudujb\.com/,
name: '贵族网盘',
},
'xunniu': {
reg: /(?:https?:\/\/)?www\.xunniu(?:fxp|wp|fx)\.com\/file-\d+\.html/,
host: /www\.xunniuwp\.com/,
name: '迅牛网盘',
},
'xueqiupan': {
reg: /(?:https?:\/\/)?www\.xueqiupan\.com\/file-\d+\.html/,
host: /www\.xueqiupan\.com/,
name: '雪球云盘',
},
'77file': {
reg: /(?:https?:\/\/)?www\.77file\.com\/s\/[a-zA-Z\d]+/,
host: /www\.77file\.com/,
name: '77file',
},
'ownfile': {
reg: /(?:https?:\/\/)?ownfile\.net\/files\/[a-zA-Z\d]+\.html/,
host: /ownfile\.net/,
name: 'OwnFile',
},
'feiyunfile': {
reg: /(?:https?:\/\/)?www\.feiyunfile\.com\/file\/[\w=]+\.html/,
host: /www\.feiyunfile\.com/,
name: '飞云网盘',
},
'yifile': {
reg: /(?:https?:\/\/)?www\.yifile\.com\/f\/\w+/,
host: /www\.yifile\.com/,
name: 'YiFile',
},
'dufile': {
reg: /(?:https?:\/\/)?dufile\.com\/file\/\w+\.html/,
host: /dufile\.com/,
name: 'duFile',
},
'flowus': {
reg: /((?:https?:\/\/)?flowus\.cn\/[\S ^\/]*\/?share\/[a-z\d]{8}-[a-z\d]{4}-[a-z\d]{4}-[a-z\d]{4}-[a-z\d]{12})/,
host: /flowus\.cn/,
name: 'FlowUs息流',
storage: 'hash'
},
'chrome': {
reg: /^https?:\/\/chrome.google.com\/webstore\/.+?\/([a-z]{32})(?=[\/#?]|$)/,
host: /chrome\.google\.com/,
replaceHost: "chrome.crxsoso.com",
name: 'Chrome商店',
},
'edge': {
reg: /^https?:\/\/microsoftedge.microsoft.com\/addons\/.+?\/([a-z]{32})(?=[\/#?]|$)/,
host: /microsoftedge\.microsoft\.com/,
replaceHost: "microsoftedge.crxsoso.com",
name: 'Edge商店',
},
'firefox': {
reg: /^https?:\/\/(reviewers\.)?(addons\.mozilla\.org|addons(?:-dev)?\.allizom\.org)\/.*?(?:addon|review)\/([^/<>"'?#]+)/,
host: /addons\.mozilla\.org/,
replaceHost: "addons.crxsoso.com",
name: 'Firefox商店',
},
'microsoft': {
reg: /^https?:\/\/(?:apps|www).microsoft.com\/(?:store|p)\/.+?\/([a-zA-Z\d]{10,})(?=[\/#?]|$)/,
host: /(apps|www)\.microsoft\.com/,
replaceHost: "apps.crxsoso.com",
name: 'Windows商店',
}
};
let main = {
lastText: "lorem&",
//初始化配置数据
initValue() {
let value = [{
name: 'setting_success_times',
value: 0
}, {
name: 'setting_auto_click_btn',
value: true
}, {
name: 'setting_active_in_front',
value: true
}, {
name: 'setting_timer_open',
value: false
}, {
name: 'setting_timer',
value: 5000
}, {
name: 'setting_hotkeys',
value: 'F1'
}];
value.forEach((v) => {
if (util.getValue(v.name) === undefined) {
util.setValue(v.name, v.value);
}
});
},
// 监听选择事件
addPageListener() {
document.addEventListener("mouseup", this.smartIdentify.bind(this), true);
document.addEventListener("keydown", this.pressKey.bind(this), true);
},
// ⚠️可能会增加时间⚠️ 如果有需要可以增加选项
// 获取选择内容的HTML和文本(增加兼容性) 或 DOM节点遍历
getSelectionHTML(selection, isDOM = false) {
const testDiv = document.createElement("div");
if (!selection.isCollapsed) {
// Range 转 DocumentFragment
const docFragment = selection.getRangeAt(0).cloneContents();
testDiv.appendChild(docFragment);
}
// 拼接选中文本,增加兼容
return isDOM ? testDiv : selection.toString();
},
smartIdentify(event, str = '') {
let selection = window.getSelection();
let text = str || this.getSelectionHTML(selection);
if (text !== this.lastText && text !== '') { //选择相同文字或空不识别
let start = performance.now();
this.lastText = text;
//util.clog(`当前选中文字:${text}`);
let linkObj = this.parseLink(text);
let link = linkObj.link;
let name = linkObj.name;
let pwd = this.parsePwd(text);
if (!link) {
linkObj = this.parseParentLink(selection);
link = linkObj.link;
name = linkObj.name;
}
if (link) {
if (!/https?:\/\//.test(link)) {
link = 'https://' + link;
}
let end = performance.now();
let time = (end - start).toFixed(3);
util.clog(`文本识别结果:${name} 链接:${link} 密码:${pwd} 耗时:${time}毫秒`);
let option = {
toast: true,
showCancelButton: true,
position: 'top',
title: `发现<span style="color: #2778c4;margin: 0 5px;">${name}</span>链接`,
html: `<span style="font-size: 0.8em;">${!!pwd ? '密码:' + pwd : '是否打开?'}</span>`,
confirmButtonText: '打开',
cancelButtonText: '关闭',
customClass
};
if (util.getValue('setting_timer_open')) {
option.timer = util.getValue('setting_timer');
option.timerProgressBar = true;
}
util.setValue('setting_success_times', util.getValue('setting_success_times') + 1);
Swal.fire(option).then((res) => {
this.lastText = 'lorem&';
selection.empty();
if (res.isConfirmed || res.dismiss === 'timer') {
if (linkObj.storage == "local") {
util.setValue(linkObj.storagePwdName, pwd);
}
let active = util.getValue('setting_active_in_front');
if (pwd) {
let extra = `${link}?pwd=${pwd}#${pwd}`;
if (~link.indexOf('?')) {
extra = `${link}&pwd=${pwd}#${pwd}`;
}
GM_openInTab(extra, {active});
} else {
GM_openInTab(`${link}`, {active});
}
}
});
}
}
},
pressKey(event) {
if (event.key === 'Enter') {
let confirmBtn = document.querySelector('.panai-container .swal2-confirm');
confirmBtn && confirmBtn.click();
}
if (event.key === 'Escape') {
let cancelBtn = document.querySelector('.panai-container .swal2-cancel');
cancelBtn && cancelBtn.click();
}
},
addHotKey() {
//获取设置中的快捷键
let hotkey = util.getValue('setting_hotkeys');
hotkeys(hotkey, (event, handler) => {
event.preventDefault();
this.showIdentifyBox();
});
},
//正则解析网盘链接
parseLink(text = '') {
let obj = {name: '', link: '', storage: '', storagePwdName: ''};
if (text) {
try {
text = decodeURIComponent(text);
} catch {
}
text = text.replace(/[点點]/g, '.');
text = text.replace(/[\u4e00-\u9fa5(),\u200B\uD83C-\uDBFF\uDC00-\uDFFF]/g, '');
text = text.replace(/lanzous/g, 'lanzouw'); //修正lanzous打不开的问题
for (let name in opt) {
let val = opt[name];
if (val.reg.test(text)) {
let matches = text.match(val.reg);
obj.name = val.name;
obj.link = matches[0];
obj.storage = val.storage;
obj.storagePwdName = val.storagePwdName || null;
if (val.replaceHost) {
obj.link = obj.link.replace(val.host, val.replaceHost);
}
return obj;
}
}
}
return obj;
},
//正则解析超链接类型网盘链接
parseParentLink(selection) {
const dom = this.getSelectionHTML(selection, true).querySelector('*[href]');
return this.parseLink(dom ? dom.href : "");
},
//正则解析提取码
parsePwd(text) {
text = text.replace(/\u200B/g, '').replace('%3A', ":");
text = text.replace(/(?:本帖)?隐藏的?内容[:]?/, "");
let reg = /wss:[a-zA-Z0-9]+|(?<=\s*(?:密|提取|访问|訪問|key|password|pwd|#|\?p=)\s*[码碼]?\s*[:=]?\s*)[a-zA-Z0-9]{3,8}/i;
if (reg.test(text)) {
let match = text.match(reg);
return match[0];
}
return '';
},
//根据域名检测网盘类型
panDetect() {
let hostname = location.hostname;
for (let name in opt) {
let val = opt[name];
if (val.host.test(hostname)) {
return name;
}
}
return '';
},
//自动填写密码
autoFillPassword() {
let query = util.parseQuery('pwd|p');
let hash = location.hash.slice(1).replace(/\W/g, "") //hash中可能存在密码需要过滤掉非密码字符
let pwd = query || hash;
let panType = this.panDetect();
for (let name in opt) {
let val = opt[name];
if (panType === name) {
if (val.storage === 'local') {
//当前local存储的密码不一定是当前链接的密码用户可能通过url直接访问或者恢复页面这样取出来的密码可能是其他链接的
//如果能从url中获取到密码则应该优先使用url中获取的密码
//util.getValue查询不到key时默认返回undefined已经形成逻辑短路此处赋空值无效也无需赋空值.详见https://github.com/syhyz1990/panAI/commit/efb6ff0c77972920b26617bb836a2e19dd14a749
pwd = pwd || util.getValue(val.storagePwdName);
pwd && this.doFillAction(val.input, val.button, pwd);
}
if (val.storage === 'hash') {
if (!/^(?:wss:[a-zA-Z\d]+|[a-zA-Z0-9]{3,8})$/.test(pwd)) { //过滤掉不正常的Hash
return;
}
pwd && this.doFillAction(val.input, val.button, pwd);
}
}
}
},
doFillAction(inputSelector, buttonSelector, pwd) {
let maxTime = 10;
let ins = setInterval(async () => {
maxTime--;
let input = util.query(inputSelector);
let button = util.query(buttonSelector);
if (input && !util.isHidden(input)) {
clearInterval(ins);
Swal.fire({
toast: true,
position: 'top',
showCancelButton: false,
showConfirmButton: false,
title: 'AI已识别到密码正自动帮您填写',
icon: 'success',
timer: 2000,
customClass
});
let lastValue = input.value;
input.value = pwd;
//Vue & React 触发 input 事件
let event = new Event('input', {bubbles: true});
let tracker = input._valueTracker;
if (tracker) {
tracker.setValue(lastValue);
}
input.dispatchEvent(event);
if (util.getValue('setting_auto_click_btn')) {
await util.sleep(1000); //1秒后点击按钮
button.click();
}
} else {
maxTime === 0 && clearInterval(ins);
}
}, 800);
},
//重置识别次数
clearIdentifyTimes() {
let res = Swal.fire({
showCancelButton: true,
title: '确定要重置识别次数吗?',
icon: 'warning',
confirmButtonText: '确定',
cancelButtonText: '取消',
customClass
}).then(res => {
this.lastText = 'lorem&';
if (res.isConfirmed) {
util.setValue('setting_success_times', 0);
history.go(0);
}
});
},
//识别输入框中的内容
showIdentifyBox() {
Swal.fire({
title: '识别剪切板中文字',
input: 'textarea',
inputPlaceholder: '若选方式一,请按 Ctrl+V 粘贴要识别的文字',
html: `<div style="font-size: 12px;color: #999;margin-bottom: 8px;text-align: center;">提示:在任意网页按下 <span style="font-weight: 700;">${util.getValue("setting_hotkeys")}</span> 键可快速打开本窗口。</div><div style="font-size: 14px;line-height: 22px;padding: 10px 0 5px;text-align: left;"><div style="font-size: 16px;margin-bottom: 8px;font-weight: 700;">支持以下两种方式:</div><div><b>方式一:</b>直接粘贴文字到输入框,点击“识别方框内容”按钮。</div><div><b>方式二:</b>点击“读取剪切板”按钮。<span style="color: #d14529;font-size: 12px;">会弹出“授予网站读取剪切板”权限,同意后会自动识别剪切板中的文字。</span></div></div>`,
showCloseButton: false,
showDenyButton: true,
confirmButtonText: '识别方框内容',
denyButtonText: '读取剪切板',
customClass
}).then(res => {
if (res.isConfirmed) {
this.smartIdentify(null, res.value);
}
if (res.isDenied) {
navigator.clipboard.readText().then(text => {
this.smartIdentify(null, text);
}).catch(() => {
toast.fire({title: '读取剪切板失败,请先授权或手动粘贴后识别!', icon: 'error'});
});
}
});
},
//显示设置
showSettingBox() {
let html = `<div style="font-size: 1em;">
<label class="panai-setting-label">填写密码后自动提交<input type="checkbox" id="S-Auto" ${util.getValue('setting_auto_click_btn') ? 'checked' : ''} class="panai-setting-checkbox"></label>
<label class="panai-setting-label">前台打开网盘标签页<input type="checkbox" id="S-Active" ${util.getValue('setting_active_in_front') ? 'checked' : ''}
class="panai-setting-checkbox"></label>
<label class="panai-setting-label">倒计时结束自动打开<input type="checkbox" id="S-Timer-Open" ${util.getValue('setting_timer_open') ? 'checked' : ''} class="panai-setting-checkbox"></label>
<label class="panai-setting-label" id="Panai-Range-Wrapper" style="${util.getValue('setting_timer_open') ? '' : 'display: none'}"><span>倒计时 <span id="Timer-Value">${util.getValue('setting_timer') / 1000}秒)</span></span><input type="range" id="S-Timer" min="0" max="10000" step="500" value="${util.getValue('setting_timer')}" style="width: 200px;"></label>
<label class="panai-setting-label">快捷键设置<input type="text" id="S-hotkeys" value="${util.getValue('setting_hotkeys')}" style="width: 100px;"></label>
</div>`;
Swal.fire({
title: '识别助手配置',
html,
icon: 'info',
showCloseButton: true,
confirmButtonText: '保存',
footer: '<div style="text-align: center;font-size: 1em;">点击查看 <a href="https://www.youxiaohou.com/tool/install-panai.html" target="_blank">使用说明</a>助手免费开源Powered by <a href="https://www.youxiaohou.com">油小猴</a></div>',
customClass
}).then((res) => {
res.isConfirmed && history.go(0);
});
document.getElementById('S-Auto').addEventListener('change', (e) => {
util.setValue('setting_auto_click_btn', e.target.checked);
});
document.getElementById('S-Active').addEventListener('change', (e) => {
util.setValue('setting_active_in_front', e.target.checked);
});
document.getElementById('S-Timer-Open').addEventListener('change', (e) => {
let rangeWrapper = document.getElementById('Panai-Range-Wrapper');
e.target.checked ? rangeWrapper.style.display = 'flex' : rangeWrapper.style.display = 'none';
util.setValue('setting_timer_open', e.target.checked);
});
document.getElementById('S-Timer').addEventListener('change', (e) => {
util.setValue('setting_timer', e.target.value);
document.getElementById('Timer-Value').innerText = `${e.target.value / 1000}秒)`;
});
document.getElementById('S-hotkeys').addEventListener('change', (e) => {
util.setValue('setting_hotkeys', e.target.value);
});
},
registerMenuCommand() {
GM_registerMenuCommand('👀 已识别:' + util.getValue('setting_success_times') + '次', () => {
this.clearIdentifyTimes();
});
GM_registerMenuCommand(`📋️ 识别剪切板中文字(快捷键 ${util.getValue('setting_hotkeys')}`, () => {
this.showIdentifyBox();
});
GM_registerMenuCommand('⚙️ 设置', () => {
this.showSettingBox();
});
},
addPluginStyle() {
let style = `
.panai-container { z-index: 99999!important }
.panai-popup { font-size: 14px !important }
.panai-setting-label { display: flex;align-items: center;justify-content: space-between;padding-top: 20px; }
.panai-setting-checkbox { width: 16px;height: 16px; }
`;
if (document.head) {
util.addStyle('swal-pub-style', 'style', GM_getResourceText('swalStyle'));
util.addStyle('panai-style', 'style', style);
}
const headObserver = new MutationObserver(() => {
util.addStyle('swal-pub-style', 'style', GM_getResourceText('swalStyle'));
util.addStyle('panai-style', 'style', style);
});
headObserver.observe(document.head, {childList: true, subtree: true});
},
isTopWindow() {
return window.self === window.top;
},
init() {
this.initValue();
this.addPluginStyle();
this.addHotKey();
this.autoFillPassword();
this.addPageListener();
this.isTopWindow() && this.registerMenuCommand();
},
};
main.init();
})();

387
web-front/src/parserUrl1.js Normal file
View File

@@ -0,0 +1,387 @@
// 修改自 https://github.com/syhyz1990/panAI
const util = {
isMobile: (() => !!navigator.userAgent.match(/(phone|pad|pod|iPhone|iPod|ios|iPad|Android|Mobile|BlackBerry|IEMobile|MQQBrowser|JUC|Fennec|wOSBrowser|BrowserNG|WebOS|Symbian|Windows Phone|HarmonyOS|MicroMessenger)/i))(),
}
let opt = {
// 'baidu': {
// reg: /((?:https?:\/\/)?(?:e?yun|pan)\.baidu\.com\/(doc\/|enterprise\/)?(?:s\/[\w~]*(((-)?\w*)*)?|share\/\S{4,}))/,
// host: /(pan|e?yun)\.baidu\.com/,
// input: ['#accessCode', '.share-access-code', '#wpdoc-share-page > .u-dialog__wrapper .u-input__inner'],
// button: ['#submitBtn', '.share-access .g-button', '#wpdoc-share-page > .u-dialog__wrapper .u-btn--primary'],
// name: '百度网盘',
// storage: 'hash'
// },
// 'aliyun': {
// reg: /((?:https?:\/\/)?(?:(?:www\.)?(?:aliyundrive|alipan)\.com\/s|alywp\.net)\/[a-zA-Z\d]+)/,
// host: /www\.(aliyundrive|alipan)\.com|alywp\.net/,
// input: ['form .ant-input', 'form input[type="text"]', 'input[name="pwd"]'],
// button: ['form .button--fep7l', 'form button[type="submit"]'],
// name: '阿里云盘',
// storage: 'hash'
// },
// 'weiyun': {
// reg: /((?:https?:\/\/)?share\.weiyun\.com\/[a-zA-Z\d]+)/,
// host: /share\.weiyun\.com/,
// input: ['.mod-card-s input[type=password]', 'input.pw-input'],
// button: ['.mod-card-s .btn-main', ".pw-btn-wrap button.btn"],
// name: '微云',
// storage: 'hash'
// },
// 'tianyi': {
// reg: /((?:https?:\/\/)?cloud\.189\.cn\/(?:t\/|web\/share\?code=)?[a-zA-Z\d]+)/,
// host: /cloud\.189\.cn/,
// input: ['.access-code-item #code_txt', "input.access-code-input"],
// button: ['.access-code-item .visit', ".button"],
// name: '天翼云盘',
// storage: (() => util.isMobile === true ? 'local' : 'hash')(),
// storagePwdName: 'tmp_tianyi_pwd'
// },
// 'caiyun': {
// reg: /((?:https?:\/\/)?caiyun\.139\.com\/(?:m\/i|w\/i\/|web\/|front\/#\/detail)\??(?:linkID=)?[a-zA-Z\d]+)/,
// host: /(?:cai)?yun\.139\.com/,
// input: ['.token-form input[type=text]'],
// button: ['.token-form .btn-token'],
// name: '移动云盘',
// storage: 'local',
// storagePwdName: 'tmp_caiyun_pwd'
// },
// 'xunlei': {
// reg: /((?:https?:\/\/)?pan\.xunlei\.com\/s\/[\w-]{10,})/,
// host: /pan\.xunlei\.com/,
// input: ['.pass-input-wrap .td-input__inner'],
// button: ['.pass-input-wrap .td-button'],
// name: '迅雷云盘',
// storage: 'hash'
// },
// '360': {
// reg: /((?:https?:\/\/)?(?:[a-zA-Z\d\-.]+)?(?:yunpan\.360\.cn|yunpan\.com)(\/lk)?\/surl_\w{6,})/,
// host: /[\w.]+?yunpan\.com/,
// input: ['.pwd-input'],
// button: ['.submit-btn'],
// name: '360云盘',
// storage: 'local',
// storagePwdName: 'tmp_360_pwd'
// },
// '115': {
// reg: /((?:https?:\/\/)?115\.com\/s\/[a-zA-Z\d]+)/,
// host: /115\.com/,
// input: ['.form-decode input'],
// button: ['.form-decode .submit a'],
// name: '115网盘',
// storage: 'hash'
// },
// 'quark': {
// reg: /((?:https?:\/\/)?pan\.quark\.cn\/s\/[a-zA-Z\d-]+)/,
// host: /pan\.quark\.cn/,
// input: ['.ant-input'],
// button: ['.ant-btn-primary'],
// name: '夸克网盘',
// storage: 'local',
// storagePwdName: 'tmp_quark_pwd'
// },
// 'vdisk': {
// reg: /(?:https?:\/\/)?vdisk.weibo.com\/lc\/\w+/,
// host: /vdisk\.weibo\.com/,
// input: ['#keypass', "#access_code"],
// button: ['.search_btn_wrap a', "#linkcommon_btn"],
// name: '微盘',
// storage: 'hash',
// },
// 'uc': {
// reg: /(?:https?:\/\/)?drive\.uc\.cn\/s\/[a-zA-Z\d]+/,
// host: /drive\.uc\.cn/,
// input: ["input[class*='ShareReceivePC--input']", '.input-wrap input'],
// button: ["button[class*='ShareReceivePC--submit-btn'", '.input-wrap button'],
// name: 'UC云盘',
// storage: 'hash'
// },
// 'jianguoyun': {
// reg: /((?:https?:\/\/)?www\.jianguoyun\.com\/p\/[\w-]+)/,
// host: /www\.jianguoyun\.com/,
// input: ['input[type=password]'],
// button: ['.ok-button', '.confirm-button'],
// name: '坚果云',
// storage: 'hash'
// },
// 'wo': {
// reg: /(?:https?:\/\/)?pan\.wo\.cn\/s\/[\w_]+/,
// host: /(pan\.wo\.cn|panservice\.mail\.wo\.cn)/,
// input: ['input.el-input__inner', ".van-field__control"],
// button: ['.s-button', ".share-code button"],
// name: '联通云盘',
// storage: (() => util.isMobile === true ? 'local' : 'hash')(),
// storagePwdName: 'tmp_wo_pwd'
// },
// 'mega': {
// reg: /((?:https?:\/\/)?(?:mega\.nz|mega\.co\.nz)\/#F?![\w!-]+)/,
// host: /(?:mega\.nz|mega\.co\.nz)/,
// input: ['.dlkey-dialog input'],
// button: ['.dlkey-dialog .fm-dialog-new-folder-button'],
// name: 'Mega',
// storage: 'local'
// },
// '520vip': {
// reg: /((?:https?:\/\/)?www\.(?:520-vip|eos-53)\.com\/file-\d+\.html)/,
// host: /www\.520-vip\.com/,
// name: '520云盘',
// },
// '567pan': {
// reg: /((?:https?:\/\/)?www\.567(?:pan|yun|file|inc)\.(?:com|cn)\/file-\d+\.html)/,
// host: /www\.567inc\.cn/,
// name: '567盘',
// replaceHost: "www.567inc.com",
// },
// 'ayunpan': {
// reg: /((?:https?:\/\/)?www\.ayunpan\.com\/file-\d+\.html)/,
// host: /www\.ayunpan\.com/,
// name: 'AYunPan',
// },
// 'iycdn.com': {
// reg: /((?:https?:\/\/)?www\.iycdn\.com\/file-\d+\.html)/,
// host: /www\.iycdn\.com/,
// name: '爱优网盘',
// },
// 'feimaoyun': {
// reg: /((?:https?:\/\/)?www\.feimaoyun\.com\/s\/[0-9a-zA-Z]+)/,
// host: /www\.feimaoyun\.com/,
// name: '飞猫盘',
// },
// 'uyunp.com': {
// reg: /((?:https?:\/\/)?download\.uyunp\.com\/share\/s\/short\/\?surl=[0-9a-zA-Z]+)/,
// host: /download\.uyunp\.com/,
// name: '优云下载',
// },
// 'dudujb': {
// reg: /(?:https?:\/\/)?www\.dudujb\.com\/file-\d+\.html/,
// host: /www\.dudujb\.com/,
// name: '贵族网盘',
// },
// 'xunniu': {
// reg: /(?:https?:\/\/)?www\.xunniu(?:fxp|wp|fx)\.com\/file-\d+\.html/,
// host: /www\.xunniuwp\.com/,
// name: '迅牛网盘',
// },
// 'xueqiupan': {
// reg: /(?:https?:\/\/)?www\.xueqiupan\.com\/file-\d+\.html/,
// host: /www\.xueqiupan\.com/,
// name: '雪球云盘',
// },
// '77file': {
// reg: /(?:https?:\/\/)?www\.77file\.com\/s\/[a-zA-Z\d]+/,
// host: /www\.77file\.com/,
// name: '77file',
// },
// 'ownfile': {
// reg: /(?:https?:\/\/)?ownfile\.net\/files\/[a-zA-Z\d]+\.html/,
// host: /ownfile\.net/,
// name: 'OwnFile',
// },
// 'feiyunfile': {
// reg: /(?:https?:\/\/)?www\.feiyunfile\.com\/file\/[\w=]+\.html/,
// host: /www\.feiyunfile\.com/,
// name: '飞云网盘',
// },
// 'yifile': {
// reg: /(?:https?:\/\/)?www\.yifile\.com\/f\/\w+/,
// host: /www\.yifile\.com/,
// name: 'YiFile',
// },
// 'dufile': {
// reg: /(?:https?:\/\/)?dufile\.com\/file\/\w+\.html/,
// host: /dufile\.com/,
// name: 'duFile',
// },
// 'flowus': {
// reg: /((?:https?:\/\/)?flowus\.cn\/[\S ^\/]*\/?share\/[a-z\d]{8}-[a-z\d]{4}-[a-z\d]{4}-[a-z\d]{4}-[a-z\d]{12})/,
// host: /flowus\.cn/,
// name: 'FlowUs息流',
// storage: 'hash'
// },
// 'chrome': {
// reg: /^https?:\/\/chrome.google.com\/webstore\/.+?\/([a-z]{32})(?=[\/#?]|$)/,
// host: /chrome\.google\.com/,
// replaceHost: "chrome.crxsoso.com",
// name: 'Chrome商店',
// },
// 'edge': {
// reg: /^https?:\/\/microsoftedge.microsoft.com\/addons\/.+?\/([a-z]{32})(?=[\/#?]|$)/,
// host: /microsoftedge\.microsoft\.com/,
// replaceHost: "microsoftedge.crxsoso.com",
// name: 'Edge商店',
// },
// 'firefox': {
// reg: /^https?:\/\/(reviewers\.)?(addons\.mozilla\.org|addons(?:-dev)?\.allizom\.org)\/.*?(?:addon|review)\/([^/<>"'?#]+)/,
// host: /addons\.mozilla\.org/,
// replaceHost: "addons.crxsoso.com",
// name: 'Firefox商店',
// },
// 'microsoft': {
// reg: /^https?:\/\/(?:apps|www).microsoft.com\/(?:store|p)\/.+?\/([a-zA-Z\d]{10,})(?=[\/#?]|$)/,
// host: /(apps|www)\.microsoft\.com/,
// replaceHost: "apps.crxsoso.com",
// name: 'Windows商店',
// }
'lanzou': {
reg: /((?:https?:\/\/)?(?:[a-zA-Z0-9\-.]+)?(?:lanzou[a-z]|lanzn)\.com\/[a-zA-Z\d_\-]+(?:\/[\w-]+)?)/,
host: /(?:[a-zA-Z\d-.]+)?(?:lanzou[a-z]|lanzn)\.com/,
input: ['#pwd'],
button: ['.passwddiv-btn', '#sub'],
name: '蓝奏云',
storage: 'hash'
},
'cowtransfer': {
reg: /((?:https?:\/\/)?(?:[a-zA-Z\d-.]+)?cowtransfer\.com\/s\/[a-zA-Z\d]+)/,
host: /(?:[a-zA-Z\d-.]+)?cowtransfer\.com/,
input: ['.receive-code-input input'],
button: ['.open-button'],
name: '奶牛快传',
storage: 'hash'
},
'ctfile': {
reg: /((?:https?:\/\/)?(?:[a-zA-Z\d-.]+)?(?:ctfile|545c|u062|ghpym|474b)\.com\/\w+\/[a-zA-Z\d-]+)/,
host: /(?:[a-zA-Z\d-.]+)?(?:ctfile|545c|u062|474b)\.com/,
input: ['#passcode'],
button: ['.card-body button'],
name: '城通网盘',
storage: 'hash'
},
'123pan': {
reg: /((?:https?:\/\/)?www\.(123pan|123865|123684)\.com\/s\/[\w-]{6,})/,
host: /www\.123pan\.com/,
input: ['.ca-fot input', ".appinput .appinput"],
button: ['.ca-fot button', ".appinput button"],
name: '123云盘',
storage: 'hash'
},
'wenshushu': {
reg: /((?:https?:\/\/)?(?:www\.wenshushu|ws28)\.cn\/(?:k|box|f)\/\w+)/,
host: /www\.wenshushu\.cn/,
input: ['.pwd-inp .ivu-input'],
button: ['.pwd-inp .ivu-btn'],
name: '文叔叔网盘',
storage: 'hash'
},
// ---new---
feijix: {
reg: /https:\/\/(share\.feijipan\.com|www\.feijix\.com)\/s\/.+/,
host: /feijix\.com|feijipan\.com/,
name: '小飞机网盘'
},
lecloud: {
reg: /https:\/\/lecloud\.lenovo\.com\/share\/.+/,
host: /lenovo\.com/,
name: '联想乐云'
},
fangcloud: {
reg: /https:\/\/v2\.fangcloud\.(com|cn)\/(s|sharing)\/.+/,
host: /fangcloud\.(com|cn)/,
name: '亿方云'
},
ilanzou: {
reg: /https:\/\/www\.ilanzou\.com\/s\/.+/,
host: /ilanzou\.com/,
name: '蓝奏云优享'
},
qqMailTransfer: {
reg: /https:\/\/iwx\.mail\.qq\.com\/ftn\/download\?.+/,
host: /mail\.qq\.com/,
name: 'QQ邮箱中转站'
},
pan118: {
reg: /https:\/\/(?:[a-zA-Z\d-]+\.)?118pan\.com\/b.+/,
host: /118pan\.com/,
name: '118网盘'
},
onedrive: {
reg: /https:\/\/1drv\.ms\/[uw]\/s!.+/,
host: /1drv\.ms/,
name: 'OneDrive'
},
googleDrive: {
reg: /https:\/\/drive\.google\.com\/file\/d\/.+\/view\?usp=(sharing|drive_link)?/,
host: /drive\.google\.com/,
name: 'GoogleDrive'
},
n163Music: {
reg: /https:\/\/163cn\.tv\/.+/,
host: /163cn\.tv/,
name: '网易云音乐分享'
},
qqMusic: {
reg: /https:\/\/y\.qq\.com\/n\/ryqq\/songDetail\/.+/,
host: /y\.qq\.com/,
name: 'QQ音乐歌曲详情'
},
kuwoMusic: {
reg: /https:\/\/(m\.)?kuwo\.cn\/(newh5app\/)?play_detail\/.+/,
host: /kuwo\.cn/,
name: '酷我音乐分享'
},
miguMusic: {
reg: /https:\/\/music\.migu\.cn\/v3\/music\/song\/.+/,
host: /migu\.cn/,
name: '咪咕音乐分享'
},
other: {
reg: /https:\/\/([a-zA-Z0-9]+(-[a-zA-Z0-9]+)*\.)+[a-zA-Z]{2,}\/s\/.+/,
host: /.*/,
name: '其他/Cloudreve/可道云'
},
};
let main = {
//正则解析网盘链接
parseLink(text = '') {
let obj = {name: '', link: '', storage: '', storagePwdName: ''};
if (text) {
try {
text = decodeURIComponent(text);
} catch {
}
text = text.replace(/[点點]/g, '.');
text = text.replace(/[\u4e00-\u9fa5(),\u200B\uD83C-\uDBFF\uDC00-\uDFFF]/g, '');
text = text.replace(/lanzous/g, 'lanzouw'); //修正lanzous打不开的问题
for (let name in opt) {
let val = opt[name];
if (val.reg.test(text)) {
let matches = text.match(val.reg);
obj.name = val.name;
obj.link = matches[0];
obj.storage = val.storage;
obj.storagePwdName = val.storagePwdName || null;
if (val.replaceHost) {
obj.link = obj.link.replace(val.host, val.replaceHost);
}
return obj;
}
}
}
return obj;
},
//正则解析提取码
parsePwd(text = '') {
text = text.replace(/\u200B/g, '').replace('%3A', ":");
text = text.replace(/(?:本帖)?隐藏的?内容[:]?/, "");
let reg = /wss:[a-zA-Z0-9]+|(?<=\s*(?:密|提取|访问|訪問|key|password|pwd|#|\?p=)\s*[码碼]?\s*[:=]?\s*)[a-zA-Z0-9]{3,8}/i;
if (reg.test(text)) {
let match = text.match(reg);
return match[0];
}
return '';
},
};
export default {
parseLink: main.parseLink,
parsePwd: main.parsePwd,
opt: opt
}

View File

@@ -17,7 +17,7 @@ module.exports = {
proxy: {
'/': {
target: 'http://127.0.0.1:6400', // 请求本地
ws: true
ws: false
},
}
},

View File

@@ -5,10 +5,11 @@ import cn.qaiu.entity.ShareLinkInfo;
import cn.qaiu.lz.common.cache.CacheManager;
import cn.qaiu.lz.common.util.URLParamUtil;
import cn.qaiu.lz.web.model.LinkInfoResp;
import cn.qaiu.lz.web.model.StatisticsInfo;
import cn.qaiu.lz.web.model.SysUser;
import cn.qaiu.lz.web.service.DbService;
import cn.qaiu.lz.web.service.UserService;
import cn.qaiu.lz.web.model.StatisticsInfo;
import cn.qaiu.parser.PanDomainTemplate;
import cn.qaiu.parser.ParserCreate;
import cn.qaiu.vx.core.annotaions.RouteHandler;
import cn.qaiu.vx.core.annotaions.RouteMapping;
@@ -21,6 +22,12 @@ import io.vertx.core.http.HttpServerRequest;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import java.util.stream.Collectors;
@RouteHandler(value = "/v2", order = 10)
@Slf4j
public class ParserApi {
@@ -76,4 +83,17 @@ public class ParserApi {
return linkPrefix + (isJson ? "/json/" : "/d/") + create.genPathSuffix();
}
/**
* 获取支持的网盘列表
* @return list-map: name: 网盘名, type: 网盘标识, url: 网盘域名地址
*/
@RouteMapping("/getPanList")
public List<Map<String, String>> getPanList() {
return Arrays.stream(PanDomainTemplate.values()).map(pan -> new TreeMap<String, String>() {{
put("name", pan.getDisplayName());
put("type", pan.name().toLowerCase());
put("url", pan.getPanDomain());
}}).collect(Collectors.toList());
}
}

View File

@@ -10,11 +10,12 @@ server:
# 反向代理服务器配置路径(不用加后缀)
proxyConf: server-proxy
# vertx线程配置, 为0表示eventLoopPoolSize将会采用默认配置(CPU核心*2) workerPoolSize将会采用默认20
# vertx核心线程配置(一般无需改的), 为0表示eventLoopPoolSize将会采用默认配置(CPU核心*2) workerPoolSize将会采用默认20
vertx:
eventLoopPoolSize: 0
workerPoolSize: 0
# vertx-service配置(一般无需改的)
custom:
# 异步服务线程数
asyncServiceInstances: 4

View File

@@ -157,3 +157,17 @@ https://onedrive.live.com/redir?resid=ABFD0A26E47D3458!4699&authkey=!AO7jjiGDnJW
###
https://api.onedrive.com/v1.0/drives/abfd0a26e47d3458/items/ABFD0A26E47D3458!4699?authkey=!AO7jjiGDnJWoNwo
### 谷歌云盘
https://drive.google.com/file/d/1iofiAmFs2NaBHp4OyeIo7sbVX-jQ0imB/view?usp=sharing
###
https://drive.google.com/file/d/151bR-nk-tOBm9QAFaozJIVt2WYyCMkoz/view?usp=drive_link
#302链
#https://drive.usercontent.google.com/uc?id=1iofiAmFs2NaBHp4OyeIo7sbVX-jQ0imB&export=download
#直链
#https://drive.usercontent.google.com/download?id=1iofiAmFs2NaBHp4OyeIo7sbVX-jQ0imB&export=download
#https://drive.usercontent.google.com/download?id=151bR-nk-tOBm9QAFaozJIVt2WYyCMkoz&export=download&confirm=t&uuid=bb8870cb-debd-4ba0-b239-aca14b6a9782&at=AENtkXYr-p2Bv0EDgKyXyYcZwOwA%3A1730526150700
#https://drive.usercontent.google.com/download?id=151bR-nk-tOBm9QAFaozJIVt2WYyCMkoz&export=download&confirm=t&uuid=c9bb0ec9-3858-47a5-8cc1-979145b9d866&at=AENtkXaWSisZ7HO9EqxoIdY_38tX%3A1730526571780
#https://drive.usercontent.google.com/download?id=1_qu7GTFzIm9GpUtzSmn8F8SOn3fqaOOu&export=download&confirm=t&uuid=&at=AENtkXaWSisZ7HO9EqxoIdY_38tX%3A1730526571780

View File

@@ -172,6 +172,9 @@ GET http://127.0.0.1:6400/json/parser?url=https://iwx.mail.qq.com/ftn/download?f
###
GET http://127.0.0.1:6400/v2/statisticsInfo
###
GET http://127.0.0.1:6400/v2/getPanList
###
GET http://127.0.0.1:6400/v2/linkInfo?url=https://www.123865.com/s/iaKtVv-6OECd.html&pwd=DcGe
###
@@ -198,7 +201,7 @@ GET http://127.0.0.1:6401/json/parser?url=https://iwx.mail.qq.com/ftn/download?f
### PASS CT
# @no-redirect
GET http://127.0.0.1:6401/parser?url=https://474b.com/file/4015376-131945810
GET http://127.0.0.1:6401/parser?url=https://123123-asd.474b.com/file/4015376-131945810
### PASS MNE
@@ -231,7 +234,7 @@ GET http://127.0.0.1:6401/parser?url=https://www.kugou.com/mixsong/9q98o5b9.html
### PASS MQW 酷我
# @no-redirect
GET http://127.0.0.1:6401/parser?url=https://kuwo.cn/play_detail/395500809
GET http://127.0.0.1:6401/parser?url=https://kuwo.cn/play_detail/394906263

View File

@@ -12,4 +12,4 @@
<p> -- vert.x反向代理服务器(version 4.1.2)</p>
</div>
</body>
</html>
</html>