@mu-cabin/muc-cli 0.3.0 → 0.3.1
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 +16 -4
- package/dist/muc.mjs +120 -68
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -223,9 +223,15 @@ muc history --team 9009876543210000 --before 2026-04-20 --json | jq .
|
|
|
223
223
|
| `muc wait-react --mid <MID> [--from-uid UID] [--sticker-id ID] [--timeout 300]` | Block until someone reacts with an emoticon to `--mid`, then exit. Useful as a "human-in-the-loop approval" gate after `muc send`. Exits with `TIMEOUT` (exit 5) if no matching reaction arrives within `--timeout` seconds. |
|
|
224
224
|
| `muc listen [--from-uid UID] [--team TEAM] [--peer UID] [--contains TEXT] [--regex …] [--at-me] [--max N]` | Long-lived TCP tap that emits one **NDJSON line per matching inbound message** (in `--json` mode each line is the standard envelope; in human mode it's a one-line summary). Supports repeatable filters (OR semantics within each kind, AND across kinds), `--at-me` to restrict to group messages where another user @-mentions you (implies excluding self), `--include-self` to include your own sends, `--include-reactions` to also surface type=3 sub=300/301 frames, `--max N` to exit after N matches. Stop with `^C`. |
|
|
225
225
|
|
|
226
|
-
`--os`
|
|
227
|
-
|
|
228
|
-
|
|
226
|
+
`--os` resolves as **per-call `--os` → `defaultChatOs` in `~/.muc/config.json`
|
|
227
|
+
→ built-in `iOS`**. Valid values: `Windows`, `OS X`, `Mac`, `iOS`, `Android`.
|
|
228
|
+
Set the per-machine default once with `muc init --default-os <os>` (or the
|
|
229
|
+
`MUC_DEFAULT_OS` env var, or the interactive prompt during `muc init`). Useful
|
|
230
|
+
if your real device is an iPhone — flip the CLI default to `windows` so
|
|
231
|
+
chat-channel commands park on the PC slot instead of kicking your phone.
|
|
232
|
+
**`--os` / `defaultChatOs` does not provide coexistence — read the section
|
|
233
|
+
below before using any chat-channel command if you have a real device
|
|
234
|
+
logged in.**
|
|
229
235
|
|
|
230
236
|
Sending to anyone other than yourself requires the explicit `--yes-not-self`
|
|
231
237
|
flag — a guard against accidentally messaging real humans during testing.
|
|
@@ -286,7 +292,9 @@ in as `iOS` (Mobile slot).
|
|
|
286
292
|
|
|
287
293
|
The CLI defaults to `--os iOS` so it coexists with a Mac desktop. If your
|
|
288
294
|
iPhone is also signed in, both slots are taken and any TCP command will
|
|
289
|
-
kick one of them — fall back to REST-only commands
|
|
295
|
+
kick one of them — fall back to REST-only commands, or run
|
|
296
|
+
`muc init --default-os windows` to flip the per-machine default to the PC
|
|
297
|
+
slot (which kicks the desktop instead of the phone).
|
|
290
298
|
|
|
291
299
|
`tcp-ping` only does TCP connect + NEGOTIATE (no `auth/login`), so it can't
|
|
292
300
|
kick anything. Run it first to confirm the wire protocol is happy on your
|
|
@@ -361,6 +369,10 @@ first use; you should never need to edit them by hand.
|
|
|
361
369
|
|
|
362
370
|
## Changelog
|
|
363
371
|
|
|
372
|
+
#### `0.3.1`
|
|
373
|
+
`2026.04.29`
|
|
374
|
+
- Add `defaultChatOs` to `~/.muc/config.json`: per-machine fallback for the chat-channel `--os` slot. Configure via `muc init --default-os <windows|osx|mac|ios|android>`, the `MUC_DEFAULT_OS` env var, or the interactive prompt during `muc init`. Resolution order: per-call `--os` → `defaultChatOs` → built-in `iOS`. Use this when your real device is on the Mobile slot (e.g. iPhone) so chat-channel commands park on PC instead of kicking your phone.
|
|
375
|
+
|
|
364
376
|
#### `0.3.0`
|
|
365
377
|
`2026.04.29`
|
|
366
378
|
- Add `muc react` / `muc unreact` / `muc reactions` to add, revoke, and list emoticon reactions on existing messages
|
package/dist/muc.mjs
CHANGED
|
@@ -21288,6 +21288,7 @@ import { join } from "node:path";
|
|
|
21288
21288
|
var DIR = join(homedir(), ".muc");
|
|
21289
21289
|
var FILE = join(DIR, "config.json");
|
|
21290
21290
|
var CONFIG_SCHEMA_VERSION = 1;
|
|
21291
|
+
var CHAT_OS_VALUES = ["Windows", "OS X", "Mac", "iOS", "Android"];
|
|
21291
21292
|
var MucConfigSchema = external_exports.object({
|
|
21292
21293
|
appKey: external_exports.string().regex(/^[0-9a-f]{8}$/, "appKey must be 8 lowercase hex chars"),
|
|
21293
21294
|
appId: external_exports.string().regex(/^[0-9a-f]{24}$/, "appId must be 24 lowercase hex chars"),
|
|
@@ -21307,6 +21308,10 @@ var MucConfigSchema = external_exports.object({
|
|
|
21307
21308
|
// any other → that literal string (e.g. "\n— bot")
|
|
21308
21309
|
// Per-call `--tail` / `--no-tail` flags on `muc send` override this.
|
|
21309
21310
|
messageTail: external_exports.string().max(200).optional(),
|
|
21311
|
+
// Default chat-channel `os` slot for TCP commands when --os is not passed.
|
|
21312
|
+
// PC ({Windows, OS X, Mac}) vs Mobile ({iOS, Android}); same slot as the
|
|
21313
|
+
// running desktop will kick it. Built-in fallback is 'iOS' (Mobile).
|
|
21314
|
+
defaultChatOs: external_exports.enum(CHAT_OS_VALUES).optional(),
|
|
21310
21315
|
savedAt: external_exports.number().int().nonnegative(),
|
|
21311
21316
|
schemaVersion: external_exports.literal(CONFIG_SCHEMA_VERSION)
|
|
21312
21317
|
});
|
|
@@ -21394,6 +21399,47 @@ function saveCredentials(c) {
|
|
|
21394
21399
|
}
|
|
21395
21400
|
var credentialsPath = FILE2;
|
|
21396
21401
|
|
|
21402
|
+
// src/lib/constants.ts
|
|
21403
|
+
var APP_NAME = "MUC";
|
|
21404
|
+
var APP_VERSION = "3.3.1-250925001";
|
|
21405
|
+
var APP_VERSION_IOS = "3.3.0301";
|
|
21406
|
+
var PLATFORM_IOS = 1;
|
|
21407
|
+
var PLATFORM_ANDROID = 2;
|
|
21408
|
+
var PLATFORM_WIN = 4;
|
|
21409
|
+
var PLATFORM_MAC = 5;
|
|
21410
|
+
var SECURE_SYS_KEY = "mx_app_key";
|
|
21411
|
+
var PWD_DES_IV = Buffer.from([1, 2, 3, 4, 5, 6, 7, 8]);
|
|
21412
|
+
var DEFAULT_CHAT_OS = "iOS";
|
|
21413
|
+
var DEFAULT_REST_PLATFORM = PLATFORM_IOS;
|
|
21414
|
+
function defaultMessageTail(userName) {
|
|
21415
|
+
const name = userName.trim() || "unknown";
|
|
21416
|
+
return `
|
|
21417
|
+
\u2014\u2014 \u6765\u81EA${name}\u7684muc-cli`;
|
|
21418
|
+
}
|
|
21419
|
+
var DEFAULTS = {
|
|
21420
|
+
// Hosts/ports for the 东航 deployment. Other tenants override at init.
|
|
21421
|
+
restHost: "https://muc.ceair.com/",
|
|
21422
|
+
ssoHost: "https://store.ceair.com/",
|
|
21423
|
+
imHost: "muc.ceair.com",
|
|
21424
|
+
imPort: 8101,
|
|
21425
|
+
fileHost: "muc.ceair.com",
|
|
21426
|
+
filePort: 6101
|
|
21427
|
+
};
|
|
21428
|
+
function apiUrls(cfg) {
|
|
21429
|
+
const host = cfg.restHost.endsWith("/") ? cfg.restHost : `${cfg.restHost}/`;
|
|
21430
|
+
return {
|
|
21431
|
+
SYS: `${host}sysconfig/v5/app`,
|
|
21432
|
+
MUC: `${host}muc/v5/app`,
|
|
21433
|
+
MAM: `${host}mam/v5/app`,
|
|
21434
|
+
MAS: `${host}mas/v5/app`,
|
|
21435
|
+
MPM: `${host}mpm/v5/app`,
|
|
21436
|
+
IMM: `${host}imm/v5/app`,
|
|
21437
|
+
MRM: `${host}mrm/v5/app`,
|
|
21438
|
+
CONTACT: `${host}contacts/v5/app`,
|
|
21439
|
+
SECURE: `${host}contacts/secure/v5/app`
|
|
21440
|
+
};
|
|
21441
|
+
}
|
|
21442
|
+
|
|
21397
21443
|
// src/lib/cli.ts
|
|
21398
21444
|
var SCHEMA_VERSION = 1;
|
|
21399
21445
|
var EXIT_CODES = {
|
|
@@ -21573,6 +21619,11 @@ function parseChatOs(raw) {
|
|
|
21573
21619
|
"expected windows|osx|mac|ios|android"
|
|
21574
21620
|
);
|
|
21575
21621
|
}
|
|
21622
|
+
function resolveChatOs(optsOs, cfg) {
|
|
21623
|
+
if (optsOs !== void 0) return optsOs;
|
|
21624
|
+
if (cfg.defaultChatOs !== void 0) return cfg.defaultChatOs;
|
|
21625
|
+
return DEFAULT_CHAT_OS;
|
|
21626
|
+
}
|
|
21576
21627
|
function parseMoment(label) {
|
|
21577
21628
|
return (raw) => {
|
|
21578
21629
|
if (/^\d+$/.test(raw)) {
|
|
@@ -21717,47 +21768,6 @@ function getDeviceName() {
|
|
|
21717
21768
|
return `${hostname()} (muc-cli)`;
|
|
21718
21769
|
}
|
|
21719
21770
|
|
|
21720
|
-
// src/lib/constants.ts
|
|
21721
|
-
var APP_NAME = "MUC";
|
|
21722
|
-
var APP_VERSION = "3.3.1-250925001";
|
|
21723
|
-
var APP_VERSION_IOS = "3.3.0301";
|
|
21724
|
-
var PLATFORM_IOS = 1;
|
|
21725
|
-
var PLATFORM_ANDROID = 2;
|
|
21726
|
-
var PLATFORM_WIN = 4;
|
|
21727
|
-
var PLATFORM_MAC = 5;
|
|
21728
|
-
var SECURE_SYS_KEY = "mx_app_key";
|
|
21729
|
-
var PWD_DES_IV = Buffer.from([1, 2, 3, 4, 5, 6, 7, 8]);
|
|
21730
|
-
var DEFAULT_CHAT_OS = "iOS";
|
|
21731
|
-
var DEFAULT_REST_PLATFORM = PLATFORM_IOS;
|
|
21732
|
-
function defaultMessageTail(userName) {
|
|
21733
|
-
const name = userName.trim() || "unknown";
|
|
21734
|
-
return `
|
|
21735
|
-
\u2014\u2014 \u6765\u81EA${name}\u7684muc-cli`;
|
|
21736
|
-
}
|
|
21737
|
-
var DEFAULTS = {
|
|
21738
|
-
// Hosts/ports for the 东航 deployment. Other tenants override at init.
|
|
21739
|
-
restHost: "https://muc.ceair.com/",
|
|
21740
|
-
ssoHost: "https://store.ceair.com/",
|
|
21741
|
-
imHost: "muc.ceair.com",
|
|
21742
|
-
imPort: 8101,
|
|
21743
|
-
fileHost: "muc.ceair.com",
|
|
21744
|
-
filePort: 6101
|
|
21745
|
-
};
|
|
21746
|
-
function apiUrls(cfg) {
|
|
21747
|
-
const host = cfg.restHost.endsWith("/") ? cfg.restHost : `${cfg.restHost}/`;
|
|
21748
|
-
return {
|
|
21749
|
-
SYS: `${host}sysconfig/v5/app`,
|
|
21750
|
-
MUC: `${host}muc/v5/app`,
|
|
21751
|
-
MAM: `${host}mam/v5/app`,
|
|
21752
|
-
MAS: `${host}mas/v5/app`,
|
|
21753
|
-
MPM: `${host}mpm/v5/app`,
|
|
21754
|
-
IMM: `${host}imm/v5/app`,
|
|
21755
|
-
MRM: `${host}mrm/v5/app`,
|
|
21756
|
-
CONTACT: `${host}contacts/v5/app`,
|
|
21757
|
-
SECURE: `${host}contacts/secure/v5/app`
|
|
21758
|
-
};
|
|
21759
|
-
}
|
|
21760
|
-
|
|
21761
21771
|
// src/lib/http.ts
|
|
21762
21772
|
var UA = `MUC/${APP_VERSION} (CLI; muc-cli/${CLI_VERSION})`;
|
|
21763
21773
|
var SENSITIVE_QS = /* @__PURE__ */ new Set(["accessToken", "tokenPwd", "sign"]);
|
|
@@ -22136,6 +22146,8 @@ var FingerprintShape = external_exports.object({
|
|
|
22136
22146
|
filePort: external_exports.number(),
|
|
22137
22147
|
messageTail: external_exports.string(),
|
|
22138
22148
|
// summary: "default" / "none" / "custom (N chars)"
|
|
22149
|
+
defaultChatOs: external_exports.string(),
|
|
22150
|
+
// summary: explicit value or "default (iOS)"
|
|
22139
22151
|
savedAt: external_exports.number(),
|
|
22140
22152
|
schemaVersion: external_exports.literal(CONFIG_SCHEMA_VERSION)
|
|
22141
22153
|
});
|
|
@@ -22161,6 +22173,10 @@ function summarizeTail(t) {
|
|
|
22161
22173
|
if (t === "") return "none";
|
|
22162
22174
|
return `custom (${t.length} chars)`;
|
|
22163
22175
|
}
|
|
22176
|
+
function summarizeChatOs(v) {
|
|
22177
|
+
if (v === void 0) return `default (${DEFAULT_CHAT_OS})`;
|
|
22178
|
+
return v;
|
|
22179
|
+
}
|
|
22164
22180
|
function redactConfig(c) {
|
|
22165
22181
|
return {
|
|
22166
22182
|
appKey: fingerprint2(c.appKey),
|
|
@@ -22175,6 +22191,7 @@ function redactConfig(c) {
|
|
|
22175
22191
|
fileHost: c.fileHost,
|
|
22176
22192
|
filePort: c.filePort,
|
|
22177
22193
|
messageTail: summarizeTail(c.messageTail),
|
|
22194
|
+
defaultChatOs: summarizeChatOs(c.defaultChatOs),
|
|
22178
22195
|
savedAt: c.savedAt,
|
|
22179
22196
|
schemaVersion: c.schemaVersion
|
|
22180
22197
|
};
|
|
@@ -22320,7 +22337,7 @@ function register2(program3) {
|
|
|
22320
22337
|
description: "Bootstrap or update ~/.muc/config.json (tenant config: APP_KEY, APP_ID, signing secrets, hosts/ports). Interactive prompts by default; non-interactive via flags or MUC_* env vars. WARNING: env vars are visible to other processes via /proc/<pid>/environ and shell history \u2014 prefer interactive or flag-based for production.",
|
|
22321
22338
|
output: Output2,
|
|
22322
22339
|
configure: (cmd) => {
|
|
22323
|
-
cmd.option("--check", "verify config presence and validity (exit 0 ok / 6 missing / 7 invalid); does not modify").option("--show", "print the saved config (secrets are always redacted in both human and JSON output; cat ~/.muc/config.json for raw values)").option("--reset", "delete ~/.muc/config.json (requires --yes)").option("--yes", "confirm a destructive action like --reset").option("--no-interactive", "fail rather than prompt for missing fields").option("--app-key <hex>", "tenant APP_KEY (8 lowercase hex)").option("--app-id <hex>", "tenant APP_ID (24 lowercase hex)").option("--sign-secret-rest <s>", "REST signing secret").option("--sign-secret-secure <s>", "secure-API signing secret").option("--pwd-des-key <s>", "password DES key (defaults to APP_KEY)").option("--rest-host <url>", "REST host URL").option("--sso-host <url>", "SSO host URL (optional)").option("--im-host <h>", "IM TCP host").option("--im-port <n>", "IM TCP port").option("--file-host <h>", "file-channel TCP host").option("--file-port <n>", "file-channel TCP port").option("--message-tail <text>", "custom signature appended to outbound `muc send` text (max 200 chars)").option("--no-message-tail", "explicitly disable the message tail (no signature appended)");
|
|
22340
|
+
cmd.option("--check", "verify config presence and validity (exit 0 ok / 6 missing / 7 invalid); does not modify").option("--show", "print the saved config (secrets are always redacted in both human and JSON output; cat ~/.muc/config.json for raw values)").option("--reset", "delete ~/.muc/config.json (requires --yes)").option("--yes", "confirm a destructive action like --reset").option("--no-interactive", "fail rather than prompt for missing fields").option("--app-key <hex>", "tenant APP_KEY (8 lowercase hex)").option("--app-id <hex>", "tenant APP_ID (24 lowercase hex)").option("--sign-secret-rest <s>", "REST signing secret").option("--sign-secret-secure <s>", "secure-API signing secret").option("--pwd-des-key <s>", "password DES key (defaults to APP_KEY)").option("--rest-host <url>", "REST host URL").option("--sso-host <url>", "SSO host URL (optional)").option("--im-host <h>", "IM TCP host").option("--im-port <n>", "IM TCP port").option("--file-host <h>", "file-channel TCP host").option("--file-port <n>", "file-channel TCP port").option("--message-tail <text>", "custom signature appended to outbound `muc send` text (max 200 chars)").option("--no-message-tail", "explicitly disable the message tail (no signature appended)").option("--default-os <os>", "default chat-channel os slot for TCP commands when --os is not passed (windows|osx|mac|ios|android); built-in fallback is iOS");
|
|
22324
22341
|
},
|
|
22325
22342
|
run: async (cmd) => {
|
|
22326
22343
|
const opts = cmd.opts();
|
|
@@ -22430,6 +22447,26 @@ function register2(program3) {
|
|
|
22430
22447
|
} else if (existing && "messageTail" in existing) {
|
|
22431
22448
|
messageTail = existing.messageTail;
|
|
22432
22449
|
}
|
|
22450
|
+
let defaultChatOs;
|
|
22451
|
+
let dcoRaw;
|
|
22452
|
+
const dcoFlag = opts.defaultOs;
|
|
22453
|
+
const dcoEnv = process.env.MUC_DEFAULT_OS;
|
|
22454
|
+
if (typeof dcoFlag === "string" && dcoFlag.length > 0) {
|
|
22455
|
+
dcoRaw = dcoFlag;
|
|
22456
|
+
} else if (dcoEnv !== void 0 && dcoEnv.length > 0) {
|
|
22457
|
+
dcoRaw = dcoEnv;
|
|
22458
|
+
} else if (existing?.defaultChatOs !== void 0) {
|
|
22459
|
+
defaultChatOs = existing.defaultChatOs;
|
|
22460
|
+
} else if (interactive) {
|
|
22461
|
+
const answer = await readLine(
|
|
22462
|
+
"Default chat OS slot (windows|osx|mac|ios|android)",
|
|
22463
|
+
DEFAULT_CHAT_OS.toLowerCase()
|
|
22464
|
+
);
|
|
22465
|
+
if (answer.length > 0) dcoRaw = answer;
|
|
22466
|
+
}
|
|
22467
|
+
if (dcoRaw !== void 0) {
|
|
22468
|
+
defaultChatOs = parseChatOs(dcoRaw);
|
|
22469
|
+
}
|
|
22433
22470
|
const draft = {
|
|
22434
22471
|
appKey: String(partial.appKey ?? ""),
|
|
22435
22472
|
appId: String(partial.appId ?? ""),
|
|
@@ -22443,6 +22480,7 @@ function register2(program3) {
|
|
|
22443
22480
|
fileHost: String(partial.fileHost ?? ""),
|
|
22444
22481
|
filePort: Number(partial.filePort ?? 0),
|
|
22445
22482
|
messageTail,
|
|
22483
|
+
defaultChatOs,
|
|
22446
22484
|
savedAt: Date.now(),
|
|
22447
22485
|
schemaVersion: CONFIG_SCHEMA_VERSION
|
|
22448
22486
|
};
|
|
@@ -23220,13 +23258,14 @@ function register9(program3) {
|
|
|
23220
23258
|
description: 'Search groups the current user belongs to (TCP chat channel sid="team", cid="search_own_teams"). Pass --enrich for names + member counts. Will kick a session in the same online-slot.',
|
|
23221
23259
|
output: Output9,
|
|
23222
23260
|
configure: (cmd) => {
|
|
23223
|
-
cmd.argument("<keyword>", "team name fragment").option("--enrich", "follow up with team/get_team per id").option("--os <os>", "chat-channel os slot", parseChatOs
|
|
23261
|
+
cmd.argument("<keyword>", "team name fragment").option("--enrich", "follow up with team/get_team per id").option("--os <os>", "chat-channel os slot (default: cfg.defaultChatOs ?? iOS)", parseChatOs).option("--debug", "forward wire-level debug events to stderr");
|
|
23224
23262
|
},
|
|
23225
23263
|
run: async (cmd) => {
|
|
23226
23264
|
const [kw] = cmd.args;
|
|
23227
|
-
const { enrich, os, debug } = cmd.opts();
|
|
23265
|
+
const { enrich, os: optsOs, debug } = cmd.opts();
|
|
23228
23266
|
const cfg = requireConfig();
|
|
23229
23267
|
const cred = requireAuth(loadCredentials());
|
|
23268
|
+
const os = resolveChatOs(optsOs, cfg);
|
|
23230
23269
|
const session = await openChatSession(cred, { os, debug });
|
|
23231
23270
|
const { socket } = session;
|
|
23232
23271
|
try {
|
|
@@ -23412,11 +23451,13 @@ function register13(program3) {
|
|
|
23412
23451
|
description: "After chat-login, run sync/syncDone, sync/syncSession, sync/syncWithdraws and return the raw responses.",
|
|
23413
23452
|
output: Output13,
|
|
23414
23453
|
configure: (cmd) => {
|
|
23415
|
-
cmd.option("--os <os>", "chat-channel os slot", parseChatOs
|
|
23454
|
+
cmd.option("--os <os>", "chat-channel os slot (default: cfg.defaultChatOs ?? iOS)", parseChatOs).option("--debug", "forward wire-level debug events to stderr");
|
|
23416
23455
|
},
|
|
23417
23456
|
run: async (cmd) => {
|
|
23418
|
-
const { os, debug } = cmd.opts();
|
|
23457
|
+
const { os: optsOs, debug } = cmd.opts();
|
|
23458
|
+
const cfg = requireConfig();
|
|
23419
23459
|
const cred = requireAuth(loadCredentials());
|
|
23460
|
+
const os = resolveChatOs(optsOs, cfg);
|
|
23420
23461
|
const session = await openChatSession(cred, { os, debug });
|
|
23421
23462
|
const { socket } = session;
|
|
23422
23463
|
try {
|
|
@@ -23670,7 +23711,7 @@ function register15(program3) {
|
|
|
23670
23711
|
description: "Send a plain-text chat message via the TCP chat channel. VISIBLE TO THE RECIPIENT \u2014 non-self targets require --yes-not-self.",
|
|
23671
23712
|
output: Output15,
|
|
23672
23713
|
configure: (cmd) => {
|
|
23673
|
-
cmd.argument("<text...>", "message text (variadic; words rejoined with spaces)").option("--peer <uid>", "1:1 chat with a peer uid").option("--team <id>", "group chat with a team id").option("--to-self", "send to your own uid (default if no target given)").option("--yes-not-self", "required to confirm sending to anyone other than yourself").option("--dry-run", "build the frame but do not connect").option("--os <os>", "chat-channel os slot", parseChatOs
|
|
23714
|
+
cmd.argument("<text...>", "message text (variadic; words rejoined with spaces)").option("--peer <uid>", "1:1 chat with a peer uid").option("--team <id>", "group chat with a team id").option("--to-self", "send to your own uid (default if no target given)").option("--yes-not-self", "required to confirm sending to anyone other than yourself").option("--dry-run", "build the frame but do not connect").option("--os <os>", "chat-channel os slot (default: cfg.defaultChatOs ?? iOS)", parseChatOs).option("--tail <text>", "override message tail for this call only").option("--no-tail", "do not append a message tail for this call").option("--debug", "forward wire-level debug events to stderr");
|
|
23674
23715
|
},
|
|
23675
23716
|
run: async (cmd) => {
|
|
23676
23717
|
const text = cmd.args.join(" ").trim();
|
|
@@ -23678,6 +23719,7 @@ function register15(program3) {
|
|
|
23678
23719
|
const opts = cmd.opts();
|
|
23679
23720
|
const cfg = requireConfig();
|
|
23680
23721
|
const cred = requireAuth(loadCredentials());
|
|
23722
|
+
const os = resolveChatOs(opts.os, cfg);
|
|
23681
23723
|
requireSingleTarget(opts, "send");
|
|
23682
23724
|
const conflict = detectFlagConflict(process.argv.slice(2), "tail");
|
|
23683
23725
|
if (conflict.sawValueForm && conflict.sawNegatedForm) {
|
|
@@ -23716,7 +23758,7 @@ function register15(program3) {
|
|
|
23716
23758
|
subType: 1,
|
|
23717
23759
|
body: finalText,
|
|
23718
23760
|
fName: cred.name,
|
|
23719
|
-
platform:
|
|
23761
|
+
platform: os === "Mac" || os === "OS X" ? "Mac" : "Windows",
|
|
23720
23762
|
appKey: cfg.appKey
|
|
23721
23763
|
});
|
|
23722
23764
|
if (opts.dryRun) {
|
|
@@ -23728,7 +23770,7 @@ function register15(program3) {
|
|
|
23728
23770
|
frame: { sid: "talk", cid: "sendMsg", data: { msg } }
|
|
23729
23771
|
};
|
|
23730
23772
|
}
|
|
23731
|
-
const session = await openChatSession(cred, { os
|
|
23773
|
+
const session = await openChatSession(cred, { os, debug: opts.debug });
|
|
23732
23774
|
const { socket } = session;
|
|
23733
23775
|
let res;
|
|
23734
23776
|
try {
|
|
@@ -24468,7 +24510,7 @@ function register16(program3) {
|
|
|
24468
24510
|
description: "Upload a local file (TCP 6101) and broadcast as MESSAGE_CHAT_FILE (subType=7). VISIBLE \u2014 non-self targets require --yes-not-self.",
|
|
24469
24511
|
output: Output16,
|
|
24470
24512
|
configure: (cmd) => {
|
|
24471
|
-
cmd.argument("<file>", "absolute or relative path to a local file").option("--peer <uid>", "1:1 chat with a peer uid").option("--team <id>", "group chat with a team id").option("--to-self", "send to your own uid (default if no target given)").option("--yes-not-self", "required to confirm sending to anyone other than yourself").option("--dry-run", "resolve target + sanity-check the local file but do not upload or send").option("--os <os>", "chat-channel os slot for the talk/sendMsg", parseChatOs
|
|
24513
|
+
cmd.argument("<file>", "absolute or relative path to a local file").option("--peer <uid>", "1:1 chat with a peer uid").option("--team <id>", "group chat with a team id").option("--to-self", "send to your own uid (default if no target given)").option("--yes-not-self", "required to confirm sending to anyone other than yourself").option("--dry-run", "resolve target + sanity-check the local file but do not upload or send").option("--os <os>", "chat-channel os slot for the talk/sendMsg (default: cfg.defaultChatOs ?? iOS)", parseChatOs).option("--debug", "forward wire-level debug events to stderr");
|
|
24472
24514
|
},
|
|
24473
24515
|
run: async (cmd) => {
|
|
24474
24516
|
const filePath = path2.resolve(String(cmd.args[0] ?? ""));
|
|
@@ -24476,6 +24518,7 @@ function register16(program3) {
|
|
|
24476
24518
|
const opts = cmd.opts();
|
|
24477
24519
|
const cfg = requireConfig();
|
|
24478
24520
|
const cred = requireAuth(loadCredentials());
|
|
24521
|
+
const os = resolveChatOs(opts.os, cfg);
|
|
24479
24522
|
requireSingleTarget(opts, "send-file");
|
|
24480
24523
|
let scene;
|
|
24481
24524
|
let toId;
|
|
@@ -24526,10 +24569,10 @@ function register16(program3) {
|
|
|
24526
24569
|
expiredDay: up.expiredDay
|
|
24527
24570
|
}),
|
|
24528
24571
|
fName: cred.name,
|
|
24529
|
-
platform:
|
|
24572
|
+
platform: os === "Mac" || os === "OS X" ? "Mac" : "Windows",
|
|
24530
24573
|
appKey: cfg.appKey
|
|
24531
24574
|
});
|
|
24532
|
-
const session = await openChatSession(cred, { os
|
|
24575
|
+
const session = await openChatSession(cred, { os, debug: opts.debug });
|
|
24533
24576
|
let res;
|
|
24534
24577
|
try {
|
|
24535
24578
|
res = await session.socket.send("talk", "sendMsg", { msg });
|
|
@@ -24642,13 +24685,14 @@ function register17(program3) {
|
|
|
24642
24685
|
description: "Upload an image (TCP 6101) and broadcast as MESSAGE_CHAT_IMAGE (subType=8). VISIBLE \u2014 non-self targets require --yes-not-self.",
|
|
24643
24686
|
output: Output17,
|
|
24644
24687
|
configure: (cmd) => {
|
|
24645
|
-
cmd.argument("<file>", "PNG/JPEG/GIF/BMP image path").option("--peer <uid>", "1:1 chat with a peer uid").option("--team <id>", "group chat with a team id").option("--to-self", "send to your own uid (default)").option("--yes-not-self", "required for non-self targets").option("--width <px>", "override probed image width", parsePosInt("--width")).option("--height <px>", "override probed image height", parsePosInt("--height")).option("--dry-run", "sanity-check the local file (probe + stat) but do not upload or send").option("--os <os>", "chat-channel os slot", parseChatOs
|
|
24688
|
+
cmd.argument("<file>", "PNG/JPEG/GIF/BMP image path").option("--peer <uid>", "1:1 chat with a peer uid").option("--team <id>", "group chat with a team id").option("--to-self", "send to your own uid (default)").option("--yes-not-self", "required for non-self targets").option("--width <px>", "override probed image width", parsePosInt("--width")).option("--height <px>", "override probed image height", parsePosInt("--height")).option("--dry-run", "sanity-check the local file (probe + stat) but do not upload or send").option("--os <os>", "chat-channel os slot (default: cfg.defaultChatOs ?? iOS)", parseChatOs).option("--debug", "forward wire-level debug events to stderr");
|
|
24646
24689
|
},
|
|
24647
24690
|
run: async (cmd) => {
|
|
24648
24691
|
const filePath = path3.resolve(String(cmd.args[0] ?? ""));
|
|
24649
24692
|
const opts = cmd.opts();
|
|
24650
24693
|
const cfg = requireConfig();
|
|
24651
24694
|
const cred = requireAuth(loadCredentials());
|
|
24695
|
+
const os = resolveChatOs(opts.os, cfg);
|
|
24652
24696
|
requireSingleTarget(opts, "send-image");
|
|
24653
24697
|
let scene;
|
|
24654
24698
|
let toId;
|
|
@@ -24714,10 +24758,10 @@ function register17(program3) {
|
|
|
24714
24758
|
height
|
|
24715
24759
|
}),
|
|
24716
24760
|
fName: cred.name,
|
|
24717
|
-
platform:
|
|
24761
|
+
platform: os === "Mac" || os === "OS X" ? "Mac" : "Windows",
|
|
24718
24762
|
appKey: cfg.appKey
|
|
24719
24763
|
});
|
|
24720
|
-
const session = await openChatSession(cred, { os
|
|
24764
|
+
const session = await openChatSession(cred, { os, debug: opts.debug });
|
|
24721
24765
|
let res;
|
|
24722
24766
|
try {
|
|
24723
24767
|
res = await session.socket.send("talk", "sendMsg", { msg });
|
|
@@ -24796,13 +24840,14 @@ function register18(program3) {
|
|
|
24796
24840
|
description: "Upload an audio clip (TCP 6101) and broadcast as MESSAGE_CHAT_AUDIO (subType=9). VISIBLE \u2014 non-self targets require --yes-not-self.",
|
|
24797
24841
|
output: Output18,
|
|
24798
24842
|
configure: (cmd) => {
|
|
24799
|
-
cmd.argument("<file>", "audio file path (typically .amr)").requiredOption("--duration <ms>", "clip duration in milliseconds", parsePosInt("--duration")).option("--peer <uid>", "1:1 chat with a peer uid").option("--team <id>", "group chat with a team id").option("--to-self", "send to your own uid (default)").option("--yes-not-self", "required for non-self targets").option("--dry-run", "sanity-check the local file but do not upload or send").option("--os <os>", "chat-channel os slot", parseChatOs
|
|
24843
|
+
cmd.argument("<file>", "audio file path (typically .amr)").requiredOption("--duration <ms>", "clip duration in milliseconds", parsePosInt("--duration")).option("--peer <uid>", "1:1 chat with a peer uid").option("--team <id>", "group chat with a team id").option("--to-self", "send to your own uid (default)").option("--yes-not-self", "required for non-self targets").option("--dry-run", "sanity-check the local file but do not upload or send").option("--os <os>", "chat-channel os slot (default: cfg.defaultChatOs ?? iOS)", parseChatOs).option("--debug", "forward wire-level debug events to stderr");
|
|
24800
24844
|
},
|
|
24801
24845
|
run: async (cmd) => {
|
|
24802
24846
|
const filePath = path4.resolve(String(cmd.args[0] ?? ""));
|
|
24803
24847
|
const opts = cmd.opts();
|
|
24804
24848
|
const cfg = requireConfig();
|
|
24805
24849
|
const cred = requireAuth(loadCredentials());
|
|
24850
|
+
const os = resolveChatOs(opts.os, cfg);
|
|
24806
24851
|
requireSingleTarget(opts, "send-voice");
|
|
24807
24852
|
let scene;
|
|
24808
24853
|
let toId;
|
|
@@ -24861,10 +24906,10 @@ function register18(program3) {
|
|
|
24861
24906
|
duration: opts.duration
|
|
24862
24907
|
}),
|
|
24863
24908
|
fName: cred.name,
|
|
24864
|
-
platform:
|
|
24909
|
+
platform: os === "Mac" || os === "OS X" ? "Mac" : "Windows",
|
|
24865
24910
|
appKey: cfg.appKey
|
|
24866
24911
|
});
|
|
24867
|
-
const session = await openChatSession(cred, { os
|
|
24912
|
+
const session = await openChatSession(cred, { os, debug: opts.debug });
|
|
24868
24913
|
let res;
|
|
24869
24914
|
try {
|
|
24870
24915
|
res = await session.socket.send("talk", "sendMsg", { msg });
|
|
@@ -25033,12 +25078,13 @@ function register20(program3) {
|
|
|
25033
25078
|
description: "Withdraw a previously-sent message (P2P_MSG_CANCEL). VISIBLE TO THE RECIPIENT \u2014 non-self targets require --yes-not-self.",
|
|
25034
25079
|
output: Output20,
|
|
25035
25080
|
configure: (cmd) => {
|
|
25036
|
-
cmd.requiredOption("--mid <mid>", "message id to withdraw").option("--peer <uid>", "1:1 chat with a peer uid").option("--team <id>", "group chat with a team id").option("--to-self", "withdraw in your self-chat (default if no target)").option("--yes-not-self", "required to confirm withdrawing in a non-self conversation").option("--dry-run", "build the frame but do not connect").option("--os <os>", "chat-channel os slot", parseChatOs
|
|
25081
|
+
cmd.requiredOption("--mid <mid>", "message id to withdraw").option("--peer <uid>", "1:1 chat with a peer uid").option("--team <id>", "group chat with a team id").option("--to-self", "withdraw in your self-chat (default if no target)").option("--yes-not-self", "required to confirm withdrawing in a non-self conversation").option("--dry-run", "build the frame but do not connect").option("--os <os>", "chat-channel os slot (default: cfg.defaultChatOs ?? iOS)", parseChatOs).option("--debug", "forward wire-level debug events to stderr");
|
|
25037
25082
|
},
|
|
25038
25083
|
run: async (cmd) => {
|
|
25039
25084
|
const opts = cmd.opts();
|
|
25040
25085
|
const cfg = requireConfig();
|
|
25041
25086
|
const cred = requireAuth(loadCredentials());
|
|
25087
|
+
const os = resolveChatOs(opts.os, cfg);
|
|
25042
25088
|
requireSingleTarget(opts, "withdraw");
|
|
25043
25089
|
let scene;
|
|
25044
25090
|
let toId;
|
|
@@ -25068,7 +25114,7 @@ function register20(program3) {
|
|
|
25068
25114
|
subType: 2,
|
|
25069
25115
|
body: { mids: [opts.mid] },
|
|
25070
25116
|
fName: cred.name,
|
|
25071
|
-
platform:
|
|
25117
|
+
platform: os === "Mac" || os === "OS X" ? "Mac" : "Windows",
|
|
25072
25118
|
appKey: cfg.appKey
|
|
25073
25119
|
});
|
|
25074
25120
|
if (opts.dryRun) {
|
|
@@ -25080,7 +25126,7 @@ function register20(program3) {
|
|
|
25080
25126
|
frame: { sid: "talk", cid: "sendMsg", data: { msg } }
|
|
25081
25127
|
};
|
|
25082
25128
|
}
|
|
25083
|
-
const session = await openChatSession(cred, { os
|
|
25129
|
+
const session = await openChatSession(cred, { os, debug: opts.debug });
|
|
25084
25130
|
const { socket } = session;
|
|
25085
25131
|
let res;
|
|
25086
25132
|
try {
|
|
@@ -25123,11 +25169,13 @@ function register21(program3) {
|
|
|
25123
25169
|
description: "Send user/delSession to drop the local session record on all of the user's devices.",
|
|
25124
25170
|
output: Output21,
|
|
25125
25171
|
configure: (cmd) => {
|
|
25126
|
-
cmd.option("--peer <uid>", "session with a peer uid").option("--team <id>", "session with a team id").option("--to-self", "self-chat session (default if no target)").option("--yes-not-self", "required to confirm clearing a non-self session").option("--dry-run", "build the frame but do not connect").option("--os <os>", "chat-channel os slot", parseChatOs
|
|
25172
|
+
cmd.option("--peer <uid>", "session with a peer uid").option("--team <id>", "session with a team id").option("--to-self", "self-chat session (default if no target)").option("--yes-not-self", "required to confirm clearing a non-self session").option("--dry-run", "build the frame but do not connect").option("--os <os>", "chat-channel os slot (default: cfg.defaultChatOs ?? iOS)", parseChatOs).option("--debug", "forward wire-level debug events to stderr");
|
|
25127
25173
|
},
|
|
25128
25174
|
run: async (cmd) => {
|
|
25129
25175
|
const opts = cmd.opts();
|
|
25176
|
+
const cfg = requireConfig();
|
|
25130
25177
|
const cred = requireAuth(loadCredentials());
|
|
25178
|
+
const os = resolveChatOs(opts.os, cfg);
|
|
25131
25179
|
requireSingleTarget(opts, "clear-session");
|
|
25132
25180
|
let scene;
|
|
25133
25181
|
let toId;
|
|
@@ -25154,7 +25202,7 @@ function register21(program3) {
|
|
|
25154
25202
|
if (opts.dryRun) {
|
|
25155
25203
|
return { scene, toId, sId, dryRun: true, frame };
|
|
25156
25204
|
}
|
|
25157
|
-
const session = await openChatSession(cred, { os
|
|
25205
|
+
const session = await openChatSession(cred, { os, debug: opts.debug });
|
|
25158
25206
|
const { socket } = session;
|
|
25159
25207
|
let res;
|
|
25160
25208
|
try {
|
|
@@ -25442,13 +25490,15 @@ function register25(program3) {
|
|
|
25442
25490
|
description: "Block until someone adds an emoticon reaction (subType=300) to --mid. Consumes a TCP slot \u2014 defaults to --os iOS (Mobile slot).",
|
|
25443
25491
|
output: Output25,
|
|
25444
25492
|
configure: (cmd) => {
|
|
25445
|
-
cmd.requiredOption("--mid <mid>", "message id to wait for a reaction on").option("--from-uid <uid>", "only consider reactions from this UID (case-insensitive match against fId of the type=3 notification)").option("--sticker-id <id>", "only consider reactions whose stickerId matches").option("--timeout <seconds>", "give up after this many seconds (default 300)", parsePosInt("--timeout"), 300).option("--os <os>", "chat-channel os slot", parseChatOs
|
|
25493
|
+
cmd.requiredOption("--mid <mid>", "message id to wait for a reaction on").option("--from-uid <uid>", "only consider reactions from this UID (case-insensitive match against fId of the type=3 notification)").option("--sticker-id <id>", "only consider reactions whose stickerId matches").option("--timeout <seconds>", "give up after this many seconds (default 300)", parsePosInt("--timeout"), 300).option("--os <os>", "chat-channel os slot (default: cfg.defaultChatOs ?? iOS)", parseChatOs).option("--debug", "forward wire-level debug events to stderr");
|
|
25446
25494
|
},
|
|
25447
25495
|
run: async (cmd) => {
|
|
25448
25496
|
const opts = cmd.opts();
|
|
25497
|
+
const cfg = requireConfig();
|
|
25449
25498
|
const cred = requireAuth(loadCredentials());
|
|
25499
|
+
const os = resolveChatOs(opts.os, cfg);
|
|
25450
25500
|
const wantedFrom = opts.fromUid?.toUpperCase();
|
|
25451
|
-
const session = await openChatSession(cred, { os
|
|
25501
|
+
const session = await openChatSession(cred, { os, debug: opts.debug });
|
|
25452
25502
|
const { socket } = session;
|
|
25453
25503
|
try {
|
|
25454
25504
|
return await new Promise((resolve2, reject) => {
|
|
@@ -25588,7 +25638,7 @@ function register26(program3) {
|
|
|
25588
25638
|
description: "Tail incoming chat messages, filtered by sender / team / peer / keyword / regex / @-mention. Emit one line per match \u2014 NDJSON envelope under `--json`, human summary otherwise. Consumes a TCP slot.",
|
|
25589
25639
|
streamSchema: STREAM_SCHEMA,
|
|
25590
25640
|
configure: (cmd) => {
|
|
25591
|
-
cmd.option("--from-uid <uid>", "only emit messages from this UID (repeat for OR; matched against fId, case-insensitive)", collect, []).option("--team <id>", "only emit messages in this team (repeat for OR)", collect, []).option("--peer <uid>", "only emit p2p messages with this peer UID (repeat for OR)", collect, []).option("--contains <text>", "only emit messages whose text contains this substring, case-insensitive (repeat for OR)", collect, []).option("--regex <pattern>", "only emit messages whose text matches this RE2-flavoured regex (repeat for OR)", collect, []).option("--type <n>", "only emit messages of this `type` field (default 1; repeat for OR)", collectInt("--type"), []).option("--subtype <n>", "only emit messages of this `subType` field (repeat for OR; default = any)", collectInt("--subtype"), []).option("--max <n>", "exit after emitting this many matching lines", parsePosInt("--max")).option("--at-me", "only emit group messages that @-mention you (mirrors the desktop SDK isAtMe: scene=team_g, fId\u2260self, atIds includes self uid). Implies excluding self.").option("--include-self", "do not filter out messages whose fId is your own UID").option("--include-reactions", "also emit type=3 sub=300/301 (reaction add/remove) frames").option("--include-offline", "also emit messages flushed via cid=offMsg on connect (default: only post-connect msg)").option("--os <os>", "chat-channel os slot", parseChatOs
|
|
25641
|
+
cmd.option("--from-uid <uid>", "only emit messages from this UID (repeat for OR; matched against fId, case-insensitive)", collect, []).option("--team <id>", "only emit messages in this team (repeat for OR)", collect, []).option("--peer <uid>", "only emit p2p messages with this peer UID (repeat for OR)", collect, []).option("--contains <text>", "only emit messages whose text contains this substring, case-insensitive (repeat for OR)", collect, []).option("--regex <pattern>", "only emit messages whose text matches this RE2-flavoured regex (repeat for OR)", collect, []).option("--type <n>", "only emit messages of this `type` field (default 1; repeat for OR)", collectInt("--type"), []).option("--subtype <n>", "only emit messages of this `subType` field (repeat for OR; default = any)", collectInt("--subtype"), []).option("--max <n>", "exit after emitting this many matching lines", parsePosInt("--max")).option("--at-me", "only emit group messages that @-mention you (mirrors the desktop SDK isAtMe: scene=team_g, fId\u2260self, atIds includes self uid). Implies excluding self.").option("--include-self", "do not filter out messages whose fId is your own UID").option("--include-reactions", "also emit type=3 sub=300/301 (reaction add/remove) frames").option("--include-offline", "also emit messages flushed via cid=offMsg on connect (default: only post-connect msg)").option("--os <os>", "chat-channel os slot (default: cfg.defaultChatOs ?? iOS)", parseChatOs).option("--debug", "forward wire-level debug events to stderr");
|
|
25592
25642
|
},
|
|
25593
25643
|
run: async (cmd) => {
|
|
25594
25644
|
const opts = cmd.opts();
|
|
@@ -25615,8 +25665,10 @@ function register26(program3) {
|
|
|
25615
25665
|
}
|
|
25616
25666
|
const includeSelf = !!opts.includeSelf;
|
|
25617
25667
|
const selfUidUpper = cred.uid.toUpperCase();
|
|
25618
|
-
const
|
|
25619
|
-
const
|
|
25668
|
+
const cfg = requireConfig();
|
|
25669
|
+
const selfAppKey = cfg.appKey;
|
|
25670
|
+
const os = resolveChatOs(opts.os, cfg);
|
|
25671
|
+
const session = await openChatSession(cred, { os, debug: opts.debug });
|
|
25620
25672
|
const { socket } = session;
|
|
25621
25673
|
const json = isJsonMode();
|
|
25622
25674
|
let matched = 0;
|