Greasy Fork is available in English.

Bilibili Cookie Getter

获取哔哩哔哩网站的cookie

질문, 리뷰하거나, 이 스크립트를 신고하세요.
// ==UserScript==
// @name         Bilibili Cookie Getter
// @namespace    http://tampermonkey.net/
// @version      1.6
// @description  获取哔哩哔哩网站的cookie
// @author       Your name
// @match        *://*.bilibili.com/*
// @grant        GM_setClipboard
// @grant        GM_notification
// @grant        GM_cookie
// @grant        GM.cookie
// @grant        GM_xmlhttpRequest
// @grant        GM_getValue
// @grant        GM_setValue
// @grant        unsafeWindow
// @connect      *
// @run-at       document-start
// ==/UserScript==

(function() {
    'use strict';

    // 重要cookie列表
    const IMPORTANT_COOKIES = [
        'DedeUserID',
        'bili_jct',
        'SESSDATA',
        'bili_ticket',
        'sid'
    ];

    // 新增:指定的cookie
    const SPECIFIED_COOKIE = 'single_unread';

    // 格式化cookie字符串
    function formatCookies(cookieStr) {
        const cookieMap = new Map();
        cookieStr.split(';').forEach(cookie => {
            const [key, value] = cookie.trim().split('=');
            cookieMap.set(key, value);
        });

        // 首先添加��cookie
        let result = '// 重要Cookie:\n';
        IMPORTANT_COOKIES.forEach(key => {
            if (cookieMap.has(key)) {
                result += `${key}=${cookieMap.get(key)};\n`;
                cookieMap.delete(key);
            }
        });

        // 添加其他cookie
        result += '\n// 其他Cookie:\n';
        cookieMap.forEach((value, key) => {
            result += `${key}=${value};\n`;
        });

        return result;
    }

    // 只获取重要cookie
    function getImportantCookies(cookieStr) {
        const cookieMap = new Map();
        cookieStr.split(';').forEach(cookie => {
            const [key, value] = cookie.trim().split('=');
            if (IMPORTANT_COOKIES.includes(key)) {
                cookieMap.set(key, value);
            }
        });

        return Array.from(cookieMap)
            .map(([key, value]) => `${key}=${value}`)
            .join(';\n');
    }

    // 添加常量定义
    const MAX_RETRIES = 3;
    const MAX_CONCURRENT = 5;
    const COOKIE_DOMAINS = [
        'bilibili.com',
        '.bilibili.com',
        'www.bilibili.com',
        'api.bilibili.com',
        'passport.bilibili.com'
    ];

    // 修改 fetchWithRetry 函数
    async function fetchWithRetry(endpoint, retryCount = 0) {
        try {
            const response = await new Promise((resolve, reject) => {
                const requestOptions = {
                    method: endpoint.method,
                    url: endpoint.url,
                    headers: {
                        'User-Agent': navigator.userAgent,
                        'Cookie': document.cookie,
                        'Referer': 'https://www.bilibili.com',
                        'Origin': 'https://www.bilibili.com',
                        'Accept': 'application/json, text/plain, */*',
                        'Connection': 'keep-alive',
                        'Sec-Fetch-Site': 'same-site',
                        'Sec-Fetch-Mode': 'cors',
                        'Sec-Fetch-Dest': 'empty',
                        'X-Requested-With': 'XMLHttpRequest',
                        'Accept-Language': 'zh-CN,zh;q=0.9,en;q=0.8',
                        'Accept-Encoding': 'gzip, deflate, br',
                        // 添加更多请求头
                        'Cache-Control': 'no-cache',
                        'Pragma': 'no-cache',
                        'X-CSRF-TOKEN': document.cookie.match(/bili_jct=([^;]+)/)?.[1] || '',
                        'X-Requested-With': 'XMLHttpRequest'
                    },
                    withCredentials: true,
                    timeout: 5000,
                    anonymous: false,
                    onload: resolve,
                    onerror: reject,
                    // 添加更多选项
                    nocache: true,
                    revalidate: true
                };

                // 添加特定的请求头
                if (endpoint.headers) {
                    Object.assign(requestOptions.headers, endpoint.headers);
                }

                GM_xmlhttpRequest(requestOptions);
            });

            return response;
        } catch (error) {
            if (retryCount < MAX_RETRIES) {
                console.log(`重试请求 ${endpoint.url} (${retryCount + 1}/${MAX_RETRIES})`);
                await new Promise(resolve => setTimeout(resolve, 1000 * (retryCount + 1)));
                return fetchWithRetry(endpoint, retryCount + 1);
            }
            throw error;
        }
    }

    // 添加新的cookie获取函数
    async function getAllDomainCookies() {
        let allCookies = '';

        // 尝试从所有域名获取cookie
        for (const domain of COOKIE_DOMAINS) {
            try {
                if (typeof GM_cookie !== 'undefined') {
                    const cookies = await new Promise((resolve) => {
                        GM_cookie.list({ domain }, (cookies) => resolve(cookies));
                    });

                    if (cookies && cookies.length > 0) {
                        const domainCookies = cookies
                            .map(cookie => `${cookie.name}=${cookie.value}`)
                            .join('; ');
                        allCookies = allCookies ? `${allCookies}; ${domainCookies}` : domainCookies;
                        console.log(`从域名 ${domain} 获取到 ${cookies.length} 个cookie`);
                    }
                }
            } catch (error) {
                console.log(`获取 ${domain} 的cookie失败:`, error);
            }
        }

        return allCookies;
    }

    // 添加新的函数来处理响应
    function processResponse(response) {
        if (!response || !response.responseHeaders) return '';

        let newCookies = '';

        try {
            // 1. 从响应头获取cookie
            const headers = response.responseHeaders.toLowerCase();
            const allHeaders = headers.split('\n');

            // 处理所有可能的cookie头
            const cookieHeaders = allHeaders.filter(h =>
                h.includes('cookie') ||
                h.includes('set-cookie') ||
                h.includes('x-set-cookie')
            );

            if (cookieHeaders.length > 0) {
                newCookies = cookieHeaders
                    .map(header => {
                        const [_, value] = header.split(':', 2);
                        return value ? value.trim() : '';
                    })
                    .filter(Boolean)
                    .join('; ');
            }

            // 2. 从响应体获取cookie
            try {
                const data = JSON.parse(response.responseText);
                if (data && typeof data === 'object') {
                    const extractCookies = (obj, path = '') => {
                        let extracted = '';
                        for (const [key, value] of Object.entries(obj)) {
                            if (typeof value === 'object' && value !== null) {
                                extracted += extractCookies(value, `${path}${key}.`);
                            } else if (
                                (key.toLowerCase().includes('cookie') ||
                                key.toLowerCase().includes('token')) &&
                                typeof value === 'string'
                            ) {
                                console.log(`在路径 ${path}${key} 找到可能的cookie值`);
                                extracted += value + '; ';
                            }
                        }
                        return extracted;
                    };

                    const bodyCookies = extractCookies(data);
                    if (bodyCookies) {
                        newCookies = newCookies ? `${newCookies}; ${bodyCookies}` : bodyCookies;
                    }
                }
            } catch (e) {
                // 忽略JSON解析错误
            }

            return newCookies;
        } catch (error) {
            console.error('处理响应失败:', error);
            return '';
        }
    }

    // 修改 getExtendedCookies 函数
    async function getExtendedCookies() {
        let allCookies = new Set();

        // 1. 获取当前域名的所有cookie
        document.cookie.split(';').forEach(cookie =>
            allCookies.add(cookie.trim())
        );

        // 2. 尝试从所有域名获取cookie
        const domainCookies = await getAllDomainCookies();
        if (domainCookies) {
            domainCookies.split(';').forEach(cookie =>
                allCookies.add(cookie.trim())
            );
        }

        // 3. 尝试从localStorage获取相关信息
        try {
            for (let i = 0; i < localStorage.length; i++) {
                const key = localStorage.key(i);
                if (key.toLowerCase().includes('cookie') ||
                    key.toLowerCase().includes('token') ||
                    key.toLowerCase().includes('auth')) {
                    const value = localStorage.getItem(key);
                    if (value && value.includes('=')) {
                        allCookies.add(value.trim());
                    }
                }
            }
        } catch (e) {
            console.log('localStorage访问失败:', e);
        }

        // 4. 处理所有请求
        const allEndpoints = [
            // 基础API
            { url: 'https://api.bilibili.com/x/web-interface/nav', method: 'GET' },
            { url: 'https://api.bilibili.com/x/web-interface/nav/stat', method: 'GET' },
            // 用户相关
            { url: 'https://api.bilibili.com/x/space/myinfo', method: 'GET' },
            { url: 'https://api.bilibili.com/x/space/acc/info', method: 'GET' },
            // 视频相关
            { url: 'https://api.bilibili.com/x/player/v2', method: 'GET' },
            { url: 'https://api.bilibili.com/x/player/wbi/playurl', method: 'GET' },
            // 直播相关
            { url: 'https://api.live.bilibili.com/xlive/web-room/v1/index/getInfoByUser', method: 'GET' },
            { url: 'https://live.bilibili.com/p/html/live-web-mng/index', method: 'GET' },
            // 消息相关
            { url: 'https://message.bilibili.com/api/notify/query.notify.count.do', method: 'GET' },
            // 动态相关
            { url: 'https://api.vc.bilibili.com/dynamic_svr/v1/dynamic_svr/dynamic_new', method: 'GET' },
            // 特殊请求
            {
                url: 'https://www.bilibili.com/correspond/1',
                method: 'GET',
                headers: { 'X-From-Bili': 'main' }
            },
            {
                url: 'https://api.bilibili.com/x/web-show/res/locs',
                method: 'GET',
                headers: { 'X-From-Bili': 'main' }
            },
            // POST请求
            {
                url: 'https://api.bilibili.com/x/web-interface/nav',
                method: 'POST',
                data: {
                    build: 0,
                    mobi_app: 'web',
                    csrf: document.cookie.match(/bili_jct=([^;]+)/)?.[1] || ''
                }
            },
            {
                url: 'https://api.live.bilibili.com/xlive/web-room/v1/index/getInfoByUser',
                method: 'POST',
                data: {
                    room_id: 0,
                    platform: 'web'
                }
            },
            // 动态资源
            {
                url: 'https://www.bilibili.com/favicon.ico',
                method: 'GET',
                headers: { 'Accept': 'image/webp,*/*' }
            },
            {
                url: 'https://static.hdslb.com/images/favicon.ico',
                method: 'GET',
                headers: { 'Accept': 'image/webp,*/*' }
            }
        ];

        // 添加动态端点
        try {
            const uid = document.cookie.match(/DedeUserID=(\d+)/)?.[1];
            if (uid) {
                allEndpoints.push(
                    { url: `https://api.bilibili.com/x/space/upstat?mid=${uid}`, method: 'GET' },
                    { url: `https://api.bilibili.com/x/relation/stat?vmid=${uid}`, method: 'GET' }
                );
            }
        } catch (error) {
            console.log('获取UID失败:', error);
        }

        // 5. 并发处理请求
        const results = await Promise.allSettled(
            allEndpoints.map(endpoint =>
                endpoint.method !== 'WS' ?
                    fetchWithRetry(endpoint) :
                    Promise.resolve(null)
            )
        );

        // 6. 处理响应
        results.forEach(result => {
            if (result.status === 'fulfilled' && result.value) {
                const cookies = processResponse(result.value);
                if (cookies) {
                    cookies.split(';').forEach(cookie =>
                        allCookies.add(cookie.trim())
                    );
                }
            }
        });

        // 7. 返回去重后的有效cookie
        return Array.from(allCookies)
            .filter(cookie => {
                const [key, value] = cookie.split('=');
                return key && value && !key.includes(' ');
            })
            .join('; ');
    }

    // 修改cookie证和清理函数
    function validateAndCleanCookies(cookies) {
        // 已知的有效cookie名称列表
        const knownCookies = new Set([
            // 用户认证相关
            'DedeUserID', 'DedeUserID__ckMd5', 'bili_jct', 'SESSDATA',
            'bili_ticket', 'bili_ticket_expires', 'sid',
            // 设备和浏览器标识
            'buvid3', 'buvid4', 'buvid_fp', 'buvid_fp_plain',
            '_uuid', 'fingerprint', 'b_lsid', 'b_nut',
            // 功能和设置相关
            'CURRENT_FNVAL', 'CURRENT_QUALITY', 'CURRENT_BLACKGAP',
            'CURRENT_QUALITY_CROSS_PAGE', 'browser_resolution',
            'header_theme_version', 'home_feed_column', 'enable_web_push',
            'go-back-dyn', 'is-2022-channel',
            // 直播相关
            'LIVE_BUVID', 'live_buvid',
            // 播放器相关
            'bp_video_offset', 'bp_t_offset', 'PVID',
            // 其他系统相关
            'rpdid', 'hit-dyn-v2', 'innersign',
            'bmg_af_switch', 'bmg_src_def_domain',
            'dy_spec_agreed', 'b_timer'
        ]);

        // 分割并过滤cookie
        const cookieSet = new Set(
            cookies.split(';')
                .map(cookie => cookie.trim())
                .filter(cookie => {
                    // 基本验证
                    if (!cookie.includes('=')) return false;
                    const [key, value] = cookie.split('=');
                    if (!key || !value) return false;

                    // 清理key和value
                    const cleanKey = key.trim();
                    const cleanValue = value.trim();

                    // 验证规则
                    if (cleanKey.includes(' ') || cleanKey.length > 100) return false;
                    if (cleanValue.length > 1000) return false;
                    if (cleanValue.includes('\n') || cleanValue.includes('\r')) return false;

                    // 保留规则
                    return knownCookies.has(cleanKey) ||
                           /^bp_t_offset_\d+$/.test(cleanKey) ||
                           /^b_(lsid|nut|uid|timer)/.test(cleanKey) ||
                           /^bili_/.test(cleanKey) ||
                           /^SESSDATA$/.test(cleanKey) ||
                           /^_uuid$/.test(cleanKey) ||
                           /^buvid[0-9]?$/.test(cleanKey);
                })
                .map(cookie => {
                    const [key, value] = cookie.split('=');
                    // 允许更多的特殊字符
                    const cleanValue = value.replace(/[^\w\d\-_.%=:]/g, '');
                    return `${key.trim()}=${cleanValue}`;
                })
        );

        // 转换回字符串
        const result = Array.from(cookieSet).join('; ');
        console.log('验证后的cookie数量:', cookieSet.size);
        return result;
    }

    // 修改 forceGetCookies 函数
    async function forceGetCookies() {
        let allCookies = new Set();

        // 等待页面加载完成
        if (document.readyState !== 'complete') {
            await new Promise(resolve => {
                window.addEventListener('load', resolve);
            });
        }

        // 1. 使用多种方法获取原始cookie
        try {
            // 直接获取
            const currentCookie = document.cookie;
            if (currentCookie && typeof currentCookie === 'string') {
                currentCookie.split(';').forEach(cookie =>
                    allCookies.add(cookie.trim())
                );
            }

            // 使用Object.getOwnPropertyDescriptor
            try {
                const cookieDesc = Object.getOwnPropertyDescriptor(Document.prototype, 'cookie') ||
                                  Object.getOwnPropertyDescriptor(HTMLDocument.prototype, 'cookie');
                if (cookieDesc && cookieDesc.get) {
                    const cookieStr = cookieDesc.get.call(document);
                    if (cookieStr && typeof cookieStr === 'string') {
                        cookieStr.split(';').forEach(cookie =>
                            allCookies.add(cookie.trim())
                        );
                    }
                }
            } catch (e) {
                console.log('获取cookie描述符失败:', e);
            }

            // 尝试使用CookieStore API
            if ('cookieStore' in window) {
                try {
                    const cookies = await cookieStore.getAll();
                    cookies.forEach(cookie =>
                        allCookies.add(`${cookie.name}=${cookie.value}`)
                    );
                } catch (e) {
                    console.log('CookieStore API访问失败:', e);
                }
            }

        } catch (e) {
            console.log('获取原始cookie失败:', e);
        }

        // 2. 注入cookie监听器
        try {
            const originalSetCookie = document.__lookupSetter__('cookie');
            document.__defineSetter__('cookie', function(val) {
                allCookies.add(val.trim());
                return originalSetCookie.call(document, val);
            });
        } catch (e) {
            console.log('注入cookie监听器失败:', e);
        }

        // 3. 强制触发cookie设置
        try {
            // 触发页面重新加载cookie
            const tempIframe = document.createElement('iframe');
            tempIframe.style.display = 'none';
            tempIframe.src = 'https://www.bilibili.com/';
            document.body.appendChild(tempIframe);
            setTimeout(() => tempIframe.remove(), 1000);

            // 触发API请求
            fetch('https://api.bilibili.com/x/web-interface/nav', {
                credentials: 'include',
                mode: 'cors'
            }).catch(() => {});
        } catch (e) {
            console.log('触发cookie设置失败:', e);
        }

        // 4. 使用特殊的请求头强制获取
        const specialHeaders = {
            'X-Override-Cookie': document.cookie,
            'X-Original-Cookie': document.cookie,
            'Cookie-Debug': 'true',
            'X-Cookie-Debug': 'true'
        };

        // 5. 发送特殊请求
        const urls = [
            'https://api.bilibili.com/x/web-interface/nav',
            'https://passport.bilibili.com/x/passport-login/web/cookie/info',
            'https://www.bilibili.com/'
        ];

        for (const url of urls) {
            try {
                const response = await fetch(url, {
                    credentials: 'include',
                    mode: 'cors',
                    headers: specialHeaders
                });
                const cookies = response.headers.get('set-cookie');
                if (cookies) {
                    cookies.split(',').forEach(cookie =>
                        allCookies.add(cookie.split(';')[0].trim())
                    );
                }
            } catch (e) {
                console.log(`请求 ${url} 失败:`, e);
            }
        }

        // 6. 等待一段时间以确保所有cookie都被设置
        await new Promise(resolve => setTimeout(resolve, 1000));

        // 7. 最后一次获取当前cookie
        document.cookie.split(';').forEach(cookie =>
            allCookies.add(cookie.trim())
        );

        // 8. 返回验证后的cookie
        return validateAndCleanCookies(Array.from(allCookies).join('; '));
    }

    // 修改 getSpecifiedCookie 函数
    async function getSpecifiedCookie() {
        try {
            const allCookies = new Set();

            // 1. 劫持原生API
            const originalDescriptor = Object.getOwnPropertyDescriptor(Document.prototype, 'cookie');
            const originalGetter = originalDescriptor.get;
            const originalSetter = originalDescriptor.set;

            // 2. 注入cookie监听器
            Object.defineProperty(Document.prototype, 'cookie', {
                get: function() {
                    const value = originalGetter.call(this);
                    if (value) allCookies.add(value);
                    return value;
                },
                set: function(value) {
                    if (value) allCookies.add(value);
                    return originalSetter.call(this, value);
                },
                configurable: true
            });

            // 3. 使用GM_cookie获取所有域名的cookie
            const domains = [
                'bilibili.com',
                '.bilibili.com',
                'www.bilibili.com',
                'api.bilibili.com',
                'passport.bilibili.com',
                'live.bilibili.com',
                't.bilibili.com',
                'space.bilibili.com',
                'message.bilibili.com',
                'api.vc.bilibili.com'
            ];

            for (const domain of domains) {
                try {
                    const cookies = await new Promise((resolve) => {
                        GM_cookie.list({ domain }, (cookies) => resolve(cookies));
                    });

                    if (cookies && cookies.length > 0) {
                        cookies.forEach(cookie =>
                            allCookies.add(`${cookie.name}=${cookie.value}`)
                        );
                    }
                } catch (e) {}
            }

            // 4. 发送特殊请求
            const specialHeaders = {
                'Accept': 'application/json, text/plain, */*',
                'X-Requested-With': 'XMLHttpRequest',
                'X-CSRF-TOKEN': document.cookie.match(/bili_jct=([^;]+)/)?.[1] || '',
                'Cookie': document.cookie,
                'X-Cookie': document.cookie,
                'X-Original-Cookie': document.cookie,
                'X-Debug-Cookie': document.cookie,
                'X-Cookie-Debug': 'true',
                // 添加更多特殊头
                'X-Cookie-Override': document.cookie,
                'X-Cookie-All': document.cookie,
                'X-Cookie-Raw': document.cookie,
                'X-Cookie-Full': document.cookie
            };

            const urls = [
                'https://api.bilibili.com/x/web-interface/nav',
                'https://passport.bilibili.com/x/passport-login/web/cookie/info',
                'https://api.bilibili.com/x/web-interface/nav/stat',
                'https://api.bilibili.com/x/player/v2',
                'https://api.live.bilibili.com/xlive/web-room/v1/index/getInfoByUser',
                // 添加更多端点
                'https://api.bilibili.com/x/web-interface/wbi/index',
                'https://api.bilibili.com/x/space/wbi/acc/info',
                'https://api.bilibili.com/x/web-interface/search/default',
                'https://api.bilibili.com/x/web-interface/zone',
                'https://api.bilibili.com/x/web-show/res/locs'
            ];

            for (const url of urls) {
                try {
                    const response = await fetch(url, {
                        credentials: 'include',
                        headers: specialHeaders
                    });

                    const setCookie = response.headers.get('set-cookie');
                    if (setCookie) {
                        setCookie.split(',').forEach(cookie => {
                            const mainPart = cookie.split(';')[0];
                            if (mainPart) allCookies.add(mainPart.trim());
                        });
                    }
                } catch (e) {}
                await new Promise(resolve => setTimeout(resolve, 100));
            }

            // 5. 恢复原始API
            Object.defineProperty(Document.prototype, 'cookie', originalDescriptor);

            // 6. 返回所有cookie
            return Array.from(allCookies)
                .filter(cookie => {
                    const [key, value] = cookie.split('=');
                    return key && value && !key.includes(' ');
                })
                .join('; ');

        } catch (error) {
            console.error('获取cookie失败:', error);
            return document.cookie;
        }
    }

    // 显示通知
    function showNotification(message) {
        const toast = document.createElement('div');
        toast.style.cssText = `
            position: fixed;
            top: 70px;
            right: 80px;
            background-color: rgba(34, 34, 34, 0.9);
            color: white;
            padding: 10px 20px;
            border-radius: 4px;
            z-index: 999999999;
            font-size: 14px;
            font-family: Arial, sans-serif;
            animation: fadeInOut 4s ease-in-out;
            white-space: pre-line;
        `;

        const style = document.createElement('style');
        style.textContent = `
            @keyframes fadeInOut {
                0% { opacity: 0; transform: translateY(-20px); }
                15% { opacity: 1; transform: translateY(0); }
                85% { opacity: 1; transform: translateY(0); }
                100% { opacity: 0; transform: translateY(-20px); }
            }
        `;
        document.head.appendChild(style);

        toast.textContent = message;
        document.body.appendChild(toast);

        setTimeout(() => {
            toast.remove();
            style.remove();
        }, 5000);
    }

    // 按钮
    function addButtons() {
        const container = document.createElement('div');
        container.style.cssText = `
            position: fixed;
            top: 70px;
            right: 20px;
            display: flex;
            gap: 10px;
            z-index: 999999;
        `;

        // 完整Cookie按钮
        const fullButton = document.createElement('button');
        fullButton.textContent = '获取Cookie';
        fullButton.style.cssText = `
            padding: 8px 16px;
            background: #fb7299;
            color: white;
            border: none;
            border-radius: 4px;
            cursor: pointer;
            font-size: 14px;
            font-weight: bold;
        `;

        // 简易Cookie按钮
        const simpleButton = document.createElement('button');
        simpleButton.textContent = '简易获取';
        simpleButton.style.cssText = `
            padding: 8px 16px;
            background: #00a1d6;
            color: white;
            border: none;
            border-radius: 4px;
            cursor: pointer;
            font-size: 14px;
            font-weight: bold;
        `;

        // 新增:指定Cookie按钮
        const specifiedButton = document.createElement('button');
        specifiedButton.textContent = '获取完整Cookie';
        specifiedButton.style.cssText = `
            padding: 8px 16px;
            background: #6c757d;
            color: white;
            border: none;
            border-radius: 4px;
            cursor: pointer;
            font-size: 14px;
            font-weight: bold;
        `;

        // 添加点击事件
        fullButton.onclick = function() {
            const cookies = formatCookies(document.cookie);
            GM_setClipboard(cookies);
            showNotification('完整Cookie已复制到剪贴板');
            console.log('完整Cookies:\n', cookies);
        };

        simpleButton.onclick = function() {
            const cookies = getImportantCookies(document.cookie);
            GM_setClipboard(cookies);
            showNotification('重要Cookie已复制到剪贴板');
            console.log('要Cookies:\n', cookies);
        };

        specifiedButton.onclick = async function() {
            try {
                specifiedButton.disabled = true;
                specifiedButton.textContent = '获取中...';

                const cookies = await getSpecifiedCookie();
                if (cookies) {
                    GM_setClipboard(cookies);
                    showNotification(`Cookie已复制 (${cookies.length}字符)\n包含 ${cookies.split(';').length} 个cookie`);
                    console.log('获取的Cookie字符串:\n', cookies);
                    console.log(`字符串长度: ${cookies.length}`);
                }
            } catch (error) {
                showNotification('获取Cookie失败: ' + error.message);
                console.error('获取Cookie失败:', error);
            } finally {
                specifiedButton.disabled = false;
                specifiedButton.textContent = '获取完整Cookie';
            }
        };

        container.appendChild(fullButton);
        container.appendChild(simpleButton);
        container.appendChild(specifiedButton);
        document.body.appendChild(container);
    }

    // 添加错误处理函数
    function handleError(error, context) {
        console.error(`[Cookie Getter] ${context}:`, error);
        return null;
    }

    // 修改按钮添加逻辑
    function addButtonsWhenReady() {
        if (!document.body) {
            setTimeout(addButtonsWhenReady, 100);
            return;
        }

        try {
            addButtons();
        } catch (error) {
            handleError(error, '添加按钮失败');
        }
    }

    // 修改初始化调用
    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', addButtonsWhenReady);
    } else {
        addButtonsWhenReady();
    }

    // 添加页面错误监听
    window.addEventListener('error', function(event) {
        handleError(event.error, '页面错误');
    });

    // 添加未处理的Promise错误监听
    window.addEventListener('unhandledrejection', function(event) {
        handleError(event.reason, '未处理的Promise错误');
    });
})();