// ==UserScript==
// @name 百度网盘链接补全工具
// @namespace http://tampermonkey.net/
// @description 智能识别并补全百度网盘链接,支持选中文本提示和自动填写提取码
// @version 2.4.2
// @author deepseek
// @license MIT
// @match https://*/*
// @match http://*/*
// @grant GM_openInTab
// @grant GM_notification
// @grant GM_setValue
// @grant GM_getValue
// @grant GM_addStyle
// @grant GM_registerMenuCommand
// @grant GM_getResourceText
// @grant GM_info
// @require https://unpkg.com/sweetalert2@10.16.6/dist/sweetalert2.min.js
// @resource swalStyle https://unpkg.com/sweetalert2@10.16.6/dist/sweetalert2.min.css
// @run-at document-idle
// @homepageURL https://github.com/your-repo
// @supportURL https://github.com/your-repo/issues
// @icon data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxMjggMTI4Ij48cGF0aCBkPSJNMTAzLjYgMTA3LjRjMy41LTIuMiA4LjktNi4xIDEzLjgtMTIuNXM3LjMtMTIuNSA4LjUtMTYuNWMuNS0xLjcgMi4yLTcuNSAyLjItMTQuNyAwLTEwLjEtMy4zLTI1LjEtMTUuNC0zNi44LTE0LjUtMTQtMzIuMS0xNC4zLTM1LjctMTQuMy04IDAtMTUuNyAxLjktMjIuNiA1LjJDNDQgMjMgMzUuNyAzMS40IDMwLjggNDEuN2MtMS4zIDIuOC00IDQuNy03LjEgNS00IC4zLTcuNSA0LjQtOC45IDkuNi0uNSAxLjktMS42IDMuNS0zLjEgNC43QzQuNCA2Ni44IDAgNzUuNyAwIDg1YzAgNi44IDIuMyAxMy4xIDYuMSAxOC4yIDUuNSA3LjQgMTQuMiAxMi4yIDI0IDEyLjJoNDcuMWM0LjQgMCAxMS0uNSAxOC4zLTMuNSAzLjItMS40IDUuOS0zIDguMS00LjV6IiBmaWxsPSIjNDQ0Ii8+PHBhdGggZD0iTTExOS44IDY0LjNjLjEtMTcuMS0xMC40LTI4LTEyLjUtMzAuMUM5NSAyMi4xIDc5LjkgMjEuOCA3Ni45IDIxLjhjLTE3LjYgMC0zMy4zIDEwLjUtMzkuOSAyNi43LS42IDEuMy0xLjggMi4zLTMuNCAyLjNoLS40Yy01LjggMC0xMC42IDQuOC0xMC42IDEwLjd2LjVjMCAxLjQtLjggMi42LTEuOSAzLjNDMTMuNCA2OSA4LjggNzYuOCA4LjggODVjMCAxMi4yIDkuOSAyMi4zIDIyLjIgMjIuM2g0NS4yYzMuNi0uMSAxNy42LS45IDI5LjYtMTIgMi45LTIuOCAxMy45LTEzLjcgMTQtMzF6IiBmaWxsPSIjZGI4NDEyIi8+PHBhdGggZD0iTTExMC44IDU3LjRsLjIgMy4zYzAgMS4zLTEuMSAyLjQtMi4zIDIuNC0xLjMgMC0yLjMtMS4xLTIuMy0yLjRsLS4xLTIuOHYtLjNjMC0xLjIuOS0yLjIgMi4xLTIuM2guM2MuNyAwIDEuMy4zIDEuNy43LS4yLjEuMy41LjQgMS40em0tMy4zLTEwLjNjMCAxLjItMSAyLjMtMi4yIDIuM2gtLjFjLS44IDAtMS42LS41LTItMS4yLTQuNi04LjMtMTMuMy0xMy41LTIyLjgtMTMuNS0xLjIgMC0yLjMtMS0yLjMtMi4ydi0uMWMwLTEuMiAxLTIuMyAyLjItMi4zaC4xYTMwLjM3IDMwLjM3IDAgMCAxIDE1LjggNC40YzQuNiAyLjggOC40IDYuOCAxMS4xIDExLjUuMS4zLjIuNy4yIDEuMXpNNjkuMiA0OWwxOS40IDE0LjhjMS45IDEuNSAzLjEgMy41IDMuNSA1Ljd2LjJjLjEuNC4xLjguMSAxLjIgMCAuNi0uMSAxLjEtLjIgMS42LS40IDIuMi0xLjcgNC4yLTMuNSA1LjZMNjkuMyA5M2MtMi42IDItNS40IDIuNS03LjcgMS40LS4xLS4xLS4yLS4xLS4yLS4yLTItMS4yLTMuMi0zLjUtMy4yLTYuNHYtNi42aC01LjdjLTYuOCAwLTEyLTQuNy0xMi0xMC45IDAtNC44IDIuNi04LjUgNy4yLTEwLjMgMS4zLS41IDIuNy4yIDMuMiAxLjVzLS4xIDIuOC0xLjQgMy4zYy0yLjcgMS4xLTQgMi45LTQgNS41IDAgMy41IDMgNiA3IDZoOC4xYzEuNSAwIDIuNyAxLjIgMi43IDIuNyAwIDEuNS0xLjIgMi43LTIuNyAyLjdoLTUuMWMtMS41IDAtMi43IDEuMi0yLjcgMi43czEuMiAyLjcgMi43IDIuN2g4LjFjLjUgMCAxIC4yIDEuNC42LjcuNiAxLjEgMS43IDEuMSAyLjZ2OC40YzAgMS4zLjQgMiAuNyAyLjEuNC4yIDEuMyAwIDIuNC0uOWwxOS4yLTE0LjljMS4yLS45IDEuOC0yLjEgMS44LTMuM3MtLjYtMi4zLTEuNy0zLjFMNjYuMiA1M2MtMS4xLS45LTItMS4xLTIuNC0uOS0uMy4yLS43LjktLjcgMi4xdjcuNmMwIC45LS41IDEuNy0xLjIgMi4xLS40LjMtLjguNC0xLjMuNC0xLjQgMC0yLjUtMS4xLTIuNS0yLjV2LTcuNmMwLTMuMSAxLjMtNS41IDMuNS02LjZsLjctLjNjMi4xLS43IDQuNi0uMSA2LjkgMS43eiIgZmlsbD0iIzQ0NCIvPjwvc3ZnPg==
// @downloadURL https://update.greasyfork.icu/scripts/552532/%E7%99%BE%E5%BA%A6%E7%BD%91%E7%9B%98%E9%93%BE%E6%8E%A5%E8%A1%A5%E5%85%A8%E5%B7%A5%E5%85%B7.user.js
// @updateURL https://update.greasyfork.icu/scripts/552532/%E7%99%BE%E5%BA%A6%E7%BD%91%E7%9B%98%E9%93%BE%E6%8E%A5%E8%A1%A5%E5%85%A8%E5%B7%A5%E5%85%B7.meta.js
// ==/UserScript==
(function () {
'use strict';
// 配置选项
let config = {
debugMode: GM_getValue('debugMode', false),
autoDetect: GM_getValue('autoDetect', true),
rules: {
removeSpaces: GM_getValue('removeSpaces', true),
replaceDian: GM_getValue('replaceDian', true),
removeColon: GM_getValue('removeColon', true),
replaceMa: GM_getValue('replaceMa', true),
removeChinese: GM_getValue('removeChinese', true),
removePrefix: GM_getValue('removePrefix', true),
strictValidation: GM_getValue('strictValidation', true)
},
showResultNotification: GM_getValue('showResultNotification', true),
detectDelay: GM_getValue('detectDelay', 300),
autoSubmit: GM_getValue('autoSubmit', true),
autoClose: GM_getValue('autoClose', true),
autoCloseDelay: GM_getValue('autoCloseDelay', 5000),
activeInFront: GM_getValue('activeInFront', true),
successTimes: GM_getValue('successTimes', 0)
};
// 站点白名单管理
const siteManager = {
getWhitelist() {
try {
return JSON.parse(GM_getValue('siteWhitelist', '[]'));
} catch (e) {
console.error('Failed to parse site whitelist:', e);
return [];
}
},
setWhitelist(list) {
GM_setValue('siteWhitelist', JSON.stringify(list));
},
isCurrentSiteEnabled() {
const whitelist = this.getWhitelist();
const currentDomain = location.hostname;
return whitelist.includes(currentDomain);
},
addCurrentSite() {
const whitelist = this.getWhitelist();
const currentDomain = location.hostname;
if (!whitelist.includes(currentDomain)) {
whitelist.push(currentDomain);
this.setWhitelist(whitelist);
}
return currentDomain;
},
removeCurrentSite() {
const whitelist = this.getWhitelist();
const currentDomain = location.hostname;
const newWhitelist = whitelist.filter(domain => domain !== currentDomain);
this.setWhitelist(newWhitelist);
return currentDomain;
},
removeDomain(domain) {
const whitelist = this.getWhitelist();
const newWhitelist = whitelist.filter(d => d !== domain);
this.setWhitelist(newWhitelist);
return domain;
}
};
// 百度网盘配置
const baiduConfig = {
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',
// 新增:分享码验证规则
shareCodePattern: /^1[a-zA-Z0-9_-]{11,31}$/,
minLength: 12,
maxLength: 32
};
const customClass = {
container: 'bdpan-container',
popup: 'bdpan-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 lastSelectedText = "";
let currentDetectedLink = null;
let currentPassword = null;
// 工具函数
const util = {
log(message) {
if (config.debugMode) {
console.log(`%c[百度网盘链接补全工具]`, `background:url(${GM_info.script.icon}) center center no-repeat;background-size:12px;padding:3px`, message);
}
},
getValue(name) {
return GM_getValue(name);
},
setValue(name, value) {
GM_setValue(name, value);
},
sleep(time) {
return new Promise((resolve) => setTimeout(resolve, time));
},
isHidden(el) {
try {
return el.offsetParent === null;
} catch (e) {
return false;
}
},
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);
},
showNotification(title, text, icon = 'info') {
if (config.showResultNotification) {
Swal.fire({
toast: true,
position: 'top',
title: title,
text: text,
icon: icon,
timer: 3000,
showConfirmButton: false,
customClass: customClass
});
}
},
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);
},
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;
},
copyToClipboard(text) {
return new Promise((resolve, reject) => {
if (navigator.clipboard && window.isSecureContext) {
navigator.clipboard.writeText(text).then(resolve).catch(reject);
} else {
// 降级方案
let textArea = document.createElement("textarea");
textArea.value = text;
textArea.style.position = "fixed";
textArea.style.opacity = "0";
document.body.appendChild(textArea);
textArea.select();
try {
document.execCommand('copy');
resolve();
} catch (err) {
reject(err);
}
document.body.removeChild(textArea);
}
});
},
// 历史记录功能
getHistory() {
try {
return JSON.parse(GM_getValue('manualInputHistory', '[]'));
} catch (e) {
return [];
}
},
addToHistory(text, result) {
const history = this.getHistory();
// 保留最近10条记录
history.unshift({
text: text,
result: result,
timestamp: new Date().toISOString()
});
if (history.length > 10) {
history.pop();
}
GM_setValue('manualInputHistory', JSON.stringify(history));
},
clearHistory() {
GM_setValue('manualInputHistory', '[]');
}
};
// 主功能类
const main = {
// 初始化配置
initConfig() {
const defaultConfig = {
debugMode: false,
autoDetect: true,
rules: {
removeSpaces: true,
replaceDian: true,
removeColon: true,
replaceMa: true,
removeChinese: true,
removePrefix: true,
strictValidation: true
},
showResultNotification: true,
detectDelay: 300,
autoSubmit: true,
autoClose: true,
autoCloseDelay: 5000,
activeInFront: true,
successTimes: 0
};
for (let key in defaultConfig) {
if (util.getValue(key) === undefined) {
if (typeof defaultConfig[key] === 'object') {
for (let subKey in defaultConfig[key]) {
util.setValue(`${key}_${subKey}`, defaultConfig[key][subKey]);
}
} else {
util.setValue(key, defaultConfig[key]);
}
}
}
},
// 注册菜单命令 (仅当脚本在当前站点启用时)
registerMenuCommands() {
GM_registerMenuCommand('👀 已识别:' + config.successTimes + '次', () => {
this.clearIdentifyTimes();
});
GM_registerMenuCommand('📋 手动识别', () => {
this.showManualInput();
});
GM_registerMenuCommand('⚙️ 设置', () => {
this.showSettings();
});
GM_registerMenuCommand('📋 管理已启用网站', () => {
this.showSiteManagement();
});
GM_registerMenuCommand('❌ 在此网站禁用', () => {
this.disableOnCurrentSite();
});
GM_registerMenuCommand('🔄 重置配置', () => {
this.resetSettings();
});
},
// 注册最小菜单命令 (当脚本在当前站点未启用时)
registerMinimalMenuCommands() {
GM_registerMenuCommand(`✅ 在 ${location.hostname} 启用`, () => {
this.enableOnCurrentSite();
});
GM_registerMenuCommand('📋 管理已启用网站', () => {
this.showSiteManagement();
});
},
// 在当前站点启用脚本
enableOnCurrentSite() {
const domain = siteManager.addCurrentSite();
Swal.fire({
title: '已启用',
html: `已在 ${domain} 启用脚本。
页面即将刷新以应用更改。`,
icon: 'success',
timer: 2000,
showConfirmButton: false,
customClass: customClass
}).then(() => {
window.location.reload();
});
},
// 在当前站点禁用脚本
disableOnCurrentSite() {
Swal.fire({
title: '确认禁用',
html: `确定要在 ${location.hostname} 禁用脚本吗?`,
icon: 'warning',
showCancelButton: true,
confirmButtonText: '确定',
cancelButtonText: '取消',
customClass: customClass
}).then((result) => {
if (result.isConfirmed) {
const domain = siteManager.removeCurrentSite();
Swal.fire({
title: '已禁用',
html: `已在 ${domain} 禁用脚本。
页面即将刷新。`,
icon: 'info',
timer: 2000,
showConfirmButton: false,
customClass: customClass
}).then(() => {
window.location.reload();
});
}
});
},
// 显示站点管理界面
showSiteManagement() {
const whitelist = siteManager.getWhitelist();
let html = '
暂无已启用的网站
'; } else { html += '未能从输入文本中识别出有效的百度网盘链接或分享码。
${inputText}
请检查输入内容是否符合支持的格式。
提示: 百度网盘分享码通常以数字"1"开头,长度为12-32位字符