@skills-store/rednote 0.1.14 → 0.1.16
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 +19 -327
- package/dist/browser/connect-browser.js +59 -31
- package/dist/index.js +2 -2
- package/dist/rednote/checkLogin.js +6 -0
- package/dist/rednote/getMyProfile.js +139 -0
- package/dist/rednote/getProfile.js +145 -31
- package/dist/rednote/index.js +8 -2
- package/dist/rednote/interact.js +30 -7
- package/dist/rednote/login.js +15 -21
- package/dist/rednote/persistence.js +187 -1
- package/dist/rednote/status.js +4 -0
- package/dist/utils/browser-cli.js +1 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -36,10 +36,10 @@ For most tasks, run commands in this order:
|
|
|
36
36
|
rednote env
|
|
37
37
|
rednote browser create --name seller-main --browser chrome --port 9222
|
|
38
38
|
rednote browser connect --instance seller-main
|
|
39
|
-
rednote login
|
|
40
|
-
rednote status
|
|
41
|
-
rednote search --
|
|
42
|
-
rednote interact --
|
|
39
|
+
rednote login
|
|
40
|
+
rednote status
|
|
41
|
+
rednote search --keyword 护肤
|
|
42
|
+
rednote interact --url "https://www.xiaohongshu.com/explore/xxx?xsec_token=yyy" --like --collect --comment "写得真好"
|
|
43
43
|
```
|
|
44
44
|
|
|
45
45
|
## Commands
|
|
@@ -68,7 +68,7 @@ Use `env` first when checking installation, runtime info, or storage paths.
|
|
|
68
68
|
### `status`
|
|
69
69
|
|
|
70
70
|
```bash
|
|
71
|
-
rednote status
|
|
71
|
+
rednote status
|
|
72
72
|
```
|
|
73
73
|
|
|
74
74
|
Use `status` to confirm whether an instance exists, is running, and appears logged in.
|
|
@@ -76,7 +76,7 @@ Use `status` to confirm whether an instance exists, is running, and appears logg
|
|
|
76
76
|
### `check-login`
|
|
77
77
|
|
|
78
78
|
```bash
|
|
79
|
-
rednote check-login
|
|
79
|
+
rednote check-login
|
|
80
80
|
```
|
|
81
81
|
|
|
82
82
|
Use `check-login` when you only want to verify whether the session is still valid.
|
|
@@ -84,7 +84,7 @@ Use `check-login` when you only want to verify whether the session is still vali
|
|
|
84
84
|
### `login`
|
|
85
85
|
|
|
86
86
|
```bash
|
|
87
|
-
rednote login
|
|
87
|
+
rednote login
|
|
88
88
|
```
|
|
89
89
|
|
|
90
90
|
Use `login` after `browser connect` if the instance is not authenticated yet.
|
|
@@ -92,7 +92,7 @@ Use `login` after `browser connect` if the instance is not authenticated yet.
|
|
|
92
92
|
### `home`
|
|
93
93
|
|
|
94
94
|
```bash
|
|
95
|
-
rednote home --
|
|
95
|
+
rednote home --format md --save
|
|
96
96
|
```
|
|
97
97
|
|
|
98
98
|
Use `home` when you want the current home feed and optionally want to save it to disk.
|
|
@@ -103,6 +103,10 @@ The terminal output always uses the compact summary format below, even when `--f
|
|
|
103
103
|
id=<database nanoid>
|
|
104
104
|
title=<post title>
|
|
105
105
|
like=<liked count>
|
|
106
|
+
|
|
107
|
+
id=...
|
|
108
|
+
title=...
|
|
109
|
+
like=...
|
|
106
110
|
```
|
|
107
111
|
|
|
108
112
|
Captured home feed posts are upserted into `~/.skills-router/rednote/main.db` (the same path returned by `rednote env`). They are stored in the `rednote_posts` table, and the printed `id` is that table's `nanoid(16)` primary key.
|
|
@@ -110,8 +114,8 @@ Captured home feed posts are upserted into `~/.skills-router/rednote/main.db` (t
|
|
|
110
114
|
### `search`
|
|
111
115
|
|
|
112
116
|
```bash
|
|
113
|
-
rednote search --
|
|
114
|
-
rednote search --
|
|
117
|
+
rednote search --keyword 护肤
|
|
118
|
+
rednote search --keyword 护肤 --format json --save ./output/search.jsonl
|
|
115
119
|
```
|
|
116
120
|
|
|
117
121
|
Use `search` for keyword-based note lookup.
|
|
@@ -129,8 +133,8 @@ Captured search results are also upserted into `~/.skills-router/rednote/main.db
|
|
|
129
133
|
### `get-feed-detail`
|
|
130
134
|
|
|
131
135
|
```bash
|
|
132
|
-
rednote get-feed-detail --
|
|
133
|
-
rednote get-feed-detail --
|
|
136
|
+
rednote get-feed-detail --id <nanoid>
|
|
137
|
+
rednote get-feed-detail --url "https://www.xiaohongshu.com/explore/xxx?xsec_token=yyy"
|
|
134
138
|
```
|
|
135
139
|
|
|
136
140
|
Use `get-feed-detail` when you already have a Xiaohongshu note URL, or when you have a database `id` returned by `home` or `search`. With `--id`, the CLI looks up the saved URL from `~/.skills-router/rednote/main.db` and then navigates with that raw URL.
|
|
@@ -140,7 +144,7 @@ Captured note details and comments are also upserted into `~/.skills-router/redn
|
|
|
140
144
|
### `get-profile`
|
|
141
145
|
|
|
142
146
|
```bash
|
|
143
|
-
rednote get-profile --
|
|
147
|
+
rednote get-profile --id USER_ID
|
|
144
148
|
```
|
|
145
149
|
|
|
146
150
|
Use `get-profile` when you want author or account profile information.
|
|
@@ -149,8 +153,8 @@ Use `get-profile` when you want author or account profile information.
|
|
|
149
153
|
### `interact`
|
|
150
154
|
|
|
151
155
|
```bash
|
|
152
|
-
rednote interact --
|
|
153
|
-
rednote interact --
|
|
156
|
+
rednote interact --id <nanoid> --like --collect
|
|
157
|
+
rednote interact --id <nanoid> --like --collect --comment "写得真好"
|
|
154
158
|
```
|
|
155
159
|
|
|
156
160
|
Use `interact` when you want the single entrypoint for note operations such as like, collect, and comment in one command. Use `--comment TEXT` for replies; there is no standalone `comment` command.
|
|
@@ -168,318 +172,6 @@ Use `interact` when you want the single entrypoint for note operations such as l
|
|
|
168
172
|
- `--url` is required for `interact`; at least one of `--like`, `--collect`, or `--comment TEXT` must be provided.
|
|
169
173
|
- replies are sent with `interact --comment TEXT`.
|
|
170
174
|
|
|
171
|
-
## JSON success shapes
|
|
172
|
-
|
|
173
|
-
Use these shapes as the success model when a command returns JSON.
|
|
174
|
-
|
|
175
|
-
### Shared note item
|
|
176
|
-
|
|
177
|
-
`home`, `search`, and `profile.notes` share the normalized `RednotePost` shape:
|
|
178
|
-
|
|
179
|
-
```json
|
|
180
|
-
{
|
|
181
|
-
"id": "string",
|
|
182
|
-
"modelType": "string",
|
|
183
|
-
"xsecToken": "string|null",
|
|
184
|
-
"url": "string",
|
|
185
|
-
"noteCard": {
|
|
186
|
-
"type": "string|null",
|
|
187
|
-
"displayTitle": "string|null",
|
|
188
|
-
"cover": {
|
|
189
|
-
"urlDefault": "string|null",
|
|
190
|
-
"urlPre": "string|null",
|
|
191
|
-
"url": "string|null",
|
|
192
|
-
"fileId": "string|null",
|
|
193
|
-
"width": "number|null",
|
|
194
|
-
"height": "number|null",
|
|
195
|
-
"infoList": [{ "imageScene": "string|null", "url": "string|null" }]
|
|
196
|
-
},
|
|
197
|
-
"user": {
|
|
198
|
-
"userId": "string|null",
|
|
199
|
-
"nickname": "string|null",
|
|
200
|
-
"nickName": "string|null",
|
|
201
|
-
"avatar": "string|null",
|
|
202
|
-
"xsecToken": "string|null"
|
|
203
|
-
},
|
|
204
|
-
"interactInfo": {
|
|
205
|
-
"liked": "boolean",
|
|
206
|
-
"likedCount": "string|null",
|
|
207
|
-
"commentCount": "string|null",
|
|
208
|
-
"collectedCount": "string|null",
|
|
209
|
-
"sharedCount": "string|null"
|
|
210
|
-
},
|
|
211
|
-
"cornerTagInfo": [{ "type": "string|null", "text": "string|null" }],
|
|
212
|
-
"imageList": [{ "width": "number|null", "height": "number|null", "infoList": [{ "imageScene": "string|null", "url": "string|null" }] }],
|
|
213
|
-
"video": { "duration": "number|null" }
|
|
214
|
-
}
|
|
215
|
-
}
|
|
216
|
-
```
|
|
217
|
-
|
|
218
|
-
### `env --format json`
|
|
219
|
-
|
|
220
|
-
`env` is the main exception: it returns a raw environment object instead of `{ "ok": true, ... }`.
|
|
221
|
-
|
|
222
|
-
```json
|
|
223
|
-
{
|
|
224
|
-
"packageRoot": "string",
|
|
225
|
-
"homeDir": "string",
|
|
226
|
-
"platform": "string",
|
|
227
|
-
"nodeVersion": "string",
|
|
228
|
-
"storageHome": "string",
|
|
229
|
-
"storageRoot": "string",
|
|
230
|
-
"databasePath": "string",
|
|
231
|
-
"instancesDir": "string",
|
|
232
|
-
"instanceStorePath": "string",
|
|
233
|
-
"legacyPackageInstancesDir": "string"
|
|
234
|
-
}
|
|
235
|
-
```
|
|
236
|
-
|
|
237
|
-
### Browser commands
|
|
238
|
-
|
|
239
|
-
`browser list`:
|
|
240
|
-
|
|
241
|
-
```json
|
|
242
|
-
{
|
|
243
|
-
"lastConnect": { "scope": "default|custom", "name": "string", "browser": "chrome|edge|chromium|brave" } | null,
|
|
244
|
-
"instances": [{
|
|
245
|
-
"type": "chrome|edge|chromium|brave",
|
|
246
|
-
"name": "string",
|
|
247
|
-
"executablePath": "string",
|
|
248
|
-
"userDataDir": "string",
|
|
249
|
-
"exists": true,
|
|
250
|
-
"inUse": false,
|
|
251
|
-
"pid": "number|null",
|
|
252
|
-
"lockFiles": ["string"],
|
|
253
|
-
"matchedProcess": { "pid": "number", "name": "string", "cmdline": "string" } | null,
|
|
254
|
-
"staleLock": false,
|
|
255
|
-
"remotePort": "number|null",
|
|
256
|
-
"scope": "default|custom",
|
|
257
|
-
"instanceName": "string",
|
|
258
|
-
"createdAt": "string|null",
|
|
259
|
-
"lastConnect": false
|
|
260
|
-
}]
|
|
261
|
-
}
|
|
262
|
-
```
|
|
263
|
-
|
|
264
|
-
`browser create`:
|
|
265
|
-
|
|
266
|
-
```json
|
|
267
|
-
{
|
|
268
|
-
"ok": true,
|
|
269
|
-
"instance": {
|
|
270
|
-
"name": "string",
|
|
271
|
-
"browser": "chrome|edge|chromium|brave",
|
|
272
|
-
"userDataDir": "string",
|
|
273
|
-
"createdAt": "string",
|
|
274
|
-
"remoteDebuggingPort": "number|undefined"
|
|
275
|
-
}
|
|
276
|
-
}
|
|
277
|
-
```
|
|
278
|
-
|
|
279
|
-
`browser connect`:
|
|
280
|
-
|
|
281
|
-
```json
|
|
282
|
-
{
|
|
283
|
-
"ok": true,
|
|
284
|
-
"type": "chrome|edge|chromium|brave",
|
|
285
|
-
"executablePath": "string",
|
|
286
|
-
"userDataDir": "string",
|
|
287
|
-
"remoteDebuggingPort": "number",
|
|
288
|
-
"wsUrl": "string",
|
|
289
|
-
"pid": "number|null"
|
|
290
|
-
}
|
|
291
|
-
```
|
|
292
|
-
|
|
293
|
-
`browser remove`:
|
|
294
|
-
|
|
295
|
-
```json
|
|
296
|
-
{
|
|
297
|
-
"ok": true,
|
|
298
|
-
"removedInstance": {
|
|
299
|
-
"name": "string",
|
|
300
|
-
"browser": "chrome|edge|chromium|brave",
|
|
301
|
-
"userDataDir": "string",
|
|
302
|
-
"createdAt": "string",
|
|
303
|
-
"remoteDebuggingPort": "number|undefined"
|
|
304
|
-
},
|
|
305
|
-
"removedDir": true,
|
|
306
|
-
"closedPids": ["number"]
|
|
307
|
-
}
|
|
308
|
-
```
|
|
309
|
-
|
|
310
|
-
### Session and account commands
|
|
311
|
-
|
|
312
|
-
`status`:
|
|
313
|
-
|
|
314
|
-
```json
|
|
315
|
-
{
|
|
316
|
-
"ok": true,
|
|
317
|
-
"instance": {
|
|
318
|
-
"scope": "default|custom",
|
|
319
|
-
"name": "string",
|
|
320
|
-
"browser": "chrome|edge|chromium|brave",
|
|
321
|
-
"source": "argument|last-connect|single-instance",
|
|
322
|
-
"status": "running|stopped|missing|stale-lock",
|
|
323
|
-
"exists": true,
|
|
324
|
-
"inUse": false,
|
|
325
|
-
"pid": "number|null",
|
|
326
|
-
"remotePort": "number|null",
|
|
327
|
-
"userDataDir": "string",
|
|
328
|
-
"createdAt": "string|null",
|
|
329
|
-
"lastConnect": false
|
|
330
|
-
},
|
|
331
|
-
"rednote": {
|
|
332
|
-
"loginStatus": "logged-in|logged-out|unknown",
|
|
333
|
-
"lastLoginAt": "string|null"
|
|
334
|
-
}
|
|
335
|
-
}
|
|
336
|
-
```
|
|
337
|
-
|
|
338
|
-
`check-login`:
|
|
339
|
-
|
|
340
|
-
```json
|
|
341
|
-
{
|
|
342
|
-
"ok": true,
|
|
343
|
-
"rednote": {
|
|
344
|
-
"loginStatus": "logged-in|logged-out|unknown",
|
|
345
|
-
"lastLoginAt": "string|null",
|
|
346
|
-
"needLogin": false,
|
|
347
|
-
"checkedAt": "string"
|
|
348
|
-
}
|
|
349
|
-
}
|
|
350
|
-
```
|
|
351
|
-
|
|
352
|
-
`login`:
|
|
353
|
-
|
|
354
|
-
```json
|
|
355
|
-
{
|
|
356
|
-
"ok": true,
|
|
357
|
-
"rednote": {
|
|
358
|
-
"loginClicked": true,
|
|
359
|
-
"pageUrl": "string",
|
|
360
|
-
"waitingForPhoneLogin": true,
|
|
361
|
-
"qrCodePath": "string|null",
|
|
362
|
-
"message": "string"
|
|
363
|
-
}
|
|
364
|
-
}
|
|
365
|
-
```
|
|
366
|
-
|
|
367
|
-
### Feed and profile commands
|
|
368
|
-
|
|
369
|
-
`home` stdout (both `md` and `json`):
|
|
370
|
-
|
|
371
|
-
```text
|
|
372
|
-
id=<database nanoid>
|
|
373
|
-
title=<post title>
|
|
374
|
-
like=<liked count>
|
|
375
|
-
```
|
|
376
|
-
|
|
377
|
-
`home --format json --save PATH` writes the raw `RednotePost[]` array to disk, while stdout still prints the summary list above.
|
|
378
|
-
|
|
379
|
-
`search` stdout (both `md` and `json`):
|
|
380
|
-
|
|
381
|
-
```text
|
|
382
|
-
id=<database nanoid>
|
|
383
|
-
title=<post title>
|
|
384
|
-
like=<liked count>
|
|
385
|
-
```
|
|
386
|
-
|
|
387
|
-
`search --format json --save PATH` writes the raw `RednotePost[]` array to disk, while stdout still prints the summary list above.
|
|
388
|
-
|
|
389
|
-
`get-feed-detail --format json`:
|
|
390
|
-
|
|
391
|
-
```json
|
|
392
|
-
{
|
|
393
|
-
"ok": true,
|
|
394
|
-
"detail": {
|
|
395
|
-
"fetchedAt": "string",
|
|
396
|
-
"total": "number",
|
|
397
|
-
"items": [{
|
|
398
|
-
"url": "string",
|
|
399
|
-
"note": {
|
|
400
|
-
"noteId": "string|null",
|
|
401
|
-
"title": "string|null",
|
|
402
|
-
"desc": "string|null",
|
|
403
|
-
"type": "string|null",
|
|
404
|
-
"interactInfo": {
|
|
405
|
-
"liked": "boolean|null",
|
|
406
|
-
"likedCount": "string|null",
|
|
407
|
-
"commentCount": "string|null",
|
|
408
|
-
"collected": "boolean|null",
|
|
409
|
-
"collectedCount": "string|null",
|
|
410
|
-
"shareCount": "string|null",
|
|
411
|
-
"followed": "boolean|null"
|
|
412
|
-
},
|
|
413
|
-
"tagList": [{ "name": "string|null" }],
|
|
414
|
-
"imageList": [{ "urlDefault": "string|null", "urlPre": "string|null", "width": "number|null", "height": "number|null" }],
|
|
415
|
-
"video": { "url": "string|null", "raw": "unknown" } | null,
|
|
416
|
-
"raw": "unknown"
|
|
417
|
-
},
|
|
418
|
-
"comments": [{
|
|
419
|
-
"id": "string|null",
|
|
420
|
-
"content": "string|null",
|
|
421
|
-
"userId": "string|null",
|
|
422
|
-
"nickname": "string|null",
|
|
423
|
-
"likedCount": "string|null",
|
|
424
|
-
"subCommentCount": "number|null",
|
|
425
|
-
"raw": "unknown"
|
|
426
|
-
}]
|
|
427
|
-
}]
|
|
428
|
-
}
|
|
429
|
-
}
|
|
430
|
-
```
|
|
431
|
-
|
|
432
|
-
`get-profile --format json`:
|
|
433
|
-
|
|
434
|
-
```json
|
|
435
|
-
{
|
|
436
|
-
"ok": true,
|
|
437
|
-
"profile": {
|
|
438
|
-
"userId": "string",
|
|
439
|
-
"url": "string",
|
|
440
|
-
"fetchedAt": "string",
|
|
441
|
-
"user": {
|
|
442
|
-
"userId": "string|null",
|
|
443
|
-
"nickname": "string|null",
|
|
444
|
-
"desc": "string|null",
|
|
445
|
-
"avatar": "string|null",
|
|
446
|
-
"ipLocation": "string|null",
|
|
447
|
-
"gender": "string|null",
|
|
448
|
-
"follows": "string|number|null",
|
|
449
|
-
"fans": "string|number|null",
|
|
450
|
-
"interaction": "string|number|null",
|
|
451
|
-
"tags": ["string"],
|
|
452
|
-
"raw": "unknown"
|
|
453
|
-
},
|
|
454
|
-
"notes": ["RednotePost"],
|
|
455
|
-
"raw": {
|
|
456
|
-
"userPageData": "unknown",
|
|
457
|
-
"notes": "unknown"
|
|
458
|
-
}
|
|
459
|
-
}
|
|
460
|
-
}
|
|
461
|
-
```
|
|
462
|
-
|
|
463
|
-
### Action commands
|
|
464
|
-
|
|
465
|
-
`publish`:
|
|
466
|
-
|
|
467
|
-
```json
|
|
468
|
-
{
|
|
469
|
-
"ok": true,
|
|
470
|
-
"message": "string"
|
|
471
|
-
}
|
|
472
|
-
```
|
|
473
|
-
|
|
474
|
-
`interact`:
|
|
475
|
-
|
|
476
|
-
```json
|
|
477
|
-
{
|
|
478
|
-
"ok": true,
|
|
479
|
-
"message": "string"
|
|
480
|
-
}
|
|
481
|
-
```
|
|
482
|
-
|
|
483
175
|
## Storage
|
|
484
176
|
|
|
485
177
|
The CLI stores browser instances and metadata under:
|
|
@@ -9,44 +9,70 @@ async function resolveBrowserPid(remoteDebuggingPort, detectedPid) {
|
|
|
9
9
|
return portPids[0] ?? null;
|
|
10
10
|
}
|
|
11
11
|
export async function resolveConnectOptions(options) {
|
|
12
|
-
if (
|
|
12
|
+
if (options.instanceName) {
|
|
13
|
+
if (options.userDataDir) {
|
|
14
|
+
throw new Error('Do not combine --instance with --user-data-dir');
|
|
15
|
+
}
|
|
16
|
+
if (options.browser) {
|
|
17
|
+
throw new Error('Do not combine --instance with --browser');
|
|
18
|
+
}
|
|
19
|
+
const store = readInstanceStore();
|
|
20
|
+
const instanceName = validateInstanceName(options.instanceName);
|
|
21
|
+
const persisted = store.instances.find((instance)=>instance.name === instanceName);
|
|
22
|
+
if (!persisted) {
|
|
23
|
+
throw new Error(`Unknown instance: ${instanceName}`);
|
|
24
|
+
}
|
|
25
|
+
let remoteDebuggingPort = options.remoteDebuggingPort ?? persisted.remoteDebuggingPort;
|
|
26
|
+
if (!remoteDebuggingPort) {
|
|
27
|
+
remoteDebuggingPort = await getRandomAvailablePort();
|
|
28
|
+
updateInstanceRemoteDebuggingPort(instanceName, remoteDebuggingPort);
|
|
29
|
+
}
|
|
13
30
|
return {
|
|
14
|
-
connectOptions:
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
31
|
+
connectOptions: {
|
|
32
|
+
...options,
|
|
33
|
+
browser: persisted.browser,
|
|
34
|
+
userDataDir: persisted.userDataDir,
|
|
35
|
+
remoteDebuggingPort
|
|
36
|
+
},
|
|
37
|
+
lastConnect: {
|
|
38
|
+
scope: 'custom',
|
|
39
|
+
name: persisted.name,
|
|
40
|
+
browser: persisted.browser
|
|
19
41
|
}
|
|
20
42
|
};
|
|
21
43
|
}
|
|
22
|
-
if (options.userDataDir) {
|
|
23
|
-
throw new Error('Do not combine --instance with --user-data-dir');
|
|
24
|
-
}
|
|
25
|
-
if (options.browser) {
|
|
26
|
-
throw new Error('Do not combine --instance with --browser');
|
|
27
|
-
}
|
|
28
44
|
const store = readInstanceStore();
|
|
29
|
-
const
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
45
|
+
const lastConnect = store.lastConnect;
|
|
46
|
+
if (lastConnect && lastConnect.scope === 'custom') {
|
|
47
|
+
const persisted = store.instances.find((instance)=>instance.name === lastConnect.name);
|
|
48
|
+
if (persisted) {
|
|
49
|
+
let remoteDebuggingPort = options.remoteDebuggingPort ?? persisted.remoteDebuggingPort;
|
|
50
|
+
if (!remoteDebuggingPort) {
|
|
51
|
+
remoteDebuggingPort = await getRandomAvailablePort();
|
|
52
|
+
updateInstanceRemoteDebuggingPort(lastConnect.name, remoteDebuggingPort);
|
|
53
|
+
}
|
|
54
|
+
return {
|
|
55
|
+
connectOptions: {
|
|
56
|
+
...options,
|
|
57
|
+
instanceName: persisted.name,
|
|
58
|
+
browser: persisted.browser,
|
|
59
|
+
userDataDir: persisted.userDataDir,
|
|
60
|
+
remoteDebuggingPort
|
|
61
|
+
},
|
|
62
|
+
lastConnect: {
|
|
63
|
+
scope: 'custom',
|
|
64
|
+
name: persisted.name,
|
|
65
|
+
browser: persisted.browser
|
|
66
|
+
}
|
|
67
|
+
};
|
|
68
|
+
}
|
|
38
69
|
}
|
|
39
70
|
return {
|
|
40
|
-
connectOptions:
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
},
|
|
46
|
-
lastConnect: {
|
|
47
|
-
scope: 'custom',
|
|
48
|
-
name: persisted.name,
|
|
49
|
-
browser: persisted.browser
|
|
71
|
+
connectOptions: options,
|
|
72
|
+
lastConnect: options.userDataDir ? null : {
|
|
73
|
+
scope: 'default',
|
|
74
|
+
name: options.browser ?? 'chrome',
|
|
75
|
+
browser: options.browser ?? 'chrome'
|
|
50
76
|
}
|
|
51
77
|
};
|
|
52
78
|
}
|
|
@@ -86,6 +112,7 @@ export async function initBrowser(options = {}) {
|
|
|
86
112
|
});
|
|
87
113
|
return {
|
|
88
114
|
ok: true,
|
|
115
|
+
instanceName: options.instanceName,
|
|
89
116
|
type: spec.type,
|
|
90
117
|
executablePath,
|
|
91
118
|
userDataDir,
|
|
@@ -135,6 +162,7 @@ export async function initBrowser(options = {}) {
|
|
|
135
162
|
}
|
|
136
163
|
return {
|
|
137
164
|
ok: true,
|
|
165
|
+
instanceName: options.instanceName ?? null,
|
|
138
166
|
type: spec.type,
|
|
139
167
|
executablePath,
|
|
140
168
|
userDataDir,
|
package/dist/index.js
CHANGED
|
@@ -20,7 +20,7 @@ Commands:
|
|
|
20
20
|
check-login [--instance NAME]
|
|
21
21
|
login [--instance NAME]
|
|
22
22
|
publish [--instance NAME]
|
|
23
|
-
interact [--instance NAME] --url URL [--like] [--collect] [--comment TEXT]
|
|
23
|
+
interact [--instance NAME] [--id ID | --url URL] [--like] [--collect] [--comment TEXT]
|
|
24
24
|
home [--instance NAME] [--format md|json] [--save [PATH]]
|
|
25
25
|
search [--instance NAME] --keyword TEXT [--format md|json] [--save [PATH]]
|
|
26
26
|
get-feed-detail [--instance NAME] --url URL [--format md|json]
|
|
@@ -32,7 +32,7 @@ Examples:
|
|
|
32
32
|
npx -y @skills-store/rednote browser connect --instance seller-main
|
|
33
33
|
npx -y @skills-store/rednote env
|
|
34
34
|
npx -y @skills-store/rednote publish --instance seller-main --type video --video ./note.mp4 --title 标题 --content 描述
|
|
35
|
-
npx -y @skills-store/rednote interact --instance seller-main --
|
|
35
|
+
npx -y @skills-store/rednote interact --instance seller-main --id NOTE_ID --like --collect --comment "写得真好"
|
|
36
36
|
npx -y @skills-store/rednote search --instance seller-main --keyword 护肤
|
|
37
37
|
`);
|
|
38
38
|
}
|
|
@@ -83,8 +83,14 @@ export async function checkRednoteLogin(target, session) {
|
|
|
83
83
|
pageUrl: page.url(),
|
|
84
84
|
needLogin
|
|
85
85
|
});
|
|
86
|
+
let userId;
|
|
87
|
+
if (!needLogin) {
|
|
88
|
+
const locator = page.locator("li.user a").first();
|
|
89
|
+
userId = (await locator.getAttribute("href"))?.split('/').pop();
|
|
90
|
+
}
|
|
86
91
|
return {
|
|
87
92
|
loginStatus: needLogin ? 'logged-out' : 'logged-in',
|
|
93
|
+
userId: userId ?? null,
|
|
88
94
|
lastLoginAt: null,
|
|
89
95
|
needLogin,
|
|
90
96
|
checkedAt: new Date().toISOString()
|