siluzan-tso-cli 1.1.54 → 1.1.55-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/README.md +2 -1
- package/dist/index.js +473 -231
- package/dist/skill/SKILL.md +2 -2
- package/dist/skill/_meta.json +2 -2
- package/dist/skill/references/accounts/accounts-list.md +3 -1
- package/dist/skill/references/accounts/accounts-permissions.md +2 -2
- package/dist/skill/references/accounts/finance.md +1 -1
- package/dist/skill/references/accounts/open-account-by-media.md +1 -1
- package/dist/skill/references/accounts/open-account-google-ui.md +1 -1
- package/dist/skill/references/analytics/rag.md +1 -1
- package/dist/skill/references/analytics/reporting.md +5 -5
- package/dist/skill/references/core/agent-conventions.md +6 -4
- package/dist/skill/references/core/playbooks.md +1 -1
- package/dist/skill/references/core/setup.md +5 -5
- package/dist/skill/references/core/subagent-orchestration.md +1 -1
- package/dist/skill/references/misc/tso-home.md +2 -2
- package/dist/skill/references/operations/guard.md +1 -1
- package/dist/skill/references/report-templates/README.md +1 -1
- package/dist/skill/references/report-templates/REPORT-WORKFLOW.md +1 -1
- package/dist/skill/references/report-templates/okki-weekly-google-client.md +55 -42
- package/dist/skill/report-templates/README.md +1 -1
- package/dist/skill/report-templates/REPORT-WORKFLOW.md +1 -1
- package/dist/skill/report-templates/okki-weekly-google-client.md +55 -42
- package/dist/skill/scripts/install.ps1 +3 -3
- package/dist/skill/scripts/install.sh +3 -3
- package/dist/skill/snippets/handoff-p6-okki.md +2 -2
- package/eval/cases/compat-account-balance.scenario.json +23 -0
- package/eval/cases/compat-cpa-risk-scan.scenario.json +26 -0
- package/eval/cases/compat-d-group-mcc.scenario.json +31 -0
- package/eval/cases/compat-google-analysis-run-is-real.scenario.json +23 -0
- package/eval/cases/compat-playbook-code-w1.scenario.json +23 -0
- package/eval/cases/hosted-sop-daily-budget-circuit-breaker.scenario.json +8 -2
- package/eval/cases/uj-patrol-google-balances-low.scenario.json +9 -3
- package/package.json +1 -1
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
|
|
|
@@ -4421,12 +4421,12 @@ var init_fetch_wrapper = __esm({
|
|
|
4421
4421
|
});
|
|
4422
4422
|
|
|
4423
4423
|
// src/utils/auth.ts
|
|
4424
|
-
function requireWhitelistedBase(
|
|
4424
|
+
function requireWhitelistedBase(label2, raw) {
|
|
4425
4425
|
const trimmed = raw.trim().replace(/\/$/, "");
|
|
4426
4426
|
const err = validateBaseUrl(trimmed);
|
|
4427
4427
|
if (err) {
|
|
4428
4428
|
console.error(`
|
|
4429
|
-
\u274C ${
|
|
4429
|
+
\u274C ${label2} \u4E0D\u5408\u6CD5\uFF1A${err}`);
|
|
4430
4430
|
process.exit(1);
|
|
4431
4431
|
}
|
|
4432
4432
|
return trimmed;
|
|
@@ -4529,10 +4529,10 @@ function normalizeNumericMediaCustomerId(raw) {
|
|
|
4529
4529
|
if (!looksLikeNumericMediaCustomerId(raw)) return null;
|
|
4530
4530
|
return stripMediaCustomerIdDecorators(raw);
|
|
4531
4531
|
}
|
|
4532
|
-
function requireNumericMediaCustomerId(raw,
|
|
4532
|
+
function requireNumericMediaCustomerId(raw, label2 = "-a, --account") {
|
|
4533
4533
|
const trimmed = raw?.toString().trim() ?? "";
|
|
4534
4534
|
if (!trimmed) {
|
|
4535
|
-
throw new Error(`\u8BF7\u6307\u5B9A\u5A92\u4F53\u8D26\u6237 ID\uFF08${
|
|
4535
|
+
throw new Error(`\u8BF7\u6307\u5B9A\u5A92\u4F53\u8D26\u6237 ID\uFF08${label2}\uFF09`);
|
|
4536
4536
|
}
|
|
4537
4537
|
const id = normalizeNumericMediaCustomerId(trimmed);
|
|
4538
4538
|
if (!id) {
|
|
@@ -4609,6 +4609,24 @@ var init_currency_display = __esm({
|
|
|
4609
4609
|
}
|
|
4610
4610
|
});
|
|
4611
4611
|
|
|
4612
|
+
// src/utils/login-customer-id.ts
|
|
4613
|
+
function normalizeLoginCustomerId(value) {
|
|
4614
|
+
if (value == null) return "";
|
|
4615
|
+
return String(value).replace(/[-\s]/g, "").trim();
|
|
4616
|
+
}
|
|
4617
|
+
function filterByLoginCustomerId(items3, loginCustomerId) {
|
|
4618
|
+
const want = normalizeLoginCustomerId(loginCustomerId);
|
|
4619
|
+
if (!want) return [...items3];
|
|
4620
|
+
return items3.filter((item) => normalizeLoginCustomerId(item.ma?.loginCustomerId) === want);
|
|
4621
|
+
}
|
|
4622
|
+
var LOGIN_CUSTOMER_ID_OPTION_HELP;
|
|
4623
|
+
var init_login_customer_id = __esm({
|
|
4624
|
+
"src/utils/login-customer-id.ts"() {
|
|
4625
|
+
"use strict";
|
|
4626
|
+
LOGIN_CUSTOMER_ID_OPTION_HELP = "\u53EA\u4FDD\u7559 ma.loginCustomerId \u5339\u914D\u7684\u8D26\u6237\uFF08Google MCC\uFF1B397-889-3117 \u4E0E 3978893117 \u76F8\u540C\uFF09\u3002\u4E0D\u4F20\u5219\u4E0D\u8FC7\u6EE4";
|
|
4627
|
+
}
|
|
4628
|
+
});
|
|
4629
|
+
|
|
4612
4630
|
// src/commands/google-analysis/daily-metrics-range.ts
|
|
4613
4631
|
function pad2(n) {
|
|
4614
4632
|
return String(n).padStart(2, "0");
|
|
@@ -5411,7 +5429,8 @@ async function runAccountsDigest(opts) {
|
|
|
5411
5429
|
const maxPages = Math.max(1, Math.min(200, opts.maxPages ?? 20));
|
|
5412
5430
|
let accountsList;
|
|
5413
5431
|
let scannedFromList = false;
|
|
5414
|
-
|
|
5432
|
+
const restrictToMcc = !!opts.loginCustomerId?.trim();
|
|
5433
|
+
if (filterSet.size > 0 && !restrictToMcc) {
|
|
5415
5434
|
const mediaLookups = media === "MetaAd" ? await lookupMetaMediaAccounts(config, filterIds, opts.verbose) : /* @__PURE__ */ new Map();
|
|
5416
5435
|
accountsList = filterIds.map((id) => {
|
|
5417
5436
|
const row = mediaLookups.get(id);
|
|
@@ -5443,6 +5462,20 @@ async function runAccountsDigest(opts) {
|
|
|
5443
5462
|
process.exit(1);
|
|
5444
5463
|
}
|
|
5445
5464
|
}
|
|
5465
|
+
if (restrictToMcc) {
|
|
5466
|
+
const before = accountsList.length;
|
|
5467
|
+
accountsList = filterByLoginCustomerId(accountsList, opts.loginCustomerId);
|
|
5468
|
+
if (filterSet.size > 0) {
|
|
5469
|
+
const wanted = new Set([...filterSet].map((id) => id.replace(/[-\s]/g, "")));
|
|
5470
|
+
accountsList = accountsList.filter(
|
|
5471
|
+
(item) => wanted.has(String(item.ma?.mediaCustomerId ?? "").replace(/[-\s]/g, ""))
|
|
5472
|
+
);
|
|
5473
|
+
}
|
|
5474
|
+
process.stderr.write(
|
|
5475
|
+
`\u23F3 [accounts-digest] --login-customer-id \u4FDD\u7559 ${accountsList.length}/${before} \u6237
|
|
5476
|
+
`
|
|
5477
|
+
);
|
|
5478
|
+
}
|
|
5446
5479
|
const validIds = accountsList.filter((it) => it.ma?.mediaCustomerId && !it.ma?.invalidOAuthToken).map((it) => String(it.ma.mediaCustomerId));
|
|
5447
5480
|
let balanceMap = /* @__PURE__ */ new Map();
|
|
5448
5481
|
let overviewMap = /* @__PURE__ */ new Map();
|
|
@@ -5658,6 +5691,7 @@ var init_run = __esm({
|
|
|
5658
5691
|
init_media_account_batch();
|
|
5659
5692
|
init_media_account_lookup();
|
|
5660
5693
|
init_list_fetch();
|
|
5694
|
+
init_login_customer_id();
|
|
5661
5695
|
init_brief();
|
|
5662
5696
|
init_filters();
|
|
5663
5697
|
}
|
|
@@ -5682,7 +5716,7 @@ function register10(program2) {
|
|
|
5682
5716
|
"--skip-balance",
|
|
5683
5717
|
"\u53EA\u62C9\u6D88\u8017\u3001\u4E0D\u62C9\u4F59\u989D\uFF08\u8F6C\u5316\u6210\u672C/CPA \u5DE1\u68C0\u63A8\u8350\uFF1B\u53EF\u5C11\u4E00\u534A\u8BF7\u6C42\u65F6\u95F4\uFF09",
|
|
5684
5718
|
false
|
|
5685
|
-
).option("--page-size <n>", "\u8D26\u6237\u6E05\u5355\u5206\u9875\u5927\u5C0F\uFF08\u9ED8\u8BA4 200\uFF0C\u4E0A\u9650 500\uFF09", (v) => parseInt(v, 10)).option("--max-pages <n>", "\u6700\u591A\u626B\u63CF\u9875\u6570\uFF08\u9ED8\u8BA4 20\uFF0C\u4E0A\u9650 200\uFF09", (v) => parseInt(v, 10)).option("-t, --token <token>", "Token\uFF08\u53EF\u9009\uFF1B\u4F18\u5148\u4E8E ~/.siluzan/config.json\uFF09").option(
|
|
5719
|
+
).option("--page-size <n>", "\u8D26\u6237\u6E05\u5355\u5206\u9875\u5927\u5C0F\uFF08\u9ED8\u8BA4 200\uFF0C\u4E0A\u9650 500\uFF09", (v) => parseInt(v, 10)).option("--login-customer-id <id>", LOGIN_CUSTOMER_ID_OPTION_HELP).option("--max-pages <n>", "\u6700\u591A\u626B\u63CF\u9875\u6570\uFF08\u9ED8\u8BA4 20\uFF0C\u4E0A\u9650 200\uFF09", (v) => parseInt(v, 10)).option("-t, --token <token>", "Token\uFF08\u53EF\u9009\uFF1B\u4F18\u5148\u4E8E ~/.siluzan/config.json\uFF09").option(
|
|
5686
5720
|
"--json-out <path>",
|
|
5687
5721
|
"\u843D\u76D8\uFF08\u76EE\u5F55\u6216 *.json \u6587\u4EF6\u8DEF\u5F84\uFF09\u5E76\u66F4\u65B0 cli-manifest[-<\u67E5\u8BE2id>].json\uFF1B\u76EE\u5F55\u6A21\u5F0F\u6587\u4EF6\u540D\u4E3A `<section>[-<\u67E5\u8BE2id>].json`\uFF1Bstdout \u4E00\u884C\u6458\u8981 JSON\uFF0C\u542B outlineFile\uFF08TS \u5F0F\u7C7B\u578B\u5728 `*.outline.txt`\uFF09",
|
|
5688
5722
|
void 0
|
|
@@ -5702,7 +5736,8 @@ function register10(program2) {
|
|
|
5702
5736
|
maxPages: opts.maxPages,
|
|
5703
5737
|
jsonOut: opts.jsonOut,
|
|
5704
5738
|
refreshDp: opts.refreshDp,
|
|
5705
|
-
verbose: opts.verbose
|
|
5739
|
+
verbose: opts.verbose,
|
|
5740
|
+
loginCustomerId: opts.loginCustomerId
|
|
5706
5741
|
});
|
|
5707
5742
|
}
|
|
5708
5743
|
);
|
|
@@ -5711,6 +5746,7 @@ var init_register = __esm({
|
|
|
5711
5746
|
"src/commands/accounts-digest/_register.ts"() {
|
|
5712
5747
|
"use strict";
|
|
5713
5748
|
init_run();
|
|
5749
|
+
init_login_customer_id();
|
|
5714
5750
|
}
|
|
5715
5751
|
});
|
|
5716
5752
|
|
|
@@ -6262,9 +6298,9 @@ function xfXml(x) {
|
|
|
6262
6298
|
function stylesXml(reg) {
|
|
6263
6299
|
return `<?xml version="1.0" encoding="UTF-8" standalone="yes"?><styleSheet xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main"><fonts count="${reg.fonts.length}">${reg.fonts.map(fontXml).join("")}</fonts><fills count="${reg.fills.length}">${reg.fills.map(fillXml).join("")}</fills><borders count="${reg.borders.length}">${reg.borders.map(borderXml).join("")}</borders><cellStyleXfs count="1"><xf numFmtId="0" fontId="0" fillId="0" borderId="0"/></cellStyleXfs><cellXfs count="${reg.xfs.length}">${reg.xfs.map(xfXml).join("")}</cellXfs><cellStyles count="1"><cellStyle name="\u5E38\u89C4" xfId="0" builtinId="0"/></cellStyles></styleSheet>`;
|
|
6264
6300
|
}
|
|
6265
|
-
function cellXml(ref,
|
|
6266
|
-
if (
|
|
6267
|
-
const { value, styleId } =
|
|
6301
|
+
function cellXml(ref, cell5) {
|
|
6302
|
+
if (cell5 == null) return "";
|
|
6303
|
+
const { value, styleId } = cell5;
|
|
6268
6304
|
const sAttr = styleId ? ` s="${styleId}"` : "";
|
|
6269
6305
|
if (value == null || value === "") {
|
|
6270
6306
|
return styleId ? `<c r="${ref}"${sAttr}/>` : "";
|
|
@@ -6279,7 +6315,7 @@ function sheetXml(sheet) {
|
|
|
6279
6315
|
const rowsXml = sheet.rows.map((row, i) => {
|
|
6280
6316
|
const r = i + 1;
|
|
6281
6317
|
const htAttr = row.height ? ` ht="${row.height}" customHeight="1"` : "";
|
|
6282
|
-
const cells = row.cells.map((
|
|
6318
|
+
const cells = row.cells.map((cell5, cIdx) => cellXml(`${colLetter(cIdx)}${r}`, cell5)).join("");
|
|
6283
6319
|
return `<row r="${r}"${htAttr}>${cells}</row>`;
|
|
6284
6320
|
}).join("");
|
|
6285
6321
|
const mergesXml = sheet.merges.length ? `<mergeCells count="${sheet.merges.length}">${sheet.merges.map((m) => `<mergeCell ref="${m}"/>`).join("")}</mergeCells>` : "";
|
|
@@ -6541,7 +6577,7 @@ var init_xlsx_style_engine = __esm({
|
|
|
6541
6577
|
this.pushRow(rowCells, { height: maxHeight });
|
|
6542
6578
|
return this;
|
|
6543
6579
|
}
|
|
6544
|
-
kvRow(
|
|
6580
|
+
kvRow(label2, value, opts = {}) {
|
|
6545
6581
|
const isShaded = opts.shaded ?? this.zebra % 2 === 1;
|
|
6546
6582
|
this.zebra += 1;
|
|
6547
6583
|
const labelStyle = this.registry.resolve({
|
|
@@ -6563,7 +6599,7 @@ var init_xlsx_style_engine = __esm({
|
|
|
6563
6599
|
const height = estimateWrapHeight(value, this.colWidths[1] || 40);
|
|
6564
6600
|
const rowIndex = this.pushRow(
|
|
6565
6601
|
[
|
|
6566
|
-
{ value:
|
|
6602
|
+
{ value: label2, styleId: labelStyle },
|
|
6567
6603
|
{ value: value ?? "", styleId: valueStyle }
|
|
6568
6604
|
],
|
|
6569
6605
|
{ height }
|
|
@@ -7209,7 +7245,7 @@ function sleep3(ms, signal) {
|
|
|
7209
7245
|
signal?.addEventListener("abort", onAbort, { once: true });
|
|
7210
7246
|
});
|
|
7211
7247
|
}
|
|
7212
|
-
async function withTaskTimeout(factory, timeoutMs,
|
|
7248
|
+
async function withTaskTimeout(factory, timeoutMs, label2) {
|
|
7213
7249
|
if (!timeoutMs || timeoutMs <= 0) return factory();
|
|
7214
7250
|
let timer;
|
|
7215
7251
|
try {
|
|
@@ -7217,7 +7253,7 @@ async function withTaskTimeout(factory, timeoutMs, label) {
|
|
|
7217
7253
|
factory(),
|
|
7218
7254
|
new Promise((_, reject) => {
|
|
7219
7255
|
timer = setTimeout(() => {
|
|
7220
|
-
reject(new Error(`\u8BF7\u6C42\u8D85\u65F6\uFF08${(timeoutMs / 1e3).toFixed(0)} \u79D2\uFF09\uFF1A${
|
|
7256
|
+
reject(new Error(`\u8BF7\u6C42\u8D85\u65F6\uFF08${(timeoutMs / 1e3).toFixed(0)} \u79D2\uFF09\uFF1A${label2}`));
|
|
7221
7257
|
}, timeoutMs);
|
|
7222
7258
|
})
|
|
7223
7259
|
]);
|
|
@@ -102697,19 +102733,19 @@ function buildSearchParams(def, start, end, extras) {
|
|
|
102697
102733
|
const s = params.toString();
|
|
102698
102734
|
return s ? `?${s}` : "";
|
|
102699
102735
|
}
|
|
102700
|
-
async function fetchGoogleAnalysisHttp(
|
|
102736
|
+
async function fetchGoogleAnalysisHttp(label2, factory, http2) {
|
|
102701
102737
|
return fetchWithRetry(factory, {
|
|
102702
|
-
label,
|
|
102738
|
+
label: label2,
|
|
102703
102739
|
policy: { ...DEFAULT_RETRY_POLICY, ...http2?.retry },
|
|
102704
102740
|
signal: http2?.signal
|
|
102705
102741
|
});
|
|
102706
102742
|
}
|
|
102707
|
-
async function fetchJson(config, pathWithQuery, verbose,
|
|
102743
|
+
async function fetchJson(config, pathWithQuery, verbose, label2 = pathWithQuery, http2) {
|
|
102708
102744
|
const url = `${config.googleApiUrl}${pathWithQuery}`;
|
|
102709
|
-
return fetchGoogleAnalysisHttp(
|
|
102745
|
+
return fetchGoogleAnalysisHttp(label2, () => apiFetch2(url, config, {}, verbose), http2);
|
|
102710
102746
|
}
|
|
102711
|
-
async function fetchMainPlatformJson(url, config, verbose,
|
|
102712
|
-
return fetchGoogleAnalysisHttp(
|
|
102747
|
+
async function fetchMainPlatformJson(url, config, verbose, label2, http2) {
|
|
102748
|
+
return fetchGoogleAnalysisHttp(label2, () => apiFetch2(url, config, {}, verbose), http2);
|
|
102713
102749
|
}
|
|
102714
102750
|
function deviceBidModifierLookupKey(campaignId, adGroupId, deviceType) {
|
|
102715
102751
|
return `${campaignId ?? ""}\0${adGroupId ?? ""}\0${deviceType ?? ""}`;
|
|
@@ -102761,8 +102797,8 @@ function rowsFromAccountDailyReportsEnvelope(raw, mediaCustomerId) {
|
|
|
102761
102797
|
const list = block?.data;
|
|
102762
102798
|
return Array.isArray(list) ? list : [];
|
|
102763
102799
|
}
|
|
102764
|
-
async function fetchGoogleAnalysisSectionJson(config, fullPath, verbose, name2,
|
|
102765
|
-
const fetchSection = () => fetchJson(config, fullPath, verbose,
|
|
102800
|
+
async function fetchGoogleAnalysisSectionJson(config, fullPath, verbose, name2, label2, http2) {
|
|
102801
|
+
const fetchSection = () => fetchJson(config, fullPath, verbose, label2, http2);
|
|
102766
102802
|
switch (name2) {
|
|
102767
102803
|
case "overview":
|
|
102768
102804
|
return fetchSection();
|
|
@@ -103477,12 +103513,12 @@ function validateOkkiWeeklyReportContent(data) {
|
|
|
103477
103513
|
const summary = stringList2(block?.summary);
|
|
103478
103514
|
const suggestions = stringList2(block?.suggestions);
|
|
103479
103515
|
sheetAnalysisCounts[key] = { summary: summary.length, suggestions: suggestions.length };
|
|
103480
|
-
const
|
|
103516
|
+
const label2 = SHEET_LABELS[key];
|
|
103481
103517
|
if (summary.length < 1) {
|
|
103482
103518
|
pushMissing(
|
|
103483
103519
|
missing,
|
|
103484
103520
|
`sheet-${key}-summary`,
|
|
103485
|
-
`\u8868\u672B\u5206\u6790 \xB7 ${
|
|
103521
|
+
`\u8868\u672B\u5206\u6790 \xB7 ${label2}`,
|
|
103486
103522
|
`narrative.sheetAnalysis.${key}.summary`,
|
|
103487
103523
|
`\u22651 \u6761\u603B\u7ED3\uFF08\u5F53\u524D ${summary.length} \u6761\uFF09\u3002\u8868\u4E3A\u7A7A\u65F6\u4E5F\u987B\u5199\u300C\u672C\u5468\u671F\u65E0\u8BE5\u7EF4\u5EA6\u6570\u636E\u300D`
|
|
103488
103524
|
);
|
|
@@ -103491,7 +103527,7 @@ function validateOkkiWeeklyReportContent(data) {
|
|
|
103491
103527
|
pushMissing(
|
|
103492
103528
|
missing,
|
|
103493
103529
|
`sheet-${key}-suggestions`,
|
|
103494
|
-
`\u8868\u672B\u5206\u6790 \xB7 ${
|
|
103530
|
+
`\u8868\u672B\u5206\u6790 \xB7 ${label2}`,
|
|
103495
103531
|
`narrative.sheetAnalysis.${key}.suggestions`,
|
|
103496
103532
|
`\u22651 \u6761\u5EFA\u8BAE\uFF08\u5F53\u524D ${suggestions.length} \u6761\uFF09\u3002\u8868\u4E3A\u7A7A\u65F6\u4E5F\u987B\u5199\u53EF\u6267\u884C\u5EFA\u8BAE\u6216\u300C\u6682\u65E0\u8C03\u6574\u300D`
|
|
103497
103533
|
);
|
|
@@ -103504,12 +103540,12 @@ function validateOkkiWeeklyReportContent(data) {
|
|
|
103504
103540
|
const summary = textLen(block?.summary);
|
|
103505
103541
|
const suggestion = textLen(block?.suggestion);
|
|
103506
103542
|
reviewFilled[key] = overview > 0 && summary > 0 && suggestion > 0;
|
|
103507
|
-
const
|
|
103543
|
+
const label2 = REVIEW_LABELS[key];
|
|
103508
103544
|
if (overview < 1) {
|
|
103509
103545
|
pushMissing(
|
|
103510
103546
|
missing,
|
|
103511
103547
|
`review-${key}-overview`,
|
|
103512
|
-
`\u6570\u636E\u590D\u76D8 \xB7 ${
|
|
103548
|
+
`\u6570\u636E\u590D\u76D8 \xB7 ${label2}`,
|
|
103513
103549
|
`narrative.review.${key}.overview`,
|
|
103514
103550
|
"\u5FC5\u586B\u4E00\u6BB5\u603B\u89C8\uFF08\u5F15\u7528\u8868\u4E2D\u6570\u5B57\uFF1B\u65E0\u6570\u636E\u4E5F\u987B\u5199\u660E\uFF09"
|
|
103515
103551
|
);
|
|
@@ -103518,7 +103554,7 @@ function validateOkkiWeeklyReportContent(data) {
|
|
|
103518
103554
|
pushMissing(
|
|
103519
103555
|
missing,
|
|
103520
103556
|
`review-${key}-summary`,
|
|
103521
|
-
`\u6570\u636E\u590D\u76D8 \xB7 ${
|
|
103557
|
+
`\u6570\u636E\u590D\u76D8 \xB7 ${label2}`,
|
|
103522
103558
|
`narrative.review.${key}.summary`,
|
|
103523
103559
|
"\u5FC5\u586B\u300C\u603B\u7ED3\u300D"
|
|
103524
103560
|
);
|
|
@@ -103527,7 +103563,7 @@ function validateOkkiWeeklyReportContent(data) {
|
|
|
103527
103563
|
pushMissing(
|
|
103528
103564
|
missing,
|
|
103529
103565
|
`review-${key}-suggestion`,
|
|
103530
|
-
`\u6570\u636E\u590D\u76D8 \xB7 ${
|
|
103566
|
+
`\u6570\u636E\u590D\u76D8 \xB7 ${label2}`,
|
|
103531
103567
|
`narrative.review.${key}.suggestion`,
|
|
103532
103568
|
"\u5FC5\u586B\u300C\u5EFA\u8BAE\u300D"
|
|
103533
103569
|
);
|
|
@@ -107493,8 +107529,8 @@ async function runInit(options) {
|
|
|
107493
107529
|
for (const entry of targets) {
|
|
107494
107530
|
for (const key of entry.keys) {
|
|
107495
107531
|
const destDir = entry.isGlobal ? GLOBAL_DIRS[key](home) : PROJECT_DIRS[key](options.cwd);
|
|
107496
|
-
const
|
|
107497
|
-
console.log(`[${
|
|
107532
|
+
const label2 = entry.isGlobal ? `${key} global` : key;
|
|
107533
|
+
console.log(`[${label2}] \u2192 ${destDir}`);
|
|
107498
107534
|
const anyWritten = await writeSkillFilesToDir(destDir, skillFiles, options.force);
|
|
107499
107535
|
if (anyWritten) {
|
|
107500
107536
|
installedEntries.push({
|
|
@@ -108050,6 +108086,7 @@ function wrapListJson(params) {
|
|
|
108050
108086
|
}
|
|
108051
108087
|
|
|
108052
108088
|
// src/commands/list-accounts/main.ts
|
|
108089
|
+
init_login_customer_id();
|
|
108053
108090
|
async function runListAccounts(opts) {
|
|
108054
108091
|
let config = loadConfig(opts.token);
|
|
108055
108092
|
if (opts.refreshDp) {
|
|
@@ -108139,6 +108176,18 @@ async function runListAccounts(opts) {
|
|
|
108139
108176
|
stripListAccountsEnrichmentFields(item, exposeScopeActivated);
|
|
108140
108177
|
}
|
|
108141
108178
|
}
|
|
108179
|
+
if (opts.loginCustomerId?.trim()) {
|
|
108180
|
+
const fetched = items3.length;
|
|
108181
|
+
items3 = filterByLoginCustomerId(items3, opts.loginCustomerId);
|
|
108182
|
+
const fetchedAll = total === void 0 || (page - 1) * pageSize + fetched >= total;
|
|
108183
|
+
if (fetchedAll) {
|
|
108184
|
+
total = items3.length;
|
|
108185
|
+
} else if (fetched >= pageSize) {
|
|
108186
|
+
console.error(
|
|
108187
|
+
"\u26A0\uFE0F --login-customer-id \u53EA\u8FC7\u6EE4\u4E86\u672C\u9875\u3002\u8BF7\u52A0\u5927 --page-size\uFF0C\u4EE5\u8986\u76D6\u8BE5 MCC \u7684\u5168\u90E8\u8D26\u6237\u3002\n"
|
|
108188
|
+
);
|
|
108189
|
+
}
|
|
108190
|
+
}
|
|
108142
108191
|
const oauthFailWarning = (() => {
|
|
108143
108192
|
if (items3.length < 5) return null;
|
|
108144
108193
|
const allFail = items3.every((it) => it.ma?.invalidOAuthToken === true);
|
|
@@ -108215,6 +108264,7 @@ async function runListAccounts(opts) {
|
|
|
108215
108264
|
}
|
|
108216
108265
|
|
|
108217
108266
|
// src/commands/list-accounts/register.ts
|
|
108267
|
+
init_login_customer_id();
|
|
108218
108268
|
function register6(program2) {
|
|
108219
108269
|
program2.command("list-accounts").description(
|
|
108220
108270
|
"\u67E5\u8BE2\u5E7F\u544A\u8D26\u6237\u5217\u8868\u3002\u5F53\u524D\u8D26\u6237\u5728 TSO \u5E73\u53F0\u5173\u8054\u7684\u5168\u90E8\u5E7F\u544A\u8D26\u6237\uFF08Google/TikTok/Yandex/MetaAd/BingV2 \u7B49\u5A92\u4F53\uFF09"
|
|
@@ -108232,7 +108282,7 @@ function register6(program2) {
|
|
|
108232
108282
|
"--page-size <n>",
|
|
108233
108283
|
"\u6BCF\u9875\u6570\u91CF\uFF08\u4EA4\u4E92\u9ED8\u8BA4 20\uFF1B\u5E26 --json-out \u4E14\u672A\u6307\u5B9A\u65F6 999\uFF09",
|
|
108234
108284
|
parseInt
|
|
108235
|
-
).option("-t, --token <token>", "Token\uFF08\u53EF\u9009\uFF1B\u4F18\u5148\u4E8E ~/.siluzan/config.json\uFF09").option(
|
|
108285
|
+
).option("--login-customer-id <id>", LOGIN_CUSTOMER_ID_OPTION_HELP).option("-t, --token <token>", "Token\uFF08\u53EF\u9009\uFF1B\u4F18\u5148\u4E8E ~/.siluzan/config.json\uFF09").option(
|
|
108236
108286
|
"--json-out <path>",
|
|
108237
108287
|
"\u843D\u76D8\uFF08\u76EE\u5F55\u6216 *.json \u6587\u4EF6\u8DEF\u5F84\uFF09\u5E76\u66F4\u65B0 cli-manifest[-<\u67E5\u8BE2id>].json\uFF1B\u76EE\u5F55\u6A21\u5F0F\u6587\u4EF6\u540D\u4E3A `<section>[-<\u67E5\u8BE2id>].json`\uFF1Bstdout \u4E00\u884C\u6458\u8981 JSON\uFF0C\u542B outlineFile\uFF08TS \u5F0F\u7C7B\u578B\u5728 `*.outline.txt`\uFF09",
|
|
108238
108288
|
void 0
|
|
@@ -108252,7 +108302,8 @@ function register6(program2) {
|
|
|
108252
108302
|
jsonOut: opts.jsonOut,
|
|
108253
108303
|
unicode: opts.unicode,
|
|
108254
108304
|
refreshDp: opts.refreshDp,
|
|
108255
|
-
verbose: opts.verbose
|
|
108305
|
+
verbose: opts.verbose,
|
|
108306
|
+
loginCustomerId: opts.loginCustomerId
|
|
108256
108307
|
});
|
|
108257
108308
|
}
|
|
108258
108309
|
);
|
|
@@ -108528,6 +108579,38 @@ function register8(program2) {
|
|
|
108528
108579
|
// src/commands/balance-scan/run.ts
|
|
108529
108580
|
init_auth();
|
|
108530
108581
|
init_cli_json_snapshot();
|
|
108582
|
+
|
|
108583
|
+
// src/commands/balance-scan/delivery.ts
|
|
108584
|
+
var DELIVERY_RULE = "\u53EA\u628A userDelivery \u539F\u6837\u53D1\u7ED9\u7528\u6237\u3002\u65E0\u547D\u4E2D\u7528\u539F\u53E5\u300C\u4ECA\u65E5\u65E0\u547D\u4E2D\u300D\u3002\u4E0D\u8981\u53E6\u5199\u62A5\u544A\u3002\u5BBF\u4E3B\u8D1F\u8D23 present_files\u3002";
|
|
108585
|
+
var PATROL_ALL_CLEAR = "\u4ECA\u65E5\u65E0\u547D\u4E2D";
|
|
108586
|
+
function cell(value) {
|
|
108587
|
+
return value.replace(/\|/g, "\uFF5C").replace(/\r?\n/g, " ");
|
|
108588
|
+
}
|
|
108589
|
+
function label(hit) {
|
|
108590
|
+
return hit.advertiserName || hit.name || "-";
|
|
108591
|
+
}
|
|
108592
|
+
function buildBalanceScanDelivery(items3, dataIssueMessage) {
|
|
108593
|
+
if (dataIssueMessage) {
|
|
108594
|
+
return { allClear: false, userDelivery: dataIssueMessage, deliveryRule: DELIVERY_RULE };
|
|
108595
|
+
}
|
|
108596
|
+
const hits = items3.filter((row) => row.hitReason !== "none");
|
|
108597
|
+
if (hits.length === 0) {
|
|
108598
|
+
return { allClear: true, userDelivery: PATROL_ALL_CLEAR, deliveryRule: DELIVERY_RULE };
|
|
108599
|
+
}
|
|
108600
|
+
const header = "| \u8D26\u6237\u540D\u79F0 | \u8D26\u6237ID | \u4F59\u989D | \u5E01\u79CD |\n| --- | --- | ---: | --- |";
|
|
108601
|
+
const lines = hits.map((h) => {
|
|
108602
|
+
const balance = h.balance == null ? "\u2014" : String(h.balance);
|
|
108603
|
+
return `| ${cell(label(h))} | ${h.mediaCustomerId} | ${balance} | ${h.currencyCode ?? "\u2014"} |`;
|
|
108604
|
+
});
|
|
108605
|
+
return {
|
|
108606
|
+
allClear: false,
|
|
108607
|
+
userDelivery: [header, ...lines].join("\n"),
|
|
108608
|
+
deliveryRule: DELIVERY_RULE
|
|
108609
|
+
};
|
|
108610
|
+
}
|
|
108611
|
+
|
|
108612
|
+
// src/commands/balance-scan/run.ts
|
|
108613
|
+
init_login_customer_id();
|
|
108531
108614
|
init_balance();
|
|
108532
108615
|
init_cli_table();
|
|
108533
108616
|
init_currency_display();
|
|
@@ -108788,7 +108871,7 @@ async function runBalanceScan(opts) {
|
|
|
108788
108871
|
const pageSize = Math.max(1, Math.min(500, opts.pageSize ?? 200));
|
|
108789
108872
|
const maxPages = Math.max(1, Math.min(200, opts.maxPages ?? 20));
|
|
108790
108873
|
const filterIds = (opts.accounts ?? "").split(",").map((s) => s.trim()).filter(Boolean);
|
|
108791
|
-
const isSubset = filterIds.length > 0;
|
|
108874
|
+
const isSubset = filterIds.length > 0 && !opts.loginCustomerId?.trim();
|
|
108792
108875
|
let allItems;
|
|
108793
108876
|
let total;
|
|
108794
108877
|
if (isSubset) {
|
|
@@ -108817,6 +108900,20 @@ async function runBalanceScan(opts) {
|
|
|
108817
108900
|
total = res.total;
|
|
108818
108901
|
process.stderr.write(
|
|
108819
108902
|
`\r\u23F3 \u8D26\u6237\u6E05\u5355\u5DF2\u62C9\u53D6\uFF1A\u5171 ${allItems.length} \u6761${total !== void 0 ? `\uFF08\u63A5\u53E3 total\u2248${total}\uFF09` : ""}
|
|
108903
|
+
`
|
|
108904
|
+
);
|
|
108905
|
+
}
|
|
108906
|
+
if (opts.loginCustomerId?.trim()) {
|
|
108907
|
+
const before = allItems.length;
|
|
108908
|
+
allItems = filterByLoginCustomerId(allItems, opts.loginCustomerId);
|
|
108909
|
+
if (filterIds.length > 0) {
|
|
108910
|
+
const wanted = new Set(filterIds.map((id) => id.replace(/[-\s]/g, "")));
|
|
108911
|
+
allItems = allItems.filter(
|
|
108912
|
+
(item) => wanted.has(String(item.ma?.mediaCustomerId ?? "").replace(/[-\s]/g, ""))
|
|
108913
|
+
);
|
|
108914
|
+
}
|
|
108915
|
+
process.stderr.write(
|
|
108916
|
+
`\u23F3 [balance-scan] --login-customer-id \u4FDD\u7559 ${allItems.length}/${before} \u6237
|
|
108820
108917
|
`
|
|
108821
108918
|
);
|
|
108822
108919
|
}
|
|
@@ -108914,13 +109011,15 @@ async function runBalanceScan(opts) {
|
|
|
108914
109011
|
totalReported: total ?? null,
|
|
108915
109012
|
generatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
108916
109013
|
};
|
|
108917
|
-
const
|
|
109014
|
+
const agentBrief = buildBalanceScanDelivery(evaluated, dataIssue?.message ?? null);
|
|
109015
|
+
const scanPayload = { ok: !dataIssue, data: { items: evaluated }, meta, agentBrief };
|
|
108918
109016
|
const wroteJson = await emitCliJsonOrSnapshot(opts, {
|
|
108919
109017
|
section: `balance-scan-${media}`,
|
|
108920
109018
|
commandLabel: "balance-scan",
|
|
108921
109019
|
commandHint: media,
|
|
108922
109020
|
payload: scanPayload,
|
|
108923
|
-
idSuffix: media
|
|
109021
|
+
idSuffix: media,
|
|
109022
|
+
summaryExtras: { userDelivery: agentBrief.userDelivery }
|
|
108924
109023
|
});
|
|
108925
109024
|
if (dataIssue) {
|
|
108926
109025
|
console.error(`
|
|
@@ -108994,6 +109093,7 @@ ${media} \u8D26\u6237\u4F59\u989D\u626B\u63CF\u5B8C\u6210\uFF1A\u5171\u626B\u63C
|
|
|
108994
109093
|
}
|
|
108995
109094
|
|
|
108996
109095
|
// src/commands/balance-scan/_register.ts
|
|
109096
|
+
init_login_customer_id();
|
|
108997
109097
|
function register9(program2) {
|
|
108998
109098
|
program2.command("balance-scan").description(
|
|
108999
109099
|
"\u4E00\u952E\u626B\u63CF\u67D0\u5A92\u4F53\u4E0B\u6709\u6548\u8D26\u6237\u7684\u4F59\u989D\u4E0E\u65E5\u5747\u6D88\u8017\uFF0C\u8FD4\u56DE\u5168\u90E8\u5DF2\u68C0\u67E5\u8D26\u6237\uFF1B\u7528 hitReason \u6807\u8BB0\u7EED\u822A/\u4F59\u989D\u4E0D\u8DB3\u7684\u9884\u8B66\u884C\u3002\u66FF\u4EE3\u5FAA\u73AF\u8C03\u7528 balance \u7684\u4F20\u7EDF\u505A\u6CD5\u3002"
|
|
@@ -109015,7 +109115,7 @@ function register9(program2) {
|
|
|
109015
109115
|
"--min-daily-spend <n>",
|
|
109016
109116
|
"\u8FD1 N \u65E5\u65E5\u5747\u6D88\u8017 < \u6B64\u503C\u7684\u8D26\u6237\u89C6\u4E3A\u50F5\u5C38\u8D26\u6237\u4E0D\u505A\u7EED\u822A\u4F30\u7B97\uFF08\u9ED8\u8BA4 0.01\uFF1BN \u89C1 --spend-days\uFF09",
|
|
109017
109117
|
(v) => parseFloat(v)
|
|
109018
|
-
).option("--target-days <n>", "\u5EFA\u8BAE\u5145\u503C\u6309\u6B64\u76EE\u6807\u7EED\u822A\u5929\u6570\u8BA1\u7B97\uFF08\u9ED8\u8BA4 30\uFF09", (v) => parseFloat(v)).option("--page-size <n>", "\u5206\u9875\u5927\u5C0F\uFF08\u9ED8\u8BA4 200\uFF0C\u4E0A\u9650 500\uFF09", (v) => parseInt(v, 10)).option(
|
|
109118
|
+
).option("--target-days <n>", "\u5EFA\u8BAE\u5145\u503C\u6309\u6B64\u76EE\u6807\u7EED\u822A\u5929\u6570\u8BA1\u7B97\uFF08\u9ED8\u8BA4 30\uFF09", (v) => parseFloat(v)).option("--page-size <n>", "\u5206\u9875\u5927\u5C0F\uFF08\u9ED8\u8BA4 200\uFF0C\u4E0A\u9650 500\uFF09", (v) => parseInt(v, 10)).option("--login-customer-id <id>", LOGIN_CUSTOMER_ID_OPTION_HELP).option(
|
|
109019
109119
|
"--max-pages <n>",
|
|
109020
109120
|
"\u6700\u591A\u626B\u63CF\u9875\u6570\uFF08\u9ED8\u8BA4 20\uFF0C\u4E0A\u9650 200\uFF1B\u8D85\u51FA\u540E\u8BF7\u63D0\u9AD8 --page-size \u6216\u5206\u6B21\u626B\u63CF\uFF09",
|
|
109021
109121
|
(v) => parseInt(v, 10)
|
|
@@ -109038,7 +109138,8 @@ function register9(program2) {
|
|
|
109038
109138
|
maxPages: opts.maxPages,
|
|
109039
109139
|
jsonOut: opts.jsonOut,
|
|
109040
109140
|
refreshDp: opts.refreshDp,
|
|
109041
|
-
verbose: opts.verbose
|
|
109141
|
+
verbose: opts.verbose,
|
|
109142
|
+
loginCustomerId: opts.loginCustomerId
|
|
109042
109143
|
});
|
|
109043
109144
|
}
|
|
109044
109145
|
);
|
|
@@ -109053,13 +109154,14 @@ init_cli_json_snapshot();
|
|
|
109053
109154
|
// src/commands/guard/shared.ts
|
|
109054
109155
|
init_auth();
|
|
109055
109156
|
init_list_fetch();
|
|
109157
|
+
init_login_customer_id();
|
|
109056
109158
|
|
|
109057
109159
|
// src/commands/ad/_shared.ts
|
|
109058
109160
|
init_auth();
|
|
109059
109161
|
init_media_customer_id();
|
|
109060
|
-
function resolveAdAccountId(account,
|
|
109162
|
+
function resolveAdAccountId(account, label2 = "-a, --account") {
|
|
109061
109163
|
try {
|
|
109062
|
-
return requireNumericMediaCustomerId(account,
|
|
109164
|
+
return requireNumericMediaCustomerId(account, label2);
|
|
109063
109165
|
} catch (e) {
|
|
109064
109166
|
console.error(`
|
|
109065
109167
|
\u274C ${e instanceof Error ? e.message : String(e)}
|
|
@@ -109173,7 +109275,8 @@ function assertGoogleOnly(media) {
|
|
|
109173
109275
|
}
|
|
109174
109276
|
async function resolveGuardAccounts(opts, config) {
|
|
109175
109277
|
const filterIds = (opts.accounts ?? "").split(",").map((s) => s.trim()).filter(Boolean);
|
|
109176
|
-
|
|
109278
|
+
const wantMcc = !!opts.loginCustomerId?.trim();
|
|
109279
|
+
if (filterIds.length > 0 && !wantMcc) {
|
|
109177
109280
|
process.stderr.write(`\u23F3 [guard] \u5B50\u96C6\u6A21\u5F0F\uFF1A\u5BF9 -a \u6307\u5B9A\u7684 ${filterIds.length} \u4E2A\u8D26\u6237\u626B\u63CF\u3002
|
|
109178
109281
|
`);
|
|
109179
109282
|
return filterIds.map((id) => ({ mediaCustomerId: id, name: null }));
|
|
@@ -109185,7 +109288,22 @@ async function resolveGuardAccounts(opts, config) {
|
|
|
109185
109288
|
maxPages,
|
|
109186
109289
|
verbose: opts.verbose
|
|
109187
109290
|
});
|
|
109188
|
-
|
|
109291
|
+
let items3 = res.items;
|
|
109292
|
+
if (wantMcc) {
|
|
109293
|
+
const before = items3.length;
|
|
109294
|
+
items3 = filterByLoginCustomerId(items3, opts.loginCustomerId);
|
|
109295
|
+
process.stderr.write(
|
|
109296
|
+
`\u23F3 [guard] --login-customer-id \u4FDD\u7559 ${items3.length}/${before} \u6237
|
|
109297
|
+
`
|
|
109298
|
+
);
|
|
109299
|
+
}
|
|
109300
|
+
if (filterIds.length > 0) {
|
|
109301
|
+
const wanted = new Set(filterIds.map((id) => id.replace(/[-\s]/g, "")));
|
|
109302
|
+
items3 = items3.filter(
|
|
109303
|
+
(item) => wanted.has(String(item.ma?.mediaCustomerId ?? "").replace(/[-\s]/g, ""))
|
|
109304
|
+
);
|
|
109305
|
+
}
|
|
109306
|
+
return items3.map((item) => ({
|
|
109189
109307
|
mediaCustomerId: String(item.ma?.mediaCustomerId ?? ""),
|
|
109190
109308
|
name: item.ma?.mediaCustomerName ?? null
|
|
109191
109309
|
})).filter((a) => a.mediaCustomerId);
|
|
@@ -109268,6 +109386,41 @@ ${title}
|
|
|
109268
109386
|
console.log();
|
|
109269
109387
|
}
|
|
109270
109388
|
|
|
109389
|
+
// src/commands/guard/delivery.ts
|
|
109390
|
+
var DELIVERY_RULE2 = "\u53EA\u628A userDelivery \u539F\u6837\u53D1\u7ED9\u7528\u6237\u3002\u65E0\u547D\u4E2D\u7528\u539F\u53E5\u300C\u4ECA\u65E5\u65E0\u547D\u4E2D\u300D\u3002\u4E0D\u8981\u53E6\u5199\u62A5\u544A\u3002\u5BBF\u4E3B\u8D1F\u8D23 present_files\u3002";
|
|
109391
|
+
var PATROL_ALL_CLEAR2 = "\u4ECA\u65E5\u65E0\u547D\u4E2D";
|
|
109392
|
+
function cell2(value) {
|
|
109393
|
+
return value.replace(/\|/g, "\uFF5C").replace(/\r?\n/g, " ");
|
|
109394
|
+
}
|
|
109395
|
+
function buildBudgetCircuitDelivery(hits) {
|
|
109396
|
+
if (hits.length === 0) {
|
|
109397
|
+
return { allClear: true, userDelivery: PATROL_ALL_CLEAR2, deliveryRule: DELIVERY_RULE2 };
|
|
109398
|
+
}
|
|
109399
|
+
const header = "| \u7CFB\u5217\u540D\u79F0 | \u7CFB\u5217ID | \u8D26\u6237ID | \u5F53\u65E5\u82B1\u8D39 | \u65E5\u9884\u7B97 |\n| --- | --- | --- | ---: | ---: |";
|
|
109400
|
+
const lines = hits.map(
|
|
109401
|
+
(h) => `| ${cell2(h.campaignName)} | ${h.campaignId} | ${h.mediaCustomerId} | ${h.spend} | ${h.budget} |`
|
|
109402
|
+
);
|
|
109403
|
+
return {
|
|
109404
|
+
allClear: false,
|
|
109405
|
+
userDelivery: [header, ...lines].join("\n"),
|
|
109406
|
+
deliveryRule: DELIVERY_RULE2
|
|
109407
|
+
};
|
|
109408
|
+
}
|
|
109409
|
+
function buildZeroConvDelivery(hits) {
|
|
109410
|
+
if (hits.length === 0) {
|
|
109411
|
+
return { allClear: true, userDelivery: PATROL_ALL_CLEAR2, deliveryRule: DELIVERY_RULE2 };
|
|
109412
|
+
}
|
|
109413
|
+
const header = "| \u5BF9\u8C61\u540D\u79F0 | \u5BF9\u8C61ID | \u8D26\u6237ID | \u5F53\u65E5\u82B1\u8D39 |\n| --- | --- | --- | ---: |";
|
|
109414
|
+
const lines = hits.map(
|
|
109415
|
+
(h) => `| ${cell2(h.objectName)} | ${h.objectId} | ${h.mediaCustomerId} | ${h.spend} |`
|
|
109416
|
+
);
|
|
109417
|
+
return {
|
|
109418
|
+
allClear: false,
|
|
109419
|
+
userDelivery: [header, ...lines].join("\n"),
|
|
109420
|
+
deliveryRule: DELIVERY_RULE2
|
|
109421
|
+
};
|
|
109422
|
+
}
|
|
109423
|
+
|
|
109271
109424
|
// src/commands/guard/rules.ts
|
|
109272
109425
|
function moneyGte(leftYuan, rightYuan) {
|
|
109273
109426
|
return Math.round(leftYuan * 100) >= Math.round(rightYuan * 100);
|
|
@@ -109399,12 +109552,15 @@ async function runBudgetCircuit(opts) {
|
|
|
109399
109552
|
errorCount: errors.length
|
|
109400
109553
|
},
|
|
109401
109554
|
hits,
|
|
109402
|
-
errors
|
|
109555
|
+
errors,
|
|
109556
|
+
agentBrief: buildBudgetCircuitDelivery(hits)
|
|
109403
109557
|
};
|
|
109558
|
+
const agentBrief = payload.agentBrief;
|
|
109404
109559
|
if (await emitCliJsonOrSnapshot(opts, {
|
|
109405
109560
|
section: "guard-budget-circuit",
|
|
109406
109561
|
commandLabel: "guard budget-circuit",
|
|
109407
|
-
payload
|
|
109562
|
+
payload,
|
|
109563
|
+
summaryExtras: { userDelivery: agentBrief.userDelivery }
|
|
109408
109564
|
})) {
|
|
109409
109565
|
}
|
|
109410
109566
|
const title = `\u8D85\u9884\u7B97\u7194\u65AD\u626B\u63CF \xB7 ${date} \xB7 ratio=${ratio} \xB7 \u547D\u4E2D ${hits.length}/${checkedCampaigns}`;
|
|
@@ -109594,12 +109750,14 @@ async function runZeroConv(opts) {
|
|
|
109594
109750
|
},
|
|
109595
109751
|
hits,
|
|
109596
109752
|
skipped,
|
|
109597
|
-
errors
|
|
109753
|
+
errors,
|
|
109754
|
+
agentBrief: buildZeroConvDelivery(hits)
|
|
109598
109755
|
};
|
|
109599
109756
|
await emitCliJsonOrSnapshot(opts, {
|
|
109600
109757
|
section: "guard-zero-conv",
|
|
109601
109758
|
commandLabel: "guard zero-conv",
|
|
109602
|
-
payload
|
|
109759
|
+
payload,
|
|
109760
|
+
summaryExtras: { userDelivery: payload.agentBrief.userDelivery }
|
|
109603
109761
|
});
|
|
109604
109762
|
const title = `\u7A7A\u8017\u7194\u65AD\u626B\u63CF \xB7 ${date} \xB7 \xD7${multiple} \xB7 \u547D\u4E2D ${hits.length}/${checked}`;
|
|
109605
109763
|
printHitsTable(
|
|
@@ -109634,6 +109792,7 @@ async function runZeroConv(opts) {
|
|
|
109634
109792
|
}
|
|
109635
109793
|
|
|
109636
109794
|
// src/commands/guard/_register.ts
|
|
109795
|
+
init_login_customer_id();
|
|
109637
109796
|
function register11(program2) {
|
|
109638
109797
|
const guard = program2.command("guard").description(
|
|
109639
109798
|
"Google \u6295\u653E\u81EA\u63A7\u7194\u65AD\u626B\u63CF\uFF1A\u5168\u6237\uFF08\u6216 -a \u5B50\u96C6\uFF09\u5217\u51FA\u5F53\u65E5\u8D85\u9884\u7B97/\u7A7A\u8017\u547D\u4E2D\uFF0C\u53EA\u8BFB\u4E0D\u6682\u505C\u3002\u8981\u505C\u6295\u653E\u987B\u5BF9\u6BCF\u4E2A\u547D\u4E2D\u5BF9\u8C61\u5355\u72EC\u6267\u884C ad campaign-status / adgroup-status / ad-status\uFF08\u5E26 --commit\uFF09\u3002\u975E Google \u5A92\u4F53\u4E0D\u652F\u6301\u3002"
|
|
@@ -109643,7 +109802,7 @@ function register11(program2) {
|
|
|
109643
109802
|
).requiredOption("-m, --media <type>", "\u76EE\u524D\u4EC5\u652F\u6301 Google").option(
|
|
109644
109803
|
"-a, --accounts <ids>",
|
|
109645
109804
|
"\u6307\u5B9A\u8D26\u6237 mediaCustomerId\uFF0C\u9017\u53F7\u5206\u9694\uFF1B\u7559\u7A7A\u5219\u626B\u63CF\u540D\u4E0B\u5168\u90E8 Google \u8D26\u6237"
|
|
109646
|
-
).option("--date <YYYY-MM-DD>", "\u7EDF\u8BA1\u65E5\uFF08Asia/Shanghai \u9ED8\u8BA4\u4ECA\u5929\uFF09\uFF1B\u5F3A\u5236 start=end=\u8BE5\u65E5").option("--ratio <n>", "\u9608\u503C\u7CFB\u6570\uFF1Aspend >= budget * ratio\uFF08\u9ED8\u8BA4 1.1\uFF09", (v) => parseFloat(v)).option("--status <statusV2>", "\u53EA\u68C0\u67E5\u8BE5\u72B6\u6001\u7684\u7CFB\u5217\uFF08\u9ED8\u8BA4 Enabled\uFF1B\u4F20 * \u8868\u793A\u4E0D\u8FC7\u6EE4\uFF09", "Enabled").option("--page-size <n>", "\u8D26\u6237\u6E05\u5355\u5206\u9875\u5927\u5C0F\uFF08\u9ED8\u8BA4 200\uFF09", (v) => parseInt(v, 10)).option("--max-pages <n>", "\u6700\u591A\u626B\u63CF\u9875\u6570\uFF08\u9ED8\u8BA4 20\uFF09", (v) => parseInt(v, 10)).option("-t, --token <token>", "Token\uFF08\u53EF\u9009\uFF09").option(
|
|
109805
|
+
).option("--date <YYYY-MM-DD>", "\u7EDF\u8BA1\u65E5\uFF08Asia/Shanghai \u9ED8\u8BA4\u4ECA\u5929\uFF09\uFF1B\u5F3A\u5236 start=end=\u8BE5\u65E5").option("--ratio <n>", "\u9608\u503C\u7CFB\u6570\uFF1Aspend >= budget * ratio\uFF08\u9ED8\u8BA4 1.1\uFF09", (v) => parseFloat(v)).option("--status <statusV2>", "\u53EA\u68C0\u67E5\u8BE5\u72B6\u6001\u7684\u7CFB\u5217\uFF08\u9ED8\u8BA4 Enabled\uFF1B\u4F20 * \u8868\u793A\u4E0D\u8FC7\u6EE4\uFF09", "Enabled").option("--page-size <n>", "\u8D26\u6237\u6E05\u5355\u5206\u9875\u5927\u5C0F\uFF08\u9ED8\u8BA4 200\uFF09", (v) => parseInt(v, 10)).option("--login-customer-id <id>", LOGIN_CUSTOMER_ID_OPTION_HELP).option("--max-pages <n>", "\u6700\u591A\u626B\u63CF\u9875\u6570\uFF08\u9ED8\u8BA4 20\uFF09", (v) => parseInt(v, 10)).option("-t, --token <token>", "Token\uFF08\u53EF\u9009\uFF09").option(
|
|
109647
109806
|
"--json-out <path>",
|
|
109648
109807
|
"\u843D\u76D8\u76EE\u5F55\u6216 *.json\uFF1Bstdout \u4E00\u884C\u6458\u8981\uFF1B\u4EBA\u7C7B\u53EF\u8BFB\u8868\u59CB\u7EC8\u6253\u5370",
|
|
109649
109808
|
void 0
|
|
@@ -109660,7 +109819,8 @@ function register11(program2) {
|
|
|
109660
109819
|
token: opts.token,
|
|
109661
109820
|
jsonOut: opts.jsonOut,
|
|
109662
109821
|
refreshDp: opts.refreshDp,
|
|
109663
|
-
verbose: opts.verbose
|
|
109822
|
+
verbose: opts.verbose,
|
|
109823
|
+
loginCustomerId: opts.loginCustomerId
|
|
109664
109824
|
});
|
|
109665
109825
|
}
|
|
109666
109826
|
);
|
|
@@ -109673,7 +109833,7 @@ function register11(program2) {
|
|
|
109673
109833
|
"--fallback-target-cpa <yuan>",
|
|
109674
109834
|
"\u7EC4\u65E0 targetCpa\uFF08\u6216\u521B\u610F\u7EF4\uFF09\u65F6\u4F7F\u7528\u7684\u76EE\u6807 CPA\uFF08\u5143\uFF09",
|
|
109675
109835
|
(v) => parseFloat(v)
|
|
109676
|
-
).option("--page-size <n>", "\u8D26\u6237\u6E05\u5355\u5206\u9875\u5927\u5C0F\uFF08\u9ED8\u8BA4 200\uFF09", (v) => parseInt(v, 10)).option("--max-pages <n>", "\u6700\u591A\u626B\u63CF\u9875\u6570\uFF08\u9ED8\u8BA4 20\uFF09", (v) => parseInt(v, 10)).option("-t, --token <token>", "Token\uFF08\u53EF\u9009\uFF09").option("--json-out <path>", "\u843D\u76D8\u76EE\u5F55\u6216 *.json", void 0).option("--refresh-dp", "\u5F3A\u5236\u91CD\u62C9 Datapermission", false).option("--verbose", "\u8BE6\u7EC6\u9519\u8BEF", false).action(
|
|
109836
|
+
).option("--page-size <n>", "\u8D26\u6237\u6E05\u5355\u5206\u9875\u5927\u5C0F\uFF08\u9ED8\u8BA4 200\uFF09", (v) => parseInt(v, 10)).option("--login-customer-id <id>", LOGIN_CUSTOMER_ID_OPTION_HELP).option("--max-pages <n>", "\u6700\u591A\u626B\u63CF\u9875\u6570\uFF08\u9ED8\u8BA4 20\uFF09", (v) => parseInt(v, 10)).option("-t, --token <token>", "Token\uFF08\u53EF\u9009\uFF09").option("--json-out <path>", "\u843D\u76D8\u76EE\u5F55\u6216 *.json", void 0).option("--refresh-dp", "\u5F3A\u5236\u91CD\u62C9 Datapermission", false).option("--verbose", "\u8BE6\u7EC6\u9519\u8BEF", false).action(
|
|
109677
109837
|
async (opts) => {
|
|
109678
109838
|
await runZeroConv({
|
|
109679
109839
|
media: opts.media,
|
|
@@ -109687,7 +109847,8 @@ function register11(program2) {
|
|
|
109687
109847
|
token: opts.token,
|
|
109688
109848
|
jsonOut: opts.jsonOut,
|
|
109689
109849
|
refreshDp: opts.refreshDp,
|
|
109690
|
-
verbose: opts.verbose
|
|
109850
|
+
verbose: opts.verbose,
|
|
109851
|
+
loginCustomerId: opts.loginCustomerId
|
|
109691
109852
|
});
|
|
109692
109853
|
}
|
|
109693
109854
|
);
|
|
@@ -111448,10 +111609,10 @@ async function runInvoiceBillable(opts) {
|
|
|
111448
111609
|
})) {
|
|
111449
111610
|
return;
|
|
111450
111611
|
}
|
|
111451
|
-
const
|
|
111612
|
+
const label2 = opts.wallet ? "\u94B1\u5305\u53EF\u5F00\u7968\u8BB0\u5F55" : "\u5145\u503C\u53EF\u5F00\u7968\u8BA2\u5355";
|
|
111452
111613
|
console.log(
|
|
111453
111614
|
`
|
|
111454
|
-
${
|
|
111615
|
+
${label2}\uFF08\u7B2C ${page}/${Math.max(1, Math.ceil(total / pageSize))} \u9875\uFF0C\u672C\u9875 ${items3.length} \u6761\uFF0C\u5171 ${total} \u6761\uFF09
|
|
111455
111616
|
`
|
|
111456
111617
|
);
|
|
111457
111618
|
if (items3.length === 0) {
|
|
@@ -113596,7 +113757,7 @@ async function runAdKeywords(opts) {
|
|
|
113596
113757
|
if (key !== void 0) seen.add(key);
|
|
113597
113758
|
return true;
|
|
113598
113759
|
});
|
|
113599
|
-
const
|
|
113760
|
+
const label2 = opts.negative ? "\u5426\u5B9A\u5173\u952E\u8BCD" : "\u5173\u952E\u8BCD";
|
|
113600
113761
|
const n = items3.length;
|
|
113601
113762
|
const displayItems = opts.negative ? items3 : items3.map((row) => keywordRowToYuan(row));
|
|
113602
113763
|
const kwPayload = stripLegacyGoogleFieldsIfV2Present(
|
|
@@ -113613,7 +113774,7 @@ async function runAdKeywords(opts) {
|
|
|
113613
113774
|
}
|
|
113614
113775
|
console.log(
|
|
113615
113776
|
`
|
|
113616
|
-
${
|
|
113777
|
+
${label2}\uFF08\u8D26\u6237\uFF1A${opts.account}\uFF0C\u7B2C 1 \u9875\uFF0C\u672C\u9875 ${items3.length} \u6761` + (rawItems.length !== items3.length ? `\uFF0C\u539F\u59CB ${rawItems.length} \u6761\u5DF2\u53BB\u91CD` : "") + `\uFF09
|
|
113617
113778
|
`
|
|
113618
113779
|
);
|
|
113619
113780
|
if (items3.length === 0) {
|
|
@@ -114665,9 +114826,9 @@ function warnPolicyRiskTerms(campaign, warnings) {
|
|
|
114665
114826
|
const groups = campaign["AdGroupsForBatchJob"];
|
|
114666
114827
|
if (!Array.isArray(groups)) return;
|
|
114667
114828
|
const hitsByLabel = /* @__PURE__ */ new Map();
|
|
114668
|
-
const add = (
|
|
114669
|
-
let set = hitsByLabel.get(
|
|
114670
|
-
if (!set) hitsByLabel.set(
|
|
114829
|
+
const add = (label2, text2) => {
|
|
114830
|
+
let set = hitsByLabel.get(label2);
|
|
114831
|
+
if (!set) hitsByLabel.set(label2, set = /* @__PURE__ */ new Set());
|
|
114671
114832
|
set.add(text2.trim());
|
|
114672
114833
|
};
|
|
114673
114834
|
for (const g of groups) {
|
|
@@ -114679,8 +114840,8 @@ function warnPolicyRiskTerms(campaign, warnings) {
|
|
|
114679
114840
|
if (!Array.isArray(texts)) continue;
|
|
114680
114841
|
for (const t of texts) {
|
|
114681
114842
|
if (typeof t !== "string") continue;
|
|
114682
|
-
const
|
|
114683
|
-
if (
|
|
114843
|
+
const label2 = matchRisk(t);
|
|
114844
|
+
if (label2) add(label2, t);
|
|
114684
114845
|
}
|
|
114685
114846
|
}
|
|
114686
114847
|
}
|
|
@@ -114689,16 +114850,16 @@ function warnPolicyRiskTerms(campaign, warnings) {
|
|
|
114689
114850
|
for (const ad of ads) {
|
|
114690
114851
|
if (!ad || typeof ad !== "object") continue;
|
|
114691
114852
|
for (const t of collectRsaTexts(ad)) {
|
|
114692
|
-
const
|
|
114693
|
-
if (
|
|
114853
|
+
const label2 = matchRisk(t);
|
|
114854
|
+
if (label2) add(label2, t);
|
|
114694
114855
|
}
|
|
114695
114856
|
}
|
|
114696
114857
|
}
|
|
114697
114858
|
}
|
|
114698
|
-
for (const [
|
|
114859
|
+
for (const [label2, set] of hitsByLabel) {
|
|
114699
114860
|
const sample = [...set].slice(0, 5).map((s) => `\u300C${s}\u300D`).join("\u3001");
|
|
114700
114861
|
warnings.push(
|
|
114701
|
-
`\u653F\u7B56\u98CE\u9669\u8BCD\u9762\uFF08${
|
|
114862
|
+
`\u653F\u7B56\u98CE\u9669\u8BCD\u9762\uFF08${label2}\uFF09\uFF1A${sample}${set.size > 5 ? ` \u7B49 ${set.size} \u6761` : ""}\uFF1B\u7F51\u5173\u65E0\u653F\u7B56\u9884\u68C0\uFF0C\u521B\u5EFA\u540E\u53EF\u80FD\u88AB PolicyViolation \u62D2\u7EDD\u2014\u2014\u521B\u5EFA\u524D\u5411\u7528\u6237\u8BF4\u660E\u98CE\u9669\uFF0C\u5FC5\u8981\u65F6\u6539\u5199\u6216\u5220\u9664`
|
|
114702
114863
|
);
|
|
114703
114864
|
}
|
|
114704
114865
|
}
|
|
@@ -114851,10 +115012,10 @@ function validateLocationsFidelity(cfg, campaign, errors) {
|
|
|
114851
115012
|
if (id === void 0 || id === null) continue;
|
|
114852
115013
|
const ti = targetedIdx.get(String(id).trim());
|
|
114853
115014
|
if (ti === void 0) continue;
|
|
114854
|
-
const
|
|
115015
|
+
const label2 = typeof names[ti] === "string" ? `\u300C${names[ti]}\u300D` : "";
|
|
114855
115016
|
pushErr2(
|
|
114856
115017
|
errors,
|
|
114857
|
-
`campaign.excludedLocations[${i}].id=${String(id)} \u540C\u65F6\u51FA\u73B0\u5728 targetedLocations[${ti}]${
|
|
115018
|
+
`campaign.excludedLocations[${i}].id=${String(id)} \u540C\u65F6\u51FA\u73B0\u5728 targetedLocations[${ti}]${label2}\uFF1B\u540C\u4E00\u5730\u57DF\u65E2\u6295\u653E\u53C8\u6392\u9664\u4F1A\u4F7F BatchJob \u62A5 campaign_criterion \u2026negative immutable\u3002\u591A\u4E3A geo resolve \u628A\u6B67\u4E49\u5730\u540D\uFF08\u5982\u300C\u521A\u679C\u300Dvs\u300C\u521A\u679C\u6C11\u4E3B\u5171\u548C\u56FD\u300D\uFF09\u89E3\u6790\u6210\u540C\u4E00 ID\uFF1A\u7528 ad geo search \u6838\u5BF9\u540E\u4FEE\u6B63\u8BE5\u6761\uFF0C\u52FF\u6574\u6279\u5220\u9664\u6392\u9664\u5730\u57DF`
|
|
114858
115019
|
);
|
|
114859
115020
|
}
|
|
114860
115021
|
}
|
|
@@ -114899,7 +115060,7 @@ function validateRsaDisplayPath(prefix, ad, errors, lengthViolations) {
|
|
|
114899
115060
|
`${prefix} \u68C0\u6D4B\u5230\u5C0F\u5199 path2="${String(ad["path2"])}"\uFF0C\u540E\u7AEF\u5951\u7EA6\u5B57\u6BB5\u4E3A Path2\uFF08PascalCase\uFF09\uFF0C\u5F53\u524D\u63D0\u4EA4\u4E0D\u4F1A\u751F\u6548`
|
|
114900
115061
|
);
|
|
114901
115062
|
}
|
|
114902
|
-
for (const [field,
|
|
115063
|
+
for (const [field, label2, example] of [
|
|
114903
115064
|
["Path1", "\u663E\u793A\u8DEF\u5F84\u7B2C 1 \u6BB5", '"Path1": "products"'],
|
|
114904
115065
|
["Path2", "\u663E\u793A\u8DEF\u5F84\u7B2C 2 \u6BB5", '"Path2": "steel"']
|
|
114905
115066
|
]) {
|
|
@@ -114907,7 +115068,7 @@ function validateRsaDisplayPath(prefix, ad, errors, lengthViolations) {
|
|
|
114907
115068
|
if (raw === void 0) {
|
|
114908
115069
|
pushErr2(
|
|
114909
115070
|
errors,
|
|
114910
|
-
`${prefix}.${field} \u5B57\u6BB5\u7F3A\u5931\uFF08RSA \u5FC5\u586B\uFF09\u3002${
|
|
115071
|
+
`${prefix}.${field} \u5B57\u6BB5\u7F3A\u5931\uFF08RSA \u5FC5\u586B\uFF09\u3002${label2}\uFF0C\u5C55\u793A\u4E3A finalUrl \u57DF\u540D\u540E\u7684\u8DEF\u5F84\u6BB5\uFF08\u226415 \u5B57\u7B26\uFF0CCJK \u6309 2 \u8BA1\uFF09\u3002${RSA_PATH_BACKEND_HINT}\u3002${jsonHint}\u3002\u793A\u4F8B\uFF1A${example}`
|
|
114911
115072
|
);
|
|
114912
115073
|
continue;
|
|
114913
115074
|
}
|
|
@@ -116253,7 +116414,7 @@ function validateRsaCliCopy(input) {
|
|
|
116253
116414
|
}
|
|
116254
116415
|
}
|
|
116255
116416
|
}
|
|
116256
|
-
for (const [
|
|
116417
|
+
for (const [label2, value] of [
|
|
116257
116418
|
["--path1", input.path1],
|
|
116258
116419
|
["--path2", input.path2]
|
|
116259
116420
|
]) {
|
|
@@ -116261,7 +116422,7 @@ function validateRsaCliCopy(input) {
|
|
|
116261
116422
|
const len = calcGoogleCharLength(value);
|
|
116262
116423
|
if (len > AD_CLI_PATH_MAX_CHARS) {
|
|
116263
116424
|
errors.push(
|
|
116264
|
-
`${
|
|
116425
|
+
`${label2} \u8D85\u8FC7 ${AD_CLI_PATH_MAX_CHARS} \u5B57\u7B26\uFF08\u5F53\u524D ${len}\uFF0CCJK \u8BA1 2\uFF09\uFF1A${JSON.stringify(value)}`
|
|
116265
116426
|
);
|
|
116266
116427
|
}
|
|
116267
116428
|
}
|
|
@@ -118013,9 +118174,9 @@ async function runAdGeoAdd(opts) {
|
|
|
118013
118174
|
`);
|
|
118014
118175
|
process.exit(1);
|
|
118015
118176
|
}
|
|
118016
|
-
const
|
|
118177
|
+
const label2 = opts.exclude ? "\u5DF2\u6392\u9664" : "\u5DF2\u6DFB\u52A0\u5B9A\u4F4D";
|
|
118017
118178
|
console.log(`
|
|
118018
|
-
\u2705 \u5730\u7406\u4F4D\u7F6E ${opts.locationId} ${
|
|
118179
|
+
\u2705 \u5730\u7406\u4F4D\u7F6E ${opts.locationId} ${label2}\uFF08\u5E7F\u544A\u7CFB\u5217\uFF1A${opts.campaignId}\uFF09
|
|
118019
118180
|
`);
|
|
118020
118181
|
}
|
|
118021
118182
|
async function runAdGeoRemove(opts) {
|
|
@@ -118273,7 +118434,7 @@ function buildBatchOperationSlots(cfg) {
|
|
|
118273
118434
|
const campaign = asRecord3(cfg.campaign) ?? {};
|
|
118274
118435
|
const names = Array.isArray(cfg.locations) ? cfg.locations : [];
|
|
118275
118436
|
const slots = [];
|
|
118276
|
-
const push = (kind, path55,
|
|
118437
|
+
const push = (kind, path55, label2) => slots.push({ index: slots.length, kind, path: path55, label: label2 });
|
|
118277
118438
|
push("campaign_budget", "campaign.Budget", "\u7CFB\u5217\u9884\u7B97");
|
|
118278
118439
|
push("campaign", "campaign.Name", `\u7CFB\u5217\u300C${pickText(campaign, "Name", "name") || "\u2014"}\u300D`);
|
|
118279
118440
|
pickArray(campaign, "targetedLocations", "TargetedLocations").forEach((loc, i) => {
|
|
@@ -118822,16 +118983,16 @@ function compareCampaignCreateToLive(cfg, campaignId, live, meta) {
|
|
|
118822
118983
|
summary: `RSA \u672A\u6BD4\u5BF9\uFF08\u7EC4\u7F3A\u5931\uFF09\uFF1AAdsForBatchJob[${ai}]`
|
|
118823
118984
|
});
|
|
118824
118985
|
for (const asset of rsaAssets) {
|
|
118825
|
-
const
|
|
118986
|
+
const label2 = asset.kind === "headline" ? "\u6807\u9898" : "\u63CF\u8FF0";
|
|
118826
118987
|
pushItem(items3, {
|
|
118827
118988
|
layer: "ad",
|
|
118828
118989
|
path: asset.path,
|
|
118829
118990
|
adGroupName: groupName,
|
|
118830
118991
|
adLabel,
|
|
118831
|
-
plannedContent: `${
|
|
118992
|
+
plannedContent: `${label2}: ${asset.text}`,
|
|
118832
118993
|
status: "skipped",
|
|
118833
118994
|
liveNote: "\u5E7F\u544A\u7EC4\u672A\u521B\u5EFA\uFF0C\u8DF3\u8FC7\u6587\u6848\u6BD4\u5BF9",
|
|
118834
|
-
summary: `RSA ${
|
|
118995
|
+
summary: `RSA ${label2}\u672A\u6BD4\u5BF9\uFF08\u7EC4\u7F3A\u5931\uFF09\uFF1A${asset.text}`
|
|
118835
118996
|
});
|
|
118836
118997
|
}
|
|
118837
118998
|
continue;
|
|
@@ -118851,7 +119012,7 @@ function compareCampaignCreateToLive(cfg, campaignId, live, meta) {
|
|
|
118851
119012
|
summary: `\u5E7F\u544A\u521B\u610F\u672A\u6821\u9A8C\uFF08\u7F3A\u5C11 headlinePart1\uFF09\uFF1AAdsForBatchJob[${ai}]`
|
|
118852
119013
|
});
|
|
118853
119014
|
for (const asset of rsaAssets) {
|
|
118854
|
-
const
|
|
119015
|
+
const label2 = asset.kind === "headline" ? "\u6807\u9898" : "\u63CF\u8FF0";
|
|
118855
119016
|
const pool = asset.kind === "headline" ? liveHeadlineSet : liveDescSet;
|
|
118856
119017
|
const found = livePoolHasText(pool, asset.text);
|
|
118857
119018
|
pushItem(items3, {
|
|
@@ -118859,10 +119020,10 @@ function compareCampaignCreateToLive(cfg, campaignId, live, meta) {
|
|
|
118859
119020
|
path: asset.path,
|
|
118860
119021
|
adGroupName: groupName,
|
|
118861
119022
|
adLabel,
|
|
118862
|
-
plannedContent: `${
|
|
119023
|
+
plannedContent: `${label2}: ${asset.text}`,
|
|
118863
119024
|
status: found ? "ok" : "missing",
|
|
118864
|
-
liveNote: found ? `\u5DF2\u5728\u5BF9\u5E94 RSA \u4E0A\u627E\u5230\u6B64${
|
|
118865
|
-
summary: found ? `RSA ${
|
|
119025
|
+
liveNote: found ? `\u5DF2\u5728\u5BF9\u5E94 RSA \u4E0A\u627E\u5230\u6B64${label2}` : `\u5BF9\u5E94 RSA \u672A\u89C1\u6B64${label2}`,
|
|
119026
|
+
summary: found ? `RSA ${label2}\u5DF2\u751F\u6548\uFF1A${asset.text}` : `RSA ${label2}\u672A\u751F\u6548\uFF1A${asset.text}`
|
|
118866
119027
|
});
|
|
118867
119028
|
}
|
|
118868
119029
|
continue;
|
|
@@ -118879,7 +119040,7 @@ function compareCampaignCreateToLive(cfg, campaignId, live, meta) {
|
|
|
118879
119040
|
summary: rsaFound ? `RSA \u5DF2\u521B\u5EFA\uFF08\u9996\u6761\u6807\u9898\u300C${primary}\u300D\uFF09` : `RSA \u672A\u521B\u5EFA\uFF08\u9996\u6761\u6807\u9898\u300C${primary}\u300D\u5728\u5BF9\u5E94\u5E7F\u544A\u4E0A\u672A\u627E\u5230\uFF09`
|
|
118880
119041
|
});
|
|
118881
119042
|
for (const asset of rsaAssets) {
|
|
118882
|
-
const
|
|
119043
|
+
const label2 = asset.kind === "headline" ? "\u6807\u9898" : "\u63CF\u8FF0";
|
|
118883
119044
|
const pool = asset.kind === "headline" ? liveHeadlineSet : liveDescSet;
|
|
118884
119045
|
const found = livePoolHasText(pool, asset.text);
|
|
118885
119046
|
pushItem(items3, {
|
|
@@ -118887,10 +119048,10 @@ function compareCampaignCreateToLive(cfg, campaignId, live, meta) {
|
|
|
118887
119048
|
path: asset.path,
|
|
118888
119049
|
adGroupName: groupName,
|
|
118889
119050
|
adLabel,
|
|
118890
|
-
plannedContent: `${
|
|
119051
|
+
plannedContent: `${label2}: ${asset.text}`,
|
|
118891
119052
|
status: found ? "ok" : "missing",
|
|
118892
|
-
liveNote: found ? `\u5DF2\u5728\u5BF9\u5E94 RSA \u4E0A\u627E\u5230\u6B64${
|
|
118893
|
-
summary: found ? `RSA ${
|
|
119053
|
+
liveNote: found ? `\u5DF2\u5728\u5BF9\u5E94 RSA \u4E0A\u627E\u5230\u6B64${label2}` : `\u5BF9\u5E94 RSA \u672A\u89C1\u6B64${label2}\uFF08\u8BE5\u5E7F\u544A\u6587\u6848 ${pool.size} \u6761\uFF09`,
|
|
119054
|
+
summary: found ? `RSA ${label2}\u5DF2\u751F\u6548\uFF1A${asset.text}` : `RSA ${label2}\u672A\u751F\u6548\uFF1A${asset.text}`
|
|
118894
119055
|
});
|
|
118895
119056
|
}
|
|
118896
119057
|
}
|
|
@@ -120256,7 +120417,7 @@ function normalizeBidding(raw) {
|
|
|
120256
120417
|
};
|
|
120257
120418
|
return byNum[n] ?? null;
|
|
120258
120419
|
}
|
|
120259
|
-
function validateTextLengths(errors, lengthViolations, texts, arrayField, kind, limit,
|
|
120420
|
+
function validateTextLengths(errors, lengthViolations, texts, arrayField, kind, limit, label2) {
|
|
120260
120421
|
texts.forEach((text2, i) => {
|
|
120261
120422
|
const len = calcGoogleCharLength(text2);
|
|
120262
120423
|
if (len > limit) {
|
|
@@ -120270,7 +120431,7 @@ function validateTextLengths(errors, lengthViolations, texts, arrayField, kind,
|
|
|
120270
120431
|
countMode: "google",
|
|
120271
120432
|
text: text2
|
|
120272
120433
|
});
|
|
120273
|
-
pushErr3(errors, `${
|
|
120434
|
+
pushErr3(errors, `${label2}[${i}] \u8D85\u8FC7 ${limit} \u5B57\u7B26\uFF08\u5F53\u524D ${len}\uFF0CCJK \u8BA1 2\uFF09\uFF1A"${text2}"`);
|
|
120274
120435
|
}
|
|
120275
120436
|
});
|
|
120276
120437
|
}
|
|
@@ -120597,7 +120758,7 @@ function resolveImagePath(configFile, relOrAbs) {
|
|
|
120597
120758
|
}
|
|
120598
120759
|
function checkSpec(spec, width, height, fileSizeKB, errors, warnings) {
|
|
120599
120760
|
const {
|
|
120600
|
-
label,
|
|
120761
|
+
label: label2,
|
|
120601
120762
|
ratio,
|
|
120602
120763
|
ratioPct,
|
|
120603
120764
|
minWidth,
|
|
@@ -120610,19 +120771,19 @@ function checkSpec(spec, width, height, fileSizeKB, errors, warnings) {
|
|
|
120610
120771
|
const ratioOk = Math.abs(actualRatio - ratio) <= ratio * ratioPct;
|
|
120611
120772
|
if (!ratioOk) {
|
|
120612
120773
|
errors.push(
|
|
120613
|
-
`${
|
|
120774
|
+
`${label2}\uFF1A\u5BBD\u9AD8\u6BD4 ${width}\xD7${height}\uFF08${actualRatio.toFixed(3)}\uFF09\u504F\u79BB\u76EE\u6807 ${ratio}\uFF0C\u8D85\u51FA \xB1${(ratioPct * 100).toFixed(0)}% \u5BB9\u5DEE`
|
|
120614
120775
|
);
|
|
120615
120776
|
}
|
|
120616
120777
|
if (width < minWidth || height < minHeight) {
|
|
120617
|
-
errors.push(`${
|
|
120778
|
+
errors.push(`${label2}\uFF1A\u5C3A\u5BF8 ${width}\xD7${height} \u4F4E\u4E8E Google \u6700\u5C0F\u8981\u6C42 ${minWidth}\xD7${minHeight}`);
|
|
120618
120779
|
} else if (width < recommendedWidth || height < recommendedHeight) {
|
|
120619
120780
|
warnings.push(
|
|
120620
|
-
`${
|
|
120781
|
+
`${label2}\uFF1A\u5C3A\u5BF8 ${width}\xD7${height} \u4F4E\u4E8E\u63A8\u8350\u5C3A\u5BF8 ${recommendedWidth}\xD7${recommendedHeight}\uFF0C\u53EF\u80FD\u5F71\u54CD\u5C55\u793A\u6548\u679C`
|
|
120621
120782
|
);
|
|
120622
120783
|
}
|
|
120623
120784
|
if (fileSizeKB > maxFileSizeKB) {
|
|
120624
120785
|
errors.push(
|
|
120625
|
-
`${
|
|
120786
|
+
`${label2}\uFF1A\u6587\u4EF6\u5927\u5C0F ${fileSizeKB.toFixed(0)} KB \u8D85\u8FC7 Google \u4E0A\u9650 ${maxFileSizeKB} KB`
|
|
120626
120787
|
);
|
|
120627
120788
|
}
|
|
120628
120789
|
}
|
|
@@ -121269,9 +121430,9 @@ async function attachPmaxCampaignExtensions(opts) {
|
|
|
121269
121430
|
const header = s?.header?.trim();
|
|
121270
121431
|
const values = (s?.values ?? []).map((v) => v?.trim()).filter(Boolean);
|
|
121271
121432
|
if (!header || values.length < 3) continue;
|
|
121272
|
-
const
|
|
121433
|
+
const label2 = `${header}: ${values.join(", ")}`;
|
|
121273
121434
|
if (opts.logProgress) console.log(`
|
|
121274
|
-
\u6302\u8F7D\u7ED3\u6784\u5316\u6458\u8981\uFF1A${
|
|
121435
|
+
\u6302\u8F7D\u7ED3\u6784\u5316\u6458\u8981\uFF1A${label2}`);
|
|
121275
121436
|
const posted = await postExtension(
|
|
121276
121437
|
opts.config,
|
|
121277
121438
|
opts.googleApiUrl,
|
|
@@ -121283,11 +121444,11 @@ async function attachPmaxCampaignExtensions(opts) {
|
|
|
121283
121444
|
result.structuredSnippets.push({
|
|
121284
121445
|
ok: true,
|
|
121285
121446
|
id: String(posted.data["id"] ?? ""),
|
|
121286
|
-
label
|
|
121447
|
+
label: label2
|
|
121287
121448
|
});
|
|
121288
121449
|
} else {
|
|
121289
121450
|
result.allOk = false;
|
|
121290
|
-
result.structuredSnippets.push({ ok: false, error: posted.error, label });
|
|
121451
|
+
result.structuredSnippets.push({ ok: false, error: posted.error, label: label2 });
|
|
121291
121452
|
}
|
|
121292
121453
|
}
|
|
121293
121454
|
for (const link of ext.sitelinks ?? []) {
|
|
@@ -121337,9 +121498,9 @@ async function attachPmaxCampaignExtensions(opts) {
|
|
|
121337
121498
|
}
|
|
121338
121499
|
}
|
|
121339
121500
|
if (ext.businessMessage) {
|
|
121340
|
-
const
|
|
121501
|
+
const label2 = ext.businessMessage.starterMessage?.trim().slice(0, 40) || "WhatsApp";
|
|
121341
121502
|
if (opts.logProgress) console.log(`
|
|
121342
|
-
\u6302\u8F7D WhatsApp \u79C1\u4FE1\uFF1A${
|
|
121503
|
+
\u6302\u8F7D WhatsApp \u79C1\u4FE1\uFF1A${label2}`);
|
|
121343
121504
|
const posted = await postExtension(
|
|
121344
121505
|
opts.config,
|
|
121345
121506
|
opts.googleApiUrl,
|
|
@@ -121351,11 +121512,11 @@ async function attachPmaxCampaignExtensions(opts) {
|
|
|
121351
121512
|
result.whatsapp = {
|
|
121352
121513
|
ok: true,
|
|
121353
121514
|
id: String(posted.data["id"] ?? ""),
|
|
121354
|
-
label
|
|
121515
|
+
label: label2
|
|
121355
121516
|
};
|
|
121356
121517
|
} else {
|
|
121357
121518
|
result.allOk = false;
|
|
121358
|
-
result.whatsapp = { ok: false, error: posted.error, label };
|
|
121519
|
+
result.whatsapp = { ok: false, error: posted.error, label: label2 };
|
|
121359
121520
|
}
|
|
121360
121521
|
}
|
|
121361
121522
|
return result;
|
|
@@ -121674,8 +121835,8 @@ async function emitPmaxResult(opts, section, commandLabel, payload, idSuffix) {
|
|
|
121674
121835
|
idSuffix: idSuffix ?? opts.account
|
|
121675
121836
|
});
|
|
121676
121837
|
}
|
|
121677
|
-
function requireAccountId(account,
|
|
121678
|
-
return resolveAdAccountId(account,
|
|
121838
|
+
function requireAccountId(account, label2 = "-a, --account") {
|
|
121839
|
+
return resolveAdAccountId(account, label2);
|
|
121679
121840
|
}
|
|
121680
121841
|
|
|
121681
121842
|
// src/commands/ad/pmax-video-upload.ts
|
|
@@ -125469,15 +125630,15 @@ init_cli_json_snapshot();
|
|
|
125469
125630
|
function hasBudget(daily, lifetime) {
|
|
125470
125631
|
return daily != null || lifetime != null;
|
|
125471
125632
|
}
|
|
125472
|
-
function pushBudgetPairErrors(errors,
|
|
125633
|
+
function pushBudgetPairErrors(errors, label2, daily, lifetime) {
|
|
125473
125634
|
if (daily != null && lifetime != null) {
|
|
125474
|
-
errors.push(`${
|
|
125635
|
+
errors.push(`${label2} \u4E0D\u80FD\u540C\u65F6\u586B dailyBudget \u4E0E lifetimeBudget`);
|
|
125475
125636
|
}
|
|
125476
125637
|
if (daily != null && !(Number.isFinite(daily) && daily > 0)) {
|
|
125477
|
-
errors.push(`${
|
|
125638
|
+
errors.push(`${label2}.dailyBudget \u987B\u4E3A\u5927\u4E8E 0 \u7684\u6570\u5B57\uFF08\u4E3B\u5E01\u79CD\u5143\uFF09`);
|
|
125478
125639
|
}
|
|
125479
125640
|
if (lifetime != null && !(Number.isFinite(lifetime) && lifetime > 0)) {
|
|
125480
|
-
errors.push(`${
|
|
125641
|
+
errors.push(`${label2}.lifetimeBudget \u987B\u4E3A\u5927\u4E8E 0 \u7684\u6570\u5B57\uFF08\u4E3B\u5E01\u79CD\u5143\uFF09`);
|
|
125481
125642
|
}
|
|
125482
125643
|
}
|
|
125483
125644
|
function runMetaLeadValidation(cfg) {
|
|
@@ -125613,16 +125774,16 @@ function runMetaLeadValidation(cfg) {
|
|
|
125613
125774
|
);
|
|
125614
125775
|
}
|
|
125615
125776
|
const createStatuses = ["ACTIVE", "PAUSED", void 0, ""];
|
|
125616
|
-
for (const [
|
|
125777
|
+
for (const [label2, status] of [
|
|
125617
125778
|
["campaign.status", campaign.status],
|
|
125618
125779
|
["adset.status", adset.status],
|
|
125619
125780
|
["ad.status", ad.status]
|
|
125620
125781
|
]) {
|
|
125621
125782
|
if (status && !createStatuses.includes(status.trim().toUpperCase())) {
|
|
125622
|
-
errors.push(`${
|
|
125783
|
+
errors.push(`${label2} \u521B\u5EFA\u65F6\u53EA\u5141\u8BB8 ACTIVE / PAUSED\uFF08\u7F3A\u7701 PAUSED\uFF09`);
|
|
125623
125784
|
}
|
|
125624
125785
|
if (status && status.trim().toUpperCase() === "ACTIVE") {
|
|
125625
|
-
warnings.push(`${
|
|
125786
|
+
warnings.push(`${label2}=ACTIVE \u4F1A\u5728\u521B\u5EFA\u65F6\u5C1D\u8BD5\u6295\u653E\uFF1B\u5EFA\u8BAE\u7701\u7565\uFF0C\u9ED8\u8BA4 PAUSED\uFF0C\u786E\u8BA4\u540E\u518D\u6539\u72B6\u6001`);
|
|
125626
125787
|
}
|
|
125627
125788
|
}
|
|
125628
125789
|
const plan = cfg.plan;
|
|
@@ -126304,8 +126465,8 @@ function writeOpsExcel(outPath, cfg) {
|
|
|
126304
126465
|
["\u8BA4\u8BC1\u8D44\u8D28", text(plan.certifications), "B2B\u4FE1\u4EFB\u4FE1\u53F7"],
|
|
126305
126466
|
["\u6838\u5FC3\u5356\u70B9", text(plan.sellingPoints || endorsementText(plan)), "\u5DEE\u5F02\u5316\u4F18\u52BF"]
|
|
126306
126467
|
];
|
|
126307
|
-
for (const [
|
|
126308
|
-
profile.dataRow([
|
|
126468
|
+
for (const [label2, value, note] of profileRows) {
|
|
126469
|
+
profile.dataRow([label2, value, note || "", ""], { labelColumns: [0] });
|
|
126309
126470
|
}
|
|
126310
126471
|
profile.blankRow();
|
|
126311
126472
|
profile.sectionBar("\u5E94\u7528\u884C\u4E1A / \u5174\u8DA3\uFF08\u82F1\u6587\u5B9A\u5411\u8BCD\uFF09", { fill: OPS.section });
|
|
@@ -130432,10 +130593,10 @@ function buildBingIndustryOptions(records) {
|
|
|
130432
130593
|
const groups = [];
|
|
130433
130594
|
for (const [parentKey, children] of byParent) {
|
|
130434
130595
|
const parent = parentKey === ORPHAN_PARENT_KEY ? null : byId.get(parentKey);
|
|
130435
|
-
const
|
|
130596
|
+
const label2 = parent?.TranslationLanguage || parent?.name || (parentKey === ORPHAN_PARENT_KEY ? "\u2014" : parentKey);
|
|
130436
130597
|
groups.push({
|
|
130437
130598
|
parentId: parentKey === ORPHAN_PARENT_KEY ? "" : parentKey,
|
|
130438
|
-
label,
|
|
130599
|
+
label: label2,
|
|
130439
130600
|
children: [...children].sort(cmpCode)
|
|
130440
130601
|
});
|
|
130441
130602
|
}
|
|
@@ -130449,10 +130610,10 @@ function buildBingIndustryOptions(records) {
|
|
|
130449
130610
|
for (const g of groups) {
|
|
130450
130611
|
for (const row of g.children) {
|
|
130451
130612
|
const id = String(row.id ?? "");
|
|
130452
|
-
const
|
|
130613
|
+
const label2 = String(row.TranslationLanguage || row.name || id);
|
|
130453
130614
|
out.push({
|
|
130454
130615
|
id,
|
|
130455
|
-
label,
|
|
130616
|
+
label: label2,
|
|
130456
130617
|
group: g.label,
|
|
130457
130618
|
name: String(row.name ?? "")
|
|
130458
130619
|
});
|
|
@@ -130715,8 +130876,8 @@ async function runOpenAccountGoogleTimezones(opts) {
|
|
|
130715
130876
|
const code = String(r.Code ?? "").toLowerCase();
|
|
130716
130877
|
const name2 = String(r.Name ?? "").toLowerCase();
|
|
130717
130878
|
const time = String(r.Time ?? "").toLowerCase();
|
|
130718
|
-
const
|
|
130719
|
-
return code.includes(kw) || name2.includes(kw) || time.includes(kw) ||
|
|
130879
|
+
const label2 = `(${r.Time ?? ""})${r.Name ?? ""}`.toLowerCase();
|
|
130880
|
+
return code.includes(kw) || name2.includes(kw) || time.includes(kw) || label2.includes(kw);
|
|
130720
130881
|
});
|
|
130721
130882
|
}
|
|
130722
130883
|
const n = rows.length;
|
|
@@ -130753,11 +130914,11 @@ Google \u5F00\u6237\u53EF\u9009\u65F6\u533A\uFF08\u4E0E\u7F51\u9875 /openAnAccou
|
|
|
130753
130914
|
{ key: "label", header: "\u5C55\u793A\uFF08\u4E0E\u7F51\u9875\u76F8\u540C\uFF09" }
|
|
130754
130915
|
];
|
|
130755
130916
|
const tableRows = rows.map((r, i) => {
|
|
130756
|
-
const
|
|
130917
|
+
const label2 = `(${r.Time ?? ""})${r.Name ?? ""}`;
|
|
130757
130918
|
return {
|
|
130758
130919
|
idx: String(i + 1),
|
|
130759
130920
|
code: String(r.Code ?? "").slice(0, codeW),
|
|
130760
|
-
label:
|
|
130921
|
+
label: label2.slice(0, labelW)
|
|
130761
130922
|
};
|
|
130762
130923
|
});
|
|
130763
130924
|
printCliTable(tableRows, cols);
|
|
@@ -132613,7 +132774,7 @@ async function runMarketAnalysisCollect(opts) {
|
|
|
132613
132774
|
websiteError = err instanceof Error ? err.message : String(err);
|
|
132614
132775
|
}
|
|
132615
132776
|
}
|
|
132616
|
-
const
|
|
132777
|
+
const label2 = normalized.customerName?.trim() || normalized.website?.trim() || normalized.industry?.trim() || normalized.coreProducts?.trim() || "market";
|
|
132617
132778
|
const payload = {
|
|
132618
132779
|
customerInfo: normalized,
|
|
132619
132780
|
targetMarket: normalized.targetMarket,
|
|
@@ -132629,7 +132790,7 @@ async function runMarketAnalysisCollect(opts) {
|
|
|
132629
132790
|
{
|
|
132630
132791
|
section: "market-analysis-collect",
|
|
132631
132792
|
commandLabel: "market-analysis collect",
|
|
132632
|
-
commandHint:
|
|
132793
|
+
commandHint: label2,
|
|
132633
132794
|
payload
|
|
132634
132795
|
}
|
|
132635
132796
|
)) {
|
|
@@ -133602,7 +133763,7 @@ function buildComparisonItems(currentRows, previousRows, titleFn, keyFn) {
|
|
|
133602
133763
|
(row) => toKeyMetricRow(titleFn(row), row, prevMap.get(keyFn(row)) ?? null)
|
|
133603
133764
|
);
|
|
133604
133765
|
}
|
|
133605
|
-
function toTargetingItem(row, labelKey,
|
|
133766
|
+
function toTargetingItem(row, labelKey, label2) {
|
|
133606
133767
|
const cost = rowCost(row);
|
|
133607
133768
|
const clicks = num(row.clicks);
|
|
133608
133769
|
const impressions = num(row.impressions);
|
|
@@ -133612,7 +133773,7 @@ function toTargetingItem(row, labelKey, label) {
|
|
|
133612
133773
|
const cpc = num(row.averageCpc ?? row.cpc);
|
|
133613
133774
|
const cpa = conversions > 0 ? cost / conversions : num(row.costPerConversion ?? row.cpa);
|
|
133614
133775
|
return {
|
|
133615
|
-
[labelKey]:
|
|
133776
|
+
[labelKey]: label2,
|
|
133616
133777
|
cost,
|
|
133617
133778
|
impressions,
|
|
133618
133779
|
clicks,
|
|
@@ -135814,8 +135975,8 @@ function matchConversionAction(actions, name2) {
|
|
|
135814
135975
|
const needle = name2.trim().toLowerCase();
|
|
135815
135976
|
if (!needle) return null;
|
|
135816
135977
|
const hit = actions.find((row) => {
|
|
135817
|
-
const
|
|
135818
|
-
return
|
|
135978
|
+
const label2 = String(row.name ?? row.conversionAction ?? row.id ?? "").toLowerCase();
|
|
135979
|
+
return label2.includes(needle);
|
|
135819
135980
|
});
|
|
135820
135981
|
if (!hit) return null;
|
|
135821
135982
|
const n = num2(hit.conversions ?? hit.conversionsValue ?? hit.allConversions);
|
|
@@ -136110,9 +136271,9 @@ async function runGoogleQuarterlyCollect(opts) {
|
|
|
136110
136271
|
const snapDir = path29.resolve(opts.jsonOut);
|
|
136111
136272
|
await fs25.mkdir(snapDir, { recursive: true });
|
|
136112
136273
|
let degraded = false;
|
|
136113
|
-
const run = (
|
|
136274
|
+
const run = (label2, start, end, sections) => {
|
|
136114
136275
|
console.error(`
|
|
136115
|
-
\u{1F4E5} ${
|
|
136276
|
+
\u{1F4E5} ${label2}\uFF1A${start} ~ ${end}\uFF08${sections}\uFF09
|
|
136116
136277
|
`);
|
|
136117
136278
|
const result = invokeGoogleAnalysisCli({
|
|
136118
136279
|
account: accountId,
|
|
@@ -136126,14 +136287,14 @@ async function runGoogleQuarterlyCollect(opts) {
|
|
|
136126
136287
|
if (!result.ok && result.status !== 2) {
|
|
136127
136288
|
console.error(result.stderr || result.stdout);
|
|
136128
136289
|
console.error(`
|
|
136129
|
-
\u274C ${
|
|
136290
|
+
\u274C ${label2} \u62C9\u6570\u5931\u8D25\u3002
|
|
136130
136291
|
`);
|
|
136131
136292
|
return false;
|
|
136132
136293
|
}
|
|
136133
136294
|
if (!result.ok) {
|
|
136134
136295
|
console.error(result.stderr || result.stdout);
|
|
136135
136296
|
console.error(`
|
|
136136
|
-
\u26A0\uFE0F ${
|
|
136297
|
+
\u26A0\uFE0F ${label2} \u90E8\u5206\u7EF4\u5EA6\u5931\u8D25\uFF0C\u7EE7\u7EED\u805A\u5408\u3002
|
|
136137
136298
|
`);
|
|
136138
136299
|
degraded = true;
|
|
136139
136300
|
}
|
|
@@ -136822,10 +136983,10 @@ function estimateColWidths(rows) {
|
|
|
136822
136983
|
const colCount = rows.reduce((max, row) => Math.max(max, row.length), 0);
|
|
136823
136984
|
const widths = new Array(colCount).fill(MIN_COL_WIDTH);
|
|
136824
136985
|
for (const row of rows) {
|
|
136825
|
-
row.forEach((
|
|
136826
|
-
if (
|
|
136986
|
+
row.forEach((cell5, idx) => {
|
|
136987
|
+
if (cell5 == null) return;
|
|
136827
136988
|
const longestLine = Math.max(
|
|
136828
|
-
...String(
|
|
136989
|
+
...String(cell5).split("\n").map((l) => l.length)
|
|
136829
136990
|
);
|
|
136830
136991
|
const width = Math.min(MAX_COL_WIDTH, Math.max(MIN_COL_WIDTH, Math.ceil(longestLine * 1.3)));
|
|
136831
136992
|
if (width > widths[idx]) widths[idx] = width;
|
|
@@ -138211,10 +138372,10 @@ function sumActionArray(raw) {
|
|
|
138211
138372
|
}
|
|
138212
138373
|
|
|
138213
138374
|
// src/commands/facebook-analysis/entities.ts
|
|
138214
|
-
function fail(
|
|
138375
|
+
function fail(label2, err) {
|
|
138215
138376
|
const msg = err instanceof Error ? err.message : String(err);
|
|
138216
138377
|
console.error(`
|
|
138217
|
-
\u274C ${
|
|
138378
|
+
\u274C ${label2}\uFF1A${msg}
|
|
138218
138379
|
`);
|
|
138219
138380
|
process.exit(1);
|
|
138220
138381
|
}
|
|
@@ -138229,7 +138390,7 @@ function parseOptionalNumber2(raw) {
|
|
|
138229
138390
|
}
|
|
138230
138391
|
return n;
|
|
138231
138392
|
}
|
|
138232
|
-
function
|
|
138393
|
+
function cell3(value) {
|
|
138233
138394
|
return value == null || value === "" ? "" : String(value);
|
|
138234
138395
|
}
|
|
138235
138396
|
async function runFacebookAccountStatus(opts) {
|
|
@@ -138258,10 +138419,10 @@ Facebook \u8D26\u6237\u4FE1\u606F\uFF08${manifestId}\uFF09
|
|
|
138258
138419
|
printCliTable(
|
|
138259
138420
|
[
|
|
138260
138421
|
{
|
|
138261
|
-
id:
|
|
138262
|
-
status:
|
|
138263
|
-
disableReason:
|
|
138264
|
-
timezone:
|
|
138422
|
+
id: cell3(row.account_id ?? row.id ?? manifestId),
|
|
138423
|
+
status: cell3(row.account_status),
|
|
138424
|
+
disableReason: cell3(row.disable_reason),
|
|
138425
|
+
timezone: cell3(row.timezone_name),
|
|
138265
138426
|
currency,
|
|
138266
138427
|
balance: formatYuanDisplay(fromMinorUnitDisplay(row.balance, currency)),
|
|
138267
138428
|
spendCap: formatYuanDisplay(fromMinorUnitDisplay(row.spend_cap, currency)),
|
|
@@ -138342,13 +138503,13 @@ ${meta.title}\uFF08${manifestId}\uFF0C\u5171 ${result.items.length} \u6761\uFF09
|
|
|
138342
138503
|
if (kind === "campaigns") {
|
|
138343
138504
|
printCliTable(
|
|
138344
138505
|
result.items.map((r) => ({
|
|
138345
|
-
id:
|
|
138346
|
-
name:
|
|
138347
|
-
status:
|
|
138348
|
-
effective:
|
|
138349
|
-
dailyBudget:
|
|
138350
|
-
lifetimeBudget:
|
|
138351
|
-
bidStrategy:
|
|
138506
|
+
id: cell3(r.id),
|
|
138507
|
+
name: cell3(r.name),
|
|
138508
|
+
status: cell3(r.status),
|
|
138509
|
+
effective: cell3(r.effective_status),
|
|
138510
|
+
dailyBudget: cell3(r.daily_budget),
|
|
138511
|
+
lifetimeBudget: cell3(r.lifetime_budget),
|
|
138512
|
+
bidStrategy: cell3(r.bid_strategy)
|
|
138352
138513
|
})),
|
|
138353
138514
|
[
|
|
138354
138515
|
{ key: "id", header: "\u7CFB\u5217ID" },
|
|
@@ -138368,13 +138529,13 @@ ${meta.title}\uFF08${manifestId}\uFF0C\u5171 ${result.items.length} \u6761\uFF09
|
|
|
138368
138529
|
if (kind === "adsets") {
|
|
138369
138530
|
printCliTable(
|
|
138370
138531
|
result.items.map((r) => ({
|
|
138371
|
-
id:
|
|
138372
|
-
name:
|
|
138373
|
-
campaignId:
|
|
138374
|
-
status:
|
|
138375
|
-
dailyBudget:
|
|
138376
|
-
bidAmount:
|
|
138377
|
-
bidStrategy:
|
|
138532
|
+
id: cell3(r.id),
|
|
138533
|
+
name: cell3(r.name),
|
|
138534
|
+
campaignId: cell3(r.campaign_id),
|
|
138535
|
+
status: cell3(r.effective_status ?? r.status),
|
|
138536
|
+
dailyBudget: cell3(r.daily_budget),
|
|
138537
|
+
bidAmount: cell3(r.bid_amount),
|
|
138538
|
+
bidStrategy: cell3(r.bid_strategy)
|
|
138378
138539
|
})),
|
|
138379
138540
|
[
|
|
138380
138541
|
{ key: "id", header: "\u7EC4ID" },
|
|
@@ -138393,11 +138554,11 @@ ${meta.title}\uFF08${manifestId}\uFF0C\u5171 ${result.items.length} \u6761\uFF09
|
|
|
138393
138554
|
}
|
|
138394
138555
|
printCliTable(
|
|
138395
138556
|
result.items.map((r) => ({
|
|
138396
|
-
id:
|
|
138397
|
-
name:
|
|
138398
|
-
campaignId:
|
|
138399
|
-
adsetId:
|
|
138400
|
-
effective:
|
|
138557
|
+
id: cell3(r.id),
|
|
138558
|
+
name: cell3(r.name),
|
|
138559
|
+
campaignId: cell3(r.campaign_id),
|
|
138560
|
+
adsetId: cell3(r.adset_id),
|
|
138561
|
+
effective: cell3(r.effective_status),
|
|
138401
138562
|
landing: Array.isArray(r.landing_urls) ? r.landing_urls.join(" | ") : ""
|
|
138402
138563
|
})),
|
|
138403
138564
|
[
|
|
@@ -138487,15 +138648,15 @@ Facebook Insights ${level} ${startDate}~${endDate}\uFF08${manifestId}\uFF0C\u517
|
|
|
138487
138648
|
}
|
|
138488
138649
|
printCliTable(
|
|
138489
138650
|
items3.map((r) => ({
|
|
138490
|
-
objectId:
|
|
138491
|
-
name:
|
|
138492
|
-
date:
|
|
138493
|
-
hour:
|
|
138494
|
-
spend:
|
|
138495
|
-
clicks:
|
|
138496
|
-
impressions:
|
|
138497
|
-
ctr:
|
|
138498
|
-
conversions:
|
|
138651
|
+
objectId: cell3(r.ad_id ?? r.adset_id ?? r.campaign_id ?? r.account_id),
|
|
138652
|
+
name: cell3(r.ad_name ?? r.adset_name ?? r.campaign_name ?? r.account_name),
|
|
138653
|
+
date: cell3(r.date_start),
|
|
138654
|
+
hour: cell3(r.hourly_stats_aggregated_by_advertiser_time_zone),
|
|
138655
|
+
spend: cell3(r.spend),
|
|
138656
|
+
clicks: cell3(r.clicks),
|
|
138657
|
+
impressions: cell3(r.impressions),
|
|
138658
|
+
ctr: cell3(r.ctr),
|
|
138659
|
+
conversions: cell3(sumActionArray(r.conversions))
|
|
138499
138660
|
})),
|
|
138500
138661
|
[
|
|
138501
138662
|
{ key: "objectId", header: "\u5BF9\u8C61ID" },
|
|
@@ -141108,11 +141269,11 @@ function assertAdSecondaryStatusFilter(raw) {
|
|
|
141108
141269
|
}
|
|
141109
141270
|
return v;
|
|
141110
141271
|
}
|
|
141111
|
-
function unwrapTikTokEnvelope(raw,
|
|
141272
|
+
function unwrapTikTokEnvelope(raw, label2) {
|
|
141112
141273
|
const env = raw ?? {};
|
|
141113
141274
|
const code = env.code;
|
|
141114
141275
|
if (code !== 0 && code !== void 0) {
|
|
141115
|
-
throw new Error(`${
|
|
141276
|
+
throw new Error(`${label2} \u4E1A\u52A1\u5931\u8D25 code=${code}\uFF1A${env.message ?? "\u672A\u77E5\u9519\u8BEF"}`);
|
|
141116
141277
|
}
|
|
141117
141278
|
const list = Array.isArray(env.data?.list) ? env.data.list : [];
|
|
141118
141279
|
const info = env.data?.page_info ?? {};
|
|
@@ -141265,10 +141426,10 @@ async function fetchOfficialReport(config, opts) {
|
|
|
141265
141426
|
}
|
|
141266
141427
|
|
|
141267
141428
|
// src/commands/tiktok-analysis/entities.ts
|
|
141268
|
-
function fail2(
|
|
141429
|
+
function fail2(label2, err) {
|
|
141269
141430
|
const msg = err instanceof Error ? err.message : String(err);
|
|
141270
141431
|
console.error(`
|
|
141271
|
-
\u274C ${
|
|
141432
|
+
\u274C ${label2}\uFF1A${msg}
|
|
141272
141433
|
`);
|
|
141273
141434
|
process.exit(1);
|
|
141274
141435
|
}
|
|
@@ -142067,19 +142228,19 @@ function isoWeekKey(d) {
|
|
|
142067
142228
|
thursday.setDate(thursday.getDate() + 3);
|
|
142068
142229
|
const yearStart = new Date(thursday.getFullYear(), 0, 1);
|
|
142069
142230
|
const week = Math.floor((thursday.getTime() - yearStart.getTime()) / 864e5 / 7) + 1;
|
|
142070
|
-
const
|
|
142071
|
-
return { key: `${thursday.getFullYear()}-${
|
|
142231
|
+
const label2 = `W${String(week).padStart(2, "0")}`;
|
|
142232
|
+
return { key: `${thursday.getFullYear()}-${label2}`, label: label2, weekStart, weekEnd };
|
|
142072
142233
|
}
|
|
142073
142234
|
function aggregateDailyToWeekly(dailyRows) {
|
|
142074
142235
|
const map = /* @__PURE__ */ new Map();
|
|
142075
142236
|
for (const row of dailyRows) {
|
|
142076
142237
|
const d = parseYmd3(row.date);
|
|
142077
142238
|
if (!d) continue;
|
|
142078
|
-
const { key, label, weekStart, weekEnd } = isoWeekKey(d);
|
|
142239
|
+
const { key, label: label2, weekStart, weekEnd } = isoWeekKey(d);
|
|
142079
142240
|
let acc = map.get(key);
|
|
142080
142241
|
if (!acc) {
|
|
142081
142242
|
acc = {
|
|
142082
|
-
label,
|
|
142243
|
+
label: label2,
|
|
142083
142244
|
weekStart,
|
|
142084
142245
|
weekEnd,
|
|
142085
142246
|
days: 0,
|
|
@@ -142525,8 +142686,8 @@ function validateYandexPeriodReportContent(data) {
|
|
|
142525
142686
|
const tables = asRecord36(data.tables) ?? {};
|
|
142526
142687
|
const weeklyRows = asArray8(tables.weekly).map((r) => asRecord36(r)).filter((r) => r != null);
|
|
142527
142688
|
for (const [i, row] of weeklyRows.entries()) {
|
|
142528
|
-
const
|
|
142529
|
-
if (/nan/i.test(
|
|
142689
|
+
const label2 = `${row.weekLabel ?? ""} ${row.startDate ?? ""} ${row.endDate ?? ""}`;
|
|
142690
|
+
if (/nan/i.test(label2) || !normalizeYandexDailyDate(row.startDate) || !normalizeYandexDailyDate(row.endDate)) {
|
|
142530
142691
|
pushMissing7(
|
|
142531
142692
|
missing,
|
|
142532
142693
|
`tables-weekly-${i}`,
|
|
@@ -142845,14 +143006,14 @@ function asRecord38(raw) {
|
|
|
142845
143006
|
}
|
|
142846
143007
|
|
|
142847
143008
|
// src/commands/yandex-analysis/entities.ts
|
|
142848
|
-
function fail3(
|
|
143009
|
+
function fail3(label2, err) {
|
|
142849
143010
|
const msg = err instanceof Error ? err.message : String(err);
|
|
142850
143011
|
console.error(`
|
|
142851
|
-
\u274C ${
|
|
143012
|
+
\u274C ${label2}\uFF1A${msg}
|
|
142852
143013
|
`);
|
|
142853
143014
|
process.exit(1);
|
|
142854
143015
|
}
|
|
142855
|
-
function
|
|
143016
|
+
function cell4(value) {
|
|
142856
143017
|
if (value == null || value === "") return "";
|
|
142857
143018
|
if (Array.isArray(value)) return value.map((x) => String(x)).join(" | ");
|
|
142858
143019
|
return String(value);
|
|
@@ -142930,12 +143091,12 @@ async function runYandexAccountStatus(opts) {
|
|
|
142930
143091
|
footnote: "archived=true \u8868\u793A\u5E7F\u544A\u4E3B\u5DF2\u5F52\u6863\uFF08inactive\uFF09\u3002\u5B98\u65B9\u65E0\u5C01\u6237\u72B6\u6001\u4E0E\u539F\u56E0\u3002\u4F59\u989D\u770B balance / currency\uFF1B\u5B98\u65B9\u65E0\u72EC\u7ACB\u989D\u5EA6\u3002",
|
|
142931
143092
|
rows: [
|
|
142932
143093
|
{
|
|
142933
|
-
account:
|
|
142934
|
-
archived:
|
|
142935
|
-
balance:
|
|
142936
|
-
currency:
|
|
142937
|
-
spend:
|
|
142938
|
-
conversions:
|
|
143094
|
+
account: cell4(row.account ?? result.accountId),
|
|
143095
|
+
archived: cell4(row.archived),
|
|
143096
|
+
balance: cell4(row.balance),
|
|
143097
|
+
currency: cell4(row.currency),
|
|
143098
|
+
spend: cell4(row.spend),
|
|
143099
|
+
conversions: cell4(row.conversions)
|
|
142939
143100
|
}
|
|
142940
143101
|
],
|
|
142941
143102
|
columns: [
|
|
@@ -142971,15 +143132,15 @@ async function runYandexCampaignEntities(opts) {
|
|
|
142971
143132
|
empty: "\u5F53\u524D\u8FC7\u6EE4\u4E0B\u65E0\u7CFB\u5217\u884C\uFF08\u9ED8\u8BA4\u53EA\u51FA\u73B0\u6709\u6D88\u8017\u7684\u5BF9\u8C61\uFF09\u3002",
|
|
142972
143133
|
footnote: "\u9ED8\u8BA4 SEARCH\u3002\u5168\u6E20\u9053\u82B1\u8D39\u987B --network ALL\uFF08\u884C\u5185 network \u4E3A null\uFF09\u3002budget \u662F\u7CFB\u5217\u65E5\u9884\u7B97\uFF0C\u81EA\u52A8\u7B56\u7565\u5E38\u4E3A\u7A7A\uFF1B\u5BF9\u7167 weeklyBudget\u3002\u81EA\u52A8\u51FA\u4EF7\u4E0D\u8981\u5F53\u624B\u52A8 CPC \u6539\u4EF7\u3002",
|
|
142973
143134
|
rows: items3.map((r) => ({
|
|
142974
|
-
campaignId:
|
|
142975
|
-
name:
|
|
142976
|
-
spend:
|
|
142977
|
-
budget:
|
|
142978
|
-
weeklyBudget:
|
|
142979
|
-
strategy:
|
|
142980
|
-
targetCpa:
|
|
142981
|
-
status:
|
|
142982
|
-
date:
|
|
143135
|
+
campaignId: cell4(r.campaignId),
|
|
143136
|
+
name: cell4(r.campaignName),
|
|
143137
|
+
spend: cell4(r.spend),
|
|
143138
|
+
budget: cell4(r.budget),
|
|
143139
|
+
weeklyBudget: cell4(r.weeklyBudget),
|
|
143140
|
+
strategy: cell4(r.strategy),
|
|
143141
|
+
targetCpa: cell4(r.targetCpa),
|
|
143142
|
+
status: cell4(r.status),
|
|
143143
|
+
date: cell4(r.date)
|
|
142983
143144
|
})),
|
|
142984
143145
|
columns: [
|
|
142985
143146
|
{ key: "campaignId", header: "\u7CFB\u5217ID" },
|
|
@@ -143017,16 +143178,16 @@ async function runYandexAdGroupEntities(opts) {
|
|
|
143017
143178
|
empty: "\u5F53\u524D\u8FC7\u6EE4\u4E0B\u65E0\u5E7F\u544A\u7EC4\u884C\uFF08\u9ED8\u8BA4\u53EA\u51FA\u73B0\u6709\u6D88\u8017\u7684\u5BF9\u8C61\uFF09\u3002",
|
|
143018
143179
|
footnote: "campaignTargetCpa \u662F\u7CFB\u5217\u76EE\u6807\uFF08\u53EA\u53D6 Search\uFF09\uFF0C\u4E0D\u662F\u7EC4\u7EA7\u76EE\u6807\u4EF7\u3002conversions<=0 \u65F6\u4E0D\u8981\u5224 CPA\u3002\u672C\u6279\u6CA1\u6709\u6539\u4EF7\u63A5\u53E3\u3002",
|
|
143019
143180
|
rows: items3.map((r) => ({
|
|
143020
|
-
adGroupId:
|
|
143021
|
-
name:
|
|
143022
|
-
campaignId:
|
|
143023
|
-
spend:
|
|
143024
|
-
conversions:
|
|
143025
|
-
cpa:
|
|
143026
|
-
targetCpa:
|
|
143027
|
-
weeklyBudget:
|
|
143028
|
-
strategy:
|
|
143029
|
-
date:
|
|
143181
|
+
adGroupId: cell4(r.adGroupId),
|
|
143182
|
+
name: cell4(r.adGroupName),
|
|
143183
|
+
campaignId: cell4(r.campaignId),
|
|
143184
|
+
spend: cell4(r.spend),
|
|
143185
|
+
conversions: cell4(r.conversions),
|
|
143186
|
+
cpa: cell4(r.costPerConversion),
|
|
143187
|
+
targetCpa: cell4(r.campaignTargetCpa),
|
|
143188
|
+
weeklyBudget: cell4(r.campaignWeeklyBudget),
|
|
143189
|
+
strategy: cell4(r.campaignStrategy),
|
|
143190
|
+
date: cell4(r.date)
|
|
143030
143191
|
})),
|
|
143031
143192
|
columns: [
|
|
143032
143193
|
{ key: "adGroupId", header: "\u7EC4ID" },
|
|
@@ -143068,15 +143229,15 @@ async function runYandexAdEntities(opts) {
|
|
|
143068
143229
|
empty: filtered ? "\u5F53\u524D\u5BA1\u6838\u8FC7\u6EE4\u4E0B\u65E0\u8BB0\u5F55\uFF08\u7A7A\u5217\u8868=\u6210\u529F\u4E14\u6CA1\u6709\u672A\u5F52\u6863\u5339\u914D\u9879\uFF09\u3002" : "\u5F53\u524D\u8FC7\u6EE4\u4E0B\u65E0\u5E7F\u544A\u884C\uFF08\u9ED8\u8BA4\u53EA\u51FA\u73B0\u533A\u95F4\u5185\u6709\u6D88\u8017\u7684\u5E7F\u544A\uFF09\u3002",
|
|
143069
143230
|
footnote: "landingUrls \u7A7A\u6570\u7EC4\u4E0D\u662F\u6B7B\u94FE\uFF08Dynamic/Smart/Shopping \u6216\u4EC5 TurboPage \u5E38\u4E3A []\uFF09\u3002CLI \u4E0D\u63A2\u6D3B HTTP\u3002\u62D2\u5BA1\u7528 --status REJECTED\uFF08\u4E0E --time-increment \u4E92\u65A5\uFF1B\u5DF2\u5F52\u6863\u4E0D\u4F1A\u51FA\u73B0\uFF09\u3002",
|
|
143070
143231
|
rows: items3.map((r) => ({
|
|
143071
|
-
adId:
|
|
143072
|
-
campaignId:
|
|
143073
|
-
adGroupId:
|
|
143074
|
-
spend:
|
|
143075
|
-
conversions:
|
|
143076
|
-
ctr:
|
|
143077
|
-
roi:
|
|
143078
|
-
status:
|
|
143079
|
-
landing:
|
|
143232
|
+
adId: cell4(r.adId),
|
|
143233
|
+
campaignId: cell4(r.campaignId),
|
|
143234
|
+
adGroupId: cell4(r.adGroupId),
|
|
143235
|
+
spend: cell4(r.spend),
|
|
143236
|
+
conversions: cell4(r.conversions),
|
|
143237
|
+
ctr: cell4(r.ctr),
|
|
143238
|
+
roi: cell4(r.roi),
|
|
143239
|
+
status: cell4(r.status),
|
|
143240
|
+
landing: cell4(r.landingUrls)
|
|
143080
143241
|
})),
|
|
143081
143242
|
columns: [
|
|
143082
143243
|
{ key: "adId", header: "\u5E7F\u544AID" },
|
|
@@ -143119,17 +143280,17 @@ async function runYandexInsights(opts) {
|
|
|
143119
143280
|
empty: "\u65E0\u62A5\u8868\u884C\uFF08\u9ED8\u8BA4\u53EA\u51FA\u73B0\u533A\u95F4\u5185\u6709\u6D88\u8017\u7684\u5BF9\u8C61\uFF09\u3002",
|
|
143120
143281
|
footnote: "revenue \u662F\u6210\u4EA4\u989D PurchaseRevenue\uFF0C\u4E0D\u662F\u76EE\u6807\u8D4B\u503C\u3002roi=(\u6210\u4EA4\u989D\u2212\u82B1\u8D39)/\u82B1\u8D39\u3002geo/devices \u9ED8\u8BA4 SEARCH\uFF0C\u5168\u7F51\u987B --network ALL\u3002\u65E0\u5C0F\u65F6\u7EF4\u5EA6\u3002",
|
|
143121
143282
|
rows: items3.map((r) => ({
|
|
143122
|
-
id:
|
|
143283
|
+
id: cell4(
|
|
143123
143284
|
r.adId ?? r.adGroupId ?? r.campaignId ?? r.keywordId ?? r.regionName ?? r.device ?? r.date
|
|
143124
143285
|
),
|
|
143125
|
-
name:
|
|
143286
|
+
name: cell4(
|
|
143126
143287
|
r.adName ?? r.adGroupName ?? r.campaignName ?? r.keyword ?? r.regionName ?? r.device
|
|
143127
143288
|
),
|
|
143128
|
-
spend:
|
|
143129
|
-
conversions:
|
|
143130
|
-
ctr:
|
|
143131
|
-
roi:
|
|
143132
|
-
date:
|
|
143289
|
+
spend: cell4(r.spend),
|
|
143290
|
+
conversions: cell4(r.conversions),
|
|
143291
|
+
ctr: cell4(r.ctr),
|
|
143292
|
+
roi: cell4(r.roi),
|
|
143293
|
+
date: cell4(r.date)
|
|
143133
143294
|
})),
|
|
143134
143295
|
columns: [
|
|
143135
143296
|
{ key: "id", header: "\u5BF9\u8C61" },
|
|
@@ -143267,37 +143428,118 @@ function hasDateFromTo(args) {
|
|
|
143267
143428
|
(a) => a === "--date-from" || a === "--date-to" || a.startsWith("--date-from=") || a.startsWith("--date-to=")
|
|
143268
143429
|
);
|
|
143269
143430
|
}
|
|
143431
|
+
var RERUN_HINT = "\u7ACB\u523B\u6539\u8DD1\u63D0\u793A\u4E2D\u7684\u90A3\u6761\uFF0C\u4E0D\u8981\u505C\u5728\u9519\u8BEF\u547D\u4EE4\u3002";
|
|
143432
|
+
function fatal(body) {
|
|
143433
|
+
const text2 = body.replace(/\s+$/g, "");
|
|
143434
|
+
if (text2.includes(RERUN_HINT)) return `
|
|
143435
|
+
${text2}
|
|
143436
|
+
`;
|
|
143437
|
+
return `
|
|
143438
|
+
${text2}
|
|
143439
|
+
${RERUN_HINT}
|
|
143440
|
+
`;
|
|
143441
|
+
}
|
|
143442
|
+
function playbookCodeFatal(cmd) {
|
|
143443
|
+
if (!/^(?:W\d+|P\d+(?:-FB)?)$/i.test(cmd)) return null;
|
|
143444
|
+
const key = cmd.toUpperCase();
|
|
143445
|
+
const known = {
|
|
143446
|
+
W1: "siluzan-tso list-accounts [-m Google] --json-out <dir>",
|
|
143447
|
+
P2: "siluzan-tso balance-scan -m Google --json-out <dir>",
|
|
143448
|
+
P3: "siluzan-tso accounts-digest -m Google --start <S> --end <D> --json-out <dir>"
|
|
143449
|
+
};
|
|
143450
|
+
const replacement = known[key];
|
|
143451
|
+
if (replacement) {
|
|
143452
|
+
return fatal(
|
|
143453
|
+
`\u274C \`${cmd}\` \u662F\u8DEF\u7531\u7F16\u53F7\uFF0C\u4E0D\u662F\u547D\u4EE4\u3002\u8BF7\u6539\u8DD1\uFF1A
|
|
143454
|
+
${replacement}`
|
|
143455
|
+
);
|
|
143456
|
+
}
|
|
143457
|
+
return fatal(
|
|
143458
|
+
`\u274C \`${cmd}\` \u662F\u8DEF\u7531\u7F16\u53F7\uFF0C\u4E0D\u662F\u547D\u4EE4\u3002\u8D26\u6237\u5217\u8868\u7528 list-accounts\uFF0C\u591A\u6237\u4F59\u989D\u7528 balance-scan\uFF0C\u591A\u6237\u6D88\u8017/CPA \u7528 accounts-digest\u3002\u5176\u5B83\u7F16\u53F7\u5148 Read SKILL \u8DEF\u7531\u8868\u3002`
|
|
143459
|
+
);
|
|
143460
|
+
}
|
|
143461
|
+
var LOGIN_CUSTOMER_COMMANDS = /* @__PURE__ */ new Set([
|
|
143462
|
+
"list-accounts",
|
|
143463
|
+
"balance-scan",
|
|
143464
|
+
"accounts-digest",
|
|
143465
|
+
"guard"
|
|
143466
|
+
]);
|
|
143467
|
+
function loginCustomerFlagIssue(args) {
|
|
143468
|
+
const cmd = args[0] ?? "";
|
|
143469
|
+
for (const arg of args) {
|
|
143470
|
+
const raw = arg.startsWith("--") ? arg.slice(2).split("=")[0] : "";
|
|
143471
|
+
if (!raw) continue;
|
|
143472
|
+
const norm = raw.toLowerCase().replace(/_/g, "-");
|
|
143473
|
+
const looksLike = norm.includes("login") && norm.includes("customer");
|
|
143474
|
+
if (!looksLike) continue;
|
|
143475
|
+
if (norm !== "login-customer-id") {
|
|
143476
|
+
return fatal(
|
|
143477
|
+
`\u274C \u6CA1\u6709 \`--${raw}\`\u3002MCC \u5B50\u6237\u8BF7\u7528 --login-customer-id\uFF0C\u53EA\u52A0\u5728 list-accounts\u3001balance-scan\u3001accounts-digest\u3001guard\u3002`
|
|
143478
|
+
);
|
|
143479
|
+
}
|
|
143480
|
+
if (!LOGIN_CUSTOMER_COMMANDS.has(cmd)) {
|
|
143481
|
+
return fatal(
|
|
143482
|
+
`\u274C \`${cmd || "\u8BE5\u547D\u4EE4"}\` \u4E0D\u652F\u6301 --login-customer-id\u3002\u8BF7\u6539\u8DD1 list-accounts\u3001balance-scan\u3001accounts-digest \u6216 guard\u3002`
|
|
143483
|
+
);
|
|
143484
|
+
}
|
|
143485
|
+
}
|
|
143486
|
+
return null;
|
|
143487
|
+
}
|
|
143270
143488
|
function agentCompatFatalMessage(argv) {
|
|
143271
143489
|
const args = argv.slice(2);
|
|
143272
143490
|
if (args.includes("--period") || args.some((a) => a.startsWith("--period="))) {
|
|
143273
|
-
return
|
|
143491
|
+
return fatal(
|
|
143492
|
+
"\u274C \u6CA1\u6709 --period \u9009\u9879\u3002\u8BF7\u7528 --start/--end\uFF08\u6216\u517C\u5BB9\u522B\u540D --start-date/--end-date\uFF09\u6307\u5B9A YYYY-MM-DD \u533A\u95F4\u3002"
|
|
143493
|
+
);
|
|
143274
143494
|
}
|
|
143275
143495
|
if (hasDateFromTo(args)) {
|
|
143276
|
-
return
|
|
143496
|
+
return fatal(
|
|
143497
|
+
"\u274C \u6CA1\u6709 `--date-from` / `--date-to`\u3002\u8BF7\u7528 `--start` / `--end`\uFF08YYYY-MM-DD\uFF09\u3002\n \u5355\u65E5\u9884\u7B97/\u7A7A\u8017\u7194\u65AD\u8BF7\u7528\uFF1Asiluzan-tso guard budget-circuit|zero-conv -m Google --date <\u5F53\u65E5> --json-out <dir>"
|
|
143498
|
+
);
|
|
143277
143499
|
}
|
|
143278
143500
|
if (jsonOutMissingPath(args)) {
|
|
143279
|
-
return
|
|
143501
|
+
return fatal(
|
|
143502
|
+
"\u274C `--json-out` \u5FC5\u987B\u5E26\u8DEF\u5F84\uFF08\u76EE\u5F55\u6216 *.json \u6587\u4EF6\uFF09\uFF0CJSON \u843D\u76D8\u800C\u975E\u6253\u5370\u5230 stdout\uFF0C\u4E0D\u80FD\u7BA1\u9053\u7ED9 python/jq\u3002\n \u793A\u4F8B\uFF1Asiluzan-tso ad campaigns -a <id> --json-out ./snap\n \u7136\u540E\u7528 node/python \u8BFB ./snap \u4E0B writtenFiles\uFF08\u89C1 stdout \u6458\u8981\u7684 absoluteSnapshotDir\uFF09\u3002"
|
|
143503
|
+
);
|
|
143280
143504
|
}
|
|
143281
143505
|
const cmd = args[0];
|
|
143506
|
+
if (!cmd) return null;
|
|
143282
143507
|
if (cmd === "google-ads") {
|
|
143283
|
-
return
|
|
143508
|
+
return fatal(
|
|
143509
|
+
"\u274C \u6CA1\u6709 `google-ads` \u547D\u540D\u7A7A\u95F4\u3002\u8BF7\u6539\u7528\uFF1A\n - \u8D26\u6237\u5206\u6790\u62C9\u6570\uFF1Asiluzan-tso google-analysis \u2026\n - \u5E7F\u544A\u7CFB\u5217/\u7EC4/\u521B\u610F/\u5173\u952E\u8BCD\uFF1Asiluzan-tso ad campaigns|groups|list|keywords \u2026\n \uFF08\u6CA1\u6709 campaign-list\uFF1B\u5217\u8868\u547D\u4EE4\u662F campaigns / groups / list / keywords\uFF09\n - \u5E7F\u544A\u8BCA\u65AD\u62A5\u544A\uFF1Asiluzan-tso google-ads-diagnosis \u2026\n - \u5B63\u5EA6\u7ECF\u8425\u62A5\u544A\uFF1Asiluzan-tso google-quarterly \u2026"
|
|
143510
|
+
);
|
|
143284
143511
|
}
|
|
143285
143512
|
if (cmd === "adgroups" || cmd === "ad" && args[1] === "adgroups") {
|
|
143286
|
-
return
|
|
143513
|
+
return fatal(
|
|
143514
|
+
"\u274C \u6CA1\u6709 `adgroups` \u547D\u4EE4\u3002\u8BF7\u7528\uFF1Asiluzan-tso ad groups -a <mediaCustomerId> --json-out <dir>"
|
|
143515
|
+
);
|
|
143287
143516
|
}
|
|
143288
143517
|
if (adSubcommandHasMediaFlag(args)) {
|
|
143289
|
-
return
|
|
143518
|
+
return fatal(
|
|
143519
|
+
"\u274C `ad \u2026` \u5B50\u547D\u4EE4\u6CA1\u6709 `-m/--media`\uFF0C\u8D26\u6237\u7528 `-a/--account <mediaCustomerId>`\u3002\n \u5355\u6237\uFF1Asiluzan-tso ad campaigns -a <id> --start <\u65E5> --end <\u65E5> --json-out ./snap\n \u5168\u6237\u5F53\u65E5\u8D85\u9884\u7B97/\u7A7A\u8017\u7194\u65AD\uFF1Asiluzan-tso guard budget-circuit|zero-conv -m Google --json-out ./snap"
|
|
143520
|
+
);
|
|
143290
143521
|
}
|
|
143291
143522
|
if (cmd === "list" && (args.length === 1 || args[1]?.startsWith("-"))) {
|
|
143292
|
-
return
|
|
143523
|
+
return fatal(
|
|
143524
|
+
"\u274C \u6CA1\u6709\u9876\u5C42 `list` \u547D\u4EE4\u3002\u67E5\u8BE2\u5E7F\u544A\u8D26\u6237\u5217\u8868\u8BF7\u7528\uFF1A\n siluzan-tso list-accounts [-m Google] [-k <id\u6216\u5173\u952E\u5B57>] --json-out <dir>"
|
|
143525
|
+
);
|
|
143293
143526
|
}
|
|
143294
143527
|
if (cmd === "accounts") {
|
|
143295
|
-
return
|
|
143528
|
+
return fatal(
|
|
143529
|
+
"\u274C \u6CA1\u6709 `accounts` \u547D\u540D\u7A7A\u95F4\u3002\u67E5\u8BE2\u8D26\u6237\u5217\u8868\u8BF7\u7528\uFF1A\n siluzan-tso list-accounts \u2026\n \u591A\u8D26\u6237\u753B\u50CF\uFF1Asiluzan-tso accounts-digest \u2026"
|
|
143530
|
+
);
|
|
143531
|
+
}
|
|
143532
|
+
if (cmd === "account" && args[1] === "balance") {
|
|
143533
|
+
return fatal(
|
|
143534
|
+
"\u274C \u6CA1\u6709 `account balance`\u3002\u5355\u6237\uFF1Asiluzan-tso balance -m <\u5A92\u4F53> -a <id>\u3002\n \u591A\u6237\uFF1Asiluzan-tso balance-scan -m Google --json-out <dir>"
|
|
143535
|
+
);
|
|
143296
143536
|
}
|
|
143297
143537
|
if (cmd === "cpa-risk-scan" || cmd === "cpa-scan" || cmd === "cpa_risk_scan") {
|
|
143298
|
-
return
|
|
143538
|
+
return fatal(
|
|
143539
|
+
"\u274C \u6CA1\u6709 `cpa-risk-scan` / `cpa-scan` \u547D\u4EE4\u3002\u8F6C\u5316\u6210\u672C / CPA \u5DE1\u68C0\u8BF7\u7528\uFF1A\n siluzan-tso accounts-digest -m Google --max-cpa <\u9608\u503C> --start <S> --end <D> \\\n --skip-balance --json-out ./snap-cpa\n \u96F6\u8F6C\u5316\u4EC5\u5F53\u6D88\u8017\u5DF2\u8D85\u8FC7\u9608\u503C\u624D\u547D\u4E2D\u3002\u8BFB\u76D8\u540E\u628A agentBrief.userDelivery \u539F\u6837\u53D1\u7ED9\u7528\u6237\u3002"
|
|
143540
|
+
);
|
|
143299
143541
|
}
|
|
143300
|
-
return
|
|
143542
|
+
return playbookCodeFatal(cmd) ?? loginCustomerFlagIssue(args);
|
|
143301
143543
|
}
|
|
143302
143544
|
function interceptAgentCompatArgv(argv) {
|
|
143303
143545
|
const msg = agentCompatFatalMessage(argv);
|