NOTICE: By continued use of this site you understand and agree to the binding Hizmet Şartları and Gizlilik Politikası.
// ==UserScript==
// @name 威软全能网盘增强助手 (Open API 终极直连版)
// @namespace Weiruan-Pan-Helper
// @version 7.2.0
// @description 支持夸克、百度、阿里云盘。修正 AList 最新 API 网关,完美适配 JWT 超长 Token,满速提取直链。
// @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-end
// @connect drive.quark.cn
// @connect pan.baidu.com
// @connect openapi.alipan.com
// @connect api.alistgo.com
// @connect api.nn.ci
// @homepage https://github.com/weiruankeji2025/weiruan-quark
// ==/UserScript==
(function() {
'use strict';
const CONFIG = {
VERSION: "7.2.0",
DEBUG: true,
UA_ALIYUN: "AliApp(Yundrive/4.0.0)",
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",
};
const State = {
fileMemoryMap: new Map(),
aliToken: GM_getValue('weiruan_ali_token', ''),
};
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]; },
getFileIcon: (fn) => {
const ext = (fn || '').split('.').pop().toLowerCase();
if (['mp4', 'mkv', 'avi', 'mov'].includes(ext)) return '🎬';
if (['mp3', 'wav', 'flac'].includes(ext)) return '🎵';
if (['zip', 'rar', '7z'].includes(ext)) return '📦';
return '📄';
},
post: (url, data, customHeaders = {}) => new Promise((resolve, reject) => {
GM_xmlhttpRequest({
method: "POST", url: url,
headers: Object.assign({"Content-Type": "application/json"}, customHeaders),
data: typeof data === 'string' ? data : JSON.stringify(data), responseType: 'json',
onload: res => res.status >= 200 && res.status < 300 ? resolve(res.response) : reject(res),
onerror: reject
});
}),
toast: (msg, type = 'success', duration = 4000) => {
if (!document.body) return;
document.querySelector('.weiruan-toast')?.remove();
const div = document.createElement('div'); div.className = 'weiruan-toast'; div.innerText = msg;
const colors = { success: '#764ba2', error: '#ff4444', info: '#00bbff', warning: '#ffbb00' };
div.style.cssText = `position: fixed; top: 80px; left: 50%; transform: translateX(-50%); background: ${colors[type] || colors.success}; color: ${type==='warning'?'#333':'white'}; padding: 16px 28px; border-radius: 12px; z-index: 2147483649; font-size: 15px; font-weight: bold; box-shadow: 0 10px 30px rgba(0,0,0,0.3); animation: weiruan-toast-in 0.3s ease-out; font-family: -apple-system, sans-serif; white-space: pre-line; text-align: center;`;
document.body.appendChild(div);
setTimeout(() => { div.style.animation = 'weiruan-toast-out 0.3s ease-out forwards'; setTimeout(() => div.remove(), 300); }, duration);
}
};
// ==================== 🔑 Open API 核心授权引擎 ====================
const AliOpenAPI = {
async getAccessToken() {
if (!State.aliToken) return null;
Utils.toast('正在通过 AList 开放网关验证身份...', 'info', 2000);
try {
// 【核心修复】:使用最新可用的 alistgo 网关
const res = await Utils.post('https://api.alistgo.com/alist/ali_open/token', {
grant_type: "refresh_token",
refresh_token: State.aliToken
});
if (res && res.access_token) {
if (res.refresh_token) {
State.aliToken = res.refresh_token;
GM_setValue('weiruan_ali_token', res.refresh_token);
}
return res.access_token;
}
} catch (e) {
Utils.log("Token 刷新失败,请检查是否过期或复制错误", e);
}
return null;
},
async getDownloadUrl(driveId, fileId, accessToken) {
try {
const res = await Utils.post('https://openapi.alipan.com/adrive/v1.0/openFile/getDownloadUrl', {
drive_id: driveId,
file_id: fileId,
expire_sec: 14400 // 4小时有效
}, { "Authorization": "Bearer " + accessToken });
if (res && res.url) return res.url;
} catch (e) {
Utils.log(`获取文件 ${fileId} 直链失败`, e);
}
return null;
}
};
// ==================== 适配器 ====================
const Adapters = {
quark: {
name: "夸克网盘", matches: ['pan.quark.cn'], ua: CONFIG.UA_QUARK,
getSelectedFiles: function() {
const files = new Map();
document.querySelectorAll('.ant-checkbox-wrapper-checked, .ant-checkbox-checked, input[type="checkbox"]:checked').forEach(el => {
if (el.closest('.ant-table-thead')) return;
const row = el.closest('.ant-table-row, .file-list-item, [data-fid]');
const fid = row?.getAttribute('data-fid') || row?.getAttribute('data-file-id');
if (fid) files.set(fid, { fid, name: row.querySelector('.file-name')?.innerText.trim() || '未命名', isDir: false, size: 0, download_url: '' });
});
return Array.from(files.values());
},
processFiles: async f => f
},
baidu: {
name: "百度网盘", matches: ['pan.baidu.com', 'yun.baidu.com'], ua: CONFIG.UA_BAIDU,
getSelectedFiles: function() {
try {
return unsafeWindow.require('system-core:context/context.js').instanceForSystem.list.getSelected().map(item => ({
fid: item.fs_id, name: item.server_filename, isDir: item.isdir === 1, size: item.size, download_url: ''
}));
} catch (e) { return []; }
},
processFiles: async f => f
},
aliyun: {
name: "阿里云盘 (OpenAPI版)", matches: ['aliyundrive.com', 'alipan.com'], ua: CONFIG.UA_ALIYUN,
getSelectedFiles: function() {
const files = new Map();
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.name.trim(), obj);
for (let key in obj) {
if (key === 'return' || key === 'child' || key === 'sibling' || key.startsWith('__')) continue;
try { findFilesInFiber(obj[key], visited, depth + 1); } catch(e) {}
}
};
document.querySelectorAll('#root, #app, [class*="layout"], [class*="container"]').forEach(el => {
const key = Object.keys(el).find(k => k.startsWith('__reactFiber$'));
if (key) findFilesInFiber(el[key]);
});
document.querySelectorAll('input[type="checkbox"]:checked, [aria-checked="true"], [class*="checked"], .icon-checked').forEach(el => {
if (el.closest('thead') || el.closest('[class*="header"]')) return;
let matched = false, currentEl = el;
for (let i = 0; i < 5 && currentEl; i++) {
const titleVal = currentEl.getAttribute('title') || currentEl.getAttribute('data-title');
if (titleVal && State.fileMemoryMap.has(titleVal.trim())) {
const memObj = State.fileMemoryMap.get(titleVal.trim());
files.set(memObj.file_id, { fid: memObj.file_id, drive_id: memObj.drive_id, name: memObj.name, isDir: memObj.type === 'folder', size: memObj.size || 0 });
matched = true; break;
}
currentEl = currentEl.parentElement;
}
if (!matched) {
currentEl = el;
const cleanStr = str => (str || '').replace(/[^a-zA-Z0-9\u4e00-\u9fa5]/g, '');
for (let i = 0; i < 10 && currentEl; i++) {
const cleanRowText = cleanStr(currentEl.textContent);
if (cleanRowText.length > 1) {
for (let [memName, memObj] of Array.from(State.fileMemoryMap.entries()).sort((a,b) => b[0].length - a[0].length)) {
const cName = cleanStr(memName);
if (cName.length > 0 && cleanRowText.includes(cName.substring(0, 5))) {
files.set(memObj.file_id, { fid: memObj.file_id, drive_id: memObj.drive_id, name: memObj.name, isDir: memObj.type === 'folder', size: memObj.size || 0 });
matched = true; break;
}
}
}
if (matched) break; currentEl = currentEl.parentElement;
}
}
});
return Array.from(files.values());
},
processFiles: async function(files) {
const validFiles = files.filter(f => !f.isDir);
if (validFiles.length < files.length) Utils.toast('已过滤文件夹,OpenAPI 仅支持提取文件直链。', 'warning');
if (validFiles.length === 0) return null;
const accessToken = await AliOpenAPI.getAccessToken();
if (!accessToken) {
Utils.toast('⚠️ Token 无效或已过期,请重新配置!', 'error');
UI.showAuthWindow();
return null;
}
Utils.toast(`正在向阿里云盘服务器申请 ${validFiles.length} 个满速直链...`, 'info');
let readyFiles = [];
for (let f of validFiles) {
const url = await AliOpenAPI.getDownloadUrl(f.drive_id, f.fid, accessToken);
if (url) readyFiles.push({ ...f, file_name: f.name, download_url: url });
}
if (readyFiles.length === 0) { Utils.toast('提取失败,Token可能过期,请重新配置。', 'error'); return null; }
return readyFiles;
}
}
};
const DriveManager = {
currentAdapter: null,
init() {
const host = location.host;
for (const key in Adapters) {
if (Adapters[key].matches.some(m => host.includes(m))) {
this.currentAdapter = Adapters[key]; break;
}
}
},
async runExtraction() {
if (!this.currentAdapter) return;
if (this.currentAdapter.name.includes("阿里云盘") && !State.aliToken) {
UI.showAuthWindow();
return;
}
const btn = document.getElementById('weiruan-btn');
try {
if (btn) { btn.innerHTML = `<span class="weiruan-spinner"></span> 处理中`; btn.disabled = true; }
const initialFiles = this.currentAdapter.getSelectedFiles();
if (initialFiles.length === 0) {
Utils.toast('⚠️ 请先在页面上勾选需要下载的文件!', 'error');
return;
}
const resultData = await this.currentAdapter.processFiles(initialFiles);
if (resultData && resultData.length > 0) {
UI.showResultWindow(resultData);
}
} catch (e) {
Utils.log("提取过程出错", e);
} finally {
if (btn) { btn.innerHTML = `<span class="weiruan-icon">⚡</span> 威软提取`; btn.disabled = false; }
}
}
};
// ==================== 界面 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-slide-in { from { opacity: 0; transform: scale(0.9); } to { opacity: 1; transform: scale(1); } }
@keyframes weiruan-spin { to { transform: rotate(360deg); } }
.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 20px; border: none; border-radius: 0 25px 25px 0; cursor: pointer; box-shadow: 0 4px 15px rgba(102, 126, 234, 0.5); transition: all 0.3s ease; }
.weiruan-btn:hover { padding-left: 26px; box-shadow: 0 6px 20px rgba(102, 126, 234, 0.6); }
.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: 10px 16px; border-radius: 20px; font-size: 13px; font-weight: bold; cursor: pointer; box-shadow: 0 2px 10px rgba(0,0,0,0.1); transition: all 0.2s; white-space: nowrap; border: 1px solid #eee; }
.weiruan-menu-item:hover { background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; transform: translateX(5px); }
.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: #fff; width: 720px; max-width: 92%; border-radius: 16px; box-shadow: 0 25px 50px rgba(0,0,0,0.3); display: flex; flex-direction: column; overflow: hidden; font-family: sans-serif; animation: weiruan-slide-in 0.3s ease-out; }
.weiruan-modal-header { padding: 18px 24px; 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; }
.weiruan-modal-close { cursor: pointer; font-size: 28px; line-height: 1; }
.weiruan-toolbar { padding: 12px 24px; background: #f8f9ff; border-bottom: 1px solid #eee; display: flex; justify-content: space-between; align-items: center;}
.weiruan-btn-group { display: flex; gap: 8px; }
.weiruan-action-btn { padding: 8px 16px; border: none; border-radius: 6px; cursor: pointer; font-size: 13px; font-weight: 500; color: white; transition: transform 0.2s;}
.weiruan-action-btn:hover { transform: translateY(-1px); }
.weiruan-action-btn.primary { background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); }
.weiruan-action-btn.success { background: linear-gradient(135deg, #56ab2f 0%, #a8e063 100%); }
.weiruan-modal-body { padding: 16px 24px; overflow-y: auto; max-height: 450px; }
.weiruan-file-item { background: #f9f9f9; padding: 14px 16px; margin-bottom: 10px; border-radius: 10px; border-left: 4px solid #667eea; display: flex; justify-content: space-between; align-items: center; }
.weiruan-file-info { overflow: hidden; flex: 1; margin-right: 12px; }
.weiruan-file-name { font-weight: 600; color: #333; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; font-size: 14px; }
.weiruan-file-meta { font-size: 12px; color: #888; margin-top: 4px; }
.weiruan-file-btn { padding: 6px 12px; border: none; border-radius: 5px; cursor: pointer; font-size: 12px; color: white; text-decoration: none; display: inline-block;}
.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-input { width: 100%; padding: 12px; border: 2px solid #ddd; border-radius: 8px; font-size: 14px; margin: 15px 0; outline: none; transition: border-color 0.2s; box-sizing: border-box; }
.weiruan-input:focus { border-color: #667eea; }
.weiruan-footer { padding: 12px 24px; border-top: 1px solid #eee; text-align: center; font-size: 12px; color: #999; }
`);
},
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 = () => DriveManager.runExtraction();
document.body.appendChild(btn);
const menu = document.createElement('div');
menu.className = 'weiruan-menu';
menu.innerHTML = `<div class="weiruan-menu-item" id="wr-menu-auth">🔑 阿里云盘 OpenAPI 授权</div>`;
document.body.appendChild(menu);
document.getElementById('wr-menu-auth').onclick = () => UI.showAuthWindow();
},
showAuthWindow: () => {
document.getElementById('weiruan-modal')?.remove();
const modal = document.createElement('div');
modal.id = 'weiruan-modal';
modal.className = `weiruan-modal-overlay`;
modal.innerHTML = `
<div class="weiruan-modal" style="width: 500px;">
<div class="weiruan-modal-header">
<h3 class="weiruan-modal-title">🔐 配置阿里云盘 OpenAPI 授权</h3>
<span class="weiruan-modal-close" id="weiruan-modal-close">×</span>
</div>
<div class="weiruan-modal-body">
<div style="background:#fff3cd; color:#856404; padding:12px; border-radius:8px; font-size:13px; margin-bottom:15px; line-height:1.5;">
<b>请按以下步骤完成授权(仅需一次,告别限速):</b><br><br>
1. 点击下方按钮,前往 AList 官方开放平台。<br>
2. 在新页面中使用阿里云盘 APP 扫码。<br>
3. 扫码成功后,复制生成的 <b>Refresh Token(长代码)</b>。<br>
4. 将其完整粘贴到下方输入框,并点击保存。
</div>
<button class="weiruan-action-btn primary" id="wr-goto-auth" style="width: 100%; padding: 12px; font-size: 15px; margin-bottom: 10px;">
👉 1. 点击前往获取 Refresh Token
</button>
<input type="text" class="weiruan-input" id="wr-token-input" placeholder="👉 2. 请将获取到的 Token 粘贴在此处..." value="${State.aliToken}">
<button class="weiruan-action-btn success" id="wr-save-token" style="width: 100%; padding: 12px; font-size: 15px;">
💾 保存 Token 并立即提取
</button>
</div>
</div>`;
document.body.appendChild(modal);
document.getElementById('weiruan-modal-close').addEventListener('click', () => modal.remove());
document.getElementById('wr-goto-auth').addEventListener('click', () => {
window.open('https://alist.nn.ci/tool/aliyundrive/request', '_blank');
});
document.getElementById('wr-save-token').addEventListener('click', () => {
const tokenVal = document.getElementById('wr-token-input').value.trim();
// 放宽验证,只要是长字符串就行
if (tokenVal.length < 50 || !tokenVal.startsWith('ey')) {
Utils.toast('Token 格式不正确!请确保复制了完整的以 ey 开头的超长代码。', 'error');
return;
}
State.aliToken = tokenVal;
GM_setValue('weiruan_ali_token', tokenVal);
Utils.toast('✅ 授权保存成功!正在为您提取直链...', 'success');
modal.remove();
DriveManager.runExtraction();
});
},
showResultWindow: (data) => {
document.getElementById('weiruan-modal')?.remove();
const modal = document.createElement('div');
modal.id = 'weiruan-modal';
modal.className = `weiruan-modal-overlay`;
const fileListHTML = data.map((f, index) => `
<div class="weiruan-file-item">
<div class="weiruan-file-info">
<div class="weiruan-file-name" title="${f.name}"><span>${Utils.getFileIcon(f.file_name)}</span> ${f.file_name}</div>
<div class="weiruan-file-meta">${Utils.formatSize(f.size)} | 官方 OpenAPI 满速通道</div>
</div>
<div style="display:flex; gap:6px;">
<a href="${f.download_url.replace(/"/g, '"')}" target="_blank" class="weiruan-file-btn idm">⬇️ 浏览器 / IDM 下载</a>
<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">🚀 满速直链提取成功!(共 ${data.length} 个)</h3>
<span class="weiruan-modal-close" id="weiruan-modal-close">×</span>
</div>
<div>
<div class="weiruan-toolbar">
<div class="weiruan-toolbar-info">💡 提示:使用 IDM 时若文件名不对,请手动修改后缀名。</div>
<div class="weiruan-btn-group">
<button class="weiruan-action-btn primary" id="weiruan-copy-all-btn">📦 复制全部直链 URL</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">威软科技 出品 · 彻底击碎网盘限速</div>
</div>`;
document.body.appendChild(modal);
document.getElementById('weiruan-modal-close').addEventListener('click', () => modal.remove());
const activeUA = CONFIG.UA_ALIYUN;
const getLinks = () => data.map(f => f.download_url).join('\n');
const getAria2 = () => data.map(f => `aria2c -c -x 16 -s 16 "${f.download_url}" -o "${f.file_name}" -U "${activeUA}" --header="Cookie: ${document.cookie}"`).join('\n\n');
document.getElementById('weiruan-copy-all-btn').addEventListener('click', () => { GM_setClipboard(getLinks()); Utils.toast('✅ 全部链接已复制'); });
document.getElementById('weiruan-copy-aria2-btn').addEventListener('click', () => { GM_setClipboard(getAria2()); Utils.toast('✅ aria2 命令已复制'); });
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(() => {
// 阻止官方下载按钮事件绑定
document.body.addEventListener('click', (e) => {
const t = e.target;
if ((t.innerText || t.textContent || '').includes('下载') && !t.closest('#weiruan-btn') && !t.closest('#weiruan-modal')) {
if (location.host.includes('aliyundrive.com') || location.host.includes('alipan.com')) {
Utils.toast('🛑 要使用满速提取,请点击左侧紫色的\n【⚡ 威软提取】悬浮按钮!', 'warning', 4000);
}
}
}, true);
UI.injectStyles();
UI.createFloatButton();
DriveManager.init();
console.log(`[威软全能助手] v${CONFIG.VERSION} 网关修正版已启动`);
});
})();