// # Source: https://github.com/huwangkeji/juejin_checkin/blob/main/juejin_checkin.js
// # Raw: https://raw.githubusercontent.com/huwangkeji/juejin_checkin/main/juejin_checkin.js
// # Repo: huwangkeji/juejin_checkin
// # Path: juejin_checkin.js
// # UploadedAt: 2026-05-19T14:34:11Z
// # SHA256: 6f8a138b51c397220444c9312040dbe3407af5aeed4fa4467a36672aeb8bcfd1
// # Category: web版/账密
// # Evidence: web/H5关键词 + username/password/login
// 

/*
 * @name         掘金自动签到脚本
 * @description  掘金社区每日签到 + 免费抽奖 + 沾喜气 + Bug消除，支持Cookie自动签到
 * @namespace    https://juejin.cn
 * @version      1.0.0
 * @author       CodeBuddy
 *
 * 【青龙面板使用说明】
 * 1. 依赖管理 -> NodeJS -> 添加依赖: axios
 * 2. 环境变量 (必填):
 *    - JUEJIN_COOKIE: 掘金Cookie (从浏览器开发者工具复制)
 *    - JUEJIN_AID: API参数aid (通常为2608)
 *    - JUEJIN_UUID: API参数uuid
 *    - JUEJIN_MSTOKEN: API参数msToken
 *    - JUEJIN_A_BOGUS: API参数a_bogus
 * 3. 环境变量 (可选):
 *    - JUEJIN_COOKIE_2 ~ JUEJIN_COOKIE_5: 多账号Cookie
 *    - JUEJIN_NOTIFY: 是否推送通知 (默认true)
 * 4. 定时规则: 30 6 * * * (每天早上6:30执行)
 *
 * 【参数获取方式】
 * 1. 浏览器打开 https://juejin.cn 并登录
 * 2. 按F12打开开发者工具 -> Network(网络)标签
 * 3. 刷新页面，找到任意一个 api.juejin.cn 的请求
 * 4. 在 Request Headers 中复制完整的 Cookie 值
 * 5. 在 Query String Parameters 中复制 aid, uuid, msToken, a_bogus
 * 6. 粘贴到青龙面板对应的环境变量中
 * 7. Cookie和参数有效期约30天，过期后需重新获取
 *
 * 【功能列表】
 * - Cookie自动签到（支持多账号）
 * - 每日签到
 * - 免费抽奖
 * - 沾喜气
 * - Bug消除
 * - 查询矿石余额/签到天数/幸运值
 * - 青龙面板通知推送
 */

const axios = require('axios');

// ==================== 配置区域 ====================

const API_BASE = 'https://api.juejin.cn';

// 请求头
const DEFAULT_HEADERS = {
  'User-Agent':
    'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36',
  'Referer': 'https://juejin.cn/',
  'Origin': 'https://juejin.cn',
  'Content-Type': 'application/json',
  'sec-ch-ua': '"Not/A)Brand";v="99", "Chromium";v="148"',
  'sec-ch-ua-mobile': '?0',
  'sec-ch-ua-platform': '"Windows"',
};

// ==================== 工具函数 ====================

function log(msg) {
  const now = new Date().toLocaleString('zh-CN', { timeZone: 'Asia/Shanghai' });
  console.log(`[${now}] ${msg}`);
}

function sleep(ms) {
  return new Promise((resolve) => setTimeout(resolve, ms));
}

/**
 * 创建带Cookie和参数的axios实例
 */
function createApiClient(cookie, params) {
  const instance = axios.create({
    baseURL: API_BASE,
    headers: {
      ...DEFAULT_HEADERS,
      Cookie: cookie,
    },
    timeout: 30000,
  });

  // 请求拦截 - 自动添加查询参数
  instance.interceptors.request.use((config) => {
    if (params && Object.keys(params).length > 0) {
      config.params = { ...config.params, ...params };
    }
    // POST请求body为空对象
    if (config.method === 'post' && !config.data) {
      config.data = {};
    }
    return config;
  });

  // 响应拦截
  instance.interceptors.response.use(
    (response) => {
      const data = response.data;
      // 处理空响应
      if (data === '' || data === null || data === undefined) {
        throw new Error('API返回空响应，可能需要更新参数');
      }
      if (typeof data === 'object' && data.err_no !== 0) {
        throw new Error(`API错误: [${data.err_no}] ${data.err_msg || '未知错误'}`);
      }
      return data.data;
    },
    (error) => {
      if (error.response) {
        const data = error.response.data;
        if (data && typeof data === 'object' && data.err_no !== undefined) {
          throw new Error(`API错误: [${data.err_no}] ${data.err_msg || '未知错误'}`);
        }
        throw new Error(`HTTP错误: ${error.response.status} ${error.response.statusText}`);
      }
      throw error;
    }
  );

  return instance;
}

// ==================== API 调用 ====================

/**
 * 检查今日签到状态
 */
async function getTodayStatus(api) {
  try {
    const data = await api.get('/growth_api/v1/get_today_status');
    return data === true;
  } catch (e) {
    log('⚠️ 查询签到状态失败: ' + e.message);
    return null;
  }
}

/**
 * 执行签到
 */
async function checkIn(api) {
  try {
    const data = await api.post('/growth_api/v1/check_in');
    log('✅ 签到成功！');
    return { success: true, data };
  } catch (e) {
    if (e.message.includes('15001') || e.message.includes('已签到') || e.message.includes('duplicate')) {
      log('📌 今日已签到，无需重复签到');
      return { success: true, already: true };
    }
    if (e.message.includes('3013')) {
      log('📌 今日已签到 (3013)');
      return { success: true, already: true };
    }
    if (e.message.includes('空响应')) {
      log('⚠️ API返回空响应，参数可能已过期，建议重新获取');
      return { success: false, error: e.message };
    }
    log('❌ 签到失败: ' + e.message);
    return { success: false, error: e.message };
  }
}

/**
 * 获取签到天数统计
 */
async function getCounts(api) {
  try {
    const data = await api.get('/growth_api/v1/get_counts');
    return data;
  } catch (e) {
    log('⚠️ 获取签到统计失败: ' + e.message);
    return null;
  }
}

/**
 * 获取当前矿石数
 */
async function getCurrentPoint(api) {
  try {
    const data = await api.get('/growth_api/v1/get_cur_point');
    return data;
  } catch (e) {
    log('⚠️ 获取矿石余额失败: ' + e.message);
    return null;
  }
}

/**
 * 获取抽奖配置
 */
async function getLotteryConfig(api) {
  try {
    const data = await api.get('/growth_api/v1/lottery_config/get');
    return data;
  } catch (e) {
    log('⚠️ 获取抽奖配置失败: ' + e.message);
    return null;
  }
}

/**
 * 免费抽奖
 */
async function drawLottery(api) {
  try {
    const data = await api.post('/growth_api/v1/lottery/draw');
    log('🎉 抽奖成功！奖品: ' + (data.lottery_name || '未知'));
    return { success: true, data };
  } catch (e) {
    log('❌ 抽奖失败: ' + e.message);
    return { success: false, error: e.message };
  }
}

/**
 * 沾喜气
 */
async function dipLucky(api) {
  try {
    // 先获取幸运用户列表
    const luckyUsers = await api.post('/growth_api/v1/lottery_history/global_big', {
      page_no: 1,
      page_size: 5,
    });

    if (luckyUsers && luckyUsers.lotteries && luckyUsers.lotteries.length > 0) {
      const historyId = luckyUsers.lotteries[0].history_id;
      const data = await api.post('/growth_api/v1/lottery_lucky/dip_lucky', {
        lottery_history_id: historyId,
      });
      log('🍀 沾喜气成功！幸运值: ' + (data.dip_value || 0));
      return { success: true, data };
    }
    log('⚠️ 暂无可沾喜气的用户');
    return { success: false };
  } catch (e) {
    log('❌ 沾喜气失败: ' + e.message);
    return { success: false, error: e.message };
  }
}

/**
 * 获取我的幸运值
 */
async function getMyLucky(api) {
  try {
    const data = await api.post('/growth_api/v1/lottery_lucky/my_lucky');
    return data;
  } catch (e) {
    log('⚠️ 获取幸运值失败: ' + e.message);
    return null;
  }
}

/**
 * 查询用户信息 (验证Cookie有效性)
 */
async function getUserInfo(api) {
  try {
    const data = await api.get('/user_api/v1/user/get');
    return data;
  } catch (e) {
    log('⚠️ Cookie无效或已过期: ' + e.message);
    return null;
  }
}

/**
 * 获取Bug消除配置
 */
async function getBugFixConfig(api) {
  try {
    const data = await api.get('/growth_api/v1/bugfix/not_collect');
    return data;
  } catch (e) {
    log('⚠️ 获取Bug配置失败: ' + e.message);
    return null;
  }
}

/**
 * 消除Bug
 */
async function fixBug(api, bugId) {
  try {
    const data = await api.post('/growth_api/v1/bugfix/collect', {
      bug_type: bugId,
    });
    log('🐛 Bug消除成功！');
    return { success: true, data };
  } catch (e) {
    log('❌ Bug消除失败: ' + e.message);
    return { success: false, error: e.message };
  }
}

// ==================== 青龙面板通知 ====================

/**
 * 青龙面板通知推送
 */
async function sendNotify(title, content) {
  if (process.env.JUEJIN_NOTIFY === 'false') {
    log('📢 通知已禁用');
    return;
  }

  try {
    // 尝试加载青龙面板的通知模块
    const notifyPath = require('path').join(process.cwd(), 'notify.js');
    if (require('fs').existsSync(notifyPath)) {
      const sendNotifyFn = require(notifyPath);
      if (typeof sendNotifyFn === 'function') {
        await sendNotifyFn(title, content);
        log('📢 青龙通知已发送');
        return;
      }
    }

    // 尝试从全局加载
    try {
      const { sendNotify: qinglongNotify } = require('qlnotify');
      await qinglongNotify(title, content);
      log('📢 青龙通知已发送');
      return;
    } catch (e) {
      // 忽略
    }

    log('📢 青龙通知模块未找到，仅控制台输出');
  } catch (e) {
    log('⚠️ 发送通知失败: ' + e.message);
  }
}

// ==================== 单个账号签到流程 ====================

async function runAccount(cookie, params, index) {
  const prefix = index > 1 ? `[账号${index}] ` : '';
  log('');
  log(`${prefix}═══════════════════════════════════════`);
  log(`${prefix}   开始处理账号 ${index}`);
  log(`${prefix}═══════════════════════════════════════`);

  if (!cookie || cookie.trim().length === 0) {
    log(`${prefix}❌ Cookie为空，跳过`);
    return null;
  }

  // 创建API客户端
  const api = createApiClient(cookie, params);

  // 验证Cookie有效性
  log(`${prefix}🔍 验证Cookie...`);
  const userInfo = await getUserInfo(api);
  if (!userInfo) {
    log(`${prefix}❌ Cookie已失效，请重新获取`);
    return {
      success: false,
      error: 'Cookie已失效',
      userName: '未知用户',
    };
  }

  const userName = userInfo.user_name || userInfo.nick_name || '未知用户';
  log(`${prefix}✅ Cookie有效！用户: ${userName}`);

  // 签到
  log(`${prefix}📅 执行签到...`);
  const todayStatus = await getTodayStatus(api);
  let signInResult = { success: true, already: todayStatus === true };

  if (todayStatus === true) {
    log(`${prefix}📌 今日已签到，跳过`);
  } else if (todayStatus === false) {
    signInResult = await checkIn(api);
    if (!signInResult.success) {
      log(`${prefix}🔄 签到失败，1秒后重试...`);
      await sleep(1000);
      signInResult = await checkIn(api);
    }
  } else {
    log(`${prefix}⚠️ 无法查询签到状态，直接尝试签到...`);
    signInResult = await checkIn(api);
  }

  // 抽奖
  log(`${prefix}🎰 执行抽奖...`);
  const lotteryConfig = await getLotteryConfig(api);
  let lotteryResult = { success: false };
  if (lotteryConfig && lotteryConfig.free_count > 0) {
    log(`${prefix}🎁 有 ${lotteryConfig.free_count} 次免费抽奖机会`);
    lotteryResult = await drawLottery(api);
  } else if (lotteryConfig) {
    log(`${prefix}📌 今日免费抽奖次数已用完`);
  }

  // 沾喜气
  log(`${prefix}🍀 沾喜气...`);
  const dipResult = await dipLucky(api);

  // Bug消除
  log(`${prefix}🐛 消除Bug...`);
  const bugConfig = await getBugFixConfig(api);
  let bugFixResult = { success: false };
  if (bugConfig && Array.isArray(bugConfig) && bugConfig.length > 0) {
    const bug = bugConfig[0];
    log(`${prefix}🔧 发现未消除的Bug: ${bug.bug_type}`);
    bugFixResult = await fixBug(api, bug.bug_type);
  } else {
    log(`${prefix}📌 暂无Bug可消除`);
  }

  // 查询统计信息
  log(`${prefix}📊 查询统计...`);
  const counts = await getCounts(api);
  const point = await getCurrentPoint(api);
  const lucky = await getMyLucky(api);

  if (counts) {
    log(`${prefix}📅 连续签到: ${counts.cont_count || 0} 天`);
    log(`${prefix}📅 累计签到: ${counts.sum_count || 0} 天`);
  }
  if (point !== null) {
    log(`${prefix}💰 当前矿石: ${point}`);
  }
  if (lucky) {
    log(`${prefix}🍀 幸运值: ${lucky.total_value || 0}`);
  }

  log(`${prefix}✅ 账号处理完成`);

  return {
    success: true,
    userName,
    signIn: signInResult,
    lottery: lotteryResult,
    dip: dipResult,
    bugFix: bugFixResult,
    counts,
    point,
    lucky,
  };
}

// ==================== 主流程 ====================

async function main() {
  log('═══════════════════════════════════════');
  log('   掘金自动签到脚本 v1.0.0');
  log('═══════════════════════════════════════');

  // 收集所有账号的配置
  const accounts = [];

  // 主账号
  const mainCookie = process.env.JUEJIN_COOKIE || '';
  const mainParams = {
    aid: process.env.JUEJIN_AID || '2608',
    uuid: process.env.JUEJIN_UUID || '',
    msToken: process.env.JUEJIN_MSTOKEN || '',
    a_bogus: process.env.JUEJIN_A_BOGUS || '',
    spider: '0',
  };

  if (mainCookie) {
    accounts.push({ cookie: mainCookie, params: mainParams });
  }

  // 多账号支持
  for (let i = 2; i <= 5; i++) {
    const cookie = process.env[`JUEJIN_COOKIE_${i}`] || '';
    if (cookie) {
      accounts.push({
        cookie,
        params: {
          aid: process.env[`JUEJIN_AID_${i}`] || mainParams.aid,
          uuid: process.env[`JUEJIN_UUID_${i}`] || '',
          msToken: process.env[`JUEJIN_MSTOKEN_${i}`] || '',
          a_bogus: process.env[`JUEJIN_A_BOGUS_${i}`] || '',
          spider: '0',
        },
      });
    }
  }

  if (accounts.length === 0) {
    log('');
    log('❌ 未配置Cookie，请设置环境变量 JUEJIN_COOKIE');
    log('');
    log('【参数获取方式】');
    log('1. 浏览器打开 https://juejin.cn 并登录');
    log('2. 按F12打开开发者工具 -> Network(网络)标签');
    log('3. 刷新页面，找到任意一个 api.juejin.cn 的请求');
    log('4. 在 Request Headers 中复制完整的 Cookie 值');
    log('5. 在 Query String Parameters 中复制 aid, uuid, msToken, a_bogus');
    log('6. 粘贴到青龙面板对应的环境变量中');
    log('');
    process.exit(1);
  }

  log(`📱 共配置 ${accounts.length} 个账号`);

  // 执行每个账号的签到
  const results = [];
  for (let i = 0; i < accounts.length; i++) {
    const result = await runAccount(accounts[i].cookie, accounts[i].params, i + 1);
    if (result) results.push(result);
  }

  // 生成通知内容
  log('');
  log('📢 发送通知...');

  let notifyTitle = '掘金每日签到报告';
  let notifyContent = '';

  for (let i = 0; i < results.length; i++) {
    const r = results[i];
    const prefix = results.length > 1 ? `【账号${i + 1}】` : '';

    if (!r.success) {
      notifyContent += `${prefix}❌ ${r.userName}: ${r.error}\n`;
      continue;
    }

    notifyContent += `${prefix}👤 ${r.userName}\n`;
    notifyContent += `  📅 连续签到: ${r.counts?.cont_count || 0} 天\n`;
    notifyContent += `  📅 累计签到: ${r.counts?.sum_count || 0} 天\n`;
    notifyContent += `  💰 当前矿石: ${r.point ?? '未知'}\n`;
    notifyContent += `  🍀 幸运值: ${r.lucky?.total_value || 0}\n`;
    notifyContent += `  ✅ 签到: ${r.signIn.already ? '今日已签到' : r.signIn.success ? '成功' : '失败'}\n`;
    notifyContent += `  🎰 抽奖: ${r.lottery.success ? '成功 - ' + (r.lottery.data?.lottery_name || '') : '未抽奖/失败'}\n`;
    notifyContent += `  🍀 沾喜气: ${r.dip.success ? '成功' : '失败'}\n`;
    notifyContent += `  🐛 Bug消除: ${r.bugFix.success ? '成功' : '无/失败'}\n`;
    notifyContent += '\n';
  }

  await sendNotify(notifyTitle, notifyContent);

  log('');
  log('═══════════════════════════════════════');
  log('   脚本执行完成！');
  log('═══════════════════════════════════════');
}

// 执行主函数
main().catch((error) => {
  log('💥 脚本异常退出: ' + error.message);
  console.error(error);
  process.exit(1);
});
