// ==UserScript== // @name 百度贴吧一键签到脚本 // @namespace https://blog.qitongtingyu.online/ // @version 1.0 // @description 百度贴吧一键签到脚本 - 自动获取关注贴吧列表并批量签到,支持移动端和桌面端,提供美观的签到结果展示 // @author 栖桐听雨 // @icon https://tb3.bdstatic.com/public/icon/favicon-v2.ico // @match *://tieba.baidu.com/* // @grant GM_xmlhttpRequest // @connect tieba.baidu.com // @license MIT // @run-at document-end // ==/UserScript== (function () { 'use strict'; const colors = { primary: '#a18276', primaryDark: '#8a6f64', primaryLight: '#b89a8f', accent: '#f4b886', bgPrimary: '#fefdfb', bgHighlight: 'rgba(244, 184, 134, 0.3)', textPrimary: '#5c4a42', textWhite: '#ffffff', border: 'rgba(92, 74, 66, 0.12)', success: '#7a9e7e', error: '#c97b7b', info: '#a18276', scrollbarTrack: 'rgba(161, 130, 118, 0.08)', scrollbarThumb: 'rgba(161, 130, 118, 0.4)', scrollbarThumbHover: 'rgba(161, 130, 118, 0.6)', shadowPrimary: 'rgba(161, 130, 118, 0.35)', shadowPrimaryHover: 'rgba(161, 130, 118, 0.45)', shadowPrimaryActive: 'rgba(161, 130, 118, 0.3)', shadowModal: 'rgba(0, 0, 0, 0.15)' }; const styles = ` body > #tiebaAutoSignBtn, body > .tieba-sign-mask { all: initial; } @keyframes noise { 0%, 100% { background-position: 0 0; } 10% { background-position: -5% -10%; } 20% { background-position: -15% 5%; } 30% { background-position: 7% -25%; } 40% { background-position: 20% 25%; } 50% { background-position: -25% 10%; } 60% { background-position: 15% 5%; } 70% { background-position: 0 15%; } 80% { background-position: 25% 35%; } 90% { background-position: -10% 10%; } } .noise-bg::before { content: ""; position: absolute; top: 0; left: 0; width: 100%; height: 100%; opacity: 0.03; pointer-events: none; background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 200 200' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='noiseFilter'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.65' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23noiseFilter)'/%3E%3C/svg%3E"); animation: noise 8s steps(10) infinite; } body > #tiebaAutoSignBtn { position: fixed; bottom: 24px; right: 24px; z-index: 99999; padding: 14px 24px; background: linear-gradient(135deg, ${colors.primary} 0%, ${colors.primaryDark} 100%); color: ${colors.textWhite}; border: none; border-radius: 12px; cursor: pointer; font-size: 15px; font-weight: 500; letter-spacing: 0.5px; box-shadow: 0 6px 20px ${colors.shadowPrimary}; transition: transform 0.15s cubic-bezier(0.2, 0.8, 0.2, 1), box-shadow 0.15s cubic-bezier(0.2, 0.8, 0.2, 1), background 0.2s ease; -webkit-tap-highlight-color: transparent; touch-action: manipulation; outline: none; } body > #tiebaAutoSignBtn:hover { background: linear-gradient(135deg, ${colors.primaryLight} 0%, ${colors.primary} 100%); box-shadow: 0 8px 28px ${colors.shadowPrimaryHover}; transform: translateY(-2px); } body > #tiebaAutoSignBtn:active { transform: translateY(0) scale(0.98); box-shadow: 0 4px 12px ${colors.shadowPrimaryActive}; } body > #tiebaAutoSignBtn:disabled { background: linear-gradient(135deg, #a89a90 0%, #8a7268 100%); cursor: not-allowed; transform: none; box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); } body > .tieba-sign-mask { position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0, 0, 0, 0.45); backdrop-filter: blur(4px); z-index: 100000; display: flex; align-items: center; justify-content: center; overflow: hidden; touch-action: none; } .tieba-sign-mask .tieba-sign-dialog { width: 90%; max-width: 700px; max-height: 85vh; background: ${colors.bgPrimary}; border-radius: 16px; box-shadow: 0 12px 48px ${colors.shadowModal}; display: flex; flex-direction: column; overflow: hidden; animation: dialogEnter 0.3s cubic-bezier(0.2, 0.8, 0.2, 1); } @keyframes dialogEnter { 0% { opacity: 0; transform: scale(0.95) translateY(10px); } 100% { opacity: 1; transform: scale(1) translateY(0); } } .tieba-sign-dialog .tieba-sign-dialog-header { background: linear-gradient(135deg, ${colors.primary} 0%, ${colors.primaryDark} 100%); color: ${colors.textWhite}; padding: 16px 20px; font-size: 17px; font-weight: 500; letter-spacing: 0.5px; display: flex; justify-content: space-between; align-items: center; } .tieba-sign-dialog-header .tieba-sign-close { width: 36px; height: 36px; border-radius: 10px; background: rgba(255, 255, 255, 0.12); color: ${colors.textWhite}; border: none; cursor: pointer; font-size: 26px; font-weight: bold; display: flex; align-items: center; justify-content: center; transition: all 0.15s cubic-bezier(0.2, 0.8, 0.2, 1); -webkit-tap-highlight-color: transparent; touch-action: manipulation; } .tieba-sign-dialog-header .tieba-sign-close:hover { background: rgba(255, 255, 255, 0.25); transform: scale(1.05); } .tieba-sign-dialog-header .tieba-sign-close:active { background: rgba(255, 255, 255, 0.35); transform: scale(0.95); } .tieba-sign-dialog .tieba-sign-dialog-body { padding: 20px; overflow-y: auto; flex: 1; font-size: 14px; line-height: 1.7; color: ${colors.textPrimary}; -webkit-text-size-adjust: 100%; text-size-adjust: 100%; } .tieba-sign-dialog-body::-webkit-scrollbar { width: 6px; } .tieba-sign-dialog-body::-webkit-scrollbar-track { background: ${colors.scrollbarTrack}; border-radius: 3px; } .tieba-sign-dialog-body::-webkit-scrollbar-thumb { background: ${colors.scrollbarThumb}; border-radius: 3px; transition: background 0.2s ease; } .tieba-sign-dialog-body::-webkit-scrollbar-thumb:hover { background: ${colors.scrollbarThumbHover}; } .tieba-sign-dialog-body .tieba-sign-summary { background: linear-gradient(135deg, ${colors.bgHighlight} 0%, rgba(244, 184, 134, 0.1) 100%); padding: 16px; border-radius: 12px; margin-bottom: 20px; border-left: 4px solid ${colors.accent}; } .tieba-sign-dialog-body .tieba-sign-result-item { padding: 10px 0; border-bottom: 1px solid ${colors.border}; transition: background 0.15s cubic-bezier(0.2, 0.8, 0.2, 1); } .tieba-sign-dialog-body .tieba-sign-result-item:hover { background: rgba(161, 130, 118, 0.1); } .tieba-sign-dialog-body .tieba-sign-result-item:last-child { border-bottom: none; } .tieba-sign-result-item.tieba-sign-success { color: ${colors.success}; font-weight: 500; } .tieba-sign-result-item.tieba-sign-existed { color: ${colors.info}; } .tieba-sign-result-item.tieba-sign-fail { color: ${colors.error}; font-weight: 500; } .tieba-sign-dialog .tieba-sign-dialog-footer { padding: 16px 20px; text-align: right; border-top: 1px solid ${colors.border}; } .tieba-sign-dialog-footer .tieba-sign-confirm { padding: 10px 24px; background: linear-gradient(135deg, ${colors.primary} 0%, ${colors.primaryDark} 100%); color: ${colors.textWhite}; border: none; border-radius: 8px; cursor: pointer; font-size: 15px; font-weight: 500; letter-spacing: 0.5px; transition: transform 0.15s cubic-bezier(0.2, 0.8, 0.2, 1), box-shadow 0.15s cubic-bezier(0.2, 0.8, 0.2, 1), background 0.2s ease; -webkit-tap-highlight-color: transparent; touch-action: manipulation; min-height: 44px; min-width: 88px; } .tieba-sign-dialog-footer .tieba-sign-confirm:hover { background: linear-gradient(135deg, ${colors.primaryLight} 0%, ${colors.primary} 100%); box-shadow: 0 4px 16px ${colors.shadowPrimary}; transform: translateY(-1px); } .tieba-sign-dialog-footer .tieba-sign-confirm:active { transform: translateY(0) scale(0.98); } @media (max-width: 480px) { body > #tiebaAutoSignBtn { padding: 12px 20px; font-size: 14px; bottom: 16px; right: 16px; border-radius: 24px; } .tieba-sign-mask .tieba-sign-dialog { width: 95%; max-height: 80vh; border-radius: 12px; } .tieba-sign-dialog .tieba-sign-dialog-header { padding: 12px 16px; font-size: 16px; } .tieba-sign-dialog-header .tieba-sign-close { width: 32px; height: 32px; border-radius: 8px; } .tieba-sign-dialog .tieba-sign-dialog-body { padding: 16px; font-size: 13px; } .tieba-sign-dialog-body .tieba-sign-summary { padding: 12px; } .tieba-sign-dialog-footer .tieba-sign-confirm { padding: 8px 20px; font-size: 14px; min-height: 40px; } } @media (min-width: 481px) and (max-width: 768px) { body > #tiebaAutoSignBtn { padding: 14px 22px; font-size: 15px; bottom: 20px; right: 20px; } .tieba-sign-mask .tieba-sign-dialog { width: 85%; max-height: 80vh; } } @media (orientation: landscape) and (max-height: 500px) { .tieba-sign-mask .tieba-sign-dialog { max-height: 90vh; width: 80%; } body > #tiebaAutoSignBtn { bottom: 12px; padding: 10px 18px; font-size: 13px; } } `; function createStyles() { const style = document.createElement('style'); style.textContent = styles; document.head.appendChild(style); } function isMobile() { return /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent) || window.innerWidth <= 768; } function createDialog(title, content) { document.querySelector('.tieba-sign-mask')?.remove(); const mask = document.createElement('div'); mask.className = 'tieba-sign-mask'; mask.innerHTML = `
${title}
${content}
`; document.body.appendChild(mask); document.body.style.overflow = 'hidden'; const close = () => { mask.remove(); document.body.style.overflow = ''; }; mask.querySelectorAll('.tieba-sign-close, .tieba-sign-confirm').forEach(btn => { btn.addEventListener('click', close); btn.addEventListener('touchend', e => { e.preventDefault(); close(); }); }); mask.addEventListener('click', e => e.target === mask && close()); } function formatResults(success, existed, fail, totalContSign, results) { const summary = `
签到结果汇总
总计贴吧数:${success + existed + fail} | 签到成功:${success} | 今日已签:${existed} | 签到失败:${fail}
累计连续签到:${totalContSign}
`; const list = results.map(result => { let className = 'tieba-sign-fail'; if (result.includes('✅')) className = 'tieba-sign-success'; else if (result.includes('ℹ️')) className = 'tieba-sign-existed'; return `
${result.replace(/\n/g, '
')}
`; }).join(''); return summary + `
${list}
`; } function createSignButton() { if (document.getElementById('tiebaAutoSignBtn')) return; const btn = document.createElement('button'); btn.id = 'tiebaAutoSignBtn'; btn.textContent = '贴吧一键签到'; btn.className = 'noise-bg'; const handleSign = async () => { if (btn.disabled) return; btn.disabled = true; btn.textContent = '签到中...'; await autoSign(); btn.disabled = false; btn.textContent = '贴吧一键签到'; }; btn.addEventListener('touchend', e => { e.preventDefault(); handleSign(); }); btn.addEventListener('click', handleSign); document.body.appendChild(btn); } function extractTiebaNames(html) { const names = new Set(); const regex1 = /([^<]+)<\/a>/g; let match; while ((match = regex1.exec(html)) !== null) { const name = (match[2] || match[3]).trim(); if (name) names.add(name); } if (names.size === 0) { const regex2 = /balvname="([^"]+)"/g; while ((match = regex2.exec(html)) !== null) { const name = match[1].trim(); if (name) names.add(name); } } return [...names].map(name => ({ forum_name: name })); } function showErrorPrompt(message) { const defaultTieba = 'redstone_machinery_communication'; const input = prompt(`${message}\n\n已为你填充默认贴吧:${defaultTieba}\n如需添加其他贴吧,请用英文逗号分隔`, defaultTieba); return input ? input.split(',') .map(name => name.trim()) .filter(name => name) .map(name => ({ forum_name: name })) : []; } async function getFollowedTieba() { return new Promise(resolve => { GM_xmlhttpRequest({ method: 'GET', url: 'https://tieba.baidu.com/f/like/mylike?pn=1', headers: { 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8', 'Referer': 'https://tieba.baidu.com/f/like/mylike', 'Cookie': document.cookie, 'User-Agent': navigator.userAgent, 'Cache-Control': 'no-cache', 'Pragma': 'no-cache' }, responseType: 'text', timeout: 20000, onload: response => { try { const tiebaList = extractTiebaNames(response.responseText); resolve(tiebaList.length > 0 ? tiebaList : showErrorPrompt('自动提取贴吧列表失败')); } catch (e) { resolve(showErrorPrompt(`提取贴吧列表出错:${e.message}`)); } }, onerror: () => resolve(showErrorPrompt('网络请求失败,请检查网络')), ontimeout: () => resolve(showErrorPrompt('请求超时,请检查网络')) }); }); } async function getTBS() { return new Promise(resolve => { GM_xmlhttpRequest({ method: 'GET', url: 'https://tieba.baidu.com/dc/common/tbs', headers: { 'Cookie': document.cookie, 'User-Agent': navigator.userAgent }, responseType: 'text', timeout: 10000, onload: response => { try { resolve(JSON.parse(response.responseText).tbs || ''); } catch { const match = document.documentElement.innerHTML.match(/tbs[=:"']+([0-9a-f]+)/); resolve(match ? match[1] : ''); } }, onerror: () => { const match = document.documentElement.innerHTML.match(/tbs[=:"']+([0-9a-f]+)/); resolve(match ? match[1] : ''); }, ontimeout: () => resolve('') }); }); } async function signSingleTieba(name) { return new Promise(async resolve => { const encodedName = encodeURIComponent(name); const tbs = await getTBS(); const postData = `ie=utf-8&kw=${encodedName}${tbs ? `&tbs=${tbs}` : ''}`; GM_xmlhttpRequest({ method: 'POST', url: 'https://tieba.baidu.com/sign/add', data: postData, headers: { 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8', 'Referer': `https://tieba.baidu.com/f?kw=${encodedName}&fr=ala0`, 'X-Requested-With': 'XMLHttpRequest', 'Cookie': document.cookie, 'User-Agent': navigator.userAgent, 'Origin': 'https://tieba.baidu.com', 'Cache-Control': 'no-cache', 'Pragma': 'no-cache' }, timeout: 15000, onload: response => { try { const result = JSON.parse(response.responseText); switch (result.no) { case 0: const uinfo = result.data?.uinfo || {}; const finfo = result.data?.finfo || {}; resolve(`✅ ${name}:签到成功\n 连续签到:${uinfo.cont_sign_num || 0}天 | 总签到:${uinfo.total_sign_num || 0}次\n 本吧排名:${finfo.current_rank_info?.sign_count || 0}`); case 1101: resolve(`ℹ️ ${name}:今日已签到`); case 100002: resolve(`❌ ${name}:签到失败(未登录/登录过期)`); case 34004: resolve(`❌ ${name}:签到失败(需要验证)`); default: resolve(`❌ ${name}:签到失败(${result.error || result.errmsg || '未知错误'})`); } } catch (e) { resolve(`❌ ${name}:解析结果失败(${e.message})`); } }, onerror: () => resolve(`❌ ${name}:网络请求失败`), ontimeout: () => resolve(`❌ ${name}:请求超时`) }); }); } async function autoSign() { try { const tiebaList = await getFollowedTieba(); if (tiebaList.length === 0) { createDialog('提示', '
未获取到任何需要签到的贴吧!
'); return; } const results = []; let [success, existed, fail, totalContSign] = [0, 0, 0, 0]; const isMobileDevice = isMobile(); const delay = isMobileDevice ? 1500 : 1000; const throttle = isMobileDevice ? 3 : 5; for (let i = 0; i < tiebaList.length; i++) { const result = await signSingleTieba(tiebaList[i].forum_name); results.push(result); if (result.includes('✅')) success++; else if (result.includes('ℹ️')) existed++; else fail++; const contSignMatch = result.match(/连续签到:(\d+)天/); if (contSignMatch) totalContSign += parseInt(contSignMatch[1]); if ((i + 1) % throttle === 0) { await new Promise(resolve => setTimeout(resolve, delay)); } } createDialog('贴吧签到结果', formatResults(success, existed, fail, totalContSign, results)); } catch (error) { createDialog('签到出错', `
签到过程出错:${error.message || error}
`); console.error('签到错误详情:', error); } } function init() { createStyles(); setTimeout(createSignButton, isMobile() ? 3000 : 2000); console.log('✅ 百度贴吧一键签到脚本已加载完成'); } document.readyState === 'complete' ? init() : window.addEventListener('load', init); })();