Greasy Fork is available in English.
支持夸克、百度、阿里云盘。搭载【无感网络劫持引擎】,精准截获阿里 CDN 真实直链并强行唤起提取面板,彻底粉碎封锁。
当前为
// ==UserScript==
// @name 威软全能网盘增强助手
// @namespace Weiruan-Pan-Helper
// @version 3.3.0
// @description 支持夸克、百度、阿里云盘。搭载【无感网络劫持引擎】,精准截获阿里 CDN 真实直链并强行唤起提取面板,彻底粉碎封锁。
// @author 威软科技
// @license MIT
// @icon https://pan.quark.cn/favicon.ico
// @match *://pan.quark.cn/*
// @match *://pan.baidu.com/*
// @match *://yun.baidu.com/*
// @match *://*.aliyundrive.com/*
// @match *://*.alipan.com/*
// @grant GM_xmlhttpRequest
// @grant GM_setClipboard
// @grant GM_setValue
// @grant GM_getValue
// @grant GM_addStyle
// @grant unsafeWindow
// @run-at document-start
// @connect drive.quark.cn
// @connect pan.baidu.com
// @connect api.aliyundrive.com
// @homepage https://github.com/weiruankeji2025/weiruan-quark
// ==/UserScript==
(function() {
'use strict';
const CONFIG = {
VERSION: "3.3.0",
DEBUG: true,
HISTORY_MAX: 100,
UA_QUARK: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) quark-cloud-drive/2.5.20 Chrome/100.0.4896.160",
UA_BAIDU: "netdisk;7.0.3.2;PC;PC-Windows;10.0.19045",
UA_ALIYUN: "AliApp(Yundrive/4.0.0)",
};
const State = {
lang: GM_getValue('weiruan_lang', 'zh'),
theme: GM_getValue('weiruan_theme', 'auto'),
history: GM_getValue('weiruan_history', []),
fileMemoryMap: new Map(), // 存储全页面的文件信息字典
getLang() { return {
title: '威软全能网盘助手', downloadHelper: '下载助手', processing: '处理中...', success: '解析成功',
error: '错误', noFiles: '请先勾选需要下载的文件', networkError: '网络请求失败,请检查网络',
copied: '已复制', copyAll: '复制全部', copyAria2: '导出 aria2', copyCurl: '导出 cURL',
totalSize: '总大小', history: '历史记录', clearHistory: '清空历史', settings: '设置',
darkMode: '深色模式', language: '语言', all: '全部', files: '个文件', noHistory: '暂无下载历史',
auto: '跟随系统', light: '浅色', dark: '深色'
}; },
setLang(lang) { this.lang = lang; GM_setValue('weiruan_lang', lang); },
setTheme(theme) { this.theme = theme; GM_setValue('weiruan_theme', theme); if(document.body) UI.applyTheme(); },
isDark() { return this.theme === 'auto' ? window.matchMedia('(prefers-color-scheme: dark)').matches : this.theme === 'dark'; },
addHistory(files) {
const newHistory = files.map(f => ({ name: f.file_name, size: f.size, time: Date.now() }));
this.history = [...newHistory, ...this.history].slice(0, CONFIG.HISTORY_MAX);
GM_setValue('weiruan_history', this.history);
},
clearHistory() { this.history = []; GM_setValue('weiruan_history', []); }
};
const Utils = {
log: (...args) => { if (CONFIG.DEBUG) console.log('[威软全能助手]', ...args); },
formatSize: (bytes) => { if (!bytes) return '0 B'; const k = 1024, i = Math.floor(Math.log(bytes) / Math.log(k)); return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + ['B', 'KB', 'MB', 'GB', 'TB'][i]; },
getFileType: (fn) => { if(!fn) return 'other'; const ext = fn.split('.').pop().toLowerCase(); const t = { video: ['mp4', 'mkv', 'avi', 'mov', 'wmv', 'flv', 'rmvb', 'm4v'], audio: ['mp3', 'wav', 'flac', 'aac', 'ogg', 'wma', 'm4a'], image: ['jpg', 'jpeg', 'png', 'gif', 'bmp', 'webp', 'svg', 'ico'], document: ['pdf', 'doc', 'docx', 'xls', 'xlsx', 'ppt', 'pptx', 'txt', 'md'], archive: ['zip', 'rar', '7z', 'tar', 'gz', 'bz2'] }; for (const [type, exts] of Object.entries(t)) if (exts.includes(ext)) return type; return 'other'; },
getFileIcon: (fn) => ({ video: '🎬', audio: '🎵', image: '🖼️', document: '📄', archive: '📦', other: '📁' }[Utils.getFileType(fn)] || '📁'),
generateBatchLinks: (files) => files.map(f => f.download_url).join('\n'),
generateAria2Commands: (files, ua) => files.map(f => `${f.folderPath ? `mkdir -p "${f.folderPath}" && ` : ''}aria2c -c -x 16 -s 16 "${f.download_url}" -o "${f.fullPath || f.file_name}" -U "${ua}" --header="Cookie: ${document.cookie}"`).join('\n\n'),
generateCurlCommands: (files, ua) => files.map(f => `${f.folderPath ? `mkdir -p "${f.folderPath}" && ` : ''}curl -L -C - "${f.download_url}" -o "${f.fullPath || f.file_name}" -A "${ua}" -b "${document.cookie}"`).join('\n\n'),
toast: (msg, type = 'success') => {
if (!document.body) return;
document.querySelector('.weiruan-toast')?.remove();
const div = document.createElement('div'); div.className = 'weiruan-toast'; div.innerText = msg;
const colors = { success: 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)', error: 'linear-gradient(135deg, #ff6b6b 0%, #ee5a5a 100%)', info: 'linear-gradient(135deg, #4facfe 0%, #00f2fe 100%)', warning: 'linear-gradient(135deg, #f6d365 0%, #fda085 100%)' };
div.style.cssText = `position: fixed; top: 80px; left: 50%; transform: translateX(-50%); background: ${colors[type] || colors.success}; color: ${type==='warning'?'#333':'white'}; padding: 12px 24px; border-radius: 8px; z-index: 2147483649; font-size: 14px; box-shadow: 0 4px 20px rgba(0,0,0,0.25); animation: weiruan-toast-in 0.3s ease-out; font-family: -apple-system, BlinkMacSystemFont, sans-serif; white-space: pre-line; line-height: 1.5;`;
document.body.appendChild(div);
setTimeout(() => { div.style.animation = 'weiruan-toast-out 0.3s ease-out forwards'; setTimeout(() => div.remove(), 300); }, 4500);
},
// 更新内存字典的公用方法
updateMemoryMap: () => {
const findFilesInFiber = (obj, visited = new Set(), depth = 0) => {
if (!obj || typeof obj !== 'object' || depth > 15) return;
if (visited.has(obj)) return;
visited.add(obj);
if (obj.file_id && obj.name && typeof obj.file_id === 'string' && obj.file_id.length > 5) {
State.fileMemoryMap.set(obj.file_id, obj); // 以 file_id 为 key,方便劫持时快速反查
}
for (let key in obj) {
if (key === 'return' || key === 'child' || key === 'sibling' || key.startsWith('__') || obj[key] instanceof Node) continue;
try { findFilesInFiber(obj[key], visited, depth + 1); } catch(e) {}
}
};
if(document.body) {
document.querySelectorAll('#root, #app, [class*="layout"], [class*="container"], [class*="body"]').forEach(el => {
const key = Object.keys(el).find(k => k.startsWith('__reactFiber$') || k.startsWith('__reactInternalInstance$'));
if (key) findFilesInFiber(el[key]);
});
}
}
};
// ==================== 🕸️ 时空级底层网络劫持 ====================
const NetworkHook = {
init() {
const win = unsafeWindow || window;
if (win._weiruan_hooked) return;
win._weiruan_hooked = true;
Utils.log('🕸️ 威软拦截网已布署!正在监控底层发出的 get_download_url 请求');
// 劫持批量下载、单个下载等关键接口
const hookUrls = ['get_download_url', 'downloadUrl', 'batch'];
const origFetch = win.fetch;
win.fetch = async function(...args) {
const reqUrl = typeof args[0] === 'string' ? args[0] : (args[0]?.url || '');
const response = await origFetch.apply(this, args);
if (hookUrls.some(u => reqUrl.includes(u))) {
try {
const clone = response.clone();
clone.json().then(data => {
NetworkHook.handleInterceptedData(args[1]?.body, data);
}).catch(()=>{});
} catch(e) {}
}
return response;
};
const origXhrSend = win.XMLHttpRequest.prototype.send;
win.XMLHttpRequest.prototype.send = function(body) {
this._weiruanBody = body;
this.addEventListener('load', function() {
if (this.responseURL && hookUrls.some(u => this.responseURL.includes(u))) {
try {
const data = JSON.parse(this.responseText);
NetworkHook.handleInterceptedData(this._weiruanBody, data);
} catch(e) {}
}
});
return origXhrSend.call(this, body);
};
},
// 处理劫持到的响应体
handleInterceptedData(requestBodyStr, responseData) {
Utils.updateMemoryMap(); // 确保有最新的内存字典
let capturedFiles = [];
// 提取请求中的 file_id (处理各种嵌套和 batch 批量请求的情况)
let requestedFids = [];
try {
if (requestBodyStr && typeof requestBodyStr === 'string') {
const reqObj = JSON.parse(requestBodyStr);
if (reqObj.file_id) requestedFids.push(reqObj.file_id);
if (reqObj.requests) {
reqObj.requests.forEach(req => {
if (req.body && req.body.file_id) requestedFids.push(req.body.file_id);
});
}
}
} catch(e) {}
// 解析阿里返回的数据结构 (单文件 or batch 批量数组)
if (responseData.url && requestedFids.length > 0) {
// 单文件直链
const fid = requestedFids[0];
const memInfo = State.fileMemoryMap.get(fid);
capturedFiles.push({
fid: fid,
file_name: memInfo ? memInfo.name : `已劫持文件_${fid.substring(0,6)}.mp4`,
size: memInfo ? memInfo.size : 0,
download_url: responseData.url,
folderPath: '', fullPath: ''
});
} else if (responseData.responses && Array.isArray(responseData.responses)) {
// 批量直链
responseData.responses.forEach(res => {
if (res.body && res.body.url) {
// 尝试从请求体反推对应的 fid (阿里 batch 接口的 responses 通常和 requests 顺序一致,这里用 body 返回的 file_id 最准,如果没有就按顺序拿)
const fid = res.body.file_id || (requestedFids.length > 0 ? requestedFids.shift() : 'unknown');
const memInfo = State.fileMemoryMap.get(fid);
capturedFiles.push({
fid: fid,
file_name: memInfo ? memInfo.name : `已劫持文件_${fid.substring(0,6)}.mp4`,
size: memInfo ? memInfo.size : 0,
download_url: res.body.url,
folderPath: '', fullPath: ''
});
}
});
}
// 只要抓到了真实直链,不管三七二十一,直接弹出威软面板!
if (capturedFiles.length > 0 && document.body) {
Utils.log('🎯 [无感劫持成功] 强行挂载提取面板!', capturedFiles);
Utils.toast('🎉 威软引擎拦截成功!强制提取满速直链!', 'success');
State.addHistory(capturedFiles);
UI.showResultWindow(capturedFiles);
}
}
};
NetworkHook.init(); // 起手就埋下天罗地网
// ==================== 界面 UI ====================
const UI = {
injectStyles: () => {
GM_addStyle(`
@keyframes weiruan-toast-in { from { opacity: 0; transform: translate(-50%, -20px); } to { opacity: 1; transform: translate(-50%, 0); } }
@keyframes weiruan-toast-out { from { opacity: 1; transform: translate(-50%, 0); } to { opacity: 0; transform: translate(-50%, -20px); } }
@keyframes weiruan-spin { to { transform: rotate(360deg); } }
@keyframes weiruan-slide-in { from { opacity: 0; transform: scale(0.9); } to { opacity: 1; transform: scale(1); } }
.weiruan-spinner { display: inline-block; width: 14px; height: 14px; border: 2px solid rgba(255,255,255,0.3); border-top-color: white; border-radius: 50%; animation: weiruan-spin 0.8s linear infinite; margin-right: 6px; vertical-align: middle; }
.weiruan-btn { position: fixed; top: 50%; left: 0; transform: translateY(-50%); z-index: 2147483647; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; font-size: 14px; font-weight: 600; padding: 14px 18px; border: none; border-radius: 0 25px 25px 0; cursor: pointer; box-shadow: 0 4px 15px rgba(102, 126, 234, 0.4); transition: all 0.3s ease; display: flex; align-items: center; gap: 6px; }
.weiruan-btn:hover { padding-left: 22px; box-shadow: 0 6px 25px rgba(102, 126, 234, 0.5); }
.weiruan-btn:disabled { opacity: 0.7; cursor: not-allowed; }
.weiruan-icon { font-size: 16px; }
.weiruan-menu { position: fixed; top: calc(50% + 50px); left: 0; transform: translateY(-50%); z-index: 2147483646; display: flex; flex-direction: column; gap: 5px; opacity: 0; pointer-events: none; transition: all 0.3s ease; }
.weiruan-btn:hover + .weiruan-menu, .weiruan-menu:hover { opacity: 1; pointer-events: auto; left: 5px; }
.weiruan-menu-item { background: rgba(255,255,255,0.95); color: #333; padding: 8px 14px; border-radius: 20px; font-size: 12px; cursor: pointer; box-shadow: 0 2px 10px rgba(0,0,0,0.1); transition: all 0.2s; white-space: nowrap; }
.weiruan-menu-item:hover { background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; transform: translateX(5px); }
/* Modal Styles */
.weiruan-modal-overlay { position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0, 0, 0, 0.6); z-index: 2147483648; display: flex; align-items: center; justify-content: center; backdrop-filter: blur(5px); }
.weiruan-modal { background: var(--weiruan-bg, #ffffff); width: 720px; max-width: 92%; max-height: 85vh; border-radius: 16px; box-shadow: 0 25px 50px rgba(0, 0, 0, 0.3); display: flex; flex-direction: column; overflow: hidden; animation: weiruan-slide-in 0.3s ease-out; font-family: -apple-system, BlinkMacSystemFont, sans-serif; }
.weiruan-tab-content { display: none; flex-direction: column; min-height: 0; flex: 1; overflow: hidden; }
.weiruan-tab-content.active { display: flex; }
.weiruan-modal-header { padding: 18px 24px; border-bottom: 1px solid var(--weiruan-border, #eee); display: flex; justify-content: space-between; align-items: center; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; }
.weiruan-modal-title { margin: 0; font-size: 18px; font-weight: 600; display: flex; align-items: center; gap: 8px; }
.weiruan-modal-close { cursor: pointer; font-size: 28px; line-height: 1; opacity: 0.8; transition: opacity 0.2s; width: 32px; height: 32px; display: flex; align-items: center; justify-content: center; border-radius: 50%; background: rgba(255,255,255,0.1); }
.weiruan-modal-close:hover { opacity: 1; background: rgba(255,255,255,0.2); }
.weiruan-toolbar { padding: 12px 24px; background: var(--weiruan-toolbar-bg, #f8f9ff); border-bottom: 1px solid var(--weiruan-border, #eee); display: flex; justify-content: space-between; align-items: center; flex-wrap: wrap; gap: 10px; }
.weiruan-toolbar-info { font-size: 13px; color: var(--weiruan-text-secondary, #666); }
.weiruan-btn-group { display: flex; gap: 6px; }
.weiruan-action-btn { padding: 8px 16px; border: none; border-radius: 6px; cursor: pointer; font-size: 13px; font-weight: 500; transition: all 0.2s; display: flex; align-items: center; gap: 4px; }
.weiruan-action-btn.primary { background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; }
.weiruan-action-btn.success { background: linear-gradient(135deg, #56ab2f 0%, #a8e063 100%); color: white; }
.weiruan-modal-body { padding: 16px 24px; overflow-y: auto; flex: 1; min-height: 0; max-height: 400px; background: var(--weiruan-bg, #ffffff); }
.weiruan-file-item { background: var(--weiruan-item-bg, #f9f9f9); padding: 14px 16px; margin-bottom: 10px; border-radius: 10px; border-left: 4px solid #667eea; display: flex; justify-content: space-between; align-items: center; transition: all 0.2s; }
.weiruan-file-info { overflow: hidden; flex: 1; margin-right: 12px; }
.weiruan-file-name { font-weight: 600; color: var(--weiruan-text, #333); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; display: flex; align-items: center; gap: 6px; font-size: 14px; }
.weiruan-file-meta { font-size: 12px; color: var(--weiruan-text-secondary, #888); margin-top: 4px; }
.weiruan-file-actions { display: flex; gap: 6px; flex-shrink: 0; }
.weiruan-file-btn { padding: 6px 12px; border: none; border-radius: 5px; cursor: pointer; font-size: 12px; font-weight: 500; transition: all 0.2s; text-decoration: none; display: inline-flex; align-items: center; gap: 3px; background: #333; color: white; }
.weiruan-file-btn:hover { transform: scale(1.05); }
.weiruan-file-btn.idm { background: linear-gradient(135deg, #56ab2f 0%, #a8e063 100%); }
.weiruan-file-btn.aria2 { background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%); }
.weiruan-tabs { display: flex; border-bottom: 1px solid var(--weiruan-border, #eee); padding: 0 24px; background: var(--weiruan-bg, #ffffff); }
.weiruan-tab { padding: 12px 20px; cursor: pointer; border: none; background: none; font-size: 14px; font-weight: 500; color: var(--weiruan-text-secondary, #666); position: relative; }
.weiruan-tab.active { color: #667eea; }
.weiruan-tab.active::after { content: ''; position: absolute; bottom: -1px; left: 0; right: 0; height: 2px; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); }
.weiruan-footer { padding: 12px 24px; border-top: 1px solid var(--weiruan-border, #eee); background: var(--weiruan-bg, #ffffff); text-align: center; font-size: 12px; color: var(--weiruan-text-secondary, #999); }
.weiruan-dark { --weiruan-bg: #1a1a2e; --weiruan-text: #e0e0e0; --weiruan-text-secondary: #888; --weiruan-border: #333; --weiruan-item-bg: #252540; --weiruan-toolbar-bg: #1e1e35; }
`);
},
applyTheme: () => {
const modal = document.getElementById('weiruan-modal');
if (modal) State.isDark() ? modal.classList.add('weiruan-dark') : modal.classList.remove('weiruan-dark');
},
createFloatButton: () => {
if (document.getElementById('weiruan-btn')) return;
const btn = document.createElement('button');
btn.id = 'weiruan-btn'; btn.className = 'weiruan-btn';
btn.innerHTML = `<span class="weiruan-icon">⚡</span> 下载助手`;
btn.onclick = () => {
Utils.toast(`🛡️ 由于阿里动态防盗链机制!\n\n请直接去勾选文件,然后点击页面上阿里云盘官方自带的【下载】按钮,\n助手会在底层为您瞬间截获满速直链!`, 'warning');
};
document.body.appendChild(btn);
const menu = document.createElement('div');
menu.className = 'weiruan-menu';
menu.innerHTML = `<div class="weiruan-menu-item" data-action="starmap">🌌 星际历史图</div>`;
menu.addEventListener('click', (e) => {
if (e.target.getAttribute('data-action') === 'starmap') Utils.toast('星际历史图功能已就绪', 'info');
});
document.body.appendChild(menu);
},
showResultWindow: (data) => {
const L = State.getLang();
document.getElementById('weiruan-modal')?.remove();
const totalSize = data.reduce((sum, f) => sum + f.size, 0);
const modal = document.createElement('div');
modal.id = 'weiruan-modal';
modal.className = `weiruan-modal-overlay ${State.isDark() ? 'weiruan-dark' : ''}`;
const activeUA = CONFIG.UA_ALIYUN;
const batchLinks = Utils.generateBatchLinks(data);
const aria2Commands = Utils.generateAria2Commands(data, activeUA);
const fileListHTML = data.map((f, index) => `
<div class="weiruan-file-item">
<div class="weiruan-file-info">
<div class="weiruan-file-name" title="${f.file_name}"><span>${Utils.getFileIcon(f.file_name)}</span><span>${f.file_name}</span></div>
<div class="weiruan-file-meta">${Utils.formatSize(f.size)} | 核心 ID: ${f.fid.substring(0, 8)}...</div>
</div>
<div class="weiruan-file-actions">
<a href="${f.download_url.replace(/"/g, '"')}" target="_blank" class="weiruan-file-btn idm">⬇️ IDM / 浏览器</a>
<button class="weiruan-file-btn curl weiruan-copy-curl" data-index="${index}">📋 cURL</button>
<button class="weiruan-file-btn aria2 weiruan-copy-aria2" data-index="${index}">🚀 aria2</button>
</div>
</div>`).join('');
modal.innerHTML = `
<div class="weiruan-modal">
<div class="weiruan-modal-header">
<h3 class="weiruan-modal-title"><span>🎉</span><span>拦截提取成功!(共 ${data.length} 个) - 阿里云盘</span></h3>
<span class="weiruan-modal-close" id="weiruan-modal-close">×</span>
</div>
<div class="weiruan-tabs"><button class="weiruan-tab active">📁 截获的文件</button></div>
<div class="weiruan-tab-content active">
<div class="weiruan-toolbar">
<div class="weiruan-toolbar-info"><span>${L.totalSize}: <strong>${Utils.formatSize(totalSize)}</strong></span></div>
<div class="weiruan-btn-group">
<button class="weiruan-action-btn primary" id="weiruan-copy-all-btn">📦 复制全部直链</button>
<button class="weiruan-action-btn success" id="weiruan-copy-aria2-btn">🚀 批量 aria2 命令</button>
</div>
</div>
<div class="weiruan-modal-body">${fileListHTML}</div>
</div>
<div class="weiruan-footer">${L.title} v${CONFIG.VERSION} · 威软科技出品</div>
</div>`;
document.body.appendChild(modal);
document.getElementById('weiruan-modal-close').addEventListener('click', () => modal.remove());
modal.addEventListener('click', (e) => { if (e.target === modal) modal.remove(); });
document.getElementById('weiruan-copy-all-btn').addEventListener('click', () => {
GM_setClipboard(batchLinks); Utils.toast('✅ 全部链接已复制');
});
document.getElementById('weiruan-copy-aria2-btn').addEventListener('click', () => {
GM_setClipboard(aria2Commands); Utils.toast('✅ aria2 命令已复制');
});
modal.querySelectorAll('.weiruan-copy-curl').forEach(btn => {
btn.addEventListener('click', (e) => {
const f = data[parseInt(e.target.getAttribute('data-index'))];
GM_setClipboard(`curl -L -C - "${f.download_url}" -o "${f.file_name}" -A "${activeUA}" -b "${document.cookie}"`);
Utils.toast('✅ cURL 命令已复制');
});
});
modal.querySelectorAll('.weiruan-copy-aria2').forEach(btn => {
btn.addEventListener('click', (e) => {
const f = data[parseInt(e.target.getAttribute('data-index'))];
GM_setClipboard(`aria2c -c -x 16 -s 16 "${f.download_url}" -o "${f.file_name}" -U "${activeUA}" --header="Cookie: ${document.cookie}"`);
Utils.toast('✅ aria2 命令已复制');
});
});
}
};
function domReady(fn) {
if (document.readyState === 'complete' || document.readyState === 'interactive') { setTimeout(fn, 1); }
else { document.addEventListener('DOMContentLoaded', fn); }
}
domReady(() => {
UI.injectStyles();
UI.createFloatButton();
UI.applyTheme();
console.log(`[威软全能助手] v${CONFIG.VERSION} 已在 DOM 挂载后启动`);
});
})();