// ==UserScript== // @name 百度贴吧一键签到 // @namespace https://blog.qitongtingyu.online/ // @version 1.3 // @description 一键签到所有关注的贴吧,支持大量贴吧、智能间隔防限流、失败自动重试 // @author 栖桐听雨 // @icon https://tb3.bdstatic.com/public/icon/favicon-v2.ico // @match *://tieba.baidu.com/* // @grant GM_xmlhttpRequest // @grant GM_setValue // @grant GM_getValue // @connect tieba.baidu.com // @connect c.tieba.baidu.com // @require https://unpkg.com/crypto-js@4.1.1/core.js // @require https://unpkg.com/crypto-js@4.1.1/md5.js // @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 svgIcons = { close: '', check: '', skip: '', warn: '' }; const styles = ` body > #tiebaAutoSignBtn, body > .tieba-sign-mask { all: initial; } 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; display: block; } 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; } @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%; } } @keyframes progressFlow { 0% { background-position: 0% 0%; } 100% { background-position: 200% 0%; } } @keyframes dialogEnter { 0% { opacity: 0; transform: scale(0.95) translateY(10px); } 100% { opacity: 1; transform: scale(1) translateY(0); } } .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; } .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); } .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-close { width: 36px; height: 36px; border-radius: 10px; background: rgba(255, 255, 255, 0.12); color: ${colors.textWhite}; border: none; cursor: pointer; display: flex; align-items: center; justify-content: center; transition: all 0.15s ease; -webkit-tap-highlight-color: transparent; } .tieba-sign-close svg { width: 20px; height: 20px; } .tieba-sign-close:hover { background: rgba(255, 255, 255, 0.25); transform: scale(1.05); } .tieba-sign-dialog-body { padding: 20px; overflow-y: auto; flex: 1; font-size: 14px; line-height: 1.7; color: ${colors.textPrimary}; } .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-progress-container { margin-bottom: 16px; } .tieba-sign-progress-info { display: flex; justify-content: space-between; margin-bottom: 6px; font-size: 13px; } .tieba-sign-progress-bar-bg { width: 100%; height: 8px; background: ${colors.border}; border-radius: 4px; overflow: hidden; } .tieba-sign-progress-bar { width: 0%; height: 100%; background: linear-gradient(90deg, ${colors.primary}, ${colors.accent}, ${colors.primary}); background-size: 200% 100%; border-radius: 4px; transition: width 0.3s ease; } .tieba-sign-progress-bar.loading { animation: progressFlow 1.5s linear infinite; } .tieba-sign-summary { background: linear-gradient(135deg, ${colors.bgHighlight} 0%, rgba(244, 184, 134, 0.1) 100%); padding: 16px; border-radius: 12px; margin-bottom: 12px; border-left: 4px solid ${colors.accent}; } .tieba-sign-results { max-height: 40vh; overflow-y: auto; margin-top: 12px; } .tieba-sign-results::-webkit-scrollbar { width: 6px; } .tieba-sign-results::-webkit-scrollbar-track { background: ${colors.scrollbarTrack}; border-radius: 3px; } .tieba-sign-results::-webkit-scrollbar-thumb { background: ${colors.scrollbarThumb}; border-radius: 3px; } .tieba-sign-result-item { padding: 10px 0; border-bottom: 1px solid ${colors.border}; transition: background 0.15s ease; display: flex; gap: 8px; align-items: flex-start; } .tieba-sign-result-item:hover { background: rgba(161, 130, 118, 0.1); } .tieba-sign-result-item:last-child { border-bottom: none; } .tieba-sign-result-item svg { flex-shrink: 0; width: 16px; height: 16px; margin-top: 2px; } .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-footer { padding: 16px 20px; text-align: right; border-top: 1px solid ${colors.border}; } .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 ease, box-shadow 0.15s ease; min-height: 44px; min-width: 88px; } .tieba-sign-confirm:hover { box-shadow: 0 4px 16px ${colors.shadowPrimary}; transform: translateY(-1px); } @media (max-width: 480px) { body > #tiebaAutoSignBtn { padding: 12px 20px; font-size: 14px; bottom: 16px; right: 16px; border-radius: 24px; } .tieba-sign-dialog { width: 95%; max-height: 80vh; border-radius: 12px; } .tieba-sign-dialog-header { padding: 12px 16px; font-size: 16px; } .tieba-sign-close { width: 32px; height: 32px; border-radius: 8px; } .tieba-sign-dialog-body { padding: 16px; font-size: 13px; } .tieba-sign-summary { padding: 12px; } .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-dialog { width: 85%; max-height: 80vh; } } @media (orientation: landscape) and (max-height: 500px) { .tieba-sign-dialog { max-height: 90vh; width: 80%; } body > #tiebaAutoSignBtn { bottom: 12px; padding: 10px 18px; font-size: 13px; } } `; const CACHE_KEY = 'tieba_sign_cache_v2'; const FAKE_VERSION = '9.7.8.0'; function makeFakeParams(obj) { return Object.assign({ _client_type: 4, _client_version: FAKE_VERSION, _phone_imei: '0'.repeat(15), model: 'HUAWEI P40', net_type: 1, stErrorNums: 1, stMethod: 1, stMode: 1, stSize: 320, stTime: 117, stTimesNum: 1, timestamp: Date.now() }, obj); } function sign(payload) { const sortKeys = Object.keys(payload).sort(); let str = sortKeys.reduce((acc, key) => acc += `${key}=${payload[key]}`, ''); str += 'tiebaclient!!!'; return CryptoJS.MD5(str).toString(); } function getTodayCache() { const today = new Date(); const dateStr = `${today.getFullYear()}-${String(today.getMonth() + 1).padStart(2, '0')}-${String(today.getDate()).padStart(2, '0')}`; const cache = JSON.parse(GM_getValue(CACHE_KEY, '{}')); if (cache.date !== dateStr) { GM_setValue(CACHE_KEY, JSON.stringify({ date: dateStr, signed: {} })); return new Map(); } return new Map(Object.entries(cache.signed || {})); } function saveToCache(forumName) { const today = new Date(); const dateStr = `${today.getFullYear()}-${String(today.getMonth() + 1).padStart(2, '0')}-${String(today.getDate()).padStart(2, '0')}`; const cache = JSON.parse(GM_getValue(CACHE_KEY, '{}')); if (cache.date !== dateStr) { cache.date = dateStr; cache.signed = {}; } cache.signed[forumName] = true; GM_setValue(CACHE_KEY, JSON.stringify(cache)); } 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 createProgressDialog(title) { document.querySelector('.tieba-sign-mask')?.remove(); const mask = document.createElement('div'); mask.className = 'tieba-sign-mask'; mask.innerHTML = `
${title}
准备中... 0%
`; document.body.appendChild(mask); document.body.style.overflow = 'hidden'; const el = { progressText: mask.querySelector('.tieba-sign-progress-text'), progressPercent: mask.querySelector('.tieba-sign-progress-percent'), progressBar: mask.querySelector('.tieba-sign-progress-bar'), summary: mask.querySelector('.tieba-sign-summary'), results: mask.querySelector('.tieba-sign-results'), closeBtn: mask.querySelector('.tieba-sign-close'), confirmBtn: mask.querySelector('.tieba-sign-confirm') }; let aborted = false; const close = () => { aborted = true; mask.remove(); document.body.style.overflow = ''; }; el.closeBtn.addEventListener('click', close); el.confirmBtn.addEventListener('click', close); el.confirmBtn.addEventListener('touchend', e => { e.preventDefault(); close(); }); mask.addEventListener('click', e => e.target === mask && close()); return { updateProgress: (current, total) => { if (aborted) return; const percent = total > 0 ? Math.round((current / total) * 100) : 0; el.progressText.textContent = `处理中:${current}/${total}`; el.progressPercent.textContent = `${percent}%`; el.progressBar.style.width = `${percent}%`; el.progressBar.classList.remove('loading'); }, appendResult: (status, text) => { if (aborted) return; const item = document.createElement('div'); item.className = `tieba-sign-result-item tieba-sign-${status}`; let icon = svgIcons.warn; if (status === 'success') icon = svgIcons.check; if (status === 'existed') icon = svgIcons.skip; item.innerHTML = `${icon}${text.replace(/\n/g, '
')}
`; el.results.appendChild(item); el.results.scrollTop = el.results.scrollHeight; }, updateSummary: (success, existed, fail, totalContSign, totalCount) => { if (aborted) return; el.summary.innerHTML = `签到汇总
总数:${totalCount} | 成功:${success} | 跳过:${existed} | 失败:${fail}
累计连续签到:${totalContSign}天`; }, setLoading: (text) => { if (aborted) return; el.progressText.textContent = text; el.progressBar.style.width = '30%'; el.progressBar.classList.add('loading'); }, setComplete: () => { if (aborted) return; el.progressText.textContent = '完成'; el.confirmBtn.textContent = '确定'; el.progressBar.classList.remove('loading'); }, getAborted: () => aborted }; } function createSignButton() { if (document.getElementById('tiebaAutoSignBtn')) return; const btn = document.createElement('button'); btn.id = 'tiebaAutoSignBtn'; btn.textContent = '贴吧一键签到'; btn.className = 'noise-bg'; btn.addEventListener('click', async () => { if (btn.disabled) return; btn.disabled = true; btn.textContent = '签到中...'; await autoSign(); btn.disabled = false; btn.textContent = '贴吧一键签到'; }); document.body.appendChild(btn); } function extractTiebaNamesFromHtml(html) { const names = new Set(); const regex = /([^<]+)<\/a>/g; let match; while ((match = regex.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]; } 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() { const forumMap = new Map(); const addForums = (forums) => { forums.forEach(f => { const name = f.forum_name?.trim() || f.name?.trim(); const id = f.forum_id?.toString() || f.id?.toString(); if (name) { if (id && forumMap.has(id)) { forumMap.get(id).forum_name = name; } else { forumMap.set(id || name, { forum_name: name }); } } }); }; const fromPage = () => { const html = document.querySelector('html')?.innerHTML || ''; const forumIndex = html.indexOf('{"forumArr":'); if (forumIndex !== -1) { try { const content = html.slice(forumIndex); const forumEnd = content.indexOf(');'); const jsonStr = content.slice(0, forumEnd); const data = JSON.parse(jsonStr); if (data.forumArr && Array.isArray(data.forumArr)) { addForums(data.forumArr); } } catch (e) { } } }; const fromNewmoindex = async () => { return new Promise(resolve => { GM_xmlhttpRequest({ method: 'POST', url: 'https://tieba.baidu.com/mo/q/newmoindex', headers: { 'Content-Type': 'application/x-www-form-urlencoded', 'Cookie': document.cookie, 'User-Agent': navigator.userAgent }, timeout: 20000, onload: r => { try { const data = JSON.parse(r.responseText || '{}'); if (data.data?.like_forum && Array.isArray(data.data.like_forum)) { addForums(data.data.like_forum); } } catch { } resolve(); }, onerror: () => resolve(), ontimeout: () => resolve() }); }); }; const fromAppApi = async () => { const appCommonHeader = { 'User-agent': `bdtb for Android ${FAKE_VERSION}`, Accept: '', 'Content-Type': 'application/x-www-form-urlencoded' }; let page = 1; let hasMore = true; while (hasMore && page <= 50) { const baseParams = makeFakeParams({ BDUSS: document.cookie.match(/BDUSS=([^;]+)/)?.[1] || '', page_no: page, page_size: 200 }); const params = { ...baseParams, sign: sign(baseParams) }; const dataStr = Object.keys(params).map(k => `${k}=${encodeURIComponent(params[k])}`).join('&'); const response = await new Promise(resolve => { GM_xmlhttpRequest({ method: 'POST', url: 'https://c.tieba.baidu.com/c/f/forum/like', headers: { ...appCommonHeader, 'Cookie': document.cookie }, data: dataStr, timeout: 20000, onload: r => { try { resolve(JSON.parse(r.responseText || '{}')); } catch { resolve({}); } }, onerror: () => resolve({}), ontimeout: () => resolve({}) }); }); if (response.forum_list) { const forums = []; if (response.forum_list.non_gconforum) { const list = Array.isArray(response.forum_list.non_gconforum) ? response.forum_list.non_gconforum : []; forums.push(...list); } if (response.forum_list.gconforum) { const list = Array.isArray(response.forum_list.gconforum) ? response.forum_list.gconforum : []; forums.push(...list); } if (Array.isArray(response.forum_list)) { forums.push(...response.forum_list); } addForums(forums); } hasMore = response.has_more === '1' || response.has_more === 1; page++; await new Promise(r => setTimeout(r, 200)); } }; const fromMylike = async () => { let page = 1; while (page <= 50) { const html = await new Promise(resolve => { GM_xmlhttpRequest({ method: 'GET', url: `https://tieba.baidu.com/f/like/mylike?pn=${page}`, headers: { 'Cookie': document.cookie, 'User-Agent': navigator.userAgent }, timeout: 20000, onload: r => resolve(r.responseText || ''), onerror: () => resolve(''), ontimeout: () => resolve('') }); }); const names = extractTiebaNamesFromHtml(html); names.forEach(name => { if (name) forumMap.set(name, { forum_name: name }); }); if (names.length < 20) break; await new Promise(r => setTimeout(r, 300)); page++; } }; fromPage(); await fromNewmoindex(); await fromAppApi(); await fromMylike(); const tiebaList = [...forumMap.values()]; return tiebaList.length > 0 ? tiebaList : showErrorPrompt('自动提取贴吧列表失败'); } async function getTBS() { return new Promise(resolve => { GM_xmlhttpRequest({ method: 'GET', url: 'https://tieba.baidu.com/dc/common/tbs', headers: { 'Cookie': document.cookie }, timeout: 10000, onload: r => { try { resolve(JSON.parse(r.responseText).tbs || ''); } catch { resolve(''); } }, onerror: () => resolve('') }); }); } async function signSingleTieba(name) { return new Promise(async resolve => { const tbs = await getTBS(); const data = `ie=utf-8&kw=${encodeURIComponent(name)}${tbs ? `&tbs=${tbs}` : ''}`; GM_xmlhttpRequest({ method: 'POST', url: 'https://tieba.baidu.com/sign/add', data: data, headers: { 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8', 'Referer': `https://tieba.baidu.com/f?kw=${encodeURIComponent(name)}`, 'Cookie': document.cookie }, timeout: 15000, onload: r => { try { const res = JSON.parse(r.responseText); switch (res.no) { case 0: resolve({ status: 'success', msg: `${name}:签到成功\n连续签到:${res.data?.uinfo?.cont_sign_num || 0}天 | 总签到:${res.data?.uinfo?.total_sign_num || 0}次\n本吧排名:${res.data?.finfo?.current_rank_info?.sign_count || 0}` }); break; case 1101: resolve({ status: 'existed', msg: `${name}:今日已签到` }); break; case 100002: resolve({ status: 'fail', msg: `${name}:未登录/登录过期` }); break; case 34004: resolve({ status: 'fail', msg: `${name}:需要验证` }); break; default: resolve({ status: 'fail', msg: `${name}:失败(${res.error || '未知错误'})` }); break; } } catch { resolve({ status: 'fail', msg: `${name}:解析失败` }); } }, onerror: () => resolve({ status: 'fail', msg: `${name}:网络错误` }), ontimeout: () => resolve({ status: 'fail', msg: `${name}:请求超时` }) }); }); } async function autoSign() { const dialog = createProgressDialog('贴吧一键签到'); try { dialog.setLoading('获取关注贴吧列表...'); const tiebaList = await getFollowedTieba(); if (dialog.getAborted()) return; if (tiebaList.length === 0) { dialog.appendResult('fail', '未获取到任何需要签到的贴吧'); dialog.updateSummary(0, 0, 1, 0, 0); dialog.setComplete(); return; } const cache = getTodayCache(); const toSign = []; const skipped = []; const failedList = []; for (const t of tiebaList) { if (cache.has(t.forum_name)) { skipped.push({ status: 'existed', msg: `${t.forum_name}:今日已签到(缓存)` }); } else { toSign.push(t); } } let [success, existed, fail, contSign] = [0, skipped.length, 0, 0]; dialog.updateSummary(success, existed, fail, contSign, tiebaList.length); skipped.forEach((res, index) => { dialog.appendResult(res.status, res.msg); dialog.updateProgress(skipped.length + index + 1, tiebaList.length); }); if (toSign.length === 0) { dialog.appendResult('existed', '所有贴吧今日均已签到'); dialog.updateProgress(tiebaList.length, tiebaList.length); dialog.setComplete(); return; } const baseDelay = isMobile() ? 1500 : 1200; const batchDelay = 5000; const batchSize = 5; for (let i = 0; i < toSign.length; i++) { if (dialog.getAborted()) break; dialog.updateProgress(skipped.length + i + 1, tiebaList.length); const res = await signSingleTieba(toSign[i].forum_name); dialog.appendResult(res.status, res.msg); if (res.status === 'success') { success++; saveToCache(toSign[i].forum_name); const match = res.msg.match(/连续签到:(\d+)天/); if (match) contSign += parseInt(match[1]); } else if (res.status === 'existed') { existed++; saveToCache(toSign[i].forum_name); } else { fail++; failedList.push(toSign[i]); } dialog.updateSummary(success, existed, fail, contSign, tiebaList.length); if (i !== toSign.length - 1) { if (dialog.getAborted()) break; const randomOffset = Math.floor(Math.random() * 500); await new Promise(r => setTimeout(r, baseDelay + randomOffset)); } if ((i + 1) % batchSize === 0 && i !== toSign.length - 1) { if (dialog.getAborted()) break; await new Promise(r => setTimeout(r, batchDelay)); } } if (failedList.length > 0 && !dialog.getAborted()) { dialog.appendResult('info', `准备重试 ${failedList.length} 个失败的贴吧...`); await new Promise(r => setTimeout(r, 10000)); for (let j = 0; j < failedList.length; j++) { if (dialog.getAborted()) break; const name = failedList[j].forum_name; dialog.updateProgress(skipped.length + toSign.length + j + 1, tiebaList.length + failedList.length); const res = await signSingleTieba(name); dialog.appendResult(res.status, res.msg); if (res.status === 'success') { success++; fail--; saveToCache(name); const match = res.msg.match(/连续签到:(\d+)天/); if (match) contSign += parseInt(match[1]); } else if (res.status === 'existed') { existed++; fail--; saveToCache(name); } dialog.updateSummary(success, existed, fail, contSign, tiebaList.length); if (j !== failedList.length - 1) { if (dialog.getAborted()) break; await new Promise(r => setTimeout(r, 3000 + Math.floor(Math.random() * 2000))); } } } dialog.updateProgress(tiebaList.length, tiebaList.length); dialog.setComplete(); } catch { if (!dialog.getAborted()) { dialog.appendResult('fail', '签到过程出错'); dialog.updateSummary(0, 0, 1, 0, 0); dialog.setComplete(); } } } function init() { createStyles(); setTimeout(createSignButton, isMobile() ? 3000 : 2000); } document.readyState === 'complete' ? init() : window.addEventListener('load', init); })();