siluzan-tso-cli 1.0.0-beta.32 → 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.32),供内部测试使用。正式发布后安装命令将改为 `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
 
@@ -804,15 +804,13 @@ function findDpByUrl(nodes, targetUrl) {
804
804
  }
805
805
  async function fetchDataPermission(mainApiUrl, auth) {
806
806
  const url = `${mainApiUrl}/command/menu/GetUserPermissions`;
807
- const authHeaders = auth.apiKey ? { "x-api-key": auth.apiKey } : { Authorization: `Bearer ${auth.authToken}` };
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
+ };
808
812
  try {
809
- const res = await fetch(url, {
810
- headers: {
811
- "Content-Type": "application/json",
812
- "Accept-Language": "zh-CN",
813
- ...authHeaders
814
- }
815
- });
813
+ const res = await fetch(url, { headers });
816
814
  if (!res.ok) return "";
817
815
  const json = await res.json();
818
816
  const dp = findDpByUrl(json.data ?? [], TSO_KNOWN_ROUTE);
@@ -821,6 +819,17 @@ async function fetchDataPermission(mainApiUrl, auth) {
821
819
  return "";
822
820
  }
823
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
+ }
824
833
  function loadConfig(tokenArg) {
825
834
  const shared = readSharedConfig();
826
835
  const apiKey = process.env.SILUZAN_API_KEY ?? (shared.apiKey ? shared.apiKey : void 0);
@@ -2821,9 +2830,9 @@ async function runOneSection(def, opts) {
2821
2830
  if (def.audienceFilterOption && opts.audienceType) {
2822
2831
  extras.audienceTypeFilter = opts.audienceType;
2823
2832
  }
2824
- const path11 = def.path(id);
2833
+ const path10 = def.path(id);
2825
2834
  const query = buildSearchParams(def, opts.start, opts.end, extras);
2826
- const fullPath = `${path11}${query}`;
2835
+ const fullPath = `${path10}${query}`;
2827
2836
  try {
2828
2837
  if (def.name === "materials") {
2829
2838
  const { startDate, endDate } = resolveDateRange(opts.start, opts.end);
@@ -3738,23 +3747,6 @@ async function runTransferList(opts) {
3738
3747
  }
3739
3748
 
3740
3749
  // src/commands/invoice.ts
3741
- import * as fs7 from "fs";
3742
- import * as path7 from "path";
3743
- import * as os6 from "os";
3744
- async function ensureDataPermission(config) {
3745
- if (config.dataPermission) return config;
3746
- if (!config.mainApiUrl) return config;
3747
- const dp = await fetchDataPermission(config.mainApiUrl, config);
3748
- if (!dp) return config;
3749
- const configPath = path7.join(os6.homedir(), ".siluzan", "config.json");
3750
- try {
3751
- const raw = fs7.existsSync(configPath) ? JSON.parse(fs7.readFileSync(configPath, "utf8")) : {};
3752
- raw.dataPermission = dp;
3753
- fs7.writeFileSync(configPath, JSON.stringify(raw, null, 2), "utf8");
3754
- } catch {
3755
- }
3756
- return { ...config, dataPermission: dp };
3757
- }
3758
3750
  function formatDate(d) {
3759
3751
  return d.toISOString().slice(0, 10);
3760
3752
  }
@@ -5472,8 +5464,8 @@ async function runOptimizeChildren(opts) {
5472
5464
  }
5473
5465
 
5474
5466
  // src/commands/forewarning.ts
5475
- import os7 from "os";
5476
- import path8 from "path";
5467
+ import os6 from "os";
5468
+ import path7 from "path";
5477
5469
  import QRCode from "qrcode";
5478
5470
  import open from "open";
5479
5471
  var VALID_MEDIA_TYPES7 = ["Google", "TikTok"];
@@ -5681,7 +5673,7 @@ async function runForewarningNotifyAccounts(opts) {
5681
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");
5682
5674
  if (qrLink) {
5683
5675
  try {
5684
- const imgPath = path8.join(os7.tmpdir(), "siluzan-wechat-qr.png");
5676
+ const imgPath = path7.join(os6.tmpdir(), "siluzan-wechat-qr.png");
5685
5677
  await QRCode.toFile(imgPath, qrLink, { width: 300 });
5686
5678
  await open(imgPath);
5687
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
@@ -8127,7 +8119,7 @@ function printEmailDeauthHintToStderr() {
8127
8119
  );
8128
8120
  }
8129
8121
  async function runAccountEmailAuthList(opts) {
8130
- const config = loadConfig(opts.token);
8122
+ const config = await ensureDataPermission(loadConfig(opts.token));
8131
8123
  let items;
8132
8124
  try {
8133
8125
  items = await fetchCustomerUserAccessInvitationList(
@@ -8174,7 +8166,7 @@ async function runAccountEmailAuthList(opts) {
8174
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");
8175
8167
  }
8176
8168
  async function runAccountEmailAuth(opts) {
8177
- const config = loadConfig(opts.token);
8169
+ const config = await ensureDataPermission(loadConfig(opts.token));
8178
8170
  const base = googleGatewayBase(config);
8179
8171
  const url = `${base}/command/media-account/MutateCustomerUserAccessInvitation`;
8180
8172
  const body = {
@@ -8205,7 +8197,16 @@ async function runAccountEmailAuth(opts) {
8205
8197
  }
8206
8198
  let result;
8207
8199
  try {
8208
- 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
+ );
8209
8210
  } catch (err) {
8210
8211
  console.error(`
8211
8212
  \u274C \u90AE\u7BB1\u6388\u6743\u5931\u8D25\uFF1A${err instanceof Error ? err.message : String(err)}
@@ -8237,27 +8238,53 @@ async function runAccountEmailAuth(opts) {
8237
8238
  console.log(JSON.stringify(result, null, 2));
8238
8239
  return;
8239
8240
  }
8241
+ const tail = typeof result === "string" && result.trim() ? `
8242
+ \u63A5\u53E3\u8FD4\u56DE\uFF1A${result.trim()}` : "";
8240
8243
  console.log(
8241
8244
  `
8242
- \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}
8243
8246
  `
8244
8247
  );
8245
8248
  }
8246
8249
  async function runAccountEmailDeauth(opts) {
8247
- const config = loadConfig(opts.token);
8250
+ const config = await ensureDataPermission(loadConfig(opts.token));
8248
8251
  const base = googleGatewayBase(config);
8249
8252
  const endpoint = opts.accepted !== false ? "RemoveCustomerUserAccess" : "RemoveCustomerUserAccessInvitation";
8250
8253
  const url = `${base}/command/media-account/${endpoint}`;
8254
+ const resourceName = opts.resourceName?.trim() || `customers/${opts.customerId}/customerUserAccessInvitations/${opts.invitationId}`;
8251
8255
  const body = {
8252
8256
  CustomerId: opts.customerId,
8253
8257
  // 接口字段为 invitationld(小写 L),非 invitationId,与前端保持一致
8254
8258
  invitationld: opts.invitationId,
8255
8259
  AgentType: opts.agentType,
8256
- 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"))
8257
8270
  };
8258
8271
  let result;
8259
8272
  try {
8260
- 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
+ }
8261
8288
  } catch (err) {
8262
8289
  console.error(`
8263
8290
  \u274C \u89E3\u9664\u90AE\u7BB1\u6388\u6743\u5931\u8D25\uFF1A${err instanceof Error ? err.message : String(err)}
@@ -8268,8 +8295,10 @@ async function runAccountEmailDeauth(opts) {
8268
8295
  console.log(JSON.stringify(result, null, 2));
8269
8296
  return;
8270
8297
  }
8298
+ const tail = typeof result === "string" && result.trim() ? `
8299
+ \u63A5\u53E3\u8FD4\u56DE\uFF1A${result.trim()}` : "";
8271
8300
  console.log(`
8272
- \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}
8273
8302
  `);
8274
8303
  }
8275
8304
  async function runAccountBmBind(opts) {
@@ -8304,8 +8333,8 @@ async function runAccountBmBind(opts) {
8304
8333
  }
8305
8334
 
8306
8335
  // src/commands/open-account.ts
8307
- import * as fs8 from "fs";
8308
- import * as path9 from "path";
8336
+ import * as fs7 from "fs";
8337
+ import * as path8 from "path";
8309
8338
  import * as readline from "readline/promises";
8310
8339
  import { stdin as stdinStream, stdout as stdoutStream } from "process";
8311
8340
  async function runListAdvertiserGroups(opts) {
@@ -8553,8 +8582,8 @@ async function runOpenAccountYandex(opts) {
8553
8582
  }
8554
8583
  }
8555
8584
  async function uploadAttachment(filePath, apiBaseUrl, config, verbose) {
8556
- const fileName = path9.basename(filePath);
8557
- const fileBuffer = fs8.readFileSync(filePath);
8585
+ const fileName = path8.basename(filePath);
8586
+ const fileBuffer = fs7.readFileSync(filePath);
8558
8587
  const mimeType = guessContentType(fileName);
8559
8588
  const form = new FormData();
8560
8589
  form.append("file", new Blob([fileBuffer], { type: mimeType }), fileName);
@@ -8581,7 +8610,7 @@ async function uploadAttachment(filePath, apiBaseUrl, config, verbose) {
8581
8610
  return { id: data.id, fileName, storageProvider: data.storageProvider ?? "StorageAccount" };
8582
8611
  }
8583
8612
  function guessContentType(fileName) {
8584
- const ext = path9.extname(fileName).toLowerCase();
8613
+ const ext = path8.extname(fileName).toLowerCase();
8585
8614
  const map = {
8586
8615
  ".jpg": "image/jpeg",
8587
8616
  ".jpeg": "image/jpeg",
@@ -8594,7 +8623,7 @@ function guessContentType(fileName) {
8594
8623
  }
8595
8624
  async function runOpenAccountBing(opts) {
8596
8625
  const config = loadConfig(opts.token);
8597
- if (!fs8.existsSync(opts.licenseFile)) {
8626
+ if (!fs7.existsSync(opts.licenseFile)) {
8598
8627
  console.error(`
8599
8628
  \u274C \u8425\u4E1A\u6267\u7167\u6587\u4EF6\u4E0D\u5B58\u5728\uFF1A${opts.licenseFile}
8600
8629
  `);
@@ -8675,9 +8704,9 @@ async function runOpenAccountBing(opts) {
8675
8704
  }
8676
8705
  }
8677
8706
  async function uploadToKwai(filePath, apiBaseUrl, config, verbose) {
8678
- const ext = path9.extname(filePath).toLowerCase().replace(".", "").replace("jpg", "jpeg");
8707
+ const ext = path8.extname(filePath).toLowerCase().replace(".", "").replace("jpg", "jpeg");
8679
8708
  const imageType = ext || "jpeg";
8680
- const fileBuffer = fs8.readFileSync(filePath);
8709
+ const fileBuffer = fs7.readFileSync(filePath);
8681
8710
  const base64Image = fileBuffer.toString("base64");
8682
8711
  const res = await apiFetch2(
8683
8712
  `${apiBaseUrl}/KwaiAccount/Management/Upload`,
@@ -8696,7 +8725,7 @@ async function uploadToKwai(filePath, apiBaseUrl, config, verbose) {
8696
8725
  }
8697
8726
  async function runOpenAccountKwai(opts) {
8698
8727
  const config = loadConfig(opts.token);
8699
- if (!fs8.existsSync(opts.licenseFile)) {
8728
+ if (!fs7.existsSync(opts.licenseFile)) {
8700
8729
  console.error(`
8701
8730
  \u274C \u8425\u4E1A\u6267\u7167\u6587\u4EF6\u4E0D\u5B58\u5728\uFF1A${opts.licenseFile}
8702
8731
  `);
@@ -9019,8 +9048,8 @@ async function runOpenAccountGoogle(opts) {
9019
9048
  }
9020
9049
  }
9021
9050
  async function uploadLicenseToTikTok(filePath, businessCentreType, config, verbose) {
9022
- const fileName = path9.basename(filePath);
9023
- const fileBuffer = fs8.readFileSync(filePath);
9051
+ const fileName = path8.basename(filePath);
9052
+ const fileBuffer = fs7.readFileSync(filePath);
9024
9053
  const base64Image = fileBuffer.toString("base64");
9025
9054
  const res = await apiFetch2(
9026
9055
  `${config.apiBaseUrl}/command/media-account/tiktok/Upload`,
@@ -9045,7 +9074,7 @@ async function uploadLicenseToTikTok(filePath, businessCentreType, config, verbo
9045
9074
  async function runOpenAccountTikTok(opts) {
9046
9075
  const config = loadConfig(opts.token);
9047
9076
  const bcType = opts.businessCentreType ?? "Shop";
9048
- if (!fs8.existsSync(opts.licenseFile)) {
9077
+ if (!fs7.existsSync(opts.licenseFile)) {
9049
9078
  console.error(`
9050
9079
  \u274C \u8425\u4E1A\u6267\u7167\u6587\u4EF6\u4E0D\u5B58\u5728\uFF1A${opts.licenseFile}
9051
9080
  `);
@@ -9420,9 +9449,9 @@ async function runLogin(opts = {}) {
9420
9449
  // src/index.ts
9421
9450
  function getVersion() {
9422
9451
  try {
9423
- const __dirname2 = path10.dirname(fileURLToPath3(import.meta.url));
9424
- const pkgPath = path10.join(__dirname2, "..", "package.json");
9425
- 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"));
9426
9455
  return pkg.version ?? "0.0.0";
9427
9456
  } catch {
9428
9457
  return "0.0.0";
@@ -10645,14 +10674,17 @@ accountCmd.command("email-auth").description(
10645
10674
  verbose: opts.verbose
10646
10675
  });
10647
10676
  });
10648
- 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) => {
10649
10682
  await runAccountEmailDeauth({
10650
10683
  token: opts.token,
10651
10684
  customerId: opts.customerId,
10652
10685
  invitationId: opts.invitationId,
10653
10686
  agentType: opts.agentType,
10654
10687
  resourceName: opts.resourceName,
10655
- // --pending 表示邀请待接受,accepted 为 false;否则默认已接受(accepted=true)
10656
10688
  accepted: !opts.pending,
10657
10689
  json: opts.json,
10658
10690
  verbose: opts.verbose
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "slug": "siluzan-tso",
3
- "version": "1.0.0-beta.32",
4
- "publishedAt": 1774516818975
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.32",
3
+ "version": "1.0.0-beta.33",
4
4
  "description": "Siluzan 广告账户管理 CLI — 查询账户、余额、消耗数据,管理绑定关系与充值。",
5
5
  "type": "module",
6
6
  "bin": {