// ==UserScript== // @name Cookie获取助手 // @namespace http://tampermonkey.net/ // @version 2.2.0 // @description 帮助新手用户获取网站Cookie,仅用于学习和个人使用 // @author Your Name // @match *://*/* // @match about:blank // @match about:newtab // @grant GM_setClipboard // @grant GM_notification // @grant GM_openInTab // @grant GM_cookie // @run-at document-end // ==/UserScript== (function() { 'use strict'; // 免责声明 const DISCLAIMER = ` 【免责声明】 本脚本仅用于学习和个人使用目的,帮助不熟悉技术的用户了解Cookie的获取方式。 - 本脚本不会存储、上传或泄露任何用户数据 - 所有Cookie信息仅在本地显示,不会发送到任何服务器 - 请勿将本脚本用于任何违法违规行为 - 使用本脚本即表示您同意自行承担使用风险 - 请遵守相关网站的服务条款和法律法规 `.trim(); // 平台配置 const PLATFORMS = { xiaohongshu: { name: '小红书', domain: 'xiaohongshu.com', url: 'https://www.xiaohongshu.com', checkLogin: checkXiaohongshuLogin, getCookie: getXiaohongshuCookie, verifyCookie: verifyXiaohongshuCookie, icon: '📕' }, zhihu: { name: '知乎', domain: 'zhihu.com', url: 'https://www.zhihu.com', checkLogin: () => false, // 待实现 getCookie: () => null, verifyCookie: null, icon: '🔵', disabled: true }, douyin: { name: '抖音', domain: 'douyin.com', url: 'https://www.douyin.com', checkLogin: () => false, // 待实现 getCookie: () => null, verifyCookie: null, icon: '🎵', disabled: true }, iqiyi: { name: '爱奇艺', domain: 'iqiyi.com', url: 'https://www.iqiyi.com', checkLogin: () => false, // 待实现 getCookie: () => null, verifyCookie: null, icon: '🎬', disabled: true }, tencent: { name: '腾讯视频', domain: 'v.qq.com', url: 'https://v.qq.com', checkLogin: () => false, // 待实现 getCookie: () => null, verifyCookie: null, icon: '🎥', disabled: true } }; // 检测当前平台 function getCurrentPlatform() { const hostname = window.location.hostname; for (const [key, platform] of Object.entries(PLATFORMS)) { if (hostname.includes(platform.domain)) { return key; } } return null; } // 小红书登录检测(使用页面检测,避开反爬虫) async function checkXiaohongshuLogin() { console.log('[Cookie助手] 开始检测登录状态...'); // 方法1: 检查是否有登录按钮(未登录才有) const loginButtons = document.querySelectorAll('button, a'); let hasLoginButton = false; for (const btn of loginButtons) { const text = btn.textContent.trim(); if (text === '登录' || text === '注册' || text === '登录 / 注册') { hasLoginButton = true; console.log('[Cookie助手] 发现登录按钮:', text); break; } } // 如果有登录按钮,肯定未登录 if (hasLoginButton) { console.log('[Cookie助手] 登录状态: false (发现登录按钮)'); return false; } // 方法2: 检查是否在个人主页 const isUserPage = window.location.pathname.includes('/user/profile'); if (isUserPage) { console.log('[Cookie助手] 登录状态: true (在个人主页)'); return true; } // 方法3: 检查页面标题和内容 const pageTitle = document.title; const bodyText = document.body.textContent; // 如果页面提示需要登录 if (bodyText.includes('登录后推荐更懂你的笔记') || bodyText.includes('扫码登录') || pageTitle.includes('登录')) { console.log('[Cookie助手] 登录状态: false (页面提示登录)'); return false; } // 方法4: 检查是否有用户相关元素 const hasUserElements = document.querySelector('[class*="user-card"]') !== null || document.querySelector('[class*="UserCard"]') !== null || document.querySelector('[data-v-*][class*="avatar"]') !== null; console.log('[Cookie助手] 登录状态:', hasUserElements, '(页面元素检测)'); return hasUserElements; } // 获取小红书Cookie(尝试使用GM_cookie API获取完整Cookie) async function getXiaohongshuCookie() { // 方法1: 尝试使用GM_cookie API(支持获取HttpOnly Cookie) if (typeof GM_cookie !== 'undefined') { try { const cookies = await new Promise((resolve, reject) => { GM_cookie.list({ domain: '.xiaohongshu.com' }, (cookies, error) => { if (error) { reject(error); } else { resolve(cookies); } }); }); if (cookies && cookies.length > 0) { // 将Cookie数组转换为字符串格式 const cookieString = cookies.map(c => `${c.name}=${c.value}`).join('; '); return cookieString; } } catch (error) { console.log('GM_cookie API不可用,使用备用方法'); } } // 方法2: 降级到document.cookie(只能获取非HttpOnly Cookie) const cookies = document.cookie; if (!cookies) { return null; } return cookies; } // 检查Cookie是否完整 function checkCookieComplete(cookies) { // 检查是否包含关键的HttpOnly字段 const hasWebSession = cookies.includes('web_session='); const hasIdToken = cookies.includes('id_token='); const hasAcwTc = cookies.includes('acw_tc='); return { complete: hasWebSession || hasIdToken, missing: [] .concat(!hasWebSession ? ['web_session'] : []) .concat(!hasIdToken ? ['id_token'] : []) .concat(!hasAcwTc ? ['acw_tc'] : []) }; } // 验证小红书Cookie有效性(通过设置Cookie并测试登录) async function verifyXiaohongshuCookie() { try { // 方法1: 尝试调用用户信息API const response = await fetch('https://edith.xiaohongshu.com/api/sns/web/v1/user/selfinfo', { method: 'GET', credentials: 'include', headers: { 'Accept': 'application/json, text/plain, */*', 'Accept-Language': 'zh-CN,zh;q=0.9,en;q=0.8', 'Referer': 'https://www.xiaohongshu.com/', 'User-Agent': navigator.userAgent, 'X-Requested-With': 'XMLHttpRequest' } }); if (response.status === 406) { // 如果遇到406,使用备用验证方法:检查页面元素 return verifyByPageContent(); } if (!response.ok) { return { valid: false, message: `请求失败 (${response.status})`, details: '无法连接到服务器或Cookie已失效' }; } const data = await response.json(); // 检查返回数据 if (data.success && data.data) { return { valid: true, message: 'Cookie有效', details: `用户: ${data.data.nickname || data.data.red_id || '已登录用户'}`, userData: data.data }; } else { return { valid: false, message: 'Cookie无效或已过期', details: data.msg || '请重新登录' }; } } catch (error) { // 如果API调用失败,尝试备用方法 return verifyByPageContent(); } } // 通过设置Cookie并测试登录来验证(最准确的方法) async function testLoginWithCookie(cookieString) { if (typeof GM_cookie === 'undefined') { return { valid: false, message: '不支持Cookie登录测试', details: '您的油猴管理器不支持GM_cookie API,请使用Tampermonkey或Violentmonkey' }; } try { // 解析Cookie字符串 const cookiePairs = cookieString.split(';').map(c => c.trim()); const cookieMap = {}; cookiePairs.forEach(pair => { const [name, ...valueParts] = pair.split('='); if (name) { cookieMap[name.trim()] = valueParts.join('='); } }); // 获取当前域名 const currentDomain = window.location.hostname; // 确定Cookie域名(使用当前域名或其父域名) let cookieDomain = currentDomain; if (currentDomain.includes('xiaohongshu.com')) { // 对于小红书,尝试使用当前完整域名 cookieDomain = currentDomain; } // 设置关键Cookie const criticalCookies = ['web_session', 'a1', 'webId', 'id_token', 'acw_tc', 'xsecappid', 'websectiga', 'sec_poison_id']; let setCount = 0; let failedCookies = []; for (const name of criticalCookies) { if (cookieMap[name]) { try { await new Promise((resolve, reject) => { // 尝试不同的域名设置 const cookieOptions = { name: name, value: cookieMap[name], url: window.location.href, // 使用当前URL而不是domain path: '/', secure: window.location.protocol === 'https:', httpOnly: name === 'web_session' || name === 'id_token' }; GM_cookie.set(cookieOptions, (error) => { if (error) { console.log(`设置Cookie ${name} 失败:`, error); failedCookies.push(name); resolve(); // 继续设置其他Cookie } else { console.log(`设置Cookie ${name} 成功`); setCount++; resolve(); } }); }); } catch (e) { console.log(`设置Cookie ${name} 异常:`, e); failedCookies.push(name); } } } console.log(`成功设置 ${setCount} 个Cookie,失败 ${failedCookies.length} 个`); if (failedCookies.length > 0) { console.log('失败的Cookie:', failedCookies.join(', ')); } if (setCount === 0) { return { valid: false, message: 'Cookie设置失败', details: '未找到关键Cookie字段或全部设置失败。请确保Cookie格式正确。' }; } // 等待Cookie设置生效 await new Promise(resolve => setTimeout(resolve, 1000)); // 测试登录:调用API const response = await fetch('https://edith.xiaohongshu.com/api/sns/web/v1/user/selfinfo', { method: 'GET', credentials: 'include', headers: { 'Accept': 'application/json, text/plain, */*', 'Accept-Language': 'zh-CN,zh;q=0.9,en;q=0.8', 'Referer': 'https://www.xiaohongshu.com/', 'User-Agent': navigator.userAgent, 'X-Requested-With': 'XMLHttpRequest' } }); console.log('API响应状态:', response.status); if (response.status === 406) { // 406错误:反爬虫机制,但Cookie可能已经设置成功 return { valid: true, message: '✅ Cookie已设置!', details: `已成功设置${setCount}个Cookie。由于反爬虫限制,无法通过API验证,但Cookie已生效。页面将在3秒后刷新以确认登录状态。`, needRefresh: true }; } if (response.ok) { const data = await response.json(); console.log('API响应数据:', data); if (data.success && data.data) { return { valid: true, message: '✅ Cookie有效!登录测试成功', details: `已成功使用Cookie登录,用户: ${data.data.nickname || data.data.red_id || '已登录用户'}。页面将在3秒后刷新。`, userData: data.data, needRefresh: true }; } } return { valid: false, message: 'Cookie可能无效', details: `已设置${setCount}个Cookie(失败${failedCookies.length}个),但登录验证失败。Cookie可能已过期或不完整。建议刷新页面后重试。` }; } catch (error) { console.error('登录测试错误:', error); return { valid: false, message: '登录测试失败', details: error.message || '发生未知错误' }; } } // 备用验证方法:通过页面内容验证 function verifyByPageContent() { // 检查Cookie是否存在关键字段 const cookies = document.cookie; const hasWebSession = cookies.includes('web_session='); const hasWebId = cookies.includes('webId='); const hasXsecToken = cookies.includes('xsec_token='); const hasA1 = cookies.includes('a1='); if (!hasWebSession && !hasXsecToken && !hasWebId && !hasA1) { return { valid: false, message: 'Cookie无效', details: '未找到必要的Cookie字段' }; } // 检查页面上是否有登录用户信息 const userAvatar = document.querySelector('.avatar, [class*="avatar"], [class*="Avatar"]'); const userInfo = document.querySelector('.user-info, [class*="user"], [class*="User"]'); const loginBtn = document.querySelector('[class*="login"], [class*="Login"]'); // 如果找到用户头像或用户信息,且没有登录按钮,说明已登录 if ((userAvatar || userInfo) && !loginBtn) { return { valid: true, message: 'Cookie可能有效', details: '检测到登录状态,Cookie包含必要字段。建议在小红书网站测试功能(如点赞、评论)以确认。' }; } // 如果有关键Cookie但无法确认页面状态 return { valid: true, message: 'Cookie包含必要字段', details: '已检测到登录Cookie,但无法完全验证。建议在小红书网站测试功能(如点赞、评论)以确认有效性。' }; } // 创建UI面板 function createPanel() { const panel = document.createElement('div'); panel.id = 'cookie-helper-panel'; panel.innerHTML = `
🍪 Cookie获取助手
⚠️ 免责声明(请先阅读)
${DISCLAIMER}
${Object.entries(PLATFORMS).map(([key, platform]) => `
${platform.icon} ${platform.name} ${platform.disabled ? '即将支持' : ''}
${!platform.disabled ? `` : ''}
`).join('')}
请选择一个平台
`; // 添加样式 const style = document.createElement('style'); style.textContent = ` #cookie-helper-panel { position: fixed; top: 50%; right: 20px; transform: translateY(-50%); width: 360px; max-height: 80vh; background: #ffffff; border-radius: 12px; box-shadow: 0 8px 32px rgba(0, 0, 0, 0.15); z-index: 999999; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; overflow: hidden; display: none; flex-direction: column; } .ch-header { background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; padding: 16px 20px; display: flex; justify-content: space-between; align-items: center; } .ch-title { font-size: 16px; font-weight: 600; } .ch-close { background: rgba(255, 255, 255, 0.2); border: none; color: white; font-size: 24px; width: 32px; height: 32px; border-radius: 50%; cursor: pointer; display: flex; align-items: center; justify-content: center; transition: background 0.2s; } .ch-close:hover { background: rgba(255, 255, 255, 0.3); } .ch-disclaimer { padding: 12px 20px; background: #fff3cd; border-bottom: 1px solid #ffeaa7; } .ch-disclaimer details { cursor: pointer; } .ch-disclaimer summary { font-size: 13px; color: #856404; font-weight: 500; user-select: none; } .ch-disclaimer pre { margin: 10px 0 0 0; font-size: 11px; color: #856404; white-space: pre-wrap; line-height: 1.5; } .ch-platforms { padding: 16px 20px; border-bottom: 1px solid #e9ecef; max-height: 200px; overflow-y: auto; } .ch-platform-item { display: flex; align-items: center; justify-content: space-between; padding: 12px 16px; margin-bottom: 8px; background: #f8f9fa; border-radius: 8px; cursor: pointer; transition: all 0.2s; border: 2px solid transparent; } .ch-platform-info { display: flex; align-items: center; flex: 1; } .ch-platform-item:hover:not(.disabled) { background: #e9ecef; transform: translateX(4px); } .ch-platform-item.active { background: #e7f3ff; border-color: #667eea; } .ch-platform-item.disabled { opacity: 0.5; cursor: not-allowed; } .ch-platform-test-btn { background: #17a2b8; color: white; border: none; padding: 6px 12px; border-radius: 6px; font-size: 12px; font-weight: 500; cursor: pointer; transition: all 0.2s; opacity: 0.8; } .ch-platform-test-btn:hover { opacity: 1; background: #138496; transform: scale(1.05); } .ch-platform-test-btn:active { transform: scale(0.95); } .ch-platform-icon { font-size: 24px; margin-right: 12px; } .ch-platform-name { flex: 1; font-size: 14px; font-weight: 500; } .ch-badge { font-size: 11px; padding: 2px 8px; background: #6c757d; color: white; border-radius: 10px; } .ch-content { padding: 20px; flex: 1; overflow-y: auto; } .ch-status { text-align: center; padding: 20px; color: #6c757d; font-size: 14px; } .ch-status.success { color: #28a745; } .ch-status.error { color: #dc3545; } .ch-actions { text-align: center; margin-top: 16px; display: flex; flex-direction: column; gap: 8px; } .ch-btn { background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; border: none; padding: 12px 32px; border-radius: 8px; font-size: 14px; font-weight: 500; cursor: pointer; transition: transform 0.2s, box-shadow 0.2s; } .ch-btn:hover { transform: translateY(-2px); box-shadow: 0 4px 12px rgba(102, 126, 234, 0.4); } .ch-btn:disabled { background: #6c757d; cursor: not-allowed; transform: none; } .ch-btn-refresh { background: #17a2b8; color: white; border: none; padding: 8px 16px; border-radius: 6px; font-size: 13px; cursor: pointer; transition: background 0.2s; } .ch-btn-refresh:hover { background: #138496; } .ch-result { margin-top: 16px; } .ch-result-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 8px; font-size: 13px; font-weight: 500; color: #495057; } .ch-btn-small { background: #28a745; color: white; border: none; padding: 6px 12px; border-radius: 6px; font-size: 12px; cursor: pointer; transition: background 0.2s; } .ch-btn-small:hover { background: #218838; } .ch-cookie-text { width: 100%; min-height: 120px; max-height: 200px; padding: 12px; border: 1px solid #ced4da; border-radius: 6px; font-size: 12px; font-family: 'Courier New', monospace; resize: vertical; background: #f8f9fa; } .ch-verify-section { margin-top: 12px; display: flex; flex-direction: column; gap: 8px; } .ch-btn-verify { width: 100%; background: #17a2b8; color: white; border: none; padding: 10px 16px; border-radius: 6px; font-size: 13px; font-weight: 500; cursor: pointer; transition: background 0.2s; } .ch-btn-verify:hover { background: #138496; } .ch-btn-verify:disabled { background: #6c757d; cursor: not-allowed; } .ch-btn-login-test { width: 100%; background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%); color: white; border: none; padding: 10px 16px; border-radius: 6px; font-size: 13px; font-weight: 500; cursor: pointer; transition: transform 0.2s, box-shadow 0.2s; } .ch-btn-login-test:hover { transform: translateY(-1px); box-shadow: 0 4px 12px rgba(245, 87, 108, 0.4); } .ch-btn-login-test:disabled { background: #6c757d; cursor: not-allowed; transform: none; } .ch-test-section { margin-top: 12px; } .ch-btn-test { width: 100%; background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%); color: white; border: none; padding: 12px 16px; border-radius: 6px; font-size: 14px; font-weight: 600; cursor: pointer; transition: transform 0.2s, box-shadow 0.2s; margin-bottom: 8px; } .ch-btn-test:hover { transform: translateY(-2px); box-shadow: 0 4px 12px rgba(245, 87, 108, 0.4); } .ch-btn-test:disabled { background: #6c757d; cursor: not-allowed; transform: none; } .ch-test-hint { font-size: 11px; color: #6c757d; text-align: center; line-height: 1.4; } .ch-test-result { margin-top: 12px; padding: 12px; border-radius: 6px; font-size: 13px; line-height: 1.5; } .ch-test-result.success { background: #d4edda; border: 1px solid #c3e6cb; color: #155724; } .ch-test-result.error { background: #f8d7da; border: 1px solid #f5c6cb; color: #721c24; } .ch-test-result .ch-test-title { font-weight: 600; margin-bottom: 4px; } .ch-test-result .ch-test-details { font-size: 12px; opacity: 0.9; } .ch-verify-result { margin-top: 10px; padding: 12px; border-radius: 6px; font-size: 13px; line-height: 1.5; } .ch-verify-result.valid { background: #d4edda; border: 1px solid #c3e6cb; color: #155724; } .ch-verify-result.invalid { background: #f8d7da; border: 1px solid #f5c6cb; color: #721c24; } .ch-verify-result .ch-verify-title { font-weight: 600; margin-bottom: 4px; } .ch-verify-result .ch-verify-details { font-size: 12px; opacity: 0.9; } .ch-cookie-warning { background: #fff3cd; border: 1px solid #ffeaa7; border-radius: 8px; padding: 12px; margin-bottom: 12px; } .ch-warning-title { font-weight: 600; color: #856404; margin-bottom: 8px; font-size: 14px; } .ch-warning-text { font-size: 12px; color: #856404; line-height: 1.6; margin-bottom: 10px; } .ch-btn-tutorial { width: 100%; background: #ffc107; color: #000; border: none; padding: 8px 16px; border-radius: 6px; font-size: 13px; font-weight: 500; cursor: pointer; transition: background 0.2s; } .ch-btn-tutorial:hover { background: #ffb300; } .ch-manual-input-section { margin-top: 12px; } .ch-btn-manual { width: 100%; background: #28a745; color: white; border: none; padding: 10px 16px; border-radius: 6px; font-size: 13px; font-weight: 500; cursor: pointer; transition: background 0.2s; } .ch-btn-manual:hover { background: #218838; } .ch-tutorial { padding: 0; border-top: 1px solid #e9ecef; } .ch-tutorial-header { background: #f8f9fa; padding: 16px 20px; display: flex; justify-content: space-between; align-items: center; border-bottom: 1px solid #e9ecef; } .ch-tutorial-title { font-size: 15px; font-weight: 600; color: #495057; } .ch-close-tutorial { background: rgba(0, 0, 0, 0.1); border: none; color: #495057; font-size: 24px; width: 32px; height: 32px; border-radius: 50%; cursor: pointer; display: flex; align-items: center; justify-content: center; transition: background 0.2s; } .ch-close-tutorial:hover { background: rgba(0, 0, 0, 0.2); } .ch-tutorial-content { padding: 20px; max-height: 400px; overflow-y: auto; } .ch-tutorial-step { display: flex; gap: 12px; margin-bottom: 16px; padding-bottom: 16px; border-bottom: 1px solid #e9ecef; } .ch-tutorial-step:last-child { border-bottom: none; margin-bottom: 0; padding-bottom: 0; } .ch-step-number { flex-shrink: 0; width: 32px; height: 32px; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; border-radius: 50%; display: flex; align-items: center; justify-content: center; font-weight: 600; font-size: 14px; } .ch-step-text { flex: 1; font-size: 13px; line-height: 1.6; color: #495057; } .ch-step-text strong { display: block; margin-bottom: 4px; color: #212529; } .ch-step-text code { background: #f8f9fa; padding: 2px 6px; border-radius: 3px; font-family: 'Courier New', monospace; font-size: 12px; color: #e83e8c; } .ch-toggle-btn { position: fixed; bottom: 20px; right: 20px; width: 120px; height: 48px; border-radius: 24px; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; border: none; font-size: 14px; font-weight: 600; cursor: pointer; box-shadow: 0 4px 16px rgba(102, 126, 234, 0.4); z-index: 999998; transition: transform 0.2s, box-shadow 0.3s; display: flex; align-items: center; justify-content: center; gap: 6px; } .ch-toggle-btn:hover { transform: translateY(-2px); box-shadow: 0 6px 20px rgba(102, 126, 234, 0.5); } .ch-toggle-btn::before { content: '🍪'; font-size: 20px; } `; document.head.appendChild(style); document.body.appendChild(panel); // 创建切换按钮 const toggleBtn = document.createElement('button'); toggleBtn.className = 'ch-toggle-btn'; toggleBtn.id = 'ch-toggle-btn'; toggleBtn.textContent = 'Cookie助手'; toggleBtn.title = 'Cookie获取助手 - 点击打开'; document.body.appendChild(toggleBtn); return panel; } // 初始化 function init() { const panel = createPanel(); const currentPlatform = getCurrentPlatform(); // 事件处理 const closeBtn = document.getElementById('ch-close-btn'); const toggleBtn = document.getElementById('ch-toggle-btn'); const platformItems = document.querySelectorAll('.ch-platform-item:not(.disabled)'); const getCookieBtn = document.getElementById('ch-get-cookie-btn'); const copyBtn = document.getElementById('ch-copy-btn'); const refreshBtn = document.getElementById('ch-refresh-btn'); const testCookieBtn = document.getElementById('ch-test-cookie-btn'); const manualInputBtn = document.getElementById('ch-manual-input-btn'); const showTutorialBtn = document.getElementById('ch-show-tutorial-btn'); const closeTutorialBtn = document.getElementById('ch-close-tutorial-btn'); let selectedPlatform = null; // 检查并更新平台状态的函数 async function updatePlatformStatus(platformKey) { const platform = PLATFORMS[platformKey]; const statusEl = document.getElementById('ch-status'); const actionsEl = document.getElementById('ch-actions'); const resultEl = document.getElementById('ch-result'); resultEl.style.display = 'none'; // 检查是否在目标网站 const isOnTargetSite = window.location.hostname.includes(platform.domain); if (!isOnTargetSite) { // 不在目标网站,显示跳转按钮 statusEl.innerHTML = `📍 当前不在 ${platform.name} 网站`; statusEl.className = 'ch-status'; actionsEl.style.display = 'block'; refreshBtn.style.display = 'none'; getCookieBtn.textContent = `前往 ${platform.name}`; getCookieBtn.onclick = () => { if (typeof GM_openInTab !== 'undefined') { GM_openInTab(platform.url, { active: true }); } else { window.open(platform.url, '_blank'); } }; } else { // 在目标网站,检查登录状态 statusEl.textContent = '🔄 正在检测登录状态...'; statusEl.className = 'ch-status'; const isLoggedIn = await platform.checkLogin(); if (isLoggedIn) { statusEl.textContent = `✅ 已登录 ${platform.name}`; statusEl.className = 'ch-status success'; actionsEl.style.display = 'block'; refreshBtn.style.display = 'block'; getCookieBtn.textContent = '获取Cookie'; getCookieBtn.onclick = async () => { const cookie = await platform.getCookie(); const cookieTextEl = document.getElementById('ch-cookie-text'); const cookieWarningEl = document.getElementById('ch-cookie-warning'); if (cookie) { cookieTextEl.value = cookie; resultEl.style.display = 'block'; // 检查Cookie是否完整 const checkResult = checkCookieComplete(cookie); if (!checkResult.complete) { cookieWarningEl.style.display = 'block'; } else { cookieWarningEl.style.display = 'none'; } if (typeof GM_notification !== 'undefined') { GM_notification({ text: checkResult.complete ? 'Cookie获取成功!' : 'Cookie不完整,请使用手动输入', timeout: 2000 }); } } else { alert('获取Cookie失败,请确保已登录'); } }; } else { statusEl.textContent = `❌ 暂未登录 ${platform.name},请先登录`; statusEl.className = 'ch-status error'; actionsEl.style.display = 'block'; refreshBtn.style.display = 'block'; getCookieBtn.style.display = 'none'; } } } // 切换面板显示 toggleBtn.addEventListener('click', () => { panel.style.display = panel.style.display === 'none' ? 'flex' : 'none'; // 如果打开面板且已选择平台,自动刷新状态 if (panel.style.display === 'flex' && selectedPlatform) { updatePlatformStatus(selectedPlatform); } }); closeBtn.addEventListener('click', () => { panel.style.display = 'none'; }); // 选择平台 platformItems.forEach(item => { item.addEventListener('click', (e) => { // 如果点击的是测试按钮,不触发平台选择 if (e.target.classList.contains('ch-platform-test-btn')) { return; } const platformKey = item.dataset.platform; // 更新选中状态 platformItems.forEach(i => i.classList.remove('active')); item.classList.add('active'); selectedPlatform = platformKey; // 更新平台状态 updatePlatformStatus(platformKey); }); }); // 平台测试按钮 document.querySelectorAll('.ch-platform-test-btn').forEach(btn => { btn.addEventListener('click', async (e) => { e.stopPropagation(); // 阻止事件冒泡 const platformKey = btn.dataset.platform; const platform = PLATFORMS[platformKey]; // 检查是否在目标网站 const isOnTargetSite = window.location.hostname.includes(platform.domain); if (!isOnTargetSite) { const goToSite = confirm(`当前不在${platform.name}网站。\n\n是否前往${platform.name}进行测试?`); if (goToSite) { if (typeof GM_openInTab !== 'undefined') { GM_openInTab(platform.url, { active: true }); } else { window.open(platform.url, '_blank'); } } return; } // 在目标网站上,弹出输入框 const cookieInput = prompt(`请输入要测试的${platform.name} Cookie:\n\n提示:可以从F12开发者工具的网络请求中复制完整Cookie`); if (!cookieInput || !cookieInput.trim()) { return; } // 执行登录测试 const verifyResultEl = document.getElementById('ch-verify-result'); const resultEl = document.getElementById('ch-result'); resultEl.style.display = 'block'; verifyResultEl.style.display = 'block'; verifyResultEl.className = 'ch-verify-result'; verifyResultEl.innerHTML = `
🔄 正在测试Cookie...
请稍候
`; try { const result = await testLoginWithCookie(cookieInput.trim()); verifyResultEl.className = `ch-verify-result ${result.valid ? 'valid' : 'invalid'}`; verifyResultEl.innerHTML = `
${result.valid ? '✅ ' : '❌ '}${result.message}
${result.details}
`; if (typeof GM_notification !== 'undefined') { GM_notification({ text: result.message, timeout: 3000 }); } // 如果登录成功,3秒后刷新页面 if (result.needRefresh) { setTimeout(() => { window.location.reload(); }, 3000); } } catch (error) { verifyResultEl.className = 'ch-verify-result invalid'; verifyResultEl.innerHTML = `
❌ 测试失败
${error.message}
`; } }); }); // 刷新按钮事件 refreshBtn.addEventListener('click', () => { if (selectedPlatform) { updatePlatformStatus(selectedPlatform); if (typeof GM_notification !== 'undefined') { GM_notification({ text: '状态已刷新', timeout: 1000 }); } } }); // 获取Cookie getCookieBtn.addEventListener('click', () => { // 这个事件监听器现在只是占位,实际逻辑在平台选择时动态绑定 }); // 复制Cookie copyBtn.addEventListener('click', () => { const cookieTextEl = document.getElementById('ch-cookie-text'); const cookie = cookieTextEl.value; if (typeof GM_setClipboard !== 'undefined') { GM_setClipboard(cookie); copyBtn.textContent = '✅ 已复制'; setTimeout(() => { copyBtn.textContent = '📋 复制'; }, 2000); } else { // 降级方案 cookieTextEl.select(); document.execCommand('copy'); copyBtn.textContent = '✅ 已复制'; setTimeout(() => { copyBtn.textContent = '📋 复制'; }, 2000); } }); // 测试Cookie(退出重登) testCookieBtn.addEventListener('click', async () => { const cookieTextEl = document.getElementById('ch-cookie-text'); const cookie = cookieTextEl.value; if (!cookie || !cookie.trim()) { alert('请先获取或输入Cookie'); return; } if (!confirm('⚠️ 此操作将清除当前登录状态,使用获取的Cookie重新登录。\n\n确定要继续吗?')) { return; } testCookieBtn.disabled = true; testCookieBtn.textContent = '🔄 测试中...'; try { // 1. 清除当前所有Cookie if (typeof GM_cookie !== 'undefined') { const currentCookies = await new Promise((resolve) => { GM_cookie.list({}, (cookies) => { resolve(cookies || []); }); }); for (const c of currentCookies) { await new Promise((resolve) => { GM_cookie.delete({ name: c.name, url: window.location.href }, () => resolve()); }); } } // 2. 设置新Cookie const result = await testLoginWithCookie(cookie); // 3. 刷新页面验证 if (result.valid || result.needRefresh) { if (typeof GM_notification !== 'undefined') { GM_notification({ text: '正在刷新页面验证登录...', timeout: 2000 }); } setTimeout(() => { window.location.reload(); }, 2000); } else { alert(`测试失败:${result.message}\n${result.details}`); testCookieBtn.disabled = false; testCookieBtn.textContent = '🧪 测试Cookie(退出重登)'; } } catch (error) { alert(`测试失败:${error.message}`); testCookieBtn.disabled = false; testCookieBtn.textContent = '🧪 测试Cookie(退出重登)'; } }); // 手动输入Cookie manualInputBtn.addEventListener('click', () => { const cookieTextEl = document.getElementById('ch-cookie-text'); const cookieWarningEl = document.getElementById('ch-cookie-warning'); const userInput = prompt('请粘贴从F12开发者工具复制的完整Cookie:\n\n提示:在开发者工具的"网络"标签中,找到任意请求,复制"请求标头"中的Cookie值'); if (userInput && userInput.trim()) { cookieTextEl.value = userInput.trim(); // 检查Cookie是否完整 const checkResult = checkCookieComplete(userInput.trim()); if (checkResult.complete) { cookieWarningEl.style.display = 'none'; if (typeof GM_notification !== 'undefined') { GM_notification({ text: '✅ 完整Cookie已输入!', timeout: 2000 }); } } else { if (typeof GM_notification !== 'undefined') { GM_notification({ text: '⚠️ Cookie可能仍不完整', timeout: 2000 }); } } } }); // 显示教程 showTutorialBtn.addEventListener('click', () => { const tutorialEl = document.getElementById('ch-tutorial'); tutorialEl.style.display = 'block'; }); // 关闭教程 closeTutorialBtn.addEventListener('click', () => { const tutorialEl = document.getElementById('ch-tutorial'); tutorialEl.style.display = 'none'; }); // 如果在支持的平台上,自动选中 if (currentPlatform && !PLATFORMS[currentPlatform].disabled) { const platformItem = document.querySelector(`[data-platform="${currentPlatform}"]`); if (platformItem) { platformItem.click(); } } } // 页面加载完成后初始化 if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', init); } else { init(); } })();