火星工具箱

火星扫码系统出品:百度系全站可拖拽悬浮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=>({'&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;'}[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)
            }
        }
    }

})();