rsshub 1.0.0-master.fb6d4f3 → 1.0.0-master.fb7e42c

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 (460) hide show
  1. package/lib/assets/logo.svg +1 -0
  2. package/lib/config.ts +10 -0
  3. package/lib/errors/index.test.ts +15 -5
  4. package/lib/errors/types/captcha.ts +5 -0
  5. package/lib/middleware/cache.ts +4 -0
  6. package/lib/middleware/parameter.ts +1 -1
  7. package/lib/registry.ts +6 -2
  8. package/lib/routes/10000link/info.ts +1 -1
  9. package/lib/routes/18comic/album.ts +1 -0
  10. package/lib/routes/18comic/blogs.ts +1 -0
  11. package/lib/routes/18comic/search.ts +1 -0
  12. package/lib/routes/199it/index.ts +1 -1
  13. package/lib/routes/21caijing/channel.ts +1 -1
  14. package/lib/routes/51cto/utils.ts +1 -1
  15. package/lib/routes/6v123/index.ts +487 -0
  16. package/lib/routes/6v123/namespace.ts +1 -0
  17. package/lib/routes/8kcos/cat.ts +3 -0
  18. package/lib/routes/8kcos/latest.ts +1 -0
  19. package/lib/routes/8kcos/tag.ts +1 -0
  20. package/lib/routes/91porn/author.ts +1 -0
  21. package/lib/routes/95mm/category.ts +1 -0
  22. package/lib/routes/95mm/tag.ts +1 -0
  23. package/lib/routes/aa1/60s.ts +189 -0
  24. package/lib/routes/{xinhuanet → aa1}/namespace.ts +3 -3
  25. package/lib/routes/abc/index.ts +1 -1
  26. package/lib/routes/abskoop/index.ts +3 -0
  27. package/lib/routes/abskoop/nsfw.ts +3 -0
  28. package/lib/routes/acgvinyl/namespace.ts +6 -0
  29. package/lib/routes/acgvinyl/news.ts +86 -0
  30. package/lib/routes/ally/rail.ts +1 -1
  31. package/lib/routes/amazfitwatchfaces/index.ts +1 -2
  32. package/lib/routes/anthropic/news.ts +13 -11
  33. package/lib/routes/apnews/mobile-api.ts +1 -1
  34. package/lib/routes/apnews/sitemap.ts +1 -1
  35. package/lib/routes/app-sales/index.ts +1 -1
  36. package/lib/routes/apple/apps.ts +2 -2
  37. package/lib/routes/apple/podcast.ts +58 -25
  38. package/lib/routes/apple/security-releases.ts +2 -2
  39. package/lib/routes/asiafruitchina/categories.ts +1 -1
  40. package/lib/routes/asiantolick/index.ts +3 -0
  41. package/lib/routes/asmr-200/index.ts +1 -0
  42. package/lib/routes/bandisoft/history.ts +2 -2
  43. package/lib/routes/bangumi.tv/group/reply.ts +1 -1
  44. package/lib/routes/banshujiang/index.ts +1 -1
  45. package/lib/routes/banyuetan/index.ts +1 -1
  46. package/lib/routes/baozimh/index.ts +21 -3
  47. package/lib/routes/baselang/index.ts +117 -0
  48. package/lib/routes/baselang/namespace.ts +6 -0
  49. package/lib/routes/bbc/learningenglish.ts +35 -20
  50. package/lib/routes/bestofjs/monthly.ts +137 -0
  51. package/lib/routes/bestofjs/namespace.ts +7 -0
  52. package/lib/routes/bestofjs/templates/description.art +36 -0
  53. package/lib/routes/bilibili/cache.ts +17 -1
  54. package/lib/routes/bilibili/dynamic.ts +34 -8
  55. package/lib/routes/bilibili/page.ts +1 -1
  56. package/lib/routes/bilibili/ranking.ts +25 -17
  57. package/lib/routes/bilibili/wasm-exec.ts +1 -1
  58. package/lib/routes/bilibili/weekly-recommend.ts +22 -6
  59. package/lib/routes/bjp/apod.ts +1 -1
  60. package/lib/routes/bnext/index.ts +58 -0
  61. package/lib/routes/bnext/namespace.ts +7 -0
  62. package/lib/routes/bookwalker/namespace.ts +9 -0
  63. package/lib/routes/bookwalker/search.ts +114 -0
  64. package/lib/routes/bookwalker/templates/description.art +13 -0
  65. package/lib/routes/booru/mmda.ts +1 -0
  66. package/lib/routes/buaa/jiaowu.ts +1 -1
  67. package/lib/routes/bullionvault/gold-news.ts +4 -4
  68. package/lib/routes/cast/index.ts +1 -1
  69. package/lib/routes/cbndata/information.ts +250 -0
  70. package/lib/routes/cbndata/namespace.ts +9 -0
  71. package/lib/routes/cbndata/templates/description.art +17 -0
  72. package/lib/routes/cccmc/index.ts +1 -1
  73. package/lib/routes/ccg/index.ts +181 -0
  74. package/lib/routes/ccg/namespace.ts +9 -0
  75. package/lib/routes/ccg/templates/description.art +21 -0
  76. package/lib/routes/chikubi/category.ts +1 -0
  77. package/lib/routes/chikubi/navigation.ts +1 -0
  78. package/lib/routes/chikubi/nipple-video-category.ts +1 -0
  79. package/lib/routes/chikubi/nipple-video-maker.ts +1 -0
  80. package/lib/routes/chikubi/search.ts +1 -0
  81. package/lib/routes/chinadaily/language.ts +1 -1
  82. package/lib/routes/chinaratings/credit-research.ts +1 -1
  83. package/lib/routes/chub/characters.ts +3 -0
  84. package/lib/routes/civitai/discussions.ts +1 -0
  85. package/lib/routes/civitai/models.ts +1 -0
  86. package/lib/routes/civitai/user.ts +3 -0
  87. package/lib/routes/cline/blog.ts +34 -23
  88. package/lib/routes/coolapk/utils.ts +5 -4
  89. package/lib/routes/coolbuy/index.ts +106 -0
  90. package/lib/routes/coolbuy/namespace.ts +9 -0
  91. package/lib/routes/coolbuy/templates/description.art +48 -0
  92. package/lib/routes/coolidge/film-guide.ts +60 -0
  93. package/lib/routes/coolidge/namespace.ts +7 -0
  94. package/lib/routes/coolidge/news.ts +65 -0
  95. package/lib/routes/coolidge/templates/description.art +4 -0
  96. package/lib/routes/coomer/index.ts +4 -6
  97. package/lib/routes/copymanga/comic.ts +2 -1
  98. package/lib/routes/cosplaytele/category.ts +1 -0
  99. package/lib/routes/cosplaytele/latest.ts +1 -0
  100. package/lib/routes/cosplaytele/popular.ts +1 -0
  101. package/lib/routes/cosplaytele/tag.ts +1 -0
  102. package/lib/routes/cpta/handler.ts +1 -1
  103. package/lib/routes/creative-comic/book.ts +1 -1
  104. package/lib/routes/crush/index.ts +77 -0
  105. package/lib/routes/crush/namespace.ts +7 -0
  106. package/lib/routes/cursor/blog.ts +84 -0
  107. package/lib/routes/daum/potplayer.ts +3 -3
  108. package/lib/routes/dbaplus/new.ts +392 -0
  109. package/lib/routes/dbaplus/templates/description.art +21 -0
  110. package/lib/routes/deepl/blog.ts +2 -3
  111. package/lib/routes/diariofruticola/filtro.ts +1 -1
  112. package/lib/routes/digitalpolicyalert/activity-tracker.ts +1 -1
  113. package/lib/routes/dlsite/campaign.ts +1 -0
  114. package/lib/routes/dlsite/ci-en/article.ts +1 -0
  115. package/lib/routes/dlsite/new.ts +1 -0
  116. package/lib/routes/dlsite/z-index/index.ts +3 -0
  117. package/lib/routes/dockerhub/utils.ts +1 -1
  118. package/lib/routes/dora-world/article.ts +2 -2
  119. package/lib/routes/dytt/index.ts +1 -2
  120. package/lib/routes/eeo/kuaixun.ts +154 -0
  121. package/lib/routes/eeo/namespace.ts +9 -0
  122. package/lib/routes/eeo/templates/description.art +7 -0
  123. package/lib/routes/ehentai/ehapi.ts +3 -3
  124. package/lib/routes/ehentai/favorites.ts +1 -0
  125. package/lib/routes/ehentai/search.ts +1 -0
  126. package/lib/routes/elecfans/article.ts +64 -0
  127. package/lib/routes/elecfans/namespace.ts +7 -0
  128. package/lib/routes/elecfans/soft.ts +69 -0
  129. package/lib/routes/engineering/namespace.ts +8 -0
  130. package/lib/routes/engineering/tag.ts +55 -0
  131. package/lib/routes/eventbrite/events.ts +152 -0
  132. package/lib/routes/eventbrite/namespace.ts +7 -0
  133. package/lib/routes/eventernote/actors.ts +61 -64
  134. package/lib/routes/everia/category.ts +1 -0
  135. package/lib/routes/everia/latest.ts +1 -0
  136. package/lib/routes/everia/search.ts +1 -0
  137. package/lib/routes/everia/tag.ts +1 -0
  138. package/lib/routes/expats/czech-news.ts +1 -1
  139. package/lib/routes/fangchan/list.ts +1 -1
  140. package/lib/routes/fansly/post.ts +1 -0
  141. package/lib/routes/fantia/search.ts +1 -0
  142. package/lib/routes/fantia/user.ts +1 -0
  143. package/lib/routes/finology/tag.ts +1 -1
  144. package/lib/routes/furaffinity/art.ts +1 -0
  145. package/lib/routes/furaffinity/browse.ts +1 -0
  146. package/lib/routes/furaffinity/commissions.ts +1 -0
  147. package/lib/routes/furaffinity/home.ts +1 -0
  148. package/lib/routes/furaffinity/journal-comments.ts +1 -0
  149. package/lib/routes/furaffinity/journals.ts +1 -0
  150. package/lib/routes/furaffinity/search.ts +1 -0
  151. package/lib/routes/furaffinity/shouts.ts +1 -0
  152. package/lib/routes/furaffinity/status.ts +1 -0
  153. package/lib/routes/furaffinity/submission-comments.ts +1 -0
  154. package/lib/routes/furaffinity/user.ts +1 -0
  155. package/lib/routes/furaffinity/watchers.ts +1 -0
  156. package/lib/routes/furaffinity/watching.ts +1 -0
  157. package/lib/routes/gamebase/news.ts +2 -2
  158. package/lib/routes/gamer/gnn-index.ts +8 -3
  159. package/lib/routes/gcores/categories.ts +1 -1
  160. package/lib/routes/gcores/collections.ts +1 -1
  161. package/lib/routes/gcores/tags.ts +1 -1
  162. package/lib/routes/gcores/topics.ts +1 -1
  163. package/lib/routes/gdufs/xwxy/index.ts +196 -0
  164. package/lib/routes/gelbooru/post.ts +1 -0
  165. package/lib/routes/genossenschaften/index.ts +2 -3
  166. package/lib/routes/github/activity.ts +1 -1
  167. package/lib/routes/gitstar-ranking/index.ts +1 -1
  168. package/lib/routes/go/jihs/idwr.ts +3 -4
  169. package/lib/routes/google/jules.ts +63 -0
  170. package/lib/routes/gov/mem/namespace.ts +7 -0
  171. package/lib/routes/gov/mem/zfxxgkpt.ts +96 -0
  172. package/lib/routes/gov/moa/gjs.ts +1 -1
  173. package/lib/routes/gov/mot/index.ts +157 -53
  174. package/lib/routes/grainoil/category.ts +1 -2
  175. package/lib/routes/gxmzu/lib.ts +2 -2
  176. package/lib/routes/gxmzu/utils/index.ts +2 -2
  177. package/lib/routes/hameln/chapter.ts +1 -1
  178. package/lib/routes/hanime1/previews.ts +1 -0
  179. package/lib/routes/hanime1/search.ts +1 -0
  180. package/lib/routes/hex-rays/index.ts +1 -1
  181. package/lib/routes/hit/hitgs.ts +1 -1
  182. package/lib/routes/hit/namespace.ts +1 -1
  183. package/lib/routes/hpoi/banner-item.ts +28 -11
  184. package/lib/routes/hpoi/info.ts +1 -1
  185. package/lib/routes/hudsonrivertrading/index.ts +122 -0
  186. package/lib/routes/hudsonrivertrading/namespace.ts +7 -0
  187. package/lib/routes/huggingface/daily-papers.ts +45 -9
  188. package/lib/routes/huijin-inv/namespace.ts +7 -0
  189. package/lib/routes/huijin-inv/news.ts +83 -0
  190. package/lib/routes/hupu/index.ts +170 -74
  191. package/lib/routes/hupu/types.ts +163 -0
  192. package/lib/routes/hust/gs.ts +1 -1
  193. package/lib/routes/hust/mse.ts +1 -1
  194. package/lib/routes/huxiu/util.ts +2 -2
  195. package/lib/routes/immich/cursed-knowledge.ts +49 -0
  196. package/lib/routes/immich/namespace.ts +7 -0
  197. package/lib/routes/infoq/presentations.ts +1 -1
  198. package/lib/routes/instagram/common-utils.ts +3 -3
  199. package/lib/routes/investor/index.ts +362 -148
  200. package/lib/routes/itch/devlog.ts +7 -3
  201. package/lib/routes/iwara/index.ts +3 -0
  202. package/lib/routes/iwara/subscriptions.ts +1 -0
  203. package/lib/routes/javbus/index.ts +1 -1
  204. package/lib/routes/javdb/actors.ts +1 -0
  205. package/lib/routes/javdb/index.ts +3 -0
  206. package/lib/routes/javdb/lists.ts +3 -0
  207. package/lib/routes/javdb/makers.ts +1 -0
  208. package/lib/routes/javdb/rankings.ts +1 -0
  209. package/lib/routes/javdb/search.ts +1 -0
  210. package/lib/routes/javdb/series.ts +1 -0
  211. package/lib/routes/javdb/videocodes.ts +1 -0
  212. package/lib/routes/javlibrary/bestrated.ts +3 -0
  213. package/lib/routes/javlibrary/bestreviews.ts +1 -0
  214. package/lib/routes/javlibrary/genre.ts +3 -0
  215. package/lib/routes/javlibrary/maker.ts +1 -0
  216. package/lib/routes/javlibrary/mostwanted.ts +3 -0
  217. package/lib/routes/javlibrary/newentries.ts +3 -0
  218. package/lib/routes/javlibrary/newrelease.ts +3 -0
  219. package/lib/routes/javlibrary/update.ts +3 -0
  220. package/lib/routes/javlibrary/user.ts +3 -0
  221. package/lib/routes/javlibrary/utils.ts +1 -1
  222. package/lib/routes/javtrailers/categories.ts +3 -0
  223. package/lib/routes/javtrailers/studios.ts +3 -0
  224. package/lib/routes/jbma/namespace.ts +17 -0
  225. package/lib/routes/jbma/report.ts +471 -0
  226. package/lib/routes/jetbrains/comments.ts +1 -1
  227. package/lib/routes/jingzhengu/utils.ts +1 -1
  228. package/lib/routes/jou/utils/index.ts +2 -2
  229. package/lib/routes/jpxgmn/search.ts +3 -0
  230. package/lib/routes/jpxgmn/weekly.ts +3 -0
  231. package/lib/routes/juejin/aicoding.ts +102 -0
  232. package/lib/routes/juejin/trending.ts +70 -20
  233. package/lib/routes/juejin/utils.ts +36 -51
  234. package/lib/routes/jumeili/home.ts +1 -1
  235. package/lib/routes/kakuyomu/works.ts +1 -1
  236. package/lib/routes/kemono/index.ts +11 -3
  237. package/lib/routes/kemono/templates/discord.art +1 -1
  238. package/lib/routes/kisskiss/blog.ts +1 -0
  239. package/lib/routes/komiic/comic.ts +2 -1
  240. package/lib/routes/koyso/index.ts +339 -0
  241. package/lib/routes/koyso/namespace.ts +9 -0
  242. package/lib/routes/koyso/templates/description.art +13 -0
  243. package/lib/routes/kpopping/kpics.ts +3 -4
  244. package/lib/routes/kpopping/news.ts +2 -2
  245. package/lib/routes/laimanhua/index.ts +1 -0
  246. package/lib/routes/letterboxd/index.ts +65 -0
  247. package/lib/routes/letterboxd/namespace.ts +8 -0
  248. package/lib/routes/lhratings/research.ts +1 -1
  249. package/lib/routes/literotica/category.ts +3 -0
  250. package/lib/routes/lovelive-anime/topics.ts +5 -6
  251. package/lib/routes/maccms/index.ts +1 -1
  252. package/lib/routes/mangadex/index.ts +3 -0
  253. package/lib/routes/mangadex/mdlist/feed.ts +1 -0
  254. package/lib/routes/mangadex/user/feed.ts +1 -0
  255. package/lib/routes/mangadex/user/follows.ts +1 -0
  256. package/lib/routes/manhuagui/comic.ts +1 -0
  257. package/lib/routes/manhuagui/subscribe.ts +1 -0
  258. package/lib/routes/manyvids/video.ts +3 -0
  259. package/lib/routes/mercari/util.ts +1 -1
  260. package/lib/routes/mihoyo/sr/news.ts +2 -1
  261. package/lib/routes/mihoyo/zzz/news.ts +2 -1
  262. package/lib/routes/mingpao/index.ts +1 -1
  263. package/lib/routes/musify/index.ts +2 -3
  264. package/lib/routes/mycard520/news.ts +2 -2
  265. package/lib/routes/nankai/ai-notice.ts +142 -0
  266. package/lib/routes/nankai/graduate-notice.ts +162 -0
  267. package/lib/routes/natgeo/natgeo.ts +3 -2
  268. package/lib/routes/naturalism/namespace.ts +7 -0
  269. package/lib/routes/naturalism/new.ts +59 -0
  270. package/lib/routes/netflav/index.ts +3 -0
  271. package/lib/routes/nhentai/search.ts +1 -0
  272. package/lib/routes/nhk/news-web-easy.ts +1 -1
  273. package/lib/routes/nicovideo/mylist.ts +39 -0
  274. package/lib/routes/nicovideo/types.ts +27 -0
  275. package/lib/routes/nicovideo/utils.ts +27 -1
  276. package/lib/routes/nikkei/cn/index.ts +1 -4
  277. package/lib/routes/nio/nioradio.ts +1 -1
  278. package/lib/routes/njxzc/utils/index.ts +2 -2
  279. package/lib/routes/notion/namespace.ts +2 -2
  280. package/lib/routes/now/news.ts +1 -1
  281. package/lib/routes/nytimes/index.ts +1 -1
  282. package/lib/routes/olevod/vod.ts +3 -0
  283. package/lib/routes/olevod/vodlist.ts +3 -0
  284. package/lib/routes/oreno3d/main.ts +1 -0
  285. package/lib/routes/oschina/column.ts +1 -2
  286. package/lib/routes/oschina/event.ts +1 -1
  287. package/lib/routes/osu/beatmaps/latest-ranked.ts +2 -3
  288. package/lib/routes/papers/category.ts +3 -4
  289. package/lib/routes/patreon/feed.ts +1 -0
  290. package/lib/routes/picuki/profile.ts +13 -5
  291. package/lib/routes/pixiv/bookmarks.ts +1 -0
  292. package/lib/routes/pixiv/illustfollow.ts +1 -0
  293. package/lib/routes/pixiv/novel-api/user-novels/sfw.ts +1 -1
  294. package/lib/routes/pixiv/novel-series.ts +17 -3
  295. package/lib/routes/pixiv/novels.ts +1 -0
  296. package/lib/routes/pixiv/ranking.ts +1 -0
  297. package/lib/routes/pixiv/search.ts +1 -0
  298. package/lib/routes/pixiv/user.ts +1 -0
  299. package/lib/routes/pixivision/utils.ts +1 -1
  300. package/lib/routes/pku/hr.ts +1 -1
  301. package/lib/routes/pku/scc/recruit.ts +1 -1
  302. package/lib/routes/pornhub/category-url.ts +1 -0
  303. package/lib/routes/pornhub/category.ts +1 -0
  304. package/lib/routes/pornhub/pornstar.ts +1 -0
  305. package/lib/routes/pornhub/search.ts +1 -0
  306. package/lib/routes/pornhub/users.ts +1 -0
  307. package/lib/routes/producthunt/templates/description.art +2 -2
  308. package/lib/routes/producthunt/today.ts +17 -8
  309. package/lib/routes/ps/trophy.ts +1 -1
  310. package/lib/routes/pubscholar/utils.ts +14 -1
  311. package/lib/routes/qq/lol/news.ts +1 -1
  312. package/lib/routes/qweather/3days.ts +14 -14
  313. package/lib/routes/qweather/now.ts +12 -10
  314. package/lib/routes/qweather/util.tsx +89 -0
  315. package/lib/routes/qwenlm/blog.ts +75 -0
  316. package/lib/routes/qwenlm/namespace.ts +6 -0
  317. package/lib/routes/radio-canada/latest.ts +30 -17
  318. package/lib/routes/rawkuma/manga.ts +1 -0
  319. package/lib/routes/ruc/ai.ts +1 -1
  320. package/lib/routes/ruc/hr.ts +1 -1
  321. package/lib/routes/samrdprc/index.ts +241 -0
  322. package/lib/routes/samrdprc/namespace.ts +1 -1
  323. package/lib/routes/scientificamerican/podcast.ts +2 -2
  324. package/lib/routes/scitechvista/index.ts +99 -0
  325. package/lib/routes/scitechvista/namespace.ts +7 -0
  326. package/lib/routes/scitechvista/templates/description.art +6 -0
  327. package/lib/routes/scoop/apps.ts +2 -4
  328. package/lib/routes/sdo/ff14risingstones/api.ts +78 -0
  329. package/lib/routes/sdo/ff14risingstones/constant.ts +338 -0
  330. package/lib/routes/sdo/ff14risingstones/posts.ts +80 -0
  331. package/lib/routes/sdo/ff14risingstones/strats.ts +75 -0
  332. package/lib/routes/sdo/ff14risingstones/templates/duties-party.art +41 -0
  333. package/lib/routes/sdo/ff14risingstones/templates/fc-party.art +26 -0
  334. package/lib/routes/sdo/ff14risingstones/templates/novice-network-party.art +9 -0
  335. package/lib/routes/sdo/ff14risingstones/templates/rp-party.art +15 -0
  336. package/lib/routes/sdo/ff14risingstones/timeline.ts +31 -0
  337. package/lib/routes/sdo/ff14risingstones/types/dynamic.ts +50 -0
  338. package/lib/routes/sdo/ff14risingstones/types/index.ts +3 -0
  339. package/lib/routes/sdo/ff14risingstones/types/other.ts +57 -0
  340. package/lib/routes/sdo/ff14risingstones/types/party.ts +111 -0
  341. package/lib/routes/sdo/ff14risingstones/user-dynamics.ts +32 -0
  342. package/lib/routes/sdo/ff14risingstones/user-posts.ts +32 -0
  343. package/lib/routes/sdo/ff14risingstones/user-resently.ts +38 -0
  344. package/lib/routes/sdo/ff14risingstones/user-strats.ts +32 -0
  345. package/lib/routes/sdo/ff14risingstones/utils.ts +215 -0
  346. package/lib/routes/sdo/namespace.ts +7 -0
  347. package/lib/routes/secretsanfrancisco/namespace.ts +7 -0
  348. package/lib/routes/secretsanfrancisco/rss.ts +101 -0
  349. package/lib/routes/secretsanfrancisco/templates/description.art +9 -0
  350. package/lib/routes/sehuatang/user.ts +1 -0
  351. package/lib/routes/showstart/utils.ts +1 -1
  352. package/lib/routes/shu/global.ts +6 -5
  353. package/lib/routes/shu/xxgk.ts +107 -0
  354. package/lib/routes/shuiguopai/index.ts +3 -0
  355. package/lib/routes/sis001/author.ts +1 -0
  356. package/lib/routes/sjtu/jwc.ts +1 -1
  357. package/lib/routes/skeb/following-creators.ts +1 -0
  358. package/lib/routes/skeb/following-works.ts +1 -0
  359. package/lib/routes/skeb/friend-works.ts +1 -0
  360. package/lib/routes/skeb/index.ts +1 -0
  361. package/lib/routes/skeb/search.ts +1 -0
  362. package/lib/routes/skeb/works.ts +44 -25
  363. package/lib/routes/skebetter/illust.ts +1 -0
  364. package/lib/routes/skebetter/index.ts +1 -0
  365. package/lib/routes/skebetter/manga.ts +1 -0
  366. package/lib/routes/sohu/mp.ts +1 -1
  367. package/lib/routes/sotwe/user.ts +1 -1
  368. package/lib/routes/sspai/index.ts +5 -1
  369. package/lib/routes/stcn/index.ts +1 -2
  370. package/lib/routes/stcn/rank.ts +1 -2
  371. package/lib/routes/surfshark/blog.ts +273 -77
  372. package/lib/routes/surfshark/templates/description.art +16 -4
  373. package/lib/routes/sustainabilitymag/articles.ts +1 -1
  374. package/lib/routes/syosetu/dev.ts +1 -1
  375. package/lib/routes/syosetu/ranking-isekai.ts +1 -1
  376. package/lib/routes/szse/disclosure/listed-notice.ts +44 -6
  377. package/lib/routes/t66y/post.ts +1 -0
  378. package/lib/routes/techcrunch/news.ts +1 -0
  379. package/lib/routes/techpowerup/index.ts +11 -11
  380. package/lib/routes/techpowerup/namespace.ts +1 -1
  381. package/lib/routes/techpowerup/review.ts +12 -12
  382. package/lib/routes/techpowerup/utils.ts +2 -2
  383. package/lib/routes/telegram/channel-media.ts +249 -0
  384. package/lib/routes/telegram/channel.ts +5 -4
  385. package/lib/routes/telegram/stories.ts +130 -0
  386. package/lib/routes/telegram/tglib/channel.ts +146 -117
  387. package/lib/routes/telegram/tglib/client.ts +37 -139
  388. package/lib/routes/tesla/cx.ts +1 -1
  389. package/lib/routes/test/index.ts +4 -0
  390. package/lib/routes/thegadgetflow/namespace.ts +7 -0
  391. package/lib/routes/thegadgetflow/rss.ts +99 -0
  392. package/lib/routes/thegadgetflow/templates/description.art +9 -0
  393. package/lib/routes/theverge/index.ts +20 -6
  394. package/lib/routes/threads/utils.ts +7 -3
  395. package/lib/routes/tidb/blog.ts +2 -2
  396. package/lib/routes/tmtpost/column.ts +1 -1
  397. package/lib/routes/toutiao/user.ts +2 -2
  398. package/lib/routes/trendforce/namespace.ts +9 -0
  399. package/lib/routes/trendforce/new.ts +113 -0
  400. package/lib/routes/tsinghua/news.ts +87 -0
  401. package/lib/routes/twitter/api/mobile-api/api.ts +1 -1
  402. package/lib/routes/twitter/api/web-api/api.ts +5 -1
  403. package/lib/routes/txrjy/fornumtopic.ts +2 -2
  404. package/lib/routes/typst/universe.ts +1 -1
  405. package/lib/routes/uber/blog.ts +87 -46
  406. package/lib/routes/uraaka-joshi/uraaka-joshi-user.ts +1 -0
  407. package/lib/routes/uraaka-joshi/uraaka-joshi.ts +3 -0
  408. package/lib/routes/wainao/topics.ts +1 -1
  409. package/lib/routes/wdfxw/bookfree.ts +1 -1
  410. package/lib/routes/weibo/utils.ts +17 -9
  411. package/lib/routes/wikipedia/current-events.ts +411 -0
  412. package/lib/routes/wikipedia/namespace.ts +7 -0
  413. package/lib/routes/wnacg/category.ts +3 -0
  414. package/lib/routes/wnacg/index.ts +3 -0
  415. package/lib/routes/wnacg/tag.ts +3 -0
  416. package/lib/routes/wohnnet/index.ts +2 -2
  417. package/lib/routes/xiaohongshu/user.ts +2 -2
  418. package/lib/routes/xiaohongshu/util.ts +16 -9
  419. package/lib/routes/xjtu/ee-jzxx.ts +1 -1
  420. package/lib/routes/xjtu/zs.ts +1 -1
  421. package/lib/routes/xsijishe/forum.ts +1 -0
  422. package/lib/routes/xsijishe/rank.ts +1 -0
  423. package/lib/routes/xwenming/index.ts +1 -1
  424. package/lib/routes/yahoo/news/utils.ts +7 -3
  425. package/lib/routes/ymgal/article.ts +1 -1
  426. package/lib/routes/yoasobi-music/media.ts +1 -1
  427. package/lib/routes/youtube/api/google.ts +20 -6
  428. package/lib/routes/youtube/api/subtitles.ts +86 -0
  429. package/lib/routes/youtube/api/youtubei.ts +7 -51
  430. package/lib/routes/youtube/channel.ts +1 -1
  431. package/lib/routes/youtube/community.ts +4 -4
  432. package/lib/routes/youtube/user.ts +1 -1
  433. package/lib/routes/yuanliao/index.ts +1 -1
  434. package/lib/routes/zaimanhua/comic.ts +1 -0
  435. package/lib/routes/zaimanhua/update.ts +1 -0
  436. package/lib/routes/zaker/utils.ts +1 -1
  437. package/lib/routes/zaobao/interactive.ts +18 -7
  438. package/lib/routes/zaobao/other.ts +3 -2
  439. package/lib/routes/zaobao/realtime.ts +3 -2
  440. package/lib/routes/zaobao/util.tsx +185 -0
  441. package/lib/routes/zaobao/zaobao.tsx +23 -0
  442. package/lib/routes/zaobao/znews.ts +3 -2
  443. package/lib/routes/zhihu/daily-section.ts +19 -24
  444. package/lib/routes/zhihu/daily.ts +8 -11
  445. package/lib/routes/zju/cse/index.ts +102 -0
  446. package/lib/routes/zodgame/forum.ts +1 -0
  447. package/lib/server.ts +1 -1
  448. package/lib/types.ts +1 -1
  449. package/lib/utils/puppeteer-utils.test.ts +5 -5
  450. package/lib/utils/puppeteer.test.ts +1 -1
  451. package/lib/views/index.tsx +4 -4
  452. package/package.json +55 -57
  453. package/lib/routes/gdufs/xwxy/xwxy-news.ts +0 -90
  454. package/lib/routes/hit/jwc.ts +0 -86
  455. package/lib/routes/picuki/utils.ts +0 -19
  456. package/lib/routes/qweather/templates/3days.art +0 -22
  457. package/lib/routes/qweather/templates/now.art +0 -16
  458. package/lib/routes/xinhuanet/app.ts +0 -109
  459. package/lib/routes/zaobao/templates/zaobao.art +0 -17
  460. package/lib/routes/zaobao/util.ts +0 -198
@@ -377,7 +377,7 @@ export const route: Route = {
377
377
  ],
378
378
  },
379
379
  },
380
- description: `:::tip
380
+ description: `::: tip
381
381
  订阅 [人工智能](https://banshujiang.cn//category/other/人工智能),其源网址为 \`https://banshujiang.cn//category/other/人工智能\`,请参考该 URL 指定部分构成参数,此时路由为 [\`/banshujiang/category/other/人工智能\`](https://rsshub.app/banshujiang/other/人工智能)。
382
382
  :::
383
383
 
@@ -174,7 +174,7 @@ export const route: Route = {
174
174
  ],
175
175
  },
176
176
  },
177
- description: `:::tip
177
+ description: `::: tip
178
178
  订阅 [今日谈](http://www.banyuetan.org/byt/jinritan/),其源网址为 \`http://www.banyuetan.org/byt/jinritan/\`,请参考该 URL 指定部分构成参数,此时路由为 [\`/banyuetan/jinritan\`](https://rsshub.app/banyuetan/jinritan)。
179
179
  :::
180
180
 
@@ -38,8 +38,8 @@ async function handler(ctx) {
38
38
  const response = await got(url);
39
39
  const $ = load(response.data);
40
40
  const comicTitle = $('div > div.pure-u-1-1.pure-u-sm-2-3.pure-u-md-3-4 > div > h1').text();
41
- const list = $('#layout > div.comics-detail > div:nth-child(3) > div > div.pure-g')
42
- .first() // 最新章节
41
+ const list = $('#chapter-items')
42
+ .first()
43
43
  .children()
44
44
  .toArray()
45
45
  .map((item) => {
@@ -52,8 +52,26 @@ async function handler(ctx) {
52
52
  };
53
53
  });
54
54
 
55
+ // more chapters
56
+ const otherList = $('#chapters_other_list')
57
+ .first()
58
+ .children()
59
+ .toArray()
60
+ .map((item) => {
61
+ const title = $(item).find('span').text();
62
+ const link = rootUrl + $(item).find('a').attr('href');
63
+
64
+ return {
65
+ title,
66
+ link,
67
+ };
68
+ });
69
+
70
+ const combinedList = [...list, ...otherList];
71
+ combinedList.reverse();
72
+
55
73
  const items = await Promise.all(
56
- list.map((item) =>
74
+ combinedList.map((item) =>
57
75
  cache.tryGet(item.link, async () => {
58
76
  const detailResponse = await got(item.link);
59
77
  const $ = load(detailResponse.data);
@@ -0,0 +1,117 @@
1
+ import { Route, type Data } from '@/types';
2
+ import ofetch from '@/utils/ofetch';
3
+ import { parseDate } from '@/utils/parse-date';
4
+ import InvalidParameterError from '@/errors/types/invalid-parameter';
5
+ import logger from '@/utils/logger';
6
+ import { Context } from 'hono';
7
+
8
+ type WordpressPost = {
9
+ id: number;
10
+ date: string;
11
+ date_gmt?: string;
12
+ link: string;
13
+ title?: { rendered?: string };
14
+ excerpt?: { rendered?: string };
15
+ content?: { rendered?: string };
16
+ _embedded?: {
17
+ author?: Array<{ name?: string }>;
18
+ 'wp:term'?: Array<Array<{ name?: string }>>;
19
+ };
20
+ };
21
+
22
+ const ROOT_URL = 'https://baselang.com';
23
+ const API_BASE = `${ROOT_URL}/wp-json/wp/v2`;
24
+
25
+ // Supported categories and their WP IDs
26
+ const CATEGORY_SLUG_TO_ID: Record<string, number> = {
27
+ 'advanced-grammar': 5,
28
+ 'basic-grammar': 4,
29
+ company: 8,
30
+ confidence: 9,
31
+ french: 24,
32
+ humor: 15,
33
+ medellin: 23,
34
+ motivation: 6,
35
+ pronunciation: 11,
36
+ 'study-tips': 7,
37
+ 'success-stories': 14,
38
+ travel: 13,
39
+ uncategorized: 1,
40
+ vocabulary: 12,
41
+ };
42
+
43
+ const CATEGORY_OPTIONS = Object.keys(CATEGORY_SLUG_TO_ID).map((slug) => ({ label: slug, value: slug }));
44
+
45
+ export const route: Route = {
46
+ path: '/blog/:category?',
47
+ categories: ['blog'],
48
+ example: '/baselang/blog',
49
+ parameters: {
50
+ category: {
51
+ description: 'Optional category filter',
52
+ options: CATEGORY_OPTIONS,
53
+ },
54
+ },
55
+ features: {
56
+ requireConfig: false,
57
+ requirePuppeteer: false,
58
+ antiCrawler: false,
59
+ supportBT: false,
60
+ supportPodcast: false,
61
+ supportScihub: false,
62
+ },
63
+ radar: [
64
+ {
65
+ source: ['baselang.com/blog', 'baselang.com/blog/:category'],
66
+ target: '/blog/:category',
67
+ },
68
+ ],
69
+ name: 'Blog',
70
+ maintainers: ['johan456789'],
71
+ handler,
72
+ };
73
+
74
+ async function handler(ctx: Context): Promise<Data> {
75
+ const categoryParam = (ctx.req.param('category') ?? '').toLowerCase();
76
+ logger.debug(`BaseLang: received request, category='${categoryParam || 'all'}'`);
77
+
78
+ if (categoryParam && !Object.hasOwn(CATEGORY_SLUG_TO_ID, categoryParam)) {
79
+ logger.debug(`BaseLang: invalid category '${categoryParam}'`);
80
+ throw new InvalidParameterError(`Invalid category: ${categoryParam}. Valid categories are: ${Object.keys(CATEGORY_SLUG_TO_ID).join(', ')}`);
81
+ }
82
+
83
+ const searchParams: string[] = ['per_page=20', '_embed=author,wp:term'];
84
+ if (categoryParam) {
85
+ const id = CATEGORY_SLUG_TO_ID[categoryParam];
86
+ searchParams.push(`categories=${id}`);
87
+ }
88
+
89
+ const apiUrl = `${API_BASE}/posts?${searchParams.join('&')}`;
90
+
91
+ const data = await ofetch<WordpressPost[]>(apiUrl);
92
+ logger.debug(`BaseLang: fetched ${data.length} posts`);
93
+
94
+ const items = data.map((post) => ({
95
+ title: post.title?.rendered,
96
+ description: post.content?.rendered ?? post.excerpt?.rendered ?? '',
97
+ link: post.link,
98
+ pubDate: parseDate(post.date_gmt ?? post.date),
99
+ author: post._embedded?.author?.[0]?.name,
100
+ category: Array.isArray(post._embedded?.['wp:term'])
101
+ ? post._embedded['wp:term']
102
+ .flat()
103
+ .map((term: any) => term?.name)
104
+ .filter(Boolean)
105
+ : undefined,
106
+ }));
107
+
108
+ const titleSuffix = categoryParam ? ` - ${categoryParam}` : '';
109
+ const link = categoryParam ? `${ROOT_URL}/blog/${categoryParam}/` : `${ROOT_URL}/blog/`;
110
+
111
+ return {
112
+ title: `BaseLang Blog${titleSuffix}`,
113
+ link,
114
+ language: 'en',
115
+ item: items,
116
+ } as Data;
117
+ }
@@ -0,0 +1,6 @@
1
+ import type { Namespace } from '@/types';
2
+
3
+ export const namespace: Namespace = {
4
+ name: 'BaseLang',
5
+ lang: 'en',
6
+ };
@@ -1,8 +1,22 @@
1
- import { Route } from '@/types';
1
+ import type { DataItem, Route } from '@/types';
2
2
  import cache from '@/utils/cache';
3
3
  import { load } from 'cheerio';
4
4
  import ofetch from '@/utils/ofetch';
5
5
  import { parseDate } from '@/utils/parse-date';
6
+ import { type Context } from 'hono';
7
+
8
+ const channelMap = {
9
+ 'take-away-english': '随身英语',
10
+ 'authentic-real-english': '地道英语',
11
+ 'media-english': '媒体英语',
12
+ lingohack: '英语大破解',
13
+ 'english-in-a-minute': '一分钟英语',
14
+ 'phrasal-verbs': '短语动词',
15
+ 'todays-phrase': '今日短语',
16
+ 'q-and-a': '你问我答',
17
+ 'english-at-work': '白领英语',
18
+ storytellers: '亲子英语故事',
19
+ };
6
20
 
7
21
  export const route: Route = {
8
22
  name: 'Learning English',
@@ -12,18 +26,15 @@ export const route: Route = {
12
26
  path: '/learningenglish/:channel?',
13
27
  example: '/bbc/learningenglish/take-away-english',
14
28
  parameters: {
15
- channel: 'channel, default to `take-away-english`',
29
+ channel: {
30
+ description: '英语学习分类栏目',
31
+ options: Object.entries(channelMap).map(([value, label]) => ({ value, label })),
32
+ default: 'take-away-english',
33
+ },
16
34
  },
17
- description: `| 随身英语 | 地道英语 | 媒体英语 | 英语大破解 | 一分钟英语 |
18
- | -------- | -------- | -------- | -------- | -------- |
19
- | take-away-english | authentic-real-english | media-english | lingohack | english-in-a-minute |
20
-
21
- | 短语动词 | 今日短语 | 你问我答 | 白领英语 | 亲子英语故事 |
22
- | -------- | -------- | -------- | -------- | -------- |
23
- | phrasal-verbs | todays-phrase | q-and-a | english-at-work | storytellers |`,
24
35
  };
25
36
 
26
- async function handler(ctx) {
37
+ async function handler(ctx: Context) {
27
38
  // set targetURL
28
39
  const { channel = 'take-away-english' } = ctx.req.param();
29
40
 
@@ -34,14 +45,14 @@ async function handler(ctx) {
34
45
  const $ = load(response);
35
46
 
36
47
  // get top article links
37
- const firstItem = {
48
+ const firstItem: DataItem = {
38
49
  title: $('[data-widget-index=4]').find('h2').text(),
39
50
  link: `${rootURL}${$('[data-widget-index=4]').find('h2 a').attr('href')}`,
40
51
  pubDate: parseDate($('[data-widget-index=4]').find('.details h3').text()),
41
52
  };
42
53
 
43
54
  // get rest ul article links
44
- const restItems = $('.threecol li')
55
+ const restItems: DataItem[] = $('.threecol li')
45
56
  .toArray()
46
57
  .slice(0, 10)
47
58
  .map((article) => {
@@ -55,21 +66,25 @@ async function handler(ctx) {
55
66
  });
56
67
 
57
68
  // try get article content detail
58
- const items = await Promise.all(
59
- [firstItem, ...restItems].map((item) =>
60
- cache.tryGet(item.link, async () => {
61
- const detailResponse = await ofetch(item.link, { parseResponse: (txt) => txt });
69
+ const items: DataItem[] = await Promise.all(
70
+ [firstItem, ...restItems].map((item) => {
71
+ if (!item.link) {
72
+ return item;
73
+ }
74
+
75
+ return cache.tryGet(item.link, async (): Promise<DataItem> => {
76
+ const detailResponse = await ofetch(item.link!, { parseResponse: (txt) => txt });
62
77
 
63
78
  const $content = load(detailResponse);
64
79
 
65
- item.description = $content('.widget-richtext').html();
80
+ item.description = $content('.widget-richtext').html() ?? undefined;
66
81
  return item;
67
- })
68
- )
82
+ });
83
+ })
69
84
  );
70
85
 
71
86
  return {
72
- title: `Learningenglish-${channel}-BBC`,
87
+ title: `BBC英语学习-${channelMap[channel]}`,
73
88
  link: targerURL,
74
89
  item: items,
75
90
  };
@@ -0,0 +1,137 @@
1
+ import path from 'node:path';
2
+ import { load } from 'cheerio';
3
+ import { Route, ViewType } from '@/types';
4
+ import ofetch from '@/utils/ofetch';
5
+ import cache from '@/utils/cache';
6
+ import { art } from '@/utils/render';
7
+
8
+ const BASEURL = 'https://bestofjs.org/rankings/monthly';
9
+
10
+ export const route: Route = {
11
+ path: '/rankings/monthly',
12
+ categories: ['programming'],
13
+ example: '/bestofjs/rankings/monthly',
14
+ view: ViewType.Notifications,
15
+ features: {
16
+ requireConfig: false,
17
+ requirePuppeteer: false,
18
+ antiCrawler: false,
19
+ supportBT: false,
20
+ supportPodcast: false,
21
+ supportScihub: false,
22
+ },
23
+ radar: [
24
+ {
25
+ source: ['bestofjs.org/rankings/monthly/:year/:month'],
26
+ target: '/rankings/monthly',
27
+ },
28
+ ],
29
+ name: 'Monthly Rankings',
30
+ maintainers: ['ztkuaikuai'],
31
+ url: 'bestofjs.org/rankings/monthly',
32
+ handler: async () => {
33
+ const targetMonths = getLastSixMonths();
34
+ const allNeededMonthlyRankings = await Promise.all(
35
+ targetMonths.map((data) => {
36
+ const [year, month] = data.split('-');
37
+ return getMonthlyRankings(year, month);
38
+ })
39
+ );
40
+ const items = allNeededMonthlyRankings.flatMap((oneMonthlyRankings, i) => {
41
+ const [year, month] = targetMonths[i].split('-');
42
+ const description = art(path.join(__dirname, 'templates/description.art'), { items: oneMonthlyRankings });
43
+ return {
44
+ title: `Best of JS Monthly Rankings - ${year}/${month}`,
45
+ description,
46
+ link: `${BASEURL}/${year}/${month}`,
47
+ guid: `${BASEURL}/${year}/${month}`,
48
+ author: 'Best of JS',
49
+ };
50
+ });
51
+
52
+ return {
53
+ title: 'Best of JS Monthly Rankings',
54
+ link: BASEURL,
55
+ description: 'Monthly rankings of the most popular JavaScript projects on Best of JS',
56
+ item: items,
57
+ language: 'en',
58
+ };
59
+ },
60
+ };
61
+
62
+ const getLastSixMonths = (): string[] => {
63
+ const now = new Date();
64
+ const currentYear = now.getFullYear();
65
+ const currentMonth = now.getMonth() + 1; // 0-based to 1-based
66
+ return Array.from({ length: 6 }, (_, i) => {
67
+ let month = currentMonth - (i + 1);
68
+ let year = currentYear;
69
+ if (month <= 0) {
70
+ month += 12;
71
+ year -= 1;
72
+ }
73
+ return `${year}-${month}`;
74
+ });
75
+ };
76
+
77
+ interface RankingItem {
78
+ logo: string;
79
+ projectName: string;
80
+ githubLink: string;
81
+ homepageLink: string;
82
+ description: string;
83
+ tags: string[];
84
+ starCount: string;
85
+ additionalInfo: string;
86
+ }
87
+
88
+ const getMonthlyRankings = (year: string, month: string): Promise<RankingItem[]> => {
89
+ const targetUrl = `${BASEURL}/${year}/${month}`;
90
+ return cache.tryGet(targetUrl, async () => {
91
+ const response = await ofetch(targetUrl);
92
+ const $ = load(response);
93
+ return $('table.w-full tbody tr[data-testid="project-card"]')
94
+ .toArray()
95
+ .map((el) => {
96
+ const $tr = $(el);
97
+ // Project logo
98
+ const logo =
99
+ $tr
100
+ .find('td:first img')
101
+ .attr('src')
102
+ ?.replace(/.dark./, '.') || '';
103
+ // Project name and link
104
+ const projectLink = $tr.find('td:nth-child(2) a[href^="/projects/"]').first();
105
+ const projectName = projectLink.text().trim();
106
+ // GitHub and homepage links
107
+ const githubLink = $tr.find('td:nth-child(2) a[href*="github.com"]').attr('href') || '';
108
+ const homepageLink = $tr.find('td:nth-child(2) a[href*="http"]:not([href*="github.com"])').attr('href') || '';
109
+ // Description
110
+ const description = $tr.find('td:nth-child(2) .font-serif').text().trim();
111
+ // Tags
112
+ const tags = $tr
113
+ .find('td:nth-child(2) [href*="/projects?tags="]')
114
+ .toArray()
115
+ .map((tag) => $(tag).text().trim());
116
+ // Star count
117
+ const starCount = $tr.find('td:nth-child(4) span:last').text().trim() || $tr.find('td:nth-child(2) .inline-flex span:last-child').text().trim();
118
+ // Additional info (contributors, created date)
119
+ const additionalInfo = $tr
120
+ .find('td:nth-child(3) > div')
121
+ .toArray()
122
+ .slice(1)
123
+ .map((el) => $(el).text().trim())
124
+ .join('; ');
125
+ return {
126
+ logo,
127
+ projectName,
128
+ githubLink,
129
+ homepageLink,
130
+ description,
131
+ tags,
132
+ starCount,
133
+ additionalInfo,
134
+ };
135
+ });
136
+ });
137
+ };
@@ -0,0 +1,7 @@
1
+ import type { Namespace } from '@/types';
2
+
3
+ export const namespace: Namespace = {
4
+ name: 'Best of JS',
5
+ url: 'bestofjs.org',
6
+ lang: 'en',
7
+ };
@@ -0,0 +1,36 @@
1
+ <ul>
2
+ {{each items item index}}
3
+ <li>
4
+ <p><strong>Rank {{index + 1}}</strong></p>
5
+ {{if item.logo}}
6
+ <img src="https://bestofjs.org{{item.logo}}" alt="{{item.projectName}}" height="32" width="32" />
7
+ {{/if}}
8
+ {{if item.projectName}}
9
+ <p><strong>Project:</strong> {{item.projectName}}</p>
10
+ {{/if}}
11
+ {{if item.description}}
12
+ <p>{{item.description}}</p>
13
+ {{/if}}
14
+ {{if item.starCount}}
15
+ <p><strong>Stars:</strong> {{item.starCount}}</p>
16
+ {{/if}}
17
+ {{if item.additionalInfo}}
18
+ <p><strong>Additional Info:</strong> {{item.additionalInfo}}</p>
19
+ {{/if}}
20
+ {{if item.githubLink}}
21
+ <p><strong>GitHub:</strong> <a href="{{item.githubLink}}">{{item.githubLink}}</a></p>
22
+ {{/if}}
23
+ {{if item.homepageLink}}
24
+ <p><strong>Homepage:</strong> <a href="{{item.homepageLink}}">{{item.homepageLink}}</a></p>
25
+ {{/if}}
26
+ {{if item.tags && item.tags.length}}
27
+ <p><strong>Tags:</strong>
28
+ {{each item.tags tag tIndex}}
29
+ <a href="/projects?tags={{tag.toLowerCase()}}">{{tag}}</a>{{if tIndex < item.tags.length - 1}}, {{/if}}
30
+ {{/each}}
31
+ </p>
32
+ {{/if}}
33
+ </li>
34
+ <br />
35
+ {{/each}}
36
+ </ul>
@@ -6,6 +6,17 @@ import { config } from '@/config';
6
6
  import logger from '@/utils/logger';
7
7
  import { getPuppeteerPage } from '@/utils/puppeteer';
8
8
  import { JSDOM } from 'jsdom';
9
+ import { RateLimiterMemory, RateLimiterQueue } from 'rate-limiter-flexible';
10
+
11
+ const subtitleLimiter = new RateLimiterMemory({
12
+ points: 5,
13
+ duration: 1,
14
+ execEvenly: true,
15
+ });
16
+
17
+ const subtitleLimiterQueue = new RateLimiterQueue(subtitleLimiter, {
18
+ maxQueueSize: 4800,
19
+ });
9
20
 
10
21
  const getCookie = (disableConfig = false) => {
11
22
  if (Object.keys(config.bilibili.cookies).length > 0 && !disableConfig) {
@@ -200,7 +211,7 @@ const getCidFromId = (aid, pid, bvid) => {
200
211
  const { data } = await got(`https://api.bilibili.com/x/web-interface/view?${bvid ? `bvid=${bvid}` : `aid=${aid}`}`, {
201
212
  referer: `https://www.bilibili.com/video/${bvid || `av${aid}`}`,
202
213
  });
203
- return data.data.pages[pid - 1].cid;
214
+ return data?.data?.pages[pid - 1]?.cid;
204
215
  });
205
216
  };
206
217
 
@@ -244,8 +255,13 @@ const getVideoSubtitle = async (
244
255
  }
245
256
 
246
257
  const cid = await getCidFromId(undefined, 1, bvid);
258
+ if (!cid) {
259
+ return [];
260
+ }
261
+
247
262
  const cookie = await getCookie();
248
263
  return cache.tryGet(`bili-video-subtitle-${bvid}`, async () => {
264
+ await subtitleLimiterQueue.removeTokens(1);
249
265
  const response = await got(`https://api.bilibili.com/x/player/wbi/v2?bvid=${bvid}&cid=${cid}`, {
250
266
  headers: {
251
267
  Referer: `https://www.bilibili.com/video/${bvid}`,
@@ -9,6 +9,7 @@ import cacheIn from './cache';
9
9
  import { BilibiliWebDynamicResponse, Item2, Modules } from './api-interface';
10
10
  import { parseDuration } from '@/utils/helpers';
11
11
  import { config } from '@/config';
12
+ import CaptchaError from '@/errors/types/captcha';
12
13
 
13
14
  export const route: Route = {
14
15
  path: '/user/dynamic/:uid/:routeParams?',
@@ -125,34 +126,58 @@ const getIframe = (data?: Modules, embed: boolean = true) => {
125
126
  };
126
127
 
127
128
  const getImgs = (data?: Modules) => {
128
- const imgUrls: string[] = [];
129
+ const imgUrls: {
130
+ url: string;
131
+ width?: number;
132
+ height?: number;
133
+ }[] = [];
129
134
  const major = data?.module_dynamic?.major;
130
135
  if (!major) {
131
136
  return '';
132
137
  }
133
138
  // 动态图片
134
139
  if (major.opus?.pics?.length) {
135
- imgUrls.push(...major.opus.pics.map((e) => e.url));
140
+ imgUrls.push(
141
+ ...major.opus.pics.map((e) => ({
142
+ url: e.url,
143
+ width: e.width,
144
+ height: e.height,
145
+ }))
146
+ );
136
147
  }
137
148
  // 专栏封面
138
149
  if (major.article?.covers?.length) {
139
- imgUrls.push(...major.article.covers);
150
+ imgUrls.push(
151
+ ...major.article.covers.map((e) => ({
152
+ url: e,
153
+ }))
154
+ );
140
155
  }
141
156
  // 相簿
142
157
  if (major.draw?.items?.length) {
143
- imgUrls.push(...major.draw.items.map((e) => e.src));
158
+ imgUrls.push(
159
+ ...major.draw.items.map((e) => ({
160
+ url: e.src,
161
+ width: e.width,
162
+ height: e.height,
163
+ }))
164
+ );
144
165
  }
145
166
  // 正在直播的动态
146
167
  if (major.live_rcmd?.content) {
147
- imgUrls.push(JSON.parse(major.live_rcmd.content)?.live_play_info?.cover);
168
+ imgUrls.push({
169
+ url: JSON.parse(major.live_rcmd.content)?.live_play_info?.cover,
170
+ });
148
171
  }
149
172
  const type = major.type.replace('MAJOR_TYPE_', '').toLowerCase();
150
173
  if (major[type]?.cover) {
151
- imgUrls.push(major[type].cover);
174
+ imgUrls.push({
175
+ url: major[type]?.cover,
176
+ });
152
177
  }
153
178
  return imgUrls
154
179
  .filter(Boolean)
155
- .map((url) => `<img src="${url}">`)
180
+ .map((img) => `<img src="${img.url}" ${img.width ? `width="${img.width}"` : ''} ${img.height ? `height="${img.height}"` : ''}>`)
156
181
  .join('');
157
182
  };
158
183
 
@@ -266,7 +291,8 @@ async function handler(ctx) {
266
291
  body = await getDynamic(cookie);
267
292
 
268
293
  if (body?.code === -352) {
269
- throw new Error('遇到源站风控校验,请稍后再试');
294
+ cache.set('bili-cookie', '');
295
+ throw new CaptchaError('遇到源站风控校验,请稍后再试');
270
296
  }
271
297
  }
272
298
  const items = (body as BilibiliWebDynamicResponse)?.data?.items;
@@ -45,7 +45,7 @@ async function handler(ctx) {
45
45
  link,
46
46
  description: `视频 ${name} 的视频选集列表`,
47
47
  item: data
48
- .sort((a, b) => b.page - a.page)
48
+ .toSorted((a, b) => b.page - a.page)
49
49
  .slice(0, ctx.req.query('limit') ? Number.parseInt(ctx.req.query('limit')) : 10)
50
50
  .map((item) => ({
51
51
  title: item.part,
@@ -2,6 +2,8 @@ import { Route, ViewType } from '@/types';
2
2
  import got from '@/utils/got';
3
3
  import utils, { getVideoUrl } from './utils';
4
4
  import { parseDuration } from '@/utils/helpers';
5
+ import { config } from '@/config';
6
+ import cache from './cache';
5
7
 
6
8
  // https://www.bilibili.com/v/popular/rank/all
7
9
 
@@ -212,22 +214,28 @@ async function handler(ctx) {
212
214
  return {
213
215
  title: `bilibili 排行榜-${ridChinese}`,
214
216
  link,
215
- item: list.map((item) => ({
216
- title: item.title,
217
- description: utils.renderUGCDescription(embed, item.pic, item.description || item.title, item.aid, undefined, item.bvid),
218
- pubDate: item.create && new Date(item.create).toUTCString(),
219
- author: item.author,
220
- link: !item.create || (new Date(item.create).getTime() / 1000 > utils.bvidTime && item.bvid) ? `https://www.bilibili.com/video/${item.bvid}` : `https://www.bilibili.com/video/av${item.aid}`,
221
- image: item.pic,
222
- attachments: item.bvid
223
- ? [
224
- {
225
- url: getVideoUrl(item.bvid),
226
- mime_type: 'text/html',
227
- duration_in_seconds: parseDuration(item.duration),
228
- },
229
- ]
230
- : undefined,
231
- })),
217
+ item: await Promise.all(
218
+ list.map(async (item) => {
219
+ const subtitles = !config.bilibili.excludeSubtitles && item.bvid ? await cache.getVideoSubtitleAttachment(item.bvid) : [];
220
+ return {
221
+ title: item.title,
222
+ description: utils.renderUGCDescription(embed, item.pic, item.description || item.title, item.aid, undefined, item.bvid),
223
+ pubDate: item.create && new Date(item.create).toUTCString(),
224
+ author: item.author,
225
+ link: !item.create || (new Date(item.create).getTime() / 1000 > utils.bvidTime && item.bvid) ? `https://www.bilibili.com/video/${item.bvid}` : `https://www.bilibili.com/video/av${item.aid}`,
226
+ image: item.pic,
227
+ attachments: item.bvid
228
+ ? [
229
+ {
230
+ url: getVideoUrl(item.bvid),
231
+ mime_type: 'text/html',
232
+ duration_in_seconds: parseDuration(item.duration),
233
+ },
234
+ ...subtitles,
235
+ ]
236
+ : undefined,
237
+ };
238
+ })
239
+ ),
232
240
  };
233
241
  }
@@ -595,7 +595,7 @@
595
595
  }
596
596
  argvPtrs.push(0);
597
597
 
598
- const keys = Object.keys(this.env).sort();
598
+ const keys = Object.keys(this.env).toSorted();
599
599
  for (const key of keys) {
600
600
  argvPtrs.push(strPtr(`${key}=${this.env[key]}`));
601
601
  }