// ==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 // @downloadURL https://update.greasyfork.icu/scripts/575138/%E5%A8%81%E8%BD%AF%E5%85%A8%E8%83%BD%E7%BD%91%E7%9B%98%E5%A2%9E%E5%BC%BA%E5%8A%A9%E6%89%8B%20%28Open%20API%20%E7%BB%88%E6%9E%81%E7%9B%B4%E8%BF%9E%E7%89%88%29.user.js // @updateURL https://update.greasyfork.icu/scripts/575138/%E5%A8%81%E8%BD%AF%E5%85%A8%E8%83%BD%E7%BD%91%E7%9B%98%E5%A2%9E%E5%BC%BA%E5%8A%A9%E6%89%8B%20%28Open%20API%20%E7%BB%88%E6%9E%81%E7%9B%B4%E8%BF%9E%E7%89%88%29.meta.js // ==/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 = ` 处理中`; 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 = ` 威软提取`; 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 = ` 威软提取`; btn.onclick = () => DriveManager.runExtraction(); document.body.appendChild(btn); const menu = document.createElement('div'); menu.className = 'weiruan-menu'; menu.innerHTML = `
`; 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 = `