// ==UserScript== // @name QQ空间自动点赞 (全能GUI版) // @namespace https://scriptcat.org/ // @version 3.0 // @description 支持个人中心 + 好友主页自动点赞。内置GUI设置界面,支持白名单/黑名单配置。 // @author AI Assistant // @match https://user.qzone.qq.com/* // @match https://qzone.qq.com/* // @grant GM_getValue // @grant GM_setValue // @grant GM_addStyle // @run-at document-idle // ==/UserScript== (function() { 'use strict'; // --- 默认配置 --- const DEFAULT_CONFIG = { mode: 'all', // all | whitelist | blacklist names: '', // 逗号或换行分隔 minDelay: 800, maxDelay: 2000, enable: true // 总开关 }; // --- 样式定义 --- const STYLES = ` #qz-helper-btn { position: fixed; bottom: 50px; right: 20px; z-index: 9999; background: linear-gradient(135deg, #FF9800, #F44336); color: #fff; border: none; border-radius: 50px; padding: 10px 20px; font-size: 14px; font-weight: bold; box-shadow: 0 4px 15px rgba(244, 67, 54, 0.4); cursor: pointer; transition: transform 0.2s; } #qz-helper-btn:hover { transform: scale(1.05); } #qz-settings-panel { position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%); width: 400px; background: #fff; z-index: 10000; border-radius: 12px; box-shadow: 0 10px 30px rgba(0,0,0,0.3); padding: 20px; font-family: "Microsoft YaHei", sans-serif; display: none; border: 1px solid #eee; } .qz-header { display: flex; justify-content: space-between; align-items: center; border-bottom: 1px solid #eee; padding-bottom: 10px; margin-bottom: 15px; } .qz-header h3 { margin: 0; font-size: 18px; color: #333; } .qz-close { cursor: pointer; font-size: 24px; color: #999; line-height: 1; } .qz-form-item { margin-bottom: 15px; } .qz-form-item label { display: block; margin-bottom: 5px; font-weight: bold; font-size: 13px; color: #555; } .qz-form-item select, .qz-form-item input, .qz-form-item textarea { width: 100%; box-sizing: border-box; padding: 8px; border: 1px solid #ddd; border-radius: 6px; font-size: 13px; outline: none; } .qz-form-item select:focus, .qz-form-item input:focus, .qz-form-item textarea:focus { border-color: #FF9800; } .qz-form-item textarea { height: 80px; resize: vertical; } .qz-delay-group { display: flex; gap: 10px; align-items: center; } .qz-footer { margin-top: 20px; text-align: right; } .qz-btn { padding: 8px 25px; border-radius: 6px; border: none; cursor: pointer; font-size: 13px; font-weight: bold; transition: background 0.2s;} .qz-btn-primary { background: #FF9800; color: white; } .qz-btn-primary:hover { background: #F57C00; } .qz-status-bar { margin-top: 15px; font-size: 12px; color: #666; border-top: 1px solid #eee; padding-top: 10px; background: #f9f9f9; padding: 10px; border-radius: 4px;} `; GM_addStyle(STYLES); // --- 状态管理 --- let config = GM_getValue('qz_config', DEFAULT_CONFIG); let isRunning = false; // --- GUI 构建函数 (保持不变,略微美化) --- function createGUI() { if (document.getElementById('qz-helper-btn')) return; const btn = document.createElement('button'); btn.id = 'qz-helper-btn'; btn.innerHTML = '❤️ 点赞设置'; btn.onclick = togglePanel; document.body.appendChild(btn); const panel = document.createElement('div'); panel.id = 'qz-settings-panel'; panel.innerHTML = `

QQ空间点赞助手 v3.0

×
状态: 准备就绪
`; document.body.appendChild(panel); panel.querySelector('.qz-close').onclick = togglePanel; panel.querySelector('#qz-save').onclick = saveConfig; } function togglePanel() { const panel = document.getElementById('qz-settings-panel'); if (panel.style.display === 'block') { panel.style.display = 'none'; } else { loadConfigToUI(); panel.style.display = 'block'; } } function loadConfigToUI() { config = GM_getValue('qz_config', DEFAULT_CONFIG); document.getElementById('qz-enable').value = config.enable.toString(); document.getElementById('qz-mode').value = config.mode; document.getElementById('qz-names').value = config.names; document.getElementById('qz-min-delay').value = config.minDelay; document.getElementById('qz-max-delay').value = config.maxDelay; } function saveConfig() { const newConfig = { enable: document.getElementById('qz-enable').value === 'true', mode: document.getElementById('qz-mode').value, names: document.getElementById('qz-names').value, minDelay: parseInt(document.getElementById('qz-min-delay').value) || 800, maxDelay: parseInt(document.getElementById('qz-max-delay').value) || 2000 }; GM_setValue('qz_config', newConfig); config = newConfig; const btn = document.getElementById('qz-save'); btn.innerText = "已保存!"; setTimeout(() => { btn.innerText = "保存并应用"; document.getElementById('qz-settings-panel').style.display = 'none'; }, 800); updateStatus("配置已更新,继续扫描..."); } function updateStatus(text) { const el = document.getElementById('qz-status'); if (el) el.innerText = `状态: ${text}`; } // --- 核心逻辑增强版 --- const sleep = (ms) => new Promise(r => setTimeout(r, ms)); const randomSleep = (min, max) => sleep(Math.floor(Math.random() * (max - min + 1) + min)); const getNameList = () => { if (!config.names) return []; return config.names.split(/[,,\n]/).map(s => s.trim()).filter(s => s); }; const checkPermission = (author) => { const list = getNameList(); if (config.mode === 'all') return true; if (config.mode === 'whitelist') return list.includes(author); if (config.mode === 'blacklist') return !list.includes(author); return false; }; /** * 获取页面上所有的动态元素 * 关键修改:同时查找主文档和 app_canvas_frame 框架内的元素 */ const getAllFeeds = () => { let feeds = []; // 1. 扫描主文档 try { const mainFeeds = document.querySelectorAll('.f-single'); if(mainFeeds.length > 0) feeds = feeds.concat(Array.from(mainFeeds)); } catch(e) {} // 2. 扫描 Iframe (针对个人主页) try { const iframe = document.getElementById('app_canvas_frame'); if (iframe && iframe.contentDocument) { const frameFeeds = iframe.contentDocument.querySelectorAll('.f-single'); if(frameFeeds.length > 0) feeds = feeds.concat(Array.from(frameFeeds)); } } catch (e) { // 可能会遇到跨域保护,但在QQ空间同域下通常没事 console.warn("访问Iframe受限:", e); } return feeds; }; const mainTask = async () => { if (isRunning) return; config = GM_getValue('qz_config', DEFAULT_CONFIG); if (!config.enable) { updateStatus("脚本暂停中"); return; } isRunning = true; updateStatus("正在扫描动态 (含好友主页)..."); try { const feeds = getAllFeeds(); let hasAction = false; for (const feed of feeds) { if (!config.enable) break; // 1. 查找点赞按钮 (v3通用版) const likeBtn = feed.querySelector('.qz_like_btn_v3'); if (!likeBtn) continue; // 2. 检查是否已赞 // item-on 类代表已赞,或者 title/aria-label 包含取消 if (likeBtn.classList.contains('item-on')) continue; // 3. 获取作者昵称 // 个人主页的结构略有不同,有时候昵称在 .user-info 里 let nickEl = feed.querySelector('.f-nick') || feed.querySelector('.user-info .nickname'); // 如果在个人主页找不到昵称元素,可能需要从页面标题或者顶部获取(视作该页面的主人) // 这里做个兜底:如果找不到昵称,但在个人主页Iframe里,通常意味着是号主发的 let author = ""; if (nickEl) { author = nickEl.innerText.trim(); } else { // 尝试获取动态所有者备选方案 const ownerEl = document.querySelector('.head-detail .user-name') || (document.getElementById('app_canvas_frame') && document.getElementById('app_canvas_frame').contentDocument.querySelector('.user-name')); if(ownerEl) author = ownerEl.innerText.trim(); } if (!author) continue; // 如果实在找不到名字,为了安全起见跳过 // 4. 权限校验 if (checkPermission(author)) { updateStatus(`正在点赞: ${author}`); likeBtn.click(); hasAction = true; await randomSleep(config.minDelay, config.maxDelay); } } if (!hasAction) { // 判断当前是在哪个环境 const count = feeds.length; updateStatus(`扫描了 ${count} 条动态,暂无新内容。`); } } catch (e) { console.error("点赞出错:", e); updateStatus("发生错误,重试中..."); } finally { isRunning = false; } }; // --- 启动 --- window.addEventListener('load', () => { createGUI(); // 首次延迟启动 setTimeout(mainTask, 3000); // 循环扫描 (4秒一次) setInterval(mainTask, 4000); console.log("QQ空间全能点赞助手 v3.0 已加载"); }); })();