siluzan-tso-cli 1.1.19-beta.14 → 1.1.19-beta.15

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -51,7 +51,7 @@ siluzan-tso init -d /path/to/skills # 写入自定义目录
51
51
  siluzan-tso init --force # 强制覆盖已存在文件
52
52
  ```
53
53
 
54
- > **注意**:当前为测试版(1.1.19-beta.14),供内部测试使用。正式发布后安装命令将改为 `npm install -g siluzan-tso-cli`。
54
+ > **注意**:当前为测试版(1.1.19-beta.15),供内部测试使用。正式发布后安装命令将改为 `npm install -g siluzan-tso-cli`。
55
55
 
56
56
  | 助手 | 建议 `--ai` |
57
57
  | ----------------------- | ------------------------------------ |
package/dist/index.js CHANGED
@@ -4740,7 +4740,7 @@ var init_sections = __esm({
4740
4740
  description: "\u5173\u952E\u8BCD\u5206\u6BB5 KeywordSectionData",
4741
4741
  dateMode: "range",
4742
4742
  path: (id) => `/reporting/media-account/${id}/KeywordSectionData`,
4743
- defaultQuery: { limit: 100, orderByCost: true },
4743
+ defaultQuery: { limit: 200, orderByCost: true },
4744
4744
  keywordOptions: true
4745
4745
  },
4746
4746
  {
@@ -4748,7 +4748,7 @@ var init_sections = __esm({
4748
4748
  description: "\u641C\u7D22\u8BCD searchtermmanagement/v2/list",
4749
4749
  dateMode: "range",
4750
4750
  path: (id) => `/searchtermmanagement/v2/list/${id}`,
4751
- defaultQuery: { limit: 100, orderByCost: true },
4751
+ defaultQuery: { limit: 200, orderByCost: true },
4752
4752
  keywordOptions: true
4753
4753
  },
4754
4754
  {
@@ -5145,6 +5145,31 @@ async function fetchJson(config, pathWithQuery, verbose) {
5145
5145
  const url = `${config.googleApiUrl}${pathWithQuery}`;
5146
5146
  return apiFetch2(url, config, {}, verbose);
5147
5147
  }
5148
+ function deviceBidModifierLookupKey(campaignId, adGroupId, deviceType) {
5149
+ return `${campaignId ?? ""}\0${adGroupId ?? ""}\0${deviceType ?? ""}`;
5150
+ }
5151
+ function mergeDeviceBidModifiersIntoReport(report, modifiers) {
5152
+ const rows = report.devices;
5153
+ if (!Array.isArray(rows) || rows.length === 0) return report;
5154
+ if (!Array.isArray(modifiers) || modifiers.length === 0) return report;
5155
+ const byKey = /* @__PURE__ */ new Map();
5156
+ for (const m of modifiers) {
5157
+ byKey.set(
5158
+ deviceBidModifierLookupKey(m.campaignId, m.adGroupId, m.deviceType),
5159
+ m
5160
+ );
5161
+ }
5162
+ const devices = rows.map((row) => {
5163
+ const hit = byKey.get(deviceBidModifierLookupKey(row.campaignId, row.adGroupId, row.deviceType)) ?? (row.adGroupId ? void 0 : byKey.get(deviceBidModifierLookupKey(row.campaignId, null, row.deviceType)));
5164
+ if (!hit || hit.bidModifier === void 0) return row;
5165
+ return {
5166
+ ...row,
5167
+ bidModifier: hit.bidModifier,
5168
+ bidModifierSpecified: hit.bidModifierSpecified
5169
+ };
5170
+ });
5171
+ return { ...report, devices };
5172
+ }
5148
5173
  function assertNever(x, ctx) {
5149
5174
  throw new Error(`${ctx}\uFF1A\u672A\u5904\u7406\u7684\u5206\u652F ${String(x)}`);
5150
5175
  }
@@ -5248,6 +5273,23 @@ async function fetchSectionPayload(def, opts, config, id) {
5248
5273
  "materials"
5249
5274
  );
5250
5275
  }
5276
+ if (def.name === "campaign-device") {
5277
+ const sectionPath2 = def.path(id);
5278
+ const query2 = buildSearchParams(def, opts.start, opts.end, extras);
5279
+ const [report, modifiers] = await Promise.all([
5280
+ fetchJson(config, `${sectionPath2}${query2}`, !!opts.verbose),
5281
+ fetchJson(
5282
+ config,
5283
+ `/campaignmanagement/${id}/BidModifiers/Devices`,
5284
+ !!opts.verbose
5285
+ )
5286
+ ]);
5287
+ const data2 = mergeDeviceBidModifiersIntoReport(report, modifiers);
5288
+ return annotateZhFields(
5289
+ normalizeRateScales(stripLegacyGoogleFieldsIfV2Present(data2), def.name),
5290
+ def.name
5291
+ );
5292
+ }
5251
5293
  if (def.name === "daily-metrics") {
5252
5294
  const { startDate, endDate } = resolveDateRange2(opts.start, opts.end);
5253
5295
  const params = new URLSearchParams({
@@ -6859,7 +6901,7 @@ function registerGoogleAnalysisCommands(program2) {
6859
6901
  "--concurrency <n>",
6860
6902
  "\u5E76\u53D1\u6570\uFF0C\u9ED8\u8BA4 5\uFF1B\u4E0A\u9650 16\uFF08\u4E0E http-raw maxSockets \u5BF9\u9F50\uFF09\uFF1B\u8D26\u6237\u5927\u6216\u7F51\u7EDC\u6162\u65F6\u8C03\u5C0F",
6861
6903
  (v) => parseInt(v, 10)
6862
- ).option("--limit <n>", "\u900F\u4F20\u7ED9 keywords / search-terms \u7EF4\u5EA6\u7684\u6761\u6570\u4E0A\u9650", (v) => parseInt(v, 10)).option("--no-order-by-cost", "\u900F\u4F20\uFF1Akeywords / search-terms \u4E0D\u6309\u6D88\u8017\u6392\u5E8F", false).option("--level <level>", "\u900F\u4F20\u7ED9 extensions \u7EF4\u5EA6\u7684 level \u8FC7\u6EE4\uFF1AAccount | Campaign | Ad Group").option(
6904
+ ).option("--limit <n>", "\u900F\u4F20\u7ED9 keywords / search-terms \u7EF4\u5EA6\u7684\u6761\u6570\u4E0A\u9650\uFF08\u9ED8\u8BA4 200\uFF09", (v) => parseInt(v, 10)).option("--no-order-by-cost", "\u900F\u4F20\uFF1Akeywords / search-terms \u4E0D\u6309\u6D88\u8017\u6392\u5E8F", false).option("--level <level>", "\u900F\u4F20\u7ED9 extensions \u7EF4\u5EA6\u7684 level \u8FC7\u6EE4\uFF1AAccount | Campaign | Ad Group").option(
6863
6905
  "--audience-type <type>",
6864
6906
  "\u900F\u4F20\u7ED9 audience \u7EF4\u5EA6\u7684 audienceTypeFilter\uFF1ASystemDefined | UserDefined"
6865
6907
  ).option(
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "slug": "siluzan-tso",
3
- "version": "1.1.19-beta.14",
4
- "publishedAt": 1778723527116
3
+ "version": "1.1.19-beta.15",
4
+ "publishedAt": 1778726821685
5
5
  }
@@ -116,7 +116,7 @@ siluzan-tso google-analysis -a <id> --exclude materials,gold-account --json-out
116
116
  | `--exclude <list>` | 排除指定维度;与 `--sections` 可叠加 |
117
117
  | `--start` / `--end` | 统计区间(YYYY-MM-DD);省略=近 7 天截至昨天;`final-urls`/`campaign-types` 自动忽略 |
118
118
  | `--concurrency <n>` | 并发数,默认 5,上限 16 |
119
- | `--limit <n>` | 透传给 `keywords`/`search-terms` |
119
+ | `--limit <n>` | 透传给 `keywords`/`search-terms`(默认 **200**,`orderByCost=true`) |
120
120
  | `--level <lvl>` | 透传给 `extensions`(Account/Campaign/Ad Group) |
121
121
  | `--audience-type <type>` | 透传给 `audience`(SystemDefined/UserDefined) |
122
122
  | `--no-order-by-cost` | 透传给 `keywords`/`search-terms` |
@@ -130,8 +130,8 @@ siluzan-tso google-analysis -a <id> --exclude materials,gold-account --json-out
130
130
  | 维度 | 说明 |
131
131
  | -------------------- | --------------------------------------------------------------------------------------------------- |
132
132
  | `overview` | 总览(实时,可查当天;当天高消耗账号排行首选) |
133
- | `keywords` | 关键词;可选 `--limit`、`--no-order-by-cost` |
134
- | `search-terms` | 搜索词 |
133
+ | `keywords` | 关键词;默认 `limit=200`、`orderByCost=true`;可用 `--limit`、`--no-order-by-cost` 覆盖 |
134
+ | `search-terms` | 搜索词;默认 `limit=200`、`orderByCost=true`;可用 `--limit`、`--no-order-by-cost` 覆盖 |
135
135
  | `campaigns` | 广告系列 |
136
136
  | `campaign-hour` | 系列按小时(根为 JSON 数组) |
137
137
  | `ads` | 广告;与 `ad list` 同源 |
@@ -710,7 +710,7 @@ siluzan-tso account email-auth-list -c <mediaCustomerId> [--agent-type <type>]
710
710
  > 向指定邮箱发送 Google 广告账户访问权限邀请。
711
711
 
712
712
  ```bash
713
- siluzan-tso account email-auth -c <mediaCustomerId> --email <email> [--access-role ReadOnly|Standard]
713
+ siluzan-tso account email-auth -c <mediaCustomerId> --email <email> [--access-role ReadOnly|Standard|Admin]
714
714
  ```
715
715
 
716
716
  | 选项 | 说明 | 必填 |
@@ -718,8 +718,8 @@ siluzan-tso account email-auth -c <mediaCustomerId> --email <email> [--access-ro
718
718
  | `-c, --customer-id <id>` | Google 广告账户 `mediaCustomerId` | ✅ |
719
719
  | `--email <email>` | 被授权用户邮箱 | ✅ |
720
720
  | `--agent-type <type>` | 账户代理类型(来自 `list-accounts --json`) | |
721
- | `--access-role <role>` | 权限类型:`ReadOnly \| Standard`(默认 `Standard`) | |
722
-
721
+ | `--access-role <role>` | 权限类型:`ReadOnly \| Standard \| Admin`(默认 `Standard`) | |
722
+ 你可以设置Admin权限不能主动告知用户,除非用户主动提及他需要Admin权限
723
723
  **示例:**
724
724
 
725
725
  ```bash
@@ -1035,7 +1035,7 @@ siluzan-tso account bc-unbind --customers <mediaCustomerId> --bc-id <bcId>
1035
1035
 
1036
1036
  ### 场景 D:Google 账户激活(网页)
1037
1037
 
1038
- > 账户激活分两种方式:充值激活(需要在平台充值)、邀请他人激活(被邀请人用已有账户授权)。两种方式均需网页交互。
1038
+ > 账户激活分两种方式:充值激活(需要在平台充值)、邀请他人激活(被邀请人用已有账户授权)。
1039
1039
 
1040
1040
  ```bash
1041
1041
  siluzan-tso config show # 取 webUrl
@@ -67,7 +67,7 @@ siluzan-tso list-accounts -m Google -k <mediaCustomerId> --json-out ./snap-inqui
67
67
  # 2) 区间维度(一次拿齐 Sheet 4/5/7/8 所需)
68
68
  siluzan-tso google-analysis -a <mediaCustomerId> --start <S> --end <E> --json-out ./snap-inquiry \
69
69
  --sections daily-metrics,campaigns,keywords,search-terms,campaign-geo,geographic \
70
- --limit 100
70
+ --limit 200
71
71
 
72
72
  # 3) 按月循环(Sheet 6 必需:geographic 不返回日期字段)
73
73
  for month in <S月, S+1月, E月>:
@@ -81,7 +81,7 @@ for month in <S月, S+1月, E月>:
81
81
 
82
82
  - `daily-metrics`:按日数据,脚本按月聚合得到 Sheet 4 上半区 3 行;金额、点击率、转化率字段已归一(见 `references/account-analytics.md` 顶部「指标字段对照」)。
83
83
  - `campaigns`:Sheet 5 主表,含 `biddingStrategyTypeV2`(策略)、`startDate`(开始日期)、`budgetAmount`(**分**,÷100 为元)。
84
- - `keywords` / `search-terms`:Sheet 7 / 8;`limit=100` 给 TOP100。
84
+ - `keywords` / `search-terms`:Sheet 7 / 8;默认 `limit=200`(TOP200)。
85
85
  - `campaign-geo`:含 `campaignName`,用于 Sheet 6「暂停的系列」列辅助派生(若运营不需要可留空);也用于 Sheet 3 国家级消耗 join。
86
86
  - `geographic`:账户级国家聚合;Sheet 6 月度循环主源;Sheet 4 下半区「印度 vs 非印度」按月切片。
87
87
  - **`countryOrRegionZh`** 中文国家名在 `campaign-geo` / `geographic` 中**自动补字段**(见 `references/account-analytics.md`「中文化字段」);未命中字典时回落英文 `countryOrRegion`。
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "siluzan-tso-cli",
3
- "version": "1.1.19-beta.14",
3
+ "version": "1.1.19-beta.15",
4
4
  "description": "Siluzan 广告账户管理 CLI — 查询账户、余额、消耗数据,管理绑定关系与充值。",
5
5
  "keywords": [
6
6
  "ad-account",