@sovovs/bycli 2.1.54 → 2.1.55

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
@@ -28753,51 +28753,6 @@
28753
28753
  "sourceFile": "weibo/user-posts.js",
28754
28754
  "navigateBefore": "https://weibo.com"
28755
28755
  },
28756
- {
28757
- "site": "weixin",
28758
- "name": "accounts",
28759
- "description": "Search WeChat official accounts and return their fakeids",
28760
- "access": "read",
28761
- "domain": "mp.weixin.qq.com",
28762
- "strategy": "intercept",
28763
- "browser": "conditional",
28764
- "args": [
28765
- {
28766
- "name": "query",
28767
- "type": "str",
28768
- "required": true,
28769
- "positional": true,
28770
- "help": "Official-account name to search for"
28771
- },
28772
- {
28773
- "name": "limit",
28774
- "type": "int",
28775
- "default": 10,
28776
- "required": false,
28777
- "help": "Maximum number of matching accounts to return"
28778
- },
28779
- {
28780
- "name": "auth-source",
28781
- "type": "str",
28782
- "default": "browser",
28783
- "required": false,
28784
- "help": "Credential source: browser session or environment variables",
28785
- "choices": [
28786
- "browser",
28787
- "env"
28788
- ]
28789
- }
28790
- ],
28791
- "columns": [
28792
- "nickname",
28793
- "fakeid",
28794
- "alias"
28795
- ],
28796
- "type": "js",
28797
- "modulePath": "weixin/accounts.js",
28798
- "sourceFile": "weixin/accounts.js",
28799
- "navigateBefore": true
28800
- },
28801
28756
  {
28802
28757
  "site": "weixin",
28803
28758
  "name": "article-fetch",
@@ -28909,7 +28864,7 @@
28909
28864
  "type": "str",
28910
28865
  "required": true,
28911
28866
  "positional": true,
28912
- "help": "Official-account fakeid returned by weixin accounts"
28867
+ "help": "Official-account fakeid returned by weixin get-public-account-info"
28913
28868
  },
28914
28869
  {
28915
28870
  "name": "name",
@@ -29514,6 +29469,51 @@
29514
29469
  "modulePath": "weixin/freepublish-list.js",
29515
29470
  "sourceFile": "weixin/freepublish-list.js"
29516
29471
  },
29472
+ {
29473
+ "site": "weixin",
29474
+ "name": "get-public-account-info",
29475
+ "description": "Search WeChat official accounts and return their fakeids",
29476
+ "access": "read",
29477
+ "domain": "mp.weixin.qq.com",
29478
+ "strategy": "intercept",
29479
+ "browser": "conditional",
29480
+ "args": [
29481
+ {
29482
+ "name": "query",
29483
+ "type": "str",
29484
+ "required": true,
29485
+ "positional": true,
29486
+ "help": "Official-account name to search for"
29487
+ },
29488
+ {
29489
+ "name": "limit",
29490
+ "type": "int",
29491
+ "default": 10,
29492
+ "required": false,
29493
+ "help": "Maximum number of matching accounts to return"
29494
+ },
29495
+ {
29496
+ "name": "auth-source",
29497
+ "type": "str",
29498
+ "default": "browser",
29499
+ "required": false,
29500
+ "help": "Credential source: browser session or environment variables",
29501
+ "choices": [
29502
+ "browser",
29503
+ "env"
29504
+ ]
29505
+ }
29506
+ ],
29507
+ "columns": [
29508
+ "nickname",
29509
+ "fakeid",
29510
+ "alias"
29511
+ ],
29512
+ "type": "js",
29513
+ "modulePath": "weixin/get-public-account-info.js",
29514
+ "sourceFile": "weixin/get-public-account-info.js",
29515
+ "navigateBefore": true
29516
+ },
29517
29517
  {
29518
29518
  "site": "weixin",
29519
29519
  "name": "home-overview",
@@ -29765,7 +29765,7 @@
29765
29765
  "type": "str",
29766
29766
  "required": true,
29767
29767
  "positional": true,
29768
- "help": "Official-account fakeid returned by weixin accounts"
29768
+ "help": "Official-account fakeid returned by weixin get-public-account-info"
29769
29769
  },
29770
29770
  {
29771
29771
  "name": "name",
@@ -19,7 +19,7 @@ export const articlesCommand = cli({
19
19
  description: 'List published articles from a WeChat official account',
20
20
  strategy: Strategy.COOKIE, browser: browserRequired,
21
21
  args: [
22
- { name: 'fakeid', positional: true, required: true, help: 'Official-account fakeid returned by weixin accounts' },
22
+ { name: 'fakeid', positional: true, required: true, help: 'Official-account fakeid returned by weixin get-public-account-info' },
23
23
  { name: 'name', help: 'Official-account name; exact case-insensitive match required for browser Sogou fallback' }, { name: 'limit', type: 'int', help: 'Maximum number of articles to return' }, { name: 'max-pages', type: 'int', help: 'Maximum number of history pages to scan' },
24
24
  { name: 'auth-source', default: 'browser', choices: ['browser', 'env'], help: 'Credential source: browser session or environment variables' },
25
25
  ],
@@ -8,8 +8,8 @@ import { readAuthSource } from './_wechat/args.js';
8
8
  const DOMAIN = 'mp.weixin.qq.com';
9
9
  const browserRequired = args => readAuthSource(args) === 'browser';
10
10
 
11
- export const accountsCommand = cli({
12
- site: 'weixin', name: 'accounts', access: 'read', domain: DOMAIN,
11
+ export const getPublicAccountInfoCommand = cli({
12
+ site: 'weixin', name: 'get-public-account-info', access: 'read', domain: DOMAIN,
13
13
  description: 'Search WeChat official accounts and return their fakeids',
14
14
  strategy: Strategy.INTERCEPT, browser: browserRequired,
15
15
  args: [
@@ -32,7 +32,7 @@ export const accountsCommand = cli({
32
32
  credentials = { ...credentials, fingerprint: await captureSearchBizFingerprint(page, query) };
33
33
  }
34
34
  const rows = await executeSearchBiz({ page, source: authSource, credentials, query, limit });
35
- if (rows.length === 0) throw new EmptyResultError('weixin accounts', `No official accounts matched "${query}".`);
35
+ if (rows.length === 0) throw new EmptyResultError('weixin get-public-account-info', `No official accounts matched "${query}".`);
36
36
  return rows.map(row => ({ nickname: row.nickname, fakeid: row.fakeid, alias: row.alias || null }));
37
37
  },
38
38
  });
@@ -17,6 +17,12 @@ function sourceValue(value) {
17
17
  return source;
18
18
  }
19
19
 
20
+ function limitValue(value) {
21
+ const limit = value ?? 20;
22
+ if (!Number.isSafeInteger(limit) || limit < 1) throw new ArgumentError('limit must be a positive safe integer');
23
+ return limit;
24
+ }
25
+
20
26
  export function projectOfficialRows(rows, fallbackReason = null) {
21
27
  return rows.map(row => ({
22
28
  article_id: row.article_id, title: row.title, author: row.author, digest: row.digest,
@@ -39,6 +45,29 @@ async function browserRows(page, args, fallbackReason) {
39
45
  }));
40
46
  }
41
47
 
48
+ async function officialRows(args) {
49
+ const limit = limitValue(args.limit);
50
+ const rows = [];
51
+ let offset = 0;
52
+ while (rows.length < limit) {
53
+ const remaining = limit - rows.length;
54
+ const count = remaining > 20 ? 20 : remaining;
55
+ let pageRows;
56
+ try {
57
+ pageRows = await freepublishListCommand.func({
58
+ ...args, offset, count, content: args.content ?? 'none',
59
+ });
60
+ } catch (error) {
61
+ if (error instanceof EmptyResultError && rows.length > 0) break;
62
+ throw error;
63
+ }
64
+ rows.push(...pageRows);
65
+ offset += count;
66
+ if (pageRows.length < count) break;
67
+ }
68
+ return rows.slice(0, limit);
69
+ }
70
+
42
71
  export const publishedArticlesCommand = cli({
43
72
  site: 'weixin', name: 'published-articles', access: 'read', domain: 'mp.weixin.qq.com',
44
73
  description: 'List published Weixin articles with optional official-API-to-browser fallback',
@@ -56,17 +85,17 @@ export const publishedArticlesCommand = cli({
56
85
  columns: FACADE_COLUMNS,
57
86
  func: async (page, args) => {
58
87
  const source = sourceValue(args.source);
59
- if (source === 'browser') return browserRows(page, args, null);
88
+ const limit = limitValue(args.limit);
89
+ const normalizedArgs = { ...args, limit };
90
+ if (source === 'browser') return browserRows(page, normalizedArgs, null);
60
91
  const credentials = readOfficialApiCredentials(args);
61
- if (source === 'auto' && !credentials.configured) return browserRows(page, args, 'api-not-configured');
92
+ if (source === 'auto' && !credentials.configured) return browserRows(page, normalizedArgs, 'api-not-configured');
62
93
  try {
63
- const rows = await freepublishListCommand.func({
64
- ...args, offset: 0, count: Math.min(args.limit ?? 20, 20), content: args.content ?? 'none',
65
- });
94
+ const rows = await officialRows(normalizedArgs);
66
95
  return projectOfficialRows(rows);
67
96
  } catch (error) {
68
97
  if (source === 'auto' && isFreepublishFallbackEligible(error)) {
69
- return browserRows(page, args, 'api-not-authorized');
98
+ return browserRows(page, normalizedArgs, 'api-not-authorized');
70
99
  }
71
100
  if (error instanceof EmptyResultError) throw error;
72
101
  throw error;
@@ -164,7 +164,7 @@ export const saveArticlesCommand = cli({
164
164
  description: 'Download WeChat official-account articles as Markdown files',
165
165
  strategy: Strategy.COOKIE, browser: browserRequired,
166
166
  args: [
167
- { name: 'fakeid', positional: true, required: true, help: 'Official-account fakeid returned by weixin accounts' }, { name: 'name', help: 'Official-account name; exact case-insensitive match required for browser Sogou fallback' },
167
+ { name: 'fakeid', positional: true, required: true, help: 'Official-account fakeid returned by weixin get-public-account-info' }, { name: 'name', help: 'Official-account name; exact case-insensitive match required for browser Sogou fallback' },
168
168
  { name: 'output', default: './weixin-articles', help: 'Directory for saved Markdown files' }, { name: 'limit', type: 'int', help: 'Maximum number of articles to save' },
169
169
  { name: 'max-pages', type: 'int', help: 'Maximum number of history pages to scan' }, { name: 'auth-source', default: 'browser', choices: ['browser', 'env'], help: 'Credential source: browser session or environment variables' },
170
170
  ],
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sovovs/bycli",
3
- "version": "2.1.54",
3
+ "version": "2.1.55",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },