@jackwener/opencli 1.7.6 → 1.7.8
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 +17 -8
- package/README.zh-CN.md +14 -8
- package/cli-manifest.json +469 -11
- package/clis/51job/company.js +125 -0
- package/clis/51job/detail.js +108 -0
- package/clis/51job/hot.js +55 -0
- package/clis/51job/search.js +79 -0
- package/clis/51job/utils.js +302 -0
- package/clis/51job/utils.test.js +69 -0
- package/clis/amazon/discussion.js +37 -6
- package/clis/amazon/discussion.test.js +147 -32
- package/clis/bilibili/video.js +11 -4
- package/clis/bilibili/video.test.js +51 -0
- package/clis/chatgpt/image.js +1 -1
- package/clis/chatgpt-app/ask.js +3 -19
- package/clis/chatgpt-app/ax.js +132 -1
- package/clis/chatgpt-app/ax.test.js +23 -0
- package/clis/chatgpt-app/send.js +2 -21
- package/clis/deepseek/ask.js +50 -18
- package/clis/deepseek/ask.test.js +195 -2
- package/clis/deepseek/utils.js +113 -29
- package/clis/deepseek/utils.test.js +109 -1
- package/clis/gemini/image.js +1 -1
- package/clis/instagram/download.js +1 -1
- package/clis/powerchina/search.js +250 -0
- package/clis/powerchina/search.test.js +67 -0
- package/clis/sinafinance/stock.js +5 -2
- package/clis/sinafinance/stock.test.js +59 -0
- package/clis/toutiao/articles.js +81 -0
- package/clis/toutiao/articles.test.js +23 -0
- package/clis/twitter/likes.js +3 -2
- package/clis/twitter/search.js +4 -2
- package/clis/twitter/search.test.js +4 -0
- package/clis/twitter/shared.js +28 -0
- package/clis/twitter/shared.test.js +96 -0
- package/clis/twitter/thread.js +3 -1
- package/clis/twitter/timeline.js +3 -2
- package/clis/twitter/tweets.js +3 -2
- package/clis/twitter/tweets.test.js +1 -1
- package/clis/web/read.js +25 -5
- package/clis/web/read.test.js +76 -0
- package/clis/weixin/create-draft.js +225 -0
- package/clis/weixin/drafts.js +65 -0
- package/clis/weixin/drafts.test.js +65 -0
- package/clis/weread/ai-outline.js +170 -0
- package/clis/weread/ai-outline.test.js +83 -0
- package/clis/weread/book.js +57 -44
- package/clis/weread/commands.test.js +24 -0
- package/clis/xiaoyuzhou/podcast-episodes.js +2 -2
- package/clis/xiaoyuzhou/podcast-episodes.test.js +78 -0
- package/dist/src/browser/analyze.d.ts +103 -0
- package/dist/src/browser/analyze.js +230 -0
- package/dist/src/browser/analyze.test.d.ts +1 -0
- package/dist/src/browser/analyze.test.js +164 -0
- package/dist/src/browser/article-extract.d.ts +57 -0
- package/dist/src/browser/article-extract.e2e.test.d.ts +1 -0
- package/dist/src/browser/article-extract.e2e.test.js +105 -0
- package/dist/src/browser/article-extract.js +169 -0
- package/dist/src/browser/article-extract.test.d.ts +1 -0
- package/dist/src/browser/article-extract.test.js +94 -0
- package/dist/src/browser/cdp.js +11 -2
- package/dist/src/browser/verify-fixture.d.ts +59 -0
- package/dist/src/browser/verify-fixture.js +213 -0
- package/dist/src/browser/verify-fixture.test.d.ts +1 -0
- package/dist/src/browser/verify-fixture.test.js +161 -0
- package/dist/src/cli.d.ts +32 -0
- package/dist/src/cli.js +333 -43
- package/dist/src/cli.test.js +257 -1
- package/dist/src/commanderAdapter.js +12 -0
- package/dist/src/commanderAdapter.test.js +11 -0
- package/dist/src/daemon.d.ts +3 -2
- package/dist/src/daemon.js +16 -4
- package/dist/src/daemon.test.d.ts +1 -0
- package/dist/src/daemon.test.js +19 -0
- package/dist/src/download/article-download.d.ts +12 -0
- package/dist/src/download/article-download.js +141 -17
- package/dist/src/download/article-download.test.js +196 -0
- package/dist/src/download/index.js +73 -86
- package/dist/src/errors.js +4 -2
- package/dist/src/errors.test.js +13 -0
- package/dist/src/launcher.d.ts +1 -1
- package/dist/src/launcher.js +3 -3
- package/dist/src/output.js +1 -1
- package/dist/src/output.test.js +6 -0
- package/package.json +5 -1
package/cli-manifest.json
CHANGED
|
@@ -271,6 +271,264 @@
|
|
|
271
271
|
"modulePath": "36kr/search.js",
|
|
272
272
|
"sourceFile": "36kr/search.js"
|
|
273
273
|
},
|
|
274
|
+
{
|
|
275
|
+
"site": "51job",
|
|
276
|
+
"name": "company",
|
|
277
|
+
"description": "51job 公司简介 + 在招职位(按 encCoId)",
|
|
278
|
+
"domain": "jobs.51job.com",
|
|
279
|
+
"strategy": "cookie",
|
|
280
|
+
"browser": true,
|
|
281
|
+
"args": [
|
|
282
|
+
{
|
|
283
|
+
"name": "encCoId",
|
|
284
|
+
"type": "string",
|
|
285
|
+
"required": true,
|
|
286
|
+
"positional": true,
|
|
287
|
+
"help": "加密公司 ID(search 返回的 encCoId)"
|
|
288
|
+
},
|
|
289
|
+
{
|
|
290
|
+
"name": "limit",
|
|
291
|
+
"type": "int",
|
|
292
|
+
"default": 20,
|
|
293
|
+
"required": false,
|
|
294
|
+
"help": "返回职位数(1-50)"
|
|
295
|
+
}
|
|
296
|
+
],
|
|
297
|
+
"columns": [
|
|
298
|
+
"rank",
|
|
299
|
+
"jobId",
|
|
300
|
+
"title",
|
|
301
|
+
"salary",
|
|
302
|
+
"city",
|
|
303
|
+
"workYear",
|
|
304
|
+
"degree",
|
|
305
|
+
"funcType",
|
|
306
|
+
"issueDate",
|
|
307
|
+
"url",
|
|
308
|
+
"companyName",
|
|
309
|
+
"companyType",
|
|
310
|
+
"companySize",
|
|
311
|
+
"companyIndustry",
|
|
312
|
+
"companyIntro",
|
|
313
|
+
"companyUrl"
|
|
314
|
+
],
|
|
315
|
+
"type": "js",
|
|
316
|
+
"modulePath": "51job/company.js",
|
|
317
|
+
"sourceFile": "51job/company.js",
|
|
318
|
+
"navigateBefore": false
|
|
319
|
+
},
|
|
320
|
+
{
|
|
321
|
+
"site": "51job",
|
|
322
|
+
"name": "detail",
|
|
323
|
+
"description": "51job 职位详情(按 jobId)",
|
|
324
|
+
"domain": "jobs.51job.com",
|
|
325
|
+
"strategy": "cookie",
|
|
326
|
+
"browser": true,
|
|
327
|
+
"args": [
|
|
328
|
+
{
|
|
329
|
+
"name": "jobId",
|
|
330
|
+
"type": "string",
|
|
331
|
+
"required": true,
|
|
332
|
+
"positional": true,
|
|
333
|
+
"help": "职位 ID(search 返回的 jobId)"
|
|
334
|
+
}
|
|
335
|
+
],
|
|
336
|
+
"columns": [
|
|
337
|
+
"jobId",
|
|
338
|
+
"title",
|
|
339
|
+
"salary",
|
|
340
|
+
"location",
|
|
341
|
+
"workYear",
|
|
342
|
+
"degree",
|
|
343
|
+
"category",
|
|
344
|
+
"address",
|
|
345
|
+
"ageRequirement",
|
|
346
|
+
"description",
|
|
347
|
+
"welfare",
|
|
348
|
+
"company",
|
|
349
|
+
"companyType",
|
|
350
|
+
"companySize",
|
|
351
|
+
"companyIndustry",
|
|
352
|
+
"companyUrl",
|
|
353
|
+
"url"
|
|
354
|
+
],
|
|
355
|
+
"type": "js",
|
|
356
|
+
"modulePath": "51job/detail.js",
|
|
357
|
+
"sourceFile": "51job/detail.js",
|
|
358
|
+
"navigateBefore": false
|
|
359
|
+
},
|
|
360
|
+
{
|
|
361
|
+
"site": "51job",
|
|
362
|
+
"name": "hot",
|
|
363
|
+
"description": "51job 推荐职位(按城市/行业/排序浏览)",
|
|
364
|
+
"domain": "we.51job.com",
|
|
365
|
+
"strategy": "cookie",
|
|
366
|
+
"browser": true,
|
|
367
|
+
"args": [
|
|
368
|
+
{
|
|
369
|
+
"name": "area",
|
|
370
|
+
"type": "string",
|
|
371
|
+
"default": "全国",
|
|
372
|
+
"required": false,
|
|
373
|
+
"help": "城市名或 6 位城市码(默认 \"全国\")"
|
|
374
|
+
},
|
|
375
|
+
{
|
|
376
|
+
"name": "sort",
|
|
377
|
+
"type": "string",
|
|
378
|
+
"default": "综合",
|
|
379
|
+
"required": false,
|
|
380
|
+
"help": "排序:综合 / 最新 / 薪资 / 距离"
|
|
381
|
+
},
|
|
382
|
+
{
|
|
383
|
+
"name": "page",
|
|
384
|
+
"type": "int",
|
|
385
|
+
"default": 1,
|
|
386
|
+
"required": false,
|
|
387
|
+
"help": "页码(1-based)"
|
|
388
|
+
},
|
|
389
|
+
{
|
|
390
|
+
"name": "limit",
|
|
391
|
+
"type": "int",
|
|
392
|
+
"default": 20,
|
|
393
|
+
"required": false,
|
|
394
|
+
"help": "返回条数(1-50)"
|
|
395
|
+
}
|
|
396
|
+
],
|
|
397
|
+
"columns": [
|
|
398
|
+
"rank",
|
|
399
|
+
"jobId",
|
|
400
|
+
"title",
|
|
401
|
+
"salary",
|
|
402
|
+
"salaryMin",
|
|
403
|
+
"salaryMax",
|
|
404
|
+
"city",
|
|
405
|
+
"district",
|
|
406
|
+
"workYear",
|
|
407
|
+
"degree",
|
|
408
|
+
"tags",
|
|
409
|
+
"company",
|
|
410
|
+
"companyFull",
|
|
411
|
+
"companyType",
|
|
412
|
+
"companySize",
|
|
413
|
+
"industry",
|
|
414
|
+
"hr",
|
|
415
|
+
"issueDate",
|
|
416
|
+
"url",
|
|
417
|
+
"companyUrl",
|
|
418
|
+
"encCoId"
|
|
419
|
+
],
|
|
420
|
+
"type": "js",
|
|
421
|
+
"modulePath": "51job/hot.js",
|
|
422
|
+
"sourceFile": "51job/hot.js",
|
|
423
|
+
"navigateBefore": false
|
|
424
|
+
},
|
|
425
|
+
{
|
|
426
|
+
"site": "51job",
|
|
427
|
+
"name": "search",
|
|
428
|
+
"description": "51job 前程无忧关键词职位搜索",
|
|
429
|
+
"domain": "we.51job.com",
|
|
430
|
+
"strategy": "cookie",
|
|
431
|
+
"browser": true,
|
|
432
|
+
"args": [
|
|
433
|
+
{
|
|
434
|
+
"name": "keyword",
|
|
435
|
+
"type": "string",
|
|
436
|
+
"required": true,
|
|
437
|
+
"positional": true,
|
|
438
|
+
"help": "搜索关键词(岗位名 / 技能 / 公司)"
|
|
439
|
+
},
|
|
440
|
+
{
|
|
441
|
+
"name": "area",
|
|
442
|
+
"type": "string",
|
|
443
|
+
"default": "全国",
|
|
444
|
+
"required": false,
|
|
445
|
+
"help": "城市名或 6 位城市码(如 \"杭州\" / \"080200\" / \"全国\")"
|
|
446
|
+
},
|
|
447
|
+
{
|
|
448
|
+
"name": "salary",
|
|
449
|
+
"type": "string",
|
|
450
|
+
"default": "",
|
|
451
|
+
"required": false,
|
|
452
|
+
"help": "薪资区间(如 \"10-15k\" / \"1-1.5万\" / \"20-30k\")"
|
|
453
|
+
},
|
|
454
|
+
{
|
|
455
|
+
"name": "experience",
|
|
456
|
+
"type": "string",
|
|
457
|
+
"default": "",
|
|
458
|
+
"required": false,
|
|
459
|
+
"help": "工作年限(如 \"应届\" / \"1-3年\" / \"3-5年\" / \"5-7年\")"
|
|
460
|
+
},
|
|
461
|
+
{
|
|
462
|
+
"name": "degree",
|
|
463
|
+
"type": "string",
|
|
464
|
+
"default": "",
|
|
465
|
+
"required": false,
|
|
466
|
+
"help": "学历要求(如 \"本科\" / \"大专\" / \"硕士\")"
|
|
467
|
+
},
|
|
468
|
+
{
|
|
469
|
+
"name": "companyType",
|
|
470
|
+
"type": "string",
|
|
471
|
+
"default": "",
|
|
472
|
+
"required": false,
|
|
473
|
+
"help": "公司性质(如 \"外资\" / \"国企\" / \"民营\")"
|
|
474
|
+
},
|
|
475
|
+
{
|
|
476
|
+
"name": "companySize",
|
|
477
|
+
"type": "string",
|
|
478
|
+
"default": "",
|
|
479
|
+
"required": false,
|
|
480
|
+
"help": "公司规模(如 \"50-150\" / \"1000-5000\")"
|
|
481
|
+
},
|
|
482
|
+
{
|
|
483
|
+
"name": "sort",
|
|
484
|
+
"type": "string",
|
|
485
|
+
"default": "综合",
|
|
486
|
+
"required": false,
|
|
487
|
+
"help": "排序:综合 / 最新 / 薪资 / 距离"
|
|
488
|
+
},
|
|
489
|
+
{
|
|
490
|
+
"name": "page",
|
|
491
|
+
"type": "int",
|
|
492
|
+
"default": 1,
|
|
493
|
+
"required": false,
|
|
494
|
+
"help": "页码(1-based)"
|
|
495
|
+
},
|
|
496
|
+
{
|
|
497
|
+
"name": "limit",
|
|
498
|
+
"type": "int",
|
|
499
|
+
"default": 20,
|
|
500
|
+
"required": false,
|
|
501
|
+
"help": "返回条数(1-50)"
|
|
502
|
+
}
|
|
503
|
+
],
|
|
504
|
+
"columns": [
|
|
505
|
+
"rank",
|
|
506
|
+
"jobId",
|
|
507
|
+
"title",
|
|
508
|
+
"salary",
|
|
509
|
+
"salaryMin",
|
|
510
|
+
"salaryMax",
|
|
511
|
+
"city",
|
|
512
|
+
"district",
|
|
513
|
+
"workYear",
|
|
514
|
+
"degree",
|
|
515
|
+
"tags",
|
|
516
|
+
"company",
|
|
517
|
+
"companyFull",
|
|
518
|
+
"companyType",
|
|
519
|
+
"companySize",
|
|
520
|
+
"industry",
|
|
521
|
+
"hr",
|
|
522
|
+
"issueDate",
|
|
523
|
+
"url",
|
|
524
|
+
"companyUrl",
|
|
525
|
+
"encCoId"
|
|
526
|
+
],
|
|
527
|
+
"type": "js",
|
|
528
|
+
"modulePath": "51job/search.js",
|
|
529
|
+
"sourceFile": "51job/search.js",
|
|
530
|
+
"navigateBefore": false
|
|
531
|
+
},
|
|
274
532
|
{
|
|
275
533
|
"site": "amazon",
|
|
276
534
|
"name": "bestsellers",
|
|
@@ -3274,7 +3532,7 @@
|
|
|
3274
3532
|
{
|
|
3275
3533
|
"name": "op",
|
|
3276
3534
|
"type": "str",
|
|
3277
|
-
"default": "
|
|
3535
|
+
"default": "~/Pictures/chatgpt",
|
|
3278
3536
|
"required": false,
|
|
3279
3537
|
"help": "Output directory"
|
|
3280
3538
|
},
|
|
@@ -4150,9 +4408,6 @@
|
|
|
4150
4408
|
"help": "Attach a file (PDF, image, text) with the prompt"
|
|
4151
4409
|
}
|
|
4152
4410
|
],
|
|
4153
|
-
"columns": [
|
|
4154
|
-
"response"
|
|
4155
|
-
],
|
|
4156
4411
|
"timeout": 180,
|
|
4157
4412
|
"type": "js",
|
|
4158
4413
|
"modulePath": "deepseek/ask.js",
|
|
@@ -6865,7 +7120,7 @@
|
|
|
6865
7120
|
{
|
|
6866
7121
|
"name": "op",
|
|
6867
7122
|
"type": "str",
|
|
6868
|
-
"default": "
|
|
7123
|
+
"default": "~/tmp/gemini-images",
|
|
6869
7124
|
"required": false,
|
|
6870
7125
|
"help": "Output directory shorthand"
|
|
6871
7126
|
},
|
|
@@ -8146,7 +8401,7 @@
|
|
|
8146
8401
|
{
|
|
8147
8402
|
"name": "path",
|
|
8148
8403
|
"type": "str",
|
|
8149
|
-
"default": "
|
|
8404
|
+
"default": "~/Downloads/Instagram",
|
|
8150
8405
|
"required": false,
|
|
8151
8406
|
"help": "Download directory"
|
|
8152
8407
|
}
|
|
@@ -12784,6 +13039,43 @@
|
|
|
12784
13039
|
"sourceFile": "pixiv/user.js",
|
|
12785
13040
|
"navigateBefore": "https://www.pixiv.net"
|
|
12786
13041
|
},
|
|
13042
|
+
{
|
|
13043
|
+
"site": "powerchina",
|
|
13044
|
+
"name": "search",
|
|
13045
|
+
"description": "搜索中国电建阳光采购公告",
|
|
13046
|
+
"domain": "bid.powerchina.cn",
|
|
13047
|
+
"strategy": "cookie",
|
|
13048
|
+
"browser": true,
|
|
13049
|
+
"args": [
|
|
13050
|
+
{
|
|
13051
|
+
"name": "query",
|
|
13052
|
+
"type": "str",
|
|
13053
|
+
"required": true,
|
|
13054
|
+
"positional": true,
|
|
13055
|
+
"help": "Search keyword, e.g. \"procurement\""
|
|
13056
|
+
},
|
|
13057
|
+
{
|
|
13058
|
+
"name": "limit",
|
|
13059
|
+
"type": "int",
|
|
13060
|
+
"default": 20,
|
|
13061
|
+
"required": false,
|
|
13062
|
+
"help": "Number of results (max 50)"
|
|
13063
|
+
}
|
|
13064
|
+
],
|
|
13065
|
+
"columns": [
|
|
13066
|
+
"rank",
|
|
13067
|
+
"content_type",
|
|
13068
|
+
"title",
|
|
13069
|
+
"publish_time",
|
|
13070
|
+
"project_code",
|
|
13071
|
+
"budget_or_limit",
|
|
13072
|
+
"url"
|
|
13073
|
+
],
|
|
13074
|
+
"type": "js",
|
|
13075
|
+
"modulePath": "powerchina/search.js",
|
|
13076
|
+
"sourceFile": "powerchina/search.js",
|
|
13077
|
+
"navigateBefore": "https://bid.powerchina.cn"
|
|
13078
|
+
},
|
|
12787
13079
|
{
|
|
12788
13080
|
"site": "producthunt",
|
|
12789
13081
|
"name": "browse",
|
|
@@ -15338,6 +15630,36 @@
|
|
|
15338
15630
|
"sourceFile": "tiktok/user.js",
|
|
15339
15631
|
"navigateBefore": "https://www.tiktok.com"
|
|
15340
15632
|
},
|
|
15633
|
+
{
|
|
15634
|
+
"site": "toutiao",
|
|
15635
|
+
"name": "articles",
|
|
15636
|
+
"description": "获取头条号创作者后台文章列表及数据",
|
|
15637
|
+
"domain": "mp.toutiao.com",
|
|
15638
|
+
"strategy": "cookie",
|
|
15639
|
+
"browser": true,
|
|
15640
|
+
"args": [
|
|
15641
|
+
{
|
|
15642
|
+
"name": "page",
|
|
15643
|
+
"type": "int",
|
|
15644
|
+
"default": 1,
|
|
15645
|
+
"required": false,
|
|
15646
|
+
"help": "页码 (1-4)"
|
|
15647
|
+
}
|
|
15648
|
+
],
|
|
15649
|
+
"columns": [
|
|
15650
|
+
"title",
|
|
15651
|
+
"date",
|
|
15652
|
+
"status",
|
|
15653
|
+
"展现",
|
|
15654
|
+
"阅读",
|
|
15655
|
+
"点赞",
|
|
15656
|
+
"评论"
|
|
15657
|
+
],
|
|
15658
|
+
"type": "js",
|
|
15659
|
+
"modulePath": "toutiao/articles.js",
|
|
15660
|
+
"sourceFile": "toutiao/articles.js",
|
|
15661
|
+
"navigateBefore": "https://mp.toutiao.com"
|
|
15662
|
+
},
|
|
15341
15663
|
{
|
|
15342
15664
|
"site": "twitter",
|
|
15343
15665
|
"name": "accept",
|
|
@@ -15722,7 +16044,9 @@
|
|
|
15722
16044
|
"name",
|
|
15723
16045
|
"text",
|
|
15724
16046
|
"likes",
|
|
15725
|
-
"url"
|
|
16047
|
+
"url",
|
|
16048
|
+
"has_media",
|
|
16049
|
+
"media_urls"
|
|
15726
16050
|
],
|
|
15727
16051
|
"type": "js",
|
|
15728
16052
|
"modulePath": "twitter/likes.js",
|
|
@@ -16087,7 +16411,9 @@
|
|
|
16087
16411
|
"created_at",
|
|
16088
16412
|
"likes",
|
|
16089
16413
|
"views",
|
|
16090
|
-
"url"
|
|
16414
|
+
"url",
|
|
16415
|
+
"has_media",
|
|
16416
|
+
"media_urls"
|
|
16091
16417
|
],
|
|
16092
16418
|
"type": "js",
|
|
16093
16419
|
"modulePath": "twitter/search.js",
|
|
@@ -16123,7 +16449,9 @@
|
|
|
16123
16449
|
"text",
|
|
16124
16450
|
"likes",
|
|
16125
16451
|
"retweets",
|
|
16126
|
-
"url"
|
|
16452
|
+
"url",
|
|
16453
|
+
"has_media",
|
|
16454
|
+
"media_urls"
|
|
16127
16455
|
],
|
|
16128
16456
|
"type": "js",
|
|
16129
16457
|
"modulePath": "twitter/thread.js",
|
|
@@ -16166,7 +16494,9 @@
|
|
|
16166
16494
|
"replies",
|
|
16167
16495
|
"views",
|
|
16168
16496
|
"created_at",
|
|
16169
|
-
"url"
|
|
16497
|
+
"url",
|
|
16498
|
+
"has_media",
|
|
16499
|
+
"media_urls"
|
|
16170
16500
|
],
|
|
16171
16501
|
"type": "js",
|
|
16172
16502
|
"modulePath": "twitter/timeline.js",
|
|
@@ -16232,7 +16562,9 @@
|
|
|
16232
16562
|
"retweets",
|
|
16233
16563
|
"replies",
|
|
16234
16564
|
"views",
|
|
16235
|
-
"url"
|
|
16565
|
+
"url",
|
|
16566
|
+
"has_media",
|
|
16567
|
+
"media_urls"
|
|
16236
16568
|
],
|
|
16237
16569
|
"type": "js",
|
|
16238
16570
|
"modulePath": "twitter/tweets.js",
|
|
@@ -16767,6 +17099,13 @@
|
|
|
16767
17099
|
"default": 3,
|
|
16768
17100
|
"required": false,
|
|
16769
17101
|
"help": "Seconds to wait after page load"
|
|
17102
|
+
},
|
|
17103
|
+
{
|
|
17104
|
+
"name": "stdout",
|
|
17105
|
+
"type": "boolean",
|
|
17106
|
+
"default": false,
|
|
17107
|
+
"required": false,
|
|
17108
|
+
"help": "Print markdown to stdout instead of saving to a file"
|
|
16770
17109
|
}
|
|
16771
17110
|
],
|
|
16772
17111
|
"columns": [
|
|
@@ -17002,6 +17341,56 @@
|
|
|
17002
17341
|
"sourceFile": "weibo/user.js",
|
|
17003
17342
|
"navigateBefore": "https://weibo.com"
|
|
17004
17343
|
},
|
|
17344
|
+
{
|
|
17345
|
+
"site": "weixin",
|
|
17346
|
+
"name": "create-draft",
|
|
17347
|
+
"description": "创建微信公众号图文草稿",
|
|
17348
|
+
"domain": "mp.weixin.qq.com",
|
|
17349
|
+
"strategy": "cookie",
|
|
17350
|
+
"browser": true,
|
|
17351
|
+
"args": [
|
|
17352
|
+
{
|
|
17353
|
+
"name": "title",
|
|
17354
|
+
"type": "str",
|
|
17355
|
+
"required": true,
|
|
17356
|
+
"help": "文章标题 (最长64字)"
|
|
17357
|
+
},
|
|
17358
|
+
{
|
|
17359
|
+
"name": "content",
|
|
17360
|
+
"type": "str",
|
|
17361
|
+
"required": true,
|
|
17362
|
+
"positional": true,
|
|
17363
|
+
"help": "文章正文"
|
|
17364
|
+
},
|
|
17365
|
+
{
|
|
17366
|
+
"name": "author",
|
|
17367
|
+
"type": "str",
|
|
17368
|
+
"required": false,
|
|
17369
|
+
"help": "作者名 (最长8字)"
|
|
17370
|
+
},
|
|
17371
|
+
{
|
|
17372
|
+
"name": "cover-image",
|
|
17373
|
+
"type": "str",
|
|
17374
|
+
"required": false,
|
|
17375
|
+
"help": "封面图片路径 (会先上传到正文再设为封面)"
|
|
17376
|
+
},
|
|
17377
|
+
{
|
|
17378
|
+
"name": "summary",
|
|
17379
|
+
"type": "str",
|
|
17380
|
+
"required": false,
|
|
17381
|
+
"help": "文章摘要"
|
|
17382
|
+
}
|
|
17383
|
+
],
|
|
17384
|
+
"columns": [
|
|
17385
|
+
"status",
|
|
17386
|
+
"detail"
|
|
17387
|
+
],
|
|
17388
|
+
"timeout": 180,
|
|
17389
|
+
"type": "js",
|
|
17390
|
+
"modulePath": "weixin/create-draft.js",
|
|
17391
|
+
"sourceFile": "weixin/create-draft.js",
|
|
17392
|
+
"navigateBefore": false
|
|
17393
|
+
},
|
|
17005
17394
|
{
|
|
17006
17395
|
"site": "weixin",
|
|
17007
17396
|
"name": "download",
|
|
@@ -17044,6 +17433,75 @@
|
|
|
17044
17433
|
"sourceFile": "weixin/download.js",
|
|
17045
17434
|
"navigateBefore": "https://mp.weixin.qq.com"
|
|
17046
17435
|
},
|
|
17436
|
+
{
|
|
17437
|
+
"site": "weixin",
|
|
17438
|
+
"name": "drafts",
|
|
17439
|
+
"description": "列出微信公众号草稿箱",
|
|
17440
|
+
"domain": "mp.weixin.qq.com",
|
|
17441
|
+
"strategy": "cookie",
|
|
17442
|
+
"browser": true,
|
|
17443
|
+
"args": [
|
|
17444
|
+
{
|
|
17445
|
+
"name": "limit",
|
|
17446
|
+
"type": "int",
|
|
17447
|
+
"default": 10,
|
|
17448
|
+
"required": false,
|
|
17449
|
+
"help": "最多显示条数"
|
|
17450
|
+
}
|
|
17451
|
+
],
|
|
17452
|
+
"columns": [
|
|
17453
|
+
"Index",
|
|
17454
|
+
"Title",
|
|
17455
|
+
"Time"
|
|
17456
|
+
],
|
|
17457
|
+
"timeout": 60,
|
|
17458
|
+
"type": "js",
|
|
17459
|
+
"modulePath": "weixin/drafts.js",
|
|
17460
|
+
"sourceFile": "weixin/drafts.js",
|
|
17461
|
+
"navigateBefore": false
|
|
17462
|
+
},
|
|
17463
|
+
{
|
|
17464
|
+
"site": "weread",
|
|
17465
|
+
"name": "ai-outline",
|
|
17466
|
+
"description": "Get AI-generated outline for a book",
|
|
17467
|
+
"domain": "weread.qq.com",
|
|
17468
|
+
"strategy": "cookie",
|
|
17469
|
+
"browser": true,
|
|
17470
|
+
"args": [
|
|
17471
|
+
{
|
|
17472
|
+
"name": "book-id",
|
|
17473
|
+
"type": "str",
|
|
17474
|
+
"required": true,
|
|
17475
|
+
"positional": true,
|
|
17476
|
+
"help": "Book ID (from shelf or search results)"
|
|
17477
|
+
},
|
|
17478
|
+
{
|
|
17479
|
+
"name": "limit",
|
|
17480
|
+
"type": "int",
|
|
17481
|
+
"default": 200,
|
|
17482
|
+
"required": false,
|
|
17483
|
+
"help": "Max outline items to return"
|
|
17484
|
+
},
|
|
17485
|
+
{
|
|
17486
|
+
"name": "depth",
|
|
17487
|
+
"type": "int",
|
|
17488
|
+
"default": 4,
|
|
17489
|
+
"required": false,
|
|
17490
|
+
"help": "Max outline depth (2=topics, 3=key points, 4=details)"
|
|
17491
|
+
},
|
|
17492
|
+
{
|
|
17493
|
+
"name": "raw",
|
|
17494
|
+
"type": "boolean",
|
|
17495
|
+
"default": false,
|
|
17496
|
+
"required": false,
|
|
17497
|
+
"help": "Output structured rows (chapter/idx/level/text) for programmatic use"
|
|
17498
|
+
}
|
|
17499
|
+
],
|
|
17500
|
+
"type": "js",
|
|
17501
|
+
"modulePath": "weread/ai-outline.js",
|
|
17502
|
+
"sourceFile": "weread/ai-outline.js",
|
|
17503
|
+
"navigateBefore": "https://weread.qq.com"
|
|
17504
|
+
},
|
|
17047
17505
|
{
|
|
17048
17506
|
"site": "weread",
|
|
17049
17507
|
"name": "book",
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 51job company jobs + basic info by encCoId.
|
|
3
|
+
*
|
|
4
|
+
* Navigates to `jobs.51job.com/all/co<encCoId>.html`. Each job card is an
|
|
5
|
+
* `<a sensorsdata="…">` whose attribute is a JSON blob with jobId, title,
|
|
6
|
+
* salary, area, year, degree — so parsing is just JSON, not DOM-text fragile.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { cli, Strategy } from '@jackwener/opencli/registry';
|
|
10
|
+
import { CliError } from '@jackwener/opencli/errors';
|
|
11
|
+
import { JOBS_ORIGIN, requirePage, navigateTo, parseCompanyJobCard } from './utils.js';
|
|
12
|
+
|
|
13
|
+
cli({
|
|
14
|
+
site: '51job',
|
|
15
|
+
name: 'company',
|
|
16
|
+
description: '51job 公司简介 + 在招职位(按 encCoId)',
|
|
17
|
+
domain: 'jobs.51job.com',
|
|
18
|
+
strategy: Strategy.COOKIE,
|
|
19
|
+
browser: true,
|
|
20
|
+
navigateBefore: false,
|
|
21
|
+
args: [
|
|
22
|
+
{ name: 'encCoId', type: 'string', required: true, positional: true, help: '加密公司 ID(search 返回的 encCoId)' },
|
|
23
|
+
{ name: 'limit', type: 'int', default: 20, help: '返回职位数(1-50)' },
|
|
24
|
+
],
|
|
25
|
+
columns: [
|
|
26
|
+
'rank', 'jobId', 'title', 'salary', 'city', 'workYear', 'degree',
|
|
27
|
+
'funcType', 'issueDate', 'url',
|
|
28
|
+
'companyName', 'companyType', 'companySize', 'companyIndustry',
|
|
29
|
+
'companyIntro', 'companyUrl',
|
|
30
|
+
],
|
|
31
|
+
func: async (page, kwargs) => {
|
|
32
|
+
requirePage(page);
|
|
33
|
+
const encCoId = String(kwargs.encCoId ?? '').trim();
|
|
34
|
+
if (!encCoId) throw new CliError('INVALID_ARGUMENT', 'encCoId is required');
|
|
35
|
+
if (!/^[A-Za-z0-9_]+$/.test(encCoId)) {
|
|
36
|
+
throw new CliError('INVALID_ARGUMENT', `encCoId must be alphanumeric/underscore, got "${encCoId}"`);
|
|
37
|
+
}
|
|
38
|
+
const limit = Math.max(1, Math.min(Number(kwargs.limit) || 20, 50));
|
|
39
|
+
|
|
40
|
+
const url = `${JOBS_ORIGIN}/all/co${encCoId}.html`;
|
|
41
|
+
await navigateTo(page, url, 2);
|
|
42
|
+
|
|
43
|
+
const script = `(() => {
|
|
44
|
+
const sel = s => document.querySelector(s)?.innerText?.trim() || '';
|
|
45
|
+
const bodyText = (document.body.innerText || '').slice(0, 400);
|
|
46
|
+
if (/公司不存在|页面不存在|账号状态异常/.test(bodyText)) {
|
|
47
|
+
return { error: 'NOT_FOUND', bodyText };
|
|
48
|
+
}
|
|
49
|
+
const companyName = sel('h1') || sel('.cname');
|
|
50
|
+
// Company introduction block
|
|
51
|
+
const introEl = document.querySelector('#companyIntroRef, .c-intro');
|
|
52
|
+
const companyIntro = introEl ? (introEl.innerText || '').trim() : '';
|
|
53
|
+
// Info sidebar (type / size / industry) — labels sit in .com-info dl or .coinfo
|
|
54
|
+
const sidebarText = sel('.ci-content, .company-info, .coinfo, .com-info');
|
|
55
|
+
const links = [...document.querySelectorAll('a[sensorsdata]')]
|
|
56
|
+
.filter(a => /\\/\\d{6,}\\.html/.test(a.href || ''))
|
|
57
|
+
.slice(0, 60)
|
|
58
|
+
.map(a => {
|
|
59
|
+
return {
|
|
60
|
+
href: a.href,
|
|
61
|
+
sensorsdata: a.getAttribute('sensorsdata') || '',
|
|
62
|
+
text: (a.innerText || '').trim(),
|
|
63
|
+
};
|
|
64
|
+
});
|
|
65
|
+
// Company meta is three inline spans under .c-info.ellipsis
|
|
66
|
+
// (title/size/industry) — extract them by position.
|
|
67
|
+
const cInfo = document.querySelector('.c-info.ellipsis');
|
|
68
|
+
const cInfoParts = cInfo
|
|
69
|
+
? [...cInfo.querySelectorAll('span')].map(s => (s.innerText || '').trim()).filter(Boolean)
|
|
70
|
+
: [];
|
|
71
|
+
return {
|
|
72
|
+
companyName,
|
|
73
|
+
companyIntro,
|
|
74
|
+
links,
|
|
75
|
+
cInfoParts,
|
|
76
|
+
sidebarText: sidebarText.slice(0, 400),
|
|
77
|
+
};
|
|
78
|
+
})()`;
|
|
79
|
+
const data = await page.evaluate(script);
|
|
80
|
+
if (data.error === 'NOT_FOUND') {
|
|
81
|
+
throw new CliError('NO_DATA', `Company ${encCoId} not found`);
|
|
82
|
+
}
|
|
83
|
+
if (!data.companyName) {
|
|
84
|
+
throw new CliError('NO_DATA', `Could not parse company page ${encCoId}; layout may have changed`);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
const companyUrl = url;
|
|
88
|
+
const [companyType = '', companySize = '', companyIndustry = ''] = data.cInfoParts || [];
|
|
89
|
+
|
|
90
|
+
const seen = new Set();
|
|
91
|
+
const rows = [];
|
|
92
|
+
for (const link of data.links || []) {
|
|
93
|
+
const job = parseCompanyJobCard(link);
|
|
94
|
+
if (!job) continue;
|
|
95
|
+
if (seen.has(job.jobId)) continue;
|
|
96
|
+
seen.add(job.jobId);
|
|
97
|
+
rows.push({
|
|
98
|
+
rank: rows.length + 1,
|
|
99
|
+
...job,
|
|
100
|
+
companyName: data.companyName,
|
|
101
|
+
companyType,
|
|
102
|
+
companySize,
|
|
103
|
+
companyIndustry,
|
|
104
|
+
companyIntro: data.companyIntro || '',
|
|
105
|
+
companyUrl,
|
|
106
|
+
});
|
|
107
|
+
if (rows.length >= limit) break;
|
|
108
|
+
}
|
|
109
|
+
if (rows.length === 0) {
|
|
110
|
+
// Still return a sentinel row with the company info so caller isn't left with [].
|
|
111
|
+
return [{
|
|
112
|
+
rank: 0,
|
|
113
|
+
jobId: '',
|
|
114
|
+
title: '(no active jobs)',
|
|
115
|
+
salary: '', city: '', workYear: '', degree: '',
|
|
116
|
+
funcType: '', issueDate: '', url: '',
|
|
117
|
+
companyName: data.companyName,
|
|
118
|
+
companyType, companySize, companyIndustry,
|
|
119
|
+
companyIntro: data.companyIntro || '',
|
|
120
|
+
companyUrl,
|
|
121
|
+
}];
|
|
122
|
+
}
|
|
123
|
+
return rows;
|
|
124
|
+
},
|
|
125
|
+
});
|