@sovovs/bycli 2.1.65 → 2.1.66

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/cli-manifest.json CHANGED
@@ -30292,7 +30292,7 @@
30292
30292
  {
30293
30293
  "site": "weixin-channels",
30294
30294
  "name": "post-detail",
30295
- "description": "读取单条视频号作品的概览、趋势、来源和留存,默认最近 7 天;建议使用 --format json",
30295
+ "description": "读取单条视频号作品的概览、趋势、来源占比、逐日来源明细和留存,默认最近 7 天;建议使用 --format json",
30296
30296
  "access": "read",
30297
30297
  "domain": "channels.weixin.qq.com",
30298
30298
  "strategy": "cookie",
@@ -30334,6 +30334,7 @@
30334
30334
  "overview",
30335
30335
  "trend",
30336
30336
  "sources",
30337
+ "data_details",
30337
30338
  "retention"
30338
30339
  ],
30339
30340
  "type": "js",
@@ -30401,7 +30402,7 @@
30401
30402
  {
30402
30403
  "site": "weixin-channels",
30403
30404
  "name": "sources",
30404
- "description": "按视频号后台返回的来源统计账号指标,默认最近 7 天,截至昨日",
30405
+ "description": "按视频号后台来源汇总账号指标及播放占比,默认最近 7 天,截至昨日",
30405
30406
  "access": "read",
30406
30407
  "domain": "channels.weixin.qq.com",
30407
30408
  "strategy": "cookie",
@@ -30432,6 +30433,7 @@
30432
30433
  "columns": [
30433
30434
  "source",
30434
30435
  "views",
30436
+ "views_pct",
30435
30437
  "recommendations",
30436
30438
  "likes",
30437
30439
  "comments",
@@ -174,6 +174,7 @@ export function normalizeSources(data, range) {
174
174
  if (!isRecord(data) || !Array.isArray(data.dataByTabtype)) {
175
175
  throw new CommandExecutionError('Weixin Channels returned malformed source metrics');
176
176
  }
177
+ const totalViews = normalizeOverview(data, range).views;
177
178
  return data.dataByTabtype.map((item) => {
178
179
  if (!isRecord(item) || item.tabType == null || typeof item.tabTypeName !== 'string' || !isRecord(item.data)) {
179
180
  throw new CommandExecutionError('Weixin Channels returned a source without its identity or metrics');
@@ -181,10 +182,13 @@ export function normalizeSources(data, range) {
181
182
  if (typeof item.tabType !== 'string' && !(Number.isSafeInteger(item.tabType) && item.tabType >= 0)) {
182
183
  throw new CommandExecutionError('Weixin Channels returned an invalid source identity');
183
184
  }
185
+ const overview = normalizeOverview({ totalData: item.data }, range);
184
186
  return {
185
- ...normalizeOverview({ totalData: item.data }, range),
187
+ ...overview,
186
188
  source_id: item.tabType,
187
189
  source: item.tabTypeName,
190
+ views_pct: totalViews === null || totalViews === 0 || overview.views === null
191
+ ? null : roundTwo(overview.views / totalViews * 100),
188
192
  };
189
193
  });
190
194
  }
@@ -242,13 +246,20 @@ export function normalizeDetail(data, retention, id, range) {
242
246
  throw new CommandExecutionError('Weixin Channels returned an unexpected single-post detail payload');
243
247
  }
244
248
  const feed = data.feedData[0];
249
+ const sources = normalizeSources(feed, range);
250
+ const trend = normalizeTrend(feed, range);
251
+ const sourceTrends = feed.dataByTabtype.map((item) => normalizeTrend({ totalData: item.data }, range));
245
252
  return {
246
253
  id: postId(id),
247
254
  start_date: range.startDate,
248
255
  end_date: range.endDate,
249
256
  overview: normalizeOverview(feed, range),
250
- trend: normalizeTrend(feed, range),
251
- sources: normalizeSources(feed, range),
257
+ trend,
258
+ sources,
259
+ data_details: trend.flatMap((_, dayIndex) => sources.map((source, sourceIndex) => {
260
+ const { date, ...metrics } = sourceTrends[sourceIndex][dayIndex];
261
+ return { date, source_id: source.source_id, source: source.source, ...metrics };
262
+ })),
252
263
  retention: normalizeRetention(retention),
253
264
  fans_breakdown_available: !data.notExistFansData,
254
265
  };
@@ -8,7 +8,7 @@ export const postDetailCommand = cli({
8
8
  name: 'post-detail',
9
9
  access: 'read',
10
10
  domain: 'channels.weixin.qq.com',
11
- description: '读取单条视频号作品的概览、趋势、来源和留存,默认最近 7 天;建议使用 --format json',
11
+ description: '读取单条视频号作品的概览、趋势、来源占比、逐日来源明细和留存,默认最近 7 天;建议使用 --format json',
12
12
  strategy: Strategy.COOKIE,
13
13
  browser: true,
14
14
  navigateBefore: false,
@@ -18,7 +18,7 @@ export const postDetailCommand = cli({
18
18
  { name: 'start-date', type: 'str', valueRequired: true, help: '统计开始日期 YYYY-MM-DD(包含),须同时提供 --end-date' },
19
19
  { name: 'end-date', type: 'str', valueRequired: true, help: '统计结束日期 YYYY-MM-DD(包含),最晚为上海昨日' },
20
20
  ],
21
- columns: ['id', 'start_date', 'end_date', 'overview', 'trend', 'sources', 'retention'],
21
+ columns: ['id', 'start_date', 'end_date', 'overview', 'trend', 'sources', 'data_details', 'retention'],
22
22
  func: async (page, args = {}) => {
23
23
  const id = args.id;
24
24
  if (typeof id !== 'string' || !/^\d+$/.test(id)) {
@@ -7,7 +7,7 @@ export const sourcesCommand = cli({
7
7
  name: 'sources',
8
8
  access: 'read',
9
9
  domain: 'channels.weixin.qq.com',
10
- description: '按视频号后台返回的来源统计账号指标,默认最近 7 天,截至昨日',
10
+ description: '按视频号后台来源汇总账号指标及播放占比,默认最近 7 天,截至昨日',
11
11
  strategy: Strategy.COOKIE,
12
12
  browser: true,
13
13
  navigateBefore: false,
@@ -16,7 +16,7 @@ export const sourcesCommand = cli({
16
16
  { name: 'start-date', type: 'str', valueRequired: true, help: '开始日期 YYYY-MM-DD(包含),须同时提供 --end-date' },
17
17
  { name: 'end-date', type: 'str', valueRequired: true, help: '结束日期 YYYY-MM-DD(包含),最晚为上海昨日' },
18
18
  ],
19
- columns: ['source', 'views', 'recommendations', 'likes', 'comments', 'shares', 'follows'],
19
+ columns: ['source', 'views', 'views_pct', 'recommendations', 'likes', 'comments', 'shares', 'follows'],
20
20
  func: async (page, args = {}) => {
21
21
  const range = resolveDateRange(args, new Date(), 7);
22
22
  const data = await fetchTotalData(page, range);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sovovs/bycli",
3
- "version": "2.1.65",
3
+ "version": "2.1.66",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },