siluzan-tso-cli 1.1.57 → 1.1.58-beta.2

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/dist/index.js CHANGED
@@ -4049,7 +4049,7 @@ var DEFAULT_API_BASE;
4049
4049
  var init_defaults = __esm({
4050
4050
  "src/config/defaults.ts"() {
4051
4051
  "use strict";
4052
- DEFAULT_API_BASE = "https://tso-api.siluzan.com";
4052
+ DEFAULT_API_BASE = "https://tso-api-ci.siluzan.com";
4053
4053
  }
4054
4054
  });
4055
4055
 
@@ -104889,18 +104889,68 @@ async function writeProgress(paths, progress) {
104889
104889
  function readProgress(paths) {
104890
104890
  return readJsonIfExists(paths.progressFile);
104891
104891
  }
104892
- async function appendTaskLog(paths, entry) {
104892
+ function clampTaskLogEntry(entry) {
104893
+ const message = entry.lastError;
104894
+ if (!message || message.length <= MAX_TASK_LOG_ERROR_CHARS) return entry;
104895
+ return {
104896
+ ...entry,
104897
+ lastError: `${message.slice(0, MAX_TASK_LOG_ERROR_CHARS)}\u2026(truncated)`
104898
+ };
104899
+ }
104900
+ function isTaskLogEntry(value) {
104901
+ if (!value || typeof value !== "object") return false;
104902
+ const row = value;
104903
+ return typeof row.at === "string" && typeof row.id === "string" && typeof row.accountId === "string" && typeof row.section === "string" && typeof row.state === "string" && TASK_LOG_STATES.has(row.state) && typeof row.attempts === "number";
104904
+ }
104905
+ async function writeTaskLogLine(paths, entry) {
104893
104906
  await fs31.mkdir(paths.stateDir, { recursive: true });
104894
- await fs31.appendFile(paths.tasksLogFile, JSON.stringify(entry) + "\n", "utf8");
104907
+ await fs31.appendFile(paths.tasksLogFile, JSON.stringify(clampTaskLogEntry(entry)) + "\n", "utf8");
104908
+ }
104909
+ async function appendTaskLog(paths, entry) {
104910
+ const file = paths.tasksLogFile;
104911
+ const prev = taskLogAppendQueue.get(file) ?? Promise.resolve();
104912
+ const current = prev.then(() => writeTaskLogLine(paths, entry));
104913
+ taskLogAppendQueue.set(
104914
+ file,
104915
+ current.then(
104916
+ () => void 0,
104917
+ () => void 0
104918
+ )
104919
+ );
104920
+ await current;
104895
104921
  }
104896
104922
  async function readTaskLog(paths) {
104923
+ let raw;
104897
104924
  try {
104898
- const raw = await fs31.readFile(paths.tasksLogFile, "utf8");
104899
- return raw.split("\n").filter((s) => s.trim() !== "").map((line) => JSON.parse(line));
104925
+ raw = await fs31.readFile(paths.tasksLogFile, "utf8");
104900
104926
  } catch (e) {
104901
104927
  if (e.code === "ENOENT") return [];
104902
104928
  throw e;
104903
104929
  }
104930
+ const entries = [];
104931
+ let skipped = 0;
104932
+ for (const line of raw.split("\n")) {
104933
+ const text2 = line.trim();
104934
+ if (!text2) continue;
104935
+ try {
104936
+ const parsed = JSON.parse(text2);
104937
+ if (!isTaskLogEntry(parsed)) {
104938
+ skipped += 1;
104939
+ continue;
104940
+ }
104941
+ entries.push(parsed);
104942
+ } catch {
104943
+ skipped += 1;
104944
+ }
104945
+ }
104946
+ if (skipped > 0) {
104947
+ process.stderr.write(
104948
+ `
104949
+ \u26A0\uFE0F tasks.jsonl \u6709 ${skipped} \u884C\u65E0\u6CD5\u89E3\u6790\uFF0C\u5DF2\u8DF3\u8FC7\u3002\u6CA1\u6709\u5B8C\u6574\u6210\u529F\u8BB0\u5F55\u7684\u4EFB\u52A1\u4F1A\u5728 resume \u65F6\u91CD\u8DD1\u3002
104950
+ `
104951
+ );
104952
+ }
104953
+ return entries;
104904
104954
  }
104905
104955
  function replayTaskStates(entries) {
104906
104956
  const map = /* @__PURE__ */ new Map();
@@ -104964,11 +105014,21 @@ async function tryAcquireLock(paths) {
104964
105014
  async function releaseLock(paths) {
104965
105015
  await fs31.rm(paths.lockFile, { force: true }).catch(() => void 0);
104966
105016
  }
104967
- var BATCH_SCHEMA_VERSION;
105017
+ var BATCH_SCHEMA_VERSION, MAX_TASK_LOG_ERROR_CHARS, TASK_LOG_STATES, taskLogAppendQueue;
104968
105018
  var init_batch_manifest = __esm({
104969
105019
  "src/utils/batch-manifest.ts"() {
104970
105020
  "use strict";
104971
105021
  BATCH_SCHEMA_VERSION = 1;
105022
+ MAX_TASK_LOG_ERROR_CHARS = 500;
105023
+ TASK_LOG_STATES = /* @__PURE__ */ new Set([
105024
+ "pending",
105025
+ "running",
105026
+ "success",
105027
+ "failed_retryable",
105028
+ "failed_permanent",
105029
+ "skipped"
105030
+ ]);
105031
+ taskLogAppendQueue = /* @__PURE__ */ new Map();
104972
105032
  }
104973
105033
  });
104974
105034
 
@@ -113899,8 +113959,68 @@ init_cli_json_snapshot();
113899
113959
  init_strip_legacy_google_fields();
113900
113960
  init_cli_table();
113901
113961
 
113962
+ // src/commands/ad/search-field-patch.ts
113963
+ function buildSearchFieldPatch(pairs) {
113964
+ const updateMask = [];
113965
+ const fields = {};
113966
+ for (const [name2, value] of pairs) {
113967
+ updateMask.push(name2);
113968
+ fields[name2] = value;
113969
+ }
113970
+ return { updateMask, fields };
113971
+ }
113972
+ function campaignEditPatchPairs(input) {
113973
+ const pairs = [];
113974
+ if (input.name !== void 0) pairs.push(["name", input.name]);
113975
+ if (input.budgetCents !== void 0) pairs.push(["budgetAmount", input.budgetCents]);
113976
+ if (input.biddingStrategyTypeV2 !== void 0) {
113977
+ pairs.push(["biddingStrategyTypeV2", input.biddingStrategyTypeV2]);
113978
+ }
113979
+ if (input.targetSpendBidCeilingCents !== void 0) {
113980
+ pairs.push(["targetSpend_BidCeilingAmount", input.targetSpendBidCeilingCents]);
113981
+ }
113982
+ if (input.targetCpaCents !== void 0) {
113983
+ pairs.push(["targetCpa_BidingAmount", input.targetCpaCents]);
113984
+ }
113985
+ if (input.targetRoas !== void 0) pairs.push(["targetRoas", input.targetRoas]);
113986
+ if (input.manualCpcEnhanced !== void 0) {
113987
+ pairs.push(["manualCpc_EnhancedCpcEnabled", input.manualCpcEnhanced]);
113988
+ }
113989
+ return pairs;
113990
+ }
113991
+ function campaignStatusPatchPairs(status) {
113992
+ return [["status", status]];
113993
+ }
113994
+ function adGroupEditPatchPairs(input) {
113995
+ const pairs = [];
113996
+ if (input.name !== void 0) pairs.push(["name", input.name]);
113997
+ if (input.maxCpcCents !== void 0) pairs.push(["maxCpc", input.maxCpcCents]);
113998
+ if (input.targetCpaCents !== void 0) pairs.push(["targetCpa", input.targetCpaCents]);
113999
+ return pairs;
114000
+ }
114001
+ function adGroupStatusPatchPairs(status) {
114002
+ return [["status", status]];
114003
+ }
114004
+ function keywordFieldPatchPairs(input) {
114005
+ const pairs = [];
114006
+ if (input.status !== void 0) pairs.push(["userStatus", input.status]);
114007
+ if (input.maxCpcCents !== void 0) pairs.push(["maxCpc", input.maxCpcCents]);
114008
+ if (input.finalUrl !== void 0) pairs.push(["finalUrl", input.finalUrl]);
114009
+ return pairs;
114010
+ }
114011
+ function adEditPatchPairs(input) {
114012
+ const pairs = [];
114013
+ if (input.status !== void 0) pairs.push(["status", input.status]);
114014
+ if (input.finalUrl !== void 0) pairs.push(["finalUrl", input.finalUrl]);
114015
+ if (input.headlines !== void 0) pairs.push(["headlines", [...input.headlines]]);
114016
+ if (input.descriptions !== void 0) pairs.push(["descriptions", [...input.descriptions]]);
114017
+ if (input.path1 !== void 0) pairs.push(["path1", input.path1]);
114018
+ if (input.path2 !== void 0) pairs.push(["path2", input.path2]);
114019
+ return pairs;
114020
+ }
114021
+
113902
114022
  // src/commands/ad/write-verification.ts
113903
- var CAMPAIGN_WRITE_SCOPE = "gateway-full-put";
114023
+ var CAMPAIGN_WRITE_SCOPE = "search-field-patch";
113904
114024
  function sameWriteValue(expected, actual) {
113905
114025
  if (expected === actual) return true;
113906
114026
  if (typeof expected === "string" && typeof actual === "string") {
@@ -114537,71 +114657,91 @@ async function runAdKeywordEdit(opts) {
114537
114657
  );
114538
114658
  process.exit(1);
114539
114659
  }
114660
+ const patchPairs = keywordFieldPatchPairs({
114661
+ status: opts.status,
114662
+ maxCpcCents: opts.maxCpc !== void 0 ? toCentAmount(opts.maxCpc) : void 0,
114663
+ finalUrl: opts.finalUrl
114664
+ });
114665
+ const replacesText = opts.text !== void 0 || opts.matchType !== void 0;
114540
114666
  const params = new URLSearchParams();
114541
114667
  params.set("startDate", toGoogleDate(opts.startDate, -30));
114542
114668
  params.set("endDate", toGoogleDate(opts.endDate, 0));
114543
114669
  const listUrl = `${googleApiUrl}/keywordmanagement/v2/list/${opts.account}?${params}`;
114544
- let keyword;
114545
- try {
114546
- keyword = await findItemInList(listUrl, config, opts.id, opts.verbose);
114547
- } catch (err) {
114548
- console.error(`
114549
- \u274C \u67E5\u8BE2\u5173\u952E\u8BCD\u5931\u8D25\uFF1A${err instanceof Error ? err.message : String(err)}
114550
- `);
114551
- process.exit(1);
114552
- }
114553
- const body = { ...keyword };
114554
- if (opts.matchType !== void 0) {
114555
- const base = opts.text !== void 0 ? opts.text : firstKeywordTextFromRecord(keyword);
114556
- if (!String(base).trim()) {
114557
- console.error("\n\u274C \u65E0\u6CD5\u89E3\u6790\u5F53\u524D\u5173\u952E\u8BCD\u6587\u6848\uFF0C\u8BF7\u540C\u65F6\u4F20 --text <\u8BCD\u5E72>\n");
114558
- process.exit(1);
114559
- }
114560
- body["keywordText"] = [formatKeywordTextForMatchType(base, opts.matchType)];
114561
- body["matchTypeV2"] = opts.matchType;
114562
- } else if (opts.text !== void 0) {
114563
- body["keywordText"] = [opts.text];
114564
- }
114565
- if (opts.maxCpc !== void 0) body["maxCPC"] = toCentAmount(opts.maxCpc);
114566
- if (opts.finalUrl !== void 0) body["finalURL"] = opts.finalUrl;
114567
- if (opts.status !== void 0) body["userStatusV2"] = opts.status;
114568
114670
  const notAppliedHint = ` \u8BF7\u52FF\u6539\u7528\u300C\u5220\u9664\u540E\u91CD\u5EFA\u300D\u7ED5\u8FC7\uFF08\u4F1A\u4E22\u5931\u5173\u952E\u8BCD id \u4E0E\u5386\u53F2\u6570\u636E\uFF09\uFF0C\u8BF7\u53CD\u9988\u5E73\u53F0\u6392\u67E5\u3002
114569
114671
  `;
114570
- const url = `${googleApiUrl}/keywordmanagement/Keyword/${opts.account}/batch`;
114571
114672
  let currentId = opts.id;
114572
- try {
114573
- const raw = await apiFetch2(
114574
- url,
114575
- config,
114576
- { method: "PUT", body: JSON.stringify([body]) },
114577
- opts.verbose
114578
- );
114579
- const first = Array.isArray(raw) && raw.length > 0 && raw[0] && typeof raw[0] === "object" ? raw[0] : null;
114580
- const returnedId = first && typeof first["id"] === "string" ? first["id"] : void 0;
114581
- if (returnedId && returnedId !== opts.id) {
114582
- currentId = returnedId;
114583
- console.log(
114584
- `
114585
- \u2139\uFE0F \u7F51\u5173\u8FD4\u56DE\u7684\u5173\u952E\u8BCD id \u5DF2\u53D8\u66F4\u4E3A ${returnedId}\uFF08\u8BF7\u6C42\u65F6 id \u4E3A ${opts.id}\uFF0CchangeKind=replace\uFF09\uFF0C\u540E\u7EED\u67E5\u8BE2\u8BF7\u4F7F\u7528\u65B0 id\u3002
114586
- `
114673
+ if (replacesText) {
114674
+ let keyword;
114675
+ try {
114676
+ keyword = await findItemInList(
114677
+ listUrl,
114678
+ config,
114679
+ opts.id,
114680
+ opts.verbose
114587
114681
  );
114682
+ } catch (err) {
114683
+ console.error(`
114684
+ \u274C \u67E5\u8BE2\u5173\u952E\u8BCD\u5931\u8D25\uFF1A${err instanceof Error ? err.message : String(err)}
114685
+ `);
114686
+ process.exit(1);
114588
114687
  }
114589
- const mismatches = first ? findKeywordEditMismatches(body, first, opts) : [];
114590
- if (mismatches.length > 0) {
114591
- console.error(
114592
- `
114593
- \u274C \u7F51\u5173\u8FD4\u56DE\u6210\u529F\uFF0C\u4F46\u4EE5\u4E0B\u5B57\u6BB5\u672A\u751F\u6548\uFF1A
114594
- ${mismatches.map((m) => ` - ${m}`).join("\n")}
114595
- ` + notAppliedHint
114688
+ const body = { ...keyword };
114689
+ if (opts.matchType !== void 0) {
114690
+ const base = opts.text !== void 0 ? opts.text : firstKeywordTextFromRecord(keyword);
114691
+ if (!String(base).trim()) {
114692
+ console.error("\n\u274C \u65E0\u6CD5\u89E3\u6790\u5F53\u524D\u5173\u952E\u8BCD\u6587\u6848\uFF0C\u8BF7\u540C\u65F6\u4F20 --text <\u8BCD\u5E72>\n");
114693
+ process.exit(1);
114694
+ }
114695
+ body["keywordText"] = [formatKeywordTextForMatchType(base, opts.matchType)];
114696
+ body["matchTypeV2"] = opts.matchType;
114697
+ } else if (opts.text !== void 0) {
114698
+ body["keywordText"] = [opts.text];
114699
+ }
114700
+ const url = `${googleApiUrl}/keywordmanagement/Keyword/${opts.account}/batch`;
114701
+ try {
114702
+ const raw = await apiFetch2(
114703
+ url,
114704
+ config,
114705
+ { method: "PUT", body: JSON.stringify([body]) },
114706
+ opts.verbose
114596
114707
  );
114708
+ const first = Array.isArray(raw) && raw.length > 0 && raw[0] && typeof raw[0] === "object" ? raw[0] : null;
114709
+ const returnedId = first && typeof first["id"] === "string" ? first["id"] : void 0;
114710
+ if (returnedId && returnedId !== opts.id) {
114711
+ currentId = returnedId;
114712
+ console.log(
114713
+ `
114714
+ \u2139\uFE0F \u7F51\u5173\u8FD4\u56DE\u7684\u5173\u952E\u8BCD id \u5DF2\u53D8\u66F4\u4E3A ${returnedId}\uFF08\u8BF7\u6C42\u65F6 id \u4E3A ${opts.id}\uFF0CchangeKind=replace\uFF09\uFF0C\u540E\u7EED\u67E5\u8BE2\u8BF7\u4F7F\u7528\u65B0 id\u3002
114715
+ `
114716
+ );
114717
+ }
114718
+ } catch (err) {
114719
+ console.error(`
114720
+ \u274C \u7F16\u8F91\u5173\u952E\u8BCD\u5931\u8D25\uFF1A${err instanceof Error ? err.message : String(err)}
114721
+ `);
114597
114722
  process.exit(1);
114598
114723
  }
114599
- } catch (err) {
114600
- console.error(`
114724
+ }
114725
+ if (patchPairs.length > 0) {
114726
+ const patchUrl = `${googleApiUrl}/keywordmanagement/Keyword/${opts.account}/${currentId}`;
114727
+ try {
114728
+ await apiFetch2(
114729
+ patchUrl,
114730
+ config,
114731
+ { method: "PATCH", body: JSON.stringify(buildSearchFieldPatch(patchPairs)) },
114732
+ opts.verbose
114733
+ );
114734
+ } catch (err) {
114735
+ console.error(`
114601
114736
  \u274C \u7F16\u8F91\u5173\u952E\u8BCD\u5931\u8D25\uFF1A${err instanceof Error ? err.message : String(err)}
114602
114737
  `);
114603
- process.exit(1);
114738
+ process.exit(1);
114739
+ }
114604
114740
  }
114741
+ const readbackExpected = {
114742
+ finalURL: opts.finalUrl,
114743
+ maxCPC: opts.maxCpc !== void 0 ? toCentAmount(opts.maxCpc) : void 0
114744
+ };
114605
114745
  if (opts.finalUrl !== void 0 || opts.maxCpc !== void 0 || opts.status !== void 0) {
114606
114746
  let fresh;
114607
114747
  try {
@@ -114620,7 +114760,7 @@ ${mismatches.map((m) => ` - ${m}`).join("\n")}
114620
114760
  );
114621
114761
  process.exit(1);
114622
114762
  }
114623
- const mismatches = findKeywordEditMismatches(body, fresh, opts);
114763
+ const mismatches = findKeywordEditMismatches(readbackExpected, fresh, opts);
114624
114764
  if (mismatches.length > 0) {
114625
114765
  console.error(
114626
114766
  `
@@ -114658,26 +114798,17 @@ async function runAdKeywordStatus(opts) {
114658
114798
  opts = withResolvedAdAccount(opts);
114659
114799
  const config = await ensureDataPermission(loadConfig(opts.token));
114660
114800
  const googleApiUrl = requireGoogleApi(config);
114661
- const params = new URLSearchParams();
114662
- params.set("startDate", toGoogleDate(opts.startDate, -30));
114663
- params.set("endDate", toGoogleDate(opts.endDate, 0));
114664
- const listUrl = `${googleApiUrl}/keywordmanagement/v2/list/${opts.account}?${params}`;
114665
- let keyword;
114666
- try {
114667
- keyword = await findItemInList(listUrl, config, opts.id, opts.verbose);
114668
- } catch (err) {
114669
- console.error(`
114670
- \u274C \u67E5\u8BE2\u5173\u952E\u8BCD\u5931\u8D25\uFF1A${err instanceof Error ? err.message : String(err)}
114671
- `);
114672
- process.exit(1);
114673
- }
114674
- const body = { ...keyword, userStatusV2: opts.status };
114675
- const url = `${googleApiUrl}/keywordmanagement/Keyword/${opts.account}/batch`;
114801
+ const url = `${googleApiUrl}/keywordmanagement/Keyword/${opts.account}/${opts.id}`;
114676
114802
  try {
114677
114803
  await apiFetch2(
114678
114804
  url,
114679
114805
  config,
114680
- { method: "PUT", body: JSON.stringify([body]) },
114806
+ {
114807
+ method: "PATCH",
114808
+ body: JSON.stringify(
114809
+ buildSearchFieldPatch(keywordFieldPatchPairs({ status: opts.status }))
114810
+ )
114811
+ },
114681
114812
  opts.verbose
114682
114813
  );
114683
114814
  } catch (err) {
@@ -116331,7 +116462,7 @@ async function reportFailedCampaignPut(opts) {
116331
116462
  `);
116332
116463
  process.exit(1);
116333
116464
  }
116334
- const hint = judged.kind === "partial" ? "\u56DE\u8BFB\u9884\u7B97\u5DF2\u76F8\u5BF9\u63D0\u4EA4\u524D\u53D8\u5316\u3002\u9884\u7B97\u53EF\u80FD\u5DF2\u5199\u5165\uFF0C\u7CFB\u5217\u5176\u4F59\u66F4\u65B0\u672A\u5B8C\u6210\u3002\u4E0D\u8981\u6574\u5305\u91CD\u63D0\u3002" : "\u56DE\u8BFB\u5931\u8D25\u6216\u65E0\u6CD5\u5BF9\u6BD4\u9884\u7B97\uFF0C\u5199\u5165\u7ED3\u679C\u672A\u77E5\u3002\u4E0D\u8981\u6574\u5305\u91CD\u63D0\u3002";
116465
+ const hint = judged.kind === "partial" ? "\u56DE\u8BFB\u9884\u7B97\u5DF2\u76F8\u5BF9\u63D0\u4EA4\u524D\u53D8\u5316\u3002\u9884\u7B97\u53EF\u80FD\u5DF2\u5199\u5165\uFF0C\u5176\u4F59\u66F4\u65B0\u672A\u5B8C\u6210\u3002\u4E0D\u8981\u7ACB\u523B\u91CD\u53D1\u3002" : "\u56DE\u8BFB\u5931\u8D25\u6216\u65E0\u6CD5\u5BF9\u6BD4\u9884\u7B97\uFF0C\u5199\u5165\u7ED3\u679C\u672A\u77E5\u3002\u4E0D\u8981\u7ACB\u523B\u91CD\u53D1\u3002";
116335
116466
  await reportCampaignWrite({
116336
116467
  jsonOut: opts.jsonOut,
116337
116468
  account: opts.account,
@@ -116403,9 +116534,14 @@ async function runAdCampaignStatus(opts) {
116403
116534
  );
116404
116535
  process.exit(1);
116405
116536
  }
116406
- const body = { ...campaign, statusV2: opts.status };
116537
+ const body = buildSearchFieldPatch(campaignStatusPatchPairs(opts.status));
116407
116538
  try {
116408
- await apiFetch2(detailUrl, config, { method: "PUT", body: JSON.stringify(body) }, opts.verbose);
116539
+ await apiFetch2(
116540
+ detailUrl,
116541
+ config,
116542
+ { method: "PATCH", body: JSON.stringify(body) },
116543
+ opts.verbose
116544
+ );
116409
116545
  } catch (err) {
116410
116546
  await reportFailedCampaignPut({
116411
116547
  err,
@@ -116721,24 +116857,17 @@ async function runAdCampaignEdit(opts) {
116721
116857
  );
116722
116858
  process.exit(1);
116723
116859
  }
116724
- const body = { ...campaign };
116725
- if (opts.name !== void 0) body["name"] = opts.name;
116726
- if (opts.budget !== void 0) body["budget"] = toCentAmount(opts.budget);
116727
- if (opts.biddingStrategy !== void 0) {
116728
- body["biddingStrategyTypeV2"] = opts.biddingStrategy.toUpperCase();
116729
- }
116730
- if (opts.targetSpendBidCeiling !== void 0)
116731
- body["targetSpend_BidCeilingAmount"] = toCentAmount(opts.targetSpendBidCeiling);
116732
- if (opts.targetCpa !== void 0) body["targetCpa_BidingAmount"] = toCentAmount(opts.targetCpa);
116733
- if (opts.targetRoas !== void 0) body["targetRoas"] = opts.targetRoas;
116734
- if (opts.manualCpcEnhanced !== void 0)
116735
- body["manualCpc_EnhancedCpcEnabled"] = opts.manualCpcEnhanced;
116736
- if (opts.targetSearchNetwork !== void 0)
116737
- body["targetSearchNetwork"] = opts.targetSearchNetwork;
116738
- if (opts.targetContentNetwork !== void 0)
116739
- body["targetContentNetwork"] = opts.targetContentNetwork;
116740
- const hasChange = opts.name !== void 0 || opts.budget !== void 0 || opts.biddingStrategy !== void 0 || opts.targetSpendBidCeiling !== void 0 || opts.targetCpa !== void 0 || opts.targetRoas !== void 0 || opts.manualCpcEnhanced !== void 0 || opts.targetSearchNetwork !== void 0 || opts.targetContentNetwork !== void 0;
116741
- if (!hasChange) {
116860
+ const patchPairs = campaignEditPatchPairs({
116861
+ name: opts.name,
116862
+ budgetCents: opts.budget !== void 0 ? toCentAmount(opts.budget) : void 0,
116863
+ biddingStrategyTypeV2: opts.biddingStrategy?.toUpperCase(),
116864
+ targetSpendBidCeilingCents: opts.targetSpendBidCeiling !== void 0 ? toCentAmount(opts.targetSpendBidCeiling) : void 0,
116865
+ targetCpaCents: opts.targetCpa !== void 0 ? toCentAmount(opts.targetCpa) : void 0,
116866
+ targetRoas: opts.targetRoas,
116867
+ manualCpcEnhanced: opts.manualCpcEnhanced
116868
+ });
116869
+ const wantsNetwork = opts.targetSearchNetwork !== void 0 || opts.targetContentNetwork !== void 0;
116870
+ if (patchPairs.length === 0 && !wantsNetwork) {
116742
116871
  console.error("\n\u274C \u8BF7\u81F3\u5C11\u6307\u5B9A\u4E00\u4E2A\u4FEE\u6539\u9879\uFF08--name / --budget / --bidding / \u2026\uFF09\n");
116743
116872
  process.exit(1);
116744
116873
  }
@@ -116748,23 +116877,66 @@ async function runAdCampaignEdit(opts) {
116748
116877
  );
116749
116878
  process.exit(1);
116750
116879
  }
116751
- try {
116752
- await apiFetch2(detailUrl, config, { method: "PUT", body: JSON.stringify(body) }, opts.verbose);
116753
- } catch (err) {
116754
- await reportFailedCampaignPut({
116755
- err,
116756
- detailUrl,
116757
- config,
116758
- verbose: opts.verbose,
116759
- budgetCentsBefore: readCampaignBudgetCents(campaign),
116760
- jsonOut: opts.jsonOut,
116761
- account: opts.account,
116762
- id: opts.id,
116763
- section: "ad-campaign-edit",
116764
- commandLabel: "ad campaign-edit",
116765
- failureLabel: "\u7F16\u8F91\u5E7F\u544A\u7CFB\u5217\u5931\u8D25"
116766
- });
116767
- return;
116880
+ if (patchPairs.length > 0) {
116881
+ try {
116882
+ await apiFetch2(
116883
+ detailUrl,
116884
+ config,
116885
+ {
116886
+ method: "PATCH",
116887
+ body: JSON.stringify(buildSearchFieldPatch(patchPairs))
116888
+ },
116889
+ opts.verbose
116890
+ );
116891
+ } catch (err) {
116892
+ await reportFailedCampaignPut({
116893
+ err,
116894
+ detailUrl,
116895
+ config,
116896
+ verbose: opts.verbose,
116897
+ budgetCentsBefore: readCampaignBudgetCents(campaign),
116898
+ jsonOut: opts.jsonOut,
116899
+ account: opts.account,
116900
+ id: opts.id,
116901
+ section: "ad-campaign-edit",
116902
+ commandLabel: "ad campaign-edit",
116903
+ failureLabel: "\u7F16\u8F91\u5E7F\u544A\u7CFB\u5217\u5931\u8D25"
116904
+ });
116905
+ return;
116906
+ }
116907
+ }
116908
+ if (wantsNetwork) {
116909
+ try {
116910
+ const fresh = await fetchCampaignRecord(detailUrl, config, opts.verbose);
116911
+ const networkBody = { ...fresh };
116912
+ if (opts.targetSearchNetwork !== void 0) {
116913
+ networkBody["targetSearchNetwork"] = opts.targetSearchNetwork;
116914
+ }
116915
+ if (opts.targetContentNetwork !== void 0) {
116916
+ networkBody["targetContentNetwork"] = opts.targetContentNetwork;
116917
+ }
116918
+ await apiFetch2(
116919
+ detailUrl,
116920
+ config,
116921
+ { method: "PUT", body: JSON.stringify(networkBody) },
116922
+ opts.verbose
116923
+ );
116924
+ } catch (err) {
116925
+ await reportFailedCampaignPut({
116926
+ err,
116927
+ detailUrl,
116928
+ config,
116929
+ verbose: opts.verbose,
116930
+ budgetCentsBefore: readCampaignBudgetCents(campaign),
116931
+ jsonOut: opts.jsonOut,
116932
+ account: opts.account,
116933
+ id: opts.id,
116934
+ section: "ad-campaign-edit",
116935
+ commandLabel: "ad campaign-edit",
116936
+ failureLabel: "\u7F16\u8F91\u5E7F\u544A\u7CFB\u5217\u5931\u8D25"
116937
+ });
116938
+ return;
116939
+ }
116768
116940
  }
116769
116941
  const parts = [];
116770
116942
  if (opts.name !== void 0) parts.push(`\u540D\u79F0\u2192${opts.name}`);
@@ -116954,26 +117126,15 @@ async function runAdGroupStatus(opts) {
116954
117126
  opts = withResolvedAdAccount(opts);
116955
117127
  const config = loadConfig(opts.token);
116956
117128
  const googleApiUrl = requireGoogleApi(config);
116957
- const listUrl = adgroupListUrl(googleApiUrl, opts.account, opts.startDate, opts.endDate);
116958
- let adgroup;
116959
- try {
116960
- adgroup = await findItemInList(listUrl, config, opts.id, opts.verbose);
116961
- } catch (err) {
116962
- console.error(`
116963
- \u274C \u67E5\u8BE2\u5E7F\u544A\u7EC4\u5931\u8D25\uFF1A${err instanceof Error ? err.message : String(err)}
116964
- `);
116965
- process.exit(1);
116966
- }
116967
- const putUrl = `${googleApiUrl}/adgroupnmanagement/adgroup/${opts.account}/${opts.id}`;
116968
- const body = { ...adgroup, statusV2: opts.status };
116969
- try {
116970
- await apiFetch2(putUrl, config, { method: "PUT", body: JSON.stringify(body) }, opts.verbose);
116971
- } catch (err) {
116972
- console.error(`
116973
- \u274C \u72B6\u6001\u66F4\u65B0\u5931\u8D25\uFF1A${err instanceof Error ? err.message : String(err)}
116974
- `);
116975
- process.exit(1);
116976
- }
117129
+ await patchAdGroup(
117130
+ googleApiUrl,
117131
+ config,
117132
+ opts.account,
117133
+ opts.id,
117134
+ adGroupStatusPatchPairs(opts.status),
117135
+ opts.verbose,
117136
+ "\u72B6\u6001\u66F4\u65B0\u5931\u8D25"
117137
+ );
116977
117138
  console.log(`
116978
117139
  \u2705 \u5E7F\u544A\u7EC4 ${opts.id} \u5DF2\u8BBE\u7F6E\u4E3A ${opts.status}
116979
117140
  `);
@@ -117009,26 +117170,15 @@ async function runAdGroupRename(opts) {
117009
117170
  opts = withResolvedAdAccount(opts);
117010
117171
  const config = loadConfig(opts.token);
117011
117172
  const googleApiUrl = requireGoogleApi(config);
117012
- const listUrl = adgroupListUrl(googleApiUrl, opts.account, opts.startDate, opts.endDate);
117013
- let adgroup;
117014
- try {
117015
- adgroup = await findItemInList(listUrl, config, opts.id, opts.verbose);
117016
- } catch (err) {
117017
- console.error(`
117018
- \u274C \u67E5\u8BE2\u5E7F\u544A\u7EC4\u5931\u8D25\uFF1A${err instanceof Error ? err.message : String(err)}
117019
- `);
117020
- process.exit(1);
117021
- }
117022
- const putUrl = `${googleApiUrl}/adgroupnmanagement/adgroup/${opts.account}/${opts.id}`;
117023
- const body = { ...adgroup, name: opts.name };
117024
- try {
117025
- await apiFetch2(putUrl, config, { method: "PUT", body: JSON.stringify(body) }, opts.verbose);
117026
- } catch (err) {
117027
- console.error(`
117028
- \u274C \u6539\u540D\u5931\u8D25\uFF1A${err instanceof Error ? err.message : String(err)}
117029
- `);
117030
- process.exit(1);
117031
- }
117173
+ await patchAdGroup(
117174
+ googleApiUrl,
117175
+ config,
117176
+ opts.account,
117177
+ opts.id,
117178
+ adGroupEditPatchPairs({ name: opts.name }),
117179
+ opts.verbose,
117180
+ "\u6539\u540D\u5931\u8D25"
117181
+ );
117032
117182
  console.log(`
117033
117183
  \u2705 \u5E7F\u544A\u7EC4 ${opts.id} \u5DF2\u6539\u540D\u4E3A\u300C${opts.name}\u300D
117034
117184
  `);
@@ -117052,32 +117202,38 @@ async function runAdGroupEdit(opts) {
117052
117202
  }
117053
117203
  const config = loadConfig(opts.token);
117054
117204
  const googleApiUrl = requireGoogleApi(config);
117055
- const listUrl = adgroupListUrl(googleApiUrl, opts.account, opts.startDate, opts.endDate);
117056
- let adgroup;
117057
- try {
117058
- adgroup = await findItemInList(listUrl, config, opts.id, opts.verbose);
117059
- } catch (err) {
117060
- console.error(`
117061
- \u274C \u67E5\u8BE2\u5E7F\u544A\u7EC4\u5931\u8D25\uFF1A${err instanceof Error ? err.message : String(err)}
117205
+ await patchAdGroup(
117206
+ googleApiUrl,
117207
+ config,
117208
+ opts.account,
117209
+ opts.id,
117210
+ adGroupEditPatchPairs({
117211
+ name: hasName ? opts.name.trim() : void 0,
117212
+ maxCpcCents: hasMax ? toCentAmount(opts.maxCPCAmount) : void 0,
117213
+ targetCpaCents: hasTcpa ? toCentAmount(opts.targetCpaAmount) : void 0
117214
+ }),
117215
+ opts.verbose,
117216
+ "\u7F16\u8F91\u5E7F\u544A\u7EC4\u5931\u8D25"
117217
+ );
117218
+ console.log(`
117219
+ \u2705 \u5E7F\u544A\u7EC4 ${opts.id} \u5DF2\u66F4\u65B0
117062
117220
  `);
117063
- process.exit(1);
117064
- }
117065
- const body = { ...adgroup };
117066
- if (hasName) body["name"] = opts.name.trim();
117067
- if (hasMax) body["maxCPCAmount"] = toCentAmount(opts.maxCPCAmount);
117068
- if (hasTcpa) body["targetCpaAmount"] = toCentAmount(opts.targetCpaAmount);
117069
- const putUrl = `${googleApiUrl}/adgroupnmanagement/adgroup/${opts.account}/${opts.id}`;
117221
+ }
117222
+ async function patchAdGroup(googleApiUrl, config, account, id, pairs, verbose, failureLabel) {
117223
+ const url = `${googleApiUrl}/adgroupnmanagement/adgroup/${account}/${id}`;
117070
117224
  try {
117071
- await apiFetch2(putUrl, config, { method: "PUT", body: JSON.stringify(body) }, opts.verbose);
117225
+ await apiFetch2(
117226
+ url,
117227
+ config,
117228
+ { method: "PATCH", body: JSON.stringify(buildSearchFieldPatch(pairs)) },
117229
+ verbose
117230
+ );
117072
117231
  } catch (err) {
117073
117232
  console.error(`
117074
- \u274C \u7F16\u8F91\u5E7F\u544A\u7EC4\u5931\u8D25\uFF1A${err instanceof Error ? err.message : String(err)}
117233
+ \u274C ${failureLabel}\uFF1A${err instanceof Error ? err.message : String(err)}
117075
117234
  `);
117076
117235
  process.exit(1);
117077
117236
  }
117078
- console.log(`
117079
- \u2705 \u5E7F\u544A\u7EC4 ${opts.id} \u5DF2\u66F4\u65B0
117080
- `);
117081
117237
  }
117082
117238
 
117083
117239
  // src/commands/ad/ad-creative.ts
@@ -117304,23 +117460,17 @@ async function runAdStatus(opts) {
117304
117460
  opts = withResolvedAdAccount(opts);
117305
117461
  const config = loadConfig(opts.token);
117306
117462
  const googleApiUrl = requireGoogleApi(config);
117307
- const params = new URLSearchParams();
117308
- params.set("startDate", toGoogleDate(opts.startDate, -30));
117309
- params.set("endDate", toGoogleDate(opts.endDate, 0));
117310
- const listUrl = `${googleApiUrl}/admanagement/v2/list/${opts.account}?${params}`;
117311
- let ad;
117312
- try {
117313
- ad = await findItemInList(listUrl, config, opts.id, opts.verbose);
117314
- } catch (err) {
117315
- console.error(`
117316
- \u274C \u67E5\u8BE2\u5E7F\u544A\u5931\u8D25\uFF1A${err instanceof Error ? err.message : String(err)}
117317
- `);
117318
- process.exit(1);
117319
- }
117320
- const putUrl = `${googleApiUrl}/admanagement/campaign/${opts.account}/${opts.id}`;
117321
- const body = { ...ad, statusV2: opts.status };
117463
+ const url = `${googleApiUrl}/admanagement/campaign/${opts.account}/${opts.id}`;
117322
117464
  try {
117323
- await apiFetch2(putUrl, config, { method: "PUT", body: JSON.stringify(body) }, opts.verbose);
117465
+ await apiFetch2(
117466
+ url,
117467
+ config,
117468
+ {
117469
+ method: "PATCH",
117470
+ body: JSON.stringify(buildSearchFieldPatch(adEditPatchPairs({ status: opts.status })))
117471
+ },
117472
+ opts.verbose
117473
+ );
117324
117474
  } catch (err) {
117325
117475
  console.error(`
117326
117476
  \u274C \u72B6\u6001\u66F4\u65B0\u5931\u8D25\uFF1A${err instanceof Error ? err.message : String(err)}
@@ -117361,6 +117511,11 @@ async function runAdDelete(opts) {
117361
117511
  \u2705 \u5E7F\u544A ${opts.id} \u5DF2\u5220\u9664
117362
117512
  `);
117363
117513
  }
117514
+ function emptyPathClears(value) {
117515
+ if (value === void 0) return void 0;
117516
+ const trimmed = value.trim();
117517
+ return trimmed === "" ? null : trimmed;
117518
+ }
117364
117519
  async function runAdEdit(opts) {
117365
117520
  opts = withResolvedAdAccount(opts);
117366
117521
  const config = await ensureDataPermission(loadConfig(opts.token));
@@ -117382,40 +117537,19 @@ async function runAdEdit(opts) {
117382
117537
  console.error(formatRsaCliValidationError(rsaErrors));
117383
117538
  process.exit(1);
117384
117539
  }
117385
- const params = new URLSearchParams();
117386
- params.set("startDate", toGoogleDate(opts.startDate, -30));
117387
- params.set("endDate", toGoogleDate(opts.endDate, 0));
117388
- const listUrl = `${googleApiUrl}/admanagement/v2/list/${opts.account}?${params}`;
117389
- let ad;
117390
- try {
117391
- ad = await findItemInList(listUrl, config, opts.id, opts.verbose);
117392
- } catch (err) {
117393
- console.error(`
117394
- \u274C \u67E5\u8BE2\u5E7F\u544A\u5931\u8D25\uFF1A${err instanceof Error ? err.message : String(err)}
117395
- `);
117396
- process.exit(1);
117397
- }
117398
- const body = { ...ad };
117399
- if (opts.headlines) {
117400
- const [h1, h2, h3, ...more] = opts.headlines;
117401
- body["headlinePart1"] = h1;
117402
- body["headlinePart2"] = h2;
117403
- body["headlinePart3"] = h3;
117404
- if (more.length > 0) body["AddtionalHeadlines"] = more;
117405
- }
117406
- if (opts.descriptions) {
117407
- const [d1, d2, ...more] = opts.descriptions;
117408
- body["adDescription"] = d1;
117409
- body["adDescription2"] = d2;
117410
- if (more.length > 0) body["AddtionalAdDescriptions"] = more;
117411
- }
117412
- if (opts.finalUrl !== void 0) body["finalUrl"] = opts.finalUrl;
117413
- if (opts.path1 !== void 0) body["path1"] = opts.path1;
117414
- if (opts.path2 !== void 0) body["path2"] = opts.path2;
117415
- if (opts.status !== void 0) body["statusV2"] = opts.status;
117416
- const putUrl = `${googleApiUrl}/admanagement/campaign/${opts.account}/${opts.id}`;
117540
+ const url = `${googleApiUrl}/admanagement/campaign/${opts.account}/${opts.id}`;
117541
+ const body = buildSearchFieldPatch(
117542
+ adEditPatchPairs({
117543
+ status: opts.status,
117544
+ finalUrl: opts.finalUrl,
117545
+ headlines: opts.headlines,
117546
+ descriptions: opts.descriptions,
117547
+ path1: emptyPathClears(opts.path1),
117548
+ path2: emptyPathClears(opts.path2)
117549
+ })
117550
+ );
117417
117551
  try {
117418
- await apiFetch2(putUrl, config, { method: "PUT", body: JSON.stringify(body) }, opts.verbose);
117552
+ await apiFetch2(url, config, { method: "PATCH", body: JSON.stringify(body) }, opts.verbose);
117419
117553
  } catch (err) {
117420
117554
  console.error(`
117421
117555
  \u274C \u7F16\u8F91\u5E7F\u544A\u5931\u8D25\uFF1A${err instanceof Error ? err.message : String(err)}
@@ -124642,7 +124776,7 @@ function register21(program2) {
124642
124776
  });
124643
124777
  }
124644
124778
  );
124645
- adCmd.command("campaign-status").description("\u5207\u6362\u5E7F\u544A\u7CFB\u5217\u72B6\u6001\uFF08Enabled / Paused\uFF09").requiredOption("-a, --account <id>", "Google \u8D26\u6237 mediaCustomerId").requiredOption("--id <campaignId>", "\u5E7F\u544A\u7CFB\u5217 ID").requiredOption("--status <status>", "\u76EE\u6807\u72B6\u6001\uFF1AEnabled | Paused").option("--json-out <path>", "\u843D\u76D8\u6838\u9A8C\u7ED3\u679C\uFF08writeScope=gateway-full-put\uFF09").option("-t, --token <token>", "Auth Token").option("--verbose", "\u8BE6\u7EC6\u9519\u8BEF\u4FE1\u606F", false).action(
124779
+ adCmd.command("campaign-status").description("\u5207\u6362\u5E7F\u544A\u7CFB\u5217\u72B6\u6001\uFF08Enabled / Paused\uFF09").requiredOption("-a, --account <id>", "Google \u8D26\u6237 mediaCustomerId").requiredOption("--id <campaignId>", "\u5E7F\u544A\u7CFB\u5217 ID").requiredOption("--status <status>", "\u76EE\u6807\u72B6\u6001\uFF1AEnabled | Paused").option("--json-out <path>", "\u843D\u76D8\u6838\u9A8C\u7ED3\u679C\uFF08writeScope=search-field-patch\uFF09").option("-t, --token <token>", "Auth Token").option("--verbose", "\u8BE6\u7EC6\u9519\u8BEF\u4FE1\u606F", false).action(
124646
124780
  async (opts) => {
124647
124781
  if (opts.status !== "Enabled" && opts.status !== "Paused") {
124648
124782
  console.error("\n\u274C --status \u53EA\u63A5\u53D7 Enabled \u6216 Paused\n");
@@ -125148,7 +125282,9 @@ function register21(program2) {
125148
125282
  verbose: opts.verbose
125149
125283
  });
125150
125284
  });
125151
- adCmd.command("campaign-edit").description("\u7F16\u8F91\u5E7F\u544A\u7CFB\u5217\uFF08\u540D\u79F0/\u9884\u7B97/\u51FA\u4EF7\u7B56\u7565/\u6295\u653E\u7F51\u7EDC\uFF0C\u81F3\u5C11\u4F20\u4E00\u4E2A\u4FEE\u6539\u9879\uFF09").requiredOption("-a, --account <id>", "Google \u8D26\u6237 mediaCustomerId").requiredOption("--id <campaignId>", "\u5E7F\u544A\u7CFB\u5217 ID").option("--name <name>", "\u65B0\u540D\u79F0").option(
125285
+ adCmd.command("campaign-edit").description(
125286
+ "\u7F16\u8F91\u641C\u7D22\u5E7F\u544A\u7CFB\u5217\u3002\u540D\u79F0/\u9884\u7B97/\u51FA\u4EF7\u8D70\u5B57\u6BB5\u7EA7 PATCH\uFF1B\u6295\u653E\u7F51\u7EDC\u4ECD\u7528\u6574\u5305 PUT\u3002\u81F3\u5C11\u4F20\u4E00\u4E2A\u4FEE\u6539\u9879"
125287
+ ).requiredOption("-a, --account <id>", "Google \u8D26\u6237 mediaCustomerId").requiredOption("--id <campaignId>", "\u5E7F\u544A\u7CFB\u5217 ID").option("--name <name>", "\u65B0\u540D\u79F0").option(
125152
125288
  "--budget <amount>",
125153
125289
  "\u65B0\u9884\u7B97\uFF0C\u4E3B\u5E01\u79CD\u91D1\u989D\uFF08\u5982 100 \u8868\u793A \xA5100\uFF1B\u652F\u6301\u5C0F\u6570\uFF1BCLI \u5185\u90E8\u81EA\u52A8 \xD7100 \u5199\u5165\u300C\u5206\u300D\u5B57\u6BB5\uFF09",
125154
125290
  parseFloat
@@ -125171,7 +125307,7 @@ function register21(program2) {
125171
125307
  "--search-network <bool>",
125172
125308
  "\u6295\u653E\u5230 Google \u641C\u7D22\uFF1Atrue | false",
125173
125309
  (v) => v === "true"
125174
- ).option("--content-network <bool>", "\u6295\u653E\u5230\u5C55\u793A\u7F51\u7EDC\uFF1Atrue | false", (v) => v === "true").option("--json-out <path>", "\u843D\u76D8\u6838\u9A8C\u7ED3\u679C\uFF08writeScope=gateway-full-put\uFF09").option("-t, --token <token>", "Auth Token").option("--verbose", "\u8BE6\u7EC6\u9519\u8BEF\u4FE1\u606F", false).action(
125310
+ ).option("--content-network <bool>", "\u6295\u653E\u5230\u5C55\u793A\u7F51\u7EDC\uFF1Atrue | false", (v) => v === "true").option("--json-out <path>", "\u843D\u76D8\u6838\u9A8C\u7ED3\u679C\uFF08writeScope=search-field-patch\uFF09").option("-t, --token <token>", "Auth Token").option("--verbose", "\u8BE6\u7EC6\u9519\u8BEF\u4FE1\u606F", false).action(
125175
125311
  async (opts) => {
125176
125312
  await runAdCampaignEdit({
125177
125313
  token: opts.token,
@@ -125204,7 +125340,7 @@ function register21(program2) {
125204
125340
  });
125205
125341
  }
125206
125342
  );
125207
- adCmd.command("adgroup-edit").description("\u7F16\u8F91\u5E7F\u544A\u7EC4\uFF08\u540D\u79F0\u3001\u6700\u9AD8 CPC\u3001\u7EC4\u7EA7\u76EE\u6807 CPA\uFF1B\u81F3\u5C11\u4F20\u4E00\u9879\uFF1B\u4E0E\u7F51\u5173 PUT \u4E00\u81F4\uFF09").requiredOption("-a, --account <id>", "Google \u8D26\u6237 mediaCustomerId").requiredOption("--id <adgroupId>", "\u5E7F\u544A\u7EC4 ID").option("--name <name>", "\u65B0\u540D\u79F0").option(
125343
+ adCmd.command("adgroup-edit").description("\u7F16\u8F91\u641C\u7D22\u5E7F\u544A\u7EC4\uFF08\u540D\u79F0\u3001\u6700\u9AD8 CPC\u3001\u7EC4\u7EA7\u76EE\u6807 CPA\uFF1B\u81F3\u5C11\u4F20\u4E00\u9879\uFF1B\u5B57\u6BB5\u7EA7 PATCH\uFF09").requiredOption("-a, --account <id>", "Google \u8D26\u6237 mediaCustomerId").requiredOption("--id <adgroupId>", "\u5E7F\u544A\u7EC4 ID").option("--name <name>", "\u65B0\u540D\u79F0").option(
125208
125344
  "--max-cpc <n>",
125209
125345
  "\u6700\u9AD8 CPC\uFF0C\u4E3B\u5E01\u79CD\u91D1\u989D\uFF08\u5982 1.5 \u8868\u793A \xA51.50\uFF1BCLI \u5185\u90E8 \xD7100 \u5199\u5165\u300C\u5206\u300D\u5B57\u6BB5\uFF09",
125210
125346
  parseFloat
@@ -125228,7 +125364,7 @@ function register21(program2) {
125228
125364
  }
125229
125365
  );
125230
125366
  adCmd.command("ad-edit").description(
125231
- "\u7F16\u8F91\u81EA\u9002\u5E94\u641C\u7D22\u5E7F\u544A\uFF08RESPONSIVE_SEARCH_AD\uFF09\uFF1A\u6807\u9898/\u63CF\u8FF0/\u843D\u5730\u9875/\u8DEF\u5F84/\u72B6\u6001\uFF1B\u4E0E\u7F51\u9875 PUT admanagement/campaign \u884C\u4E3A\u4E00\u81F4"
125367
+ "\u7F16\u8F91\u81EA\u9002\u5E94\u641C\u7D22\u5E7F\u544A\uFF08RESPONSIVE_SEARCH_AD\uFF09\uFF1A\u6807\u9898/\u63CF\u8FF0/\u843D\u5730\u9875/\u8DEF\u5F84/\u72B6\u6001\uFF1B\u5B57\u6BB5\u7EA7 PATCH\uFF0C\u53EA\u5199\u672C\u6B21\u4F20\u5165\u7684\u5B57\u6BB5"
125232
125368
  ).requiredOption("-a, --account <id>", "Google \u8D26\u6237 mediaCustomerId").requiredOption("--id <adId>", "\u5E7F\u544A ID").option(
125233
125369
  "--headlines <h1,h2,h3,...>",
125234
125370
  "\u65B0\u6807\u9898\u5217\u8868\uFF0C\u9017\u53F7\u5206\u9694\uFF08\u81F3\u5C11 3 \u4E2A\uFF0C\u6700\u591A 15 \u4E2A\uFF0C\u6BCF\u4E2A \u226430 \u5B57\u7B26\uFF1B\u6620\u5C04 headlinePart1/2/3 \u4E0E AddtionalHeadlines\uFF09",
@@ -125273,7 +125409,7 @@ function register21(program2) {
125273
125409
  });
125274
125410
  }
125275
125411
  );
125276
- adCmd.command("keyword-edit").description("\u7F16\u8F91\u641C\u7D22\u5173\u952E\u8BCD\uFF08\u6570\u7EC4 body\uFF0C\u5148 list \u518D\u5408\u5E76\uFF09").requiredOption("-a, --account <id>", "Google \u8D26\u6237 mediaCustomerId").requiredOption("--id <keywordId>", "\u5173\u952E\u8BCD ID\uFF08\u6765\u81EA ad keywords --json-out \u2192 id\uFF09").option("--text <text>", "\u65B0\u5173\u952E\u8BCD\u6587\u672C\uFF08\u5199\u5165 keywordText \u6570\u7EC4\uFF09").option(
125412
+ adCmd.command("keyword-edit").description("\u7F16\u8F91\u641C\u7D22\u5173\u952E\u8BCD\u3002\u72B6\u6001/\u51FA\u4EF7/\u7F51\u5740\u8D70\u5B57\u6BB5\u7EA7 PATCH\uFF1B\u6539\u8BCD\u9762\u6216\u5339\u914D\u7C7B\u578B\u4ECD\u7528\u6279\u91CF PUT").requiredOption("-a, --account <id>", "Google \u8D26\u6237 mediaCustomerId").requiredOption("--id <keywordId>", "\u5173\u952E\u8BCD ID\uFF08\u6765\u81EA ad keywords --json-out \u2192 id\uFF09").option("--text <text>", "\u65B0\u5173\u952E\u8BCD\u6587\u672C\uFF08\u5199\u5165 keywordText \u6570\u7EC4\uFF09").option(
125277
125413
  "--match-type <type>",
125278
125414
  '\u65B0\u5339\u914D\u7C7B\u578B\uFF1ABroad | Phrase | Exact\uFF08\u5199 matchTypeV2\uFF0C\u5E76\u9ED8\u8BA4\u540C\u6B65\u6539\u5199 keywordText \u4E3A\u8BCD\u5E72/"\u8BCD"/[\u8BCD] \u4EE5\u7B26\u5408\u7F51\u5173\u63A8\u65AD\uFF09'
125279
125415
  ).option(
@@ -125312,7 +125448,7 @@ function register21(program2) {
125312
125448
  });
125313
125449
  }
125314
125450
  );
125315
- adCmd.command("keyword-status").description("\u5207\u6362\u641C\u7D22\u5173\u952E\u8BCD\u72B6\u6001\uFF08Enabled / Paused\uFF0C\u5199\u5165 userStatusV2\uFF09").requiredOption("-a, --account <id>", "Google \u8D26\u6237 mediaCustomerId").requiredOption("--id <keywordId>", "\u5173\u952E\u8BCD ID\uFF08\u6765\u81EA ad keywords --json-out \u2192 id\uFF09").requiredOption("--status <status>", "\u76EE\u6807\u72B6\u6001\uFF1AEnabled | Paused").option("--start <date>", "\u5217\u8868\u67E5\u8BE2\u8D77\u59CB\u65E5\u671F YYYY-MM-DD").option("--end <date>", "\u5217\u8868\u67E5\u8BE2\u7ED3\u675F\u65E5\u671F YYYY-MM-DD").option("-t, --token <token>", "Auth Token").option("--verbose", "\u8BE6\u7EC6\u9519\u8BEF\u4FE1\u606F", false).action(
125451
+ adCmd.command("keyword-status").description("\u5207\u6362\u641C\u7D22\u5173\u952E\u8BCD\u72B6\u6001\uFF08Enabled / Paused\uFF0C\u5B57\u6BB5\u7EA7 PATCH userStatus\uFF09").requiredOption("-a, --account <id>", "Google \u8D26\u6237 mediaCustomerId").requiredOption("--id <keywordId>", "\u5173\u952E\u8BCD ID\uFF08\u6765\u81EA ad keywords --json-out \u2192 id\uFF09").requiredOption("--status <status>", "\u76EE\u6807\u72B6\u6001\uFF1AEnabled | Paused").option("--start <date>", "\u5217\u8868\u67E5\u8BE2\u8D77\u59CB\u65E5\u671F YYYY-MM-DD").option("--end <date>", "\u5217\u8868\u67E5\u8BE2\u7ED3\u675F\u65E5\u671F YYYY-MM-DD").option("-t, --token <token>", "Auth Token").option("--verbose", "\u8BE6\u7EC6\u9519\u8BEF\u4FE1\u606F", false).action(
125316
125452
  async (opts) => {
125317
125453
  if (opts.status !== "Enabled" && opts.status !== "Paused") {
125318
125454
  console.error("\n\u274C --status \u53EA\u63A5\u53D7 Enabled \u6216 Paused\n");