@jackwener/opencli 0.9.8 → 1.0.1

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.
Files changed (165) hide show
  1. package/CDP.md +1 -1
  2. package/CDP.zh-CN.md +1 -1
  3. package/CLI-ELECTRON.md +2 -2
  4. package/CLI-EXPLORER.md +4 -4
  5. package/README.md +35 -58
  6. package/README.zh-CN.md +36 -60
  7. package/SKILL.md +10 -8
  8. package/TESTING.md +7 -7
  9. package/dist/browser/daemon-client.d.ts +37 -0
  10. package/dist/browser/daemon-client.js +82 -0
  11. package/dist/browser/discover.d.ts +11 -34
  12. package/dist/browser/discover.js +15 -205
  13. package/dist/browser/errors.d.ts +6 -20
  14. package/dist/browser/errors.js +24 -63
  15. package/dist/browser/index.d.ts +2 -12
  16. package/dist/browser/index.js +2 -12
  17. package/dist/browser/mcp.d.ts +9 -21
  18. package/dist/browser/mcp.js +70 -285
  19. package/dist/browser/page.d.ts +36 -7
  20. package/dist/browser/page.js +212 -81
  21. package/dist/browser.test.js +10 -231
  22. package/dist/cli-manifest.json +561 -14
  23. package/dist/clis/apple-podcasts/episodes.d.ts +1 -0
  24. package/dist/clis/apple-podcasts/episodes.js +28 -0
  25. package/dist/clis/apple-podcasts/search.d.ts +1 -0
  26. package/dist/clis/apple-podcasts/search.js +29 -0
  27. package/dist/clis/apple-podcasts/top.d.ts +1 -0
  28. package/dist/clis/apple-podcasts/top.js +34 -0
  29. package/dist/clis/apple-podcasts/utils.d.ts +11 -0
  30. package/dist/clis/apple-podcasts/utils.js +30 -0
  31. package/dist/clis/apple-podcasts/utils.test.d.ts +1 -0
  32. package/dist/clis/apple-podcasts/utils.test.js +57 -0
  33. package/dist/clis/chatwise/history.js +18 -1
  34. package/dist/clis/discord-app/channels.js +33 -21
  35. package/dist/clis/neteasemusic/like.d.ts +1 -0
  36. package/dist/clis/neteasemusic/like.js +25 -0
  37. package/dist/clis/neteasemusic/lyrics.d.ts +1 -0
  38. package/dist/clis/neteasemusic/lyrics.js +47 -0
  39. package/dist/clis/neteasemusic/next.d.ts +1 -0
  40. package/dist/clis/neteasemusic/next.js +26 -0
  41. package/dist/clis/neteasemusic/play.d.ts +1 -0
  42. package/dist/clis/neteasemusic/play.js +26 -0
  43. package/dist/clis/neteasemusic/playing.d.ts +1 -0
  44. package/dist/clis/neteasemusic/playing.js +59 -0
  45. package/dist/clis/neteasemusic/playlist.d.ts +1 -0
  46. package/dist/clis/neteasemusic/playlist.js +46 -0
  47. package/dist/clis/neteasemusic/prev.d.ts +1 -0
  48. package/dist/clis/neteasemusic/prev.js +25 -0
  49. package/dist/clis/neteasemusic/search.d.ts +1 -0
  50. package/dist/clis/neteasemusic/search.js +52 -0
  51. package/dist/clis/neteasemusic/status.d.ts +1 -0
  52. package/dist/clis/neteasemusic/status.js +16 -0
  53. package/dist/clis/neteasemusic/volume.d.ts +1 -0
  54. package/dist/clis/neteasemusic/volume.js +54 -0
  55. package/dist/clis/twitter/accept.d.ts +1 -0
  56. package/dist/clis/twitter/accept.js +202 -0
  57. package/dist/clis/twitter/followers.js +30 -22
  58. package/dist/clis/twitter/following.js +19 -14
  59. package/dist/clis/twitter/notifications.js +29 -22
  60. package/dist/clis/twitter/reply-dm.d.ts +1 -0
  61. package/dist/clis/twitter/reply-dm.js +181 -0
  62. package/dist/clis/twitter/search.js +50 -12
  63. package/dist/clis/weread/book.d.ts +1 -0
  64. package/dist/clis/weread/book.js +26 -0
  65. package/dist/clis/weread/highlights.d.ts +1 -0
  66. package/dist/clis/weread/highlights.js +23 -0
  67. package/dist/clis/weread/notebooks.d.ts +1 -0
  68. package/dist/clis/weread/notebooks.js +21 -0
  69. package/dist/clis/weread/notes.d.ts +1 -0
  70. package/dist/clis/weread/notes.js +29 -0
  71. package/dist/clis/weread/ranking.d.ts +1 -0
  72. package/dist/clis/weread/ranking.js +28 -0
  73. package/dist/clis/weread/search.d.ts +1 -0
  74. package/dist/clis/weread/search.js +25 -0
  75. package/dist/clis/weread/shelf.d.ts +1 -0
  76. package/dist/clis/weread/shelf.js +24 -0
  77. package/dist/clis/weread/utils.d.ts +20 -0
  78. package/dist/clis/weread/utils.js +72 -0
  79. package/dist/clis/weread/utils.test.d.ts +1 -0
  80. package/dist/clis/weread/utils.test.js +85 -0
  81. package/dist/daemon.d.ts +13 -0
  82. package/dist/daemon.js +187 -0
  83. package/dist/doctor.d.ts +10 -65
  84. package/dist/doctor.js +49 -602
  85. package/dist/doctor.test.js +30 -170
  86. package/dist/main.js +12 -41
  87. package/dist/pipeline/executor.test.js +1 -0
  88. package/dist/pipeline/steps/browser.js +2 -2
  89. package/dist/pipeline/steps/intercept.js +1 -2
  90. package/dist/runtime.d.ts +1 -4
  91. package/dist/runtime.js +1 -4
  92. package/dist/setup.d.ts +6 -0
  93. package/dist/setup.js +46 -160
  94. package/dist/types.d.ts +6 -0
  95. package/extension/dist/background.js +484 -0
  96. package/extension/icons/icon-128.png +0 -0
  97. package/extension/icons/icon-16.png +0 -0
  98. package/extension/icons/icon-32.png +0 -0
  99. package/extension/icons/icon-48.png +0 -0
  100. package/extension/manifest.json +31 -0
  101. package/extension/package.json +16 -0
  102. package/extension/src/background.ts +370 -0
  103. package/extension/src/cdp.ts +125 -0
  104. package/extension/src/protocol.ts +57 -0
  105. package/extension/store-assets/screenshot-1280x800.png +0 -0
  106. package/extension/tsconfig.json +15 -0
  107. package/extension/vite.config.ts +18 -0
  108. package/package.json +5 -5
  109. package/src/browser/daemon-client.ts +113 -0
  110. package/src/browser/discover.ts +18 -232
  111. package/src/browser/errors.ts +30 -100
  112. package/src/browser/index.ts +2 -13
  113. package/src/browser/mcp.ts +81 -282
  114. package/src/browser/page.ts +223 -83
  115. package/src/browser.test.ts +9 -239
  116. package/src/clis/apple-podcasts/episodes.ts +28 -0
  117. package/src/clis/apple-podcasts/search.ts +29 -0
  118. package/src/clis/apple-podcasts/top.ts +34 -0
  119. package/src/clis/apple-podcasts/utils.test.ts +72 -0
  120. package/src/clis/apple-podcasts/utils.ts +37 -0
  121. package/src/clis/chatgpt/README.md +1 -1
  122. package/src/clis/chatgpt/README.zh-CN.md +1 -1
  123. package/src/clis/chatwise/history.ts +15 -1
  124. package/src/clis/discord-app/channels.ts +33 -21
  125. package/src/clis/neteasemusic/README.md +31 -0
  126. package/src/clis/neteasemusic/README.zh-CN.md +31 -0
  127. package/src/clis/neteasemusic/like.ts +28 -0
  128. package/src/clis/neteasemusic/lyrics.ts +53 -0
  129. package/src/clis/neteasemusic/next.ts +30 -0
  130. package/src/clis/neteasemusic/play.ts +30 -0
  131. package/src/clis/neteasemusic/playing.ts +62 -0
  132. package/src/clis/neteasemusic/playlist.ts +51 -0
  133. package/src/clis/neteasemusic/prev.ts +29 -0
  134. package/src/clis/neteasemusic/search.ts +58 -0
  135. package/src/clis/neteasemusic/status.ts +18 -0
  136. package/src/clis/neteasemusic/volume.ts +61 -0
  137. package/src/clis/twitter/accept.ts +213 -0
  138. package/src/clis/twitter/followers.ts +36 -29
  139. package/src/clis/twitter/following.ts +25 -20
  140. package/src/clis/twitter/notifications.ts +34 -27
  141. package/src/clis/twitter/reply-dm.ts +193 -0
  142. package/src/clis/twitter/search.ts +53 -13
  143. package/src/clis/weread/book.ts +28 -0
  144. package/src/clis/weread/highlights.ts +25 -0
  145. package/src/clis/weread/notebooks.ts +23 -0
  146. package/src/clis/weread/notes.ts +31 -0
  147. package/src/clis/weread/ranking.ts +29 -0
  148. package/src/clis/weread/search.ts +26 -0
  149. package/src/clis/weread/shelf.ts +26 -0
  150. package/src/clis/weread/utils.test.ts +104 -0
  151. package/src/clis/weread/utils.ts +74 -0
  152. package/src/daemon.ts +217 -0
  153. package/src/doctor.test.ts +32 -193
  154. package/src/doctor.ts +58 -669
  155. package/src/main.ts +11 -34
  156. package/src/pipeline/executor.test.ts +1 -0
  157. package/src/pipeline/steps/browser.ts +2 -2
  158. package/src/pipeline/steps/intercept.ts +1 -2
  159. package/src/runtime.ts +2 -6
  160. package/src/setup.ts +47 -183
  161. package/src/types.ts +1 -0
  162. package/tests/e2e/public-commands.test.ts +68 -1
  163. package/dist/clis/grok/debug.d.ts +0 -1
  164. package/dist/clis/grok/debug.js +0 -45
  165. package/src/clis/grok/debug.ts +0 -49
@@ -137,6 +137,119 @@
137
137
  "domain": "localhost",
138
138
  "columns": []
139
139
  },
140
+ {
141
+ "site": "apple-podcasts",
142
+ "name": "episodes",
143
+ "description": "List recent episodes of an Apple Podcast (use ID from search)",
144
+ "strategy": "public",
145
+ "browser": false,
146
+ "args": [
147
+ {
148
+ "name": "id",
149
+ "type": "str",
150
+ "required": true,
151
+ "positional": true,
152
+ "help": "Podcast ID (collectionId from search output)"
153
+ },
154
+ {
155
+ "name": "limit",
156
+ "type": "int",
157
+ "default": 15,
158
+ "required": false,
159
+ "help": "Max episodes to show"
160
+ }
161
+ ],
162
+ "type": "ts",
163
+ "modulePath": "apple-podcasts/episodes.js",
164
+ "columns": [
165
+ "title",
166
+ "duration",
167
+ "date"
168
+ ]
169
+ },
170
+ {
171
+ "site": "apple-podcasts",
172
+ "name": "search",
173
+ "description": "Search Apple Podcasts",
174
+ "strategy": "public",
175
+ "browser": false,
176
+ "args": [
177
+ {
178
+ "name": "keyword",
179
+ "type": "str",
180
+ "required": true,
181
+ "positional": true,
182
+ "help": "Search keyword"
183
+ },
184
+ {
185
+ "name": "limit",
186
+ "type": "int",
187
+ "default": 10,
188
+ "required": false,
189
+ "help": "Max results"
190
+ }
191
+ ],
192
+ "type": "ts",
193
+ "modulePath": "apple-podcasts/search.js",
194
+ "columns": [
195
+ "id",
196
+ "title",
197
+ "author",
198
+ "episodes",
199
+ "genre"
200
+ ]
201
+ },
202
+ {
203
+ "site": "apple-podcasts",
204
+ "name": "top",
205
+ "description": "Top podcasts chart on Apple Podcasts",
206
+ "strategy": "public",
207
+ "browser": false,
208
+ "args": [
209
+ {
210
+ "name": "limit",
211
+ "type": "int",
212
+ "default": 20,
213
+ "required": false,
214
+ "help": "Number of podcasts (max 100)"
215
+ },
216
+ {
217
+ "name": "country",
218
+ "type": "str",
219
+ "default": "us",
220
+ "required": false,
221
+ "help": "Country code (e.g. us, cn, gb, jp)"
222
+ }
223
+ ],
224
+ "type": "ts",
225
+ "modulePath": "apple-podcasts/top.js",
226
+ "columns": [
227
+ "rank",
228
+ "title",
229
+ "author",
230
+ "id"
231
+ ]
232
+ },
233
+ {
234
+ "site": "apple-podcasts",
235
+ "name": "utils",
236
+ "description": "",
237
+ "strategy": "cookie",
238
+ "browser": true,
239
+ "args": [],
240
+ "type": "ts",
241
+ "modulePath": "apple-podcasts/utils.js"
242
+ },
243
+ {
244
+ "site": "apple-podcasts",
245
+ "name": "utils.test",
246
+ "description": "",
247
+ "strategy": "cookie",
248
+ "browser": true,
249
+ "args": [],
250
+ "type": "ts",
251
+ "modulePath": "apple-podcasts/utils.test.js"
252
+ },
140
253
  {
141
254
  "site": "barchart",
142
255
  "name": "flow",
@@ -1956,20 +2069,6 @@
1956
2069
  "response"
1957
2070
  ]
1958
2071
  },
1959
- {
1960
- "site": "grok",
1961
- "name": "debug",
1962
- "description": "Debug grok page structure",
1963
- "strategy": "cookie",
1964
- "browser": true,
1965
- "args": [],
1966
- "type": "ts",
1967
- "modulePath": "grok/debug.js",
1968
- "domain": "grok.com",
1969
- "columns": [
1970
- "data"
1971
- ]
1972
- },
1973
2072
  {
1974
2073
  "site": "hackernews",
1975
2074
  "name": "top",
@@ -2514,6 +2613,173 @@
2514
2613
  ],
2515
2614
  "type": "yaml"
2516
2615
  },
2616
+ {
2617
+ "site": "neteasemusic",
2618
+ "name": "like",
2619
+ "description": "Like/unlike the currently playing song",
2620
+ "strategy": "ui",
2621
+ "browser": true,
2622
+ "args": [],
2623
+ "type": "ts",
2624
+ "modulePath": "neteasemusic/like.js",
2625
+ "domain": "localhost",
2626
+ "columns": [
2627
+ "Status"
2628
+ ]
2629
+ },
2630
+ {
2631
+ "site": "neteasemusic",
2632
+ "name": "lyrics",
2633
+ "description": "Get the lyrics of the currently playing song",
2634
+ "strategy": "ui",
2635
+ "browser": true,
2636
+ "args": [],
2637
+ "type": "ts",
2638
+ "modulePath": "neteasemusic/lyrics.js",
2639
+ "domain": "localhost",
2640
+ "columns": [
2641
+ "Line"
2642
+ ]
2643
+ },
2644
+ {
2645
+ "site": "neteasemusic",
2646
+ "name": "next",
2647
+ "description": "Skip to the next song",
2648
+ "strategy": "ui",
2649
+ "browser": true,
2650
+ "args": [],
2651
+ "type": "ts",
2652
+ "modulePath": "neteasemusic/next.js",
2653
+ "domain": "localhost",
2654
+ "columns": [
2655
+ "Status"
2656
+ ]
2657
+ },
2658
+ {
2659
+ "site": "neteasemusic",
2660
+ "name": "play",
2661
+ "description": "Toggle play/pause for the current song",
2662
+ "strategy": "ui",
2663
+ "browser": true,
2664
+ "args": [],
2665
+ "type": "ts",
2666
+ "modulePath": "neteasemusic/play.js",
2667
+ "domain": "localhost",
2668
+ "columns": [
2669
+ "Status"
2670
+ ]
2671
+ },
2672
+ {
2673
+ "site": "neteasemusic",
2674
+ "name": "playing",
2675
+ "description": "Get the currently playing song info",
2676
+ "strategy": "ui",
2677
+ "browser": true,
2678
+ "args": [],
2679
+ "type": "ts",
2680
+ "modulePath": "neteasemusic/playing.js",
2681
+ "domain": "localhost",
2682
+ "columns": [
2683
+ "Title",
2684
+ "Artist",
2685
+ "Album",
2686
+ "Duration",
2687
+ "Progress"
2688
+ ]
2689
+ },
2690
+ {
2691
+ "site": "neteasemusic",
2692
+ "name": "playlist",
2693
+ "description": "Show the current playback queue / playlist",
2694
+ "strategy": "ui",
2695
+ "browser": true,
2696
+ "args": [],
2697
+ "type": "ts",
2698
+ "modulePath": "neteasemusic/playlist.js",
2699
+ "domain": "localhost",
2700
+ "columns": [
2701
+ "Index",
2702
+ "Title",
2703
+ "Artist"
2704
+ ]
2705
+ },
2706
+ {
2707
+ "site": "neteasemusic",
2708
+ "name": "prev",
2709
+ "description": "Go back to the previous song",
2710
+ "strategy": "ui",
2711
+ "browser": true,
2712
+ "args": [],
2713
+ "type": "ts",
2714
+ "modulePath": "neteasemusic/prev.js",
2715
+ "domain": "localhost",
2716
+ "columns": [
2717
+ "Status"
2718
+ ]
2719
+ },
2720
+ {
2721
+ "site": "neteasemusic",
2722
+ "name": "search",
2723
+ "description": "Search for songs, artists, albums, or playlists",
2724
+ "strategy": "ui",
2725
+ "browser": true,
2726
+ "args": [
2727
+ {
2728
+ "name": "query",
2729
+ "type": "str",
2730
+ "required": true,
2731
+ "positional": true,
2732
+ "help": "Search query"
2733
+ }
2734
+ ],
2735
+ "type": "ts",
2736
+ "modulePath": "neteasemusic/search.js",
2737
+ "domain": "localhost",
2738
+ "columns": [
2739
+ "Index",
2740
+ "Title",
2741
+ "Artist"
2742
+ ]
2743
+ },
2744
+ {
2745
+ "site": "neteasemusic",
2746
+ "name": "status",
2747
+ "description": "Check CDP connection to NeteaseMusic Desktop",
2748
+ "strategy": "ui",
2749
+ "browser": true,
2750
+ "args": [],
2751
+ "type": "ts",
2752
+ "modulePath": "neteasemusic/status.js",
2753
+ "domain": "localhost",
2754
+ "columns": [
2755
+ "Status",
2756
+ "Url",
2757
+ "Title"
2758
+ ]
2759
+ },
2760
+ {
2761
+ "site": "neteasemusic",
2762
+ "name": "volume",
2763
+ "description": "Get or set the volume level (0-100)",
2764
+ "strategy": "ui",
2765
+ "browser": true,
2766
+ "args": [
2767
+ {
2768
+ "name": "level",
2769
+ "type": "str",
2770
+ "required": false,
2771
+ "positional": true,
2772
+ "help": "Volume level 0-100 (omit to read current)"
2773
+ }
2774
+ ],
2775
+ "type": "ts",
2776
+ "modulePath": "neteasemusic/volume.js",
2777
+ "domain": "localhost",
2778
+ "columns": [
2779
+ "Status",
2780
+ "Volume"
2781
+ ]
2782
+ },
2517
2783
  {
2518
2784
  "site": "notion",
2519
2785
  "name": "export",
@@ -3378,6 +3644,37 @@
3378
3644
  "url"
3379
3645
  ]
3380
3646
  },
3647
+ {
3648
+ "site": "twitter",
3649
+ "name": "accept",
3650
+ "description": "Auto-accept DM requests containing specific keywords",
3651
+ "strategy": "ui",
3652
+ "browser": true,
3653
+ "args": [
3654
+ {
3655
+ "name": "keyword",
3656
+ "type": "string",
3657
+ "required": true,
3658
+ "help": "Keywords to match (comma-separated for OR, e.g. "
3659
+ },
3660
+ {
3661
+ "name": "max",
3662
+ "type": "int",
3663
+ "default": 20,
3664
+ "required": false,
3665
+ "help": "Maximum number of requests to accept (default: 20)"
3666
+ }
3667
+ ],
3668
+ "type": "ts",
3669
+ "modulePath": "twitter/accept.js",
3670
+ "domain": "x.com",
3671
+ "columns": [
3672
+ "index",
3673
+ "status",
3674
+ "user",
3675
+ "message"
3676
+ ]
3677
+ },
3381
3678
  {
3382
3679
  "site": "twitter",
3383
3680
  "name": "article",
@@ -3699,6 +3996,37 @@
3699
3996
  "created_at"
3700
3997
  ]
3701
3998
  },
3999
+ {
4000
+ "site": "twitter",
4001
+ "name": "reply-dm",
4002
+ "description": "Send a message to recent DM conversations",
4003
+ "strategy": "ui",
4004
+ "browser": true,
4005
+ "args": [
4006
+ {
4007
+ "name": "text",
4008
+ "type": "string",
4009
+ "required": true,
4010
+ "help": "Message text to send (e.g. "
4011
+ },
4012
+ {
4013
+ "name": "max",
4014
+ "type": "int",
4015
+ "default": 20,
4016
+ "required": false,
4017
+ "help": "Maximum number of conversations to reply to (default: 20)"
4018
+ }
4019
+ ],
4020
+ "type": "ts",
4021
+ "modulePath": "twitter/reply-dm.js",
4022
+ "domain": "x.com",
4023
+ "columns": [
4024
+ "index",
4025
+ "status",
4026
+ "user",
4027
+ "message"
4028
+ ]
4029
+ },
3702
4030
  {
3703
4031
  "site": "twitter",
3704
4032
  "name": "reply",
@@ -4217,6 +4545,225 @@
4217
4545
  "url"
4218
4546
  ]
4219
4547
  },
4548
+ {
4549
+ "site": "weread",
4550
+ "name": "book",
4551
+ "description": "View book details on WeRead",
4552
+ "strategy": "cookie",
4553
+ "browser": true,
4554
+ "args": [
4555
+ {
4556
+ "name": "bookId",
4557
+ "type": "str",
4558
+ "required": true,
4559
+ "positional": true,
4560
+ "help": "Book ID (numeric, from search or shelf results)"
4561
+ }
4562
+ ],
4563
+ "type": "ts",
4564
+ "modulePath": "weread/book.js",
4565
+ "domain": "weread.qq.com",
4566
+ "columns": [
4567
+ "title",
4568
+ "author",
4569
+ "publisher",
4570
+ "intro",
4571
+ "category",
4572
+ "rating"
4573
+ ]
4574
+ },
4575
+ {
4576
+ "site": "weread",
4577
+ "name": "highlights",
4578
+ "description": "List your highlights (underlines) in a book",
4579
+ "strategy": "cookie",
4580
+ "browser": true,
4581
+ "args": [
4582
+ {
4583
+ "name": "bookId",
4584
+ "type": "str",
4585
+ "required": true,
4586
+ "positional": true,
4587
+ "help": "Book ID (from shelf or search results)"
4588
+ },
4589
+ {
4590
+ "name": "limit",
4591
+ "type": "int",
4592
+ "default": 20,
4593
+ "required": false,
4594
+ "help": "Max results"
4595
+ }
4596
+ ],
4597
+ "type": "ts",
4598
+ "modulePath": "weread/highlights.js",
4599
+ "domain": "weread.qq.com",
4600
+ "columns": [
4601
+ "chapter",
4602
+ "text",
4603
+ "createTime"
4604
+ ]
4605
+ },
4606
+ {
4607
+ "site": "weread",
4608
+ "name": "notebooks",
4609
+ "description": "List books that have highlights or notes",
4610
+ "strategy": "cookie",
4611
+ "browser": true,
4612
+ "args": [],
4613
+ "type": "ts",
4614
+ "modulePath": "weread/notebooks.js",
4615
+ "domain": "weread.qq.com",
4616
+ "columns": [
4617
+ "title",
4618
+ "author",
4619
+ "noteCount",
4620
+ "bookId"
4621
+ ]
4622
+ },
4623
+ {
4624
+ "site": "weread",
4625
+ "name": "notes",
4626
+ "description": "List your notes (thoughts) on a book",
4627
+ "strategy": "cookie",
4628
+ "browser": true,
4629
+ "args": [
4630
+ {
4631
+ "name": "bookId",
4632
+ "type": "str",
4633
+ "required": true,
4634
+ "positional": true,
4635
+ "help": "Book ID (from shelf or search results)"
4636
+ },
4637
+ {
4638
+ "name": "limit",
4639
+ "type": "int",
4640
+ "default": 20,
4641
+ "required": false,
4642
+ "help": "Max results"
4643
+ }
4644
+ ],
4645
+ "type": "ts",
4646
+ "modulePath": "weread/notes.js",
4647
+ "domain": "weread.qq.com",
4648
+ "columns": [
4649
+ "chapter",
4650
+ "text",
4651
+ "review",
4652
+ "createTime"
4653
+ ]
4654
+ },
4655
+ {
4656
+ "site": "weread",
4657
+ "name": "ranking",
4658
+ "description": "WeRead book rankings by category",
4659
+ "strategy": "public",
4660
+ "browser": false,
4661
+ "args": [
4662
+ {
4663
+ "name": "category",
4664
+ "type": "str",
4665
+ "default": "all",
4666
+ "required": false,
4667
+ "positional": true,
4668
+ "help": "Category: all (default), rising, or numeric category ID"
4669
+ },
4670
+ {
4671
+ "name": "limit",
4672
+ "type": "int",
4673
+ "default": 20,
4674
+ "required": false,
4675
+ "help": "Max results"
4676
+ }
4677
+ ],
4678
+ "type": "ts",
4679
+ "modulePath": "weread/ranking.js",
4680
+ "domain": "weread.qq.com",
4681
+ "columns": [
4682
+ "rank",
4683
+ "title",
4684
+ "author",
4685
+ "category",
4686
+ "readingCount",
4687
+ "bookId"
4688
+ ]
4689
+ },
4690
+ {
4691
+ "site": "weread",
4692
+ "name": "search",
4693
+ "description": "Search books on WeRead",
4694
+ "strategy": "public",
4695
+ "browser": false,
4696
+ "args": [
4697
+ {
4698
+ "name": "keyword",
4699
+ "type": "str",
4700
+ "required": true,
4701
+ "positional": true,
4702
+ "help": "Search keyword"
4703
+ },
4704
+ {
4705
+ "name": "limit",
4706
+ "type": "int",
4707
+ "default": 10,
4708
+ "required": false,
4709
+ "help": "Max results"
4710
+ }
4711
+ ],
4712
+ "type": "ts",
4713
+ "modulePath": "weread/search.js",
4714
+ "domain": "weread.qq.com",
4715
+ "columns": [
4716
+ "rank",
4717
+ "title",
4718
+ "author",
4719
+ "bookId"
4720
+ ]
4721
+ },
4722
+ {
4723
+ "site": "weread",
4724
+ "name": "shelf",
4725
+ "description": "List books on your WeRead bookshelf",
4726
+ "strategy": "cookie",
4727
+ "browser": true,
4728
+ "args": [
4729
+ {
4730
+ "name": "limit",
4731
+ "type": "int",
4732
+ "default": 20,
4733
+ "required": false,
4734
+ "help": "Max results"
4735
+ }
4736
+ ],
4737
+ "type": "ts",
4738
+ "modulePath": "weread/shelf.js",
4739
+ "domain": "weread.qq.com",
4740
+ "columns": [
4741
+ "title",
4742
+ "author",
4743
+ "progress",
4744
+ "bookId"
4745
+ ]
4746
+ },
4747
+ {
4748
+ "site": "weread",
4749
+ "name": "utils",
4750
+ "description": "",
4751
+ "strategy": "cookie",
4752
+ "browser": false,
4753
+ "args": [],
4754
+ "type": "ts",
4755
+ "modulePath": "weread/utils.js"
4756
+ },
4757
+ {
4758
+ "site": "weread",
4759
+ "name": "utils.test",
4760
+ "description": "",
4761
+ "strategy": "cookie",
4762
+ "browser": true,
4763
+ "args": [],
4764
+ "type": "ts",
4765
+ "modulePath": "weread/utils.test.js"
4766
+ },
4220
4767
  {
4221
4768
  "site": "xiaohongshu",
4222
4769
  "name": "creator-note-detail",
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,28 @@
1
+ import { cli, Strategy } from '../../registry.js';
2
+ import { CliError } from '../../errors.js';
3
+ import { itunesFetch, formatDuration, formatDate } from './utils.js';
4
+ cli({
5
+ site: 'apple-podcasts',
6
+ name: 'episodes',
7
+ description: 'List recent episodes of an Apple Podcast (use ID from search)',
8
+ strategy: Strategy.PUBLIC,
9
+ browser: false,
10
+ args: [
11
+ { name: 'id', positional: true, required: true, help: 'Podcast ID (collectionId from search output)' },
12
+ { name: 'limit', type: 'int', default: 15, help: 'Max episodes to show' },
13
+ ],
14
+ columns: ['title', 'duration', 'date'],
15
+ func: async (_page, args) => {
16
+ const limit = Math.max(1, Math.min(Number(args.limit), 200));
17
+ // results[0] is the podcast itself; the rest are episodes
18
+ const data = await itunesFetch(`/lookup?id=${args.id}&entity=podcastEpisode&limit=${limit + 1}`);
19
+ const episodes = (data.results ?? []).filter((r) => r.kind === 'podcast-episode');
20
+ if (!episodes.length)
21
+ throw new CliError('NOT_FOUND', 'No episodes found', 'Check the podcast ID from: opencli apple-podcasts search <keyword>');
22
+ return episodes.slice(0, limit).map((ep) => ({
23
+ title: ep.trackName,
24
+ duration: formatDuration(ep.trackTimeMillis),
25
+ date: formatDate(ep.releaseDate),
26
+ }));
27
+ },
28
+ });
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,29 @@
1
+ import { cli, Strategy } from '../../registry.js';
2
+ import { CliError } from '../../errors.js';
3
+ import { itunesFetch } from './utils.js';
4
+ cli({
5
+ site: 'apple-podcasts',
6
+ name: 'search',
7
+ description: 'Search Apple Podcasts',
8
+ strategy: Strategy.PUBLIC,
9
+ browser: false,
10
+ args: [
11
+ { name: 'keyword', positional: true, required: true, help: 'Search keyword' },
12
+ { name: 'limit', type: 'int', default: 10, help: 'Max results' },
13
+ ],
14
+ columns: ['id', 'title', 'author', 'episodes', 'genre'],
15
+ func: async (_page, args) => {
16
+ const term = encodeURIComponent(args.keyword);
17
+ const limit = Math.max(1, Math.min(Number(args.limit), 25));
18
+ const data = await itunesFetch(`/search?term=${term}&media=podcast&limit=${limit}`);
19
+ if (!data.results?.length)
20
+ throw new CliError('NOT_FOUND', 'No podcasts found', `Try a different keyword`);
21
+ return data.results.map((p) => ({
22
+ id: p.collectionId,
23
+ title: p.collectionName,
24
+ author: p.artistName,
25
+ episodes: p.trackCount ?? '-',
26
+ genre: p.primaryGenreName ?? '-',
27
+ }));
28
+ },
29
+ });
@@ -0,0 +1 @@
1
+ export {};