mslxdff 0.1.199 → 0.1.203
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.
- package/README.md +3 -3
- package/bin/mslxdff.js +1 -1
- package/package.json +38 -38
- package/plugins/README.md +14 -14
- package/plugins/prefer-model.mjs.example +14 -14
- package/src/anthropic/count-tokens.js +61 -61
- package/src/anthropic/request-body.js +126 -126
- package/src/anthropic/shared.js +18 -18
- package/src/anthropic/sse-aggregate.js +56 -56
- package/src/anthropic/translate.js +287 -287
- package/src/anthropic/web-search.js +361 -361
- package/src/api-kind.js +31 -31
- package/src/autostart.js +288 -288
- package/src/bench/probe.js +1 -1
- package/src/bench/runner.js +1 -1
- package/src/bench/via-probe.js +1 -1
- package/src/bench/via.js +144 -144
- package/src/bench/workbuddy-bench.js +1 -1
- package/src/chat/config.js +11 -11
- package/src/chat/cooling.js +81 -81
- package/src/chat/direct.js +58 -58
- package/src/chat/index.js +6 -6
- package/src/chat/spinner.js +38 -38
- package/src/chat/sse.js +69 -69
- package/src/chat/stats.js +247 -247
- package/src/chat/store.js +48 -48
- package/src/chat/tool-handlers.js +67 -67
- package/src/chat/tools.js +1 -1
- package/src/chat/upstream.js +59 -59
- package/src/chat-pipeline/auto-race.js +158 -158
- package/src/chat-pipeline/empty-turn.js +147 -147
- package/src/chat-pipeline/engine.js +17 -17
- package/src/chat-pipeline/serial-trial.js +283 -283
- package/src/chat-pipeline/terminal-verdict.js +147 -147
- package/src/chooser.js +54 -54
- package/src/claude-desktop/apply.js +101 -101
- package/src/claude-desktop/context1m.js +38 -38
- package/src/claude-desktop/doctor.js +146 -146
- package/src/claude-desktop/slots.js +152 -152
- package/src/cli/bootstrap.js +1 -1
- package/src/cli/commands/claude-desktop.js +284 -284
- package/src/cli/commands/daemon.js +231 -231
- package/src/cli/commands/model/list-live.js +22 -22
- package/src/cli/commands/model/list-providers.js +76 -76
- package/src/cli/commands/model/list-render.js +77 -77
- package/src/cli/commands/model/list-sort.js +52 -52
- package/src/cli/commands/model/list-tty.js +76 -76
- package/src/cli/commands/model/list.js +166 -166
- package/src/cli/commands/model/live-models.js +24 -24
- package/src/cli/commands/model/stats.js +43 -43
- package/src/cli/commands/model/status.js +47 -47
- package/src/cli/commands/model.js +51 -51
- package/src/cli/commands/provider/add.js +108 -108
- package/src/cli/commands/provider/allowlist.js +99 -99
- package/src/cli/commands/provider/cline-free.js +99 -99
- package/src/cli/commands/provider/cline-login.js +218 -218
- package/src/cli/commands/provider/cline-quota.js +65 -65
- package/src/cli/commands/provider/codearts-login.js +45 -45
- package/src/cli/commands/provider/config.js +119 -119
- package/src/cli/commands/provider/globalqwenwork-login.js +126 -126
- package/src/cli/commands/provider/keys-guard.js +50 -50
- package/src/cli/commands/provider/keys.js +161 -161
- package/src/cli/commands/provider/qoder-checkin.js +81 -81
- package/src/cli/commands/provider/qoder-login.js +102 -102
- package/src/cli/commands/provider/raccoon-login.js +180 -180
- package/src/cli/commands/provider/raccoon-password.js +162 -162
- package/src/cli/commands/provider/raccoon-quota.js +109 -109
- package/src/cli/commands/provider/traework-checkin.js +144 -144
- package/src/cli/commands/provider/traework-login.js +164 -164
- package/src/cli/commands/provider/workbuddy-login.js +153 -153
- package/src/cli/commands/provider/zcode-login.js +77 -77
- package/src/cli/commands/provider/zcode-quota.js +55 -55
- package/src/cli/commands/provider.js +1 -1
- package/src/cli/commands/stats.js +149 -149
- package/src/cli/commands/system.js +261 -261
- package/src/cli/commands/timezone.js +47 -47
- package/src/cli/commands/use-group.js +60 -60
- package/src/cli/commands/workbuddy.js +189 -189
- package/src/cli/format.js +141 -141
- package/src/cli/group-helpers.js +70 -70
- package/src/cli/help.js +80 -80
- package/src/cli/index.js +70 -70
- package/src/cli/interactive.js +121 -121
- package/src/cli/join-core.js +99 -99
- package/src/cli/join-wizard.js +175 -175
- package/src/cli/policy.js +136 -136
- package/src/cli/provider-row.js +126 -126
- package/src/cli/util.js +24 -24
- package/src/compat.js +53 -53
- package/src/events.js +38 -38
- package/src/free-lane.js +131 -131
- package/src/free-watcher.js +63 -63
- package/src/groups.js +262 -262
- package/src/logs.js +195 -195
- package/src/metrics.js +62 -62
- package/src/model-capabilities/context-lookup.js +65 -65
- package/src/model-capabilities/merge.js +142 -142
- package/src/model-trace.js +187 -187
- package/src/models.js +1 -1
- package/src/opencode-identity.js +72 -72
- package/src/peers.js +254 -251
- package/src/plugins.js +107 -107
- package/src/providers/base.js +164 -164
- package/src/providers/classify.js +22 -22
- package/src/providers/cline/allowlist-sync.js +93 -93
- package/src/providers/cline/free-catalog.js +71 -71
- package/src/providers/cline/headers.js +37 -37
- package/src/providers/cline/index.js +130 -130
- package/src/providers/cline/models.js +150 -150
- package/src/providers/cline/usage.js +274 -274
- package/src/providers/codearts/auth-pool.js +148 -148
- package/src/providers/codearts/concurrency.js +34 -34
- package/src/providers/codearts/const.js +65 -65
- package/src/providers/codearts/dpop.js +95 -95
- package/src/providers/codearts/index.js +175 -175
- package/src/providers/codearts/login.js +214 -214
- package/src/providers/codearts/models.js +182 -182
- package/src/providers/codearts/sign.js +96 -96
- package/src/providers/codearts/sse.js +204 -204
- package/src/providers/codearts/stream.js +209 -209
- package/src/providers/codearts/sts.js +124 -124
- package/src/providers/codearts.js +1 -1
- package/src/providers/dispatcher.js +146 -146
- package/src/providers/generic.js +156 -156
- package/src/providers/globalqwenwork/account-store.js +141 -141
- package/src/providers/globalqwenwork/constants.js +73 -73
- package/src/providers/globalqwenwork/crypto.js +2 -2
- package/src/providers/globalqwenwork/http.js +2 -2
- package/src/providers/globalqwenwork/index.js +331 -331
- package/src/providers/globalqwenwork/payload.js +147 -147
- package/src/providers/globalqwenwork/rsa.js +2 -2
- package/src/providers/globalqwenwork/sse.js +2 -2
- package/src/providers/globalqwenwork/stream.js +2 -2
- package/src/providers/globalqwenwork.js +1 -1
- package/src/providers/globalworkbuddy/account-store.js +198 -198
- package/src/providers/globalworkbuddy/auth.js +97 -97
- package/src/providers/globalworkbuddy/catalog.js +138 -138
- package/src/providers/globalworkbuddy/constants.js +73 -73
- package/src/providers/globalworkbuddy/device-auth.js +120 -120
- package/src/providers/globalworkbuddy/errors.js +98 -98
- package/src/providers/globalworkbuddy/headers.js +89 -89
- package/src/providers/globalworkbuddy/models.js +96 -96
- package/src/providers/globalworkbuddy/payload.js +80 -80
- package/src/providers/index.js +5 -5
- package/src/providers/model-id.js +172 -172
- package/src/providers/opencode.js +19 -19
- package/src/providers/openrouter.js +31 -31
- package/src/providers/qoder/account-store.js +106 -106
- package/src/providers/qoder/aggregate.js +60 -60
- package/src/providers/qoder/baseprompt.json +591 -591
- package/src/providers/qoder/checkin.js +160 -160
- package/src/providers/qoder/constants.js +44 -44
- package/src/providers/qoder/encode.js +41 -41
- package/src/providers/qoder/fingerprint.js +38 -38
- package/src/providers/qoder/models.js +77 -77
- package/src/providers/qoder/oauth.js +84 -84
- package/src/providers/qoder/payload.js +162 -162
- package/src/providers/qoder/request.js +27 -27
- package/src/providers/qoder/session.js +134 -134
- package/src/providers/qoder/sticky.js +38 -38
- package/src/providers/qoder/stream.js +116 -116
- package/src/providers/qoder.js +1 -1
- package/src/providers/raccoon/account-store.js +216 -216
- package/src/providers/raccoon/auth.js +67 -67
- package/src/providers/raccoon/chat.js +228 -228
- package/src/providers/raccoon/const.js +180 -165
- package/src/providers/raccoon/credits.js +185 -175
- package/src/providers/raccoon/crypto.js +43 -0
- package/src/providers/raccoon/envelope.js +31 -31
- package/src/providers/raccoon/headers.js +45 -45
- package/src/providers/raccoon/index.js +216 -216
- package/src/providers/raccoon/login.js +279 -279
- package/src/providers/raccoon/models.js +160 -160
- package/src/providers/raccoon/password-login.js +102 -87
- package/src/providers/raccoon/qr-codewords.js +115 -115
- package/src/providers/raccoon/qr.js +236 -236
- package/src/providers/raccoon/sse.js +135 -135
- package/src/providers/responses-channel.js +120 -120
- package/src/providers/share-keys.js +53 -53
- package/src/providers/traework/account-store.js +234 -234
- package/src/providers/traework/chat.js +217 -217
- package/src/providers/traework/checkin.js +77 -77
- package/src/providers/traework/constants.js +41 -41
- package/src/providers/traework/errors.js +52 -52
- package/src/providers/traework/headers.js +79 -79
- package/src/providers/traework/index.js +132 -132
- package/src/providers/traework/market-identity.js +116 -116
- package/src/providers/traework/models.js +98 -98
- package/src/providers/traework/payload.js +86 -86
- package/src/providers/traework/sse.js +184 -184
- package/src/providers/traework/token.js +52 -52
- package/src/providers/traework.js +2 -2
- package/src/providers/workbuddy/account-store.js +186 -186
- package/src/providers/workbuddy/auth.js +158 -158
- package/src/providers/workbuddy/balance.js +86 -86
- package/src/providers/workbuddy/cat-travel.js +125 -125
- package/src/providers/workbuddy/checkin.js +75 -75
- package/src/providers/workbuddy/desktop-info.js +78 -78
- package/src/providers/workbuddy/growth-api.js +67 -67
- package/src/providers/workbuddy/growth-plans.js +63 -63
- package/src/providers/workbuddy/growth.js +181 -181
- package/src/providers/workbuddy/index.js +217 -217
- package/src/providers/workbuddy/models.js +126 -126
- package/src/providers/workbuddy/payload.js +141 -141
- package/src/providers/workbuddy/rotation-log.js +83 -83
- package/src/providers/workbuddy/sanitize-tools.js +61 -61
- package/src/providers/workbuddy/sdk-chat.js +26 -26
- package/src/providers/workbuddy-balance.js +78 -78
- package/src/providers/zcode/account-store.js +129 -129
- package/src/providers/zcode/auth.js +28 -28
- package/src/providers/zcode/chat.js +179 -179
- package/src/providers/zcode/const.js +54 -54
- package/src/providers/zcode/context-shape.js +162 -162
- package/src/providers/zcode/headers.js +93 -93
- package/src/providers/zcode/index.js +124 -124
- package/src/providers/zcode/models.js +65 -65
- package/src/providers/zcode/oauth.js +120 -120
- package/src/providers/zcode/quota.js +176 -176
- package/src/providers/zcode/sse.js +196 -196
- package/src/readline-compat.js +25 -25
- package/src/responses/translate.js +311 -311
- package/src/routes/chat/broadband-handler.js +72 -72
- package/src/routes/chat/empty-turn-report.js +31 -31
- package/src/routes/chat/exhausted-handler.js +87 -87
- package/src/routes/chat/hedge-handler.js +130 -130
- package/src/routes/chat/index.js +1 -1
- package/src/routes/chat/local-handler.js +63 -63
- package/src/routes/chat/peer-handler.js +81 -81
- package/src/routes/chat.js +3 -3
- package/src/routes/fallback.js +88 -88
- package/src/routes/groups-relay.js +214 -214
- package/src/routes/groups.js +122 -122
- package/src/routes/helpers.js +83 -83
- package/src/routes/index.js +147 -147
- package/src/routes/messages-route.js +365 -365
- package/src/routes/peers.js +23 -1
- package/src/routes/relay-queue.js +181 -181
- package/src/routes/relay.js +60 -60
- package/src/routes/responses-route.js +213 -213
- package/src/routes/stream-body.js +84 -84
- package/src/routes/stream-hold.js +337 -337
- package/src/routes/stream-scan.js +366 -366
- package/src/routes.js +3 -3
- package/src/runtime/auto-update.js +113 -113
- package/src/runtime/bootstrap.js +8 -0
- package/src/runtime/broadband-stream.js +79 -79
- package/src/runtime/broadband.js +103 -103
- package/src/runtime/group-sync.js +81 -81
- package/src/runtime/keep-warm.js +120 -0
- package/src/runtime/lifecycle-forensics.js +116 -116
- package/src/runtime/lifecycle-log.js +87 -87
- package/src/runtime/log-stamp.js +73 -73
- package/src/runtime/proc-info.js +137 -137
- package/src/runtime/qoder-checkin.js +93 -93
- package/src/runtime/raccoon-checkin.js +126 -126
- package/src/runtime/server-lifecycle.js +189 -189
- package/src/runtime/traework-checkin.js +118 -118
- package/src/runtime/workbuddy-checkin.js +120 -120
- package/src/runtime/workbuddy-growth.js +133 -133
- package/src/server.js +7 -0
- package/src/state/facade.js +58 -58
- package/src/state/memory.js +162 -162
- package/src/state/merge.js +25 -25
- package/src/state/migrations/cline-unify.js +94 -94
- package/src/state/migrations.js +33 -33
- package/src/state/persist.js +42 -42
- package/src/state/provider-config.js +142 -142
- package/src/state/schemas/group.js +31 -31
- package/src/state/schemas/model.js +94 -94
- package/src/state/schemas/peer.js +31 -31
- package/src/state/schemas/port.js +10 -10
- package/src/state/schemas/provider.js +202 -202
- package/src/state/schemas/timezone.js +70 -70
- package/src/state/schemas/token.js +48 -48
- package/src/state/schemas/use-group.js +102 -102
- package/src/state/store.js +176 -176
- package/src/state.js +1 -1
- package/src/sync-claude-desktop.js +234 -234
- package/src/sync-claude.js +152 -152
- package/src/sync-codex.js +116 -116
- package/src/sync-workbuddy.js +158 -158
- package/src/talk-full-redact.js +129 -129
- package/src/talk-full.js +131 -131
- package/src/talk-log.js +257 -257
- package/src/text-tokens.js +52 -52
- package/src/thinking-effort.js +67 -67
- package/src/time.js +106 -106
- package/src/timeline.js +26 -26
- package/src/transport/index.js +1 -1
- package/src/upstream-engine/index.js +74 -72
- package/src/upstream-engine/mode.js +15 -15
- package/src/upstream-engine/sdk/attempt.js +221 -221
- package/src/upstream-engine/sdk/chat.js +28 -28
- package/src/upstream-engine/sdk/convert.js +192 -192
- package/src/upstream-engine/sdk/diagnose.js +62 -62
- package/src/upstream-engine/sdk/dispatch.js +55 -55
- package/src/upstream-engine/sdk/responses.js +176 -176
- package/src/upstream-engine/sdk/sse.js +166 -166
- package/src/upstream-responses.js +305 -305
- package/src/upstream.js +53 -1
- package/src/usage/record.js +106 -106
- package/src/usage/report.js +195 -195
- package/src/v6pool/claim.js +157 -157
- package/src/v6pool/config.js +65 -65
- package/src/v6pool/detect.js +130 -130
- package/src/v6pool/index.js +152 -152
- package/src/v6pool/prefix.js +140 -140
- package/src/v6pool/probe.js +40 -40
- package/src/v6pool/report.js +104 -104
- package/src/v6pool/rotate.js +263 -239
- package/src/warp-pool/config.js +74 -74
- package/src/warp-pool/health.js +106 -106
- package/src/warp-pool/identity.js +141 -141
- package/src/warp-pool/index.js +358 -358
- package/src/warp-pool/keys.js +29 -29
- package/src/warp-pool/nodes.js +95 -95
- package/src/warp-pool/ports.js +160 -160
- package/src/warp-pool/register.js +113 -113
- package/src/warp-pool/report.js +232 -232
- package/src/warp-pool/revive.js +168 -168
- package/src/warp-pool/rotate.js +214 -214
- package/src/warp-pool/strategy.js +43 -43
- package/src/warp-pool/verdict.js +69 -69
- package/src/warp-pool/wireproxy.js +162 -162
- package/docs/cli_help_mini.md +0 -146
- package/src/providers/AGENTS.md +0 -49
- package/src/routes/AGENTS.md +0 -37
|
@@ -1,162 +1,162 @@
|
|
|
1
|
-
// mslxdff -provider raccoon login --password —— 手机号 + 密码登录(多账号免扫码)。
|
|
2
|
-
//
|
|
3
|
-
// 为什么需要它:扫码登录一次只能加一个号,且要手机在手边;密码登录可以在同一个终端里
|
|
4
|
-
// 连着把多个号加完(脚本化也行),是「批量补号」的正路。
|
|
5
|
-
//
|
|
6
|
-
// 安全:密码**只经手本进程内存**,绝不落盘、绝不打印、绝不进 argv(除非用户显式 `--password=xxx`,
|
|
7
|
-
// 那种情况会在回执里提示一次「密码已进 shell 历史」)。落盘的是 token,与扫码登录同一条路。
|
|
8
|
-
import { compatFetch } from "../../../compat.js";
|
|
9
|
-
import { loginRaccoonWithPassword, normalizePhone } from "../../../providers/raccoon/password-login.js";
|
|
10
|
-
import { finishRaccoonLogin } from "./raccoon-login.js";
|
|
11
|
-
|
|
12
|
-
const RELOGIN_HINT = " (可重试:mslxdff -provider raccoon login --password)";
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
* 从 rest 里取 `--key=value` 或 `--key value` 两种写法。
|
|
16
|
-
* **裸旗标(无值)返回 undefined**,不是空串 —— 这样 `?? deps.x` 才能正常回落,
|
|
17
|
-
* 否则 `"" ?? deps.x` 恒取空串,把「只写了 --password 想让程序询问」误判成「显式给了空密码」。
|
|
18
|
-
*/
|
|
19
|
-
function flagValue(rest, ...names) {
|
|
20
|
-
for (let i = 0; i < rest.length; i++) {
|
|
21
|
-
const cur = String(rest[i]);
|
|
22
|
-
for (const name of names) {
|
|
23
|
-
if (cur === name) {
|
|
24
|
-
const next = rest[i + 1];
|
|
25
|
-
return typeof next === "string" && next.length > 0 && !next.startsWith("-") ? next : undefined;
|
|
26
|
-
}
|
|
27
|
-
if (cur.startsWith(`${name}=`)) {
|
|
28
|
-
const v = cur.slice(name.length + 1);
|
|
29
|
-
return v.length > 0 ? v : undefined;
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
return undefined;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
/**
|
|
37
|
-
* TTY 隐藏输入:**不碰 readline**(它会自己接管 stdin 的原始模式,与我们抢同一份字节),
|
|
38
|
-
* 直接开 raw mode 逐字符读,每个键回显一个 `*` 给出「确实收到了」的可见反馈。
|
|
39
|
-
* 非 TTY 返回 null(由调用方转成「必须用 flag」的指引,绝不从管道偷读)。
|
|
40
|
-
*/
|
|
41
|
-
async function promptHidden(label) {
|
|
42
|
-
if (!process.stdin.isTTY || !process.stdout.isTTY) return null;
|
|
43
|
-
return await new Promise((resolve) => {
|
|
44
|
-
const wasRaw = Boolean(process.stdin.isRaw);
|
|
45
|
-
let buf = "";
|
|
46
|
-
const done = (value) => {
|
|
47
|
-
process.stdin.removeListener("data", onData);
|
|
48
|
-
try { process.stdin.setRawMode(wasRaw); } catch {}
|
|
49
|
-
process.stdin.pause();
|
|
50
|
-
process.stdout.write("\n");
|
|
51
|
-
resolve(value);
|
|
52
|
-
};
|
|
53
|
-
const onData = (chunk) => {
|
|
54
|
-
for (const ch of String(chunk)) {
|
|
55
|
-
if (ch === "\r" || ch === "\n") return done(buf);
|
|
56
|
-
if (ch === "\u0003") return done(null); // Ctrl-C
|
|
57
|
-
if (ch === "\u007f" || ch === "\b") { // 退格
|
|
58
|
-
if (buf.length > 0) { buf = buf.slice(0, -1); process.stdout.write("\b \b"); }
|
|
59
|
-
continue;
|
|
60
|
-
}
|
|
61
|
-
if (ch < " ") continue; // 忽略其余控制字符
|
|
62
|
-
buf += ch;
|
|
63
|
-
process.stdout.write("*");
|
|
64
|
-
}
|
|
65
|
-
};
|
|
66
|
-
process.stdout.write(label);
|
|
67
|
-
try { process.stdin.setRawMode(true); } catch {}
|
|
68
|
-
process.stdin.resume();
|
|
69
|
-
process.stdin.setEncoding("utf8");
|
|
70
|
-
process.stdin.on("data", onData);
|
|
71
|
-
});
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
async function promptVisible(label) {
|
|
75
|
-
if (!process.stdin.isTTY || !process.stdout.isTTY) return null;
|
|
76
|
-
const { createInterface } = await import("../../../readline-compat.js");
|
|
77
|
-
const rl = createInterface({ input: process.stdin, output: process.stdout, terminal: true });
|
|
78
|
-
try {
|
|
79
|
-
return await rl.question(label);
|
|
80
|
-
} finally {
|
|
81
|
-
rl.close();
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
export async function handleRaccoonPasswordLogin(id, sub, rest = [], deps = {}) {
|
|
86
|
-
const fetchImpl = deps.fetchImpl || compatFetch;
|
|
87
|
-
const log = deps.log || ((m) => console.log(m));
|
|
88
|
-
const exit = deps.exit || ((code) => process.exit(code));
|
|
89
|
-
|
|
90
|
-
log("=".repeat(60));
|
|
91
|
-
log(" Raccoon 登录(商汤小浣熊 · 手机号 + 密码)");
|
|
92
|
-
log("=".repeat(60));
|
|
93
|
-
log("");
|
|
94
|
-
|
|
95
|
-
let phone = flagValue(rest, "--phone") ?? deps.phone;
|
|
96
|
-
// `--password` 既是「模式开关」也可携带值:`--password`(裸)→ 交互询问,`--password=xxx` → 直接用。
|
|
97
|
-
let password = flagValue(rest, "--password", "-p") ?? deps.password;
|
|
98
|
-
const nationCode = flagValue(rest, "--nation", "--nation-code", "--area") || deps.nationCode || "86";
|
|
99
|
-
|
|
100
|
-
if (!phone) {
|
|
101
|
-
const asked = await promptVisible(" 手机号: ");
|
|
102
|
-
if (asked === null) {
|
|
103
|
-
log("❌ 非交互环境(非 TTY)无法询问手机号 —— 请用 --phone 传入");
|
|
104
|
-
log(RELOGIN_HINT);
|
|
105
|
-
exit(1);
|
|
106
|
-
return true;
|
|
107
|
-
}
|
|
108
|
-
phone = asked;
|
|
109
|
-
}
|
|
110
|
-
const cleanPhone = normalizePhone(phone);
|
|
111
|
-
if (!cleanPhone) {
|
|
112
|
-
log("❌ 手机号不能为空(只填数字即可)");
|
|
113
|
-
log(RELOGIN_HINT);
|
|
114
|
-
exit(1);
|
|
115
|
-
return true;
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
if (!password) {
|
|
119
|
-
const asked = await promptHidden(" 密码(输入不回显): ");
|
|
120
|
-
if (asked === null) {
|
|
121
|
-
log("❌ 非交互环境(非 TTY)无法安全询问密码 —— 请用 --password 传入");
|
|
122
|
-
log(RELOGIN_HINT);
|
|
123
|
-
exit(1);
|
|
124
|
-
return true;
|
|
125
|
-
}
|
|
126
|
-
password = asked;
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
if (String(password || "").length === 0) {
|
|
130
|
-
log("❌ 密码不能为空");
|
|
131
|
-
log(RELOGIN_HINT);
|
|
132
|
-
exit(1);
|
|
133
|
-
return true;
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
log("🔐 正在登录…");
|
|
137
|
-
let credential;
|
|
138
|
-
try {
|
|
139
|
-
credential = await loginRaccoonWithPassword(
|
|
140
|
-
{ phone: cleanPhone, password, nationCode },
|
|
141
|
-
{ fetchImpl, env: deps.env },
|
|
142
|
-
);
|
|
143
|
-
} catch (error) {
|
|
144
|
-
log("");
|
|
145
|
-
log(`❌ 登录失败:${error?.message ?? error}`);
|
|
146
|
-
log(RELOGIN_HINT);
|
|
147
|
-
exit(1);
|
|
148
|
-
return true;
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
// 密码已用完,立刻从本进程的作用域里抹掉(降内存残留;不是安全边界,是习惯)
|
|
152
|
-
password = undefined;
|
|
153
|
-
|
|
154
|
-
const masked = cleanPhone.length > 4 ? `${"*".repeat(cleanPhone.length - 4)}${cleanPhone.slice(-4)}` : cleanPhone;
|
|
155
|
-
return await finishRaccoonLogin({
|
|
156
|
-
credential,
|
|
157
|
-
fetchImpl,
|
|
158
|
-
deps,
|
|
159
|
-
log,
|
|
160
|
-
methodNote: ` 登录方式: 密码登录(手机号 ${masked})`,
|
|
161
|
-
});
|
|
162
|
-
}
|
|
1
|
+
// mslxdff -provider raccoon login --password —— 手机号 + 密码登录(多账号免扫码)。
|
|
2
|
+
//
|
|
3
|
+
// 为什么需要它:扫码登录一次只能加一个号,且要手机在手边;密码登录可以在同一个终端里
|
|
4
|
+
// 连着把多个号加完(脚本化也行),是「批量补号」的正路。
|
|
5
|
+
//
|
|
6
|
+
// 安全:密码**只经手本进程内存**,绝不落盘、绝不打印、绝不进 argv(除非用户显式 `--password=xxx`,
|
|
7
|
+
// 那种情况会在回执里提示一次「密码已进 shell 历史」)。落盘的是 token,与扫码登录同一条路。
|
|
8
|
+
import { compatFetch } from "../../../compat.js";
|
|
9
|
+
import { loginRaccoonWithPassword, normalizePhone } from "../../../providers/raccoon/password-login.js";
|
|
10
|
+
import { finishRaccoonLogin } from "./raccoon-login.js";
|
|
11
|
+
|
|
12
|
+
const RELOGIN_HINT = " (可重试:mslxdff -provider raccoon login --password)";
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* 从 rest 里取 `--key=value` 或 `--key value` 两种写法。
|
|
16
|
+
* **裸旗标(无值)返回 undefined**,不是空串 —— 这样 `?? deps.x` 才能正常回落,
|
|
17
|
+
* 否则 `"" ?? deps.x` 恒取空串,把「只写了 --password 想让程序询问」误判成「显式给了空密码」。
|
|
18
|
+
*/
|
|
19
|
+
function flagValue(rest, ...names) {
|
|
20
|
+
for (let i = 0; i < rest.length; i++) {
|
|
21
|
+
const cur = String(rest[i]);
|
|
22
|
+
for (const name of names) {
|
|
23
|
+
if (cur === name) {
|
|
24
|
+
const next = rest[i + 1];
|
|
25
|
+
return typeof next === "string" && next.length > 0 && !next.startsWith("-") ? next : undefined;
|
|
26
|
+
}
|
|
27
|
+
if (cur.startsWith(`${name}=`)) {
|
|
28
|
+
const v = cur.slice(name.length + 1);
|
|
29
|
+
return v.length > 0 ? v : undefined;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
return undefined;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* TTY 隐藏输入:**不碰 readline**(它会自己接管 stdin 的原始模式,与我们抢同一份字节),
|
|
38
|
+
* 直接开 raw mode 逐字符读,每个键回显一个 `*` 给出「确实收到了」的可见反馈。
|
|
39
|
+
* 非 TTY 返回 null(由调用方转成「必须用 flag」的指引,绝不从管道偷读)。
|
|
40
|
+
*/
|
|
41
|
+
async function promptHidden(label) {
|
|
42
|
+
if (!process.stdin.isTTY || !process.stdout.isTTY) return null;
|
|
43
|
+
return await new Promise((resolve) => {
|
|
44
|
+
const wasRaw = Boolean(process.stdin.isRaw);
|
|
45
|
+
let buf = "";
|
|
46
|
+
const done = (value) => {
|
|
47
|
+
process.stdin.removeListener("data", onData);
|
|
48
|
+
try { process.stdin.setRawMode(wasRaw); } catch {}
|
|
49
|
+
process.stdin.pause();
|
|
50
|
+
process.stdout.write("\n");
|
|
51
|
+
resolve(value);
|
|
52
|
+
};
|
|
53
|
+
const onData = (chunk) => {
|
|
54
|
+
for (const ch of String(chunk)) {
|
|
55
|
+
if (ch === "\r" || ch === "\n") return done(buf);
|
|
56
|
+
if (ch === "\u0003") return done(null); // Ctrl-C
|
|
57
|
+
if (ch === "\u007f" || ch === "\b") { // 退格
|
|
58
|
+
if (buf.length > 0) { buf = buf.slice(0, -1); process.stdout.write("\b \b"); }
|
|
59
|
+
continue;
|
|
60
|
+
}
|
|
61
|
+
if (ch < " ") continue; // 忽略其余控制字符
|
|
62
|
+
buf += ch;
|
|
63
|
+
process.stdout.write("*");
|
|
64
|
+
}
|
|
65
|
+
};
|
|
66
|
+
process.stdout.write(label);
|
|
67
|
+
try { process.stdin.setRawMode(true); } catch {}
|
|
68
|
+
process.stdin.resume();
|
|
69
|
+
process.stdin.setEncoding("utf8");
|
|
70
|
+
process.stdin.on("data", onData);
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
async function promptVisible(label) {
|
|
75
|
+
if (!process.stdin.isTTY || !process.stdout.isTTY) return null;
|
|
76
|
+
const { createInterface } = await import("../../../readline-compat.js");
|
|
77
|
+
const rl = createInterface({ input: process.stdin, output: process.stdout, terminal: true });
|
|
78
|
+
try {
|
|
79
|
+
return await rl.question(label);
|
|
80
|
+
} finally {
|
|
81
|
+
rl.close();
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
export async function handleRaccoonPasswordLogin(id, sub, rest = [], deps = {}) {
|
|
86
|
+
const fetchImpl = deps.fetchImpl || compatFetch;
|
|
87
|
+
const log = deps.log || ((m) => console.log(m));
|
|
88
|
+
const exit = deps.exit || ((code) => process.exit(code));
|
|
89
|
+
|
|
90
|
+
log("=".repeat(60));
|
|
91
|
+
log(" Raccoon 登录(商汤小浣熊 · 手机号 + 密码)");
|
|
92
|
+
log("=".repeat(60));
|
|
93
|
+
log("");
|
|
94
|
+
|
|
95
|
+
let phone = flagValue(rest, "--phone") ?? deps.phone;
|
|
96
|
+
// `--password` 既是「模式开关」也可携带值:`--password`(裸)→ 交互询问,`--password=xxx` → 直接用。
|
|
97
|
+
let password = flagValue(rest, "--password", "-p") ?? deps.password;
|
|
98
|
+
const nationCode = flagValue(rest, "--nation", "--nation-code", "--area") || deps.nationCode || "86";
|
|
99
|
+
|
|
100
|
+
if (!phone) {
|
|
101
|
+
const asked = await promptVisible(" 手机号: ");
|
|
102
|
+
if (asked === null) {
|
|
103
|
+
log("❌ 非交互环境(非 TTY)无法询问手机号 —— 请用 --phone 传入");
|
|
104
|
+
log(RELOGIN_HINT);
|
|
105
|
+
exit(1);
|
|
106
|
+
return true;
|
|
107
|
+
}
|
|
108
|
+
phone = asked;
|
|
109
|
+
}
|
|
110
|
+
const cleanPhone = normalizePhone(phone);
|
|
111
|
+
if (!cleanPhone) {
|
|
112
|
+
log("❌ 手机号不能为空(只填数字即可)");
|
|
113
|
+
log(RELOGIN_HINT);
|
|
114
|
+
exit(1);
|
|
115
|
+
return true;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
if (!password) {
|
|
119
|
+
const asked = await promptHidden(" 密码(输入不回显): ");
|
|
120
|
+
if (asked === null) {
|
|
121
|
+
log("❌ 非交互环境(非 TTY)无法安全询问密码 —— 请用 --password 传入");
|
|
122
|
+
log(RELOGIN_HINT);
|
|
123
|
+
exit(1);
|
|
124
|
+
return true;
|
|
125
|
+
}
|
|
126
|
+
password = asked;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
if (String(password || "").length === 0) {
|
|
130
|
+
log("❌ 密码不能为空");
|
|
131
|
+
log(RELOGIN_HINT);
|
|
132
|
+
exit(1);
|
|
133
|
+
return true;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
log("🔐 正在登录…");
|
|
137
|
+
let credential;
|
|
138
|
+
try {
|
|
139
|
+
credential = await loginRaccoonWithPassword(
|
|
140
|
+
{ phone: cleanPhone, password, nationCode },
|
|
141
|
+
{ fetchImpl, env: deps.env },
|
|
142
|
+
);
|
|
143
|
+
} catch (error) {
|
|
144
|
+
log("");
|
|
145
|
+
log(`❌ 登录失败:${error?.message ?? error}`);
|
|
146
|
+
log(RELOGIN_HINT);
|
|
147
|
+
exit(1);
|
|
148
|
+
return true;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
// 密码已用完,立刻从本进程的作用域里抹掉(降内存残留;不是安全边界,是习惯)
|
|
152
|
+
password = undefined;
|
|
153
|
+
|
|
154
|
+
const masked = cleanPhone.length > 4 ? `${"*".repeat(cleanPhone.length - 4)}${cleanPhone.slice(-4)}` : cleanPhone;
|
|
155
|
+
return await finishRaccoonLogin({
|
|
156
|
+
credential,
|
|
157
|
+
fetchImpl,
|
|
158
|
+
deps,
|
|
159
|
+
log,
|
|
160
|
+
methodNote: ` 登录方式: 密码登录(手机号 ${masked})`,
|
|
161
|
+
});
|
|
162
|
+
}
|
|
@@ -1,109 +1,109 @@
|
|
|
1
|
-
// mslxdff -provider raccoon quota — 逐号查积分余额(五分项)
|
|
2
|
-
// mslxdff -provider raccoon checkin — 领「桌面端登录奖励」
|
|
3
|
-
// ⚠ 纠偏(2026-10-10 账单实测):这家**没有每日签到**。三种积分来源里只有登录奖励 3000 需要领,
|
|
4
|
-
// 且**每号一次性**;每日 300 与注册礼包 3000 都由服务端自动发(无端点),每日 300 当天 23:59:59 清零。
|
|
5
|
-
// 判据一律走账单:上游对重复领取照样回 code:0,只信回执就会谎报到账。
|
|
6
|
-
import { normalizeProviderId } from "../../../providers/model-id.js";
|
|
7
|
-
import { compatFetch } from "../../../compat.js";
|
|
8
|
-
import { listRaccoonAccountDocs, raccoonCredentialFromDoc } from "../../../providers/raccoon/account-store.js";
|
|
9
|
-
import { claimRaccoonLoginReward, fetchRaccoonBalance, raccoonClaimStatus } from "../../../providers/raccoon/credits.js";
|
|
10
|
-
import { raccoonTokenFingerprint } from "../../../providers/raccoon/auth.js";
|
|
11
|
-
|
|
12
|
-
const SUBS = new Set(["quota", "credits", "balance", "checkin", "signin"]);
|
|
13
|
-
|
|
14
|
-
/** 逐号列出(旧实现只取 docs[0],多号时会漏看余额、漏领一次性礼包)。 */
|
|
15
|
-
function targets(deps) {
|
|
16
|
-
if (deps.credential) return [{ name: "", credential: deps.credential }];
|
|
17
|
-
return listRaccoonAccountDocs(deps.dir ? { dirs: [deps.dir] } : {})
|
|
18
|
-
.filter((d) => d.accessToken)
|
|
19
|
-
.map((d) => ({ name: d.name || "", credential: raccoonCredentialFromDoc(d) }));
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
const STATUS_LINE = {
|
|
23
|
-
claimed: (r) => `🎁 已领取 +${r.points} 分 —— 账单已确认入账(每号仅此一次)`,
|
|
24
|
-
already: () => `已领过 —— 每号只有一次,没有"明天再来"这回事`,
|
|
25
|
-
phantom: () => `⚠ 上游回执「成功」但账单里查不到这笔 → 判定未到账,别当领过`,
|
|
26
|
-
unverified: () => `已提交,但账单暂时查不到 → 未确认,稍后用 quota 核对`,
|
|
27
|
-
error: (r) => `❌ 领取失败:${r.msg || "未知原因"}`,
|
|
28
|
-
};
|
|
29
|
-
|
|
30
|
-
// row.account 在构造时已换成 token 指纹(凭据纪律:CLI 只打指纹,绝不打完整 token)
|
|
31
|
-
const label = (row) => `[${row.account}${row.uid ? " · " + row.uid : ""}]`;
|
|
32
|
-
|
|
33
|
-
function expiredHint(error) {
|
|
34
|
-
return error?.authExpired || error?.status === 401 || error?.code === 200001 || error?.code === 200003
|
|
35
|
-
? "登录态已失效(access_token 只有约 3 小时寿命),重新扫码: mslxdff -provider raccoon login"
|
|
36
|
-
: "";
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
export async function handleRaccoonQuota(id, sub, rest = [], deps = {}) {
|
|
40
|
-
const pid = normalizeProviderId(id) || String(id || "").toLowerCase();
|
|
41
|
-
if (pid !== "raccoon") return false;
|
|
42
|
-
if (!SUBS.has(sub)) return false;
|
|
43
|
-
|
|
44
|
-
const fetchImpl = deps.fetchImpl || compatFetch;
|
|
45
|
-
const log = deps.log || ((m) => console.log(m));
|
|
46
|
-
const exit = deps.exit || ((code) => process.exit(code));
|
|
47
|
-
const json = rest.includes("--json");
|
|
48
|
-
const isCheckin = sub === "checkin" || sub === "signin";
|
|
49
|
-
const list = targets(deps);
|
|
50
|
-
|
|
51
|
-
if (!list.length) {
|
|
52
|
-
if (json) log(JSON.stringify({ error: "not_logged_in", hint: "mslxdff -provider raccoon login" }));
|
|
53
|
-
else {
|
|
54
|
-
log("未登录:还没有可用的 raccoon 账号");
|
|
55
|
-
log(" 先运行: mslxdff -provider raccoon login(登录时会自动领一次性登录奖励)");
|
|
56
|
-
}
|
|
57
|
-
exit(1);
|
|
58
|
-
return true;
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
const rows = [];
|
|
62
|
-
for (const t of list) {
|
|
63
|
-
const base = { account: raccoonTokenFingerprint(t.credential.access_token), uid: t.credential.uid, name: t.name };
|
|
64
|
-
try {
|
|
65
|
-
if (isCheckin) {
|
|
66
|
-
const r = await claimRaccoonLoginReward({ credential: t.credential, fetchImpl, env: deps.env });
|
|
67
|
-
const status = raccoonClaimStatus(r);
|
|
68
|
-
rows.push({ ...base, ok: status === "claimed" || status === "already", status, points: r.points });
|
|
69
|
-
} else {
|
|
70
|
-
const b = await fetchRaccoonBalance({ credential: t.credential, fetchImpl, env: deps.env });
|
|
71
|
-
rows.push({ ...base, ok: true, total: b.total, items: b.items });
|
|
72
|
-
}
|
|
73
|
-
} catch (e) {
|
|
74
|
-
rows.push({ ...base, ok: false, status: "error", msg: String(e?.message ?? e).slice(0, 160), relogin: expiredHint(e) });
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
const failed = rows.filter((r) => !r.ok).length;
|
|
78
|
-
|
|
79
|
-
if (json) {
|
|
80
|
-
log(JSON.stringify({ accounts: rows, ok: rows.length - failed, total: rows.length }));
|
|
81
|
-
exit(failed === rows.length ? 1 : 0);
|
|
82
|
-
return true;
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
if (isCheckin) {
|
|
86
|
-
log(`raccoon 登录奖励(每号一次性)· 共 ${rows.length} 个号`);
|
|
87
|
-
for (const r of rows) log(` ${label(r)} ${STATUS_LINE[r.status]?.(r) || r.status}`);
|
|
88
|
-
if (rows.some((r) => r.status === "claimed")) log(` 查看余额: mslxdff -provider raccoon quota`);
|
|
89
|
-
exit(failed === rows.length ? 1 : 0);
|
|
90
|
-
return true;
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
log(`raccoon 积分 · 共 ${rows.length} 个号`);
|
|
94
|
-
for (const r of rows) {
|
|
95
|
-
if (!r.ok) {
|
|
96
|
-
log(` ${label(r)} ❌ ${r.msg}`);
|
|
97
|
-
if (r.relogin) log(` → ${r.relogin}`);
|
|
98
|
-
continue;
|
|
99
|
-
}
|
|
100
|
-
const detail = r.items.length ? r.items.map((i) => `${i.label} ${i.value}`).join(" · ") : "(上游未返回分项明细)";
|
|
101
|
-
log(` ${label(r)} 可用 ${r.total} ${detail}`);
|
|
102
|
-
}
|
|
103
|
-
log("");
|
|
104
|
-
log(" ⚠ 「每日积分」当天 23:59:59 清零,当天不花就作废;奖励/充值积分不过期。上游按倍率自动先扣当日池。");
|
|
105
|
-
log(" ⚠ 倍率 0 的模型不扣积分(`mslxdff -provider raccoon models` 看倍率列),想省积分优先用它们。");
|
|
106
|
-
log(" 登录奖励每号只有一次,登录时已自动领;本命令的 checkin 只是补领兜底。");
|
|
107
|
-
exit(failed === rows.length ? 1 : 0);
|
|
108
|
-
return true;
|
|
109
|
-
}
|
|
1
|
+
// mslxdff -provider raccoon quota — 逐号查积分余额(五分项)
|
|
2
|
+
// mslxdff -provider raccoon checkin — 领「桌面端登录奖励」
|
|
3
|
+
// ⚠ 纠偏(2026-10-10 账单实测):这家**没有每日签到**。三种积分来源里只有登录奖励 3000 需要领,
|
|
4
|
+
// 且**每号一次性**;每日 300 与注册礼包 3000 都由服务端自动发(无端点),每日 300 当天 23:59:59 清零。
|
|
5
|
+
// 判据一律走账单:上游对重复领取照样回 code:0,只信回执就会谎报到账。
|
|
6
|
+
import { normalizeProviderId } from "../../../providers/model-id.js";
|
|
7
|
+
import { compatFetch } from "../../../compat.js";
|
|
8
|
+
import { listRaccoonAccountDocs, raccoonCredentialFromDoc } from "../../../providers/raccoon/account-store.js";
|
|
9
|
+
import { claimRaccoonLoginReward, fetchRaccoonBalance, raccoonClaimStatus } from "../../../providers/raccoon/credits.js";
|
|
10
|
+
import { raccoonTokenFingerprint } from "../../../providers/raccoon/auth.js";
|
|
11
|
+
|
|
12
|
+
const SUBS = new Set(["quota", "credits", "balance", "checkin", "signin"]);
|
|
13
|
+
|
|
14
|
+
/** 逐号列出(旧实现只取 docs[0],多号时会漏看余额、漏领一次性礼包)。 */
|
|
15
|
+
function targets(deps) {
|
|
16
|
+
if (deps.credential) return [{ name: "", credential: deps.credential }];
|
|
17
|
+
return listRaccoonAccountDocs(deps.dir ? { dirs: [deps.dir] } : {})
|
|
18
|
+
.filter((d) => d.accessToken)
|
|
19
|
+
.map((d) => ({ name: d.name || "", credential: raccoonCredentialFromDoc(d) }));
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const STATUS_LINE = {
|
|
23
|
+
claimed: (r) => `🎁 已领取 +${r.points} 分 —— 账单已确认入账(每号仅此一次)`,
|
|
24
|
+
already: () => `已领过 —— 每号只有一次,没有"明天再来"这回事`,
|
|
25
|
+
phantom: () => `⚠ 上游回执「成功」但账单里查不到这笔 → 判定未到账,别当领过`,
|
|
26
|
+
unverified: () => `已提交,但账单暂时查不到 → 未确认,稍后用 quota 核对`,
|
|
27
|
+
error: (r) => `❌ 领取失败:${r.msg || "未知原因"}`,
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
// row.account 在构造时已换成 token 指纹(凭据纪律:CLI 只打指纹,绝不打完整 token)
|
|
31
|
+
const label = (row) => `[${row.account}${row.uid ? " · " + row.uid : ""}]`;
|
|
32
|
+
|
|
33
|
+
function expiredHint(error) {
|
|
34
|
+
return error?.authExpired || error?.status === 401 || error?.code === 200001 || error?.code === 200003
|
|
35
|
+
? "登录态已失效(access_token 只有约 3 小时寿命),重新扫码: mslxdff -provider raccoon login"
|
|
36
|
+
: "";
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export async function handleRaccoonQuota(id, sub, rest = [], deps = {}) {
|
|
40
|
+
const pid = normalizeProviderId(id) || String(id || "").toLowerCase();
|
|
41
|
+
if (pid !== "raccoon") return false;
|
|
42
|
+
if (!SUBS.has(sub)) return false;
|
|
43
|
+
|
|
44
|
+
const fetchImpl = deps.fetchImpl || compatFetch;
|
|
45
|
+
const log = deps.log || ((m) => console.log(m));
|
|
46
|
+
const exit = deps.exit || ((code) => process.exit(code));
|
|
47
|
+
const json = rest.includes("--json");
|
|
48
|
+
const isCheckin = sub === "checkin" || sub === "signin";
|
|
49
|
+
const list = targets(deps);
|
|
50
|
+
|
|
51
|
+
if (!list.length) {
|
|
52
|
+
if (json) log(JSON.stringify({ error: "not_logged_in", hint: "mslxdff -provider raccoon login" }));
|
|
53
|
+
else {
|
|
54
|
+
log("未登录:还没有可用的 raccoon 账号");
|
|
55
|
+
log(" 先运行: mslxdff -provider raccoon login(登录时会自动领一次性登录奖励)");
|
|
56
|
+
}
|
|
57
|
+
exit(1);
|
|
58
|
+
return true;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const rows = [];
|
|
62
|
+
for (const t of list) {
|
|
63
|
+
const base = { account: raccoonTokenFingerprint(t.credential.access_token), uid: t.credential.uid, name: t.name };
|
|
64
|
+
try {
|
|
65
|
+
if (isCheckin) {
|
|
66
|
+
const r = await claimRaccoonLoginReward({ credential: t.credential, fetchImpl, env: deps.env });
|
|
67
|
+
const status = raccoonClaimStatus(r);
|
|
68
|
+
rows.push({ ...base, ok: status === "claimed" || status === "already", status, points: r.points });
|
|
69
|
+
} else {
|
|
70
|
+
const b = await fetchRaccoonBalance({ credential: t.credential, fetchImpl, env: deps.env });
|
|
71
|
+
rows.push({ ...base, ok: true, total: b.total, items: b.items });
|
|
72
|
+
}
|
|
73
|
+
} catch (e) {
|
|
74
|
+
rows.push({ ...base, ok: false, status: "error", msg: String(e?.message ?? e).slice(0, 160), relogin: expiredHint(e) });
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
const failed = rows.filter((r) => !r.ok).length;
|
|
78
|
+
|
|
79
|
+
if (json) {
|
|
80
|
+
log(JSON.stringify({ accounts: rows, ok: rows.length - failed, total: rows.length }));
|
|
81
|
+
exit(failed === rows.length ? 1 : 0);
|
|
82
|
+
return true;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
if (isCheckin) {
|
|
86
|
+
log(`raccoon 登录奖励(每号一次性)· 共 ${rows.length} 个号`);
|
|
87
|
+
for (const r of rows) log(` ${label(r)} ${STATUS_LINE[r.status]?.(r) || r.status}`);
|
|
88
|
+
if (rows.some((r) => r.status === "claimed")) log(` 查看余额: mslxdff -provider raccoon quota`);
|
|
89
|
+
exit(failed === rows.length ? 1 : 0);
|
|
90
|
+
return true;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
log(`raccoon 积分 · 共 ${rows.length} 个号`);
|
|
94
|
+
for (const r of rows) {
|
|
95
|
+
if (!r.ok) {
|
|
96
|
+
log(` ${label(r)} ❌ ${r.msg}`);
|
|
97
|
+
if (r.relogin) log(` → ${r.relogin}`);
|
|
98
|
+
continue;
|
|
99
|
+
}
|
|
100
|
+
const detail = r.items.length ? r.items.map((i) => `${i.label} ${i.value}`).join(" · ") : "(上游未返回分项明细)";
|
|
101
|
+
log(` ${label(r)} 可用 ${r.total} ${detail}`);
|
|
102
|
+
}
|
|
103
|
+
log("");
|
|
104
|
+
log(" ⚠ 「每日积分」当天 23:59:59 清零,当天不花就作废;奖励/充值积分不过期。上游按倍率自动先扣当日池。");
|
|
105
|
+
log(" ⚠ 倍率 0 的模型不扣积分(`mslxdff -provider raccoon models` 看倍率列),想省积分优先用它们。");
|
|
106
|
+
log(" 登录奖励每号只有一次,登录时已自动领;本命令的 checkin 只是补领兜底。");
|
|
107
|
+
exit(failed === rows.length ? 1 : 0);
|
|
108
|
+
return true;
|
|
109
|
+
}
|