大佬论坛(dalao.net)静默自动签到脚本

V Evan 屌  (UID: 5630) [复制链接]
帖子链接已复制到剪贴板
帖子已经有人评论啦,不支持删除!

837 7

天天忘记签到,现在好了,访问自动签到!!!哈哈😄

// ==UserScript==
// @name         大佬论坛(dalao.net)静默自动签到(修复版)
// @namespace    https://www.dalao.net/
// @version      0.1.1
// @description  访问 dalao.net 时自动执行每日签到(不弹窗、不打扰)
// @author       www.evan.xin
// @match        https://www.dalao.net/*
// @run-at       document-idle
// @grant        GM_getValue
// @grant        GM_setValue
// ==/UserScript==

(function () {
  'use strict';

  const DEBUG = false; // true: 控制台输出调试信息
  const log = (...args) => DEBUG && console.log('[dalao-auto-signin]', ...args);

  // 仅在主域 + 顶层页面运行,避免 iframe / 资源请求等
  if (location.hostname !== 'www.dalao.net') return;
  if (window.top !== window.self) return;

  // 一天只跑一次(本地记录,避免每次刷新都请求)
  const today = new Date();
  const todayKey = `${today.getFullYear()}-${String(today.getMonth() + 1).padStart(2, '0')}-${String(today.getDate()).padStart(2, '0')}`;
  const lastRun = GM_getValue('lastRun', '');
  if (lastRun === todayKey) {
    log('already ran today:', todayKey);
    return;
  }

  // 简单 sleep
  const sleep = (ms) => new Promise((r) => setTimeout(r, ms));

  // 解析类似 JSON 的响应(Content-Type 可能不是 application/json)
  const safeJsonParse = (text) => {
    try {
      return JSON.parse(text);
    } catch (e) {
      return null;
    }
  };

  // 判断是否登录(尽量宽松:只要页面上出现账号设置/退出/头像等任一)
  const isLoggedIn = () => {
    const hasAccountSettings = !!document.querySelector('a[title="个人账号设置"], a[href*="my.htm"], a[href*="user-"], a[href*="/my-"]');
    const hasLogout = !!document.querySelector('a[href*="logout"], a[href*="/logout"], a[title*="退出"], a:has(span[aria-label="logout"])');
    const hasAvatar = !!document.querySelector('img.avatar, img[alt*="avatar"], .avatar img');
    return hasAccountSettings || hasLogout || hasAvatar;
  };

  // 是否存在“签到入口”(用于减少未登录时的无意义请求;但不作为硬条件)
  const hasSigninEntry = () => {
    return (
      !!document.querySelector('#nav-signin') ||
      !!document.querySelector('a[href*="signin.htm"], a[href*="/signin"], a[onclick*="signin"], a[title*="签到"], a:contains("签到")')
    );
  };

  // 由于 :contains 不是标准选择器,上面那条可能报错,兜底处理
  const safeHasSigninEntry = () => {
    try {
      return hasSigninEntry();
    } catch (e) {
      // 退化:遍历链接文本
      const links = Array.from(document.querySelectorAll('a'));
      return links.some((a) => (a.textContent || '').includes('签到') || (a.getAttribute('href') || '').includes('signin'));
    }
  };

  async function doSigninOnce() {
    // 随机延迟,降低“刚打开页面就请求”的突兀感
    const delay = 3000 + Math.floor(Math.random() * 7000);
    await sleep(delay);

    if (!isLoggedIn()) {
      log('not logged in, skip');
      return false;
    }

    // 如果页面上完全找不到签到相关入口,也先不浪费请求(可按需注释掉)
    if (!safeHasSigninEntry()) {
      log('no signin entry detected, skip');
      return false;
    }

    // POST /signin.htm(站点逻辑通常是无 body)
    let resp;
    try {
      resp = await fetch('https://www.dalao.net/signin.htm', {
        method: 'POST',
        credentials: 'include',
        headers: {
          'X-Requested-With': 'XMLHttpRequest',
          // 某些站点会校验 referer
          'Referer': location.href,
        },
      });
    } catch (e) {
      log('fetch error:', e);
      return false;
    }

    const text = await resp.text();
    const data = safeJsonParse(text);
    log('signin response:', resp.status, data || text.slice(0, 200));

    // 兼容不同字段名
    const message = (data && (data.message ?? data.msg ?? data.mesg)) ? String(data.message ?? data.msg ?? data.mesg) : String(text);

    // 成功/已签到都算完成,写入今日标记,避免重复请求
    if (/签到成功|今日已签到|已经签到|已签到/.test(message) || (data && (data.code === 0 || data.ok === 1))) {
      GM_setValue('lastRun', todayKey);
      log('marked lastRun:', todayKey);
      return true;
    }

    // 服务器返回 200 但 message 未匹配时,也别重复轰炸:
    // 你可以把下面这一段注释掉,让它只在明确成功时才写入。
    if (resp.ok) {
      log('resp.ok but message not matched, keep lastRun unchanged');
    }

    return false;
  }

  // 失败重试:轻量两次(网络抖动时有用)
  (async () => {
    for (let i = 0; i < 2; i++) {
      const ok = await doSigninOnce();
      if (ok || GM_getValue('lastRun', '') === todayKey) break;
      await sleep(2000 + Math.floor(Math.random() * 3000));
    }
  })();
})();

直接贴到油猴脚本中即可。有问题🤨随时交流!!!

𝐌𝐢.𝐂𝐃𝐁𝐎𝐁𝐎𝐉𝐈
已有评论 ( 7 )
提示:您必须 登录 才能查看此内容。
域名市场
   域名载入中...
创建新帖
自助推广 (点击空位或 这里 添加)
确认删除
确定要删除这篇帖子吗?删除后将无法恢复。
删除成功
帖子已成功删除,页面将自动刷新。
删除失败
删除帖子时发生错误,请稍后再试。