您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
在“链接合集帖”一键批量打开邀请链接;在邀请页自动点击“接受邀请”,成功后自动关页并继续
// ==UserScript== // @license MIT // @name Discuz 好友助手 // @namespace https://tdsheepvillage.com // @version 1.0.3 // @description 在“链接合集帖”一键批量打开邀请链接;在邀请页自动点击“接受邀请”,成功后自动关页并继续 // @author you // @match https://www.tdsheepvillage.com/* // @match https://tdsheepvillage.com/* // @icon https://www.google.com/s2/favicons?sz=64&domain=tdsheepvillage.com // @grant GM_openInTab // @grant GM_setValue // @grant GM_getValue // @grant GM_addStyle // @grant unsafeWindow // @run-at document-idle // ==/UserScript== (function () { 'use strict'; const HOST = location.host; // ------------- 小工具 ------------- const sleep = (ms) => new Promise(r => setTimeout(r, ms)); const includesText = (el, kw) => !!el && ((el.textContent || el.value || '') + '').includes(kw); // 统一的强制关闭(带多重兜底) function forceCloseTab(delay = 0) { setTimeout(() => { try { window.close(); } catch (e) {} // 再兜底一次:跳 blank 后再关,部分浏览器更容易成功 setTimeout(() => { try { location.href = 'about:blank'; } catch (e) {} setTimeout(() => { try { window.close(); } catch (e) {} }, 60); }, 400); }, delay); } function createPanel() { const wrap = document.createElement('div'); wrap.id = 'invite-batch-panel'; wrap.innerHTML = ` <div class="ibp-card"> <div class="ibp-title">批量接受好友邀请</div> <div class="ibp-note">已识别链接:<span class="ibp-count">0</span> 条</div> <div class="ibp-note ibp-progress">待开始</div> <button class="ibp-btn">开始批量接受(0)</button> </div> `; GM_addStyle(` #invite-batch-panel{position:fixed;right:16px;bottom:16px;z-index:999999;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica,Arial} #invite-batch-panel .ibp-card{background:#fff;border:1px solid #e5e7eb;border-radius:12px;box-shadow:0 8px 24px rgba(0,0,0,.12);padding:12px 14px;min-width:230px} .ibp-title{font-weight:600;margin-bottom:6px} .ibp-note{font-size:13px;color:#374151;margin:4px 0} .ibp-btn{all:unset;border:1px solid #2563eb;color:#2563eb;border-radius:8px;padding:6px 10px;cursor:pointer;font-size:13px} .ibp-btn:disabled{opacity:.5;cursor:not-allowed} `); document.body.appendChild(wrap); return wrap; } // ------------- 场景 A:邀请落地页(自动点“接受邀请”,自动关闭标签) ------------- async function autoAcceptOnInvitePage() { // 1) 屏蔽/自动通过 alert/confirm/prompt,避免阻塞 try { unsafeWindow.alert = () => {}; unsafeWindow.confirm = () => true; unsafeWindow.prompt = () => null; } catch (e) { // 某些环境没有 unsafeWindow,用 window 兜底 window.alert = () => {}; window.confirm = () => true; window.prompt = () => null; } // 2) 判断是否邀请页(找“接受邀请”等按钮) const btns = Array.from(document.querySelectorAll('a,button,input')) .filter(el => { const t = (el.textContent || el.value || '').trim(); return /接受邀请|接受 好友邀请|同意|Accept/i.test(t); }); if (btns.length === 0) return false; // 不是邀请页 // 已是好友/已处理:直接关闭 const bodyTxt = (document.body.innerText || '').trim(); if (/(已是好友|已接受邀请|请求已发送|等待验证|正在处理)/.test(bodyTxt)) { forceCloseTab(500); return true; } // 3) 点击“接受邀请” btns[0].click(); // 4) 最多等 2.5s 观察成功提示;无论如何最后都关 const okCheck = () => /(已是好友|操作成功|已接受邀请|请求已发送|等待验证|正在处理)/.test((document.body.innerText || '').trim()); const t0 = Date.now(); while (Date.now() - t0 < 2500) { if (okCheck()) break; await sleep(150); } // 5) 关闭(强制兜底) forceCloseTab(200); return true; } // ------------- 场景 B:链接合集帖(批量打开) ------------- function collectInviteLinks() { // 合集帖每条是本站完整链接,且带 c=xxx 参数 const as = Array.from(document.querySelectorAll('a[href]')); const list = as .map(a => a.href) .filter(h => /^https?:\/\//.test(h) && h.includes(HOST) && /[?&]c=/.test(h) ); return Array.from(new Set(list)); } async function runBatch() { const panel = document.getElementById('invite-batch-panel'); const progressEl = panel.querySelector('.ibp-progress'); const btn = panel.querySelector('.ibp-btn'); const links = collectInviteLinks(); let done = 0; btn.disabled = true; for (const url of links) { progressEl.textContent = `打开并处理:${done + 1} / ${links.length}`; GM_openInTab(url, { active: false, insert: true, setParent: true }); // 节流,避免被风控;需要更快可调小(自担风险) await sleep(1600); done++; } progressEl.textContent = `完成:${done} / ${links.length}`; btn.disabled = false; } (async function main() { // 邀请页:自动接受并关页 const handled = await autoAcceptOnInvitePage(); if (handled) return; // 合集帖:显示控制面板并运行 const links = collectInviteLinks(); if (links.length > 0) { const panel = createPanel(); panel.querySelector('.ibp-count').textContent = links.length; const btn = panel.querySelector('.ibp-btn'); const progressEl = panel.querySelector('.ibp-progress'); btn.textContent = `开始批量接受(${links.length})`; progressEl.textContent = '就绪'; btn.addEventListener('click', runBatch); } })(); })();