功能:访问自动静默签到、页面显示签到状态、预防多请求问题(当天对应UID只请求一次)
// ==UserScript==
// @name 大佬论坛-每日自动签到
// @version 1.0.0
// @description 每天自动静默签到,按UID记录,头部导航显示绿色"已签"
// @author 五霸哥
// @match *://*.dalao.net/*
// @match *://dalao.net/*
// @grant GM_setValue
// @grant GM_getValue
// @grant GM_registerMenuCommand
// @run-at document-end
// ==/UserScript==
(function() {
'use strict';
// 避免在 iframe 中执行
if (window.self !== window.top) return;
// ==================== 配置区域 ====================
const SIGNIN_URL = 'signin.htm';
const STORAGE_KEY = 'dahua_auto_signin_v2';
const DEBUG = true;
// ==================================================
function log(...args) {
if (DEBUG) console.log('[自动签到]', ...args);
}
function getTodayKey() {
const d = new Date();
return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}-${String(d.getDate()).padStart(2, '0')}`;
}
// ==================== UID 相关 ====================
/**
* 获取当前登录用户的 UID
*/
function getCurrentUid() {
// 1. 优先从全局变量获取(页面中通常有 var uid = 1234;)
if (typeof window.uid !== 'undefined' && window.uid) {
return String(window.uid);
}
// 2. 从导航栏个人链接提取
const myLink = document.querySelector('a[href="my.htm"]');
if (myLink) {
const text = myLink.textContent || '';
const m = text.match(/UID:\s*(\d+)/);
if (m) return m[1];
}
// 3. 从 user-xxx.htm 链接提取当前用户自己的
const userLinks = document.querySelectorAll('a[href*="user-"]');
for (const a of userLinks) {
const href = a.getAttribute('href') || '';
const m = href.match(/user-(\d+)\.htm/);
if (m) return m[1];
}
return null;
}
/**
* 读取本地签到记录
* 格式: { "1": "2026-05-05", "333": "2026-05-04" }
*/
function getSigninRecord() {
try {
return JSON.parse(localStorage.getItem(STORAGE_KEY) || '{}');
} catch {
return {};
}
}
function saveSigninRecord(record) {
try {
localStorage.setItem(STORAGE_KEY, JSON.stringify(record));
} catch (e) {
log('localStorage 写入失败', e);
}
}
function isSignedToday(uid) {
if (!uid) return false;
const record = getSigninRecord();
return record[uid] === getTodayKey();
}
function markSignedToday(uid) {
if (!uid) return;
const record = getSigninRecord();
record[uid] = getTodayKey();
saveSigninRecord(record);
log(`UID ${uid} 已标记今天签到成功`);
}
function clearSigninRecord() {
localStorage.removeItem(STORAGE_KEY);
alert('签到记录已清除,刷新页面后将重新尝试签到。');
}
if (typeof GM_registerMenuCommand !== 'undefined') {
GM_registerMenuCommand('🔄 清除签到记录', clearSigninRecord);
}
// ==================== 头部状态更新 ====================
/**
* 设置签到处理中状态:图标变为蓝色
*/
function setSigninProcessing() {
const selectors = ['#nav-signin', '#nav-signin-mobile'];
selectors.forEach(sel => {
const link = document.querySelector(sel);
if (!link) return;
const icon = link.querySelector('i.far.fa-calendar-check, i.fa-calendar-check');
if (icon) {
icon.style.color = '#007bff';
icon.style.transition = 'color 0.3s ease';
}
});
}
/**
* 更新头部导航为已签到状态:图标和文字均变为绿色
*/
function updateHeaderSigned() {
// --- 桌面端 ---
const desktopLink = document.querySelector('#nav-signin');
if (desktopLink) {
const icon = desktopLink.querySelector('i.far.fa-calendar-check, i.fa-calendar-check');
if (icon) {
icon.style.color = '#28a745';
icon.style.transition = 'color 0.3s ease';
}
const span = desktopLink.querySelector('span');
if (span && span.textContent.trim() === '签到') {
span.textContent = '已签';
span.style.color = '#28a745';
span.style.fontWeight = 'bold';
}
log('桌面端头部已改为绿色"已签"');
}
// --- 移动端 ---
const mobileLink = document.querySelector('#nav-signin-mobile');
if (mobileLink) {
const icon = mobileLink.querySelector('i.far.fa-calendar-check, i.fa-calendar-check');
if (icon) {
icon.style.color = '#28a745';
icon.style.transition = 'color 0.3s ease';
}
log('移动端头部图标已改为绿色');
}
}
// ==================== 静默签到核心 ====================
function checkSignedFromHtml(html) {
const hasSignedText = /今日已签到/.test(html);
const hasUnsignedText = /今日未签到/.test(html);
return hasSignedText && !hasUnsignedText;
}
function extractVerifyKey(html) {
const match = html.match(/var\s+g_verify_key\s*=\s*"([^"]+)"/);
return match ? match[1] : null;
}
/**
* 使用页面自带的 $.xpost 进行静默签到,确保请求格式与手动点击完全一致
*/
function silentSignin(retryCount) {
retryCount = retryCount || 0;
return new Promise((resolve) => {
// 等待 jQuery 及 $.xpost 可用(最多等 5 秒)
let waitCount = 0;
const maxWait = 50;
function trySignin() {
if (typeof $ === 'undefined' || typeof $.xpost !== 'function') {
if (++waitCount < maxWait) {
setTimeout(trySignin, 100);
return;
}
log('jQuery 或 $.xpost 未加载,无法静默签到');
resolve(false);
return;
}
log('开始静默签到...');
// 1. 先 GET signin.htm 获取 verify_key 及当前状态
$.get(SIGNIN_URL, function(html) {
if (checkSignedFromHtml(html)) {
log('服务器返回已签到');
resolve(true);
return;
}
const verifyKey = extractVerifyKey(html);
if (!verifyKey) {
log('未找到 verify_key');
resolve(false);
return;
}
log('verify_key:', verifyKey);
// 2. 延迟 2 秒后发送签到请求,避免触发频率限制
setTimeout(function() {
doXpost(verifyKey);
}, 2000);
}).fail(function(xhr, status, err) {
log('获取 signin.htm 失败:', status, err);
resolve(false);
});
function doXpost(verifyKey) {
// 使用页面原生的 $.xpost 发送签到请求
$.xpost(SIGNIN_URL, { verify_key: verifyKey }, function(code, message) {
log('$.xpost 响应 code=', code, 'message=', message);
if (code === 0) {
log('静默签到成功');
resolve(true);
return;
}
const msg = (typeof message === 'object'
? (message.message || JSON.stringify(message))
: message) || '';
if (/已签到|已经签到|今日已签/.test(String(msg))) {
log('服务器提示已签到');
resolve(true);
return;
}
// 触发频率限制,且未超过最大重试次数时,延迟 5 秒后重试
if (/操作太快|太快了|请稍后再试/.test(String(msg)) && retryCount < 2) {
log('触发频率限制,5秒后第' + (retryCount + 1) + '次重试...');
setTimeout(function() {
silentSignin(retryCount + 1).then(resolve);
}, 5000);
return;
}
log('静默签到失败:', msg);
resolve(false);
});
}
}
trySignin();
});
}
// ==================== 主入口 ====================
async function main() {
const uid = getCurrentUid();
log('UID:', uid, '| 页面:', location.pathname, '| 今天:', getTodayKey());
if (!uid) {
log('未获取到 UID,跳过');
return;
}
// 1. 本地已有记录 → 直接改头部,不再调接口
if (isSignedToday(uid)) {
log('本地记录该账号今天已签到,跳过接口调用');
updateHeaderSigned();
return;
}
// 2. 本地无记录 → 静默签到
setSigninProcessing();
const ok = await silentSignin();
if (ok) {
markSignedToday(uid);
updateHeaderSigned();
}
}
// ==================== 启动 ====================
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', main);
} else {
main();
}
})();
紫名炫彩昵称2025-12-13到期
给楼主投上 1 枚硬币
当前您的硬币余额:0