publishport-opencli 1.8.5-pp.4 → 1.8.5-pp.6
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 +266 -117
- package/clis/_shared/article/login.js +19 -2
- package/clis/_shared/site-auth.js +30 -3
- package/clis/_shared/video-publish-registration.test.js +5 -6
- package/clis/amazon/auth.js +1 -1
- package/clis/bilibili/auth.js +1 -1
- package/clis/bilibili/partitions.js +77 -0
- package/clis/bilibili/topics.js +74 -0
- package/clis/bilibili/upload.js +425 -109
- package/clis/bilibili/upload.test.js +65 -81
- package/clis/bilibili/video-drafts.js +61 -0
- package/clis/boss/auth.js +1 -1
- package/clis/douban/auth.js +1 -1
- package/clis/douyin/auth.js +1 -1
- package/clis/gemini/auth.js +1 -1
- package/clis/github/auth.js +1 -1
- package/clis/jd/auth.js +1 -1
- package/clis/kimi/auth.js +1 -1
- package/clis/medium/article.js +397 -0
- package/clis/medium/login.js +15 -0
- package/clis/medium/whoami.js +31 -0
- package/clis/notebooklm/auth.js +1 -1
- package/clis/tiktok/auth.js +1 -1
- package/clis/twitter/auth.js +1 -1
- package/clis/upwork/auth.js +1 -1
- package/clis/weibo/auth.js +1 -1
- package/clis/weixin/article.js +7 -5
- package/clis/weixin/login.js +15 -0
- package/clis/weixin/whoami.js +9 -2
- package/clis/xiaohongshu/auth.js +1 -1
- package/clis/youtube/auth.js +1 -1
- package/dist/src/external-clis.yaml +0 -7
- package/package.json +3 -2
- package/clis/bilibili/publish.js +0 -253
package/cli-manifest.json
CHANGED
|
@@ -3803,37 +3803,6 @@
|
|
|
3803
3803
|
"sourceFile": "bilibili/article.js",
|
|
3804
3804
|
"navigateBefore": "https://member.bilibili.com"
|
|
3805
3805
|
},
|
|
3806
|
-
{
|
|
3807
|
-
"site": "bilibili",
|
|
3808
|
-
"name": "biliup-login",
|
|
3809
|
-
"description": "B站 biliup 扫码登录,生成投稿用 cookie(一次性)",
|
|
3810
|
-
"access": "write",
|
|
3811
|
-
"strategy": "local",
|
|
3812
|
-
"browser": false,
|
|
3813
|
-
"args": [
|
|
3814
|
-
{
|
|
3815
|
-
"name": "account",
|
|
3816
|
-
"type": "str",
|
|
3817
|
-
"default": "default",
|
|
3818
|
-
"required": false,
|
|
3819
|
-
"help": "biliup 账号名(cookie 存 ~/.publishport/bilibili/<account>.json)"
|
|
3820
|
-
},
|
|
3821
|
-
{
|
|
3822
|
-
"name": "cookie",
|
|
3823
|
-
"type": "str",
|
|
3824
|
-
"default": "",
|
|
3825
|
-
"required": false,
|
|
3826
|
-
"help": "直接指定 cookie 输出路径(覆盖 --account)"
|
|
3827
|
-
}
|
|
3828
|
-
],
|
|
3829
|
-
"columns": [
|
|
3830
|
-
"status",
|
|
3831
|
-
"cookie"
|
|
3832
|
-
],
|
|
3833
|
-
"type": "js",
|
|
3834
|
-
"modulePath": "bilibili/publish.js",
|
|
3835
|
-
"sourceFile": "bilibili/publish.js"
|
|
3836
|
-
},
|
|
3837
3806
|
{
|
|
3838
3807
|
"site": "bilibili",
|
|
3839
3808
|
"name": "categories",
|
|
@@ -4414,78 +4383,27 @@
|
|
|
4414
4383
|
},
|
|
4415
4384
|
{
|
|
4416
4385
|
"site": "bilibili",
|
|
4417
|
-
"name": "
|
|
4386
|
+
"name": "partitions",
|
|
4418
4387
|
"aliases": [
|
|
4419
|
-
"
|
|
4420
|
-
],
|
|
4421
|
-
"description": "投稿视频到B站(经官方 biliup;一条命令完成;需先 biliup-login)",
|
|
4422
|
-
"access": "write",
|
|
4423
|
-
"strategy": "local",
|
|
4424
|
-
"browser": false,
|
|
4425
|
-
"args": [
|
|
4426
|
-
{
|
|
4427
|
-
"name": "video",
|
|
4428
|
-
"type": "str",
|
|
4429
|
-
"required": true,
|
|
4430
|
-
"positional": true,
|
|
4431
|
-
"help": "视频文件路径"
|
|
4432
|
-
},
|
|
4433
|
-
{
|
|
4434
|
-
"name": "title",
|
|
4435
|
-
"type": "str",
|
|
4436
|
-
"required": true,
|
|
4437
|
-
"help": "稿件标题"
|
|
4438
|
-
},
|
|
4439
|
-
{
|
|
4440
|
-
"name": "desc",
|
|
4441
|
-
"type": "str",
|
|
4442
|
-
"default": "",
|
|
4443
|
-
"required": false,
|
|
4444
|
-
"help": "稿件简介"
|
|
4445
|
-
},
|
|
4446
|
-
{
|
|
4447
|
-
"name": "tid",
|
|
4448
|
-
"type": "str",
|
|
4449
|
-
"required": true,
|
|
4450
|
-
"help": "分区 ID(B站 category id,如体育-足球=...)"
|
|
4451
|
-
},
|
|
4452
|
-
{
|
|
4453
|
-
"name": "tags",
|
|
4454
|
-
"type": "str",
|
|
4455
|
-
"default": "",
|
|
4456
|
-
"required": false,
|
|
4457
|
-
"help": "标签,逗号分隔(tag1,tag2)"
|
|
4458
|
-
},
|
|
4459
|
-
{
|
|
4460
|
-
"name": "schedule",
|
|
4461
|
-
"type": "str",
|
|
4462
|
-
"default": "",
|
|
4463
|
-
"required": false,
|
|
4464
|
-
"help": "定时发布时间(ISO8601 或 Unix 秒;不填即立即)"
|
|
4465
|
-
},
|
|
4466
|
-
{
|
|
4467
|
-
"name": "account",
|
|
4468
|
-
"type": "str",
|
|
4469
|
-
"default": "default",
|
|
4470
|
-
"required": false,
|
|
4471
|
-
"help": "biliup 账号名(cookie 存 ~/.publishport/bilibili/<account>.json)"
|
|
4472
|
-
},
|
|
4473
|
-
{
|
|
4474
|
-
"name": "cookie",
|
|
4475
|
-
"type": "str",
|
|
4476
|
-
"default": "",
|
|
4477
|
-
"required": false,
|
|
4478
|
-
"help": "直接指定 biliup cookie 文件路径(覆盖 --account)"
|
|
4479
|
-
}
|
|
4388
|
+
"tid-list"
|
|
4480
4389
|
],
|
|
4390
|
+
"description": "列出 B站视频投稿分区(tid + 名称 + 父分区 + 简介),供 `bilibili upload --tid` 取合法分区 id。禁止臆造 tid。",
|
|
4391
|
+
"access": "read",
|
|
4392
|
+
"domain": "member.bilibili.com",
|
|
4393
|
+
"strategy": "cookie",
|
|
4394
|
+
"browser": true,
|
|
4395
|
+
"args": [],
|
|
4481
4396
|
"columns": [
|
|
4482
|
-
"
|
|
4483
|
-
"
|
|
4484
|
-
"
|
|
4397
|
+
"tid",
|
|
4398
|
+
"name",
|
|
4399
|
+
"parent",
|
|
4400
|
+
"parent_name",
|
|
4401
|
+
"desc"
|
|
4485
4402
|
],
|
|
4486
4403
|
"type": "js",
|
|
4487
|
-
"modulePath": "bilibili/
|
|
4488
|
-
"sourceFile": "bilibili/
|
|
4404
|
+
"modulePath": "bilibili/partitions.js",
|
|
4405
|
+
"sourceFile": "bilibili/partitions.js",
|
|
4406
|
+
"navigateBefore": "https://member.bilibili.com"
|
|
4489
4407
|
},
|
|
4490
4408
|
{
|
|
4491
4409
|
"site": "bilibili",
|
|
@@ -4632,6 +4550,36 @@
|
|
|
4632
4550
|
"sourceFile": "bilibili/summary.js",
|
|
4633
4551
|
"navigateBefore": "https://www.bilibili.com"
|
|
4634
4552
|
},
|
|
4553
|
+
{
|
|
4554
|
+
"site": "bilibili",
|
|
4555
|
+
"name": "topics",
|
|
4556
|
+
"aliases": [
|
|
4557
|
+
"topic-list"
|
|
4558
|
+
],
|
|
4559
|
+
"description": "列出某分区下可参与的投稿话题(topic_id + 名称 + 简介 + 播放量),供 `bilibili upload --topic` 取合法 topic_id。禁止臆造。先用 `bilibili partitions` 取 tid。",
|
|
4560
|
+
"access": "read",
|
|
4561
|
+
"domain": "member.bilibili.com",
|
|
4562
|
+
"strategy": "cookie",
|
|
4563
|
+
"browser": true,
|
|
4564
|
+
"args": [
|
|
4565
|
+
{
|
|
4566
|
+
"name": "tid",
|
|
4567
|
+
"type": "number",
|
|
4568
|
+
"required": true,
|
|
4569
|
+
"help": "分区 id(用 `bilibili partitions` 取)。话题按分区提供。"
|
|
4570
|
+
}
|
|
4571
|
+
],
|
|
4572
|
+
"columns": [
|
|
4573
|
+
"topic_id",
|
|
4574
|
+
"name",
|
|
4575
|
+
"play",
|
|
4576
|
+
"desc"
|
|
4577
|
+
],
|
|
4578
|
+
"type": "js",
|
|
4579
|
+
"modulePath": "bilibili/topics.js",
|
|
4580
|
+
"sourceFile": "bilibili/topics.js",
|
|
4581
|
+
"navigateBefore": "https://member.bilibili.com"
|
|
4582
|
+
},
|
|
4635
4583
|
{
|
|
4636
4584
|
"site": "bilibili",
|
|
4637
4585
|
"name": "unfollow",
|
|
@@ -4663,9 +4611,9 @@
|
|
|
4663
4611
|
{
|
|
4664
4612
|
"site": "bilibili",
|
|
4665
4613
|
"name": "upload",
|
|
4666
|
-
"description": "投稿视频到 B
|
|
4614
|
+
"description": "投稿视频到 B站(在真实浏览器登录态里走 web 投稿:preupload→upos 分块→add/v3)。默认仅 dry-run 校验,加 --execute 才真正上传并提交。",
|
|
4667
4615
|
"access": "write",
|
|
4668
|
-
"domain": "
|
|
4616
|
+
"domain": "member.bilibili.com",
|
|
4669
4617
|
"strategy": "cookie",
|
|
4670
4618
|
"browser": true,
|
|
4671
4619
|
"args": [
|
|
@@ -4674,7 +4622,7 @@
|
|
|
4674
4622
|
"type": "str",
|
|
4675
4623
|
"required": true,
|
|
4676
4624
|
"positional": true,
|
|
4677
|
-
"help": "
|
|
4625
|
+
"help": "视频文件路径"
|
|
4678
4626
|
},
|
|
4679
4627
|
{
|
|
4680
4628
|
"name": "title",
|
|
@@ -4682,24 +4630,30 @@
|
|
|
4682
4630
|
"required": false,
|
|
4683
4631
|
"help": "稿件标题(默认取文件名)"
|
|
4684
4632
|
},
|
|
4633
|
+
{
|
|
4634
|
+
"name": "tid",
|
|
4635
|
+
"type": "number",
|
|
4636
|
+
"required": true,
|
|
4637
|
+
"help": "分区 id(B站 typeid,必填,禁止臆造)。合法值用 `bilibili partitions` 列举后取。"
|
|
4638
|
+
},
|
|
4685
4639
|
{
|
|
4686
4640
|
"name": "tag",
|
|
4687
4641
|
"type": "str",
|
|
4688
4642
|
"required": true,
|
|
4689
4643
|
"help": "标签,逗号分隔(B站要求至少 1 个)"
|
|
4690
4644
|
},
|
|
4691
|
-
{
|
|
4692
|
-
"name": "tid",
|
|
4693
|
-
"type": "number",
|
|
4694
|
-
"required": false,
|
|
4695
|
-
"help": "分区 id(如 201 科学科普;不传用 biliup 默认)"
|
|
4696
|
-
},
|
|
4697
4645
|
{
|
|
4698
4646
|
"name": "desc",
|
|
4699
4647
|
"type": "str",
|
|
4700
4648
|
"required": false,
|
|
4701
4649
|
"help": "简介"
|
|
4702
4650
|
},
|
|
4651
|
+
{
|
|
4652
|
+
"name": "topic",
|
|
4653
|
+
"type": "number",
|
|
4654
|
+
"required": false,
|
|
4655
|
+
"help": "参与话题的 topic_id(重要流量入口)。合法值用 `bilibili topics --tid <tid>` 列举,禁止臆造;mission_id 自动匹配。"
|
|
4656
|
+
},
|
|
4703
4657
|
{
|
|
4704
4658
|
"name": "cover",
|
|
4705
4659
|
"type": "str",
|
|
@@ -4716,43 +4670,61 @@
|
|
|
4716
4670
|
"name": "source",
|
|
4717
4671
|
"type": "str",
|
|
4718
4672
|
"required": false,
|
|
4719
|
-
"help": "转载来源 URL(copyright=2
|
|
4673
|
+
"help": "转载来源 URL(copyright=2 时必填)"
|
|
4720
4674
|
},
|
|
4721
4675
|
{
|
|
4722
|
-
"name": "
|
|
4676
|
+
"name": "dynamic",
|
|
4723
4677
|
"type": "str",
|
|
4724
4678
|
"required": false,
|
|
4725
|
-
"help": "
|
|
4679
|
+
"help": "同步发布的动态文案(可空)"
|
|
4680
|
+
},
|
|
4681
|
+
{
|
|
4682
|
+
"name": "no-reprint",
|
|
4683
|
+
"type": "boolean",
|
|
4684
|
+
"required": false,
|
|
4685
|
+
"help": "禁止转载(默认允许)"
|
|
4726
4686
|
},
|
|
4727
4687
|
{
|
|
4728
4688
|
"name": "dtime",
|
|
4729
4689
|
"type": "number",
|
|
4730
4690
|
"required": false,
|
|
4731
|
-
"help": "定时发布的 10 位 unix
|
|
4691
|
+
"help": "定时发布的 10 位 unix 时间戳(可空=立即)"
|
|
4732
4692
|
},
|
|
4733
4693
|
{
|
|
4734
|
-
"name": "
|
|
4694
|
+
"name": "line",
|
|
4735
4695
|
"type": "str",
|
|
4736
4696
|
"required": false,
|
|
4737
|
-
"help": "
|
|
4697
|
+
"help": "上传线路:bda2/bldsa/qn/ws(默认 bda2)"
|
|
4698
|
+
},
|
|
4699
|
+
{
|
|
4700
|
+
"name": "concurrency",
|
|
4701
|
+
"type": "number",
|
|
4702
|
+
"required": false,
|
|
4703
|
+
"help": "分块并发数(默认 3)"
|
|
4704
|
+
},
|
|
4705
|
+
{
|
|
4706
|
+
"name": "draft",
|
|
4707
|
+
"type": "boolean",
|
|
4708
|
+
"required": false,
|
|
4709
|
+
"help": "存草稿而非直接发布(上传视频后存到创作中心草稿箱,不公开)"
|
|
4738
4710
|
},
|
|
4739
4711
|
{
|
|
4740
4712
|
"name": "execute",
|
|
4741
4713
|
"type": "boolean",
|
|
4742
4714
|
"required": false,
|
|
4743
|
-
"help": "
|
|
4715
|
+
"help": "真正发布投稿;不带(也不带 --draft)则只做 dry-run 校验"
|
|
4744
4716
|
}
|
|
4745
4717
|
],
|
|
4746
4718
|
"columns": [
|
|
4747
4719
|
"status",
|
|
4748
4720
|
"title",
|
|
4749
|
-
"
|
|
4750
|
-
"
|
|
4721
|
+
"bvid",
|
|
4722
|
+
"url"
|
|
4751
4723
|
],
|
|
4752
4724
|
"type": "js",
|
|
4753
4725
|
"modulePath": "bilibili/upload.js",
|
|
4754
4726
|
"sourceFile": "bilibili/upload.js",
|
|
4755
|
-
"navigateBefore": "https://
|
|
4727
|
+
"navigateBefore": "https://member.bilibili.com"
|
|
4756
4728
|
},
|
|
4757
4729
|
{
|
|
4758
4730
|
"site": "bilibili",
|
|
@@ -4836,6 +4808,30 @@
|
|
|
4836
4808
|
"sourceFile": "bilibili/video.js",
|
|
4837
4809
|
"navigateBefore": true
|
|
4838
4810
|
},
|
|
4811
|
+
{
|
|
4812
|
+
"site": "bilibili",
|
|
4813
|
+
"name": "video-drafts",
|
|
4814
|
+
"aliases": [
|
|
4815
|
+
"upload-drafts"
|
|
4816
|
+
],
|
|
4817
|
+
"description": "列出 B站视频投稿草稿箱里的草稿(id + 标题 + 时长 + 修改时间),供确认 `bilibili upload --draft` 结果。(专栏草稿见 `bilibili drafts`)",
|
|
4818
|
+
"access": "read",
|
|
4819
|
+
"domain": "member.bilibili.com",
|
|
4820
|
+
"strategy": "cookie",
|
|
4821
|
+
"browser": true,
|
|
4822
|
+
"args": [],
|
|
4823
|
+
"columns": [
|
|
4824
|
+
"id",
|
|
4825
|
+
"title",
|
|
4826
|
+
"duration",
|
|
4827
|
+
"mtime",
|
|
4828
|
+
"cid"
|
|
4829
|
+
],
|
|
4830
|
+
"type": "js",
|
|
4831
|
+
"modulePath": "bilibili/video-drafts.js",
|
|
4832
|
+
"sourceFile": "bilibili/video-drafts.js",
|
|
4833
|
+
"navigateBefore": "https://member.bilibili.com"
|
|
4834
|
+
},
|
|
4839
4835
|
{
|
|
4840
4836
|
"site": "bilibili",
|
|
4841
4837
|
"name": "whoami",
|
|
@@ -24673,6 +24669,80 @@
|
|
|
24673
24669
|
"modulePath": "mdn/search.js",
|
|
24674
24670
|
"sourceFile": "mdn/search.js"
|
|
24675
24671
|
},
|
|
24672
|
+
{
|
|
24673
|
+
"site": "medium",
|
|
24674
|
+
"name": "article",
|
|
24675
|
+
"description": "发布 Medium 文章(走 medium.com 内部编辑器端点,非官方 API)。默认正式发布;加 --draft 仅存草稿。正文 Markdown,图片自动转存 Medium 图床。可选 --tags/--subtitle/--canonical-url。",
|
|
24676
|
+
"access": "write",
|
|
24677
|
+
"domain": "medium.com",
|
|
24678
|
+
"strategy": "cookie",
|
|
24679
|
+
"browser": true,
|
|
24680
|
+
"args": [
|
|
24681
|
+
{
|
|
24682
|
+
"name": "title",
|
|
24683
|
+
"type": "str",
|
|
24684
|
+
"required": true,
|
|
24685
|
+
"positional": true,
|
|
24686
|
+
"help": "文章标题(作为 Medium 文章标题)"
|
|
24687
|
+
},
|
|
24688
|
+
{
|
|
24689
|
+
"name": "text",
|
|
24690
|
+
"type": "str",
|
|
24691
|
+
"required": false,
|
|
24692
|
+
"positional": true,
|
|
24693
|
+
"help": "文章正文(Markdown)"
|
|
24694
|
+
},
|
|
24695
|
+
{
|
|
24696
|
+
"name": "file",
|
|
24697
|
+
"type": "str",
|
|
24698
|
+
"required": false,
|
|
24699
|
+
"help": "正文文件路径(UTF-8,Markdown)"
|
|
24700
|
+
},
|
|
24701
|
+
{
|
|
24702
|
+
"name": "tags",
|
|
24703
|
+
"type": "str",
|
|
24704
|
+
"required": false,
|
|
24705
|
+
"help": "Medium 话题标签,逗号分隔,最多 5 个(如 \"AI,Programming,Open Source\")"
|
|
24706
|
+
},
|
|
24707
|
+
{
|
|
24708
|
+
"name": "subtitle",
|
|
24709
|
+
"type": "str",
|
|
24710
|
+
"required": false,
|
|
24711
|
+
"help": "副标题(可选,显示在标题下方)"
|
|
24712
|
+
},
|
|
24713
|
+
{
|
|
24714
|
+
"name": "canonical-url",
|
|
24715
|
+
"type": "str",
|
|
24716
|
+
"required": false,
|
|
24717
|
+
"help": "原文规范链接(可选,内容首发别处时填,避免 SEO 重复)"
|
|
24718
|
+
},
|
|
24719
|
+
{
|
|
24720
|
+
"name": "draft",
|
|
24721
|
+
"type": "boolean",
|
|
24722
|
+
"required": false,
|
|
24723
|
+
"help": "仅保存草稿,不正式发布"
|
|
24724
|
+
},
|
|
24725
|
+
{
|
|
24726
|
+
"name": "execute",
|
|
24727
|
+
"type": "boolean",
|
|
24728
|
+
"required": false,
|
|
24729
|
+
"help": "确认执行写操作。不加此参数则拒绝写入。"
|
|
24730
|
+
}
|
|
24731
|
+
],
|
|
24732
|
+
"columns": [
|
|
24733
|
+
"status",
|
|
24734
|
+
"outcome",
|
|
24735
|
+
"message",
|
|
24736
|
+
"target_type",
|
|
24737
|
+
"target",
|
|
24738
|
+
"created_target",
|
|
24739
|
+
"created_url"
|
|
24740
|
+
],
|
|
24741
|
+
"type": "js",
|
|
24742
|
+
"modulePath": "medium/article.js",
|
|
24743
|
+
"sourceFile": "medium/article.js",
|
|
24744
|
+
"navigateBefore": "https://medium.com"
|
|
24745
|
+
},
|
|
24676
24746
|
{
|
|
24677
24747
|
"site": "medium",
|
|
24678
24748
|
"name": "feed",
|
|
@@ -24710,6 +24780,36 @@
|
|
|
24710
24780
|
"sourceFile": "medium/feed.js",
|
|
24711
24781
|
"navigateBefore": "https://medium.com"
|
|
24712
24782
|
},
|
|
24783
|
+
{
|
|
24784
|
+
"site": "medium",
|
|
24785
|
+
"name": "login",
|
|
24786
|
+
"description": "打开 Medium 首页并等待浏览器完成登录(供桌面客户端引导登录)。",
|
|
24787
|
+
"access": "write",
|
|
24788
|
+
"domain": "medium.com",
|
|
24789
|
+
"strategy": "cookie",
|
|
24790
|
+
"browser": true,
|
|
24791
|
+
"args": [
|
|
24792
|
+
{
|
|
24793
|
+
"name": "timeout",
|
|
24794
|
+
"type": "int",
|
|
24795
|
+
"default": 300,
|
|
24796
|
+
"required": false,
|
|
24797
|
+
"help": "等待用户完成登录的最长秒数"
|
|
24798
|
+
}
|
|
24799
|
+
],
|
|
24800
|
+
"columns": [
|
|
24801
|
+
"status",
|
|
24802
|
+
"logged_in",
|
|
24803
|
+
"user_id",
|
|
24804
|
+
"username"
|
|
24805
|
+
],
|
|
24806
|
+
"type": "js",
|
|
24807
|
+
"modulePath": "medium/login.js",
|
|
24808
|
+
"sourceFile": "medium/login.js",
|
|
24809
|
+
"navigateBefore": false,
|
|
24810
|
+
"siteSession": "persistent",
|
|
24811
|
+
"defaultWindowMode": "foreground"
|
|
24812
|
+
},
|
|
24713
24813
|
{
|
|
24714
24814
|
"site": "medium",
|
|
24715
24815
|
"name": "search",
|
|
@@ -24822,6 +24922,25 @@
|
|
|
24822
24922
|
"sourceFile": "medium/user.js",
|
|
24823
24923
|
"navigateBefore": "https://medium.com"
|
|
24824
24924
|
},
|
|
24925
|
+
{
|
|
24926
|
+
"site": "medium",
|
|
24927
|
+
"name": "whoami",
|
|
24928
|
+
"description": "查询当前登录的 Medium 账户信息。",
|
|
24929
|
+
"access": "read",
|
|
24930
|
+
"domain": "medium.com",
|
|
24931
|
+
"strategy": "cookie",
|
|
24932
|
+
"browser": true,
|
|
24933
|
+
"args": [],
|
|
24934
|
+
"columns": [
|
|
24935
|
+
"logged_in",
|
|
24936
|
+
"user_id",
|
|
24937
|
+
"username"
|
|
24938
|
+
],
|
|
24939
|
+
"type": "js",
|
|
24940
|
+
"modulePath": "medium/whoami.js",
|
|
24941
|
+
"sourceFile": "medium/whoami.js",
|
|
24942
|
+
"navigateBefore": "https://medium.com"
|
|
24943
|
+
},
|
|
24825
24944
|
{
|
|
24826
24945
|
"site": "mubu",
|
|
24827
24946
|
"name": "doc",
|
|
@@ -41606,6 +41725,36 @@
|
|
|
41606
41725
|
"sourceFile": "weixin/drafts.js",
|
|
41607
41726
|
"navigateBefore": false
|
|
41608
41727
|
},
|
|
41728
|
+
{
|
|
41729
|
+
"site": "weixin",
|
|
41730
|
+
"name": "login",
|
|
41731
|
+
"description": "打开微信公众平台首页并等待浏览器完成扫码登录(供桌面客户端引导登录)。",
|
|
41732
|
+
"access": "write",
|
|
41733
|
+
"domain": "mp.weixin.qq.com",
|
|
41734
|
+
"strategy": "cookie",
|
|
41735
|
+
"browser": true,
|
|
41736
|
+
"args": [
|
|
41737
|
+
{
|
|
41738
|
+
"name": "timeout",
|
|
41739
|
+
"type": "int",
|
|
41740
|
+
"default": 300,
|
|
41741
|
+
"required": false,
|
|
41742
|
+
"help": "等待用户完成登录的最长秒数"
|
|
41743
|
+
}
|
|
41744
|
+
],
|
|
41745
|
+
"columns": [
|
|
41746
|
+
"status",
|
|
41747
|
+
"logged_in",
|
|
41748
|
+
"user_id",
|
|
41749
|
+
"username"
|
|
41750
|
+
],
|
|
41751
|
+
"type": "js",
|
|
41752
|
+
"modulePath": "weixin/login.js",
|
|
41753
|
+
"sourceFile": "weixin/login.js",
|
|
41754
|
+
"navigateBefore": false,
|
|
41755
|
+
"siteSession": "persistent",
|
|
41756
|
+
"defaultWindowMode": "foreground"
|
|
41757
|
+
},
|
|
41609
41758
|
{
|
|
41610
41759
|
"site": "weixin",
|
|
41611
41760
|
"name": "search",
|
|
@@ -17,6 +17,19 @@ import { checkLogin } from './auth.js';
|
|
|
17
17
|
const DEFAULT_TIMEOUT_SECONDS = 300;
|
|
18
18
|
const POLL_INTERVAL_MS = 3000;
|
|
19
19
|
|
|
20
|
+
// 登录是用户看得见的前台窗口;一旦确认登录就在源头关掉它,别等 daemon 的 idle 超时
|
|
21
|
+
// 才消失(那正是「登录完窗口不自动关闭」的体感)。尽力而为:direct-CDP / 测试 page
|
|
22
|
+
// 没有 closeWindow,关窗失败也绝不能把成功的登录变成报错。
|
|
23
|
+
async function closeLoginWindow(page) {
|
|
24
|
+
if (typeof page?.closeWindow === 'function') {
|
|
25
|
+
try {
|
|
26
|
+
await page.closeWindow();
|
|
27
|
+
} catch {
|
|
28
|
+
/* 窗口可能已不在;忽略 */
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
20
33
|
/**
|
|
21
34
|
* 给走文章共享基建的平台注册一个 `login` 命令。
|
|
22
35
|
*
|
|
@@ -53,12 +66,14 @@ export function registerArticleLogin(config) {
|
|
|
53
66
|
// 已登录直接返回(checkLogin 内部会导航到 home 并探鉴权)。
|
|
54
67
|
const first = await checkLogin(page, config.profile);
|
|
55
68
|
if (first.isAuthenticated) {
|
|
56
|
-
|
|
69
|
+
const result = {
|
|
57
70
|
status: 'already_logged_in',
|
|
58
71
|
logged_in: true,
|
|
59
72
|
user_id: first.userId || '',
|
|
60
73
|
username: first.username || '',
|
|
61
74
|
};
|
|
75
|
+
await closeLoginWindow(page);
|
|
76
|
+
return result;
|
|
62
77
|
}
|
|
63
78
|
|
|
64
79
|
// 未登录:打开登录页,让用户手动完成登录,再轮询登录态。
|
|
@@ -71,12 +86,14 @@ export function registerArticleLogin(config) {
|
|
|
71
86
|
await page.wait(Math.min(POLL_INTERVAL_MS / 1000, Math.max(0.2, remainMs / 1000)));
|
|
72
87
|
const r = await checkLogin(page, config.profile);
|
|
73
88
|
if (r.isAuthenticated) {
|
|
74
|
-
|
|
89
|
+
const result = {
|
|
75
90
|
status: 'login_complete',
|
|
76
91
|
logged_in: true,
|
|
77
92
|
user_id: r.userId || '',
|
|
78
93
|
username: r.username || '',
|
|
79
94
|
};
|
|
95
|
+
await closeLoginWindow(page);
|
|
96
|
+
return result;
|
|
80
97
|
}
|
|
81
98
|
}
|
|
82
99
|
|
|
@@ -20,6 +20,21 @@ async function tryProbe(config, page, phase) {
|
|
|
20
20
|
return normalizeIdentity(config.site, await probe(page, { phase }));
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
+
// Login opens a *foreground* window the user interacts with. Once login is
|
|
24
|
+
// confirmed, close it at the source so it doesn't linger until the daemon's idle
|
|
25
|
+
// timeout — that lingering window is the "登录完窗口不自动关闭" complaint.
|
|
26
|
+
// Best-effort: direct-CDP pages / tests have no closeWindow, and a failed close
|
|
27
|
+
// must never turn a successful login into an error.
|
|
28
|
+
async function closeLoginWindow(page) {
|
|
29
|
+
if (typeof page?.closeWindow === 'function') {
|
|
30
|
+
try {
|
|
31
|
+
await page.closeWindow();
|
|
32
|
+
} catch {
|
|
33
|
+
/* window may already be gone; ignore */
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
23
38
|
function authHint(config) {
|
|
24
39
|
return `Run \`opencli ${config.site} login\` to open the login page, then retry.`;
|
|
25
40
|
}
|
|
@@ -87,9 +102,15 @@ export function registerSiteAuthCommands(config) {
|
|
|
87
102
|
columns: ['status', ...commandColumns(config)],
|
|
88
103
|
func: async (page, kwargs) => {
|
|
89
104
|
try {
|
|
90
|
-
|
|
105
|
+
const result = { status: 'already_logged_in', ...await tryProbe(config, page, 'identity') };
|
|
106
|
+
await closeLoginWindow(page);
|
|
107
|
+
return result;
|
|
91
108
|
} catch (error) {
|
|
92
|
-
if (!isAuthRequired(error))
|
|
109
|
+
if (!isAuthRequired(error)) {
|
|
110
|
+
// 非「未登录」的真错误:也把登录窗收掉,别让它杵在那(见 closeLoginWindow 注释)。
|
|
111
|
+
await closeLoginWindow(page);
|
|
112
|
+
throw error;
|
|
113
|
+
}
|
|
93
114
|
}
|
|
94
115
|
|
|
95
116
|
await page.goto(config.loginUrl);
|
|
@@ -101,13 +122,19 @@ export function registerSiteAuthCommands(config) {
|
|
|
101
122
|
await page.wait(Math.min(POLL_INTERVAL_MS / 1000, Math.max(0.2, (deadline - Date.now()) / 1000)));
|
|
102
123
|
try {
|
|
103
124
|
const identity = await tryProbe(config, page, 'poll');
|
|
125
|
+
await closeLoginWindow(page);
|
|
104
126
|
return { status: 'login_complete', ...identity };
|
|
105
127
|
} catch (error) {
|
|
106
|
-
if (!isAuthRequired(error))
|
|
128
|
+
if (!isAuthRequired(error)) {
|
|
129
|
+
await closeLoginWindow(page);
|
|
130
|
+
throw error;
|
|
131
|
+
}
|
|
107
132
|
lastAuthMessage = getErrorMessage(error);
|
|
108
133
|
}
|
|
109
134
|
}
|
|
110
135
|
|
|
136
|
+
// 超时(用户没在时限内完成):同样关掉登录窗,避免失败后窗口残留。
|
|
137
|
+
await closeLoginWindow(page);
|
|
111
138
|
throw new TimeoutError(
|
|
112
139
|
`${config.site} login`,
|
|
113
140
|
timeoutSeconds,
|
|
@@ -5,7 +5,7 @@ import '../kuaishou/publish.js';
|
|
|
5
5
|
import '../tiktok/publish.js';
|
|
6
6
|
import '../youtube/publish.js';
|
|
7
7
|
import '../baijiahao/publish.js';
|
|
8
|
-
import '../bilibili/
|
|
8
|
+
import '../bilibili/upload.js';
|
|
9
9
|
|
|
10
10
|
function find(site, name) {
|
|
11
11
|
return [...getRegistry().values()].find((c) => c.site === site && c.name === name);
|
|
@@ -40,11 +40,10 @@ describe('video publish adapters registration', () => {
|
|
|
40
40
|
expect(cmd.args.map((a) => a.name)).toEqual(expect.arrayContaining(['video', 'title', 'schedule']));
|
|
41
41
|
});
|
|
42
42
|
|
|
43
|
-
it('registers bilibili
|
|
44
|
-
const cmd = find('bilibili', '
|
|
43
|
+
it('registers bilibili upload (browser-native web 投稿)', () => {
|
|
44
|
+
const cmd = find('bilibili', 'upload');
|
|
45
45
|
expect(cmd).toBeDefined();
|
|
46
|
-
expect(cmd.browser).toBe(
|
|
47
|
-
expect(cmd.args.map((a) => a.name)).toEqual(expect.arrayContaining(['
|
|
48
|
-
expect(find('bilibili', 'biliup-login')).toBeDefined();
|
|
46
|
+
expect(cmd.browser).toBe(true);
|
|
47
|
+
expect(cmd.args.map((a) => a.name)).toEqual(expect.arrayContaining(['file', 'title', 'tid', 'tag']));
|
|
49
48
|
});
|
|
50
49
|
});
|
package/clis/amazon/auth.js
CHANGED
|
@@ -3,7 +3,7 @@ import { registerSiteAuthCommands } from '../_shared/site-auth.js';
|
|
|
3
3
|
|
|
4
4
|
async function hasAmazonSessionCookies(page) {
|
|
5
5
|
const cookies = await page.getCookies({ url: 'https://www.amazon.com' });
|
|
6
|
-
const names = new Set(cookies.map(c => c.name));
|
|
6
|
+
const names = new Set(cookies.filter(c => c.value).map(c => c.name));
|
|
7
7
|
return names.has('at-main') || names.has('x-main');
|
|
8
8
|
}
|
|
9
9
|
|
package/clis/bilibili/auth.js
CHANGED
|
@@ -4,7 +4,7 @@ import { apiGet, getSelfUid } from './utils.js';
|
|
|
4
4
|
|
|
5
5
|
async function hasBilibiliSessionCookies(page) {
|
|
6
6
|
const cookies = await page.getCookies({ url: 'https://www.bilibili.com' });
|
|
7
|
-
const names = new Set(cookies.map(cookie => cookie.name));
|
|
7
|
+
const names = new Set(cookies.filter(cookie => cookie.value).map(cookie => cookie.name));
|
|
8
8
|
return names.has('SESSDATA') && names.has('DedeUserID');
|
|
9
9
|
}
|
|
10
10
|
|