creditdaddy 0.9.5 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,96 +1,97 @@
1
- /**
2
- * ZCode 活动自动领取 — 签到调度器每轮调用。
3
- *
4
- * 策略(对齐用户手动路径,逐级尝试):
5
- * 1. billing/preview 查可领活动;为空 → 无事可做(返回 null,不留痕迹)
6
- * 2. 先直接 claim(不带验证码:服务端未风控时可直接成功)
7
- * 3. 返回 3007/3001(需要验证码 / 参数被拒)且有验证码提供者 → 拉 captcha 配置,
8
- * 让提供者(桌面版的隐藏窗口跑阿里云验证码 SDK 静默验证)拿 captchaVerifyParam 后重试
9
- * 4. 没有提供者(NAS / 纯 CLI)或验证码需要人工 → 标记「需手动领取」,卡片上提示
10
- * - 1003(已领取过)按成功口径处理并记忆
11
- * 结果写入账号 lastResult(签到日历记忆用的是 status checked-in/already,第二天照常重查 preview)
12
- */
13
-
14
- import { logger } from './logger.js';
15
- import { fetchClaimPlans, claimPlan, fetchCaptchaConfig } from './zcodeClient.js';
16
-
17
- // 桌面版(Electron 主进程)注册的隐藏窗口验证码实现;NAS / CLI 为 null(走「需手动领取」分支)
18
- let captchaProvider = null;
19
- export function setZcodeCaptchaProvider(fn) { captchaProvider = typeof fn === 'function' ? fn : null; }
20
- export function hasZcodeCaptchaProvider() { return Boolean(captchaProvider); }
21
-
22
- const grantsText = (plan) => (plan.grants && plan.grants.length ? plan.grants.join(';') : '');
23
-
24
- /**
25
- * 为单个 ZCode 账号执行一次自动领取。
26
- * @returns {null | { status, message, claims: Array }} null = preview 为空或查询失败(已记日志,不上卡片)
27
- */
28
- export async function zcodeAutoClaim(account) {
29
- const label = account.name || account.uid || account.id;
30
- let plans;
31
- try {
32
- plans = (await fetchClaimPlans(account)).plans;
33
- } catch (e) {
34
- logger.debug('ZCODE-CLAIM', `${label} 活动查询失败:${e.message}`);
35
- return null;
36
- }
37
- if (!plans.length) return null;
38
-
39
- const claims = [];
40
- let anySuccess = false;
41
- let needManual = false;
42
-
43
- for (const plan of plans) {
44
- const planName = plan.name || plan.planId;
45
- // 第 2 步:先试不带验证码
46
- try {
47
- const r = await claimPlan(account, plan.planId, {});
48
- claims.push({ plan: planName, via: 'direct', ok: true });
49
- anySuccess = true;
50
- logger.info('ZCODE-CLAIM', `${label} 已领取「${planName}」(免验证码)${grantsText(plan) ? ':' + grantsText(plan) : ''}`);
51
- continue;
52
- } catch (e) {
53
- if (e.code === 1003) {
54
- claims.push({ plan: planName, ok: true, already: true });
55
- logger.info('ZCODE-CLAIM', `${label}「${planName}」已领取过`);
56
- continue;
57
- }
58
- if (e.code !== 3007 && e.code !== 3001) {
59
- claims.push({ plan: planName, ok: false, message: e.message });
60
- logger.warn('ZCODE-CLAIM', `${label} 领取「${planName}」失败:${e.message}`);
61
- continue;
62
- }
63
- }
64
- // 第 3 步:需要验证码
65
- if (!captchaProvider) {
66
- needManual = true;
67
- claims.push({ plan: planName, ok: false, needManual: true });
68
- logger.info('ZCODE-CLAIM', `${label}「${planName}」需要验证码,本环境无法自动通过,请在面板手动领取`);
69
- continue;
70
- }
71
- try {
72
- const cfg = await fetchCaptchaConfig();
73
- if (!cfg.enabled || !cfg.sceneId) throw new Error('验证码配置不可用');
74
- const { captchaParam, region } = await captchaProvider(cfg);
75
- await claimPlan(account, plan.planId, { captchaParam, region });
76
- claims.push({ plan: planName, via: 'captcha', ok: true });
77
- anySuccess = true;
78
- logger.info('ZCODE-CLAIM', `${label} 已领取「${planName}」(静默验证码)${grantsText(plan) ? ':' + grantsText(plan) : ''}`);
79
- } catch (e2) {
80
- needManual = true;
81
- claims.push({ plan: planName, ok: false, needManual: true, message: e2.message });
82
- logger.warn('ZCODE-CLAIM', `${label}「${planName}」验证码未完成:${e2.message}(可在面板手动领取)`);
83
- }
84
- }
85
-
86
- const names = claims.filter((c) => c.ok && !c.already).map((c) => c.plan);
87
- const status = names.length ? 'checked-in'
88
- : claims.every((c) => c.already) ? 'already'
89
- : 'failed';
90
- const message = status === 'checked-in'
91
- ? `已领取:${names.join('、')}${claims.some((c) => c.via === 'captcha') ? '(静默验证码)' : ''}`
92
- : status === 'already' ? '活动均已领取过'
93
- : needManual ? `有 ${claims.filter((c) => c.needManual).length} 个活动需要验证码,请在面板手动领取`
94
- : `领取失败:${claims.filter((c) => !c.ok).map((c) => c.message).filter(Boolean)[0] || '未知错误'}`;
95
- return { status, message, claims };
96
- }
1
+ /**
2
+ * ZCode 活动自动领取 — 签到调度器每轮调用。
3
+ *
4
+ * 策略(对齐用户手动路径,逐级尝试):
5
+ * 1. billing/preview 查可领活动;为空 → 无事可做(返回 null,不留痕迹)
6
+ * 2. 先直接 claim(不带验证码:服务端未风控时可直接成功)
7
+ * 3. 返回 3007/3001(需要验证码 / 参数被拒)且有验证码提供者 → 拉 captcha 配置,
8
+ * 让提供者(桌面版的隐藏窗口跑阿里云验证码 SDK 静默验证)拿 captchaVerifyParam 后重试
9
+ * 4. 没有提供者(NAS / 纯 CLI)或验证码需要人工 → 标记「需手动领取」,卡片上提示
10
+ * - 1003(已领取过)按成功口径处理并记忆
11
+ * 结果写入账号 lastResult(签到日历记忆用的是 status checked-in/already,第二天照常重查 preview)
12
+ */
13
+
14
+ import { logger } from './logger.js';
15
+ import { fetchClaimPlans, claimPlan, fetchCaptchaConfig } from './zcodeClient.js';
16
+
17
+ // 桌面版(Electron 主进程)注册的隐藏窗口验证码实现;NAS / CLI 为 null(走「需手动领取」分支)
18
+ let captchaProvider = null;
19
+ export function setZcodeCaptchaProvider(fn) { captchaProvider = typeof fn === 'function' ? fn : null; }
20
+ export function hasZcodeCaptchaProvider() { return Boolean(captchaProvider); }
21
+ export function getZcodeCaptchaProvider() { return captchaProvider; }
22
+
23
+ const grantsText = (plan) => (plan.grants && plan.grants.length ? plan.grants.join(';') : '');
24
+
25
+ /**
26
+ * 为单个 ZCode 账号执行一次自动领取。
27
+ * @returns {null | { status, message, claims: Array }} null = preview 为空或查询失败(已记日志,不上卡片)
28
+ */
29
+ export async function zcodeAutoClaim(account) {
30
+ const label = account.name || account.uid || account.id;
31
+ let plans;
32
+ try {
33
+ plans = (await fetchClaimPlans(account)).plans;
34
+ } catch (e) {
35
+ logger.debug('ZCODE-CLAIM', `${label} 活动查询失败:${e.message}`);
36
+ return null;
37
+ }
38
+ if (!plans.length) return null;
39
+
40
+ const claims = [];
41
+ let anySuccess = false;
42
+ let needManual = false;
43
+
44
+ for (const plan of plans) {
45
+ const planName = plan.name || plan.planId;
46
+ // 第 2 步:先试不带验证码
47
+ try {
48
+ const r = await claimPlan(account, plan.planId, {});
49
+ claims.push({ plan: planName, via: 'direct', ok: true });
50
+ anySuccess = true;
51
+ logger.info('ZCODE-CLAIM', `${label} 已领取「${planName}」(免验证码)${grantsText(plan) ? ':' + grantsText(plan) : ''}`);
52
+ continue;
53
+ } catch (e) {
54
+ if (e.code === 1003) {
55
+ claims.push({ plan: planName, ok: true, already: true });
56
+ logger.info('ZCODE-CLAIM', `${label}「${planName}」已领取过`);
57
+ continue;
58
+ }
59
+ if (e.code !== 3007 && e.code !== 3001) {
60
+ claims.push({ plan: planName, ok: false, message: e.message });
61
+ logger.warn('ZCODE-CLAIM', `${label} 领取「${planName}」失败:${e.message}`);
62
+ continue;
63
+ }
64
+ }
65
+ // 第 3 步:需要验证码
66
+ if (!captchaProvider) {
67
+ needManual = true;
68
+ claims.push({ plan: planName, ok: false, needManual: true });
69
+ logger.info('ZCODE-CLAIM', `${label}「${planName}」需要验证码,本环境无法自动通过,请在面板手动领取`);
70
+ continue;
71
+ }
72
+ try {
73
+ const cfg = await fetchCaptchaConfig();
74
+ if (!cfg.enabled || !cfg.sceneId) throw new Error('验证码配置不可用');
75
+ const { captchaParam, region } = await captchaProvider(cfg);
76
+ await claimPlan(account, plan.planId, { captchaParam, region });
77
+ claims.push({ plan: planName, via: 'captcha', ok: true });
78
+ anySuccess = true;
79
+ logger.info('ZCODE-CLAIM', `${label} 已领取「${planName}」(静默验证码)${grantsText(plan) ? ':' + grantsText(plan) : ''}`);
80
+ } catch (e2) {
81
+ needManual = true;
82
+ claims.push({ plan: planName, ok: false, needManual: true, message: e2.message });
83
+ logger.warn('ZCODE-CLAIM', `${label}「${planName}」验证码未完成:${e2.message}(可在面板手动领取)`);
84
+ }
85
+ }
86
+
87
+ const names = claims.filter((c) => c.ok && !c.already).map((c) => c.plan);
88
+ const status = names.length ? 'checked-in'
89
+ : claims.every((c) => c.already) ? 'already'
90
+ : 'failed';
91
+ const message = status === 'checked-in'
92
+ ? `已领取:${names.join('、')}${claims.some((c) => c.via === 'captcha') ? '(静默验证码)' : ''}`
93
+ : status === 'already' ? '活动均已领取过'
94
+ : needManual ? `有 ${claims.filter((c) => c.needManual).length} 个活动需要验证码,请在面板手动领取`
95
+ : `领取失败:${claims.filter((c) => !c.ok).map((c) => c.message).filter(Boolean)[0] || '未知错误'}`;
96
+ return { status, message, claims };
97
+ }