您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
火星扫码系统出品:百度系全站可拖拽悬浮logo,批量智能注入、复制、清理CK+一键检测接码API到期!
// ==UserScript== // @name 火星工具箱 // @namespace https://hxxt.cc/ // @version 3.0 // @description 火星扫码系统出品:百度系全站可拖拽悬浮logo,批量智能注入、复制、清理CK+一键检测接码API到期! // @author 火星扫码系统 & ChatGPT // @match *://*.baidu.com/* // @icon https://hxxt.cc/color-space-logo.png // @license 只要您给我署名就可以修改 // @grant GM_xmlhttpRequest // @grant GM_setClipboard // @connect * // ==/UserScript== (function () { 'use strict'; // --- 创建悬浮Logo --- function createFloatLogo() { if (document.getElementById('huoxing_ck_logo_2024')) return; const ball = document.createElement('div'); ball.id = 'huoxing_ck_logo_2024'; ball.style.position = 'fixed'; ball.style.top = '250px'; ball.style.right = '24px'; ball.style.zIndex = '2147483647'; ball.style.width = '56px'; ball.style.height = '56px'; ball.style.background = 'transparent'; ball.style.borderRadius = '50%'; ball.style.boxShadow = '0 3px 15px rgba(0,128,255,.19)'; ball.style.display = 'flex'; ball.style.alignItems = 'center'; ball.style.justifyContent = 'center'; ball.style.cursor = 'pointer'; ball.style.userSelect = 'none'; ball.title = "火星工具箱"; ball.style.transition = 'box-shadow 0.18s, right 0.3s, left 0.3s, opacity 0.2s'; // 插入logo图片 const img = document.createElement('img'); img.src = 'https://hxxt.cc/color-space-logo.png'; img.alt = '火星扫码系统LOGO'; img.style.width = '45px'; img.style.height = '35px'; img.style.borderRadius = '50%'; img.style.boxShadow = '0 2px 10px rgba(0,128,255,0.11)'; img.draggable = false; ball.appendChild(img); document.body.appendChild(ball); // 拖动逻辑 let dragging = false, lastX = 0, lastY = 0, startLeft = 0, startTop = 0, side = 'right'; // 记录吸附边 function getSide() { const rect = ball.getBoundingClientRect(); return rect.left + rect.width/2 < window.innerWidth/2 ? 'left' : 'right'; } // 只允许贴边,完全显示 function stickToEdge() { const rect = ball.getBoundingClientRect(); let top = parseInt(ball.style.top); if (isNaN(top)) top = rect.top; // 限制上下 top = Math.max(10, Math.min(window.innerHeight - rect.height - 10, top)); ball.style.top = top + 'px'; // 判断左右 if (rect.left + rect.width/2 < window.innerWidth/2) { // 吸附左侧,完全显示 ball.style.left = '0px'; ball.style.right = ''; side = 'left'; } else { // 吸附右侧,完全显示 ball.style.left = ''; ball.style.right = '0px'; side = 'right'; } } // 拖拽 ball.addEventListener('mousedown', function(e){ dragging = true; lastX = e.clientX; lastY = e.clientY; const rect = ball.getBoundingClientRect(); startLeft = rect.left; startTop = rect.top; ball.style.transition = "none"; e.preventDefault(); }); document.addEventListener('mousemove', function(e){ if(dragging){ let dx = e.clientX - lastX; let dy = e.clientY - lastY; lastX = e.clientX; lastY = e.clientY; let newTop = (parseInt(ball.style.top)||startTop) + dy; // 只允许左右贴边 // 判断鼠标在左半还是右半 if(e.clientX < window.innerWidth/2){ // 贴左 ball.style.left = '0px'; ball.style.right = ''; side = 'left'; }else{ // 贴右 ball.style.left = ''; ball.style.right = '0px'; side = 'right'; } // 限制上下 newTop = Math.max(10, Math.min(window.innerHeight - ball.offsetHeight - 10, newTop)); ball.style.top = newTop + 'px'; } }); document.addEventListener('mouseup', function(){ if(dragging){ dragging = false; ball.style.transition = 'box-shadow 0.18s, right 0.3s, left 0.3s, opacity 0.2s'; stickToEdge(); } }); // 鼠标悬停/移开都保持完全显示 ball.addEventListener('mouseenter', ()=> { ball.style.boxShadow="0 6px 24px 6px #33aadd44"; ball.style.transform = "scale(1.15)"; if(side==='left'){ ball.style.left = '0px'; }else{ ball.style.right = '0px'; } }); ball.addEventListener('mouseleave', ()=>{ ball.style.boxShadow="0 3px 15px rgba(0,128,255,.19)"; ball.style.transform="scale(1)"; if(side==='left'){ ball.style.left = '0px'; }else{ ball.style.right = '0px'; } }); // 点击弹主界面 ball.addEventListener('click', function(){ createUI(); }); // 初始吸附 stickToEdge(); // 窗口变化时自动吸边 window.addEventListener('resize', stickToEdge); } // --- 主页面 --- function createUI() { if (document.getElementById('huoxing_ck_panel_2024')) return; // 遮罩 const mask = document.createElement("div"); mask.id = "huoxing_ck_mask_2024"; mask.style.position = "fixed"; mask.style.left = "0"; mask.style.top = "0"; mask.style.width = "100vw"; mask.style.height = "100vh"; mask.style.background = "rgba(0,0,0,0.12)"; mask.style.zIndex = "2147483646"; mask.onclick = closeUI; // 面板 const div = document.createElement("div"); div.id = "huoxing_ck_panel_2024"; div.style.position = "fixed"; div.style.top = "110px"; div.style.right = "90px"; div.style.zIndex = "2147483647"; div.style.background = "#fff"; div.style.border = "2px solid #0075ff"; div.style.boxShadow = "0 2px 16px rgba(0,128,255,0.14)"; div.style.padding = "20px 22px 16px"; div.style.borderRadius = "13px"; div.style.fontSize = "15px"; div.style.color = "#222"; div.style.minWidth = "370px"; div.style.maxWidth = "98vw"; div.style.lineHeight = "1.7"; // 标题栏 div.innerHTML = ` <div style="display:flex;align-items:center;margin-bottom:4px;"> <img src="https://hxxt.cc/color-space-logo.png" alt="logo" style="height:34px;width:34px;border-radius:50%;margin-right:9px;background:#f8faff;box-shadow:0 1px 6px #eaf1fd;"> <span style="font-weight:bold;font-size:17px;color:#2075FF;">火星百度CK管理工具</span> </div> <div style="color:#2275ff;font-size:13px;margin-bottom:8px;">—— 火星扫码系统出品 ——</div> <div style="margin-bottom:7px;font-size:13px;"> <span style="color:#2075FF">当前域名:</span> <span>${window.location.hostname}</span> </div> `; // === 【1】当前CK展示区:增加卡片效果 === const cookieCard = document.createElement('div'); cookieCard.style.background = "#f9fbfd"; cookieCard.style.border = "1.5px solid #d6e7ff"; cookieCard.style.boxShadow = "0 2px 8px rgba(32,117,255,.04)"; cookieCard.style.borderRadius = "9px"; cookieCard.style.padding = "12px 10px 8px 10px"; cookieCard.style.marginBottom = "13px"; const cookieShow = document.createElement('textarea'); cookieShow.id = "current_cookie_display"; cookieShow.readOnly = true; cookieShow.value = getAllCookieString(); cookieShow.title = '当前域所有Cookie,可手动选中复制'; cookieShow.style.width = '100%'; cookieShow.style.height = '54px'; cookieShow.style.fontFamily = "monospace"; cookieShow.style.background = "#f4faff"; cookieShow.style.resize = "vertical"; cookieShow.style.cursor = "pointer"; cookieShow.style.color = "#444"; cookieShow.style.fontSize = "13px"; cookieShow.style.border = "1px solid #baddff"; cookieShow.style.borderRadius = "6px"; cookieShow.style.boxShadow = "0 1px 3px #e9f1ff"; cookieShow.style.outline = "none"; cookieShow.style.padding = "7px 8px"; cookieCard.appendChild(cookieShow); // 按钮行(复制、清理) const btnBar = document.createElement("div"); btnBar.style.marginTop = "8px"; btnBar.style.display = "flex"; btnBar.style.gap = "10px"; const btnCopy = document.createElement('button'); btnCopy.innerText = "复制当前CK"; btnCopy.style.background = "#40a9ff"; btnCopy.style.color = "#fff"; btnCopy.style.padding = "5px 16px"; btnCopy.style.border = "none"; btnCopy.style.borderRadius = "3px"; btnCopy.style.fontSize = "13px"; btnCopy.onclick = function(){ copyToClipboard(cookieShow.value); showMsg('已复制当前域全部cookie到剪贴板!'); }; btnBar.appendChild(btnCopy); const btnClear = document.createElement('button'); btnClear.innerText = "清理当前CK"; btnClear.style.background = "#ff4747"; btnClear.style.color = "#fff"; btnClear.style.padding = "5px 16px"; btnClear.style.border = "none"; btnClear.style.borderRadius = "3px"; btnClear.style.fontSize = "13px"; btnClear.onclick = function(){ clearAllCookiesSmart(); setTimeout(()=>{ cookieShow.value = getAllCookieString(); showMsg('已清理当前域全部Cookie!'); },400); }; btnBar.appendChild(btnClear); cookieCard.appendChild(btnBar); div.appendChild(cookieCard); // 用卡片包裹 // === 【2】注入区域也加卡片 === const inputCard = document.createElement('div'); inputCard.style.background = "#f9fbfd"; inputCard.style.border = "1.5px solid #d6e7ff"; inputCard.style.boxShadow = "0 2px 8px rgba(32,117,255,.04)"; inputCard.style.borderRadius = "9px"; inputCard.style.padding = "12px 10px 8px 10px"; inputCard.style.marginBottom = "11px"; const ta = document.createElement('textarea'); ta.id = "input_baidu_ck"; ta.placeholder = "请粘贴你的完整Cookie,如:BDUSS=xxx; BAIDUID=yyy; ..."; ta.style.width = "100%"; ta.style.height = "78px"; ta.style.resize = "vertical"; ta.style.background = "#f4faff"; ta.style.fontFamily = "monospace"; ta.style.color = "#444"; ta.style.fontSize = "13px"; ta.style.border = "1px solid #baddff"; ta.style.borderRadius = "6px"; ta.style.boxShadow = "0 1px 3px #e9f1ff"; ta.style.outline = "none"; ta.style.padding = "7px 8px"; inputCard.appendChild(ta); div.appendChild(inputCard); // 注入与关闭按钮 const bar = document.createElement('div'); bar.style.textAlign = "left"; bar.style.display = "flex"; bar.style.gap = "14px"; bar.style.marginTop = "2px"; const btnSet = document.createElement('button'); btnSet.innerText = "注入CK"; btnSet.style.background = "#2075ff"; btnSet.style.color = "#fff"; btnSet.style.padding = "7px 26px"; btnSet.style.border = "none"; btnSet.style.borderRadius = "3px"; btnSet.style.fontSize = "15px"; btnSet.onclick = function(){ const ckStr = ta.value.trim(); if (!ckStr) { showMsg("请先粘贴Cookie!"); return; } clearAllCookiesSmart(); setTimeout(()=>{ let count = injectCookieSmart(ckStr); cookieShow.value = getAllCookieString(); showMsg(`已清理并注入${count}个Cookie,刷新页面后生效!`); },300); }; bar.appendChild(btnSet); const btnClose = document.createElement('button'); btnClose.innerText = "关闭"; btnClose.style.color = "#888"; btnClose.style.background = "#f8f8ff"; btnClose.style.padding = "7px 18px"; btnClose.style.border = "none"; btnClose.style.borderRadius = "3px"; btnClose.style.fontSize = "15px"; btnClose.onclick = closeUI; bar.appendChild(btnClose); div.appendChild(bar); // 提示消息 const tip = document.createElement('div'); tip.id = 'result_baidu_ck'; tip.style.margin = "10px 0 2px"; tip.style.color = "#33a853"; tip.style.fontSize = "13px"; div.appendChild(tip); // ==== 新增:底部"接码API到期批量检测"按钮 ==== const detectBtn = document.createElement('button'); detectBtn.innerText = '接码API到期批量检测'; detectBtn.style.display = "block"; detectBtn.style.width = "100%"; detectBtn.style.margin = '22px 0 0 0'; detectBtn.style.background = "#f9fcff"; detectBtn.style.border = "1.5px solid #3388ee"; detectBtn.style.color = "#2177cc"; detectBtn.style.borderRadius = "6px"; detectBtn.style.fontWeight = "bold"; detectBtn.style.padding = "12px"; detectBtn.style.fontSize = "17px"; detectBtn.style.cursor = "pointer"; detectBtn.onmouseenter = ()=>{detectBtn.style.background="#e6f5ff";} detectBtn.onmouseleave = ()=>{detectBtn.style.background="#f9fcff";} detectBtn.onclick = showApiChecker; div.appendChild(detectBtn); // ==== 新增:检测导入卡密重复功能按钮 ==== const dedupBtn = document.createElement('button'); dedupBtn.innerText = '检测导入卡密重复功能'; dedupBtn.style.display = "block"; dedupBtn.style.width = "100%"; dedupBtn.style.margin = '12px 0 0 0'; dedupBtn.style.background = "#fff9f9"; dedupBtn.style.border = "1.5px solid #ff8888"; dedupBtn.style.color = "#d22"; dedupBtn.style.borderRadius = "6px"; dedupBtn.style.fontWeight = "bold"; dedupBtn.style.padding = "12px"; dedupBtn.style.fontSize = "17px"; dedupBtn.style.cursor = "pointer"; dedupBtn.onmouseenter = ()=>{dedupBtn.style.background="#ffeaea";} dedupBtn.onmouseleave = ()=>{dedupBtn.style.background="#fff9f9";} dedupBtn.onclick = showDedupTool; div.appendChild(dedupBtn); document.body.appendChild(mask); document.body.appendChild(div); function showMsg(msg){ tip.innerText = msg; } } function closeUI() { const e = document.getElementById('huoxing_ck_panel_2024'); if(e) e.remove(); const m = document.getElementById('huoxing_ck_mask_2024'); if(m) m.remove(); } // 获取当前全cookie串 function getAllCookieString(){ return document.cookie || ''; } // 一键复制文本到剪贴板 function copyToClipboard(str){ if(navigator.clipboard){ navigator.clipboard.writeText(str); } else { // 老浏览器降级 const t = document.createElement("textarea"); t.value = str; document.body.appendChild(t); t.select(); document.execCommand('copy'); document.body.removeChild(t); } } // 智能注入cookie function injectCookieSmart(cookieStr) { const arr = cookieStr.split(";").map(x => x.trim()).filter(x => x && x.includes("=")); let cnt = 0; const host = window.location.hostname; const idx = host.indexOf(".baidu.com"); let currentDomain = ""; if(idx >= 0){ currentDomain = host.substring(idx - (host.charAt(idx-1)==='.'?1:0)); } else { currentDomain = host; } for (let kv of arr) { let [k, v] = kv.split("="); k = k.trim(); v = v.trim(); if (k && v !== undefined) { document.cookie = `${k}=${v}; path=/; domain=.${host};`; if(currentDomain && '.'+currentDomain !== '.'+host){ document.cookie = `${k}=${v}; path=/; domain=${currentDomain};`; } cnt++; } } return cnt; } // 清空当前域下所有Cookie(主流兼容写法) function clearAllCookiesSmart(){ const cookies = document.cookie ? document.cookie.split(';') : []; const host = window.location.hostname; const idx = host.indexOf(".baidu.com"); let currentDomain = ""; if(idx >= 0){ currentDomain = host.substring(idx - (host.charAt(idx-1)==='.'?1:0)); } else { currentDomain = host; } for(let c of cookies){ let eq = c.indexOf('='); if(eq < 0) continue; let name = c.substr(0, eq).trim(); // 当前完整host document.cookie = `${name}=;expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/; domain=.${host};`; // .baidu.com 或 tieba.baidu.com if(currentDomain && '.'+currentDomain !== '.'+host){ document.cookie = `${name}=;expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/; domain=${currentDomain};`; } } } // 快捷键 Alt+Q 唤出主界面 document.addEventListener('keydown', function(e){ if(e.altKey && e.key === 'q'){ e.preventDefault(); createUI(); } }); // 页加载自动插悬浮logo window.addEventListener('load', ()=>{ setTimeout(createFloatLogo,600); }); // ============ 接码API终极优化版(全屏,函数封装) ============ function showApiChecker() { if(document.getElementById('api_checker_fullscreen_box')) { document.getElementById('api_checker_fullscreen_box').style.display = 'block'; return; } // --------- 全屏主界面 --------- let fullscreenBox = document.createElement("div"); fullscreenBox.id = "api_checker_fullscreen_box"; fullscreenBox.style.display = 'block'; const filterHtml = ` <label style="margin-right:12px;"><input type="checkbox" class="filter_check" value="gt35" checked> 超过35天</label> <label style="margin-right:12px;"><input type="checkbox" class="filter_check" value="lt35" checked> 小于35天</label> <label style="margin-right:12px;"><input type="checkbox" class="filter_check" value="expired" checked> 已经过期</label> `; fullscreenBox.innerHTML = ` <div id="api_checker_close" style="position:absolute;top:12px;right:24px;font-size:30px;color:#888;cursor:pointer;z-index:100001;">×</div> <div style="display:flex;height:100vh;width:100vw;"> <!-- 左栏 --> <div style="flex:1.1;padding:36px 20px 20px 36px;background:#f5f6fa;box-sizing:border-box;display:flex;flex-direction:column;"> <textarea id="my_links" rows="18" style="width:100%;resize:vertical;min-height:160px;max-height:60vh;font-size:16px;" placeholder="粘贴你的多行文本"></textarea> <div id="links_count_info" style="margin:10px 0 4px 2px;color:#666;">共 0 个账号</div> <button id="check_time_btn" style="padding:7px 18px;border-radius:6px;background:#3271ae;color:#fff;font-size:17px;border:none;cursor:pointer;margin-bottom:6px;margin-top:6px;">检测时间</button> <div style="font-size:13px;line-height:1.6;color:#aaa;"> 请将待检测的账号信息粘贴于此,一行一个。支持----分隔的长行,会自动提取每行中的接口链接。 </div> </div> <!-- 右栏 --> <div style="flex:2.5;background:#fff;padding:36px 32px 20px 16px;overflow-y:auto;display:flex;flex-direction:column;"> <div style="margin-bottom:14px;"> <span style="font-weight:bold;font-size:17px;color:#555">筛选:</span> <span id="result_filter_area">${filterHtml}</span> <button id="copy_filtered_btn" style="margin-left:28px;padding:6px 15px 6px 11px;border-radius:5px;background:#3271ae;color:#fff;font-size:15px;border:none;cursor:pointer;"><span style="font-size:15px">📋</span> 批量复制筛选结果</button> </div> <div id="result_box" style="font-size:16px;flex:1;"></div> <div style="margin:14px 0 0 0;text-align:right"> <button id="copy_all_btn" style="padding:7px 17px 7px 13px;border-radius:7px;background:#2ecc71;color:#fff;font-size:16px;border:none;cursor:pointer;"><span style="font-size:17px">📋</span> 一键复制全部原始行</button> </div> </div> </div> `; Object.assign(fullscreenBox.style, { position:'fixed', left:'0', top:'0', width:'100vw', height:'100vh', background:'#2228f019', zIndex:100000, transition:'all .3s' }); document.body.appendChild(fullscreenBox); // 显示/隐藏逻辑 document.getElementById('api_checker_close').onclick = function() { fullscreenBox.style.display = 'none'; }; // 动态统计数量 function updateCountInfo() { let value = document.getElementById('my_links').value.trim(); let lines = value ? value.split('\n') : []; let count = 0; for(let line of lines){ if(extractUrl(line)) count++; } document.getElementById('links_count_info').textContent = `共 ${count} 个账号`; } document.getElementById('my_links').addEventListener('input', updateCountInfo); // --------- 解析URL函数 --------- function extractUrl(row){ let match = row.match(/https?:\/\/.*?(?=;|,|\s|----|$)/i); return match ? match[0] : null; } function extractName(row){ const reg = /^([^-\s]{1,40})----[^-]+----[^-]+----https?:\/\//; let m = row.match(reg); return m ? m[1] : ''; } let resultsArr = []; document.getElementById('check_time_btn').onclick = function(){ let rows = document.getElementById('my_links').value.trim().split('\n'); let resultBox = document.getElementById('result_box'); resultBox.innerHTML = ''; resultsArr = []; let total = 0; let urlRows = []; for(let row of rows) { let url = extractUrl(row); if(url) urlRows.push({row,url}); } total = urlRows.length; updateCountInfo(); if(total === 0) { resultBox.innerHTML = `<div style='color:#aa3434'>未识别到任何有效链接!</div>`; return; } resultsArr.length = 0; urlRows.forEach(({row,url},idx)=>{ let entryDiv = document.createElement('div'); entryDiv.style.marginBottom = '14px'; entryDiv.style.padding = '9px 11px 10px 11px'; entryDiv.style.border = '1px solid #eee'; entryDiv.style.borderRadius = '7px'; entryDiv.style.background = idx%2===0?'#fafcff':'#f5f7fd'; entryDiv.style.position = 'relative'; resultBox.appendChild(entryDiv); GM_xmlhttpRequest({ method: "GET", url: url, timeout:15000, onload: function(response) { let dateMatch = response.responseText.match(/\d{4}-\d{2}-\d{2}( \d{2}:\d{2}:\d{2})?/); let name = extractName(row); let statusType = "", dayDiff = null, stateTxt='', color='', bg=''; if(dateMatch){ let dateStr = dateMatch[0]; let date; if(dateStr.length > 10){ date = new Date(dateStr.replace(/-/g,'/')); }else{ date = new Date(dateStr.replace(/-/g,'/')); } if(isNaN(date.getTime())){ entryDiv.innerHTML = ` ${name ? `<span style="font-size:17px;color:#2980b9;font-weight:bold;padding-right:10px;">${name}</span>` : ''} <a href="${url}" target="_blank" style="color:#3271ae;text-decoration:underline">${url}</a><br> <span style="color:#e67e22;line-height:1.7">返回内容:${response.responseText}<span style="color:#c0392b;">(无法解析日期)</span></span> `; addCopyBtn(entryDiv, row); resultsArr.push({ row, name, url, date:null, dayDiff:null, statusType:'nodate', entryDiv }); return; } let now = new Date(); dayDiff = Math.floor((date.setHours(0,0,0,0) - now.setHours(0,0,0,0))/(1000*60*60*24)); if(dayDiff < 0){ statusType = "expired"; stateTxt = `<span style="color:#c0392b;font-weight:bold;">已过期${-dayDiff}天</span>`; color = "#c0392b"; bg = "#ffeae8"; } else if(dayDiff < 35){ statusType = "lt35"; stateTxt = `<span style="color:#f39c12;font-weight:bold;">剩余${dayDiff}天</span>`; color = "#f39c12"; bg = "#fffaea"; } else { statusType = "gt35"; stateTxt = `<span style="color:#27ae60;font-weight:bold;">剩余${dayDiff}天</span>`; color = "#27ae60"; bg = "#eafded"; } entryDiv.style.background = bg; entryDiv.innerHTML = ` ${name ? `<span style="font-size:17px;color:#2980b9;font-weight:bold;padding-right:10px;">${name}</span>` : ''} <a href="${url}" target="_blank" style="color:#3271ae;text-decoration:underline">${url}</a><br> 返回时间:<span style="color:${color};font-weight:bold;">${dateStr}</span> (${stateTxt}) `; addCopyBtn(entryDiv, row); resultsArr.push({ row, name, url, date: dateStr, dayDiff, statusType, entryDiv }); }else{ entryDiv.innerHTML = ` ${name ? `<span style="font-size:17px;color:#2980b9;font-weight:bold;padding-right:10px;">${name}</span>` : ''} <a href="${url}" target="_blank" style="color:#3271ae;text-decoration:underline">${url}</a><br> <span style="color:#e67e22;line-height:1.7">返回内容:${response.responseText}<span style="color:#c0392b;">(未找到日期)</span></span> `; addCopyBtn(entryDiv, row); resultsArr.push({ row, name, url, date:null, dayDiff:null, statusType:'nodate', entryDiv }); } }, ontimeout: function(){ entryDiv.innerHTML = `${name ? `<span style="font-size:17px;color:#2980b9;font-weight:bold;padding-right:10px;">${name}</span>` : ''} <a href="${url}" target="_blank" style="color:#3271ae;text-decoration:underline">${url}</a> <div style="color:#c0392b;">请求超时</div>`; addCopyBtn(entryDiv, row); resultsArr.push({ row, name, url, date:null, dayDiff:null, statusType:'nodate', entryDiv }); }, onerror: function(){ entryDiv.innerHTML = `${name ? `<span style="font-size:17px;color:#2980b9;font-weight:bold;padding-right:10px;">${name}</span>` : ''} <a href="${url}" target="_blank" style="color:#3271ae;text-decoration:underline">${url}</a> <div style="color:#c0392b;">请求失败</div>`; addCopyBtn(entryDiv, row); resultsArr.push({ row, name, url, date:null, dayDiff:null, statusType:'nodate', entryDiv }); } }); }); }; function addCopyBtn(div, row) { let btn = document.createElement('button'); btn.textContent = '复制'; Object.assign(btn.style, { position:'absolute',top:'8px',right:'12px',padding:'2px 10px',border:'1px solid #bbb',borderRadius:'5px',background:'#f7f7fc',color:'#444',fontSize:'14px',cursor:'pointer' }); btn.onclick = function(e){ e.stopPropagation(); e.preventDefault(); if(typeof GM_setClipboard === 'function'){ GM_setClipboard(row); }else{ copyToClipboardFallback(row); } btn.textContent = '已复制!'; setTimeout(()=>{btn.textContent = '复制'},1100); }; div.appendChild(btn); } function copyToClipboardFallback(text) { let ta = document.createElement('textarea'); ta.value = text; document.body.appendChild(ta); ta.select(); document.execCommand('copy'); document.body.removeChild(ta); } document.getElementById('copy_filtered_btn').onclick = function(){ let checked = Array.from(document.querySelectorAll('.filter_check')).filter(el=>el.checked).map(el=>el.value); if(resultsArr.length === 0){ alert('请先检测数据'); return; } let outLines = []; for(let item of resultsArr){ if(checked.includes(item.statusType)){ outLines.push(item.row); } } if(outLines.length === 0){ alert('没有符合条件的数据'); return; } let content = outLines.join('\n'); if(typeof GM_setClipboard === 'function'){ GM_setClipboard(content); }else{ copyToClipboardFallback(content); } this.textContent = "已复制!"; setTimeout(()=>{this.textContent='📋 批量复制筛选结果'},1200); }; document.getElementById('copy_all_btn').onclick = function(){ let val = document.getElementById('my_links').value.trim(); if(val){ if(typeof GM_setClipboard === 'function'){ GM_setClipboard(val); }else{ copyToClipboardFallback(val); } this.textContent = '已复制!'; setTimeout(()=>{this.textContent='📋 一键复制全部原始行'},1300); } }; document.getElementById('result_filter_area').onclick = function(e){ if(e.target.classList.contains('filter_check')){ // 可扩展自动刷新 } }; } // ========== 账号去重小工具弹窗 ========== function showDedupTool() { if(document.getElementById('accountDedupTool')) return; const FIELDS = [ {key:'account', name:'账号'}, {key:'password', name:'密码'}, {key:'card', name:'卡密'}, {key:'api', name:'API'}, {key:'ck', name:'CK'} ]; // 主面板 const overlay = document.createElement('div'); overlay.id = 'accountDedupTool'; Object.assign(overlay.style, { position: 'fixed', top: 0, left: 0, right: 0, bottom: 0, background: '#fff', zIndex: 2147483648, display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center' }); // 标题和关闭按钮 const header = document.createElement('div'); header.innerHTML = '<strong style="font-size:22px;color:#333;">账号去重小工具</strong>'; header.style.marginBottom = '10px'; const closeBtn = document.createElement('span'); closeBtn.textContent = '✖'; Object.assign(closeBtn.style, { position: 'absolute', top: '20px', right: '40px', fontSize: '24px', color: '#888', cursor: 'pointer', zIndex: 2147483649 }); closeBtn.onclick = () => overlay.remove(); overlay.appendChild(closeBtn); // 勾选区域 const fieldSelectArea = document.createElement('div'); fieldSelectArea.style.margin = '0 0 16px 0'; fieldSelectArea.style.textAlign = 'left'; fieldSelectArea.style.width = "80vw"; fieldSelectArea.style.maxWidth = "1200px"; let fieldCheckboxes = {}; FIELDS.forEach(field=>{ const label = document.createElement('label'); label.style.marginRight = '24px'; const cb = document.createElement('input'); cb.type = "checkbox"; cb.checked = true; cb.value = field.key; fieldCheckboxes[field.key] = cb; label.appendChild(cb); label.appendChild(document.createTextNode(' ' + field.name)); fieldSelectArea.appendChild(label); }); // 输入包裹区 const wrap = document.createElement('div'); wrap.style.position = 'relative'; wrap.style.width = '80vw'; wrap.style.maxWidth = '1200px'; wrap.style.height = '55vh'; wrap.style.marginBottom = '18px'; // textarea 显示输入 const textarea = document.createElement('textarea'); Object.assign(textarea.style, { width: '100%', height: '100%', fontSize: '17px', border: '1px solid #ccc', borderRadius: '6px', padding: '10px', background: '#fff', color: '#222', resize: 'none', outline: 'none', overflowY: 'auto', boxSizing: 'border-box', position: 'absolute', top: 0, left: 0, zIndex: 2, textAlign: 'left' }); textarea.setAttribute('placeholder', '一行一个,如:22msId3y113na----jt522.qrj----cjn03iduyi1clomk----https://abg.yunqi6.com/new_get_code##JBBKM##cjn03iduyi1clomk----'); // 预览(红字显示第二次及以后) const previewDiv = document.createElement('div'); Object.assign(previewDiv.style, { width: '100%', height: '100%', fontSize: '17px', padding: '10px', whiteSpace: 'pre-wrap', wordBreak: 'break-all', background: '#fff', color: '#222', borderRadius: '6px', border: '1px solid #ccc', boxSizing: 'border-box', pointerEvents: 'none', position: 'absolute', top: 0, left: 0, zIndex: 1, textAlign: 'left', overflowY: 'auto', }); wrap.appendChild(previewDiv); wrap.appendChild(textarea); // 字段提取,为一条数据生成数组 function splitFields(line) { let arr = line.split('----'); while(arr.length<FIELDS.length) arr.push(''); if(arr.length>FIELDS.length){ arr[FIELDS.length-1] = arr.slice(FIELDS.length-1).join('----'); arr = arr.slice(0,FIELDS.length); } return arr; } // 把fields数组根据勾选重组为字符串(去掉两头多余----) function joinFields(arr, selectedArr) { let out = []; for(let i=0;i<FIELDS.length;++i){ if(selectedArr[i]) out.push((arr[i]||'').trim()); } while(out.length && !out[out.length-1]) out.pop(); return out.join('----'); } // 获取当前勾选的字段索引列表 function getSelectedFlags() { return FIELDS.map(f=>fieldCheckboxes[f.key].checked); } // 通用处理函数 function processLines(rawText) { const lines = rawText.split('\n'); let accCount = new Map(); let accFirstIdx = new Map(); let trimmedFieldArrs = []; for(let i=0; i<lines.length; ++i){ let line = lines[i].trim(); if(!line) { trimmedFieldArrs.push(null); continue; } let fields = splitFields(line); trimmedFieldArrs.push(fields); let acc = (fields[0]||'').trim(); accCount.set(acc, (accCount.get(acc)||0)+1); if(!accFirstIdx.has(acc)) accFirstIdx.set(acc,i); } return {lines, accCount, accFirstIdx, trimmedFieldArrs}; } // 让textarea滚动时预览区同步 textarea.addEventListener('scroll', ()=>{ previewDiv.scrollTop = textarea.scrollTop; previewDiv.scrollLeft = textarea.scrollLeft; }); // 实时渲染高亮重复行(第二次及以后出现的账号,文字变红), 并只显示勾选字段 function renderHighlight() { previewDiv.style.height = textarea.clientHeight+"px"; previewDiv.style.width = textarea.clientWidth+"px"; const text = textarea.value; const selectedFlags = getSelectedFlags(); const {lines, accCount, trimmedFieldArrs} = processLines(text); let accSeen = new Map(); let html = ''; for(let i=0;i<lines.length;++i){ let line = lines[i]; if(!trimmedFieldArrs[i]) { html += '<br/>'; continue; } let fields = trimmedFieldArrs[i]; let acc = (fields[0]||'').trim(); let showLine = joinFields(fields,selectedFlags); if(!accSeen.has(acc)) { accSeen.set(acc,1); html += `<span>${escapeHtml(showLine)}</span><br/>`; } else { html += `<span style="color:#ff3232">${escapeHtml(showLine)}</span><br/>`; } } html = html.replace(/(<br\/>)+$/,'<br/>'); previewDiv.innerHTML = html; } textarea.addEventListener('input',renderHighlight); Object.values(fieldCheckboxes).forEach(cb=>cb.onchange=renderHighlight); setTimeout(renderHighlight,100); // 四个按钮 const btnCopyUnique = makeButton('复制不重复行', '#388e3c'); btnCopyUnique.onclick = () => { const selectedFlags = getSelectedFlags(); const {lines, accFirstIdx, trimmedFieldArrs} = processLines(textarea.value); let res = []; for(let [acc, idx] of accFirstIdx.entries()){ if(trimmedFieldArrs[idx]){ let showLine = joinFields(trimmedFieldArrs[idx], selectedFlags); if(showLine) res.push(showLine); } } if(res.length===0){alert('没有可复制的数据');return;} if(typeof GM_setClipboard === 'function') GM_setClipboard(res.join('\n')); else copyToClipboard(res.join('\n')); alert(`已复制${res.length}行(每个账号只留第一次出现)`); }; const btnCopyRepeat = makeButton('复制重复行', '#fbc02d'); btnCopyRepeat.onclick = () => { const selectedFlags = getSelectedFlags(); const {lines, trimmedFieldArrs} = processLines(textarea.value); let accSeen = new Map(), repeatRows = []; for(let i=0;i<lines.length;++i){ if(!trimmedFieldArrs[i]) continue; let fields = trimmedFieldArrs[i]; let acc = (fields[0]||'').trim(); if(!accSeen.has(acc)) { accSeen.set(acc,1); } else { let showLine = joinFields(fields, selectedFlags); if(showLine) repeatRows.push(showLine); } } if(repeatRows.length===0){alert('没有重复行');return;} if(typeof GM_setClipboard === 'function') GM_setClipboard(repeatRows.join('\n')); else copyToClipboard(repeatRows.join('\n')); alert(`已复制${repeatRows.length}条重复行(只包含第2次及以后,且仅勾选字段)`); }; const btnRemoveUnique = makeButton('清理不重复行', '#e53935'); btnRemoveUnique.onclick = () => { const selectedFlags = getSelectedFlags(); const {accCount, accFirstIdx, trimmedFieldArrs} = processLines(textarea.value); let res = []; for(let [acc, idx] of accFirstIdx.entries()){ if(accCount.get(acc) > 1 && trimmedFieldArrs[idx]){ let showLine = joinFields(trimmedFieldArrs[idx], selectedFlags); if(showLine) res.push(showLine); } } textarea.value = res.join('\n'); renderHighlight(); alert(`已清理,仅保留${res.length}个重复账号的第一行(单独账号已全部删除),且仅保留勾选字段`); }; const btnRemoveRepeat = makeButton('删除重复行', '#1976d2'); btnRemoveRepeat.onclick = () => { const selectedFlags = getSelectedFlags(); const {lines, trimmedFieldArrs} = processLines(textarea.value); let accSeen = new Map(), keptRows = []; for(let i=0;i<lines.length;++i){ if(!trimmedFieldArrs[i]) continue; let fields = trimmedFieldArrs[i]; let acc = (fields[0]||'').trim(); if(!accSeen.has(acc)) { accSeen.set(acc,1); let showLine = joinFields(fields, selectedFlags); if(showLine) keptRows.push(showLine); } } textarea.value = keptRows.join('\n'); renderHighlight(); alert(`已删除所有重复行,只保留每个账号第一次出现和唯一账号,且仅保留勾选字段`); }; function makeButton(txt, bg) { const btn = document.createElement('button'); btn.textContent = txt; Object.assign(btn.style, { margin: '0 14px 0 0', padding: '12px 22px', fontSize: '16px', border: 'none', borderRadius: '5px', background: bg || '#2e7d32', color: '#fff', cursor: 'pointer' }); btn.onmouseover = () => btn.style.background='#1565c0'; btn.onmouseleave = () => btn.style.background=bg||'#2e7d32'; return btn; } function escapeHtml(str) { return str.replace(/[&<>\"]/g, c=>({'&':'&','<':'<','>':'>','"':'"'}[c])); } const btnBox = document.createElement('div'); btnBox.appendChild(btnCopyUnique); btnBox.appendChild(btnCopyRepeat); btnBox.appendChild(btnRemoveUnique); btnBox.appendChild(btnRemoveRepeat); btnBox.style.margin = '25px 0 0 0'; overlay.appendChild(header); overlay.appendChild(fieldSelectArea); overlay.appendChild(wrap); overlay.appendChild(btnBox); document.body.appendChild(overlay); window.addEventListener('keydown', _escClose); function _escClose(e){ if(e.key==="Escape"){ try{overlay.remove()}catch(_){} window.removeEventListener('keydown',_escClose) } } } })();