siluzan-tso-cli 1.0.0-beta.31 → 1.0.0-beta.33

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 CHANGED
@@ -20,7 +20,7 @@ siluzan-tso init -d /path/to/skills # 写入自定义目录
20
20
  siluzan-tso init --force # 强制覆盖已存在文件
21
21
  ```
22
22
 
23
- > **注意**:当前为测试版(1.0.0-beta.31),供内部测试使用。正式发布后安装命令将改为 `npm install -g siluzan-tso-cli`。
23
+ > **注意**:当前为测试版(1.0.0-beta.33),供内部测试使用。正式发布后安装命令将改为 `npm install -g siluzan-tso-cli`。
24
24
 
25
25
  | 助手 | 建议 `--ai` |
26
26
  |------|-------------|
package/dist/index.js CHANGED
@@ -1,8 +1,8 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  // src/index.ts
4
- import * as fs9 from "fs";
5
- import * as path10 from "path";
4
+ import * as fs8 from "fs";
5
+ import * as path9 from "path";
6
6
  import { fileURLToPath as fileURLToPath3 } from "url";
7
7
  import { Command } from "commander";
8
8
 
@@ -802,12 +802,15 @@ function findDpByUrl(nodes, targetUrl) {
802
802
  }
803
803
  return void 0;
804
804
  }
805
- async function fetchDataPermission(mainApiUrl, authToken) {
805
+ async function fetchDataPermission(mainApiUrl, auth) {
806
806
  const url = `${mainApiUrl}/command/menu/GetUserPermissions`;
807
+ const headers = {
808
+ "Content-Type": "application/json",
809
+ "Accept-Language": "zh-CN",
810
+ ...auth.apiKey ? { "x-api-key": auth.apiKey } : { Authorization: `Bearer ${auth.authToken}` }
811
+ };
807
812
  try {
808
- const res = await fetch(url, {
809
- headers: { Authorization: `Bearer ${authToken}`, "Content-Type": "application/json" }
810
- });
813
+ const res = await fetch(url, { headers });
811
814
  if (!res.ok) return "";
812
815
  const json = await res.json();
813
816
  const dp = findDpByUrl(json.data ?? [], TSO_KNOWN_ROUTE);
@@ -816,6 +819,17 @@ async function fetchDataPermission(mainApiUrl, authToken) {
816
819
  return "";
817
820
  }
818
821
  }
822
+ async function ensureDataPermission(config) {
823
+ if (config.dataPermission?.trim()) return config;
824
+ if (!config.mainApiUrl) return config;
825
+ const dp = await fetchDataPermission(config.mainApiUrl, config);
826
+ if (!dp) return config;
827
+ try {
828
+ writeSharedConfig({ dataPermission: dp });
829
+ } catch {
830
+ }
831
+ return { ...config, dataPermission: dp };
832
+ }
819
833
  function loadConfig(tokenArg) {
820
834
  const shared = readSharedConfig();
821
835
  const apiKey = process.env.SILUZAN_API_KEY ?? (shared.apiKey ? shared.apiKey : void 0);
@@ -1549,7 +1563,7 @@ async function runListAccounts(opts) {
1549
1563
  process.exit(1);
1550
1564
  }
1551
1565
  }
1552
- if (items.length > 0) {
1566
+ if (items.length > 0 && !opts.quick) {
1553
1567
  const groups = /* @__PURE__ */ new Map();
1554
1568
  for (const item of items) {
1555
1569
  const id = item.ma.mediaCustomerId;
@@ -1638,9 +1652,13 @@ async function runListAccounts(opts) {
1638
1652
  return;
1639
1653
  }
1640
1654
  const totalInfo = total !== void 0 ? `\uFF0C\u5171 ${total} \u6761` : "";
1641
- console.log(`
1642
- \u5E7F\u544A\u8D26\u6237\u5217\u8868\uFF08\u7B2C ${page} \u9875\uFF0C\u672C\u9875 ${items.length} \u6761${totalInfo}\uFF09
1643
- `);
1655
+ let listHeader = `
1656
+ \u5E7F\u544A\u8D26\u6237\u5217\u8868\uFF08\u7B2C ${page} \u9875\uFF0C\u672C\u9875 ${items.length} \u6761${totalInfo}\uFF09`;
1657
+ if (opts.quick) {
1658
+ listHeader += "\n \uFF08\u5FEB\u901F\u6A21\u5F0F\uFF1A\u672A\u5408\u5E76\u4F59\u989D\u3001\u6295\u653E\u6D88\u8017\u4E0E Arit \u5F97\u5206\uFF1B\u8868\u4E2D\u5BF9\u5E94\u5217\u4E3A\u300C-\u300D\u3002TikTok/Meta \u4ECD\u5408\u5E76\u5217\u8868\u63A5\u53E3\u540C\u5305\u5185\u7684 adList\u3002\uFF09";
1659
+ }
1660
+ listHeader += "\n";
1661
+ console.log(listHeader);
1644
1662
  if (items.length === 0) {
1645
1663
  console.log("\u6682\u65E0\u5E7F\u544A\u8D26\u6237\u6570\u636E\u3002\n");
1646
1664
  return;
@@ -2812,9 +2830,9 @@ async function runOneSection(def, opts) {
2812
2830
  if (def.audienceFilterOption && opts.audienceType) {
2813
2831
  extras.audienceTypeFilter = opts.audienceType;
2814
2832
  }
2815
- const path11 = def.path(id);
2833
+ const path10 = def.path(id);
2816
2834
  const query = buildSearchParams(def, opts.start, opts.end, extras);
2817
- const fullPath = `${path11}${query}`;
2835
+ const fullPath = `${path10}${query}`;
2818
2836
  try {
2819
2837
  if (def.name === "materials") {
2820
2838
  const { startDate, endDate } = resolveDateRange(opts.start, opts.end);
@@ -3729,23 +3747,6 @@ async function runTransferList(opts) {
3729
3747
  }
3730
3748
 
3731
3749
  // src/commands/invoice.ts
3732
- import * as fs7 from "fs";
3733
- import * as path7 from "path";
3734
- import * as os6 from "os";
3735
- async function ensureDataPermission(config) {
3736
- if (config.dataPermission) return config;
3737
- if (!config.mainApiUrl) return config;
3738
- const dp = await fetchDataPermission(config.mainApiUrl, config.authToken);
3739
- if (!dp) return config;
3740
- const configPath = path7.join(os6.homedir(), ".siluzan", "config.json");
3741
- try {
3742
- const raw = fs7.existsSync(configPath) ? JSON.parse(fs7.readFileSync(configPath, "utf8")) : {};
3743
- raw.dataPermission = dp;
3744
- fs7.writeFileSync(configPath, JSON.stringify(raw, null, 2), "utf8");
3745
- } catch {
3746
- }
3747
- return { ...config, dataPermission: dp };
3748
- }
3749
3750
  function formatDate(d) {
3750
3751
  return d.toISOString().slice(0, 10);
3751
3752
  }
@@ -5463,8 +5464,8 @@ async function runOptimizeChildren(opts) {
5463
5464
  }
5464
5465
 
5465
5466
  // src/commands/forewarning.ts
5466
- import os7 from "os";
5467
- import path8 from "path";
5467
+ import os6 from "os";
5468
+ import path7 from "path";
5468
5469
  import QRCode from "qrcode";
5469
5470
  import open from "open";
5470
5471
  var VALID_MEDIA_TYPES7 = ["Google", "TikTok"];
@@ -5672,7 +5673,7 @@ async function runForewarningNotifyAccounts(opts) {
5672
5673
  console.log(" \u901A\u77E5\u6E20\u9053\uFF1A\u4E1D\u8DEF\u8D5E\u5E73\u53F0\u5FAE\u4FE1\u670D\u52A1\u53F7\uFF08\u9700\u626B\u7801\u5173\u6CE8\u540E\u624D\u80FD\u6536\u5230\u9884\u8B66\u901A\u77E5\uFF09\n");
5673
5674
  if (qrLink) {
5674
5675
  try {
5675
- const imgPath = path8.join(os7.tmpdir(), "siluzan-wechat-qr.png");
5676
+ const imgPath = path7.join(os6.tmpdir(), "siluzan-wechat-qr.png");
5676
5677
  await QRCode.toFile(imgPath, qrLink, { width: 300 });
5677
5678
  await open(imgPath);
5678
5679
  console.log(` \u{1F4F7} \u4E8C\u7EF4\u7801\u5DF2\u5728\u6D4F\u89C8\u5668\u4E2D\u6253\u5F00\uFF0C\u8BF7\u7528\u624B\u673A\u5FAE\u4FE1\u626B\u7801\u5173\u6CE8"\u4E1D\u8DEF\u8D5E\u5E73\u53F0"\u670D\u52A1\u53F7
@@ -8118,7 +8119,7 @@ function printEmailDeauthHintToStderr() {
8118
8119
  );
8119
8120
  }
8120
8121
  async function runAccountEmailAuthList(opts) {
8121
- const config = loadConfig(opts.token);
8122
+ const config = await ensureDataPermission(loadConfig(opts.token));
8122
8123
  let items;
8123
8124
  try {
8124
8125
  items = await fetchCustomerUserAccessInvitationList(
@@ -8165,7 +8166,7 @@ async function runAccountEmailAuthList(opts) {
8165
8166
  console.log("\n\u63D0\u793A\uFF1A\u4F7F\u7528 account email-deauth \u89E3\u9664\u6388\u6743\uFF0C--invitation-id \u6765\u81EA\u4E0A\u65B9\u9080\u8BF7 ID\u3002\n");
8166
8167
  }
8167
8168
  async function runAccountEmailAuth(opts) {
8168
- const config = loadConfig(opts.token);
8169
+ const config = await ensureDataPermission(loadConfig(opts.token));
8169
8170
  const base = googleGatewayBase(config);
8170
8171
  const url = `${base}/command/media-account/MutateCustomerUserAccessInvitation`;
8171
8172
  const body = {
@@ -8196,7 +8197,16 @@ async function runAccountEmailAuth(opts) {
8196
8197
  }
8197
8198
  let result;
8198
8199
  try {
8199
- result = await apiFetch2(url, config, { method: "POST", body: JSON.stringify(body) }, opts.verbose);
8200
+ result = await apiFetch2(
8201
+ url,
8202
+ config,
8203
+ {
8204
+ method: "POST",
8205
+ body: JSON.stringify(body),
8206
+ headers: { isqs: "true" }
8207
+ },
8208
+ opts.verbose
8209
+ );
8200
8210
  } catch (err) {
8201
8211
  console.error(`
8202
8212
  \u274C \u90AE\u7BB1\u6388\u6743\u5931\u8D25\uFF1A${err instanceof Error ? err.message : String(err)}
@@ -8228,27 +8238,53 @@ async function runAccountEmailAuth(opts) {
8228
8238
  console.log(JSON.stringify(result, null, 2));
8229
8239
  return;
8230
8240
  }
8241
+ const tail = typeof result === "string" && result.trim() ? `
8242
+ \u63A5\u53E3\u8FD4\u56DE\uFF1A${result.trim()}` : "";
8231
8243
  console.log(
8232
8244
  `
8233
- \u2705 \u5DF2\u5411 ${opts.email} \u53D1\u9001 Google \u5E7F\u544A\u8D26\u6237\uFF08${opts.customerId}\uFF09\u6388\u6743\u9080\u8BF7\uFF08\u6743\u9650\uFF1A${opts.accessRole ?? "Standard"}\uFF09\u3002
8245
+ \u2705 \u5DF2\u5411 ${opts.email} \u53D1\u9001 Google \u5E7F\u544A\u8D26\u6237\uFF08${opts.customerId}\uFF09\u6388\u6743\u9080\u8BF7\uFF08\u6743\u9650\uFF1A${opts.accessRole ?? "Standard"}\uFF09\u3002${tail}
8234
8246
  `
8235
8247
  );
8236
8248
  }
8237
8249
  async function runAccountEmailDeauth(opts) {
8238
- const config = loadConfig(opts.token);
8250
+ const config = await ensureDataPermission(loadConfig(opts.token));
8239
8251
  const base = googleGatewayBase(config);
8240
8252
  const endpoint = opts.accepted !== false ? "RemoveCustomerUserAccess" : "RemoveCustomerUserAccessInvitation";
8241
8253
  const url = `${base}/command/media-account/${endpoint}`;
8254
+ const resourceName = opts.resourceName?.trim() || `customers/${opts.customerId}/customerUserAccessInvitations/${opts.invitationId}`;
8242
8255
  const body = {
8243
8256
  CustomerId: opts.customerId,
8244
8257
  // 接口字段为 invitationld(小写 L),非 invitationId,与前端保持一致
8245
8258
  invitationld: opts.invitationId,
8246
8259
  AgentType: opts.agentType,
8247
- resourceName: opts.resourceName
8260
+ resourceName
8261
+ };
8262
+ const bodyStr = JSON.stringify(body);
8263
+ const headers = {
8264
+ "Content-Type": "application/json; charset=utf-8",
8265
+ Accept: "application/json, text/plain, */*",
8266
+ "Accept-Language": "zh-CN",
8267
+ ...config.apiKey ? { "x-api-key": config.apiKey } : { Authorization: `Bearer ${config.authToken}` },
8268
+ Datapermission: config.dataPermission ?? "",
8269
+ "Content-Length": String(Buffer.byteLength(bodyStr, "utf8"))
8248
8270
  };
8249
8271
  let result;
8250
8272
  try {
8251
- result = await apiFetch2(url, config, { method: "DELETE", body: JSON.stringify(body) }, opts.verbose);
8273
+ const res = await rawRequest(url, { method: "DELETE", headers, body: bodyStr });
8274
+ const text = res.text;
8275
+ if (res.status < 200 || res.status >= 300) {
8276
+ const detail = opts.verbose ? `\uFF1A${text.slice(0, 300)}` : "";
8277
+ throw new Error(`HTTP ${res.status}${detail}`);
8278
+ }
8279
+ if (!text.trim()) {
8280
+ result = null;
8281
+ } else {
8282
+ try {
8283
+ result = JSON.parse(text);
8284
+ } catch {
8285
+ result = text;
8286
+ }
8287
+ }
8252
8288
  } catch (err) {
8253
8289
  console.error(`
8254
8290
  \u274C \u89E3\u9664\u90AE\u7BB1\u6388\u6743\u5931\u8D25\uFF1A${err instanceof Error ? err.message : String(err)}
@@ -8259,8 +8295,10 @@ async function runAccountEmailDeauth(opts) {
8259
8295
  console.log(JSON.stringify(result, null, 2));
8260
8296
  return;
8261
8297
  }
8298
+ const tail = typeof result === "string" && result.trim() ? `
8299
+ \u63A5\u53E3\u8FD4\u56DE\uFF1A${result.trim()}` : "";
8262
8300
  console.log(`
8263
- \u2705 \u5DF2\u89E3\u9664\u9080\u8BF7 ${opts.invitationId} \u7684\u90AE\u7BB1\u6388\u6743\u3002
8301
+ \u2705 \u5DF2\u89E3\u9664\u9080\u8BF7 ${opts.invitationId} \u7684\u90AE\u7BB1\u6388\u6743\u3002${tail}
8264
8302
  `);
8265
8303
  }
8266
8304
  async function runAccountBmBind(opts) {
@@ -8295,8 +8333,8 @@ async function runAccountBmBind(opts) {
8295
8333
  }
8296
8334
 
8297
8335
  // src/commands/open-account.ts
8298
- import * as fs8 from "fs";
8299
- import * as path9 from "path";
8336
+ import * as fs7 from "fs";
8337
+ import * as path8 from "path";
8300
8338
  import * as readline from "readline/promises";
8301
8339
  import { stdin as stdinStream, stdout as stdoutStream } from "process";
8302
8340
  async function runListAdvertiserGroups(opts) {
@@ -8544,18 +8582,19 @@ async function runOpenAccountYandex(opts) {
8544
8582
  }
8545
8583
  }
8546
8584
  async function uploadAttachment(filePath, apiBaseUrl, config, verbose) {
8547
- const fileName = path9.basename(filePath);
8548
- const fileBuffer = fs8.readFileSync(filePath);
8585
+ const fileName = path8.basename(filePath);
8586
+ const fileBuffer = fs7.readFileSync(filePath);
8549
8587
  const mimeType = guessContentType(fileName);
8550
8588
  const form = new FormData();
8551
8589
  form.append("file", new Blob([fileBuffer], { type: mimeType }), fileName);
8552
8590
  const uploadUrl = `${apiBaseUrl}/command/attachment`;
8591
+ const authHeaders = config.apiKey ? { "x-api-key": config.apiKey } : { Authorization: `Bearer ${config.authToken}` };
8553
8592
  const res = await fetch(uploadUrl, {
8554
8593
  method: "POST",
8555
8594
  headers: {
8556
- Authorization: `Bearer ${config.authToken}`,
8595
+ "Accept-Language": "zh-CN",
8596
+ ...authHeaders,
8557
8597
  Datapermission: config.dataPermission ?? ""
8558
- // 注意:不手动设置 Content-Type,让 fetch 自动添加含 boundary 的值
8559
8598
  },
8560
8599
  body: form
8561
8600
  });
@@ -8571,7 +8610,7 @@ async function uploadAttachment(filePath, apiBaseUrl, config, verbose) {
8571
8610
  return { id: data.id, fileName, storageProvider: data.storageProvider ?? "StorageAccount" };
8572
8611
  }
8573
8612
  function guessContentType(fileName) {
8574
- const ext = path9.extname(fileName).toLowerCase();
8613
+ const ext = path8.extname(fileName).toLowerCase();
8575
8614
  const map = {
8576
8615
  ".jpg": "image/jpeg",
8577
8616
  ".jpeg": "image/jpeg",
@@ -8584,7 +8623,7 @@ function guessContentType(fileName) {
8584
8623
  }
8585
8624
  async function runOpenAccountBing(opts) {
8586
8625
  const config = loadConfig(opts.token);
8587
- if (!fs8.existsSync(opts.licenseFile)) {
8626
+ if (!fs7.existsSync(opts.licenseFile)) {
8588
8627
  console.error(`
8589
8628
  \u274C \u8425\u4E1A\u6267\u7167\u6587\u4EF6\u4E0D\u5B58\u5728\uFF1A${opts.licenseFile}
8590
8629
  `);
@@ -8665,9 +8704,9 @@ async function runOpenAccountBing(opts) {
8665
8704
  }
8666
8705
  }
8667
8706
  async function uploadToKwai(filePath, apiBaseUrl, config, verbose) {
8668
- const ext = path9.extname(filePath).toLowerCase().replace(".", "").replace("jpg", "jpeg");
8707
+ const ext = path8.extname(filePath).toLowerCase().replace(".", "").replace("jpg", "jpeg");
8669
8708
  const imageType = ext || "jpeg";
8670
- const fileBuffer = fs8.readFileSync(filePath);
8709
+ const fileBuffer = fs7.readFileSync(filePath);
8671
8710
  const base64Image = fileBuffer.toString("base64");
8672
8711
  const res = await apiFetch2(
8673
8712
  `${apiBaseUrl}/KwaiAccount/Management/Upload`,
@@ -8686,7 +8725,7 @@ async function uploadToKwai(filePath, apiBaseUrl, config, verbose) {
8686
8725
  }
8687
8726
  async function runOpenAccountKwai(opts) {
8688
8727
  const config = loadConfig(opts.token);
8689
- if (!fs8.existsSync(opts.licenseFile)) {
8728
+ if (!fs7.existsSync(opts.licenseFile)) {
8690
8729
  console.error(`
8691
8730
  \u274C \u8425\u4E1A\u6267\u7167\u6587\u4EF6\u4E0D\u5B58\u5728\uFF1A${opts.licenseFile}
8692
8731
  `);
@@ -9009,8 +9048,8 @@ async function runOpenAccountGoogle(opts) {
9009
9048
  }
9010
9049
  }
9011
9050
  async function uploadLicenseToTikTok(filePath, businessCentreType, config, verbose) {
9012
- const fileName = path9.basename(filePath);
9013
- const fileBuffer = fs8.readFileSync(filePath);
9051
+ const fileName = path8.basename(filePath);
9052
+ const fileBuffer = fs7.readFileSync(filePath);
9014
9053
  const base64Image = fileBuffer.toString("base64");
9015
9054
  const res = await apiFetch2(
9016
9055
  `${config.apiBaseUrl}/command/media-account/tiktok/Upload`,
@@ -9035,7 +9074,7 @@ async function uploadLicenseToTikTok(filePath, businessCentreType, config, verbo
9035
9074
  async function runOpenAccountTikTok(opts) {
9036
9075
  const config = loadConfig(opts.token);
9037
9076
  const bcType = opts.businessCentreType ?? "Shop";
9038
- if (!fs8.existsSync(opts.licenseFile)) {
9077
+ if (!fs7.existsSync(opts.licenseFile)) {
9039
9078
  console.error(`
9040
9079
  \u274C \u8425\u4E1A\u6267\u7167\u6587\u4EF6\u4E0D\u5B58\u5728\uFF1A${opts.licenseFile}
9041
9080
  `);
@@ -9410,9 +9449,9 @@ async function runLogin(opts = {}) {
9410
9449
  // src/index.ts
9411
9450
  function getVersion() {
9412
9451
  try {
9413
- const __dirname2 = path10.dirname(fileURLToPath3(import.meta.url));
9414
- const pkgPath = path10.join(__dirname2, "..", "package.json");
9415
- const pkg = JSON.parse(fs9.readFileSync(pkgPath, "utf8"));
9452
+ const __dirname2 = path9.dirname(fileURLToPath3(import.meta.url));
9453
+ const pkgPath = path9.join(__dirname2, "..", "package.json");
9454
+ const pkg = JSON.parse(fs8.readFileSync(pkgPath, "utf8"));
9416
9455
  return pkg.version ?? "0.0.0";
9417
9456
  } catch {
9418
9457
  return "0.0.0";
@@ -9465,7 +9504,15 @@ program.command("list-accounts").description("\u67E5\u8BE2\u5E7F\u544A\u8D26\u62
9465
9504
  "-s, --status <status>",
9466
9505
  "\u8D26\u6237\u72B6\u6001\uFF1Anormal\uFF08\u6B63\u5E38\uFF09| invalid\uFF08\u5931\u6548\uFF09| all\uFF08\u5168\u90E8\uFF0C\u9ED8\u8BA4\uFF09",
9467
9506
  "all"
9468
- ).option("-p, --page <n>", "\u9875\u7801\uFF08\u9ED8\u8BA4 1\uFF09", parseInt).option("--page-size <n>", "\u6BCF\u9875\u6570\u91CF\uFF08\u9ED8\u8BA4 20\uFF09", parseInt).option("-t, --token <token>", "Token\uFF08\u53EF\u9009\uFF1B\u4F18\u5148\u4E8E ~/.siluzan/config.json\uFF09").option("--json", "\u4EE5 JSON \u683C\u5F0F\u8F93\u51FA\u539F\u59CB\u54CD\u5E94", false).option(
9507
+ ).option("-p, --page <n>", "\u9875\u7801\uFF08\u9ED8\u8BA4 1\uFF09", parseInt).option("--page-size <n>", "\u6BCF\u9875\u6570\u91CF\uFF08\u9ED8\u8BA4 20\uFF09", parseInt).option("-t, --token <token>", "Token\uFF08\u53EF\u9009\uFF1B\u4F18\u5148\u4E8E ~/.siluzan/config.json\uFF09").option(
9508
+ "--json",
9509
+ "\u4EE5 JSON \u8F93\u51FA\uFF08\u542B\u5206\u9875\u4FE1\u5C01\u4E0E items\uFF1B\u9ED8\u8BA4\u4ECD\u4F1A\u5408\u5E76\u4F59\u989D/\u6D88\u8017/Arit\uFF0C\u4E0E\u8868\u683C\u4E00\u81F4\u3002\u52A0 --quick \u5219 items \u4EC5\u542B\u5217\u8868\u63A5\u53E3\u5B57\u6BB5\uFF09",
9510
+ false
9511
+ ).option(
9512
+ "--quick",
9513
+ "\u5FEB\u901F\u6A21\u5F0F\uFF1A\u53EA\u8BF7\u6C42\u8D26\u6237\u5217\u8868\u63A5\u53E3\uFF0C\u4E0D\u518D\u5E76\u884C\u62C9\u53D6\u4F59\u989D\uFF08GetMediaAccountInfo\uFF09\u3001\u6295\u653E\u6982\u89C8\uFF08accountsoverview\uFF09\u3001ARIT \u8BCA\u65AD\u5F97\u5206\uFF1B\u8BF7\u6C42\u66F4\u5C11\u3001\u8FD4\u56DE\u66F4\u5FEB\u3002\u8868\u683C\u4E0E JSON \u4E2D\u4F59\u989D\u3001\u6D88\u8017\u3001\u5C55\u793A/\u70B9\u51FB/\u8F6C\u5316/CPC\u3001Arit \u7B49\u5C06\u4E3A\u7A7A\u6216\u300C-\u300D\u3002TikTok/Meta \u5217\u8868\u54CD\u5E94\u5185\u7684 adList \u4ECD\u4F1A\u6309\u7F51\u9875\u903B\u8F91\u5408\u5E76\u5230\u540C\u6761\u8BB0\u5F55\u3002",
9514
+ false
9515
+ ).option(
9469
9516
  "--unicode",
9470
9517
  "\u4F7F\u7528 Unicode \u7EBF\u6846\u8868\u683C\uFF08cli-table3\uFF09\uFF1B\u9ED8\u8BA4 ASCII +-|",
9471
9518
  false
@@ -9482,6 +9529,7 @@ program.command("list-accounts").description("\u67E5\u8BE2\u5E7F\u544A\u8D26\u62
9482
9529
  page: opts.page,
9483
9530
  pageSize: opts.pageSize,
9484
9531
  json: opts.json,
9532
+ quick: opts.quick,
9485
9533
  unicode: opts.unicode,
9486
9534
  verbose: opts.verbose
9487
9535
  });
@@ -10626,14 +10674,17 @@ accountCmd.command("email-auth").description(
10626
10674
  verbose: opts.verbose
10627
10675
  });
10628
10676
  });
10629
- accountCmd.command("email-deauth").description("Google\uFF1A\u89E3\u9664\u90AE\u7BB1\u6388\u6743\uFF08\u64A4\u9500\u5DF2\u53D1\u51FA\u7684\u6388\u6743\u9080\u8BF7\uFF09").requiredOption("-c, --customer-id <id>", "Google \u5E7F\u544A\u8D26\u6237 mediaCustomerId").requiredOption("--invitation-id <id>", "\u9080\u8BF7 ID\uFF08\u6765\u81EA account email-auth-list\uFF09").requiredOption("--agent-type <type>", "\u8D26\u6237\u4EE3\u7406\u7C7B\u578B").requiredOption("--resource-name <name>", "\u8D44\u6E90\u540D\u79F0\uFF08\u6765\u81EA account email-auth-list --json \u7684 resourceName \u5B57\u6BB5\uFF09").option("--pending", "\u9080\u8BF7\u5C1A\u672A\u88AB\u63A5\u53D7\uFF08\u5F85\u63A5\u53D7\u72B6\u6001\uFF09\uFF0C\u52A0\u6B64\u53C2\u6570\u4F7F\u7528\u4E0D\u540C\u89E3\u9664\u63A5\u53E3", false).option("-t, --token <token>", "Auth Token").option("--json", "\u8F93\u51FA\u539F\u59CB JSON", false).option("--verbose", "\u8BE6\u7EC6\u9519\u8BEF\u4FE1\u606F", false).action(async (opts) => {
10677
+ accountCmd.command("email-deauth").description("Google\uFF1A\u89E3\u9664\u90AE\u7BB1\u6388\u6743\uFF08\u64A4\u9500\u5DF2\u53D1\u51FA\u7684\u6388\u6743\u9080\u8BF7\uFF09").requiredOption("-c, --customer-id <id>", "Google \u5E7F\u544A\u8D26\u6237 mediaCustomerId").requiredOption("--invitation-id <id>", "\u9080\u8BF7 ID\uFF08\u6765\u81EA account email-auth-list\uFF09").requiredOption("--agent-type <type>", "\u8D26\u6237\u4EE3\u7406\u7C7B\u578B").requiredOption("--resource-name <name>", "\u8D44\u6E90\u540D\u79F0\uFF08\u6765\u81EA account email-auth-list --json \u7684 resourceName \u5B57\u6BB5\uFF09").option(
10678
+ "--pending",
10679
+ "\u9080\u8BF7\u4E3A\u5F85\u63A5\u53D7\uFF08Pending\uFF09\u65F6\u5FC5\u52A0\uFF1A\u8D70 RemoveCustomerUserAccessInvitation\uFF1B\u5DF2\u63A5\u53D7\uFF08Invited\uFF09\u65F6\u4E0D\u8981\u52A0",
10680
+ false
10681
+ ).option("-t, --token <token>", "Auth Token").option("--json", "\u8F93\u51FA\u539F\u59CB JSON", false).option("--verbose", "\u8BE6\u7EC6\u9519\u8BEF\u4FE1\u606F", false).action(async (opts) => {
10630
10682
  await runAccountEmailDeauth({
10631
10683
  token: opts.token,
10632
10684
  customerId: opts.customerId,
10633
10685
  invitationId: opts.invitationId,
10634
10686
  agentType: opts.agentType,
10635
10687
  resourceName: opts.resourceName,
10636
- // --pending 表示邀请待接受,accepted 为 false;否则默认已接受(accepted=true)
10637
10688
  accepted: !opts.pending,
10638
10689
  json: opts.json,
10639
10690
  verbose: opts.verbose
@@ -73,6 +73,7 @@ description: >-
73
73
  | TSO 首页(网页) | `config show` 取 `webUrl` → `{webUrl}/v3/foreign_trade/tso/home` |
74
74
  | 查广告主组(TikTok 等取 magKey) | `siluzan-tso open-account list-groups` |
75
75
  | Google 开户(脚本) | `siluzan-tso open-account google --company "…" --promotion-link "…" --promotion-type b2c ...`(**无需 magKey**) |
76
+
76
77
  | Google 开户时区列表 | `siluzan-tso open-account google-timezones`(可加 `--keyword`) |
77
78
  | TikTok 开户时区列表 | `siluzan-tso open-account tiktok-timezones`(可加 `--keyword`) |
78
79
  | TikTok 行业列表 | `siluzan-tso open-account tiktok-industries`(两级结构,传叶子节点 ID) |
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "slug": "siluzan-tso",
3
- "version": "1.0.0-beta.31",
4
- "publishedAt": 1774509377471
3
+ "version": "1.0.0-beta.33",
4
+ "publishedAt": 1774518784168
5
5
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "siluzan-tso-cli",
3
- "version": "1.0.0-beta.31",
3
+ "version": "1.0.0-beta.33",
4
4
  "description": "Siluzan 广告账户管理 CLI — 查询账户、余额、消耗数据,管理绑定关系与充值。",
5
5
  "type": "module",
6
6
  "bin": {