// ==UserScript== // @name 网盘下载链接自动捕获助手 Pro // @namespace https://workbuddy.local/download-accelerator // @version 2.0.0 // @description 自动解析夸克/UC/百度网盘分享页面文件列表,批量获取直链下载地址+Cookie,一键导出到下载加速器 // @author DownloadAccelerator // @match *://pan.quark.cn/* // @match *://drive.uc.cn/* // @match *://pan.baidu.com/* // @match *://yun.baidu.com/* // @icon data:image/svg+xml, // @grant GM_setClipboard // @grant GM_notification // @grant GM_xmlhttpRequest // @grant GM_setValue // @grant GM_getValue // @connect pan.quark.cn // @connect drive.uc.cn // @connect pan.baidu.com // @connect d.pcs.baidu.com // @connect * // @run-at document-start // @license MIT // ==/UserScript== (function () { 'use strict'; // ============================================================ // 全局配置 // ============================================================ const PANEL_ID = 'dl-accel-panel'; const MAX_LINKS = 200; const AUTO_CAPTURE = true; const AUTO_COPY = false; const SITE = detectSite(); let capturedLinks = []; let fileList = []; // 解析到的文件列表 let isResolving = false; // 是否正在解析 let shareInfo = null; // 当前分享页信息 let autoCopyEnabled = GM_getValue('autoCopy', AUTO_COPY); // ============================================================ // 站点检测 // ============================================================ function detectSite() { const host = location.hostname; if (host.includes('quark')) { return { name: '夸克网盘', key: 'quark', host: 'https://pan.quark.cn' }; } if (host.includes('uc.cn')) { return { name: 'UC网盘', key: 'uc', host: 'https://drive.uc.cn' }; } if (host.includes('baidu')) { return { name: '百度网盘', key: 'baidu', host: 'https://pan.baidu.com' }; } return { name: '未知网盘', key: 'unknown', host: '' }; } // ============================================================ // 分享页面检测 // ============================================================ function detectSharePage() { const path = location.pathname; const match = path.match(/\/s\/([a-zA-Z0-9]+)/); if (match) { return { shareId: match[1], isShare: true }; } // 百度网盘 /share/init?surl=xxx const params = new URLSearchParams(location.search); const surl = params.get('surl'); if (surl) { return { shareId: surl, isShare: true }; } return { shareId: null, isShare: false }; } // ============================================================ // [核心] 网络请求拦截 - fetch // ============================================================ const originalFetch = window.fetch; window.fetch = function (...args) { const url = typeof args[0] === 'string' ? args[0] : (args[0]?.url || ''); const options = args[1] || {}; const promise = originalFetch.apply(this, args); // 异步分析响应 if (AUTO_CAPTURE) { promise.then(response => { const cloned = response.clone(); cloned.text().then(text => { analyzeResponse(url, options, text, cloned.status, cloned.headers); }).catch(() => {}); }).catch(() => {}); } return promise; }; // ============================================================ // [核心] 网络请求拦截 - XMLHttpRequest // ============================================================ const OriginalXHR = window.XMLHttpRequest; const xhrOpen = OriginalXHR.prototype.open; const xhrSend = OriginalXHR.prototype.send; OriginalXHR.prototype.open = function (method, url, ...rest) { this._dl_url = url; this._dl_method = method; return xhrOpen.call(this, method, url, ...rest); }; OriginalXHR.prototype.send = function (body) { const self = this; this.addEventListener('load', function () { if (AUTO_CAPTURE) { try { analyzeResponse(self._dl_url, {}, self.responseText, self.status, null); } catch (e) {} } }); return xhrSend.call(this, body); }; // ============================================================ // [核心] 响应分析引擎 - 自动识别各种API响应格式 // ============================================================ function analyzeResponse(url, options, responseText, status, headers) { if (!url || status !== 200) return; let data = null; try { data = JSON.parse(responseText); } catch (e) { return; // 非JSON响应跳过 } // ----- 1. 检测文件列表响应 ----- const fileItems = extractFileList(url, data); if (fileItems.length > 0) { mergeFileList(fileItems); updatePanel(); showToast(`检测到 ${fileItems.length} 个文件`); } // ----- 2. 检测下载链接响应 ----- const dlLinks = extractDownloadLinks(url, data, options); for (const dl of dlLinks) { addCapturedLink(dl.url, dl.fileName, dl.fileSize, dl.fid); } // ----- 3. 检测百度网盘 yunData ----- if (SITE.key === 'baidu' && !shareInfo) { extractBaiduYunData(); } } // ============================================================ // 文件列表提取 - 支持多平台响应格式 // ============================================================ function extractFileList(url, data) { const items = []; if (!data || typeof data !== 'object') return items; // --- 夸克/UC 网盘文件列表 --- // API: /1/clouddrive/share/sharepage/detail if (url.includes('sharepage/detail') || url.includes('share/detail')) { const list = data.data?.list || data.list || []; for (const f of list) { items.push({ fid: f.fid || f.file_id || '', fileName: f.file_name || f.filename || f.name || '', fileSize: f.size || f.file_size || 0, dir: f.dir || f.is_dir || f.category === 'folder', pdirFid: f.pdir_fid || f.parent_id || '', category: f.category || f.obj_category || 'file', raw: f }); } } // --- 百度网盘文件列表 --- // API: /share/wxlist 或 /api/list if (url.includes('wxlist') || url.includes('/api/list') || url.includes('share/list')) { const list = data.data?.list || data.list || data.records || []; for (const f of list) { items.push({ fid: f.fs_id || f.fsId || '', fileName: f.server_filename || f.filename || f.name || '', fileSize: f.size || 0, dir: f.isdir === 1 || f.isdir === true, pdirFid: f.parent_path || f.path || '', category: f.category || 0, raw: f }); } } // --- 通用: 嵌套的 list 字段 --- if (items.length === 0) { const possibleList = data.data?.list || data.data?.items || data.data?.files || data.list || []; if (Array.isArray(possibleList) && possibleList.length > 0) { for (const f of possibleList) { const name = f.file_name || f.filename || f.name || f.server_filename; if (name && (f.fid || f.file_id || f.fs_id)) { items.push({ fid: f.fid || f.file_id || f.fs_id || '', fileName: name, fileSize: f.size || f.file_size || 0, dir: f.is_dir || f.isdir === 1 || f.category === 'folder', pdirFid: f.pdir_fid || f.parent_id || f.path || '', category: f.category || '', raw: f }); } } } } return items; } // ============================================================ // 下载链接提取 - 支持多平台响应格式 // ============================================================ function extractDownloadLinks(url, data, options) { const links = []; if (!data || typeof data !== 'object') return links; // --- 夸克/UC 下载链接 --- // API: /1/clouddrive/file/download/v2/detail if (url.includes('file/download') || url.includes('download/v2/detail') || url.includes('download/info')) { const dlList = data.data || []; const arr = Array.isArray(dlList) ? dlList : [dlList]; for (const item of arr) { const dlUrl = item.download_url || item.downloadUrl || item.url; if (dlUrl) { links.push({ url: dlUrl, fileName: item.file_name || item.filename || '', fileSize: item.size || 0, fid: item.fid || item.file_id || '' }); } } } // --- 百度网盘下载链接 --- // API: /api/download 或 /share/download if (url.includes('/api/download') || url.includes('/share/download') || url.includes('dlink')) { const dlList = data.dlink || data.data?.dlink || []; const arr = Array.isArray(dlList) ? dlList : [dlList]; for (const item of arr) { const dlUrl = item.dlink || item.download_url || item.url; if (dlUrl) { links.push({ url: dlUrl, fileName: item.server_filename || item.filename || '', fileSize: item.size || 0, fid: item.fs_id || '' }); } } } // --- 通用: 任何包含 download_url 的响应 --- if (links.length === 0) { const searchKeys = ['download_url', 'downloadUrl', 'dlink', 'direct_url', 'directUrl']; function deepSearch(obj, depth) { if (depth > 3 || !obj || typeof obj !== 'object') return; for (const key of Object.keys(obj)) { if (searchKeys.includes(key) && typeof obj[key] === 'string' && obj[key].startsWith('http')) { links.push({ url: obj[key], fileName: obj.file_name || obj.filename || obj.server_filename || obj.name || '', fileSize: obj.size || obj.file_size || 0, fid: obj.fid || obj.file_id || obj.fs_id || '' }); } else if (typeof obj[key] === 'object') { deepSearch(obj[key], depth + 1); } } } deepSearch(data, 0); } return links; } // ============================================================ // 百度网盘 yunData 提取 // ============================================================ function extractBaiduYunData() { if (SITE.key !== 'baidu') return; if (typeof window.yunData === 'undefined') { // 尝试从页面 script 中提取 setTimeout(extractBaiduYunData, 2000); return; } try { const yun = window.yunData; if (yun.SIGN &&yun.FS_ID) { shareInfo = { sign: yun.SIGN, bdstoken: yun.MYBDSTOKEN || yun.bdstoken, shareId: yun.SHARE_ID || '', uk: yun.SHARE_UK || yun.uk || '', fsIds: Array.isArray(yun.FS_ID) ? yun.FS_ID : [yun.FS_ID] }; } } catch (e) {} } // ============================================================ // [平台API] 夸克/UC - 获取文件列表 // ============================================================ async function quarkGetFileList(shareId, pdirFid, page) { const baseUrl = SITE.host; const apiUrl = `${baseUrl}/1/clouddrive/share/sharepage/detail?pr=ucpro&fr=pc`; try { // 先获取 share token const tokenResp = await fetch(`${baseUrl}/1/clouddrive/share/sharepage/token?pr=ucpro&fr=pc`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ share_id: shareId }) }); const tokenData = await tokenResp.json(); // 获取文件列表 const listResp = await fetch(apiUrl, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ share_id: shareId, pdir_fid: pdirFid || '0', force: 0, _page: page || 1, _size: 50, _fetch_total: 1, _sort: 'file_type:asc,updated_at:desc' }) }); const listData = await listResp.json(); if (listData.code === 0 || listData.code === '0') { return listData.data?.list || []; } return []; } catch (e) { console.warn('[捕获助手] 获取文件列表失败:', e); return []; } } // ============================================================ // [平台API] 夸克/UC - 获取下载链接 // ============================================================ async function quarkGetDownloadLink(fids) { const baseUrl = SITE.host; const apiUrl = `${baseUrl}/1/clouddrive/file/download/v2/detail?pr=ucpro&fr=pc`; try { const resp = await fetch(apiUrl, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ fid_list: fids }) }); const data = await resp.json(); if (data.code === 0 || data.code === '0') { return data.data || []; } return []; } catch (e) { console.warn('[捕获助手] 获取下载链接失败:', e); return []; } } // ============================================================ // [平台API] 百度网盘 - 获取下载链接 // ============================================================ async function baiduGetDownloadLink(fsIds) { const bdstoken = window.yunData?.MYBDSTOKEN || window.yunData?.bdstoken || ''; const apiUrl = `/api/download?clienttype=0&app_id=250528&web=1&bdstoken=${bdstoken}`; try { const params = new URLSearchParams(); params.append('type', 'dlink'); for (const id of fsIds) { params.append('fidlist', `[${id}]`); } const resp = await fetch(apiUrl, { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, body: `fidlist=[${fsIds.join(',')}]&type=dlink` }); const data = await resp.json(); if (data.errno === 0) { return data.dlink || []; } return []; } catch (e) { console.warn('[捕获助手] 获取百度下载链接失败:', e); return []; } } // ============================================================ // [核心] 自动解析当前分享页 - 获取所有文件下载链接 // ============================================================ async function autoResolveSharePage() { if (isResolving) { showToast('正在解析中,请稍候...'); return; } const share = detectSharePage(); if (!share.isShare) { showToast('当前不是分享页面'); return; } isResolving = true; updateResolveButton(true); showToast('开始自动解析分享页面...'); try { if (SITE.key === 'quark' || SITE.key === 'uc') { await resolveQuarkShare(share.shareId); } else if (SITE.key === 'baidu') { await resolveBaiduShare(); } } catch (e) { showToast('解析失败: ' + e.message); console.error('[捕获助手] 解析失败:', e); } finally { isResolving = false; updateResolveButton(false); } } // 夸克/UC 分享页解析 async function resolveQuarkShare(shareId) { // 获取根目录文件列表 const files = await quarkGetFileList(shareId, '0', 1); if (files.length === 0) { showToast('未获取到文件,请确保已保存到网盘或已通过密码验证'); return; } // 过滤出文件(排除文件夹) const fileOnly = files.filter(f => !f.dir && !f.file_type?.includes('folder')); const folders = files.filter(f => f.dir || f.file_type?.includes('folder')); showToast(`发现 ${files.length} 个项目(${fileOnly.length} 文件, ${folders.length} 文件夹),正在获取下载链接...`); // 批量获取文件下载链接(每批最多10个) const batchSize = 10; for (let i = 0; i < fileOnly.length; i += batchSize) { const batch = fileOnly.slice(i, i + batchSize); const fids = batch.map(f => f.fid); const dlData = await quarkGetDownloadLink(fids); for (const dl of dlData) { addCapturedLink( dl.download_url, dl.file_name || batch.find(f => f.fid === dl.fid)?.file_name || '', dl.size || 0, dl.fid ); } updatePanel(); // 小延迟避免请求过快 if (i + batchSize < fileOnly.length) { await sleep(500); } } showToast(`解析完成!共获取 ${capturedLinks.length} 个下载链接`); } // 百度网盘分享页解析 async function resolveBaiduShare() { // 等待 yunData 加载 if (!window.yunData) { showToast('页面数据未加载完成,请稍后再试'); return; } const yun = window.yunData; const fsIds = Array.isArray(yun.FS_ID) ? yun.FS_ID : [yun.FS_ID].filter(Boolean); if (fsIds.length === 0) { showToast('未找到文件,请确保已保存到网盘'); return; } showToast(`发现 ${fsIds.length} 个文件,正在获取下载链接...`); // 批量获取下载链接 const batchSize = 5; for (let i = 0; i < fsIds.length; i += batchSize) { const batch = fsIds.slice(i, i + batchSize); const dlData = await baiduGetDownloadLink(batch); for (const dl of dlData) { addCapturedLink( dl.dlink, dl.server_filename || dl.filename || '', dl.size || 0, dl.fs_id ); } updatePanel(); if (i + batchSize < fsIds.length) { await sleep(800); } } showToast(`解析完成!共获取 ${capturedLinks.length} 个下载链接`); } // ============================================================ // 链接管理 // ============================================================ function addCapturedLink(url, fileName, fileSize, fid) { if (!url || url === '') return; // 去重 const exists = capturedLinks.find(l => l.url === url || (fid && l.fid === fid)); if (exists) { // 更新信息 if (fileName && !exists.fileName) exists.fileName = fileName; if (fileSize && !exists.fileSize) exists.fileSize = fileSize; return; } capturedLinks.unshift({ url: url, fileName: fileName || '', fileSize: fileSize || 0, fid: fid || '', cookies: document.cookie, userAgent: navigator.userAgent, referer: location.href, source: SITE.name, time: new Date().toLocaleString('zh-CN') }); if (capturedLinks.length > MAX_LINKS) capturedLinks.pop(); saveLinks(); showToast(`捕获: ${fileName || '下载链接'}`); if (autoCopyEnabled) { copyToClipboard(url); } } function mergeFileList(items) { for (const item of items) { if (!item.dir) { const exists = fileList.find(f => f.fid === item.fid); if (!exists) { fileList.push(item); } } } } function saveLinks() { try { GM_setValue('capturedLinks', JSON.stringify(capturedLinks)); } catch (e) { try { sessionStorage.setItem('dl_links', JSON.stringify(capturedLinks)); } catch(e) {} } } function loadLinks() { try { const data = GM_getValue('capturedLinks', null); if (data) { capturedLinks = JSON.parse(data) || []; } else { const ss = sessionStorage.getItem('dl_links'); if (ss) capturedLinks = JSON.parse(ss) || []; } } catch (e) { capturedLinks = []; } } // ============================================================ // UI - 浮动面板 // ============================================================ function createPanel() { if (document.getElementById(PANEL_ID)) return; const panel = document.createElement('div'); panel.id = PANEL_ID; panel.innerHTML = `
下载链接捕获 ${SITE.name} 0
📥
尚未捕获到下载链接
点击「自动解析」一键获取分享页所有文件链接
或在网盘中正常下载,链接会自动捕获
`; function append() { if (document.body) { document.body.appendChild(panel); bindEvents(); updatePanel(); } else { setTimeout(append, 100); } } append(); } // ============================================================ // 事件绑定 // ============================================================ function bindEvents() { // 折叠 const toggleBtn = document.getElementById('dl-toggle-btn'); const body = document.getElementById('dl-body'); let collapsed = false; toggleBtn.addEventListener('click', () => { collapsed = !collapsed; body.classList.toggle('collapsed', collapsed); toggleBtn.textContent = collapsed ? '+' : '−'; }); // 拖拽 makeDraggable(document.getElementById(PANEL_ID), document.getElementById('dl-header-bar')); // 自动解析 document.getElementById('dl-resolve-btn').addEventListener('click', autoResolveSharePage); // 导出全部 document.getElementById('dl-export-btn').addEventListener('click', exportAllLinks); // 复制全部链接 document.getElementById('dl-copy-all-btn').addEventListener('click', copyAllLinks); // 清空 document.getElementById('dl-clear-btn').addEventListener('click', () => { if (capturedLinks.length === 0) return; if (confirm(`确定清空 ${capturedLinks.length} 个链接?`)) { capturedLinks = []; fileList = []; saveLinks(); updatePanel(); } }); // 自动复制开关 document.getElementById('dl-auto-copy').addEventListener('change', (e) => { autoCopyEnabled = e.target.checked; GM_setValue('autoCopy', autoCopyEnabled); showToast(autoCopyEnabled ? '已开启自动复制' : '已关闭自动复制'); }); } function updateResolveButton(loading) { const btn = document.getElementById('dl-resolve-btn'); if (!btn) return; if (loading) { btn.innerHTML = ' 解析中...'; btn.disabled = true; } else { btn.innerHTML = '🔍 自动解析'; btn.disabled = false; } } // ============================================================ // 拖拽 // ============================================================ function makeDraggable(panel, handle) { let dragging = false, sx, sy, sl, st; handle.addEventListener('mousedown', (e) => { if (e.target.tagName === 'BUTTON') return; dragging = true; sx = e.clientX; sy = e.clientY; const r = panel.getBoundingClientRect(); sl = r.left; st = r.top; panel.style.right = 'auto'; panel.style.left = sl + 'px'; panel.style.top = st + 'px'; e.preventDefault(); }); document.addEventListener('mousemove', (e) => { if (!dragging) return; let nl = Math.max(0, Math.min(innerWidth - panel.offsetWidth, sl + e.clientX - sx)); let nt = Math.max(0, Math.min(innerHeight - 40, st + e.clientY - sy)); panel.style.left = nl + 'px'; panel.style.top = nt + 'px'; }); document.addEventListener('mouseup', () => { dragging = false; }); } // ============================================================ // 面板更新 // ============================================================ function updatePanel() { const container = document.getElementById('dl-list-container'); const countEl = document.getElementById('dl-count'); const footerCount = document.getElementById('dl-footer-count'); if (!container) return; if (countEl) countEl.textContent = capturedLinks.length; if (footerCount) footerCount.textContent = capturedLinks.length; if (capturedLinks.length === 0) { container.innerHTML = `
📥
尚未捕获到下载链接
点击「自动解析」一键获取分享页所有文件链接
或在网盘中正常下载,链接会自动捕获
`; return; } let html = ''; for (let i = 0; i < capturedLinks.length; i++) { const link = capturedLinks[i]; const name = link.fileName || '(未命名文件)'; const sizeStr = link.fileSize ? formatSize(link.fileSize) : '--'; const icon = getFileIcon(name); const shortUrl = link.url.length > 80 ? link.url.substring(0, 77) + '...' : link.url; html += `
${icon}${escapeHtml(name)}
${sizeStr} | ${link.source} | ${link.time}
${escapeHtml(shortUrl)}
`; } container.innerHTML = html; } // ============================================================ // 复制操作 // ============================================================ window.__dlCopy = function (i) { const link = capturedLinks[i]; if (!link) return; copyToClipboard(link.url); showToast('链接已复制'); }; window.__dlCopyFull = function (i) { const link = capturedLinks[i]; if (!link) return; const text = formatForAccelerator(link); copyToClipboard(text); showToast('链接+Cookie已复制,粘贴到下载加速器'); }; window.__dlOpen = function (i) { const link = capturedLinks[i]; if (!link) return; window.open(link.url, '_blank'); }; function copyAllLinks() { if (capturedLinks.length === 0) { showToast('没有链接可复制'); return; } const text = capturedLinks.map(l => l.url).join('\n'); copyToClipboard(text); showToast(`已复制 ${capturedLinks.length} 个链接`); } function exportAllLinks() { if (capturedLinks.length === 0) { showToast('没有链接可导出'); return; } const lines = capturedLinks.map((link, i) => { return formatForAccelerator(link, i > 0); }); const text = lines.join('\n\n---\n\n'); copyToClipboard(text); showToast(`已导出 ${capturedLinks.length} 个链接(含Cookie),粘贴到下载加速器`); } function formatForAccelerator(link, separator) { return [ `下载链接: ${link.url}`, `文件名: ${link.fileName || '(自动获取)'}`, ``, `自定义请求头:`, `Cookie: ${link.cookies}`, `User-Agent: ${link.userAgent}`, link.referer ? `Referer: ${link.referer}` : '', ].filter(Boolean).join('\n'); } // ============================================================ // 工具函数 // ============================================================ function formatSize(bytes) { if (!bytes || bytes === 0) return '--'; if (bytes < 1024) return bytes + ' B'; if (bytes < 1048576) return (bytes / 1024).toFixed(1) + ' KB'; if (bytes < 1073741824) return (bytes / 1048576).toFixed(1) + ' MB'; return (bytes / 1073741824).toFixed(2) + ' GB'; } function getFileIcon(name) { const ext = name.split('.').pop()?.toLowerCase(); const map = { 'mp4': '🎬', 'avi': '🎬', 'mkv': '🎬', 'mov': '🎬', 'wmv': '🎬', 'flv': '🎬', 'rmvb': '🎬', 'mp3': '🎵', 'wav': '🎵', 'flac': '🎵', 'ape': '🎵', 'aac': '🎵', 'm4a': '🎵', 'jpg': '🖼️', 'jpeg': '🖼️', 'png': '🖼️', 'gif': '🖼️', 'bmp': '🖼️', 'webp': '🖼️', 'pdf': '📕', 'doc': '📘', 'docx': '📘', 'xls': '📗', 'xlsx': '📗', 'ppt': '📙', 'pptx': '📙', 'zip': '📦', 'rar': '📦', '7z': '📦', 'tar': '📦', 'gz': '📦', 'exe': '⚙️', 'msi': '⚙️', 'apk': '📱', 'dmg': '💻', 'txt': '📄', 'md': '📄', 'json': '📄', 'iso': '💿', 'epub': '📖', 'mobi': '📖', }; return map[ext] || '📄'; } function escapeHtml(str) { if (!str) return ''; return str.replace(/&/g, '&').replace(//g, '>') .replace(/"/g, '"').replace(/'/g, '''); } function copyToClipboard(text) { if (typeof GM_setClipboard === 'function') { GM_setClipboard(text); } else { const ta = document.createElement('textarea'); ta.value = text; ta.style.cssText = 'position:fixed;opacity:0;'; document.body.appendChild(ta); ta.select(); try { document.execCommand('copy'); } catch (e) {} document.body.removeChild(ta); } } function sleep(ms) { return new Promise(r => setTimeout(r, ms)); } // ============================================================ // Toast 通知 // ============================================================ function showToast(msg) { if (typeof GM_notification === 'function') { GM_notification({ title: '下载链接捕获助手 Pro', text: msg, timeout: 2500 }); } let toast = document.getElementById('dl-toast'); if (!toast) { toast = document.createElement('div'); toast.id = 'dl-toast'; toast.style.cssText = ` position: fixed; bottom: 30px; left: 50%; transform: translateX(-50%) translateY(80px); background: #333; color: #fff; padding: 10px 24px; border-radius: 10px; font-size: 13px; font-family: "Microsoft YaHei UI",sans-serif; z-index: 1000000; opacity: 0; transition: transform 0.3s, opacity 0.3s; box-shadow: 0 4px 20px rgba(0,0,0,0.25); `; function appendToast() { if (document.body) document.body.appendChild(toast); else setTimeout(appendToast, 100); } appendToast(); } toast.textContent = '⚡ ' + msg; toast.style.opacity = '1'; toast.style.transform = 'translateX(-50%) translateY(0)'; clearTimeout(toast._timer); toast._timer = setTimeout(() => { toast.style.opacity = '0'; toast.style.transform = 'translateX(-50%) translateY(80px)'; }, 2500); } // ============================================================ // 初始化 // ============================================================ function init() { loadLinks(); function onReady() { createPanel(); // 如果是分享页,自动提示 const share = detectSharePage(); if (share.isShare) { setTimeout(() => { showToast(`检测到分享页面,点击「自动解析」一键获取下载链接`); }, 1500); } // 百度网盘: 注入 yunData 监听 if (SITE.key === 'baidu') { injectBaiduHook(); } } if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', onReady); } else { onReady(); } console.log(`[下载捕获助手 Pro v2.0] 已加载 - ${SITE.name}`); } // ============================================================ // 百度网盘 yunData 钩子 // ============================================================ function injectBaiduHook() { // 监听 yunData 是否出现 let attempts = 0; const checkYunData = setInterval(() => { attempts++; if (window.yunData || attempts > 30) { clearInterval(checkYunData); if (window.yunData) { extractBaiduYunData(); console.log('[捕获助手] 百度网盘 yunData 已捕获'); } } }, 500); } init(); })();