siluzan-tso-cli 1.1.24 → 1.1.25-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 +535 -140
- package/dist/skill/SKILL.md +4 -1
- package/dist/skill/_meta.json +2 -2
- package/dist/skill/assets/pmax-create-template.md +8 -8
- package/dist/skill/references/accounts/accounts.md +23 -17
- package/dist/skill/references/accounts/currency.md +1 -1
- package/dist/skill/references/accounts/finance.md +4 -4
- package/dist/skill/references/accounts/open-account-by-media.md +150 -14
- package/dist/skill/references/accounts/open-account-google-ui.md +2 -2
- package/dist/skill/references/analytics/account-analytics.md +35 -21
- package/dist/skill/references/analytics/rag.md +1 -1
- package/dist/skill/references/analytics/reporting.md +2 -2
- package/dist/skill/references/analytics/website-diagnosis-guide.md +9 -2
- package/dist/skill/references/core/agent-conventions.md +2 -0
- package/dist/skill/references/core/playbooks.md +3 -2
- package/dist/skill/references/core/setup.md +5 -5
- package/dist/skill/references/core/skill-authoring.md +1 -1
- package/dist/skill/references/core/workflows.md +15 -13
- package/dist/skill/references/operations/hosted-automation-monitoring-json.md +1 -1
- package/dist/skill/references/operations/hosted-automation-optimize-scale.md +2 -2
- package/dist/skill/references/operations/hosted-automation-self-control.md +1 -1
- package/dist/skill/report-templates/README.md +1 -1
- package/dist/skill/report-templates/REPORT-WORKFLOW.md +5 -0
- package/dist/skill/report-templates/google-account-diagnosis-report.md +7 -0
- package/dist/skill/report-templates/google-ads-diagnosis.md +51 -2
- package/dist/skill/report-templates/google-inquiry-analysis.md +8 -8
- package/dist/skill/report-templates/google-period-report.md +2 -2
- package/dist/skill/report-templates/okki-weekly-google-client.md +4 -4
- package/dist/skill/report-templates/report-template.html +1 -0
- package/dist/skill/report-templates/website-diagnosis-report.html +450 -36
- package/dist/skill/report-templates/website-diagnosis-report.md +6 -5
- package/dist/skill/scripts/install.ps1 +3 -3
- package/dist/skill/scripts/install.sh +3 -3
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -3328,7 +3328,7 @@ var DEFAULT_API_BASE;
|
|
|
3328
3328
|
var init_defaults = __esm({
|
|
3329
3329
|
"src/config/defaults.ts"() {
|
|
3330
3330
|
"use strict";
|
|
3331
|
-
DEFAULT_API_BASE = "https://tso-api.siluzan.com";
|
|
3331
|
+
DEFAULT_API_BASE = "https://tso-api-ci.siluzan.com";
|
|
3332
3332
|
}
|
|
3333
3333
|
});
|
|
3334
3334
|
|
|
@@ -4611,6 +4611,118 @@ var init_accounts_digest2 = __esm({
|
|
|
4611
4611
|
}
|
|
4612
4612
|
});
|
|
4613
4613
|
|
|
4614
|
+
// src/commands/google-analysis/wrap-snapshot-envelope.ts
|
|
4615
|
+
function coerceToRowArray(value) {
|
|
4616
|
+
if (Array.isArray(value)) return value;
|
|
4617
|
+
if (value === null || typeof value !== "object") return [];
|
|
4618
|
+
const o = value;
|
|
4619
|
+
const keys = Object.keys(o);
|
|
4620
|
+
if (keys.length === 0) return [];
|
|
4621
|
+
if (keys.every((k) => /^\d+$/.test(k))) {
|
|
4622
|
+
return keys.sort((a, b) => Number(a) - Number(b)).map((k) => o[k]);
|
|
4623
|
+
}
|
|
4624
|
+
return [];
|
|
4625
|
+
}
|
|
4626
|
+
function asRecord(value) {
|
|
4627
|
+
if (value === null || typeof value !== "object" || Array.isArray(value)) return null;
|
|
4628
|
+
return value;
|
|
4629
|
+
}
|
|
4630
|
+
function readGatewayList(bag) {
|
|
4631
|
+
const items = coerceToRowArray(bag.data);
|
|
4632
|
+
const meta = {};
|
|
4633
|
+
if (typeof bag.code === "number") meta.code = bag.code;
|
|
4634
|
+
if (typeof bag.message === "string") meta.message = bag.message;
|
|
4635
|
+
return { items, ...Object.keys(meta).length > 0 ? { meta } : {} };
|
|
4636
|
+
}
|
|
4637
|
+
function flattenMaterials(payload) {
|
|
4638
|
+
const bag = asRecord(payload);
|
|
4639
|
+
if (!bag) return [];
|
|
4640
|
+
const images = coerceToRowArray(bag.images).map(
|
|
4641
|
+
(row) => asRecord(row) ? { ...row, assetType: "image" } : row
|
|
4642
|
+
);
|
|
4643
|
+
const videos = coerceToRowArray(bag.videos).map(
|
|
4644
|
+
(row) => asRecord(row) ? { ...row, assetType: "video" } : row
|
|
4645
|
+
);
|
|
4646
|
+
return [...images, ...videos];
|
|
4647
|
+
}
|
|
4648
|
+
function wrapGoogleAnalysisSnapshotPayload(section, payload) {
|
|
4649
|
+
let items = [];
|
|
4650
|
+
let record = null;
|
|
4651
|
+
let meta;
|
|
4652
|
+
if (COMPOSITE_SECTIONS.has(section)) {
|
|
4653
|
+
items = flattenMaterials(payload);
|
|
4654
|
+
} else if (RECORD_ONLY_SECTIONS.has(section)) {
|
|
4655
|
+
record = asRecord(payload);
|
|
4656
|
+
} else if (GATEWAY_LIST_SECTIONS.has(section)) {
|
|
4657
|
+
const bag = asRecord(payload);
|
|
4658
|
+
if (bag) {
|
|
4659
|
+
const r = readGatewayList(bag);
|
|
4660
|
+
items = r.items;
|
|
4661
|
+
meta = r.meta;
|
|
4662
|
+
}
|
|
4663
|
+
} else if (ROOT_ARRAY_SECTIONS.has(section)) {
|
|
4664
|
+
items = coerceToRowArray(payload);
|
|
4665
|
+
} else {
|
|
4666
|
+
const rowKey = ROW_KEY_BY_SECTION[section];
|
|
4667
|
+
const bag = asRecord(payload);
|
|
4668
|
+
if (rowKey && bag) {
|
|
4669
|
+
items = coerceToRowArray(bag[rowKey]);
|
|
4670
|
+
} else {
|
|
4671
|
+
const arr = coerceToRowArray(payload);
|
|
4672
|
+
if (arr.length > 0) items = arr;
|
|
4673
|
+
else record = asRecord(payload);
|
|
4674
|
+
}
|
|
4675
|
+
}
|
|
4676
|
+
return {
|
|
4677
|
+
schemaVersion: GOOGLE_ANALYSIS_FILE_SCHEMA_VERSION,
|
|
4678
|
+
section,
|
|
4679
|
+
itemCount: items.length,
|
|
4680
|
+
items,
|
|
4681
|
+
record,
|
|
4682
|
+
...meta !== void 0 ? { meta } : {}
|
|
4683
|
+
};
|
|
4684
|
+
}
|
|
4685
|
+
var GOOGLE_ANALYSIS_FILE_SCHEMA_VERSION, ROW_KEY_BY_SECTION, RECORD_ONLY_SECTIONS, COMPOSITE_SECTIONS, ROOT_ARRAY_SECTIONS, GATEWAY_LIST_SECTIONS;
|
|
4686
|
+
var init_wrap_snapshot_envelope = __esm({
|
|
4687
|
+
"src/commands/google-analysis/wrap-snapshot-envelope.ts"() {
|
|
4688
|
+
"use strict";
|
|
4689
|
+
GOOGLE_ANALYSIS_FILE_SCHEMA_VERSION = 3;
|
|
4690
|
+
ROW_KEY_BY_SECTION = {
|
|
4691
|
+
keywords: "keywords",
|
|
4692
|
+
campaigns: "campaigns",
|
|
4693
|
+
devices: "devices",
|
|
4694
|
+
geographic: "countries",
|
|
4695
|
+
"geo-matched": "countries",
|
|
4696
|
+
"campaign-geo": "countries",
|
|
4697
|
+
"campaign-geo-matched": "countries",
|
|
4698
|
+
"campaign-device": "devices",
|
|
4699
|
+
audience: "audience"
|
|
4700
|
+
};
|
|
4701
|
+
RECORD_ONLY_SECTIONS = /* @__PURE__ */ new Set([
|
|
4702
|
+
"overview",
|
|
4703
|
+
"resource-counts",
|
|
4704
|
+
"dimension-summary",
|
|
4705
|
+
"gold-account",
|
|
4706
|
+
"final-urls",
|
|
4707
|
+
"campaign-types",
|
|
4708
|
+
"ads-index"
|
|
4709
|
+
]);
|
|
4710
|
+
COMPOSITE_SECTIONS = /* @__PURE__ */ new Set(["materials"]);
|
|
4711
|
+
ROOT_ARRAY_SECTIONS = /* @__PURE__ */ new Set([
|
|
4712
|
+
"campaign-hour",
|
|
4713
|
+
"extensions",
|
|
4714
|
+
"asset-images",
|
|
4715
|
+
"videos",
|
|
4716
|
+
"daily-metrics",
|
|
4717
|
+
"conversion-actions"
|
|
4718
|
+
]);
|
|
4719
|
+
GATEWAY_LIST_SECTIONS = /* @__PURE__ */ new Set([
|
|
4720
|
+
"search-terms",
|
|
4721
|
+
"ads"
|
|
4722
|
+
]);
|
|
4723
|
+
}
|
|
4724
|
+
});
|
|
4725
|
+
|
|
4614
4726
|
// src/utils/snapshot/google-analysis.ts
|
|
4615
4727
|
import * as fs7 from "fs/promises";
|
|
4616
4728
|
import * as path11 from "path";
|
|
@@ -4618,7 +4730,7 @@ function googleAnalysisManifestFile(accountId) {
|
|
|
4618
4730
|
return `${applyIdSuffix("manifest", accountId)}.json`;
|
|
4619
4731
|
}
|
|
4620
4732
|
function buildOutlineHints(section) {
|
|
4621
|
-
const hints = [];
|
|
4733
|
+
const hints = [...GOOGLE_ANALYSIS_ENVELOPE_OUTLINE_HINTS];
|
|
4622
4734
|
if (RATE_BEARING_SECTIONS.has(section)) {
|
|
4623
4735
|
hints.push(...GOOGLE_ANALYSIS_RATE_NORMALIZED_OUTLINE_HINTS);
|
|
4624
4736
|
}
|
|
@@ -4656,7 +4768,8 @@ async function readManifestIfExists(absDir, accountId) {
|
|
|
4656
4768
|
try {
|
|
4657
4769
|
const raw = await fs7.readFile(manifestPath, "utf8");
|
|
4658
4770
|
const parsed = JSON.parse(raw);
|
|
4659
|
-
|
|
4771
|
+
const sv = parsed?.schemaVersion;
|
|
4772
|
+
if (sv !== 2 && sv !== SCHEMA_VERSION2 || !Array.isArray(parsed.artifacts)) {
|
|
4660
4773
|
continue;
|
|
4661
4774
|
}
|
|
4662
4775
|
return parsed;
|
|
@@ -4696,12 +4809,16 @@ async function writeGoogleAnalysisSnapshot(params) {
|
|
|
4696
4809
|
);
|
|
4697
4810
|
const relativeFile = fileName;
|
|
4698
4811
|
const writtenAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
4699
|
-
const
|
|
4812
|
+
const wrapped = wrapGoogleAnalysisSnapshotPayload(
|
|
4813
|
+
params.section,
|
|
4814
|
+
params.payload
|
|
4815
|
+
);
|
|
4816
|
+
const body = JSON.stringify(wrapped, null, 2);
|
|
4700
4817
|
await fs7.writeFile(path11.join(absDir, fileName), `${body}
|
|
4701
4818
|
`, "utf8");
|
|
4702
4819
|
const outlineFileName = snapshotOutlineFileName(fileName);
|
|
4703
4820
|
const outlineExtra = buildOutlineHints(params.section);
|
|
4704
|
-
const outlineBody = formatOutlineFileBody(fileName,
|
|
4821
|
+
const outlineBody = formatOutlineFileBody(fileName, wrapped, outlineExtra);
|
|
4705
4822
|
await fs7.writeFile(path11.join(absDir, outlineFileName), `${outlineBody}
|
|
4706
4823
|
`, "utf8");
|
|
4707
4824
|
const existing = await readManifestIfExists(absDir, accountSlug || void 0);
|
|
@@ -4735,15 +4852,16 @@ async function writeGoogleAnalysisSnapshot(params) {
|
|
|
4735
4852
|
agentHint: OUTLINE_AGENT_HINT
|
|
4736
4853
|
};
|
|
4737
4854
|
}
|
|
4738
|
-
var LEGACY_MANIFEST_FILE, CLI_PACKAGE2, SCHEMA_VERSION2, DEFAULT_FIELD_GUIDE2, GOOGLE_ANALYSIS_CAMPAIGNS_OUTLINE_BUDGET_HINTS, GOOGLE_ANALYSIS_CAMPAIGNS_COMPETITIVE_METRICS_HINTS, RATE_BEARING_SECTIONS, GOOGLE_ANALYSIS_RATE_NORMALIZED_OUTLINE_HINTS, GOOGLE_ANALYSIS_ZH_FIELD_HINTS_BY_SECTION;
|
|
4855
|
+
var LEGACY_MANIFEST_FILE, CLI_PACKAGE2, SCHEMA_VERSION2, DEFAULT_FIELD_GUIDE2, GOOGLE_ANALYSIS_CAMPAIGNS_OUTLINE_BUDGET_HINTS, GOOGLE_ANALYSIS_CAMPAIGNS_COMPETITIVE_METRICS_HINTS, RATE_BEARING_SECTIONS, GOOGLE_ANALYSIS_RATE_NORMALIZED_OUTLINE_HINTS, GOOGLE_ANALYSIS_ENVELOPE_OUTLINE_HINTS, GOOGLE_ANALYSIS_ZH_FIELD_HINTS_BY_SECTION;
|
|
4739
4856
|
var init_google_analysis = __esm({
|
|
4740
4857
|
"src/utils/snapshot/google-analysis.ts"() {
|
|
4741
4858
|
"use strict";
|
|
4742
4859
|
init_cli_json();
|
|
4860
|
+
init_wrap_snapshot_envelope();
|
|
4743
4861
|
init_dir();
|
|
4744
4862
|
LEGACY_MANIFEST_FILE = "manifest.json";
|
|
4745
4863
|
CLI_PACKAGE2 = "siluzan-tso-cli";
|
|
4746
|
-
SCHEMA_VERSION2 =
|
|
4864
|
+
SCHEMA_VERSION2 = 3;
|
|
4747
4865
|
DEFAULT_FIELD_GUIDE2 = {
|
|
4748
4866
|
markdownRefs: ["references/accounts/currency.md", "references/analytics/account-analytics.md"],
|
|
4749
4867
|
tsTypesModule: "tso-cli/src/types/google-analysis-api.ts"
|
|
@@ -4782,6 +4900,10 @@ var init_google_analysis = __esm({
|
|
|
4782
4900
|
"// \u6982\u7387\u5B57\u6BB5\uFF1A`ctr` / `conversionRate` \u81EA manifest schemaVersion 2\uFF082026-05\uFF09\u8D77\u5DF2\u7531 CLI \u7EDF\u4E00\u5F52\u4E00\u4E3A **0~1 \u5C0F\u6570**\uFF08\u5982 `0.0964` = 9.64%\uFF09\u3002",
|
|
4783
4901
|
"// \u5199 Excel 0~1 \u5C0F\u6570\u5217\uFF1A\u76F4\u63A5\u5199\u5165\uFF1B\u5199\u300Cx%\u300D\u6587\u6848\uFF1A`(v * 100).toFixed(2) + '%'`\uFF1B**\u7981\u6B62**\u518D \xF7100\u3002`interactionRate` \u4ECD\u662F\u5B57\u7B26\u4E32 0~1 \u5C0F\u6570\uFF0C`parseFloat` \u540E\u4F7F\u7528\u3002"
|
|
4784
4902
|
];
|
|
4903
|
+
GOOGLE_ANALYSIS_ENVELOPE_OUTLINE_HINTS = [
|
|
4904
|
+
"// \u7EDF\u4E00\u8BBF\u95EE\u5C42\uFF08manifest / \u6587\u4EF6\u5185\u5747\u4E3A `schemaVersion: 3`\uFF09\uFF1A\u5224\u522B\u53EA\u6709\u4E00\u6761\u2014\u2014`record` \u975E null \u5373**\u6C47\u603B\u7EF4\u5EA6**\uFF08overview/resource-counts/gold-account/ads-index/dimension-summary/final-urls/campaign-types\uFF09\uFF0C\u8BFB `record`\uFF1B\u5426\u5219\u8BFB `items[]`\uFF08\u6240\u6709\u5217\u8868\u7EF4\u5EA6\uFF0C\u542B materials\uFF0C\u884C\u5DF2\u7EDF\u4E00\u642C\u5165\uFF0C`itemCount` = `items.length`\uFF09\u3002",
|
|
4905
|
+
"// \u7EF4\u5EA6\u4E13\u5C5E\u539F\u952E\u540D\uFF08keywords/campaigns/countries/data \u7B49\uFF09\u5DF2**\u79FB\u9664**\uFF0C\u4E0D\u8981\u518D\u6309\u7EF4\u5EA6\u731C\u952E\u540D\uFF1B`search-terms`/`ads` \u7684\u7F51\u5173 `code`/`message` \u5728 `meta`\uFF08\u4E0E\u6570\u636E\u65E0\u5173\uFF09\uFF1Bmaterials \u884C\u5E26 `assetType: 'image'|'video'`\u3002"
|
|
4906
|
+
];
|
|
4785
4907
|
GOOGLE_ANALYSIS_ZH_FIELD_HINTS_BY_SECTION = {
|
|
4786
4908
|
keywords: [
|
|
4787
4909
|
"// \u4E2D\u6587\u8BD1\u540D\uFF1A`keywordMatchTypeZh`\uFF08\u7531 `keywordMatchType` \u7ECF match-type-en2zh.json \u7FFB\u8BD1\uFF0C\u8986\u76D6 BROAD/PHRASE/EXACT \u4E0E Broad/Phrase/Exact \u5927\u5C0F\u5199\uFF1B\u672A\u547D\u4E2D\u65F6\u8BE5\u5B57\u6BB5\u7F3A\u7701\uFF09\u3002"
|
|
@@ -101089,8 +101211,8 @@ var init_http_retry = __esm({
|
|
|
101089
101211
|
});
|
|
101090
101212
|
|
|
101091
101213
|
// src/utils/batch-manifest.ts
|
|
101092
|
-
import * as
|
|
101093
|
-
import * as
|
|
101214
|
+
import * as fs13 from "fs/promises";
|
|
101215
|
+
import * as path18 from "path";
|
|
101094
101216
|
import { randomUUID as randomUUID2 } from "crypto";
|
|
101095
101217
|
function generateRunId(now = /* @__PURE__ */ new Date()) {
|
|
101096
101218
|
const pad = (n) => String(n).padStart(2, "0");
|
|
@@ -101104,26 +101226,26 @@ function isValidRunId(id) {
|
|
|
101104
101226
|
}
|
|
101105
101227
|
function resolveBatchPaths(baseDir, runId) {
|
|
101106
101228
|
if (!isValidRunId(runId)) throw new Error(`\u975E\u6CD5 runId\uFF1A${runId}`);
|
|
101107
|
-
const runDir =
|
|
101108
|
-
const stateDir =
|
|
101229
|
+
const runDir = path18.resolve(baseDir, runId);
|
|
101230
|
+
const stateDir = path18.join(runDir, "state");
|
|
101109
101231
|
return {
|
|
101110
101232
|
runDir,
|
|
101111
|
-
runManifestFile:
|
|
101112
|
-
progressFile:
|
|
101113
|
-
accountsFile:
|
|
101114
|
-
resultsDir:
|
|
101115
|
-
errorsDir:
|
|
101233
|
+
runManifestFile: path18.join(runDir, "run-manifest.json"),
|
|
101234
|
+
progressFile: path18.join(runDir, "progress.json"),
|
|
101235
|
+
accountsFile: path18.join(runDir, "accounts.json"),
|
|
101236
|
+
resultsDir: path18.join(runDir, "results"),
|
|
101237
|
+
errorsDir: path18.join(runDir, "errors"),
|
|
101116
101238
|
stateDir,
|
|
101117
|
-
tasksLogFile:
|
|
101118
|
-
lockFile:
|
|
101239
|
+
tasksLogFile: path18.join(stateDir, "tasks.jsonl"),
|
|
101240
|
+
lockFile: path18.join(stateDir, "tasks.lock")
|
|
101119
101241
|
};
|
|
101120
101242
|
}
|
|
101121
101243
|
async function ensureAccountDirs(paths, accountId) {
|
|
101122
101244
|
const safe = sanitizeAccountSegment(accountId);
|
|
101123
|
-
const results =
|
|
101124
|
-
const errors =
|
|
101125
|
-
await
|
|
101126
|
-
await
|
|
101245
|
+
const results = path18.join(paths.resultsDir, safe);
|
|
101246
|
+
const errors = path18.join(paths.errorsDir, safe);
|
|
101247
|
+
await fs13.mkdir(results, { recursive: true });
|
|
101248
|
+
await fs13.mkdir(errors, { recursive: true });
|
|
101127
101249
|
return { results, errors };
|
|
101128
101250
|
}
|
|
101129
101251
|
function sanitizeAccountSegment(accountId) {
|
|
@@ -101138,20 +101260,20 @@ function sanitizeAccountSegment(accountId) {
|
|
|
101138
101260
|
return slug;
|
|
101139
101261
|
}
|
|
101140
101262
|
async function atomicWriteFile(target, content) {
|
|
101141
|
-
const dir =
|
|
101142
|
-
await
|
|
101143
|
-
const tmp =
|
|
101263
|
+
const dir = path18.dirname(target);
|
|
101264
|
+
await fs13.mkdir(dir, { recursive: true });
|
|
101265
|
+
const tmp = path18.join(dir, `.tmp-${randomUUID2()}-${path18.basename(target)}`);
|
|
101144
101266
|
try {
|
|
101145
|
-
await
|
|
101146
|
-
await
|
|
101267
|
+
await fs13.writeFile(tmp, content, "utf8");
|
|
101268
|
+
await fs13.rename(tmp, target);
|
|
101147
101269
|
} catch (e) {
|
|
101148
|
-
await
|
|
101270
|
+
await fs13.rm(tmp, { force: true }).catch(() => void 0);
|
|
101149
101271
|
throw e;
|
|
101150
101272
|
}
|
|
101151
101273
|
}
|
|
101152
101274
|
async function readJsonIfExists(file) {
|
|
101153
101275
|
try {
|
|
101154
|
-
const raw = await
|
|
101276
|
+
const raw = await fs13.readFile(file, "utf8");
|
|
101155
101277
|
return JSON.parse(raw);
|
|
101156
101278
|
} catch (e) {
|
|
101157
101279
|
if (e.code === "ENOENT") return null;
|
|
@@ -101181,12 +101303,12 @@ function readProgress(paths) {
|
|
|
101181
101303
|
return readJsonIfExists(paths.progressFile);
|
|
101182
101304
|
}
|
|
101183
101305
|
async function appendTaskLog(paths, entry) {
|
|
101184
|
-
await
|
|
101185
|
-
await
|
|
101306
|
+
await fs13.mkdir(paths.stateDir, { recursive: true });
|
|
101307
|
+
await fs13.appendFile(paths.tasksLogFile, JSON.stringify(entry) + "\n", "utf8");
|
|
101186
101308
|
}
|
|
101187
101309
|
async function readTaskLog(paths) {
|
|
101188
101310
|
try {
|
|
101189
|
-
const raw = await
|
|
101311
|
+
const raw = await fs13.readFile(paths.tasksLogFile, "utf8");
|
|
101190
101312
|
return raw.split("\n").filter((s) => s.trim() !== "").map((line) => JSON.parse(line));
|
|
101191
101313
|
} catch (e) {
|
|
101192
101314
|
if (e.code === "ENOENT") return [];
|
|
@@ -101241,9 +101363,9 @@ function emptyProgress(runId, totalTasks, accountConcurrency, sectionConcurrency
|
|
|
101241
101363
|
};
|
|
101242
101364
|
}
|
|
101243
101365
|
async function tryAcquireLock(paths) {
|
|
101244
|
-
await
|
|
101366
|
+
await fs13.mkdir(paths.stateDir, { recursive: true });
|
|
101245
101367
|
try {
|
|
101246
|
-
const handle = await
|
|
101368
|
+
const handle = await fs13.open(paths.lockFile, "wx");
|
|
101247
101369
|
await handle.writeFile(`${process.pid}@${(/* @__PURE__ */ new Date()).toISOString()}`);
|
|
101248
101370
|
await handle.close();
|
|
101249
101371
|
return true;
|
|
@@ -101253,7 +101375,7 @@ async function tryAcquireLock(paths) {
|
|
|
101253
101375
|
}
|
|
101254
101376
|
}
|
|
101255
101377
|
async function releaseLock(paths) {
|
|
101256
|
-
await
|
|
101378
|
+
await fs13.rm(paths.lockFile, { force: true }).catch(() => void 0);
|
|
101257
101379
|
}
|
|
101258
101380
|
var BATCH_SCHEMA_VERSION;
|
|
101259
101381
|
var init_batch_manifest = __esm({
|
|
@@ -101265,8 +101387,8 @@ var init_batch_manifest = __esm({
|
|
|
101265
101387
|
|
|
101266
101388
|
// src/utils/batch-runner.ts
|
|
101267
101389
|
import { performance as performance2 } from "perf_hooks";
|
|
101268
|
-
import * as
|
|
101269
|
-
import * as
|
|
101390
|
+
import * as path19 from "path";
|
|
101391
|
+
import * as fs14 from "fs/promises";
|
|
101270
101392
|
async function runPool(items, concurrencyRef, worker, signal) {
|
|
101271
101393
|
let cursor = 0;
|
|
101272
101394
|
const launch = () => {
|
|
@@ -101405,7 +101527,7 @@ async function runBatch(opts) {
|
|
|
101405
101527
|
}
|
|
101406
101528
|
const inner = {
|
|
101407
101529
|
...emptyProgress(
|
|
101408
|
-
opts.paths.runDir.split(
|
|
101530
|
+
opts.paths.runDir.split(path19.sep).pop() ?? "run",
|
|
101409
101531
|
allTasks.length,
|
|
101410
101532
|
opts.accountConcurrency,
|
|
101411
101533
|
opts.sectionConcurrency
|
|
@@ -101535,7 +101657,7 @@ async function runBatch(opts) {
|
|
|
101535
101657
|
}
|
|
101536
101658
|
);
|
|
101537
101659
|
await writer({
|
|
101538
|
-
snapshotDir:
|
|
101660
|
+
snapshotDir: path19.join(opts.paths.resultsDir, sanitizeAccountSegment(task.accountId)),
|
|
101539
101661
|
section: task.section,
|
|
101540
101662
|
accountId: task.accountId,
|
|
101541
101663
|
dateRange: result.dateRange,
|
|
@@ -101608,7 +101730,7 @@ async function runBatch(opts) {
|
|
|
101608
101730
|
};
|
|
101609
101731
|
}
|
|
101610
101732
|
async function writeTaskError(paths, errorsDir, task, err, cls) {
|
|
101611
|
-
const file =
|
|
101733
|
+
const file = path19.join(errorsDir, `${sanitizeSection(task.section)}.error.json`);
|
|
101612
101734
|
const payload = {
|
|
101613
101735
|
schemaVersion: 1,
|
|
101614
101736
|
taskId: task.id,
|
|
@@ -101654,10 +101776,10 @@ async function persistRunMetadata(input) {
|
|
|
101654
101776
|
accountsTotal: input.accounts.length,
|
|
101655
101777
|
invocation: input.invocation
|
|
101656
101778
|
};
|
|
101657
|
-
await
|
|
101658
|
-
await
|
|
101659
|
-
await
|
|
101660
|
-
await
|
|
101779
|
+
await fs14.mkdir(paths.runDir, { recursive: true });
|
|
101780
|
+
await fs14.mkdir(paths.stateDir, { recursive: true });
|
|
101781
|
+
await fs14.mkdir(paths.resultsDir, { recursive: true });
|
|
101782
|
+
await fs14.mkdir(paths.errorsDir, { recursive: true });
|
|
101661
101783
|
await writeRunManifest(paths, manifest);
|
|
101662
101784
|
await writeAccounts(paths, input.accounts);
|
|
101663
101785
|
return paths;
|
|
@@ -101720,7 +101842,7 @@ __export(google_analysis_batch_exports, {
|
|
|
101720
101842
|
parseAccountIds: () => parseAccountIds,
|
|
101721
101843
|
registerGoogleAnalysisBatchCommands: () => registerGoogleAnalysisBatchCommands
|
|
101722
101844
|
});
|
|
101723
|
-
import * as
|
|
101845
|
+
import * as path20 from "path";
|
|
101724
101846
|
import { performance as performance3 } from "perf_hooks";
|
|
101725
101847
|
function parseSections(input) {
|
|
101726
101848
|
if (!input || !input.trim()) return DEFAULT_SECTIONS;
|
|
@@ -102267,7 +102389,7 @@ var init_google_analysis_batch = __esm({
|
|
|
102267
102389
|
});
|
|
102268
102390
|
|
|
102269
102391
|
// src/commands/google-analysis/register-cli.ts
|
|
102270
|
-
import * as
|
|
102392
|
+
import * as path21 from "path";
|
|
102271
102393
|
import { performance as performance4 } from "perf_hooks";
|
|
102272
102394
|
function resolveSectionList(sections, exclude) {
|
|
102273
102395
|
const allNames = SECTIONS.map((s) => s.name);
|
|
@@ -102357,7 +102479,7 @@ async function runAllSections(opts) {
|
|
|
102357
102479
|
const results = await runWithConcurrency(tasks, concurrency);
|
|
102358
102480
|
const succeeded = results.filter((r) => r.ok).length;
|
|
102359
102481
|
const failed = results.length - succeeded;
|
|
102360
|
-
const absoluteSnapshotDir =
|
|
102482
|
+
const absoluteSnapshotDir = path21.resolve(opts.jsonOut);
|
|
102361
102483
|
const summary = {
|
|
102362
102484
|
kind: "siluzan-tso-google-analysis-snapshot-batch",
|
|
102363
102485
|
absoluteSnapshotDir,
|
|
@@ -102574,6 +102696,7 @@ var init_google_analysis2 = __esm({
|
|
|
102574
102696
|
init_normalize_rates();
|
|
102575
102697
|
init_normalize_impression_shares();
|
|
102576
102698
|
init_translate_fields();
|
|
102699
|
+
init_wrap_snapshot_envelope();
|
|
102577
102700
|
init_register_cli();
|
|
102578
102701
|
}
|
|
102579
102702
|
});
|
|
@@ -102589,9 +102712,9 @@ var init_google_analysis3 = __esm({
|
|
|
102589
102712
|
// src/index.ts
|
|
102590
102713
|
init_dist();
|
|
102591
102714
|
init_dist();
|
|
102592
|
-
import * as
|
|
102593
|
-
import * as
|
|
102594
|
-
import { fileURLToPath as
|
|
102715
|
+
import * as fs15 from "fs";
|
|
102716
|
+
import * as path23 from "path";
|
|
102717
|
+
import { fileURLToPath as fileURLToPath5 } from "url";
|
|
102595
102718
|
import { Command } from "commander";
|
|
102596
102719
|
|
|
102597
102720
|
// src/commands/login/urls.ts
|
|
@@ -103074,11 +103197,17 @@ function deriveWebUrl(apiBaseUrl) {
|
|
|
103074
103197
|
}
|
|
103075
103198
|
}
|
|
103076
103199
|
var TSO_UMI_ROUTE_PREFIX = "/v3umijs/tso";
|
|
103077
|
-
function buildTsoPageWebUrl(webUrl, tsoSubRoute) {
|
|
103078
|
-
const
|
|
103079
|
-
const umiPath = `${TSO_UMI_ROUTE_PREFIX}/${
|
|
103200
|
+
function buildTsoPageWebUrl(webUrl, tsoSubRoute, extraQuery) {
|
|
103201
|
+
const path24 = tsoSubRoute.replace(/^\/+/, "");
|
|
103202
|
+
const umiPath = `${TSO_UMI_ROUTE_PREFIX}/${path24}`;
|
|
103080
103203
|
const q = new URLSearchParams({ tso: umiPath });
|
|
103081
|
-
|
|
103204
|
+
if (extraQuery) {
|
|
103205
|
+
for (const [key, value] of Object.entries(extraQuery)) {
|
|
103206
|
+
const v = value?.trim();
|
|
103207
|
+
if (v) q.set(key, v);
|
|
103208
|
+
}
|
|
103209
|
+
}
|
|
103210
|
+
return `${webUrl.replace(/\/+$/, "")}/v3/foreign_trade/tso/${path24}?${q.toString()}`;
|
|
103082
103211
|
}
|
|
103083
103212
|
function cmdConfigShow() {
|
|
103084
103213
|
const shared = readSharedConfig();
|
|
@@ -110252,7 +110381,7 @@ function cloneKeywordBlockShell(block) {
|
|
|
110252
110381
|
delete shell["matchTypeV2"];
|
|
110253
110382
|
return shell;
|
|
110254
110383
|
}
|
|
110255
|
-
function splitKeywordsForBatchJobBlockIfMixed(block,
|
|
110384
|
+
function splitKeywordsForBatchJobBlockIfMixed(block, path24, warnings) {
|
|
110256
110385
|
const declaredUi = matchTypeV2ToUi(readBlockMatchTypeRaw(block));
|
|
110257
110386
|
const entries = collectKeywordEntriesFromBlock(block);
|
|
110258
110387
|
if (entries.length === 0) return [block];
|
|
@@ -110271,7 +110400,7 @@ function splitKeywordsForBatchJobBlockIfMixed(block, path23, warnings) {
|
|
|
110271
110400
|
(ui) => matchTypeUiToV2(ui)
|
|
110272
110401
|
);
|
|
110273
110402
|
warnings.push(
|
|
110274
|
-
`${
|
|
110403
|
+
`${path24} \u542B\u591A\u79CD\u5339\u914D\u7C7B\u578B\uFF0C\u5DF2\u81EA\u52A8\u62C6\u5206\u4E3A ${groups.size} \u4E2A KeywordsForBatchJob \u5757\uFF08${labels.join("\u3001")}\uFF09`
|
|
110275
110404
|
);
|
|
110276
110405
|
const shell = cloneKeywordBlockShell(block);
|
|
110277
110406
|
const splitBlocks = [];
|
|
@@ -110291,16 +110420,16 @@ function splitKeywordsForBatchJobBlockIfMixed(block, path23, warnings) {
|
|
|
110291
110420
|
}
|
|
110292
110421
|
return splitBlocks;
|
|
110293
110422
|
}
|
|
110294
|
-
function validateKeywordCore(core,
|
|
110423
|
+
function validateKeywordCore(core, path24, errors, lengthViolations) {
|
|
110295
110424
|
const trimmed = core.trim();
|
|
110296
110425
|
if (!trimmed) {
|
|
110297
|
-
errors.push(`${
|
|
110426
|
+
errors.push(`${path24} \u5173\u952E\u8BCD\u8BCD\u5E72\u4E0D\u80FD\u4E3A\u7A7A`);
|
|
110298
110427
|
return false;
|
|
110299
110428
|
}
|
|
110300
110429
|
if (trimmed.length > GOOGLE_KEYWORD_MAX_CORE_LENGTH) {
|
|
110301
110430
|
if (lengthViolations) {
|
|
110302
110431
|
pushLengthViolation(lengthViolations, {
|
|
110303
|
-
path:
|
|
110432
|
+
path: path24,
|
|
110304
110433
|
field: "KeywordText",
|
|
110305
110434
|
kind: "keyword_core",
|
|
110306
110435
|
limit: GOOGLE_KEYWORD_MAX_CORE_LENGTH,
|
|
@@ -110310,13 +110439,13 @@ function validateKeywordCore(core, path23, errors, lengthViolations) {
|
|
|
110310
110439
|
});
|
|
110311
110440
|
}
|
|
110312
110441
|
errors.push(
|
|
110313
|
-
`${
|
|
110442
|
+
`${path24} \u5173\u952E\u8BCD\u8BCD\u5E72\u8D85\u8FC7 ${GOOGLE_KEYWORD_MAX_CORE_LENGTH} \u5B57\u7B26\uFF08\u5F53\u524D ${trimmed.length}\uFF09\uFF1A"${trimmed}"`
|
|
110314
110443
|
);
|
|
110315
110444
|
return false;
|
|
110316
110445
|
}
|
|
110317
110446
|
if (!VALID_CORE_REGEX.test(trimmed)) {
|
|
110318
110447
|
errors.push(
|
|
110319
|
-
`${
|
|
110448
|
+
`${path24} \u542B Google \u4E0D\u5141\u8BB8\u7684\u5B57\u7B26\uFF08\u8BCD\u5E72\u4EC5\u5141\u8BB8\u5B57\u6BCD/\u6570\u5B57/\u7A7A\u683C/\u8FDE\u5B57\u7B26/\u53E5\u70B9\uFF09\uFF1A"${trimmed.slice(0, 40)}${trimmed.length > 40 ? "\u2026" : ""}"`
|
|
110320
110449
|
);
|
|
110321
110450
|
return false;
|
|
110322
110451
|
}
|
|
@@ -110373,24 +110502,24 @@ function canonicalizeKeywordBatchBlock(block, resolvedMatchV2, normalizedTexts,
|
|
|
110373
110502
|
}
|
|
110374
110503
|
}
|
|
110375
110504
|
}
|
|
110376
|
-
function pushKeywordAutoFixWarning(warnings,
|
|
110505
|
+
function pushKeywordAutoFixWarning(warnings, path24, fieldLabel, trimmedRaw, formatted, declaredUi, beforeUi, matchType, inferredMatchType) {
|
|
110377
110506
|
if (inferredMatchType) {
|
|
110378
110507
|
warnings.push(
|
|
110379
|
-
`${
|
|
110508
|
+
`${path24}.${fieldLabel} \u672A\u6307\u5B9A MatchTypeV2\uFF0C\u5DF2\u6309\u8BCD\u9762\u63A8\u65AD\u4E3A ${matchTypeUiToV2(matchType)}`
|
|
110380
110509
|
);
|
|
110381
110510
|
return;
|
|
110382
110511
|
}
|
|
110383
110512
|
if (declaredUi && beforeUi !== declaredUi) {
|
|
110384
110513
|
warnings.push(
|
|
110385
|
-
`${
|
|
110514
|
+
`${path24}.${fieldLabel} MatchTypeV2=${matchTypeUiToV2(declaredUi)} \u4E0E\u8BCD\u9762\u4E0D\u4E00\u81F4\uFF0C\u5DF2\u81EA\u52A8\u4FEE\u590D\u4E3A\uFF1A${formatted}`
|
|
110386
110515
|
);
|
|
110387
110516
|
return;
|
|
110388
110517
|
}
|
|
110389
110518
|
if (formatted !== trimmedRaw) {
|
|
110390
|
-
warnings.push(`${
|
|
110519
|
+
warnings.push(`${path24}.${fieldLabel} \u5DF2\u81EA\u52A8\u4FEE\u590D\u8BCD\u9762\uFF1A${trimmedRaw} \u2192 ${formatted}`);
|
|
110391
110520
|
}
|
|
110392
110521
|
}
|
|
110393
|
-
function normalizeKeywordTextList(texts, matchTypeRaw,
|
|
110522
|
+
function normalizeKeywordTextList(texts, matchTypeRaw, path24, fieldLabel, errors, warnings, lengthViolations) {
|
|
110394
110523
|
const declaredUi = matchTypeV2ToUi(matchTypeRaw);
|
|
110395
110524
|
const normalized = [];
|
|
110396
110525
|
const seen = /* @__PURE__ */ new Set();
|
|
@@ -110398,7 +110527,7 @@ function normalizeKeywordTextList(texts, matchTypeRaw, path23, fieldLabel, error
|
|
|
110398
110527
|
for (let k = 0; k < texts.length; k++) {
|
|
110399
110528
|
const raw = texts[k];
|
|
110400
110529
|
if (typeof raw !== "string" || !raw.trim()) {
|
|
110401
|
-
errors.push(`${
|
|
110530
|
+
errors.push(`${path24}.${fieldLabel}[${k}] \u5FC5\u987B\u662F\u975E\u7A7A\u5B57\u7B26\u4E32`);
|
|
110402
110531
|
continue;
|
|
110403
110532
|
}
|
|
110404
110533
|
const trimmedRaw = collapseDuplicateSpacesInKeywordText(raw.trim());
|
|
@@ -110406,7 +110535,7 @@ function normalizeKeywordTextList(texts, matchTypeRaw, path23, fieldLabel, error
|
|
|
110406
110535
|
const { formatted, matchType, inferredMatchType } = normalizeKeywordSurface(trimmedRaw, matchTypeRaw);
|
|
110407
110536
|
pushKeywordAutoFixWarning(
|
|
110408
110537
|
warnings,
|
|
110409
|
-
|
|
110538
|
+
path24,
|
|
110410
110539
|
fieldLabel,
|
|
110411
110540
|
trimmedRaw,
|
|
110412
110541
|
formatted,
|
|
@@ -110416,10 +110545,10 @@ function normalizeKeywordTextList(texts, matchTypeRaw, path23, fieldLabel, error
|
|
|
110416
110545
|
inferredMatchType
|
|
110417
110546
|
);
|
|
110418
110547
|
const core = unwrapKeywordDisplayTextForEdit(formatted);
|
|
110419
|
-
if (!validateKeywordCore(core, `${
|
|
110548
|
+
if (!validateKeywordCore(core, `${path24}.${fieldLabel}[${k}]`, errors, lengthViolations)) continue;
|
|
110420
110549
|
const dedupeKey = `${matchTypeUiToV2(matchType)}:${core.toLowerCase()}`;
|
|
110421
110550
|
if (seen.has(dedupeKey)) {
|
|
110422
|
-
warnings.push(`${
|
|
110551
|
+
warnings.push(`${path24}.${fieldLabel}[${k}] \u4E0E\u540C\u7EC4\u91CD\u590D\uFF0C\u5DF2\u8DF3\u8FC7\uFF1A${formatted}`);
|
|
110423
110552
|
continue;
|
|
110424
110553
|
}
|
|
110425
110554
|
seen.add(dedupeKey);
|
|
@@ -110428,12 +110557,12 @@ function normalizeKeywordTextList(texts, matchTypeRaw, path23, fieldLabel, error
|
|
|
110428
110557
|
}
|
|
110429
110558
|
return { normalized, resolvedUi };
|
|
110430
110559
|
}
|
|
110431
|
-
function normalizeKeywordsForBatchJobBlock(block,
|
|
110560
|
+
function normalizeKeywordsForBatchJobBlock(block, path24, errors, warnings, lengthViolations) {
|
|
110432
110561
|
const matchTypeRaw = readBlockMatchTypeRaw(block);
|
|
110433
110562
|
const declaredUi = matchTypeV2ToUi(matchTypeRaw);
|
|
110434
110563
|
if (matchTypeRaw !== void 0 && declaredUi === null) {
|
|
110435
110564
|
errors.push(
|
|
110436
|
-
`${
|
|
110565
|
+
`${path24}.MatchTypeV2 \u65E0\u6548\uFF08${String(matchTypeRaw)}\uFF09\uFF0C\u5408\u6CD5\u503C\uFF1ABROAD | PHRASE | EXACT`
|
|
110437
110566
|
);
|
|
110438
110567
|
return;
|
|
110439
110568
|
}
|
|
@@ -110448,7 +110577,7 @@ function normalizeKeywordsForBatchJobBlock(block, path23, errors, warnings, leng
|
|
|
110448
110577
|
const result = normalizeKeywordTextList(
|
|
110449
110578
|
texts,
|
|
110450
110579
|
matchTypeRaw,
|
|
110451
|
-
|
|
110580
|
+
path24,
|
|
110452
110581
|
"KeywordText",
|
|
110453
110582
|
errors,
|
|
110454
110583
|
warnings,
|
|
@@ -110457,7 +110586,7 @@ function normalizeKeywordsForBatchJobBlock(block, path23, errors, warnings, leng
|
|
|
110457
110586
|
normalizedTexts = result.normalized;
|
|
110458
110587
|
if (result.resolvedUi) resolvedUi = result.resolvedUi;
|
|
110459
110588
|
if (normalizedTexts.length === 0 && texts.length > 0) {
|
|
110460
|
-
errors.push(`${
|
|
110589
|
+
errors.push(`${path24}.KeywordText \u7ECF\u6821\u9A8C\u540E\u65E0\u6709\u6548\u5173\u952E\u8BCD\uFF0C\u8BF7\u4FEE\u6B63\u8BCD\u9762\u6216 MatchTypeV2`);
|
|
110461
110590
|
}
|
|
110462
110591
|
}
|
|
110463
110592
|
if (hasItems && items) {
|
|
@@ -110465,12 +110594,12 @@ function normalizeKeywordsForBatchJobBlock(block, path23, errors, warnings, leng
|
|
|
110465
110594
|
for (let k = 0; k < items.length; k++) {
|
|
110466
110595
|
const item = items[k];
|
|
110467
110596
|
if (!item || typeof item !== "object") {
|
|
110468
|
-
errors.push(`${
|
|
110597
|
+
errors.push(`${path24}.Items[${k}] \u5FC5\u987B\u662F\u5BF9\u8C61`);
|
|
110469
110598
|
continue;
|
|
110470
110599
|
}
|
|
110471
110600
|
const raw = readItemText(item);
|
|
110472
110601
|
if (raw === null || !raw.trim()) {
|
|
110473
|
-
errors.push(`${
|
|
110602
|
+
errors.push(`${path24}.Items[${k}].Text \u5FC5\u987B\u662F\u975E\u7A7A\u5B57\u7B26\u4E32`);
|
|
110474
110603
|
continue;
|
|
110475
110604
|
}
|
|
110476
110605
|
const trimmedRaw = collapseDuplicateSpacesInKeywordText(raw.trim());
|
|
@@ -110478,7 +110607,7 @@ function normalizeKeywordsForBatchJobBlock(block, path23, errors, warnings, leng
|
|
|
110478
110607
|
const { formatted, matchType, inferredMatchType } = normalizeKeywordSurface(trimmedRaw, matchTypeRaw);
|
|
110479
110608
|
pushKeywordAutoFixWarning(
|
|
110480
110609
|
warnings,
|
|
110481
|
-
|
|
110610
|
+
path24,
|
|
110482
110611
|
`Items[${k}].Text`,
|
|
110483
110612
|
trimmedRaw,
|
|
110484
110613
|
formatted,
|
|
@@ -110488,10 +110617,10 @@ function normalizeKeywordsForBatchJobBlock(block, path23, errors, warnings, leng
|
|
|
110488
110617
|
inferredMatchType
|
|
110489
110618
|
);
|
|
110490
110619
|
const core = unwrapKeywordDisplayTextForEdit(formatted);
|
|
110491
|
-
if (!validateKeywordCore(core, `${
|
|
110620
|
+
if (!validateKeywordCore(core, `${path24}.Items[${k}].Text`, errors, lengthViolations)) continue;
|
|
110492
110621
|
const dedupeKey = `${matchTypeUiToV2(matchType)}:${core.toLowerCase()}`;
|
|
110493
110622
|
if (seen.has(dedupeKey)) {
|
|
110494
|
-
warnings.push(`${
|
|
110623
|
+
warnings.push(`${path24}.Items[${k}].Text \u4E0E\u540C\u7EC4\u91CD\u590D\uFF0C\u5DF2\u8DF3\u8FC7\uFF1A${formatted}`);
|
|
110495
110624
|
continue;
|
|
110496
110625
|
}
|
|
110497
110626
|
seen.add(dedupeKey);
|
|
@@ -112925,7 +113054,7 @@ init_cli_table();
|
|
|
112925
113054
|
// src/commands/ad/campaign-batch-diff.ts
|
|
112926
113055
|
init_auth();
|
|
112927
113056
|
init_cli_json_snapshot();
|
|
112928
|
-
function
|
|
113057
|
+
function asRecord2(v) {
|
|
112929
113058
|
return v && typeof v === "object" && !Array.isArray(v) ? v : null;
|
|
112930
113059
|
}
|
|
112931
113060
|
function pickString(...vals) {
|
|
@@ -112979,7 +113108,7 @@ function liveAdHasHeadline(ad, headline) {
|
|
|
112979
113108
|
function formatExtensionPlanned(ext) {
|
|
112980
113109
|
if (!ext) return "\u2014";
|
|
112981
113110
|
const type = pickString(ext["typeV2"], ext["AssetFieldType"], ext["type"]);
|
|
112982
|
-
const props =
|
|
113111
|
+
const props = asRecord2(ext["Properties"]);
|
|
112983
113112
|
const phone = props ? pickString(props["PhoneNumber"], props["phoneNumber"]) : "";
|
|
112984
113113
|
const code = props ? pickString(props["ContryCode"], props["CountryCode"]) : "";
|
|
112985
113114
|
const parts = [type ? `\u7C7B\u578B: ${type}` : "", code || phone ? `\u7535\u8BDD: ${code}${phone}` : ""].filter(Boolean);
|
|
@@ -112990,13 +113119,13 @@ function listPlannedKeywords(campaign) {
|
|
|
112990
113119
|
if (!Array.isArray(groups)) return [];
|
|
112991
113120
|
const out = [];
|
|
112992
113121
|
for (let gi = 0; gi < groups.length; gi++) {
|
|
112993
|
-
const g =
|
|
113122
|
+
const g = asRecord2(groups[gi]);
|
|
112994
113123
|
if (!g) continue;
|
|
112995
113124
|
const groupName = pickString(g["Name"], g["name"]) || `AdGroupsForBatchJob[${gi}]`;
|
|
112996
113125
|
const blocks = g["KeywordsForBatchJob"];
|
|
112997
113126
|
if (!Array.isArray(blocks)) continue;
|
|
112998
113127
|
for (let bi = 0; bi < blocks.length; bi++) {
|
|
112999
|
-
const block =
|
|
113128
|
+
const block = asRecord2(blocks[bi]);
|
|
113000
113129
|
if (!block) continue;
|
|
113001
113130
|
const matchTypeV2 = pickString(block["MatchTypeV2"], block["matchTypeV2"]) || "BROAD";
|
|
113002
113131
|
const texts = block["KeywordText"];
|
|
@@ -113020,7 +113149,7 @@ function listPlannedNegativeKeywords(campaign) {
|
|
|
113020
113149
|
if (!Array.isArray(blocks)) return [];
|
|
113021
113150
|
const out = [];
|
|
113022
113151
|
for (let bi = 0; bi < blocks.length; bi++) {
|
|
113023
|
-
const block =
|
|
113152
|
+
const block = asRecord2(blocks[bi]);
|
|
113024
113153
|
if (!block) continue;
|
|
113025
113154
|
const matchTypeV2 = pickString(block["MatchTypeV2"], block["matchTypeV2"]) || "BROAD";
|
|
113026
113155
|
const texts = block["KeywordText"];
|
|
@@ -113060,7 +113189,7 @@ function compareCampaignCreateToLive(cfg, campaignId, live, meta) {
|
|
|
113060
113189
|
const plannedGroupCount = Array.isArray(groups) ? groups.length : 0;
|
|
113061
113190
|
if (Array.isArray(groups)) {
|
|
113062
113191
|
for (let gi = 0; gi < groups.length; gi++) {
|
|
113063
|
-
const g =
|
|
113192
|
+
const g = asRecord2(groups[gi]);
|
|
113064
113193
|
if (!g) continue;
|
|
113065
113194
|
const groupName = pickString(g["Name"], g["name"]) || `AdGroupsForBatchJob[${gi}]`;
|
|
113066
113195
|
const groupPath = `campaign.AdGroupsForBatchJob[${gi}]`;
|
|
@@ -113091,7 +113220,7 @@ function compareCampaignCreateToLive(cfg, campaignId, live, meta) {
|
|
|
113091
113220
|
const blocks = g["KeywordsForBatchJob"];
|
|
113092
113221
|
if (Array.isArray(blocks)) {
|
|
113093
113222
|
for (let bi = 0; bi < blocks.length; bi++) {
|
|
113094
|
-
const block =
|
|
113223
|
+
const block = asRecord2(blocks[bi]);
|
|
113095
113224
|
if (!block) continue;
|
|
113096
113225
|
const matchTypeV2 = pickString(block["MatchTypeV2"], block["matchTypeV2"]) || "BROAD";
|
|
113097
113226
|
const texts = block["KeywordText"];
|
|
@@ -113099,12 +113228,12 @@ function compareCampaignCreateToLive(cfg, campaignId, live, meta) {
|
|
|
113099
113228
|
for (let ki = 0; ki < texts.length; ki++) {
|
|
113100
113229
|
const t = texts[ki];
|
|
113101
113230
|
if (typeof t !== "string" || !t.trim()) continue;
|
|
113102
|
-
const
|
|
113231
|
+
const path24 = `${groupPath}.KeywordsForBatchJob[${bi}].KeywordText[${ki}]`;
|
|
113103
113232
|
const key = keywordKey(t, matchTypeV2);
|
|
113104
113233
|
if (!liveKwKeys.has(key)) {
|
|
113105
113234
|
missing.push({
|
|
113106
113235
|
layer: "keyword",
|
|
113107
|
-
path:
|
|
113236
|
+
path: path24,
|
|
113108
113237
|
adGroupName: groupName,
|
|
113109
113238
|
plannedContent: `\u8BCD\u9762: ${t} | \u5339\u914D: ${matchTypeV2}`,
|
|
113110
113239
|
liveNote: `\u540C\u7EC4\u5DF2\u6709 ${liveKwInGroup.length} \u6761\u5173\u952E\u8BCD\uFF0C\u65E0\u952E ${key}`,
|
|
@@ -113120,14 +113249,14 @@ function compareCampaignCreateToLive(cfg, campaignId, live, meta) {
|
|
|
113120
113249
|
const ads = g["AdsForBatchJob"];
|
|
113121
113250
|
if (Array.isArray(ads)) {
|
|
113122
113251
|
for (let ai = 0; ai < ads.length; ai++) {
|
|
113123
|
-
const ad =
|
|
113252
|
+
const ad = asRecord2(ads[ai]);
|
|
113124
113253
|
if (!ad) continue;
|
|
113125
|
-
const
|
|
113254
|
+
const path24 = `${groupPath}.AdsForBatchJob[${ai}]`;
|
|
113126
113255
|
const primary = pickString(ad["headlinePart1"], ad["AdTitle"]);
|
|
113127
113256
|
if (!primary) {
|
|
113128
113257
|
missing.push({
|
|
113129
113258
|
layer: "ad",
|
|
113130
|
-
path:
|
|
113259
|
+
path: path24,
|
|
113131
113260
|
adGroupName: groupName,
|
|
113132
113261
|
plannedContent: `AdsForBatchJob[${ai}]\uFF08\u7F3A\u5C11 headlinePart1\uFF0C\u65E0\u6CD5\u6BD4\u5BF9\uFF09`,
|
|
113133
113262
|
liveNote: `\u540C\u7EC4\u5DF2\u6709 ${liveAdsInGroup.length} \u6761\u521B\u610F`,
|
|
@@ -113140,7 +113269,7 @@ function compareCampaignCreateToLive(cfg, campaignId, live, meta) {
|
|
|
113140
113269
|
if (!found) {
|
|
113141
113270
|
missing.push({
|
|
113142
113271
|
layer: "ad",
|
|
113143
|
-
path:
|
|
113272
|
+
path: path24,
|
|
113144
113273
|
adGroupName: groupName,
|
|
113145
113274
|
plannedContent: `RSA \u9996\u6807\u9898: ${primary}${finalUrl ? ` | \u843D\u5730\u9875: ${finalUrl}` : ""}`,
|
|
113146
113275
|
liveNote: `\u540C\u7EC4\u5DF2\u6709 ${liveAdsInGroup.length} \u6761 RSA\uFF0C\u65E0\u6B64\u9996\u6807\u9898`,
|
|
@@ -113176,7 +113305,7 @@ function compareCampaignCreateToLive(cfg, campaignId, live, meta) {
|
|
|
113176
113305
|
).length;
|
|
113177
113306
|
if (plannedExt > liveExt && Array.isArray(extBlocks)) {
|
|
113178
113307
|
for (let ei = liveExt; ei < extBlocks.length; ei++) {
|
|
113179
|
-
const ext =
|
|
113308
|
+
const ext = asRecord2(extBlocks[ei]);
|
|
113180
113309
|
missing.push({
|
|
113181
113310
|
layer: "extension",
|
|
113182
113311
|
path: `campaign.ExtensionsForBatchJob[${ei}]`,
|
|
@@ -113204,7 +113333,7 @@ function compareCampaignCreateToLive(cfg, campaignId, live, meta) {
|
|
|
113204
113333
|
plannedKeywords: plannedKeywords.length,
|
|
113205
113334
|
liveKeywords: liveKwCount,
|
|
113206
113335
|
plannedAds: Array.isArray(groups) ? groups.reduce((n, g) => {
|
|
113207
|
-
const gr =
|
|
113336
|
+
const gr = asRecord2(g);
|
|
113208
113337
|
const ads = gr?.["AdsForBatchJob"];
|
|
113209
113338
|
return n + (Array.isArray(ads) ? ads.length : 0);
|
|
113210
113339
|
}, 0) : 0,
|
|
@@ -113278,7 +113407,7 @@ async function fetchLiveSnapshotForCampaign(config, accountId, campaignId, campa
|
|
|
113278
113407
|
};
|
|
113279
113408
|
}
|
|
113280
113409
|
function resolveCampaignIdFromBatch(record) {
|
|
113281
|
-
const campaign =
|
|
113410
|
+
const campaign = asRecord2(record["campaign"]);
|
|
113282
113411
|
return pickString(campaign?.["Id"], campaign?.["id"], record["campaignId"]);
|
|
113283
113412
|
}
|
|
113284
113413
|
function shellArgPath(p) {
|
|
@@ -113887,14 +114016,31 @@ var VALID_PMAX_BIDDING_STRATEGIES = [
|
|
|
113887
114016
|
"TARGET_CPA",
|
|
113888
114017
|
"TARGET_ROAS"
|
|
113889
114018
|
];
|
|
114019
|
+
var PMAX_HEADLINE_MIN = 3;
|
|
114020
|
+
var PMAX_HEADLINE_MAX = 15;
|
|
114021
|
+
var PMAX_HEADLINE_CHAR_MAX = 30;
|
|
114022
|
+
var PMAX_LONG_HEADLINE_MIN = 1;
|
|
114023
|
+
var PMAX_LONG_HEADLINE_MAX = 5;
|
|
114024
|
+
var PMAX_LONG_HEADLINE_CHAR_MAX = 90;
|
|
114025
|
+
var PMAX_DESCRIPTION_MIN = 2;
|
|
114026
|
+
var PMAX_DESCRIPTION_MAX = 5;
|
|
114027
|
+
var PMAX_DESCRIPTION_CHAR_MAX = 90;
|
|
114028
|
+
var PMAX_BUSINESS_NAME_CHAR_MAX = 25;
|
|
114029
|
+
var PMAX_MARKETING_IMAGE_MIN = 1;
|
|
114030
|
+
var PMAX_SQUARE_MARKETING_IMAGE_MIN = 1;
|
|
114031
|
+
var PMAX_LOGO_IMAGE_MIN = 1;
|
|
114032
|
+
var PMAX_LOGO_IMAGE_MAX = 5;
|
|
114033
|
+
var PMAX_FINAL_URL_MIN = 1;
|
|
114034
|
+
var PMAX_YOUTUBE_VIDEO_MAX_PER_CREATE = 1;
|
|
114035
|
+
var PMAX_YOUTUBE_VIDEO_MAX_PER_ASSET_GROUP = 15;
|
|
114036
|
+
var PMAX_YOUTUBE_VIDEO_MIN_DURATION_SEC = 10;
|
|
113890
114037
|
var URL_REGEX2 = /^https?:\/\/.+/;
|
|
113891
|
-
var HEADLINE_MAX = 30;
|
|
113892
|
-
var LONG_HEADLINE_MAX = 90;
|
|
113893
|
-
var DESCRIPTION_MAX = 90;
|
|
113894
|
-
var BUSINESS_NAME_MAX = 25;
|
|
113895
114038
|
function pushErr3(errors, msg) {
|
|
113896
114039
|
errors.push(msg);
|
|
113897
114040
|
}
|
|
114041
|
+
function pushWarn3(warnings, msg) {
|
|
114042
|
+
warnings.push(msg);
|
|
114043
|
+
}
|
|
113898
114044
|
function nonEmptyStrings(list) {
|
|
113899
114045
|
return (list ?? []).map((s) => s?.trim()).filter((s) => Boolean(s));
|
|
113900
114046
|
}
|
|
@@ -113964,8 +114110,11 @@ function runPmaxCreateValidation(cfg) {
|
|
|
113964
114110
|
pushErr3(errors, "budget \u5FC5\u987B\u662F\u5927\u4E8E 0 \u7684\u6570\u5B57\uFF08\u4E3B\u5E01\u79CD\u300C\u5143\u300D\uFF09");
|
|
113965
114111
|
}
|
|
113966
114112
|
const finalUrls = nonEmptyStrings(cfg.finalUrls);
|
|
113967
|
-
if (finalUrls.length
|
|
113968
|
-
pushErr3(
|
|
114113
|
+
if (finalUrls.length < PMAX_FINAL_URL_MIN) {
|
|
114114
|
+
pushErr3(
|
|
114115
|
+
errors,
|
|
114116
|
+
`finalUrls\uFF08\u5230\u8FBE\u7F51\u5740\uFF09\u81F3\u5C11 ${PMAX_FINAL_URL_MIN} \u4E2A\u6709\u6548 URL\uFF08\u987B\u4E0E\u4E1A\u52A1\u57DF\u540D\u4E00\u81F4\uFF0C\u7531 Google \u5BA1\u6838\uFF09`
|
|
114117
|
+
);
|
|
113969
114118
|
} else {
|
|
113970
114119
|
for (const u of finalUrls) {
|
|
113971
114120
|
if (!URL_REGEX2.test(u)) {
|
|
@@ -113976,34 +114125,58 @@ function runPmaxCreateValidation(cfg) {
|
|
|
113976
114125
|
const headlines = nonEmptyStrings(cfg.headlines);
|
|
113977
114126
|
const descriptions = nonEmptyStrings(cfg.descriptions);
|
|
113978
114127
|
const longHeadlines = nonEmptyStrings(cfg.longHeadlines);
|
|
113979
|
-
if (headlines.length <
|
|
113980
|
-
pushErr3(
|
|
114128
|
+
if (headlines.length < PMAX_HEADLINE_MIN) {
|
|
114129
|
+
pushErr3(
|
|
114130
|
+
errors,
|
|
114131
|
+
`headlines\uFF08HEADLINE \u77ED\u6807\u9898\uFF09\u81F3\u5C11 ${PMAX_HEADLINE_MIN} \u6761\u3001\u6700\u591A ${PMAX_HEADLINE_MAX} \u6761\u975E\u7A7A\u6807\u9898\uFF0C\u5F53\u524D ${headlines.length} \u6761`
|
|
114132
|
+
);
|
|
114133
|
+
} else if (headlines.length > PMAX_HEADLINE_MAX) {
|
|
114134
|
+
pushErr3(
|
|
114135
|
+
errors,
|
|
114136
|
+
`headlines\uFF08HEADLINE \u77ED\u6807\u9898\uFF09\u6700\u591A ${PMAX_HEADLINE_MAX} \u6761\uFF0C\u5F53\u524D ${headlines.length} \u6761`
|
|
114137
|
+
);
|
|
113981
114138
|
}
|
|
113982
|
-
if (descriptions.length <
|
|
113983
|
-
pushErr3(
|
|
114139
|
+
if (descriptions.length < PMAX_DESCRIPTION_MIN) {
|
|
114140
|
+
pushErr3(
|
|
114141
|
+
errors,
|
|
114142
|
+
`descriptions\uFF08DESCRIPTION \u63CF\u8FF0\uFF09\u81F3\u5C11 ${PMAX_DESCRIPTION_MIN} \u6761\u3001\u6700\u591A ${PMAX_DESCRIPTION_MAX} \u6761\uFF0C\u5F53\u524D ${descriptions.length} \u6761`
|
|
114143
|
+
);
|
|
114144
|
+
} else if (descriptions.length > PMAX_DESCRIPTION_MAX) {
|
|
114145
|
+
pushErr3(
|
|
114146
|
+
errors,
|
|
114147
|
+
`descriptions\uFF08DESCRIPTION \u63CF\u8FF0\uFF09\u6700\u591A ${PMAX_DESCRIPTION_MAX} \u6761\uFF0C\u5F53\u524D ${descriptions.length} \u6761`
|
|
114148
|
+
);
|
|
113984
114149
|
}
|
|
113985
|
-
if (longHeadlines.length <
|
|
113986
|
-
pushErr3(
|
|
114150
|
+
if (longHeadlines.length < PMAX_LONG_HEADLINE_MIN) {
|
|
114151
|
+
pushErr3(
|
|
114152
|
+
errors,
|
|
114153
|
+
`longHeadlines\uFF08LONG_HEADLINE \u957F\u6807\u9898\uFF09\u81F3\u5C11 ${PMAX_LONG_HEADLINE_MIN} \u6761\u3001\u6700\u591A ${PMAX_LONG_HEADLINE_MAX} \u6761\uFF0C\u5F53\u524D ${longHeadlines.length} \u6761`
|
|
114154
|
+
);
|
|
114155
|
+
} else if (longHeadlines.length > PMAX_LONG_HEADLINE_MAX) {
|
|
114156
|
+
pushErr3(
|
|
114157
|
+
errors,
|
|
114158
|
+
`longHeadlines\uFF08LONG_HEADLINE \u957F\u6807\u9898\uFF09\u6700\u591A ${PMAX_LONG_HEADLINE_MAX} \u6761\uFF0C\u5F53\u524D ${longHeadlines.length} \u6761`
|
|
114159
|
+
);
|
|
113987
114160
|
}
|
|
113988
114161
|
if (!cfg.businessName?.trim()) {
|
|
113989
|
-
pushErr3(errors, "businessName\
|
|
114162
|
+
pushErr3(errors, "businessName\uFF08BUSINESS_NAME \u5546\u5BB6\u540D\u79F0\uFF09\u5FC5\u586B\u4E14\u4EC5 1 \u6761");
|
|
113990
114163
|
}
|
|
113991
114164
|
if (!hasImageSource(cfg, "marketing")) {
|
|
113992
114165
|
pushErr3(
|
|
113993
114166
|
errors,
|
|
113994
|
-
|
|
114167
|
+
`MARKETING_IMAGE\uFF08\u6A2A\u56FE 1.91:1\uFF0C\u22645MB\uFF09\u81F3\u5C11 ${PMAX_MARKETING_IMAGE_MIN} \u5F20\uFF1AimagePaths.marketing\uFF08\u63A8\u8350\uFF09\u6216 marketingImageAssetId / marketingImageBase64`
|
|
113995
114168
|
);
|
|
113996
114169
|
}
|
|
113997
114170
|
if (!hasImageSource(cfg, "square")) {
|
|
113998
114171
|
pushErr3(
|
|
113999
114172
|
errors,
|
|
114000
|
-
|
|
114173
|
+
`SQUARE_MARKETING_IMAGE\uFF08\u65B9\u56FE 1:1\uFF0C\u22645MB\uFF09\u81F3\u5C11 ${PMAX_SQUARE_MARKETING_IMAGE_MIN} \u5F20\uFF1AimagePaths.square \u6216 squareMarketingImageAssetId / squareMarketingImageBase64`
|
|
114001
114174
|
);
|
|
114002
114175
|
}
|
|
114003
114176
|
if (!hasImageSource(cfg, "logo")) {
|
|
114004
114177
|
pushErr3(
|
|
114005
114178
|
errors,
|
|
114006
|
-
|
|
114179
|
+
`LOGO\uFF08\u54C1\u724C\u5FBD\u6807 1:1\uFF0C\u22645MB\uFF09\u81F3\u5C11 ${PMAX_LOGO_IMAGE_MIN} \u5F20\u3001\u8D44\u4EA7\u7EC4\u6700\u591A ${PMAX_LOGO_IMAGE_MAX} \u5F20\uFF1AimagePaths.logo \u6216 logoImageAssetId / logoImageBase64`
|
|
114007
114180
|
);
|
|
114008
114181
|
}
|
|
114009
114182
|
const bidding = normalizeBidding(cfg.biddingStrategyTypeV2);
|
|
@@ -114043,17 +114216,31 @@ function runPmaxCreateValidation(cfg) {
|
|
|
114043
114216
|
}
|
|
114044
114217
|
}
|
|
114045
114218
|
const youtube = cfg.youtubeUrlOrId?.trim();
|
|
114219
|
+
const videoPath = cfg.videoPath?.trim();
|
|
114220
|
+
const videoCount = (youtube ? 1 : 0) + (videoPath ? 1 : 0);
|
|
114221
|
+
if (videoCount > PMAX_YOUTUBE_VIDEO_MAX_PER_CREATE) {
|
|
114222
|
+
pushErr3(
|
|
114223
|
+
errors,
|
|
114224
|
+
`YOUTUBE_VIDEO \u521B\u5EFA\u65F6\u6700\u591A\u94FE\u63A5 ${PMAX_YOUTUBE_VIDEO_MAX_PER_CREATE} \u6761\uFF08videoPath \u4E0E youtubeUrlOrId \u4E8C\u9009\u4E00\uFF09`
|
|
114225
|
+
);
|
|
114226
|
+
}
|
|
114046
114227
|
if (youtube && youtube.length < 6) {
|
|
114047
114228
|
pushErr3(errors, "youtubeUrlOrId \u8FC7\u77ED\uFF0C\u8BF7\u586B\u5199\u5B8C\u6574 YouTube URL \u6216 11 \u4F4D\u89C6\u9891 ID");
|
|
114048
114229
|
}
|
|
114230
|
+
if (videoPath) {
|
|
114231
|
+
pushWarn3(
|
|
114232
|
+
warnings,
|
|
114233
|
+
`\u672C\u5730\u89C6\u9891\u987B \u2265${PMAX_YOUTUBE_VIDEO_MIN_DURATION_SEC} \u79D2\u4E14\u4E3A\u6A2A/\u65B9/\u7AD6\u7248\u4E4B\u4E00\uFF1BCLI \u65E0\u6CD5\u5728 validate \u9636\u6BB5\u68C0\u6D4B\u65F6\u957F\uFF0C\u8BF7\u81EA\u884C\u786E\u8BA4`
|
|
114234
|
+
);
|
|
114235
|
+
}
|
|
114049
114236
|
validateTextLengths(
|
|
114050
114237
|
errors,
|
|
114051
114238
|
lengthViolations,
|
|
114052
114239
|
headlines,
|
|
114053
114240
|
"headlines",
|
|
114054
114241
|
"pmax_headline",
|
|
114055
|
-
|
|
114056
|
-
"headlines"
|
|
114242
|
+
PMAX_HEADLINE_CHAR_MAX,
|
|
114243
|
+
"headlines\uFF08HEADLINE\uFF09"
|
|
114057
114244
|
);
|
|
114058
114245
|
validateTextLengths(
|
|
114059
114246
|
errors,
|
|
@@ -114061,8 +114248,8 @@ function runPmaxCreateValidation(cfg) {
|
|
|
114061
114248
|
longHeadlines,
|
|
114062
114249
|
"longHeadlines",
|
|
114063
114250
|
"pmax_long_headline",
|
|
114064
|
-
|
|
114065
|
-
"longHeadlines"
|
|
114251
|
+
PMAX_LONG_HEADLINE_CHAR_MAX,
|
|
114252
|
+
"longHeadlines\uFF08LONG_HEADLINE\uFF09"
|
|
114066
114253
|
);
|
|
114067
114254
|
validateTextLengths(
|
|
114068
114255
|
errors,
|
|
@@ -114070,25 +114257,25 @@ function runPmaxCreateValidation(cfg) {
|
|
|
114070
114257
|
descriptions,
|
|
114071
114258
|
"descriptions",
|
|
114072
114259
|
"pmax_description",
|
|
114073
|
-
|
|
114074
|
-
"descriptions"
|
|
114260
|
+
PMAX_DESCRIPTION_CHAR_MAX,
|
|
114261
|
+
"descriptions\uFF08DESCRIPTION\uFF09"
|
|
114075
114262
|
);
|
|
114076
114263
|
if (cfg.businessName?.trim()) {
|
|
114077
114264
|
const bnText = cfg.businessName.trim();
|
|
114078
114265
|
const bn = calcGoogleCharLength(bnText);
|
|
114079
|
-
if (bn >
|
|
114266
|
+
if (bn > PMAX_BUSINESS_NAME_CHAR_MAX) {
|
|
114080
114267
|
pushLengthViolation(lengthViolations, {
|
|
114081
114268
|
path: "businessName",
|
|
114082
114269
|
field: "businessName",
|
|
114083
114270
|
kind: "pmax_business_name",
|
|
114084
|
-
limit:
|
|
114271
|
+
limit: PMAX_BUSINESS_NAME_CHAR_MAX,
|
|
114085
114272
|
actual: bn,
|
|
114086
114273
|
countMode: "google",
|
|
114087
114274
|
text: bnText
|
|
114088
114275
|
});
|
|
114089
114276
|
pushErr3(
|
|
114090
114277
|
errors,
|
|
114091
|
-
`businessName
|
|
114278
|
+
`businessName\uFF08BUSINESS_NAME\uFF09\u8D85\u8FC7 ${PMAX_BUSINESS_NAME_CHAR_MAX} \u5B57\u7B26\uFF08\u5F53\u524D ${bn}\uFF0CCJK \u8BA1 2\uFF09\uFF1A"${bnText}"`
|
|
114092
114279
|
);
|
|
114093
114280
|
}
|
|
114094
114281
|
}
|
|
@@ -114280,13 +114467,13 @@ function pmaxChannelTypesUrl(googleApiUrl) {
|
|
|
114280
114467
|
}
|
|
114281
114468
|
function pmaxCampaignUrl(googleApiUrl, accountId, campaignId) {
|
|
114282
114469
|
const base = googleApiUrl.replace(/\/$/, "");
|
|
114283
|
-
const
|
|
114284
|
-
return campaignId ? `${
|
|
114470
|
+
const path24 = `${base}/accounts/${accountId}/campaign/pmax`;
|
|
114471
|
+
return campaignId ? `${path24}/${campaignId}` : path24;
|
|
114285
114472
|
}
|
|
114286
114473
|
function pmaxAssetGroupUrl(googleApiUrl, accountId, assetGroupId, suffix) {
|
|
114287
114474
|
const base = googleApiUrl.replace(/\/$/, "");
|
|
114288
|
-
const
|
|
114289
|
-
return suffix ? `${
|
|
114475
|
+
const path24 = `${base}/accounts/${accountId}/campaign/pmax/asset-group/${assetGroupId}`;
|
|
114476
|
+
return suffix ? `${path24}/${suffix.replace(/^\//, "")}` : path24;
|
|
114290
114477
|
}
|
|
114291
114478
|
function pmaxCampaignAssetGroupUrl(googleApiUrl, accountId, campaignId) {
|
|
114292
114479
|
const base = googleApiUrl.replace(/\/$/, "");
|
|
@@ -114564,8 +114751,19 @@ function detectDeprecatedPmaxVideoKeys(raw) {
|
|
|
114564
114751
|
if ((key === "video" || key === "videoFile" || key === "localVideo") && normalized.videoPath?.trim()) {
|
|
114565
114752
|
continue;
|
|
114566
114753
|
}
|
|
114567
|
-
if (key === "videoPaths"
|
|
114568
|
-
|
|
114754
|
+
if (key === "videoPaths") {
|
|
114755
|
+
if (Array.isArray(v)) {
|
|
114756
|
+
const paths = v.filter((p) => typeof p === "string" && p.trim());
|
|
114757
|
+
if (paths.length > PMAX_YOUTUBE_VIDEO_MAX_PER_CREATE) {
|
|
114758
|
+
msgs.push(
|
|
114759
|
+
`videoPaths \u542B ${paths.length} \u4E2A\u672C\u5730\u89C6\u9891\uFF1Bpmax-create \u5355\u6B21\u6700\u591A ${PMAX_YOUTUBE_VIDEO_MAX_PER_CREATE} \u6761\uFF0C\u8BF7\u53EA\u4FDD\u7559\u4E00\u6761\u6216\u521B\u5EFA\u540E\u7528 ad pmax-youtube-link \u8FFD\u52A0`
|
|
114760
|
+
);
|
|
114761
|
+
continue;
|
|
114762
|
+
}
|
|
114763
|
+
}
|
|
114764
|
+
if (normalized.videoPath?.trim()) {
|
|
114765
|
+
continue;
|
|
114766
|
+
}
|
|
114569
114767
|
}
|
|
114570
114768
|
msgs.push(`\u914D\u7F6E\u542B\u5DF2\u5E9F\u5F03\u5B57\u6BB5\u300C${key}\u300D\uFF0C\u8BF7\u6539\u7528 videoPath\uFF08\u672C\u5730\u6587\u4EF6\uFF09\u6216 youtubeUrlOrId`);
|
|
114571
114769
|
}
|
|
@@ -114805,6 +115003,19 @@ function runPmaxVideoValidation(configFile, cfg) {
|
|
|
114805
115003
|
return { errors, warnings };
|
|
114806
115004
|
}
|
|
114807
115005
|
if (!videoPath) return { errors, warnings };
|
|
115006
|
+
const multiYoutube = cfg.youtubeUrls;
|
|
115007
|
+
if (Array.isArray(multiYoutube)) {
|
|
115008
|
+
const count = multiYoutube.filter((u) => typeof u === "string" && u.trim()).length;
|
|
115009
|
+
if (count > PMAX_YOUTUBE_VIDEO_MAX_PER_ASSET_GROUP) {
|
|
115010
|
+
errors.push(
|
|
115011
|
+
`youtubeUrls \u8D85\u8FC7\u8D44\u4EA7\u7EC4\u4E0A\u9650 ${PMAX_YOUTUBE_VIDEO_MAX_PER_ASSET_GROUP} \u6761\uFF08\u5F53\u524D ${count} \u6761\uFF09\uFF1B\u521B\u5EFA JSON \u8BF7\u4EC5\u7528 youtubeUrlOrId \u5355\u6761`
|
|
115012
|
+
);
|
|
115013
|
+
} else if (count > 1) {
|
|
115014
|
+
errors.push(
|
|
115015
|
+
`youtubeUrls \u6570\u7EC4\u542B ${count} \u6761\uFF1Bpmax-create \u4EC5\u652F\u6301\u5355\u6761 youtubeUrlOrId\uFF0C\u5176\u4F59\u8BF7\u521B\u5EFA\u540E\u7528 ad pmax-youtube-link \u8FFD\u52A0`
|
|
115016
|
+
);
|
|
115017
|
+
}
|
|
115018
|
+
}
|
|
114808
115019
|
if (!VIDEO_UPLOAD_SUFFIX.test(videoPath)) {
|
|
114809
115020
|
errors.push(
|
|
114810
115021
|
`videoPath \u6269\u5C55\u540D\u4E0D\u53D7\u652F\u6301\uFF08${videoPath}\uFF09\uFF0C\u8BF7\u4F7F\u7528 .mp4 / .mov / .webm / .avi / .mpeg / .mpg`
|
|
@@ -119559,8 +119770,18 @@ function register23(program2) {
|
|
|
119559
119770
|
}
|
|
119560
119771
|
|
|
119561
119772
|
// src/commands/open-account/_shared.ts
|
|
119562
|
-
function
|
|
119563
|
-
const
|
|
119773
|
+
function accountOpeningHistoryWebMediaType(mediaType) {
|
|
119774
|
+
const m = mediaType.trim();
|
|
119775
|
+
if (m === "MetaAd" || m === "Meta") return "Meta";
|
|
119776
|
+
return m;
|
|
119777
|
+
}
|
|
119778
|
+
function logAccountOpeningHistoryWebUrl(apiBaseUrl, mediaType) {
|
|
119779
|
+
const extraQuery = mediaType?.trim() ? { mediaType: accountOpeningHistoryWebMediaType(mediaType) } : void 0;
|
|
119780
|
+
const url = buildTsoPageWebUrl(
|
|
119781
|
+
deriveWebUrl(apiBaseUrl),
|
|
119782
|
+
"accountOpeningHistory",
|
|
119783
|
+
extraQuery
|
|
119784
|
+
);
|
|
119564
119785
|
console.log(` \u5982\u9700\u5728\u7F51\u9875\u67E5\u770B\u6216\u786E\u8BA4\uFF0C\u8BF7\u6253\u5F00\u300C\u5F00\u6237\u8BB0\u5F55\u300D\uFF1A
|
|
119565
119786
|
${url}
|
|
119566
119787
|
`);
|
|
@@ -119821,7 +120042,7 @@ async function runOpenAccountYandex(opts) {
|
|
|
119821
120042
|
opts.verbose
|
|
119822
120043
|
);
|
|
119823
120044
|
console.log("\n\u2705 Yandex \u5F00\u6237\u7533\u8BF7\u5DF2\u63D0\u4EA4\u6210\u529F\uFF0C\u8BF7\u5728\u300C\u5F00\u6237\u8BB0\u5F55\u300D\u9875\u9762\u67E5\u770B\u5BA1\u6838\u72B6\u6001\u3002\n");
|
|
119824
|
-
logAccountOpeningHistoryWebUrl(config.apiBaseUrl);
|
|
120045
|
+
logAccountOpeningHistoryWebUrl(config.apiBaseUrl, "Yandex");
|
|
119825
120046
|
if (opts.verbose && res != null) {
|
|
119826
120047
|
console.log("\u54CD\u5E94\uFF1A", JSON.stringify(res, null, 2));
|
|
119827
120048
|
}
|
|
@@ -119960,7 +120181,7 @@ async function runOpenAccountBing(opts) {
|
|
|
119960
120181
|
opts.verbose
|
|
119961
120182
|
);
|
|
119962
120183
|
console.log("\n\u2705 Bing \u5F00\u6237\u7533\u8BF7\u5DF2\u63D0\u4EA4\u6210\u529F\uFF0C\u8BF7\u5728\u300C\u5F00\u6237\u8BB0\u5F55\u300D\u9875\u9762\u67E5\u770B\u5BA1\u6838\u72B6\u6001\u3002\n");
|
|
119963
|
-
logAccountOpeningHistoryWebUrl(config.apiBaseUrl);
|
|
120184
|
+
logAccountOpeningHistoryWebUrl(config.apiBaseUrl, "BingV2");
|
|
119964
120185
|
} catch (err) {
|
|
119965
120186
|
console.error(`
|
|
119966
120187
|
\u274C \u63D0\u4EA4\u5931\u8D25\uFF1A${err instanceof Error ? err.message : String(err)}
|
|
@@ -120122,7 +120343,7 @@ async function runOpenAccountKwai(opts) {
|
|
|
120122
120343
|
opts.verbose
|
|
120123
120344
|
);
|
|
120124
120345
|
console.log("\n\u2705 Kwai \u5F00\u6237\u7533\u8BF7\u5DF2\u63D0\u4EA4\u6210\u529F\uFF0C\u8BF7\u5728\u300C\u5F00\u6237\u8BB0\u5F55\u300D\u9875\u9762\u67E5\u770B\u5BA1\u6838\u72B6\u6001\u3002\n");
|
|
120125
|
-
logAccountOpeningHistoryWebUrl(config.apiBaseUrl);
|
|
120346
|
+
logAccountOpeningHistoryWebUrl(config.apiBaseUrl, "Kwai");
|
|
120126
120347
|
} catch (err) {
|
|
120127
120348
|
console.error(`
|
|
120128
120349
|
\u274C \u63D0\u4EA4\u5931\u8D25\uFF1A${err instanceof Error ? err.message : String(err)}
|
|
@@ -120408,7 +120629,7 @@ async function runOpenAccountGoogle(opts) {
|
|
|
120408
120629
|
\u8BF7\u5728\u300C\u5F00\u6237\u8BB0\u5F55\u300D\u9875\u9762\u67E5\u770B\u5BA1\u6838\u72B6\u6001\u3002
|
|
120409
120630
|
`
|
|
120410
120631
|
);
|
|
120411
|
-
logAccountOpeningHistoryWebUrl(config.apiBaseUrl);
|
|
120632
|
+
logAccountOpeningHistoryWebUrl(config.apiBaseUrl, "Google");
|
|
120412
120633
|
} catch (err) {
|
|
120413
120634
|
console.error(`
|
|
120414
120635
|
\u274C \u63D0\u4EA4\u5931\u8D25\uFF1A${err instanceof Error ? err.message : String(err)}
|
|
@@ -120554,7 +120775,7 @@ async function runOpenAccountTikTok(opts) {
|
|
|
120554
120775
|
\u8BF7\u5728\u300C\u5F00\u6237\u8BB0\u5F55\u300D\u9875\u9762\u67E5\u770B\u5BA1\u6838\u72B6\u6001\u3002
|
|
120555
120776
|
`
|
|
120556
120777
|
);
|
|
120557
|
-
logAccountOpeningHistoryWebUrl(config.apiBaseUrl);
|
|
120778
|
+
logAccountOpeningHistoryWebUrl(config.apiBaseUrl, "TikTok");
|
|
120558
120779
|
} catch (err) {
|
|
120559
120780
|
console.error(`
|
|
120560
120781
|
\u274C \u63D0\u4EA4\u5931\u8D25\uFF1A${err instanceof Error ? err.message : String(err)}
|
|
@@ -120749,9 +120970,103 @@ TikTok \u6CE8\u518C\u5730\u5217\u8868\uFF08\u7B2C 1 \u9875\uFF0C\u672C\u9875 ${r
|
|
|
120749
120970
|
console.log();
|
|
120750
120971
|
}
|
|
120751
120972
|
|
|
120973
|
+
// src/commands/open-account/meta.ts
|
|
120974
|
+
init_auth();
|
|
120975
|
+
init_cli_json_snapshot();
|
|
120976
|
+
var META_OPEN_ACCOUNT_LINK_PATH = "/MetaAccount/Management/GetOpenAccountLink";
|
|
120977
|
+
function parseMetaOpenAccountLinkResponse(raw) {
|
|
120978
|
+
if (typeof raw === "string") {
|
|
120979
|
+
const t = raw.trim();
|
|
120980
|
+
if (t.startsWith("http://") || t.startsWith("https://")) return t;
|
|
120981
|
+
}
|
|
120982
|
+
if (raw && typeof raw === "object") {
|
|
120983
|
+
const o = raw;
|
|
120984
|
+
for (const key of [
|
|
120985
|
+
"url",
|
|
120986
|
+
"link",
|
|
120987
|
+
"openAccountLink",
|
|
120988
|
+
"openAccountUrl",
|
|
120989
|
+
"redirectUrl",
|
|
120990
|
+
"href"
|
|
120991
|
+
]) {
|
|
120992
|
+
const v = o[key];
|
|
120993
|
+
if (typeof v === "string") {
|
|
120994
|
+
const t = v.trim();
|
|
120995
|
+
if (t.startsWith("http://") || t.startsWith("https://")) return t;
|
|
120996
|
+
}
|
|
120997
|
+
}
|
|
120998
|
+
if (o.data !== void 0) {
|
|
120999
|
+
return parseMetaOpenAccountLinkResponse(o.data);
|
|
121000
|
+
}
|
|
121001
|
+
}
|
|
121002
|
+
throw new Error("\u63A5\u53E3\u672A\u8FD4\u56DE\u6709\u6548\u7684 Meta/Facebook \u5F00\u6237\u94FE\u63A5\uFF08\u987B\u4E3A https URL\uFF09");
|
|
121003
|
+
}
|
|
121004
|
+
function metaOpenAccountLinkApiUrl(apiBaseUrl) {
|
|
121005
|
+
const base = apiBaseUrl.replace(/\/$/, "");
|
|
121006
|
+
return `${base}${META_OPEN_ACCOUNT_LINK_PATH}`;
|
|
121007
|
+
}
|
|
121008
|
+
async function fetchMetaOpenAccountLink(config, verbose) {
|
|
121009
|
+
const url = metaOpenAccountLinkApiUrl(config.apiBaseUrl);
|
|
121010
|
+
const raw = await apiFetch2(url, config, {}, verbose);
|
|
121011
|
+
return parseMetaOpenAccountLinkResponse(raw);
|
|
121012
|
+
}
|
|
121013
|
+
async function runOpenAccountMeta(opts) {
|
|
121014
|
+
const config = loadConfig(opts.token);
|
|
121015
|
+
let openAccountUrl;
|
|
121016
|
+
try {
|
|
121017
|
+
openAccountUrl = await fetchMetaOpenAccountLink(config, opts.verbose);
|
|
121018
|
+
} catch (err) {
|
|
121019
|
+
console.error(
|
|
121020
|
+
`
|
|
121021
|
+
\u274C \u83B7\u53D6 Meta/Facebook \u5F00\u6237\u94FE\u63A5\u5931\u8D25\uFF1A${err instanceof Error ? err.message : String(err)}
|
|
121022
|
+
`
|
|
121023
|
+
);
|
|
121024
|
+
process.exit(1);
|
|
121025
|
+
}
|
|
121026
|
+
const payload = {
|
|
121027
|
+
ok: true,
|
|
121028
|
+
media: "MetaAd",
|
|
121029
|
+
openAccountUrl,
|
|
121030
|
+
note: "\u94FE\u63A5\u7531 Meta \u5B98\u65B9 OE \u751F\u6210\uFF0C\u6709\u65F6\u6548\uFF1B\u8BF7\u5728\u6D4F\u89C8\u5668\u4E2D\u5B8C\u6210\u5F00\u6237\uFF0C\u8FDB\u5EA6\u89C1 account-history -m MetaAd"
|
|
121031
|
+
};
|
|
121032
|
+
if (await emitCliJsonOrSnapshot(opts, {
|
|
121033
|
+
section: "open-account-meta",
|
|
121034
|
+
commandLabel: "open-account meta",
|
|
121035
|
+
payload
|
|
121036
|
+
})) {
|
|
121037
|
+
return;
|
|
121038
|
+
}
|
|
121039
|
+
console.log("\n\u8BF7\u6253\u5F00\u6B64\u94FE\u63A5\u7EE7\u7EED Facebook \u5F00\u6237\uFF1A\n");
|
|
121040
|
+
console.log(` ${openAccountUrl}
|
|
121041
|
+
`);
|
|
121042
|
+
if (opts.openBrowser) {
|
|
121043
|
+
const opened = tryOpenBrowser(openAccountUrl);
|
|
121044
|
+
if (opened) {
|
|
121045
|
+
console.log(" \u5DF2\u5728\u9ED8\u8BA4\u6D4F\u89C8\u5668\u4E2D\u6253\u5F00\u8BE5\u94FE\u63A5\u3002\n");
|
|
121046
|
+
}
|
|
121047
|
+
}
|
|
121048
|
+
logAccountOpeningHistoryWebUrl(config.apiBaseUrl, "MetaAd");
|
|
121049
|
+
}
|
|
121050
|
+
|
|
120752
121051
|
// src/commands/open-account-register.ts
|
|
120753
121052
|
function register24(program2) {
|
|
120754
|
-
const openAccountCmd = program2.command("open-account").description("\u5F00\u6237\u7533\u8BF7\uFF08Google / TikTok / Yandex / Bing / Kwai\uFF09");
|
|
121053
|
+
const openAccountCmd = program2.command("open-account").description("\u5F00\u6237\u7533\u8BF7\uFF08Google / TikTok / Yandex / Bing / Kwai / Meta \u5F00\u6237\u94FE\u63A5\uFF09");
|
|
121054
|
+
openAccountCmd.command("meta").description(
|
|
121055
|
+
"\u83B7\u53D6 Meta/Facebook \u5B98\u65B9\u5F00\u6237\u94FE\u63A5\uFF08GET MetaAccount/Management/GetOpenAccountLink\uFF0C\u4E0E\u7F51\u9875\u300C\u7533\u8BF7\u5F00\u6237\u300D\u4E00\u81F4\uFF09"
|
|
121056
|
+
).option("-t, --token <token>", "Auth Token").option("--open-browser", "\u5C1D\u8BD5\u7528\u7CFB\u7EDF\u9ED8\u8BA4\u6D4F\u89C8\u5668\u6253\u5F00\u94FE\u63A5").option(
|
|
121057
|
+
"--json-out <path>",
|
|
121058
|
+
"\u843D\u76D8 JSON\uFF08\u542B openAccountUrl\uFF09\uFF1Bstdout \u4E00\u884C\u6458\u8981",
|
|
121059
|
+
void 0
|
|
121060
|
+
).option("--verbose", "\u8BE6\u7EC6\u9519\u8BEF\u4FE1\u606F", false).action(
|
|
121061
|
+
async (opts) => {
|
|
121062
|
+
await runOpenAccountMeta({
|
|
121063
|
+
token: opts.token,
|
|
121064
|
+
openBrowser: opts.openBrowser,
|
|
121065
|
+
jsonOut: opts.jsonOut,
|
|
121066
|
+
verbose: opts.verbose
|
|
121067
|
+
});
|
|
121068
|
+
}
|
|
121069
|
+
);
|
|
120755
121070
|
openAccountCmd.command("list-groups").description("\u67E5\u8BE2\u5E7F\u544A\u4E3B\u7EC4\u5217\u8868\uFF08\u83B7\u53D6\u5F00\u6237\u6240\u9700\u7684 --advertiser-id\uFF09").option("-t, --token <token>", "Auth Token").option(
|
|
120756
121071
|
"--json-out <path>",
|
|
120757
121072
|
"\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",
|
|
@@ -121164,7 +121479,7 @@ async function runWebsiteDiagnosisCollect(opts) {
|
|
|
121164
121479
|
htmlPreview,
|
|
121165
121480
|
...htmlFull ? { htmlContent: htmlFull } : {},
|
|
121166
121481
|
...htmlError ? { htmlError } : {},
|
|
121167
|
-
agentHint: "
|
|
121482
|
+
agentHint: "1) \u6309 website-diagnosis-rules.md \u751F\u6210\u8BCA\u65AD JSON\uFF1B2) siluzan-tso website-diagnosis render --data <diagnosis.json> --collect <\u672C\u6587\u4EF6> \u8F93\u51FA\u5E26\u56FE\u8868\u7684 website-diagnosis-report.html\u3002"
|
|
121168
121483
|
};
|
|
121169
121484
|
if (await emitCliJsonOrSnapshot(
|
|
121170
121485
|
{ jsonOut: opts.jsonOut },
|
|
@@ -121180,6 +121495,77 @@ async function runWebsiteDiagnosisCollect(opts) {
|
|
|
121180
121495
|
console.log(JSON.stringify(payload, null, 2));
|
|
121181
121496
|
}
|
|
121182
121497
|
|
|
121498
|
+
// src/commands/website-diagnosis/render-report.ts
|
|
121499
|
+
import fs12 from "fs/promises";
|
|
121500
|
+
import path17 from "path";
|
|
121501
|
+
import { fileURLToPath as fileURLToPath4 } from "url";
|
|
121502
|
+
function websiteDiagnosisReportTemplatePath() {
|
|
121503
|
+
const dir = path17.dirname(fileURLToPath4(import.meta.url));
|
|
121504
|
+
return path17.join(dir, "skill", "siluzan-ads", "report-templates", "website-diagnosis-report.html");
|
|
121505
|
+
}
|
|
121506
|
+
function readJsonFile(filePath) {
|
|
121507
|
+
const raw = fs12.readFile(filePath, "utf8");
|
|
121508
|
+
return raw.then((text) => {
|
|
121509
|
+
try {
|
|
121510
|
+
return JSON.parse(text);
|
|
121511
|
+
} catch {
|
|
121512
|
+
throw new Error(`\u65E0\u6CD5\u89E3\u6790 JSON\uFF1A${filePath}`);
|
|
121513
|
+
}
|
|
121514
|
+
});
|
|
121515
|
+
}
|
|
121516
|
+
function asRecord3(value) {
|
|
121517
|
+
if (value && typeof value === "object" && !Array.isArray(value)) {
|
|
121518
|
+
return value;
|
|
121519
|
+
}
|
|
121520
|
+
throw new Error("\u8BCA\u65AD\u6570\u636E\u987B\u4E3A JSON \u5BF9\u8C61");
|
|
121521
|
+
}
|
|
121522
|
+
function mergeCollectLighthouse(data, collect) {
|
|
121523
|
+
const lighthouse = collect.lighthouse ?? collect.lighthouseResult;
|
|
121524
|
+
if (lighthouse == null) return data;
|
|
121525
|
+
return {
|
|
121526
|
+
...data,
|
|
121527
|
+
lighthouse: data.lighthouse ?? data.lighthouseResult ?? lighthouse,
|
|
121528
|
+
...collect.lighthouseWarning && !data.lighthouseWarning ? { lighthouseWarning: collect.lighthouseWarning } : {}
|
|
121529
|
+
};
|
|
121530
|
+
}
|
|
121531
|
+
function injectReportData(html, payload) {
|
|
121532
|
+
const json = JSON.stringify(payload).replace(/</g, "\\u003c");
|
|
121533
|
+
const marker = "window.__WEBSITE_DIAGNOSIS__ = window.__WEBSITE_DIAGNOSIS__ || null;";
|
|
121534
|
+
if (!html.includes(marker)) {
|
|
121535
|
+
throw new Error("\u62A5\u544A\u6A21\u677F\u7F3A\u5C11\u6570\u636E\u6CE8\u5165\u951A\u70B9\uFF0C\u8BF7\u66F4\u65B0 website-diagnosis-report.html");
|
|
121536
|
+
}
|
|
121537
|
+
return html.replace(marker, `window.__WEBSITE_DIAGNOSIS__ = ${json};`);
|
|
121538
|
+
}
|
|
121539
|
+
async function runWebsiteDiagnosisRender(opts) {
|
|
121540
|
+
const dataPath = path17.resolve(opts.dataFile);
|
|
121541
|
+
const dataRaw = await readJsonFile(dataPath);
|
|
121542
|
+
let data = asRecord3(dataRaw);
|
|
121543
|
+
if (opts.collectFile) {
|
|
121544
|
+
const collectRaw = await readJsonFile(path17.resolve(opts.collectFile));
|
|
121545
|
+
data = mergeCollectLighthouse(data, asRecord3(collectRaw));
|
|
121546
|
+
}
|
|
121547
|
+
const templatePath = websiteDiagnosisReportTemplatePath();
|
|
121548
|
+
let html;
|
|
121549
|
+
try {
|
|
121550
|
+
html = await fs12.readFile(templatePath, "utf8");
|
|
121551
|
+
} catch {
|
|
121552
|
+
console.error(`
|
|
121553
|
+
\u274C \u672A\u627E\u5230\u62A5\u544A\u6A21\u677F\uFF1A${templatePath}
|
|
121554
|
+
\u8BF7\u5148\u6267\u884C npm run build
|
|
121555
|
+
`);
|
|
121556
|
+
process.exit(1);
|
|
121557
|
+
}
|
|
121558
|
+
const outPath = path17.resolve(
|
|
121559
|
+
opts.out ?? path17.join(path17.dirname(dataPath), "website-diagnosis-report.html")
|
|
121560
|
+
);
|
|
121561
|
+
await fs12.mkdir(path17.dirname(outPath), { recursive: true });
|
|
121562
|
+
await fs12.writeFile(outPath, injectReportData(html, data), "utf8");
|
|
121563
|
+
console.log(`
|
|
121564
|
+
\u2705 \u7F51\u7AD9\u8BCA\u65AD HTML \u62A5\u544A\u5DF2\u751F\u6210\uFF1A${outPath}
|
|
121565
|
+
`);
|
|
121566
|
+
console.log("\u5728\u6D4F\u89C8\u5668\u4E2D\u6253\u5F00\u8BE5\u6587\u4EF6\u5373\u53EF\u67E5\u770B\u56FE\u8868\u4E0E\u5B8C\u6574\u7AE0\u8282\u3002\n");
|
|
121567
|
+
}
|
|
121568
|
+
|
|
121183
121569
|
// src/commands/website-diagnosis/register.ts
|
|
121184
121570
|
function registerWebsiteDiagnosisCommands(program2) {
|
|
121185
121571
|
const root = program2.command("website-diagnosis").description(
|
|
@@ -121215,6 +121601,15 @@ function registerWebsiteDiagnosisCommands(program2) {
|
|
|
121215
121601
|
});
|
|
121216
121602
|
}
|
|
121217
121603
|
);
|
|
121604
|
+
root.command("render").description(
|
|
121605
|
+
"\u6839\u636E\u8BCA\u65AD JSON \u751F\u6210\u5E26\u56FE\u8868\u7684\u5355\u6587\u4EF6 HTML \u62A5\u544A\uFF08website-diagnosis-report.html\uFF09"
|
|
121606
|
+
).requiredOption("--data <file>", "\u8BCA\u65AD\u7ED3\u679C JSON\uFF08getWebsiteDiagnosisData \u540C\u7ED3\u6784\uFF09").option("--collect <file>", "\u53EF\u9009\uFF1Acollect \u843D\u76D8 JSON\uFF0C\u7528\u4E8E\u5408\u5E76 lighthouse").option("--out <file>", "\u8F93\u51FA HTML \u8DEF\u5F84\uFF08\u9ED8\u8BA4\u540C --data \u76EE\u5F55\uFF09").action(async (opts) => {
|
|
121607
|
+
await runWebsiteDiagnosisRender({
|
|
121608
|
+
dataFile: opts.data,
|
|
121609
|
+
collectFile: opts.collect,
|
|
121610
|
+
out: opts.out
|
|
121611
|
+
});
|
|
121612
|
+
});
|
|
121218
121613
|
}
|
|
121219
121614
|
|
|
121220
121615
|
// src/index.ts
|
|
@@ -121324,7 +121719,7 @@ function endpointHintForFacebookSection(def, apiId) {
|
|
|
121324
121719
|
|
|
121325
121720
|
// src/commands/facebook-analysis/run-batch.ts
|
|
121326
121721
|
init_auth();
|
|
121327
|
-
import * as
|
|
121722
|
+
import * as path22 from "path";
|
|
121328
121723
|
import { performance as performance5 } from "perf_hooks";
|
|
121329
121724
|
init_version();
|
|
121330
121725
|
|
|
@@ -121428,7 +121823,7 @@ async function runAllFacebookSections(opts) {
|
|
|
121428
121823
|
const results = await runWithConcurrency2(tasks, concurrency);
|
|
121429
121824
|
const succeeded = results.filter((r) => r.ok).length;
|
|
121430
121825
|
const failed = results.length - succeeded;
|
|
121431
|
-
const absoluteSnapshotDir =
|
|
121826
|
+
const absoluteSnapshotDir = path22.resolve(opts.jsonOut);
|
|
121432
121827
|
const summary = {
|
|
121433
121828
|
kind: "siluzan-tso-facebook-analysis-snapshot-batch",
|
|
121434
121829
|
absoluteSnapshotDir,
|
|
@@ -121477,9 +121872,9 @@ init_cli_json_snapshot();
|
|
|
121477
121872
|
installProcessHandlers();
|
|
121478
121873
|
function getVersion() {
|
|
121479
121874
|
try {
|
|
121480
|
-
const __dirname3 =
|
|
121481
|
-
const pkgPath =
|
|
121482
|
-
const pkg = JSON.parse(
|
|
121875
|
+
const __dirname3 = path23.dirname(fileURLToPath5(import.meta.url));
|
|
121876
|
+
const pkgPath = path23.join(__dirname3, "..", "package.json");
|
|
121877
|
+
const pkg = JSON.parse(fs15.readFileSync(pkgPath, "utf8"));
|
|
121483
121878
|
return pkg.version ?? "0.0.0";
|
|
121484
121879
|
} catch {
|
|
121485
121880
|
return "0.0.0";
|