socialdatax-skills 0.2.12 → 0.2.13
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
|
@@ -46,12 +46,12 @@ Common search phrases for this skill package:
|
|
|
46
46
|
|
|
47
47
|
## Platform MCPs
|
|
48
48
|
|
|
49
|
-
- XHS hosted MCP endpoint: `https://mcp.
|
|
50
|
-
- Douyin hosted MCP endpoint: `https://mcp.
|
|
51
|
-
- Kuaishou hosted MCP endpoint: `https://mcp.
|
|
52
|
-
- Weibo hosted MCP endpoint: `https://mcp.
|
|
53
|
-
- WeChat Channels hosted MCP endpoint: `https://mcp.
|
|
54
|
-
- Sensitive Check hosted MCP endpoint: `https://mcp.
|
|
49
|
+
- XHS hosted MCP endpoint: `https://mcp.socialdatax.com/xhs/mcp`
|
|
50
|
+
- Douyin hosted MCP endpoint: `https://mcp.socialdatax.com/douyin/mcp`
|
|
51
|
+
- Kuaishou hosted MCP endpoint: `https://mcp.socialdatax.com/kuaishou/mcp`
|
|
52
|
+
- Weibo hosted MCP endpoint: `https://mcp.socialdatax.com/weibo/mcp`
|
|
53
|
+
- WeChat Channels hosted MCP endpoint: `https://mcp.socialdatax.com/wechat/mcp`
|
|
54
|
+
- Sensitive Check hosted MCP endpoint: `https://mcp.socialdatax.com/sensitive-check/mcp`
|
|
55
55
|
- Hosted transport: `streamable-http`
|
|
56
56
|
- Authentication: `Authorization: Bearer <SOCIALDATAX_API_KEY>`
|
|
57
57
|
- Website: <https://socialdatax.com>
|
|
@@ -68,7 +68,7 @@ Common search phrases for this skill package:
|
|
|
68
68
|
- Sensitive Check MCP server name: `sensitive-check`
|
|
69
69
|
- Sensitive Check future MCP registry name: `com.socialdatax/sensitive-check`
|
|
70
70
|
- Unified MCP registry name: none; this package installs skills and calls explicit platform services.
|
|
71
|
-
- Current public capability version: `0.2.
|
|
71
|
+
- Current public capability version: `0.2.13`
|
|
72
72
|
|
|
73
73
|
## Direct CLI
|
|
74
74
|
|
|
@@ -78,6 +78,7 @@ Examples:
|
|
|
78
78
|
|
|
79
79
|
```bash
|
|
80
80
|
npx -y socialdatax-skills@latest xhs search --keyword "露营" --pretty
|
|
81
|
+
npx -y socialdatax-skills@latest xhs search --keyword "露营" --since-days 7 --pages 2 --pretty
|
|
81
82
|
npx -y socialdatax-skills@latest xhs hot-search --pretty
|
|
82
83
|
npx -y socialdatax-skills@latest xhs detail --note-id "<note_id>" --pretty
|
|
83
84
|
npx -y socialdatax-skills@latest xhs comments --note-id "<note_id>" --pretty
|
|
@@ -85,6 +86,7 @@ npx -y socialdatax-skills@latest xhs comments --note-id "<note_id>" --all --incl
|
|
|
85
86
|
npx -y socialdatax-skills@latest xhs sub-comments --note-id "<note_id>" --comment-id "<comment_id>" --pretty
|
|
86
87
|
npx -y socialdatax-skills@latest xhs user-info --user-id "<user_id>" --pretty
|
|
87
88
|
npx -y socialdatax-skills@latest xhs user-posts --user-id "<user_id>" --pretty
|
|
89
|
+
npx -y socialdatax-skills@latest xhs user-posts --user-id "<user_id>" --since-days 30 --pretty
|
|
88
90
|
npx -y socialdatax-skills@latest douyin hot-search --pretty
|
|
89
91
|
npx -y socialdatax-skills@latest douyin search --keyword "露营" --pretty
|
|
90
92
|
npx -y socialdatax-skills@latest douyin detail --aweme-id "<aweme_id>" --pretty
|
|
@@ -143,6 +145,8 @@ For XHS outputs with a returned `note_url` field, when `note_url` is non-null, p
|
|
|
143
145
|
|
|
144
146
|
For list-style commands, use `--pages <n>` to fetch N pages from the current starting point and `--max-items <n>` to cap the merged `data.items` output. Search commands support `--pages` but not `--all`, because search has no stable complete-result boundary.
|
|
145
147
|
|
|
148
|
+
For search and creator content-list commands, use `--since-days <1-365>` to keep only items whose public `publish_time` is within the last N days. Search remains bounded by `--pages` and does not promise complete platform coverage; creator content lists continue until the publish-time boundary when `--pages` is omitted.
|
|
149
|
+
|
|
146
150
|
For comments, replies, creator content lists, and Douyin creator series, use `--all` to continue until the returned `next_page_token` is empty. `--all` has no default item or page cap; add `--max-items <n>` or use `--pages <n>` when you want a bounded run.
|
|
147
151
|
|
|
148
152
|
For first-level comments, add `--include-replies` to fetch the second-level replies under each returned first-level comment. Multi-page output keeps `data.items` as the merged first-level list; each item gets `replies`, `replies_page_count`, and `replies_next_page_token`.
|
package/cli.mjs
CHANGED
|
@@ -7,7 +7,7 @@ import { dirname, join, resolve } from "node:path";
|
|
|
7
7
|
import { fileURLToPath } from "node:url";
|
|
8
8
|
|
|
9
9
|
const PACKAGE_NAME = "socialdatax-skills";
|
|
10
|
-
const PACKAGE_VERSION = "0.2.
|
|
10
|
+
const PACKAGE_VERSION = "0.2.13";
|
|
11
11
|
const PACKAGE_SPEC = `${PACKAGE_NAME}@latest`;
|
|
12
12
|
const LOG_PREFIX = `[${PACKAGE_NAME}]`;
|
|
13
13
|
const MIN_NODE_VERSION = "20.18.1";
|
|
@@ -85,6 +85,7 @@ const XHS_DIRECT_ACTION_OPTIONS = {
|
|
|
85
85
|
"pages",
|
|
86
86
|
"all",
|
|
87
87
|
"maxItems",
|
|
88
|
+
"sinceDays",
|
|
88
89
|
"sortType",
|
|
89
90
|
"noteType",
|
|
90
91
|
"publishTimeRange",
|
|
@@ -112,7 +113,16 @@ const XHS_DIRECT_ACTION_OPTIONS = {
|
|
|
112
113
|
"pretty",
|
|
113
114
|
],
|
|
114
115
|
"user-info": ["userId", "profileUrl", "pretty"],
|
|
115
|
-
"user-posts": [
|
|
116
|
+
"user-posts": [
|
|
117
|
+
"userId",
|
|
118
|
+
"profileUrl",
|
|
119
|
+
"pageToken",
|
|
120
|
+
"pages",
|
|
121
|
+
"all",
|
|
122
|
+
"maxItems",
|
|
123
|
+
"sinceDays",
|
|
124
|
+
"pretty",
|
|
125
|
+
],
|
|
116
126
|
};
|
|
117
127
|
const XHS_DIRECT_ACTION_NAMES = Object.keys(XHS_DIRECT_ACTION_OPTIONS).join(", ");
|
|
118
128
|
const XHS_OPTION_DISPLAY_NAMES = {
|
|
@@ -126,6 +136,7 @@ const XHS_OPTION_DISPLAY_NAMES = {
|
|
|
126
136
|
pageToken: "--page-token",
|
|
127
137
|
pages: "--pages",
|
|
128
138
|
maxItems: "--max-items",
|
|
139
|
+
sinceDays: "--since-days",
|
|
129
140
|
all: "--all",
|
|
130
141
|
includeReplies: "--include-replies",
|
|
131
142
|
profileUrl: "--profile-url",
|
|
@@ -151,6 +162,7 @@ const DOUYIN_DIRECT_ACTION_OPTIONS = {
|
|
|
151
162
|
"pages",
|
|
152
163
|
"all",
|
|
153
164
|
"maxItems",
|
|
165
|
+
"sinceDays",
|
|
154
166
|
"sortType",
|
|
155
167
|
"publishTimeRange",
|
|
156
168
|
"durationRange",
|
|
@@ -179,7 +191,16 @@ const DOUYIN_DIRECT_ACTION_OPTIONS = {
|
|
|
179
191
|
"pretty",
|
|
180
192
|
],
|
|
181
193
|
"user-info": ["secUserId", "profileUrl", "pretty"],
|
|
182
|
-
"user-posts": [
|
|
194
|
+
"user-posts": [
|
|
195
|
+
"secUserId",
|
|
196
|
+
"profileUrl",
|
|
197
|
+
"pageToken",
|
|
198
|
+
"pages",
|
|
199
|
+
"all",
|
|
200
|
+
"maxItems",
|
|
201
|
+
"sinceDays",
|
|
202
|
+
"pretty",
|
|
203
|
+
],
|
|
183
204
|
"user-series": ["secUserId", "profileUrl", "pageToken", "pages", "all", "maxItems", "pretty"],
|
|
184
205
|
};
|
|
185
206
|
const DOUYIN_DIRECT_ACTION_NAMES = Object.keys(DOUYIN_DIRECT_ACTION_OPTIONS).join(", ");
|
|
@@ -197,6 +218,7 @@ const DOUYIN_OPTION_DISPLAY_NAMES = {
|
|
|
197
218
|
pageToken: "--page-token",
|
|
198
219
|
pages: "--pages",
|
|
199
220
|
maxItems: "--max-items",
|
|
221
|
+
sinceDays: "--since-days",
|
|
200
222
|
all: "--all",
|
|
201
223
|
includeReplies: "--include-replies",
|
|
202
224
|
sortType: "--sort-type",
|
|
@@ -211,7 +233,7 @@ const DOUYIN_OPTION_DISPLAY_NAMES = {
|
|
|
211
233
|
};
|
|
212
234
|
const KUAISHOU_DIRECT_ACTION_OPTIONS = {
|
|
213
235
|
"hot-search": ["pretty"],
|
|
214
|
-
search: ["keyword", "pageToken", "pages", "all", "maxItems", "pretty"],
|
|
236
|
+
search: ["keyword", "pageToken", "pages", "all", "maxItems", "sinceDays", "pretty"],
|
|
215
237
|
detail: ["photoId", "url", "pretty"],
|
|
216
238
|
comments: [
|
|
217
239
|
"photoId",
|
|
@@ -234,7 +256,16 @@ const KUAISHOU_DIRECT_ACTION_OPTIONS = {
|
|
|
234
256
|
"pretty",
|
|
235
257
|
],
|
|
236
258
|
"user-info": ["userId", "profileUrl", "pretty"],
|
|
237
|
-
"user-posts": [
|
|
259
|
+
"user-posts": [
|
|
260
|
+
"userId",
|
|
261
|
+
"profileUrl",
|
|
262
|
+
"pageToken",
|
|
263
|
+
"pages",
|
|
264
|
+
"all",
|
|
265
|
+
"maxItems",
|
|
266
|
+
"sinceDays",
|
|
267
|
+
"pretty",
|
|
268
|
+
],
|
|
238
269
|
};
|
|
239
270
|
const KUAISHOU_DIRECT_ACTION_NAMES = Object.keys(KUAISHOU_DIRECT_ACTION_OPTIONS).join(", ");
|
|
240
271
|
const KUAISHOU_OPTION_DISPLAY_NAMES = {
|
|
@@ -242,6 +273,7 @@ const KUAISHOU_OPTION_DISPLAY_NAMES = {
|
|
|
242
273
|
pageToken: "--page-token",
|
|
243
274
|
pages: "--pages",
|
|
244
275
|
maxItems: "--max-items",
|
|
276
|
+
sinceDays: "--since-days",
|
|
245
277
|
all: "--all",
|
|
246
278
|
includeReplies: "--include-replies",
|
|
247
279
|
url: "--url",
|
|
@@ -252,7 +284,7 @@ const KUAISHOU_OPTION_DISPLAY_NAMES = {
|
|
|
252
284
|
};
|
|
253
285
|
const WEIBO_DIRECT_ACTION_OPTIONS = {
|
|
254
286
|
"hot-search": ["pretty"],
|
|
255
|
-
search: ["keyword", "pageToken", "pages", "all", "maxItems", "pretty"],
|
|
287
|
+
search: ["keyword", "pageToken", "pages", "all", "maxItems", "sinceDays", "pretty"],
|
|
256
288
|
detail: ["postId", "postUrl", "pretty"],
|
|
257
289
|
comments: [
|
|
258
290
|
"postId",
|
|
@@ -277,7 +309,16 @@ const WEIBO_DIRECT_ACTION_OPTIONS = {
|
|
|
277
309
|
likers: ["postId", "pageToken", "pages", "all", "maxItems", "pretty"],
|
|
278
310
|
reposts: ["postId", "pageToken", "pages", "all", "maxItems", "pretty"],
|
|
279
311
|
"user-info": ["userId", "profileUrl", "pretty"],
|
|
280
|
-
"user-posts": [
|
|
312
|
+
"user-posts": [
|
|
313
|
+
"userId",
|
|
314
|
+
"profileUrl",
|
|
315
|
+
"pageToken",
|
|
316
|
+
"pages",
|
|
317
|
+
"all",
|
|
318
|
+
"maxItems",
|
|
319
|
+
"sinceDays",
|
|
320
|
+
"pretty",
|
|
321
|
+
],
|
|
281
322
|
};
|
|
282
323
|
const WEIBO_DIRECT_ACTION_NAMES = Object.keys(WEIBO_DIRECT_ACTION_OPTIONS).join(", ");
|
|
283
324
|
const WEIBO_OPTION_DISPLAY_NAMES = {
|
|
@@ -285,6 +326,7 @@ const WEIBO_OPTION_DISPLAY_NAMES = {
|
|
|
285
326
|
pageToken: "--page-token",
|
|
286
327
|
pages: "--pages",
|
|
287
328
|
maxItems: "--max-items",
|
|
329
|
+
sinceDays: "--since-days",
|
|
288
330
|
all: "--all",
|
|
289
331
|
includeReplies: "--include-replies",
|
|
290
332
|
postId: "--post-id",
|
|
@@ -301,6 +343,7 @@ const WECHAT_DIRECT_ACTION_OPTIONS = {
|
|
|
301
343
|
"pages",
|
|
302
344
|
"all",
|
|
303
345
|
"maxItems",
|
|
346
|
+
"sinceDays",
|
|
304
347
|
"sortType",
|
|
305
348
|
"durationRange",
|
|
306
349
|
"pretty",
|
|
@@ -329,7 +372,16 @@ const WECHAT_DIRECT_ACTION_OPTIONS = {
|
|
|
329
372
|
"pretty",
|
|
330
373
|
],
|
|
331
374
|
"user-info": ["userId", "pretty"],
|
|
332
|
-
"user-posts": [
|
|
375
|
+
"user-posts": [
|
|
376
|
+
"userId",
|
|
377
|
+
"url",
|
|
378
|
+
"pageToken",
|
|
379
|
+
"pages",
|
|
380
|
+
"all",
|
|
381
|
+
"maxItems",
|
|
382
|
+
"sinceDays",
|
|
383
|
+
"pretty",
|
|
384
|
+
],
|
|
333
385
|
};
|
|
334
386
|
const WECHAT_DIRECT_ACTION_NAMES = Object.keys(WECHAT_DIRECT_ACTION_OPTIONS).join(", ");
|
|
335
387
|
const WECHAT_SEARCH_SORT_TYPES = ["all", "latest", "popular"];
|
|
@@ -344,6 +396,7 @@ const WECHAT_OPTION_DISPLAY_NAMES = {
|
|
|
344
396
|
pageToken: "--page-token",
|
|
345
397
|
pages: "--pages",
|
|
346
398
|
maxItems: "--max-items",
|
|
399
|
+
sinceDays: "--since-days",
|
|
347
400
|
all: "--all",
|
|
348
401
|
includeReplies: "--include-replies",
|
|
349
402
|
sortType: "--sort-type",
|
|
@@ -373,7 +426,7 @@ const PLATFORMS = {
|
|
|
373
426
|
status: "public",
|
|
374
427
|
registryName: "com.52choujiang/xhs-insights",
|
|
375
428
|
futureRegistryName: "com.socialdatax/xhs-insights",
|
|
376
|
-
endpoint: "https://mcp.
|
|
429
|
+
endpoint: "https://mcp.socialdatax.com/xhs/mcp",
|
|
377
430
|
apiKeyEnv: API_KEY_ENV_NAMES,
|
|
378
431
|
upstreamEnv: [
|
|
379
432
|
"SOCIAL_MEDIA_XHS_MCP_UPSTREAM_URL",
|
|
@@ -455,7 +508,7 @@ const PLATFORMS = {
|
|
|
455
508
|
status: "public",
|
|
456
509
|
registryName: "com.52choujiang/douyin-insights",
|
|
457
510
|
futureRegistryName: "com.socialdatax/douyin-insights",
|
|
458
|
-
endpoint: "https://mcp.
|
|
511
|
+
endpoint: "https://mcp.socialdatax.com/douyin/mcp",
|
|
459
512
|
apiKeyEnv: API_KEY_ENV_NAMES,
|
|
460
513
|
upstreamEnv: [
|
|
461
514
|
"SOCIAL_MEDIA_DOUYIN_MCP_UPSTREAM_URL",
|
|
@@ -539,7 +592,7 @@ const PLATFORMS = {
|
|
|
539
592
|
status: "public",
|
|
540
593
|
registryName: "com.52choujiang/kuaishou-insights",
|
|
541
594
|
futureRegistryName: "com.socialdatax/kuaishou-insights",
|
|
542
|
-
endpoint: "https://mcp.
|
|
595
|
+
endpoint: "https://mcp.socialdatax.com/kuaishou/mcp",
|
|
543
596
|
apiKeyEnv: API_KEY_ENV_NAMES,
|
|
544
597
|
upstreamEnv: [
|
|
545
598
|
"SOCIAL_MEDIA_KUAISHOU_MCP_UPSTREAM_URL",
|
|
@@ -615,7 +668,7 @@ const PLATFORMS = {
|
|
|
615
668
|
status: "public",
|
|
616
669
|
registryName: "com.52choujiang/weibo-insights",
|
|
617
670
|
futureRegistryName: "com.socialdatax/weibo-insights",
|
|
618
|
-
endpoint: "https://mcp.
|
|
671
|
+
endpoint: "https://mcp.socialdatax.com/weibo/mcp",
|
|
619
672
|
apiKeyEnv: API_KEY_ENV_NAMES,
|
|
620
673
|
upstreamEnv: [
|
|
621
674
|
"SOCIAL_MEDIA_WEIBO_MCP_UPSTREAM_URL",
|
|
@@ -699,7 +752,7 @@ const PLATFORMS = {
|
|
|
699
752
|
status: "public",
|
|
700
753
|
registryName: "com.52choujiang/wechat-channels-insights",
|
|
701
754
|
futureRegistryName: "com.socialdatax/wechat-channels-insights",
|
|
702
|
-
endpoint: "https://mcp.
|
|
755
|
+
endpoint: "https://mcp.socialdatax.com/wechat/mcp",
|
|
703
756
|
apiKeyEnv: API_KEY_ENV_NAMES,
|
|
704
757
|
upstreamEnv: [
|
|
705
758
|
"SOCIAL_MEDIA_WECHAT_MCP_UPSTREAM_URL",
|
|
@@ -771,7 +824,7 @@ const PLATFORMS = {
|
|
|
771
824
|
status: "public",
|
|
772
825
|
registryName: "sensitive-check",
|
|
773
826
|
futureRegistryName: "com.socialdatax/sensitive-check",
|
|
774
|
-
endpoint: "https://mcp.
|
|
827
|
+
endpoint: "https://mcp.socialdatax.com/sensitive-check/mcp",
|
|
775
828
|
apiKeyEnv: API_KEY_ENV_NAMES,
|
|
776
829
|
upstreamEnv: [
|
|
777
830
|
"SOCIALDATAX_SENSITIVE_CHECK_MCP_UPSTREAM_URL",
|
|
@@ -1015,6 +1068,9 @@ function validateDirectPaginationOptions(platformId, action, options) {
|
|
|
1015
1068
|
if (options.maxItems !== undefined) {
|
|
1016
1069
|
parsePositiveIntegerOption(options.maxItems, "--max-items");
|
|
1017
1070
|
}
|
|
1071
|
+
if (options.sinceDays !== undefined) {
|
|
1072
|
+
parseSinceDaysOption(options.sinceDays);
|
|
1073
|
+
}
|
|
1018
1074
|
if (options.all && action === "search") {
|
|
1019
1075
|
throw new Error(`--all is not supported for ${platformId} search. Use --pages instead.`);
|
|
1020
1076
|
}
|
|
@@ -1035,6 +1091,37 @@ function parsePositiveIntegerOption(value, displayName) {
|
|
|
1035
1091
|
return parsed;
|
|
1036
1092
|
}
|
|
1037
1093
|
|
|
1094
|
+
function parseSinceDaysOption(value) {
|
|
1095
|
+
const text = String(value);
|
|
1096
|
+
if (!/^\d+$/.test(text)) {
|
|
1097
|
+
throw new Error("--since-days must be an integer between 1 and 365.");
|
|
1098
|
+
}
|
|
1099
|
+
const parsed = Number(text);
|
|
1100
|
+
if (!Number.isSafeInteger(parsed) || parsed < 1 || parsed > 365) {
|
|
1101
|
+
throw new Error("--since-days must be an integer between 1 and 365.");
|
|
1102
|
+
}
|
|
1103
|
+
return parsed;
|
|
1104
|
+
}
|
|
1105
|
+
|
|
1106
|
+
function parseOptionalSinceDays(options) {
|
|
1107
|
+
return options.sinceDays === undefined
|
|
1108
|
+
? undefined
|
|
1109
|
+
: parseSinceDaysOption(options.sinceDays);
|
|
1110
|
+
}
|
|
1111
|
+
|
|
1112
|
+
function nativePublishTimeRangeForSinceDays(sinceDays) {
|
|
1113
|
+
if (sinceDays <= 1) {
|
|
1114
|
+
return "day";
|
|
1115
|
+
}
|
|
1116
|
+
if (sinceDays <= 7) {
|
|
1117
|
+
return "week";
|
|
1118
|
+
}
|
|
1119
|
+
if (sinceDays <= 180) {
|
|
1120
|
+
return "half_year";
|
|
1121
|
+
}
|
|
1122
|
+
return undefined;
|
|
1123
|
+
}
|
|
1124
|
+
|
|
1038
1125
|
function parseAllowedStringOption(value, displayName, allowedValues, label) {
|
|
1039
1126
|
const normalized = String(value).trim();
|
|
1040
1127
|
if (!allowedValues.includes(normalized)) {
|
|
@@ -1500,6 +1587,9 @@ function printHelp() {
|
|
|
1500
1587
|
console.log(` npx -y ${PACKAGE_SPEC} xhs search --keyword "露营" --pretty`);
|
|
1501
1588
|
console.log(" Call the XHS search tool directly and print JSON.");
|
|
1502
1589
|
console.log("");
|
|
1590
|
+
console.log(` npx -y ${PACKAGE_SPEC} xhs search --keyword "露营" --since-days 7 --pages 2 --pretty`);
|
|
1591
|
+
console.log(" Search recent XHS results and keep items published in the last 7 days.");
|
|
1592
|
+
console.log("");
|
|
1503
1593
|
console.log(` npx -y ${PACKAGE_SPEC} xhs hot-search --pretty`);
|
|
1504
1594
|
console.log(" Call the XHS search hot list tool directly and print JSON.");
|
|
1505
1595
|
console.log("");
|
|
@@ -1523,6 +1613,9 @@ function printHelp() {
|
|
|
1523
1613
|
console.log(` npx -y ${PACKAGE_SPEC} xhs user-posts --user-id "<user_id>" --pretty`);
|
|
1524
1614
|
console.log(" Call the XHS creator posts tool directly and print JSON.");
|
|
1525
1615
|
console.log("");
|
|
1616
|
+
console.log(` npx -y ${PACKAGE_SPEC} xhs user-posts --user-id "<user_id>" --since-days 30 --pretty`);
|
|
1617
|
+
console.log(" Fetch recent creator posts until the publish-time boundary is reached.");
|
|
1618
|
+
console.log("");
|
|
1526
1619
|
console.log(` npx -y ${PACKAGE_SPEC} douyin hot-search --pretty`);
|
|
1527
1620
|
console.log(" Call the Douyin main hot search list tool directly and print JSON.");
|
|
1528
1621
|
console.log("");
|
|
@@ -1762,6 +1855,8 @@ function printHelp() {
|
|
|
1762
1855
|
console.log(" Continue comments, replies, creator content lists, and creator series until next_page_token is empty; not supported for search.");
|
|
1763
1856
|
console.log(" --max-items <number>");
|
|
1764
1857
|
console.log(" Stop after collecting this many primary items.");
|
|
1858
|
+
console.log(" --since-days <1-365>");
|
|
1859
|
+
console.log(" Keep search or creator content-list items with publish_time in the last N days. Search stays bounded by --pages; creator lists continue until the time boundary when --pages is omitted.");
|
|
1765
1860
|
console.log(" --include-replies");
|
|
1766
1861
|
console.log(" For comments commands, also fetch nested second-level replies for each returned first-level comment.");
|
|
1767
1862
|
console.log(" --sort-type <general|time_descending|like_count_descending|comment_count_descending|collect_count_descending>");
|
|
@@ -1811,18 +1906,18 @@ function printRemovedMcpConfigHelp(command) {
|
|
|
1811
1906
|
console.error(" com.socialdatax/wechat-channels-insights");
|
|
1812
1907
|
console.error("");
|
|
1813
1908
|
console.error("Use hosted streamable HTTP when your client supports remote MCP:");
|
|
1814
|
-
console.error(" https://mcp.
|
|
1815
|
-
console.error(" https://mcp.
|
|
1816
|
-
console.error(" https://mcp.
|
|
1817
|
-
console.error(" https://mcp.
|
|
1818
|
-
console.error(" https://mcp.
|
|
1909
|
+
console.error(" https://mcp.socialdatax.com/xhs/mcp");
|
|
1910
|
+
console.error(" https://mcp.socialdatax.com/douyin/mcp");
|
|
1911
|
+
console.error(" https://mcp.socialdatax.com/kuaishou/mcp");
|
|
1912
|
+
console.error(" https://mcp.socialdatax.com/weibo/mcp");
|
|
1913
|
+
console.error(" https://mcp.socialdatax.com/wechat/mcp");
|
|
1819
1914
|
console.error("");
|
|
1820
1915
|
console.error("For command/stdio-only clients, use mcp-remote:");
|
|
1821
|
-
console.error(` npx -y mcp-remote https://mcp.
|
|
1822
|
-
console.error(` npx -y mcp-remote https://mcp.
|
|
1823
|
-
console.error(` npx -y mcp-remote https://mcp.
|
|
1824
|
-
console.error(` npx -y mcp-remote https://mcp.
|
|
1825
|
-
console.error(` npx -y mcp-remote https://mcp.
|
|
1916
|
+
console.error(` npx -y mcp-remote https://mcp.socialdatax.com/xhs/mcp --header "Authorization: Bearer <${PRIMARY_API_KEY_ENV}>"`);
|
|
1917
|
+
console.error(` npx -y mcp-remote https://mcp.socialdatax.com/douyin/mcp --header "Authorization: Bearer <${PRIMARY_API_KEY_ENV}>"`);
|
|
1918
|
+
console.error(` npx -y mcp-remote https://mcp.socialdatax.com/kuaishou/mcp --header "Authorization: Bearer <${PRIMARY_API_KEY_ENV}>"`);
|
|
1919
|
+
console.error(` npx -y mcp-remote https://mcp.socialdatax.com/weibo/mcp --header "Authorization: Bearer <${PRIMARY_API_KEY_ENV}>"`);
|
|
1920
|
+
console.error(` npx -y mcp-remote https://mcp.socialdatax.com/wechat/mcp --header "Authorization: Bearer <${PRIMARY_API_KEY_ENV}>"`);
|
|
1826
1921
|
}
|
|
1827
1922
|
|
|
1828
1923
|
async function runXhsDirectCommand(args) {
|
|
@@ -2475,8 +2570,13 @@ function buildXhsSearchCall(options) {
|
|
|
2475
2570
|
if (!options.keyword) {
|
|
2476
2571
|
throw new Error("Missing --keyword for xhs search.");
|
|
2477
2572
|
}
|
|
2573
|
+
const sinceDays = parseOptionalSinceDays(options);
|
|
2574
|
+
const requestedSortType =
|
|
2575
|
+
options.sortType === undefined && sinceDays !== undefined
|
|
2576
|
+
? "time_descending"
|
|
2577
|
+
: options.sortType || "general";
|
|
2478
2578
|
const sortType = parseSemanticOption(
|
|
2479
|
-
|
|
2579
|
+
requestedSortType,
|
|
2480
2580
|
"--sort-type",
|
|
2481
2581
|
XHS_SEARCH_SORT_TYPES,
|
|
2482
2582
|
XHS_LEGACY_SEARCH_SORT_TYPE_ALIASES,
|
|
@@ -2504,12 +2604,19 @@ function buildXhsSearchCall(options) {
|
|
|
2504
2604
|
}
|
|
2505
2605
|
if (options.sortType !== undefined) {
|
|
2506
2606
|
toolArguments.sort_type = sortType;
|
|
2607
|
+
} else if (sinceDays !== undefined) {
|
|
2608
|
+
toolArguments.sort_type = "time_descending";
|
|
2507
2609
|
}
|
|
2508
2610
|
if (options.noteType !== undefined) {
|
|
2509
2611
|
toolArguments.note_type = noteType;
|
|
2510
2612
|
}
|
|
2511
2613
|
if (options.publishTimeRange !== undefined) {
|
|
2512
2614
|
toolArguments.publish_time_range = publishTimeRange;
|
|
2615
|
+
} else if (sinceDays !== undefined) {
|
|
2616
|
+
const nativeRange = nativePublishTimeRangeForSinceDays(sinceDays);
|
|
2617
|
+
if (nativeRange) {
|
|
2618
|
+
toolArguments.publish_time_range = nativeRange;
|
|
2619
|
+
}
|
|
2513
2620
|
}
|
|
2514
2621
|
return {
|
|
2515
2622
|
tool: "xhs_search_notes",
|
|
@@ -2576,6 +2683,7 @@ function buildDouyinSearchCall(options) {
|
|
|
2576
2683
|
if (!options.keyword) {
|
|
2577
2684
|
throw new Error("Missing --keyword for douyin search.");
|
|
2578
2685
|
}
|
|
2686
|
+
const sinceDays = parseOptionalSinceDays(options);
|
|
2579
2687
|
const toolArguments = {
|
|
2580
2688
|
keyword: options.keyword,
|
|
2581
2689
|
};
|
|
@@ -2586,6 +2694,8 @@ function buildDouyinSearchCall(options) {
|
|
|
2586
2694
|
DOUYIN_SEARCH_SORT_TYPES,
|
|
2587
2695
|
DOUYIN_SEARCH_SORT_TYPES.join(", ")
|
|
2588
2696
|
);
|
|
2697
|
+
} else if (sinceDays !== undefined) {
|
|
2698
|
+
toolArguments.sort_type = "time_descending";
|
|
2589
2699
|
}
|
|
2590
2700
|
if (options.publishTimeRange !== undefined) {
|
|
2591
2701
|
toolArguments.publish_time_range = parseAllowedStringOption(
|
|
@@ -2594,6 +2704,11 @@ function buildDouyinSearchCall(options) {
|
|
|
2594
2704
|
DOUYIN_SEARCH_PUBLISH_TIME_RANGES,
|
|
2595
2705
|
DOUYIN_SEARCH_PUBLISH_TIME_RANGES.join(", ")
|
|
2596
2706
|
);
|
|
2707
|
+
} else if (sinceDays !== undefined) {
|
|
2708
|
+
const nativeRange = nativePublishTimeRangeForSinceDays(sinceDays);
|
|
2709
|
+
if (nativeRange) {
|
|
2710
|
+
toolArguments.publish_time_range = nativeRange;
|
|
2711
|
+
}
|
|
2597
2712
|
}
|
|
2598
2713
|
if (options.durationRange !== undefined) {
|
|
2599
2714
|
toolArguments.duration_range = parseAllowedStringOption(
|
|
@@ -2656,6 +2771,7 @@ function buildWechatSearchCall(options) {
|
|
|
2656
2771
|
if (!options.keyword) {
|
|
2657
2772
|
throw new Error("Missing --keyword for wechat search.");
|
|
2658
2773
|
}
|
|
2774
|
+
const sinceDays = parseOptionalSinceDays(options);
|
|
2659
2775
|
const toolArguments = {
|
|
2660
2776
|
keyword: options.keyword,
|
|
2661
2777
|
};
|
|
@@ -2666,6 +2782,8 @@ function buildWechatSearchCall(options) {
|
|
|
2666
2782
|
WECHAT_SEARCH_SORT_TYPES,
|
|
2667
2783
|
WECHAT_SEARCH_SORT_TYPES.join(", ")
|
|
2668
2784
|
);
|
|
2785
|
+
} else if (sinceDays !== undefined) {
|
|
2786
|
+
toolArguments.sort_type = "latest";
|
|
2669
2787
|
}
|
|
2670
2788
|
if (options.durationRange !== undefined) {
|
|
2671
2789
|
toolArguments.duration_range = parseAllowedStringOption(
|
|
@@ -2875,7 +2993,8 @@ function shouldUsePaginatedDirectOutput(options) {
|
|
|
2875
2993
|
options.all ||
|
|
2876
2994
|
options.pages !== undefined ||
|
|
2877
2995
|
options.maxItems !== undefined ||
|
|
2878
|
-
options.includeReplies
|
|
2996
|
+
options.includeReplies ||
|
|
2997
|
+
options.sinceDays !== undefined
|
|
2879
2998
|
);
|
|
2880
2999
|
}
|
|
2881
3000
|
|
|
@@ -2897,6 +3016,7 @@ function parseDirectPaginationOptions(options) {
|
|
|
2897
3016
|
options.maxItems === undefined
|
|
2898
3017
|
? undefined
|
|
2899
3018
|
: parsePositiveIntegerOption(options.maxItems, "--max-items"),
|
|
3019
|
+
sinceDays: parseOptionalSinceDays(options),
|
|
2900
3020
|
};
|
|
2901
3021
|
}
|
|
2902
3022
|
|
|
@@ -2905,7 +3025,14 @@ async function collectPaginatedDirectData(
|
|
|
2905
3025
|
pagination,
|
|
2906
3026
|
{ includeReplies = false } = {}
|
|
2907
3027
|
) {
|
|
2908
|
-
const pageLimit =
|
|
3028
|
+
const pageLimit =
|
|
3029
|
+
pagination.all || shouldAutoPaginateSinceDays(operation, pagination)
|
|
3030
|
+
? Number.POSITIVE_INFINITY
|
|
3031
|
+
: pagination.pages || 1;
|
|
3032
|
+
const sinceDaysCutoff =
|
|
3033
|
+
pagination.sinceDays === undefined
|
|
3034
|
+
? undefined
|
|
3035
|
+
: cutoffPublishTimeForSinceDays(pagination.sinceDays);
|
|
2909
3036
|
const collectedItems = [];
|
|
2910
3037
|
const itemDedupeState = createPaginatedItemDedupeState();
|
|
2911
3038
|
const seenNextMarkers = initialPaginationMarkers(operation);
|
|
@@ -2914,6 +3041,7 @@ async function collectPaginatedDirectData(
|
|
|
2914
3041
|
let nextMarker;
|
|
2915
3042
|
let parentContextData = {};
|
|
2916
3043
|
let currentOperation = cloneDirectOperation(operation);
|
|
3044
|
+
let stoppedBySinceDays = false;
|
|
2917
3045
|
|
|
2918
3046
|
while (pageCount < pageLimit) {
|
|
2919
3047
|
const pageData = await callDirectOperation(currentOperation);
|
|
@@ -2926,8 +3054,12 @@ async function collectPaginatedDirectData(
|
|
|
2926
3054
|
directPageItems(pageData),
|
|
2927
3055
|
itemDedupeState
|
|
2928
3056
|
);
|
|
3057
|
+
const filteredPage = filterItemsBySinceDays(pageItems, sinceDaysCutoff);
|
|
3058
|
+
if (shouldStopAtSinceDaysBoundary(operation, sinceDaysCutoff, pageItems)) {
|
|
3059
|
+
stoppedBySinceDays = true;
|
|
3060
|
+
}
|
|
2929
3061
|
const candidateItems = itemsForRemainingLimit(
|
|
2930
|
-
|
|
3062
|
+
filteredPage.items,
|
|
2931
3063
|
collectedItems.length,
|
|
2932
3064
|
pagination.maxItems
|
|
2933
3065
|
);
|
|
@@ -2948,6 +3080,7 @@ async function collectPaginatedDirectData(
|
|
|
2948
3080
|
if (
|
|
2949
3081
|
!nextMarker ||
|
|
2950
3082
|
reachedMaxItems(collectedItems, pagination.maxItems) ||
|
|
3083
|
+
stoppedBySinceDays ||
|
|
2951
3084
|
pageCount >= pageLimit
|
|
2952
3085
|
) {
|
|
2953
3086
|
if (markerRepeated) {
|
|
@@ -2971,6 +3104,7 @@ async function collectPaginatedDirectData(
|
|
|
2971
3104
|
items: collectedItems,
|
|
2972
3105
|
pageCount,
|
|
2973
3106
|
nextMarker,
|
|
3107
|
+
stoppedBySinceDays,
|
|
2974
3108
|
});
|
|
2975
3109
|
}
|
|
2976
3110
|
|
|
@@ -2985,6 +3119,54 @@ function directPageItems(pageData) {
|
|
|
2985
3119
|
return Array.isArray(pageData?.items) ? pageData.items : [];
|
|
2986
3120
|
}
|
|
2987
3121
|
|
|
3122
|
+
function shouldAutoPaginateSinceDays(operation, pagination) {
|
|
3123
|
+
return (
|
|
3124
|
+
operation.operation === "user-posts" &&
|
|
3125
|
+
pagination.sinceDays !== undefined &&
|
|
3126
|
+
pagination.pages === undefined
|
|
3127
|
+
);
|
|
3128
|
+
}
|
|
3129
|
+
|
|
3130
|
+
function cutoffPublishTimeForSinceDays(sinceDays) {
|
|
3131
|
+
return Math.floor(Date.now() / 1000) - sinceDays * 86400;
|
|
3132
|
+
}
|
|
3133
|
+
|
|
3134
|
+
function itemPublishTimeSeconds(item) {
|
|
3135
|
+
const value = item?.publish_time;
|
|
3136
|
+
const timestamp =
|
|
3137
|
+
typeof value === "number"
|
|
3138
|
+
? value
|
|
3139
|
+
: typeof value === "string"
|
|
3140
|
+
? Number(value)
|
|
3141
|
+
: NaN;
|
|
3142
|
+
if (!Number.isFinite(timestamp) || timestamp <= 0) {
|
|
3143
|
+
return undefined;
|
|
3144
|
+
}
|
|
3145
|
+
return timestamp;
|
|
3146
|
+
}
|
|
3147
|
+
|
|
3148
|
+
function filterItemsBySinceDays(items, cutoffPublishTime) {
|
|
3149
|
+
if (cutoffPublishTime === undefined) {
|
|
3150
|
+
return { items };
|
|
3151
|
+
}
|
|
3152
|
+
return {
|
|
3153
|
+
items: items.filter((item) => {
|
|
3154
|
+
const publishTime = itemPublishTimeSeconds(item);
|
|
3155
|
+
return publishTime !== undefined && publishTime >= cutoffPublishTime;
|
|
3156
|
+
}),
|
|
3157
|
+
};
|
|
3158
|
+
}
|
|
3159
|
+
|
|
3160
|
+
function shouldStopAtSinceDaysBoundary(operation, cutoffPublishTime, items) {
|
|
3161
|
+
if (operation.operation !== "user-posts" || cutoffPublishTime === undefined) {
|
|
3162
|
+
return false;
|
|
3163
|
+
}
|
|
3164
|
+
return items.some((item) => {
|
|
3165
|
+
const publishTime = itemPublishTimeSeconds(item);
|
|
3166
|
+
return publishTime !== undefined && publishTime < cutoffPublishTime;
|
|
3167
|
+
});
|
|
3168
|
+
}
|
|
3169
|
+
|
|
2988
3170
|
function createPaginatedItemDedupeState() {
|
|
2989
3171
|
return { seenKeys: new Set() };
|
|
2990
3172
|
}
|
|
@@ -3204,6 +3386,7 @@ function buildPaginatedData({
|
|
|
3204
3386
|
items,
|
|
3205
3387
|
pageCount,
|
|
3206
3388
|
nextMarker,
|
|
3389
|
+
stoppedBySinceDays,
|
|
3207
3390
|
}) {
|
|
3208
3391
|
const data = {
|
|
3209
3392
|
...(lastPageData && typeof lastPageData === "object" ? lastPageData : {}),
|
|
@@ -3214,6 +3397,9 @@ function buildPaginatedData({
|
|
|
3214
3397
|
};
|
|
3215
3398
|
delete data.next_page;
|
|
3216
3399
|
data.next_page_token = nextMarker || "";
|
|
3400
|
+
if (stoppedBySinceDays) {
|
|
3401
|
+
data.stopped_by_since_days = true;
|
|
3402
|
+
}
|
|
3217
3403
|
return data;
|
|
3218
3404
|
}
|
|
3219
3405
|
|
package/package.json
CHANGED
|
@@ -76,6 +76,7 @@ Optional arguments:
|
|
|
76
76
|
- Douyin `--pages <n>`: fetch and merge N search pages from the current starting point; continue with returned `next_page_token`.
|
|
77
77
|
- Kuaishou `--pages <n>`: fetch and merge N search pages from the current starting point; continue with returned `next_page_token`.
|
|
78
78
|
- `--max-items <n>`: stop after collecting N search results.
|
|
79
|
+
- `--since-days <1-365>`: keep only results whose public `publish_time` is within the last N days. Search remains bounded by `--pages` and does not promise complete platform coverage.
|
|
79
80
|
- `--pretty`: output formatting only.
|
|
80
81
|
- Kuaishou `--page-token <next_page_token>`: opaque pagination token; omit it on the first search request. Continue only with the complete returned `next_page_token` from the same search pagination chain. Do not modify, truncate, redact, mask, omit, normalize, rebuild, generate, or replace the middle with ellipses.
|
|
81
82
|
- Weibo `--page-token <next_page_token>`: opaque pagination token; omit it on the first search request. Continue only with the complete returned `next_page_token` from the same search pagination chain. Do not modify, truncate, redact, mask, omit, normalize, rebuild, generate, or replace the middle with ellipses.
|
|
@@ -126,6 +127,7 @@ Douyin content type filter values:
|
|
|
126
127
|
- `image`: image/text posts.
|
|
127
128
|
|
|
128
129
|
The command prints JSON with `platform`, `tool`, `arguments`, and `data`. Search supports `--pages` and `--max-items`, but not `--all`, because search has no stable complete-result boundary. Multi-page output keeps merged results in `data.items` and adds `page_count`, `item_count`, and the next-page marker.
|
|
130
|
+
With CLI `--since-days <n>`, XHS and Douyin search automatically prefer newest-first sorting and the closest native publish-time range unless the user explicitly sets sort or publish-time filters; WeChat Channels search defaults to `latest`; Kuaishou and Weibo only apply CLI-side `publish_time` filtering.
|
|
129
131
|
Kuaishou search pagination:
|
|
130
132
|
- Continue only when `next_page_token` is not empty.
|
|
131
133
|
- Pass the complete returned `next_page_token` back unchanged as `page_token` for the same search pagination chain. Do not modify, truncate, redact, mask, omit, normalize, rebuild, generate, or replace the middle with ellipses.
|
|
@@ -198,6 +200,7 @@ Do not pass `page` to `wechat_search_videos`; omit `page_token` on the first req
|
|
|
198
200
|
- `sort_type`: optional, one of `all`, `latest`, `popular`; omit it for the default sort.
|
|
199
201
|
- `duration_range`: optional duration filter, one of `all`, `under_5_min`, `between_5_and_20_min`, `over_20_min`; omit it for no duration filter.
|
|
200
202
|
Continue WeChat Channels pagination only when `next_page_token` is not empty. Pass the complete returned `next_page_token` back unchanged as `page_token` for the same keyword and filter chain.
|
|
203
|
+
`--since-days` uses CLI-side filtering only and is not an MCP tool argument; for MCP-only calls, request newest-first/native publish-time filters where available and filter returned `publish_time` values in your analysis.
|
|
201
204
|
|
|
202
205
|
## Output Guidance
|
|
203
206
|
|
|
@@ -73,6 +73,7 @@ Optional arguments:
|
|
|
73
73
|
- `--pages <n>`: fetch and merge N pages of creator content or creator series.
|
|
74
74
|
- `--all`: continue until `next_page_token` is empty; there is no default item or page cap.
|
|
75
75
|
- `--max-items <n>`: stop after collecting N creator content or series items.
|
|
76
|
+
- `--since-days <1-365>`: keep only creator content whose public `publish_time` is within the last N days. When `--pages` is omitted, the CLI continues creator content lists until the publish-time boundary is reached.
|
|
76
77
|
- `--pretty`: output formatting only.
|
|
77
78
|
- Kuaishou `--user-id <user_id>`: preferred when the creator user_id is already known.
|
|
78
79
|
- Kuaishou `--profile-url <profile_url_or_share_text>`: use for a profile URL, short link, or profile share text.
|
|
@@ -84,6 +85,7 @@ Optional arguments:
|
|
|
84
85
|
Use either the ID option or the profile URL option for a single command, not both.
|
|
85
86
|
|
|
86
87
|
The command prints JSON with `platform`, `tool`, `arguments`, and `data`. Multi-page output keeps merged creator content or series items in `data.items` and adds `page_count`, `item_count`, and `next_page_token`.
|
|
88
|
+
For recent creator research, prefer CLI `--since-days 30` or another user-specified day window. `--since-days` applies to creator content lists only, not Douyin `user-series`.
|
|
87
89
|
|
|
88
90
|
## Safety Boundary
|
|
89
91
|
|
|
@@ -124,6 +126,7 @@ Weibo creator post pagination uses opaque `page_token` values; pass the complete
|
|
|
124
126
|
- `wechat_get_user_posted_videos_by_user_id`: preferred when the WeChat Channels / 视频号 `@finder` user_id is already known.
|
|
125
127
|
- `wechat_get_user_posted_videos_by_url`: use a WeChat Channels / 视频号 video link or share text to resolve the author and list that creator's videos.
|
|
126
128
|
WeChat Channels / 视频号 creator video pagination uses opaque `page_token` values; pass the complete returned `next_page_token` back unchanged for the same user. Do not modify, truncate, redact, mask, omit, normalize, rebuild, generate, or replace the middle with ellipses.
|
|
129
|
+
`--since-days` uses CLI-side filtering only and is not an MCP tool argument; for MCP-only calls, continue pages as needed and filter returned `publish_time` values in your analysis.
|
|
127
130
|
|
|
128
131
|
## Output Guidance
|
|
129
132
|
|
|
@@ -168,6 +168,7 @@ Optional arguments:
|
|
|
168
168
|
- `--pages <n>`: fetch and merge N pages for search, comments, replies, creator posts, or creator series.
|
|
169
169
|
- `--all`: fetch comments, replies, creator posts, or creator series until `next_page_token` is empty; do not use it for search.
|
|
170
170
|
- `--max-items <n>`: stop after collecting N primary results.
|
|
171
|
+
- `--since-days <1-365>`: keep search or creator content-list items whose public `publish_time` is within the last N days. Search stays bounded by `--pages`; creator content lists continue until the publish-time boundary when `--pages` is omitted.
|
|
171
172
|
- `--include-replies`: for first-level comments, also fetch nested second-level replies under each returned comment.
|
|
172
173
|
- `--sort-type`, `--note-type`, `--publish-time-range`, `--duration-range`, and `--content-type`: apply only to XHS, Douyin, or WeChat Channels keyword research commands when the user asks for filtering; Kuaishou and Weibo search currently use `--keyword` and optional `--page-token`.
|
|
173
174
|
- `--comment-id`: required for reply/sub-comment commands together with the content ID.
|
|
@@ -185,6 +186,7 @@ Optional arguments:
|
|
|
185
186
|
## Choose The Narrowest Entry
|
|
186
187
|
|
|
187
188
|
Use the most specific direct CLI command for the user's task instead of forcing every request through keyword research. The command prints JSON with `platform`, `tool`, `arguments`, and `data`.
|
|
189
|
+
When the user asks for recent content, pass CLI `--since-days <n>` with bounded `--pages`; keep in mind this filters returned `publish_time` values and does not promise complete platform coverage.
|
|
188
190
|
|
|
189
191
|
## Safety Boundary
|
|
190
192
|
|