rsshub 1.0.0-master.ff3a9ce → 1.0.0-master.ff3ea5a

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.

Potentially problematic release.


This version of rsshub might be problematic. Click here for more details.

Files changed (388) hide show
  1. package/lib/config.ts +38 -0
  2. package/lib/errors/index.tsx +3 -2
  3. package/lib/middleware/debug.ts +6 -4
  4. package/lib/middleware/header.ts +4 -2
  5. package/lib/registry.test.ts +24 -1
  6. package/lib/registry.ts +40 -11
  7. package/lib/router.js +1 -1
  8. package/lib/routes/121/namespace.ts +9 -0
  9. package/lib/routes/121/templates/description.art +17 -0
  10. package/lib/routes/121/weather-live.ts +104 -0
  11. package/lib/routes/141jav/index.ts +3 -0
  12. package/lib/routes/141ppv/index.ts +3 -0
  13. package/lib/routes/163/news/rank.ts +1 -1
  14. package/lib/routes/18comic/album.ts +59 -64
  15. package/lib/routes/18comic/index.ts +1 -0
  16. package/lib/routes/18comic/search.ts +53 -4
  17. package/lib/routes/18comic/utils.ts +70 -1
  18. package/lib/routes/2048/index.ts +1 -0
  19. package/lib/routes/30secondsofcode/utils.ts +0 -1
  20. package/lib/routes/6park/index.ts +1 -1
  21. package/lib/routes/7mmtv/index.ts +1 -0
  22. package/lib/routes/91porn/index.ts +1 -0
  23. package/lib/routes/95mm/tab.ts +1 -0
  24. package/lib/routes/agefans/detail.ts +1 -1
  25. package/lib/routes/aliyun/database-month.ts +1 -1
  26. package/lib/routes/anthropic/research.ts +112 -0
  27. package/lib/routes/apnews/topics.ts +2 -1
  28. package/lib/routes/apnews/utils.ts +1 -1
  29. package/lib/routes/apple/design.ts +54 -0
  30. package/lib/routes/apple/namespace.ts +1 -1
  31. package/lib/routes/aqara/post.ts +1 -1
  32. package/lib/routes/augmentcode/blog.ts +161 -0
  33. package/lib/routes/augmentcode/namespace.ts +9 -0
  34. package/lib/routes/augmentcode/templates/description.art +17 -0
  35. package/lib/routes/azul/namespace.ts +9 -0
  36. package/lib/routes/azul/packages.ts +105 -0
  37. package/lib/routes/banshujiang/index.ts +763 -0
  38. package/lib/routes/banshujiang/namespace.ts +9 -0
  39. package/lib/routes/banshujiang/templates/description.art +17 -0
  40. package/lib/routes/bfl/announcements.ts +1 -1
  41. package/lib/routes/bilibili/cache.ts +78 -0
  42. package/lib/routes/bilibili/danmaku.ts +1 -1
  43. package/lib/routes/bilibili/dynamic.ts +8 -2
  44. package/lib/routes/bilibili/video.ts +31 -73
  45. package/lib/routes/biquge/index.ts +1 -1
  46. package/lib/routes/bsky/keyword.ts +15 -10
  47. package/lib/routes/capitalmind/insights.ts +40 -0
  48. package/lib/routes/capitalmind/namespace.ts +8 -0
  49. package/lib/routes/capitalmind/podcasts.ts +41 -0
  50. package/lib/routes/capitalmind/utils.ts +122 -0
  51. package/lib/routes/cartoonmad/comic.ts +1 -1
  52. package/lib/routes/chikubi/index.ts +1 -0
  53. package/lib/routes/chikubi/tag.ts +1 -0
  54. package/lib/routes/chocolatey/namespace.ts +9 -0
  55. package/lib/routes/chocolatey/packages.ts +122 -0
  56. package/lib/routes/cmde/index.ts +1 -1
  57. package/lib/routes/cockroachlabs/blog.ts +113 -0
  58. package/lib/routes/cockroachlabs/namespace.ts +7 -0
  59. package/lib/routes/cool18/index.ts +4 -1
  60. package/lib/routes/coomer/index.ts +12 -6
  61. package/lib/routes/coomer/namespace.ts +1 -1
  62. package/lib/routes/copymanga/comic.ts +7 -9
  63. package/lib/routes/css-tricks/articles.ts +48 -0
  64. package/lib/routes/css-tricks/collections.ts +62 -0
  65. package/lib/routes/css-tricks/namespace.ts +8 -0
  66. package/lib/routes/css-tricks/popular.ts +39 -0
  67. package/lib/routes/css-tricks/utils.ts +103 -0
  68. package/lib/routes/cursor/changelog.ts +26 -17
  69. package/lib/routes/cursor/namespace.ts +1 -1
  70. package/lib/routes/cw/utils.ts +6 -13
  71. package/lib/routes/dealstreetasia/home.ts +1 -1
  72. package/lib/routes/dedao/index.ts +3 -3
  73. package/lib/routes/deepl/blog.ts +422 -0
  74. package/lib/routes/deepl/namespace.ts +9 -0
  75. package/lib/routes/deepl/templates/description.art +21 -0
  76. package/lib/routes/deeplearning/the-batch.ts +1 -1
  77. package/lib/routes/dev.to/guides.ts +100 -0
  78. package/lib/routes/dev.to/namespace.ts +8 -0
  79. package/lib/routes/dev.to/top.ts +105 -0
  80. package/lib/routes/dgut/jwb.ts +73 -0
  81. package/lib/routes/dgut/namespace.ts +9 -0
  82. package/lib/routes/digitalpolicyalert/activity-tracker.ts +135 -0
  83. package/lib/routes/digitalpolicyalert/namespace.ts +9 -0
  84. package/lib/routes/dnaindia/common.ts +26 -8
  85. package/lib/routes/douban/other/list.ts +3 -3
  86. package/lib/routes/e-hentai/index.ts +4 -1
  87. package/lib/routes/ehentai/tag.ts +1 -0
  88. package/lib/routes/englishhome/index.ts +55 -0
  89. package/lib/routes/englishhome/namespace.ts +6 -0
  90. package/lib/routes/epicgames/index.ts +2 -2
  91. package/lib/routes/espn/news.ts +1 -1
  92. package/lib/routes/expats/czech-news.ts +272 -0
  93. package/lib/routes/expats/namespace.ts +9 -0
  94. package/lib/routes/fanbox/index.ts +1 -0
  95. package/lib/routes/fanbox/utils.ts +1 -1
  96. package/lib/routes/fansly/tag.ts +1 -0
  97. package/lib/routes/fantia/search.ts +1 -1
  98. package/lib/routes/fantube/creator.ts +69 -0
  99. package/lib/routes/fantube/namespace.ts +7 -0
  100. package/lib/routes/fantube/templates/post.art +17 -0
  101. package/lib/routes/fantube/types.ts +100 -0
  102. package/lib/routes/fantube/utils.ts +268 -0
  103. package/lib/routes/follow/profile.ts +1 -1
  104. package/lib/routes/followin/news.ts +1 -1
  105. package/lib/routes/foresightnews/util.ts +1 -1
  106. package/lib/routes/freexcomic/book.ts +4 -1
  107. package/lib/routes/gamer/hot.ts +5 -5
  108. package/lib/routes/gaoyu/blog.ts +145 -0
  109. package/lib/routes/gaoyu/namespace.ts +9 -0
  110. package/lib/routes/gaoyu/templates/description.art +7 -0
  111. package/lib/routes/geocaching/blogs.ts +2 -2
  112. package/lib/routes/github/namespace.ts +1 -1
  113. package/lib/routes/github/private-feed.ts +229 -0
  114. package/lib/routes/github/star.ts +1 -1
  115. package/lib/routes/google/extension.ts +9 -10
  116. package/lib/routes/gov/beijing/bphc/index.ts +1 -1
  117. package/lib/routes/gov/ccdi/index.ts +1 -1
  118. package/lib/routes/gov/chongqing/sydwgkzp.ts +22 -6
  119. package/lib/routes/gov/customs/list.ts +1 -1
  120. package/lib/routes/gov/general/general.ts +1 -1
  121. package/lib/routes/gov/hangzhou/zwfw.ts +1 -1
  122. package/lib/routes/gov/pbc/goutongjiaoliu.ts +1 -1
  123. package/lib/routes/gov/shenzhen/szlh/index.ts +77 -0
  124. package/lib/routes/gov/shenzhen/szlh/namespace.ts +8 -0
  125. package/lib/routes/grist/utils.ts +5 -4
  126. package/lib/routes/hanime1/search.ts +4 -2
  127. package/lib/routes/hellogithub/report.ts +1 -1
  128. package/lib/routes/hit/hitgs.ts +240 -54
  129. package/lib/routes/hit/templates/description.art +7 -0
  130. package/lib/routes/hlju/namespace.ts +8 -0
  131. package/lib/routes/hlju/news.ts +141 -0
  132. package/lib/routes/hostmonit/cloudflareyes.ts +1 -1
  133. package/lib/routes/hotukdeals/index.ts +1 -1
  134. package/lib/routes/hyperdash/namespace.ts +7 -0
  135. package/lib/routes/hyperdash/templates/description.art +34 -0
  136. package/lib/routes/hyperdash/top-traders.ts +84 -0
  137. package/lib/routes/hyperdash/utils.ts +49 -0
  138. package/lib/routes/hypergryph/arknights/announce.ts +1 -1
  139. package/lib/routes/ielts/index.ts +1 -1
  140. package/lib/routes/infoq/topic.ts +16 -13
  141. package/lib/routes/instagram/web-api/index.ts +17 -13
  142. package/lib/routes/instagram/web-api/utils.ts +46 -63
  143. package/lib/routes/jamesclear/book-summaries.ts +40 -0
  144. package/lib/routes/jamesclear/great-speeches.ts +40 -0
  145. package/lib/routes/jamesclear/namespace.ts +8 -0
  146. package/lib/routes/jamesclear/quotes.ts +40 -0
  147. package/lib/routes/jamesclear/three-two-one.ts +41 -0
  148. package/lib/routes/jamesclear/utils.ts +22 -0
  149. package/lib/routes/japanpost/utils.ts +2 -2
  150. package/lib/routes/javbus/index.ts +3 -0
  151. package/lib/routes/javdb/tags.ts +1 -0
  152. package/lib/routes/javlibrary/star.ts +1 -0
  153. package/lib/routes/javtiful/actress.ts +3 -0
  154. package/lib/routes/javtiful/channel.ts +3 -0
  155. package/lib/routes/javtrailers/casts.ts +3 -0
  156. package/lib/routes/jetbrains/comments.ts +99 -0
  157. package/lib/routes/jetbrains/namespace.ts +8 -0
  158. package/lib/routes/jimmyspa/books.ts +1 -1
  159. package/lib/routes/jimmyspa/news.ts +1 -1
  160. package/lib/routes/jpxgmn/tab.ts +3 -0
  161. package/lib/routes/kakuyomu/works.ts +3 -0
  162. package/lib/routes/kaopu/news.ts +1 -1
  163. package/lib/routes/kemono/const.ts +1 -1
  164. package/lib/routes/kemono/index.ts +12 -11
  165. package/lib/routes/kemono/namespace.ts +1 -1
  166. package/lib/routes/kiro/blog.ts +131 -0
  167. package/lib/routes/kiro/changelog.ts +128 -0
  168. package/lib/routes/kiro/namespace.ts +9 -0
  169. package/lib/routes/konachan/post.ts +3 -0
  170. package/lib/routes/kovidgoyal/kitty/changelog.ts +83 -0
  171. package/lib/routes/kovidgoyal/namespace.ts +7 -0
  172. package/lib/routes/kunchengblog/essay.ts +1 -1
  173. package/lib/routes/landiannews/category.ts +1 -1
  174. package/lib/routes/landiannews/index.ts +1 -1
  175. package/lib/routes/landiannews/tag.ts +1 -1
  176. package/lib/routes/line/utils.ts +1 -1
  177. package/lib/routes/lineageos/changes.ts +79 -0
  178. package/lib/routes/lineageos/namespace.ts +9 -0
  179. package/lib/routes/linkedin/cn/renderer.ts +1 -1
  180. package/lib/routes/liquipedia/cs-matches.ts +42 -14
  181. package/lib/routes/literotica/new.ts +1 -0
  182. package/lib/routes/lofter/tag.ts +27 -3
  183. package/lib/routes/makerworld/contest.ts +51 -0
  184. package/lib/routes/makerworld/namespace.ts +7 -0
  185. package/lib/routes/makerworld/trending.ts +45 -0
  186. package/lib/routes/makerworld/user-upload.ts +54 -0
  187. package/lib/routes/makerworld/utils.ts +18 -0
  188. package/lib/routes/manhuagui/comic.ts +1 -1
  189. package/lib/routes/manus/blog.ts +77 -0
  190. package/lib/routes/manus/namespace.ts +7 -0
  191. package/lib/routes/mastodon/tag.ts +48 -0
  192. package/lib/routes/mathpix/blog.ts +155 -0
  193. package/lib/routes/mathpix/namespace.ts +9 -0
  194. package/lib/routes/mathpix/templates/description.art +21 -0
  195. package/lib/routes/mckinsey/cn/category-map.ts +9 -15
  196. package/lib/routes/mckinsey/cn/index.ts +77 -40
  197. package/lib/routes/melonbooks/search.ts +1 -0
  198. package/lib/routes/metacritic/index.ts +2 -2
  199. package/lib/routes/meteoblue/namespace.ts +8 -0
  200. package/lib/routes/meteoblue/weathernews.ts +75 -0
  201. package/lib/routes/meteor/index.ts +1 -1
  202. package/lib/routes/microsoft/addon.ts +7 -9
  203. package/lib/routes/mihoyo/zzz/news.ts +106 -0
  204. package/lib/routes/missav/new.ts +2 -1
  205. package/lib/routes/mit/hanlab.ts +61 -0
  206. package/lib/routes/mit/namespace.ts +6 -0
  207. package/lib/routes/mittrchina/index.ts +3 -3
  208. package/lib/routes/mixcloud/config.ts +129 -0
  209. package/lib/routes/mixcloud/index.ts +163 -107
  210. package/lib/routes/mixcloud/user-playlist.ts +31 -0
  211. package/lib/routes/mixi2/community.ts +72 -0
  212. package/lib/routes/mixi2/discovery.ts +52 -0
  213. package/lib/routes/mixi2/home.ts +51 -0
  214. package/lib/routes/mixi2/namespace.ts +8 -0
  215. package/lib/routes/mixi2/user.ts +77 -0
  216. package/lib/routes/mixi2/utils.ts +56 -0
  217. package/lib/routes/modelscope/learn.ts +94 -0
  218. package/lib/routes/moodysmismicrosite/report.ts +1 -1
  219. package/lib/routes/musify/index.ts +130 -0
  220. package/lib/routes/musify/namespace.ts +9 -0
  221. package/lib/routes/musikguru/namespace.ts +9 -0
  222. package/lib/routes/musikguru/news.ts +146 -0
  223. package/lib/routes/musikguru/templates/description.art +21 -0
  224. package/lib/routes/myfans/post.ts +1 -0
  225. package/lib/routes/nankai/cc-notice.ts +114 -0
  226. package/lib/routes/nankai/jwc.ts +131 -0
  227. package/lib/routes/nankai/namespace.ts +7 -0
  228. package/lib/routes/nankai/notice.ts +84 -0
  229. package/lib/routes/nankai/yzb.ts +97 -0
  230. package/lib/routes/neu/yz.ts +172 -0
  231. package/lib/routes/newslaundry/explainer.ts +30 -0
  232. package/lib/routes/newslaundry/namespace.ts +8 -0
  233. package/lib/routes/newslaundry/nl-cheatsheet.ts +30 -0
  234. package/lib/routes/newslaundry/nl-collaborations.ts +30 -0
  235. package/lib/routes/newslaundry/podcast.ts +61 -0
  236. package/lib/routes/newslaundry/reports.ts +30 -0
  237. package/lib/routes/newslaundry/shot.ts +30 -0
  238. package/lib/routes/newslaundry/subscriber-only.ts +30 -0
  239. package/lib/routes/newslaundry/templates/description.art +28 -0
  240. package/lib/routes/newslaundry/utils.ts +108 -0
  241. package/lib/routes/newswav/latest.ts +100 -0
  242. package/lib/routes/newswav/namespace.ts +7 -0
  243. package/lib/routes/nhentai/index.ts +1 -0
  244. package/lib/routes/nifd/research.ts +16 -0
  245. package/lib/routes/nio/namespace.ts +9 -0
  246. package/lib/routes/nio/nioradio.ts +75 -0
  247. package/lib/routes/njust/cs.ts +58 -0
  248. package/lib/routes/njust/utils.ts +1 -1
  249. package/lib/routes/ntdm/video.ts +1 -1
  250. package/lib/routes/nuaa/utils/pypasswaf.ts +1 -1
  251. package/lib/routes/oilchem/index.ts +1 -1
  252. package/lib/routes/oncc/money18.ts +1 -1
  253. package/lib/routes/openai/cookbook.ts +1 -1
  254. package/lib/routes/paulgraham/article.ts +2 -2
  255. package/lib/routes/picuki/profile.ts +4 -0
  256. package/lib/routes/pixiv/bookmarks.ts +1 -1
  257. package/lib/routes/pixiv/novel-api/series/sfw.ts +1 -1
  258. package/lib/routes/pixiv/novels.ts +2 -2
  259. package/lib/routes/pixiv/user.ts +1 -1
  260. package/lib/routes/playno1/av.ts +1 -0
  261. package/lib/routes/pornhub/model.ts +3 -7
  262. package/lib/routes/pornhub/pornstar.ts +2 -7
  263. package/lib/routes/pornhub/users.ts +2 -7
  264. package/lib/routes/pornhub/utils.ts +12 -1
  265. package/lib/routes/qingting/podcast.ts +2 -1
  266. package/lib/routes/qipamaijia/index.ts +1 -0
  267. package/lib/routes/questmobile/report.ts +1 -1
  268. package/lib/routes/railway/index.ts +73 -0
  269. package/lib/routes/railway/namespace.ts +8 -0
  270. package/lib/routes/reuters/common.ts +0 -3
  271. package/lib/routes/rockthejvm/articles.ts +167 -0
  272. package/lib/routes/rockthejvm/namespace.ts +9 -0
  273. package/lib/routes/rockthejvm/templates/description.art +7 -0
  274. package/lib/routes/samrdprc/namespace.ts +7 -0
  275. package/lib/routes/samrdprc/news.ts +79 -0
  276. package/lib/routes/sankei/namespace.ts +7 -0
  277. package/lib/routes/sankei/news.ts +68 -0
  278. package/lib/routes/sankei/topics.ts +71 -0
  279. package/lib/routes/sciencenet/user.ts +1 -1
  280. package/lib/routes/scoop/apps.ts +188 -0
  281. package/lib/routes/scoop/namespace.ts +9 -0
  282. package/lib/routes/scoop/templates/description.art +56 -0
  283. package/lib/routes/scpta/namespace.ts +8 -0
  284. package/lib/routes/scpta/news.ts +101 -0
  285. package/lib/routes/seekingalpha/index.ts +1 -1
  286. package/lib/routes/sehuatang/index.ts +29 -31
  287. package/lib/routes/setn/index.ts +11 -2
  288. package/lib/routes/seu/cyber/index.ts +78 -0
  289. package/lib/routes/sicau/jiaowu.ts +42 -34
  290. package/lib/routes/sis001/forum.ts +1 -0
  291. package/lib/routes/sjtu/seiee/icisee.ts +67 -0
  292. package/lib/routes/sketis/isabelle-dev/blog/index.ts +1 -1
  293. package/lib/routes/smartlink/index.ts +13 -3
  294. package/lib/routes/sohu/mp.ts +17 -6
  295. package/lib/routes/sotwe/namespace.ts +1 -0
  296. package/lib/routes/sotwe/user.ts +98 -0
  297. package/lib/routes/spankbang/new-videos.ts +1 -0
  298. package/lib/routes/spglobal/ratings.ts +1 -1
  299. package/lib/routes/stanford/blog.ts +77 -0
  300. package/lib/routes/stanford/namespace.ts +7 -0
  301. package/lib/routes/syosetu/index.ts +1 -1
  302. package/lib/routes/t66y/index.ts +1 -0
  303. package/lib/routes/taobao/mysql.ts +157 -0
  304. package/lib/routes/taobao/namespace.ts +2 -2
  305. package/lib/routes/techcrunch/category.ts +48 -0
  306. package/lib/routes/telegram/channel.ts +2 -2
  307. package/lib/routes/tesla/cx.ts +1 -1
  308. package/lib/routes/test/index.ts +1 -1
  309. package/lib/routes/themoviedb/episodes.ts +1 -1
  310. package/lib/routes/thewirehindi/category.ts +78 -0
  311. package/lib/routes/thewirehindi/index.ts +43 -0
  312. package/lib/routes/thewirehindi/namespace.ts +7 -0
  313. package/lib/routes/thewirehindi/templates/description.art +9 -0
  314. package/lib/routes/thewirehindi/utils.ts +33 -0
  315. package/lib/routes/threads/utils.ts +2 -2
  316. package/lib/routes/tidb/blog.ts +314 -0
  317. package/lib/routes/tidb/namespace.ts +9 -0
  318. package/lib/routes/tumblr/namespace.ts +17 -0
  319. package/lib/routes/tumblr/posts.ts +74 -0
  320. package/lib/routes/tumblr/utils.ts +110 -0
  321. package/lib/routes/tver/namespace.ts +7 -0
  322. package/lib/routes/tver/series.ts +98 -0
  323. package/lib/routes/twitter/api/web-api/login.ts +1 -3
  324. package/lib/routes/twitter/api/web-api/utils.ts +23 -1
  325. package/lib/routes/twitter/utils.ts +21 -21
  326. package/lib/routes/udn/breaking-news.ts +2 -2
  327. package/lib/routes/uestc/auto.ts +1 -1
  328. package/lib/routes/uestc/cqe.ts +1 -1
  329. package/lib/routes/uestc/scse.ts +1 -1
  330. package/lib/routes/uestc/sice.ts +1 -1
  331. package/lib/routes/uestc/sise.ts +1 -1
  332. package/lib/routes/upc/jwc.ts +32 -46
  333. package/lib/routes/uptimerobot/rss.ts +1 -1
  334. package/lib/routes/visionias/daily-news-summary.ts +65 -0
  335. package/lib/routes/visionias/monthly-magazine.ts +68 -0
  336. package/lib/routes/visionias/news-today.ts +3 -13
  337. package/lib/routes/visionias/utils.ts +5 -5
  338. package/lib/routes/visionias/weekly-focus.ts +2 -2
  339. package/lib/routes/wdfxw/bookfree.ts +528 -0
  340. package/lib/routes/wdfxw/namespace.ts +8 -0
  341. package/lib/routes/wdfxw/templates/description.art +13 -0
  342. package/lib/routes/whu/swrh.ts +1 -1
  343. package/lib/routes/windsurf/blog.ts +118 -0
  344. package/lib/routes/windsurf/changelog.ts +100 -0
  345. package/lib/routes/windsurf/namespace.ts +9 -0
  346. package/lib/routes/windsurf/templates/description.art +21 -0
  347. package/lib/routes/x6d/index.ts +1 -1
  348. package/lib/routes/xbookcn/blog.ts +1 -0
  349. package/lib/routes/xiaohongshu/util.ts +1 -3
  350. package/lib/routes/xiaoyuzhou/pickup.ts +1 -1
  351. package/lib/routes/ximalaya/album.ts +32 -70
  352. package/lib/routes/ximalaya/types.ts +48 -0
  353. package/lib/routes/ximalaya/utils.ts +9 -7
  354. package/lib/routes/xmanhua/index.ts +1 -0
  355. package/lib/routes/xueqiu/cookies.ts +1 -1
  356. package/lib/routes/xueqiu/user.ts +1 -1
  357. package/lib/routes/xwenming/index.ts +184 -0
  358. package/lib/routes/xwenming/namespace.ts +9 -0
  359. package/lib/routes/yahoo/news/utils.ts +1 -1
  360. package/lib/routes/yande/post.ts +3 -0
  361. package/lib/routes/ymgal/game.ts +1 -0
  362. package/lib/routes/youtube/api/google.ts +27 -0
  363. package/lib/routes/youtube/api/youtubei.ts +70 -20
  364. package/lib/routes/youtube/community.ts +3 -1
  365. package/lib/routes/youtube/utils.ts +16 -14
  366. package/lib/routes/zaobao/util.ts +8 -5
  367. package/lib/routes/zhihu/activities.ts +3 -0
  368. package/lib/routes/zhihu/execlib/x-zse-96-v3.ts +5 -5
  369. package/lib/routes/zhizhuan100/namespace.ts +7 -0
  370. package/lib/routes/zhizhuan100/report.ts +79 -0
  371. package/lib/routes/zimuxia/portfolio.ts +1 -1
  372. package/lib/routes/zju/sis/index.ts +161 -0
  373. package/lib/server.ts +5 -0
  374. package/lib/types.ts +58 -54
  375. package/lib/utils/helpers.ts +1 -1
  376. package/lib/utils/logger.ts +1 -1
  377. package/lib/utils/proxy/index.ts +102 -18
  378. package/lib/utils/proxy/multi-proxy.ts +139 -0
  379. package/lib/utils/proxy/unify-proxy.ts +3 -1
  380. package/lib/utils/puppeteer-utils.test.ts +1 -1
  381. package/lib/utils/puppeteer.test.ts +14 -27
  382. package/lib/utils/puppeteer.ts +51 -37
  383. package/lib/utils/readable-social.test.ts +65 -0
  384. package/lib/utils/readable-social.ts +15 -1
  385. package/lib/utils/request-rewriter/fetch.ts +42 -4
  386. package/package.json +54 -56
  387. package/lib/routes/mixcloud/queries.ts +0 -2274
  388. package/lib/routes-deprecated/dev.to/top.js +0 -40
@@ -1,6 +1,6 @@
1
1
  import { describe, expect, it, vi, afterEach } from 'vitest';
2
2
  import wait from './wait';
3
- import { type Browser } from 'puppeteer';
3
+ import { type Browser } from 'rebrowser-puppeteer';
4
4
 
5
5
  let browser: Browser | null = null;
6
6
 
@@ -44,32 +44,19 @@ describe('puppeteer', () => {
44
44
  browser = null;
45
45
  }, 45000);
46
46
 
47
- if (!process.env.GITHUB_ACTIONS) {
48
- it('puppeteer without stealth', async () => {
49
- const { default: puppeteer } = await import('./puppeteer');
50
- browser = await puppeteer({ stealth: false });
51
- const page = await browser.newPage();
52
- await page.goto('https://bot.sannysoft.com', { waitUntil: 'networkidle0' });
53
- // page rendering is not instant, wait for expected elements to appear
54
- const [webDriverTest, chromeTest] = await Promise.all(['webdriver', 'chrome'].map((t) => page.waitForSelector(`td#${t}-result.result.failed`).then((hd) => hd?.evaluate((e) => e.textContent))));
55
- // the website return empty string from time to time for no reason
56
- // since we don't really care whether puppeteer without stealth passes the bot test, just let it go
57
- expect(['present (failed)', '']).toContain(webDriverTest);
58
- expect(['missing (failed)', '']).toContain(chromeTest);
59
- }, 20000);
60
-
61
- it('puppeteer with stealth', async () => {
62
- const { default: puppeteer } = await import('./puppeteer');
63
- browser = await puppeteer({ stealth: true });
64
- const page = await browser.newPage();
65
- await page.goto('https://bot.sannysoft.com', { waitUntil: 'networkidle0' });
66
- // page rendering is not instant, wait for expected elements to appear
67
- const [webDriverTest, chromeTest] = await Promise.all(['webdriver', 'chrome'].map((t) => page.waitForSelector(`td#${t}-result.result.passed`).then((hd) => hd?.evaluate((e) => e.textContent))));
68
- // these are something we really care about
69
- expect(webDriverTest).toBe('missing (passed)');
70
- expect(chromeTest).toBe('present (passed)');
71
- }, 20000);
72
- }
47
+ // if (!process.env.GITHUB_ACTIONS) {
48
+ it('puppeteer stealth test', async () => {
49
+ const { default: puppeteer } = await import('./puppeteer');
50
+ browser = await puppeteer();
51
+ const page = await browser.newPage();
52
+ await page.goto('https://bot.sannysoft.com', { waitUntil: 'networkidle0' });
53
+ // page rendering is not instant, wait for expected elements to appear
54
+ const [webDriverTest, chromeTest] = await Promise.all(['webdriver', 'chrome'].map((t) => page.waitForSelector(`td#${t}-result.result.passed`).then((hd) => hd?.evaluate((e) => e.textContent))));
55
+ // these are something we really care about
56
+ expect(webDriverTest).toBe('missing (passed)');
57
+ expect(chromeTest).toBe('present (passed)');
58
+ }, 20000);
59
+ // }
73
60
 
74
61
  it('puppeteer accept http proxy uri w/ auth', async () => {
75
62
  process.env.PROXY_URI = 'http://user:pass@rsshub.proxy:2333';
@@ -1,46 +1,42 @@
1
1
  import { config } from '@/config';
2
- import puppeteer, { Browser, Page } from 'puppeteer';
2
+ import puppeteer, { Browser, Page } from 'rebrowser-puppeteer';
3
3
  import logger from './logger';
4
4
  import proxy from './proxy';
5
5
  import { anonymizeProxy } from 'proxy-chain';
6
6
 
7
- import { type PuppeteerExtra, addExtra } from 'puppeteer-extra';
8
- import StealthPlugin from 'puppeteer-extra-plugin-stealth';
9
-
10
7
  /**
11
8
  * @deprecated use getPage instead
12
- * @param {Object} extraOptions
13
- * @param {boolean} extraOptions.stealth - Use puppeteer-extra-plugin-stealth
14
9
  * @returns Puppeteer browser
15
10
  */
16
- const outPuppeteer = async (
17
- extraOptions: {
18
- stealth?: boolean;
19
- } = {}
20
- ) => {
11
+ const outPuppeteer = async () => {
21
12
  const options = {
22
- args: ['--no-sandbox', '--disable-setuid-sandbox', '--disable-infobars', '--window-position=0,0', '--ignore-certificate-errors', '--ignore-certificate-errors-spki-list', `--user-agent=${config.ua}`],
13
+ args: [
14
+ '--no-sandbox',
15
+ '--disable-setuid-sandbox',
16
+ '--disable-blink-features=AutomationControlled',
17
+ '--window-position=0,0',
18
+ '--ignore-certificate-errors',
19
+ '--ignore-certificate-errors-spki-list',
20
+ `--user-agent=${config.ua}`,
21
+ ],
23
22
  headless: true,
24
23
  ignoreHTTPSErrors: true,
25
24
  };
26
25
 
27
- let insidePuppeteer: PuppeteerExtra | typeof puppeteer = puppeteer;
28
- if (extraOptions.stealth) {
29
- insidePuppeteer = addExtra(puppeteer);
30
- insidePuppeteer.use(StealthPlugin());
31
- }
26
+ const insidePuppeteer: typeof puppeteer = puppeteer;
32
27
 
33
- if (proxy.proxyUri && proxy.proxyObj.url_regex === '.*') {
34
- if (proxy.proxyUrlHandler?.username || proxy.proxyUrlHandler?.password) {
28
+ const currentProxy = proxy.getCurrentProxy();
29
+ if (currentProxy && proxy.proxyObj.url_regex === '.*') {
30
+ if (currentProxy.urlHandler?.username || currentProxy.urlHandler?.password) {
35
31
  // only proxies with authentication need to be anonymized
36
- if (proxy.proxyUrlHandler.protocol === 'http:') {
37
- options.args.push(`--proxy-server=${await anonymizeProxy(proxy.proxyUri)}`);
32
+ if (currentProxy.urlHandler.protocol === 'http:') {
33
+ options.args.push(`--proxy-server=${await anonymizeProxy(currentProxy.uri)}`);
38
34
  } else {
39
35
  logger.warn('SOCKS/HTTPS proxy with authentication is not supported by puppeteer, continue without proxy');
40
36
  }
41
37
  } else {
42
38
  // Chromium cannot recognize socks5h and socks4a, so we need to trim their postfixes
43
- options.args.push(`--proxy-server=${proxy.proxyUri.replace('socks5h://', 'socks5://').replace('socks4a://', 'socks4://')}`);
39
+ options.args.push(`--proxy-server=${currentProxy.uri.replace('socks5h://', 'socks5://').replace('socks4a://', 'socks4://')}`);
44
40
  }
45
41
  }
46
42
  const browser = await (config.puppeteerWSEndpoint
@@ -78,14 +74,20 @@ export const getPuppeteerPage = async (
78
74
  } = {}
79
75
  ) => {
80
76
  const options = {
81
- args: ['--no-sandbox', '--disable-setuid-sandbox', '--disable-infobars', '--window-position=0,0', '--ignore-certificate-errors', '--ignore-certificate-errors-spki-list', `--user-agent=${config.ua}`],
77
+ args: [
78
+ '--no-sandbox',
79
+ '--disable-setuid-sandbox',
80
+ '--disable-blink-features=AutomationControlled',
81
+ '--window-position=0,0',
82
+ '--ignore-certificate-errors',
83
+ '--ignore-certificate-errors-spki-list',
84
+ `--user-agent=${config.ua}`,
85
+ ],
82
86
  headless: true,
83
87
  ignoreHTTPSErrors: true,
84
88
  };
85
89
 
86
- let insidePuppeteer: PuppeteerExtra | typeof puppeteer = puppeteer;
87
- insidePuppeteer = addExtra(puppeteer);
88
- insidePuppeteer.use(StealthPlugin());
90
+ const insidePuppeteer: typeof puppeteer = puppeteer;
89
91
 
90
92
  let allowProxy = false;
91
93
  const proxyRegex = new RegExp(proxy.proxyObj.url_regex);
@@ -101,11 +103,14 @@ export const getPuppeteerPage = async (
101
103
  }
102
104
 
103
105
  let hasProxy = false;
104
- if (proxy.proxyUri && allowProxy) {
105
- if (proxy.proxyUrlHandler?.username || proxy.proxyUrlHandler?.password) {
106
+ let currentProxyState: any = null;
107
+ const currentProxy = proxy.getCurrentProxy();
108
+ if (currentProxy && allowProxy) {
109
+ currentProxyState = currentProxy;
110
+ if (currentProxy.urlHandler?.username || currentProxy.urlHandler?.password) {
106
111
  // only proxies with authentication need to be anonymized
107
- if (proxy.proxyUrlHandler.protocol === 'http:') {
108
- const urlObj = new URL(proxy.proxyUri);
112
+ if (currentProxy.urlHandler.protocol === 'http:') {
113
+ const urlObj = new URL(currentProxy.uri);
109
114
  urlObj.username = '';
110
115
  urlObj.password = '';
111
116
  options.args.push(`--proxy-server=${urlObj.toString().replace(/\/$/, '')}`);
@@ -115,7 +120,7 @@ export const getPuppeteerPage = async (
115
120
  }
116
121
  } else {
117
122
  // Chromium cannot recognize socks5h and socks4a, so we need to trim their postfixes
118
- options.args.push(`--proxy-server=${proxy.proxyUri.replace('socks5h://', 'socks5://').replace('socks4a://', 'socks4://')}`);
123
+ options.args.push(`--proxy-server=${currentProxy.uri.replace('socks5h://', 'socks5://').replace('socks4a://', 'socks4://')}`);
119
124
  hasProxy = true;
120
125
  }
121
126
  }
@@ -145,14 +150,14 @@ export const getPuppeteerPage = async (
145
150
 
146
151
  const page = await browser.newPage();
147
152
 
148
- if (hasProxy) {
149
- logger.debug(`Proxying request in puppeteer: ${url}`);
153
+ if (hasProxy && currentProxyState) {
154
+ logger.debug(`Proxying request in puppeteer via ${currentProxyState.uri}: ${url}`);
150
155
  }
151
156
 
152
- if (hasProxy && (proxy.proxyUrlHandler?.username || proxy.proxyUrlHandler?.password)) {
157
+ if (hasProxy && currentProxyState && (currentProxyState.urlHandler?.username || currentProxyState.urlHandler?.password)) {
153
158
  await page.authenticate({
154
- username: proxy.proxyUrlHandler?.username,
155
- password: proxy.proxyUrlHandler?.password,
159
+ username: currentProxyState.urlHandler?.username,
160
+ password: currentProxyState.urlHandler?.password,
156
161
  });
157
162
  }
158
163
 
@@ -161,7 +166,16 @@ export const getPuppeteerPage = async (
161
166
  }
162
167
 
163
168
  if (!instanceOptions.noGoto) {
164
- await page.goto(url, instanceOptions.gotoConfig || { waitUntil: 'domcontentloaded' });
169
+ try {
170
+ await page.goto(url, instanceOptions.gotoConfig || { waitUntil: 'domcontentloaded' });
171
+ } catch (error) {
172
+ if (hasProxy && currentProxyState && proxy.multiProxy) {
173
+ logger.warn(`Puppeteer navigation failed with proxy ${currentProxyState.uri}, marking as failed: ${error}`);
174
+ proxy.markProxyFailed(currentProxyState.uri);
175
+ throw error;
176
+ }
177
+ throw error;
178
+ }
165
179
  }
166
180
 
167
181
  return {
@@ -0,0 +1,65 @@
1
+ import { describe, expect, test } from 'vitest';
2
+ import { fallback, queryToBoolean, queryToInteger, queryToFloat } from './readable-social';
3
+
4
+ describe('fallback', () => {
5
+ test('应该返回第一个存在的参数', () => {
6
+ expect(fallback('primary', 'secondary', 'default')).toBe('primary');
7
+ expect(fallback(undefined, 42, 0)).toBe(42);
8
+ expect(fallback(null, '', 'default')).toBe('');
9
+ });
10
+
11
+ test('应该返回默认值', () => {
12
+ expect(fallback(undefined, null, 'default')).toBe('default');
13
+ expect(fallback(null, undefined, 3.14)).toBe(3.14);
14
+ });
15
+ });
16
+
17
+ describe('queryToBoolean', () => {
18
+ test('should handle truthy values', () => {
19
+ expect(queryToBoolean('1')).toBe(true);
20
+ expect(queryToBoolean('true')).toBe(true);
21
+ });
22
+
23
+ test('should handle falsy values', () => {
24
+ expect(queryToBoolean('0')).toBe(false);
25
+ expect(queryToBoolean('false')).toBe(false);
26
+ });
27
+ });
28
+
29
+ describe('queryToInteger', () => {
30
+ test('should parse valid integers', () => {
31
+ expect(queryToInteger('42')).toBe(42);
32
+ expect(queryToInteger('-3')).toBe(-3);
33
+ });
34
+
35
+ test('should handle invalid inputs', () => {
36
+ expect(queryToInteger(null)).toBeNull();
37
+ expect(queryToInteger('abc')).toBeNaN();
38
+ });
39
+ });
40
+
41
+ describe('queryToFloat', () => {
42
+ test('should handle undefined', () => {
43
+ expect(queryToFloat(undefined)).toBeUndefined();
44
+ });
45
+
46
+ test('should handle null', () => {
47
+ expect(queryToFloat(null)).toBeNull();
48
+ });
49
+
50
+ test('should return undefined for invalid input', () => {
51
+ expect(queryToFloat('invalid')).toBeNaN();
52
+ });
53
+
54
+ test('should process array input', () => {
55
+ expect(queryToFloat(['3.14'])).toBe(3.14);
56
+ });
57
+
58
+ test('should convert numeric string', () => {
59
+ expect(queryToFloat('9.8')).toBe(9.8);
60
+ });
61
+
62
+ test('should handle edge cases', () => {
63
+ expect(queryToFloat('3.1415926')).toBeCloseTo(3.141_592_6);
64
+ });
65
+ });
@@ -39,4 +39,18 @@ const queryToInteger = (s) => {
39
39
  return Number.parseInt(s);
40
40
  };
41
41
 
42
- export { fallback, queryToBoolean, queryToInteger };
42
+ const queryToFloat = (s) => {
43
+ if (s === undefined || s === null) {
44
+ return s;
45
+ }
46
+ if (Array.isArray(s)) {
47
+ if (s.length === 0) {
48
+ return;
49
+ }
50
+ s = s[0];
51
+ }
52
+ s = s.toString();
53
+ return Number.parseFloat(s);
54
+ };
55
+
56
+ export { fallback, queryToBoolean, queryToInteger, queryToFloat };
@@ -60,7 +60,7 @@ const wrappedFetch: typeof undici.fetch = async (input: RequestInfo, init?: Requ
60
60
  config.enableRemoteDebugging && useCustomHeader(request.headers);
61
61
 
62
62
  // proxy
63
- if (!init?.dispatcher && proxy.dispatcher && (proxy.proxyObj.strategy !== 'on_retry' || isRetry)) {
63
+ if (!init?.dispatcher && (proxy.proxyObj.strategy !== 'on_retry' || isRetry)) {
64
64
  const proxyRegex = new RegExp(proxy.proxyObj.url_regex);
65
65
  let urlHandler;
66
66
  try {
@@ -70,13 +70,51 @@ const wrappedFetch: typeof undici.fetch = async (input: RequestInfo, init?: Requ
70
70
  }
71
71
 
72
72
  if (proxyRegex.test(request.url) && request.url.startsWith('http') && !(urlHandler && urlHandler.host === proxy.proxyUrlHandler?.host)) {
73
- options.dispatcher = proxy.dispatcher;
74
- logger.debug(`Proxying request: ${request.url}`);
73
+ const currentProxy = proxy.getCurrentProxy();
74
+ if (currentProxy) {
75
+ const dispatcher = proxy.getDispatcherForProxy(currentProxy);
76
+ if (dispatcher) {
77
+ options.dispatcher = dispatcher;
78
+ logger.debug(`Proxying request via ${currentProxy.uri}: ${request.url}`);
79
+ }
80
+ }
75
81
  }
76
82
  }
77
83
 
78
84
  await limiterQueue.removeTokens(1);
79
- return undici.fetch(request, options);
85
+
86
+ const maxRetries = proxy.multiProxy?.allProxies.length || 1;
87
+
88
+ const attemptRequest = async (attempt: number): Promise<Response> => {
89
+ try {
90
+ return await undici.fetch(request, options);
91
+ } catch (error) {
92
+ if (options.dispatcher && proxy.multiProxy && attempt < maxRetries - 1) {
93
+ const currentProxy = proxy.getCurrentProxy();
94
+ if (currentProxy) {
95
+ logger.warn(`Request failed with proxy ${currentProxy.uri}, trying next proxy: ${error}`);
96
+ proxy.markProxyFailed(currentProxy.uri);
97
+
98
+ const nextProxy = proxy.getCurrentProxy();
99
+ if (nextProxy && nextProxy.uri !== currentProxy.uri) {
100
+ const nextDispatcher = proxy.getDispatcherForProxy(nextProxy);
101
+ if (nextDispatcher) {
102
+ options.dispatcher = nextDispatcher;
103
+ }
104
+ logger.debug(`Retrying request with proxy ${nextProxy.uri}: ${request.url}`);
105
+ return attemptRequest(attempt + 1);
106
+ } else {
107
+ logger.warn('No more proxies available, trying without proxy');
108
+ delete options.dispatcher;
109
+ return attemptRequest(attempt + 1);
110
+ }
111
+ }
112
+ }
113
+ throw error;
114
+ }
115
+ };
116
+
117
+ return attemptRequest(0);
80
118
  };
81
119
 
82
120
  export default wrappedFetch;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rsshub",
3
- "version": "1.0.0-master.ff3a9ce",
3
+ "version": "1.0.0-master.ff3ea5a",
4
4
  "description": "Make RSS Great Again!",
5
5
  "keywords": [
6
6
  "RSS"
@@ -35,45 +35,45 @@
35
35
  "@bbob/html": "4.2.0",
36
36
  "@bbob/plugin-helper": "4.2.0",
37
37
  "@bbob/preset-html5": "4.2.0",
38
- "@hono/node-server": "1.14.4",
39
- "@hono/zod-openapi": "0.19.8",
40
- "@notionhq/client": "3.1.3",
38
+ "@hono/node-server": "1.18.2",
39
+ "@hono/zod-openapi": "0.19.10",
40
+ "@notionhq/client": "4.0.2",
41
41
  "@opentelemetry/api": "1.9.0",
42
- "@opentelemetry/exporter-prometheus": "0.202.0",
43
- "@opentelemetry/exporter-trace-otlp-http": "0.202.0",
42
+ "@opentelemetry/exporter-prometheus": "0.203.0",
43
+ "@opentelemetry/exporter-trace-otlp-http": "0.203.0",
44
44
  "@opentelemetry/resources": "2.0.1",
45
45
  "@opentelemetry/sdk-metrics": "2.0.1",
46
46
  "@opentelemetry/sdk-trace-base": "2.0.1",
47
- "@opentelemetry/semantic-conventions": "1.34.0",
47
+ "@opentelemetry/semantic-conventions": "1.36.0",
48
48
  "@postlight/parser": "2.2.3",
49
49
  "@rss3/sdk": "0.0.25",
50
- "@scalar/hono-api-reference": "0.9.4",
51
- "@sentry/node": "9.29.0",
50
+ "@scalar/hono-api-reference": "0.9.13",
51
+ "@sentry/node": "10.5.0",
52
52
  "@tonyrl/rand-user-agent": "2.0.83",
53
53
  "aes-js": "3.1.2",
54
54
  "art-template": "4.13.2",
55
- "cheerio": "1.1.0",
55
+ "cheerio": "1.1.2",
56
56
  "city-timezones": "1.3.1",
57
- "cross-env": "7.0.3",
57
+ "cross-env": "10.0.0",
58
58
  "crypto-js": "4.2.0",
59
59
  "currency-symbol-map": "5.1.0",
60
60
  "dayjs": "1.11.8",
61
61
  "destr": "2.0.5",
62
62
  "directory-import": "3.3.2",
63
- "dotenv": "16.5.0",
63
+ "dotenv": "17.2.1",
64
64
  "entities": "6.0.1",
65
65
  "etag": "1.8.1",
66
- "fanfou-sdk": "5.0.0",
67
- "form-data": "4.0.3",
68
- "googleapis": "150.0.1",
69
- "hono": "4.7.11",
66
+ "fanfou-sdk": "6.0.0",
67
+ "form-data": "4.0.4",
68
+ "googleapis": "156.0.0",
69
+ "hono": "4.9.1",
70
70
  "html-to-text": "9.0.5",
71
71
  "http-cookie-agent": "6.0.8",
72
72
  "https-proxy-agent": "7.0.6",
73
73
  "iconv-lite": "0.6.3",
74
74
  "imapflow": "1.0.188",
75
75
  "instagram-private-api": "1.46.1",
76
- "ioredis": "5.6.1",
76
+ "ioredis": "5.7.0",
77
77
  "ip-regex": "5.0.0",
78
78
  "jsdom": "26.1.0",
79
79
  "json-bigint": "1.0.0",
@@ -81,8 +81,9 @@
81
81
  "jsrsasign": "10.9.0",
82
82
  "lru-cache": "11.1.0",
83
83
  "lz-string": "1.5.0",
84
- "mailparser": "3.7.3",
84
+ "mailparser": "3.7.4",
85
85
  "markdown-it": "14.1.0",
86
+ "mixi2": "0.2.2",
86
87
  "module-alias": "2.2.3",
87
88
  "narou": "1.2.0",
88
89
  "notion-to-md": "3.1.9",
@@ -92,43 +93,40 @@
92
93
  "p-map": "7.0.3",
93
94
  "pac-proxy-agent": "7.2.0",
94
95
  "proxy-chain": "2.5.9",
95
- "puppeteer": "24.10.1",
96
- "puppeteer-extra": "3.3.6",
97
- "puppeteer-extra-plugin-stealth": "2.11.2",
98
- "puppeteer-extra-plugin-user-data-dir": "2.4.1",
99
- "puppeteer-extra-plugin-user-preferences": "2.4.1",
100
- "query-string": "9.2.0",
101
- "rate-limiter-flexible": "7.1.1",
96
+ "query-string": "9.2.2",
97
+ "rate-limiter-flexible": "7.2.0",
102
98
  "re2js": "1.1.0",
99
+ "rebrowser-puppeteer": "24.8.1",
103
100
  "rfc4648": "1.5.4",
104
101
  "rss-parser": "3.13.0",
105
102
  "sanitize-html": "2.17.0",
106
103
  "simplecc-wasm": "1.1.0",
107
104
  "socks-proxy-agent": "8.0.5",
108
- "source-map": "0.7.4",
105
+ "source-map": "0.7.6",
109
106
  "telegram": "2.26.22",
110
107
  "title": "4.0.1",
111
- "tldts": "7.0.8",
108
+ "tldts": "7.0.11",
112
109
  "tosource": "2.0.0-alpha.3",
113
110
  "tough-cookie": "5.1.2",
114
- "tsx": "4.20.3",
115
- "twitter-api-v2": "1.23.2",
111
+ "tsx": "4.20.4",
112
+ "twitter-api-v2": "1.24.0",
116
113
  "ufo": "1.6.1",
117
114
  "undici": "6.21.3",
118
115
  "uuid": "11.1.0",
119
116
  "winston": "3.17.0",
120
117
  "xxhash-wasm": "1.1.0",
121
- "youtubei.js": "14.0.0",
122
- "zod": "3.25.64"
118
+ "youtube-caption-extractor": "1.8.2",
119
+ "youtubei.js": "15.0.1",
120
+ "zod": "3.25.76"
123
121
  },
124
122
  "devDependencies": {
125
- "@babel/preset-env": "7.27.2",
123
+ "@babel/preset-env": "7.28.3",
126
124
  "@babel/preset-typescript": "7.27.1",
127
125
  "@bbob/types": "4.2.0",
128
126
  "@eslint/eslintrc": "3.3.1",
129
- "@eslint/js": "9.29.0",
127
+ "@eslint/js": "9.33.0",
130
128
  "@microsoft/eslint-formatter-sarif": "3.1.0",
131
- "@stylistic/eslint-plugin": "4.4.1",
129
+ "@stylistic/eslint-plugin": "5.2.3",
132
130
  "@types/aes-js": "3.1.4",
133
131
  "@types/babel__preset-env": "7.10.0",
134
132
  "@types/crypto-js": "4.2.2",
@@ -141,43 +139,42 @@
141
139
  "@types/jsdom": "21.1.7",
142
140
  "@types/json-bigint": "1.0.4",
143
141
  "@types/jsrsasign": "10.5.13",
144
- "@types/lint-staged": "13.3.0",
145
142
  "@types/mailparser": "3.4.6",
146
143
  "@types/markdown-it": "14.1.2",
147
144
  "@types/module-alias": "2.0.4",
148
- "@types/node": "24.0.1",
145
+ "@types/node": "24.3.0",
149
146
  "@types/sanitize-html": "2.16.0",
150
147
  "@types/supertest": "6.0.3",
151
- "@types/title": "3.4.3",
148
+ "@types/title": "4.0.0",
152
149
  "@types/uuid": "10.0.0",
153
- "@typescript-eslint/eslint-plugin": "8.34.0",
154
- "@typescript-eslint/parser": "8.34.0",
155
- "@vercel/nft": "0.29.4",
150
+ "@typescript-eslint/eslint-plugin": "8.39.1",
151
+ "@typescript-eslint/parser": "8.39.1",
152
+ "@vercel/nft": "0.30.0",
156
153
  "@vitest/coverage-v8": "2.1.9",
157
- "discord-api-types": "0.38.11",
154
+ "discord-api-types": "0.38.20",
158
155
  "domhandler": "5.0.3",
159
- "eslint": "9.29.0",
160
- "eslint-config-prettier": "10.1.5",
156
+ "eslint": "9.33.0",
157
+ "eslint-config-prettier": "10.1.8",
161
158
  "eslint-nibble": "8.1.0",
162
- "eslint-plugin-n": "17.20.0",
163
- "eslint-plugin-prettier": "5.4.1",
164
- "eslint-plugin-unicorn": "59.0.1",
159
+ "eslint-plugin-n": "17.21.3",
160
+ "eslint-plugin-prettier": "5.5.4",
161
+ "eslint-plugin-unicorn": "60.0.0",
165
162
  "eslint-plugin-yml": "1.18.0",
166
- "fs-extra": "11.3.0",
167
- "globals": "16.2.0",
163
+ "fs-extra": "11.3.1",
164
+ "globals": "16.3.0",
168
165
  "got": "14.4.7",
169
166
  "husky": "9.1.7",
170
167
  "js-beautify": "1.15.4",
171
- "lint-staged": "16.1.1",
168
+ "lint-staged": "16.1.5",
172
169
  "magic-string": "0.30.17",
173
170
  "mockdate": "3.0.5",
174
171
  "msw": "2.4.3",
175
- "node-network-devtools": "1.0.26",
176
- "prettier": "3.5.3",
172
+ "node-network-devtools": "1.0.28",
173
+ "prettier": "3.6.2",
177
174
  "remark-parse": "11.0.0",
178
- "supertest": "7.1.1",
179
- "tsdown": "0.12.7",
180
- "typescript": "5.8.3",
175
+ "supertest": "7.1.4",
176
+ "tsdown": "0.14.1",
177
+ "typescript": "5.9.2",
181
178
  "unified": "11.0.5",
182
179
  "vite-tsconfig-paths": "5.1.4",
183
180
  "vitest": "2.1.9",
@@ -188,11 +185,12 @@
188
185
  },
189
186
  "scripts": {
190
187
  "build": "tsx scripts/workflow/build-routes.ts && tsdown",
188
+ "build:vercel": "tsx scripts/workflow/build-routes.ts && tsdown --config ./tsdown-vercel.config.ts && mv dist/server.js dist/index.js && tsx scripts/workflow/build-vercel-packagejson.ts",
191
189
  "build:docs": "tsx scripts/workflow/build-docs.ts",
192
190
  "dev": "cross-env NODE_ENV=dev tsx watch --inspect --clear-screen=false lib/index.ts",
193
191
  "dev:cache": "cross-env NODE_ENV=production tsx watch --clear-screen=false lib/index.ts",
194
- "format": "prettier \"**/*.{ts,tsx,js,json}\" --write && eslint --cache --fix \"**/*.{ts,tsx,js,yml}\"",
195
- "format:check": "prettier \"**/*.{ts,tsx,js,json}\" --check && eslint --cache \"**/*.{ts,tsx,js,yml}\"",
192
+ "format": "prettier \"**/*.{ts,tsx,js,json}\" --write --experimental-cli && eslint --cache --fix \"**/*.{ts,tsx,js,yml}\"",
193
+ "format:check": "prettier \"**/*.{ts,tsx,js,json}\" --check --experimental-cli && eslint --cache \"**/*.{ts,tsx,js,yml}\"",
196
194
  "format:staged": "lint-staged",
197
195
  "lint": "eslint --cache .",
198
196
  "profiling": "cross-env NODE_ENV=production tsx --prof lib/index.ts",