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
@@ -0,0 +1,9 @@
1
+ {{ if image }}
2
+ <figure>
3
+ <img src="{{ image }}" alt="{{ altText }}">
4
+ <figcaption>{{ caption }}</figcaption>
5
+ </figure>
6
+ {{ /if }}
7
+ {{ if content }}
8
+ {{@ content }}
9
+ {{ /if }}
@@ -6,6 +6,10 @@ import { load } from 'cheerio';
6
6
  import path from 'node:path';
7
7
  import { art } from '@/utils/render';
8
8
 
9
+ const excludeTypes = new Set(['NewsletterBlockType', 'RelatedPostsBlockType', 'ProductsTableBlockType', 'TableOfContentsBlockType']);
10
+
11
+ const shouldKeep = (b: any) => !excludeTypes.has(b.__typename.trim());
12
+
9
13
  export const route: Route = {
10
14
  path: '/:hub?',
11
15
  categories: ['new-media'],
@@ -46,6 +50,9 @@ export const route: Route = {
46
50
  };
47
51
 
48
52
  const renderBlock = (b) => {
53
+ if (!shouldKeep(b)) {
54
+ return '';
55
+ }
49
56
  switch (b.__typename) {
50
57
  case 'CoreEmbedBlockType':
51
58
  return b.embedHtml;
@@ -60,7 +67,7 @@ const renderBlock = (b) => {
60
67
  case 'CoreListBlockType':
61
68
  return `${b.ordered ? '<ol>' : '<ul>'}${b.items.map((i) => `<li>${i.contents.html}</li>`).join('')}${b.ordered ? '</ol>' : '</ul>'}`;
62
69
  case 'CoreParagraphBlockType':
63
- return b.contents.html;
70
+ return b.tempContents.map((c) => c.html).join('');
64
71
  case 'CorePullquoteBlockType':
65
72
  return `<blockquote>${b.contents.html}</blockquote>`;
66
73
  case 'CoreQuoteBlockType':
@@ -69,15 +76,25 @@ const renderBlock = (b) => {
69
76
  return '<hr>';
70
77
  case 'HighlightBlockType':
71
78
  return b.children.map((c) => renderBlock(c)).join('');
79
+ case 'ImageCompareBlockType':
80
+ return `<figure><img src="${b.leftImage.thumbnails.horizontal.url.split('?')[0]}" alt="${b.leftImage.alt}" /><img src="${b.rightImage.thumbnails.horizontal.url.split('?')[0]}" alt="${b.rightImage.alt}" /><figcaption>${b.caption.html}</figcaption></figure>`;
81
+ case 'ImageSliderBlockType':
82
+ return b.images.map((i) => `<figure><img src="${i.image.originalUrl.split('?')[0]}" alt="${i.alt}" /><figcaption>${i.caption.html}</figcaption></figure>`).join('');
72
83
  case 'MethodologyAccordionBlockType':
73
84
  return `<h2>${b.heading.html}</h2>${b.sections.map((s) => `<h3>${s.heading.html}</h3>${s.content.html}`).join('')}`;
85
+ case 'ProductBlockType': {
86
+ const product = b.product;
87
+ return `<div><figure><img src="${product.image.thumbnails.horizontal.url.split('?')[0]}" alt="${product.image.alt}" /><figcaption>${product.image.alt}</figcaption></figure><br><a href="${product.bestRetailLink.url}">${product.title} $${product.bestRetailLink.price}</a><br>${product.description.html}${product.pros.html ? `<br>The Good${product.pros.html}The Bad${product.cons.html}` : ''}</div>`;
88
+ }
89
+ case 'TableBlockType':
90
+ return `<table><tr>${b.header.map((cell) => `<th>${cell}</th>`).join('')}</tr>${b.rows.map((row) => `<tr>${row.map((cell) => `<td>${cell}</td>`).join('')}</tr>`).join('')}</table>`;
74
91
  default:
75
92
  throw new Error(`Unsupported block type: ${b.__typename}`);
76
93
  }
77
94
  };
78
95
 
79
96
  async function handler(ctx) {
80
- const link = ctx.req.param('hub') ? `https://www.theverge.com/${ctx.req.param('hub')}/rss/index.xml` : 'https://www.theverge.com/rss/index.xml';
97
+ const link = ctx.req.param('hub') ? `https://www.theverge.com/rss/${ctx.req.param('hub')}/index.xml` : 'https://www.theverge.com/rss/index.xml';
81
98
 
82
99
  const feed = await parser.parseURL(link);
83
100
 
@@ -96,10 +113,7 @@ async function handler(ctx) {
96
113
  ledeMediaData: node.ledeMediaData,
97
114
  });
98
115
 
99
- description += node.blocks
100
- .filter((b) => b.__typename !== 'NewsletterBlockType' && b.__typename !== 'RelatedPostsBlockType' && b.__typename !== 'ProductBlockType' && b.__typename !== 'TableOfContentsBlockType')
101
- .map((b) => renderBlock(b))
102
- .join('<br><br>');
116
+ description += node.blocks.map((b) => renderBlock(b)).join('<br><br>');
103
117
 
104
118
  if (node.__typename === 'StreamResourceType') {
105
119
  description += node.posts.edges
@@ -78,10 +78,14 @@ const getUserId = (user: string): Promise<string> =>
78
78
  throw new NotFoundError('User ID not found');
79
79
  })
80
80
  .then((result): string => {
81
- if (!result || typeof result !== 'string') {
82
- throw new TypeError('Invalid user ID type');
81
+ if (result) {
82
+ if (typeof result === 'string') {
83
+ return result;
84
+ } else if (typeof result === 'number') {
85
+ return result.toString();
86
+ }
83
87
  }
84
- return result;
88
+ throw new TypeError('Invalid user ID type');
85
89
  });
86
90
 
87
91
  const hasMedia = (post) => post.image_versions2 || post.carousel_media || post.video_versions;
@@ -7,7 +7,7 @@ import { parseDate } from '@/utils/parse-date';
7
7
  import { type CheerioAPI, load } from 'cheerio';
8
8
  import { type Context } from 'hono';
9
9
 
10
- const escapeHtml = (text: string): string => text?.replace(/&/g, '&amp;')?.replace(/</g, '&lt;')?.replace(/>/g, '&gt;')?.replace(/'/g, '&quot;')?.replace(/'/g, '&#039;') ?? text;
10
+ const escapeHtml = (text: string): string => text?.replaceAll('&', '&amp;')?.replaceAll('<', '&lt;')?.replaceAll('>', '&gt;')?.replaceAll("'", '&quot;')?.replaceAll("'", '&#039;') ?? text;
11
11
 
12
12
  const parseTextChildren = (children: any[]): string => children.map((child: any) => escapeHtml(child.text)).join('');
13
13
 
@@ -240,7 +240,7 @@ export const route: Route = {
240
240
  ],
241
241
  },
242
242
  },
243
- description: `:::tip
243
+ description: `::: tip
244
244
  订阅 [管理与运维](https://tidb.net/blog/c/management-and-operation),其源网址为 \`https://tidb.net/blog/c/management-and-operation\`,请参考该 URL 指定部分构成参数,此时路由为 [\`/tidb/blog/c/management-and-operation\`](https://rsshub.app/tidb/blog/c/management-and-operation)。
245
245
  :::
246
246
 
@@ -129,7 +129,7 @@ export const route: Route = {
129
129
  ],
130
130
  },
131
131
  },
132
- description: `:::tip
132
+ description: `::: tip
133
133
  若订阅 [AGI](https://www.tmtpost.com/column/6916385),网址为 \`https://www.tmtpost.com/column/6916385\`,请截取 \`https://www.tmtpost.com/column\` 到末尾的部分 \`6916385\` 作为 \`id\` 参数填入,此时目标路由为 [\`/tmtpost/column/6916385\`](https://rsshub.app/tmtpost/column/6916385)。
134
134
  :::
135
135
 
@@ -57,12 +57,12 @@ async function handler(ctx) {
57
57
  switch (item.cell_type) {
58
58
  case 0:
59
59
  case 49: {
60
- const video = item.video.play_addr_list.sort((a, b) => b.bitrate - a.bitrate)[0];
60
+ const video = item.video.play_addr_list.toSorted((a, b) => b.bitrate - a.bitrate)[0];
61
61
  return {
62
62
  title: item.title,
63
63
  description: art(path.join(__dirname, 'templates/video.art'), {
64
64
  poster: item.video.origin_cover.url_list[0],
65
- url: item.video.play_addr_list.sort((a, b) => b.bitrate - a.bitrate)[0].play_url_list[0],
65
+ url: item.video.play_addr_list.toSorted((a, b) => b.bitrate - a.bitrate)[0].play_url_list[0],
66
66
  }),
67
67
  link: `https://www.toutiao.com/video/${item.id}/`,
68
68
  pubDate: parseDate(item.publish_time, 'X'),
@@ -0,0 +1,9 @@
1
+ import type { Namespace } from '@/types';
2
+
3
+ export const namespace: Namespace = {
4
+ name: 'TrendForce',
5
+ url: 'trendforce.com',
6
+ categories: ['new-media'],
7
+ description: '',
8
+ lang: 'en',
9
+ };
@@ -0,0 +1,113 @@
1
+ import { type Data, type DataItem, type Route, ViewType } from '@/types';
2
+
3
+ import ofetch from '@/utils/ofetch';
4
+ import { parseDate } from '@/utils/parse-date';
5
+
6
+ import { type CheerioAPI, load } from 'cheerio';
7
+ import { type Context } from 'hono';
8
+
9
+ export const handler = async (ctx: Context): Promise<Data> => {
10
+ const limit: number = Number.parseInt(ctx.req.query('limit') ?? '10', 10);
11
+
12
+ const apiSlug = 'wp-json/wp/v2';
13
+ const baseUrl: string = 'https://www.trendforce.com';
14
+ const targetUrl: string = new URL('news/', baseUrl).href;
15
+ const apiUrl = new URL(`${apiSlug}/posts`, targetUrl).href;
16
+
17
+ const response = await ofetch(apiUrl, {
18
+ query: {
19
+ _embed: 'true',
20
+ per_page: limit,
21
+ },
22
+ });
23
+
24
+ const targetResponse = await ofetch(targetUrl);
25
+ const $: CheerioAPI = load(targetResponse);
26
+ const language = $('html').attr('lang') ?? 'en';
27
+
28
+ const items: DataItem[] = response.slice(0, limit).map((item): DataItem => {
29
+ const title: string = item.title?.rendered ?? item.title;
30
+
31
+ const $$: CheerioAPI = load(item.content.rendered);
32
+
33
+ $$('div.article_highlight-area-BG_wrap').remove();
34
+
35
+ const description: string | undefined = $$.html();
36
+ const pubDate: number | string = item.date_gmt;
37
+ const linkUrl: string | undefined = item.link;
38
+
39
+ const terminologies = item._embedded?.['wp:term'];
40
+
41
+ const categories: string[] = terminologies?.flat().map((c) => c.name) ?? [];
42
+ const authors: DataItem['author'] =
43
+ item._embedded?.author.map((author) => ({
44
+ name: author.name,
45
+ url: author.url,
46
+ avatar: undefined,
47
+ })) ?? [];
48
+ const guid: string = item.guid?.rendered ?? item.guid;
49
+ const image: string | undefined = item._embedded?.['wp:featuredmedia']?.[0].source_url ?? undefined;
50
+ const updated: number | string = item.modified_gmt ?? pubDate;
51
+
52
+ const processedItem: DataItem = {
53
+ title,
54
+ description,
55
+ pubDate: pubDate ? parseDate(pubDate) : undefined,
56
+ link: linkUrl ?? guid,
57
+ category: categories,
58
+ author: authors,
59
+ guid,
60
+ id: guid,
61
+ content: {
62
+ html: description,
63
+ text: description,
64
+ },
65
+ image,
66
+ banner: image,
67
+ updated: updated ? parseDate(updated) : undefined,
68
+ language,
69
+ };
70
+
71
+ return processedItem;
72
+ });
73
+
74
+ return {
75
+ title: $('title').text(),
76
+ description: $('meta[property="og:description"]').attr('content'),
77
+ link: targetUrl,
78
+ item: items,
79
+ allowEmpty: true,
80
+ image: $('meta[property="og:image"]').attr('content'),
81
+ author: $('meta[property="og:site_name"]').attr('content'),
82
+ language,
83
+ id: targetUrl,
84
+ };
85
+ };
86
+
87
+ export const route: Route = {
88
+ path: '/news',
89
+ name: 'News',
90
+ url: 'www.trendforce.com',
91
+ maintainers: ['nczitzk'],
92
+ handler,
93
+ example: '/trendforce/news',
94
+ parameters: undefined,
95
+ description: undefined,
96
+ categories: ['new-media'],
97
+ features: {
98
+ requireConfig: false,
99
+ requirePuppeteer: false,
100
+ antiCrawler: false,
101
+ supportRadar: true,
102
+ supportBT: false,
103
+ supportPodcast: false,
104
+ supportScihub: false,
105
+ },
106
+ radar: [
107
+ {
108
+ source: ['www.trendforce.com/news/'],
109
+ target: '/news',
110
+ },
111
+ ],
112
+ view: ViewType.Articles,
113
+ };
@@ -0,0 +1,87 @@
1
+ import { Route } from '@/types';
2
+ import ofetch from '@/utils/ofetch';
3
+ import { load } from 'cheerio';
4
+ import cache from '@/utils/cache';
5
+ import { parseDate } from '@/utils/parse-date';
6
+ import timezone from '@/utils/timezone';
7
+
8
+ export const route: Route = {
9
+ path: '/news/:category?',
10
+ categories: ['university'],
11
+ example: '/tsinghua/news',
12
+ parameters: { category: '分类,可在对应分类页 URL 中找到,留空为 `zxdt`' },
13
+ features: {
14
+ requireConfig: false,
15
+ requirePuppeteer: false,
16
+ antiCrawler: false,
17
+ supportBT: false,
18
+ supportPodcast: false,
19
+ supportScihub: false,
20
+ },
21
+ name: '清华新闻',
22
+ radar: [
23
+ {
24
+ source: ['www.tsinghua.edu.cn/news/:category'],
25
+ target: (_, url) => `/tsinghua/news/${new URL(url).pathname.split('/').pop()?.replace('.htm', '')}`,
26
+ },
27
+ ],
28
+ maintainers: ['TonyRL'],
29
+ url: 'www.tsinghua.edu.cn/news.htm',
30
+ handler,
31
+ };
32
+
33
+ async function handler(ctx) {
34
+ const { category = 'zxdt' } = ctx.req.param();
35
+ const baseUrl = 'https://www.tsinghua.edu.cn';
36
+ const link = `${baseUrl}/news/${category}.htm`;
37
+ const response = await ofetch(link);
38
+ const $ = load(response);
39
+
40
+ const list = [
41
+ ...$('.left li a')
42
+ .toArray()
43
+ .map((item) => {
44
+ const $item = $(item);
45
+ const sj = $item.find('.sj');
46
+
47
+ return {
48
+ title: $item.find('.bt').text().trim(),
49
+ link: new URL($item.attr('href'), baseUrl).href?.replace('http://', 'https://'),
50
+ pubDate: parseDate(`${sj.find('span').text().trim()}.${sj.find('p').text().trim()}`, 'YYYY.MM.DD'),
51
+ };
52
+ }),
53
+ ...($('.qhrw2_first').length
54
+ ? [
55
+ {
56
+ title: $('.qhrw2_first .bt').text().trim(),
57
+ link: $('.qhrw2_first a').attr('href')?.replace('http://', 'https://'),
58
+ pubDate: parseDate(`${$('.qhrw2_first .sj span').text().trim()}.${$('.qhrw2_first .sj p').text().trim()}`, 'YYYY.MM.DD'),
59
+ },
60
+ ]
61
+ : []),
62
+ ];
63
+
64
+ const items = await Promise.all(
65
+ list.map((item) =>
66
+ cache.tryGet(item.link, async () => {
67
+ if (!item.link?.startsWith('https://www.tsinghua.edu.cn/info/')) {
68
+ return item;
69
+ }
70
+
71
+ const response = await ofetch(item.link);
72
+ const $ = load(response);
73
+
74
+ item.description = $('.v_news_content').html();
75
+ item.pubDate = timezone(parseDate($('.sj p').text().trim(), 'YYYY年MM月DD日 HH:mm:ss'), 8);
76
+
77
+ return item;
78
+ })
79
+ )
80
+ );
81
+
82
+ return {
83
+ title: $('head title').text(),
84
+ link,
85
+ item: items,
86
+ };
87
+ }
@@ -280,7 +280,7 @@ const getUserTweets = async (id, params = {}) => {
280
280
  return !idSet.has(id_str) && idSet.add(id_str) && tweet;
281
281
  }) // deduplicate
282
282
  .filter(Boolean) // remove null
283
- .sort((a, b) => (b.id_str || b.conversation_id_str) - (a.id_str || a.conversation_id_str)) // desc
283
+ .toSorted((a, b) => (b.id_str || b.conversation_id_str) - (a.id_str || a.conversation_id_str)) // desc
284
284
  .slice(0, 20);
285
285
  cache.set(cacheKey, JSON.stringify(tweets));
286
286
  return tweets;
@@ -171,7 +171,11 @@ const getList = async (id: string, params?: Record<string, any>) =>
171
171
 
172
172
  const getUser = async (id: string) => {
173
173
  const userData: any = await getUserData(id);
174
- return (userData.data?.user || userData.data?.user_result)?.result?.legacy;
174
+ return {
175
+ profile_image_url: userData.data?.user?.result?.avatar?.image_url,
176
+ ...userData.data?.user?.result?.core,
177
+ ...(userData.data?.user || userData.data?.user_result)?.result?.legacy,
178
+ };
175
179
  };
176
180
 
177
181
  const getHomeTimeline = async (id: string, params?: Record<string, any>) =>
@@ -71,12 +71,12 @@ async function handler(ctx) {
71
71
  .remove()
72
72
  .end()
73
73
  .html()
74
- ?.replace(/(<img.*?) src=".*?"(.*?>)/g, '$1$2')
74
+ ?.replaceAll(/(<img.*?) src=".*?"(.*?>)/g, '$1$2')
75
75
  .replaceAll(/(<img.*?)zoomfile(.*?>)/g, '$1src$2'),
76
76
  pattl: content(item)
77
77
  .find('div.pattl')
78
78
  .html()
79
- ?.replace(/(<img.*?) src=".*?"(.*?>)/g, '$1$2')
79
+ ?.replaceAll(/(<img.*?) src=".*?"(.*?>)/g, '$1$2')
80
80
  .replaceAll(/(<img.*?)zoomfile(.*?>)/g, '$1src$2'),
81
81
  author: content(item).find('a.xw1').text().trim(),
82
82
  })
@@ -77,7 +77,7 @@ export const route: Route = {
77
77
  displayErrors: true,
78
78
  });
79
79
  const md = markdownit('commonmark');
80
- const items = context.an.exports.sort((a, b) => a.updatedAt - b.updatedAt);
80
+ const items = context.an.exports.toSorted((a, b) => a.updatedAt - b.updatedAt);
81
81
  const groups = new Map(items.map((it) => [it.name, it]));
82
82
  const pkgs = [...groups.values()].map((item) => {
83
83
  const $ = load(md.render(item.readme));
@@ -1,16 +1,17 @@
1
1
  import { Route } from '@/types';
2
2
  import cache from '@/utils/cache';
3
- import got from '@/utils/got';
3
+ import ofetch from '@/utils/ofetch';
4
+ import { load } from 'cheerio';
4
5
  import { parseDate } from '@/utils/parse-date';
5
6
 
6
7
  const rootURL = 'https://www.uber.com';
7
- const apiURL = 'https://blogapi.uber.com';
8
8
 
9
9
  export const route: Route = {
10
- path: '/blog/:maxPage?',
10
+ // `compat` is a never used parameter
11
+ // just for backward compatibility with the deprecated `:maxPage` parameter
12
+ path: '/blog/:compat?',
11
13
  categories: ['blog'],
12
14
  example: '/uber/blog',
13
- parameters: { maxPage: 'max number of pages to retrieve, default to 1 page at most' },
14
15
  features: {
15
16
  requireConfig: false,
16
17
  requirePuppeteer: false,
@@ -21,65 +22,105 @@ export const route: Route = {
21
22
  },
22
23
  radar: [
23
24
  {
24
- source: ['www.uber.com/:language/blog/engineering', 'www.uber.com/:language/blog'],
25
+ source: ['www.uber.com/:language/blog/engineering'],
25
26
  target: '/blog',
26
27
  },
27
28
  ],
28
29
  name: 'Engineering',
29
30
  maintainers: ['hulb'],
30
31
  handler,
31
- url: 'www.uber.com/blog/pittsburgh/engineering',
32
+ url: 'www.uber.com/en-HK/blog/engineering',
33
+ description:
34
+ "The English blog on any of Uber's regional sites (e.g., www.uber.com/en-JP/blog) is the same engineering blog provided by this route, so language selection is not supported. This route is not for the public news blog on specific regional sites (e.g., www.uber.com/ja-JP/blog).",
35
+ zh: {
36
+ description: 'uber的任何区域站点的英文blog(例如www.uber.com/en-JP/blog)都是相同的内容,正是本路由提供的engineering blog,因此本路由不提供语言选择;本路由不是uber在特定区域站点的公开新闻blog(例如www.uber.com/ja-JP/blog)',
37
+ },
32
38
  };
33
39
 
34
- async function handler(ctx) {
35
- let maxPage = Number(ctx.req.param('maxPage'));
36
- if (Number.isNaN(maxPage)) {
37
- maxPage = 1;
38
- }
39
-
40
- let pages = await Promise.all(
41
- [...Array.from({ length: maxPage }).keys()].map((pageIdx) =>
42
- got(`${apiURL}/wp-json/blog/v1/data`, {
43
- searchParams: {
44
- page: pageIdx + 1,
45
- parent: 'pittsburgh',
46
- slug: 'engineering',
47
- },
48
- })
49
- )
50
- );
51
- pages = pages.map((page) => page.data);
40
+ async function handler() {
41
+ const response = await ofetch(`${rootURL}/en-HK/blog/engineering/rss/`, {
42
+ // The source site is misconfigured or intentionally blocking requests without a specific accept header
43
+ // Without this header, it will return an HTTP 406 error
44
+ // Note that the accept type must be 'text/html'; 'application/xml' or similar will get HTTP 404 error
45
+ headers: {
46
+ accept: 'text/html',
47
+ },
48
+ // Without this, ofetch will parse the response as a blob instead of text, which cannot be loaded by cheerio
49
+ parseResponse: (txt) => txt,
50
+ });
51
+ const $ = load(response, { xmlMode: true });
52
52
 
53
53
  const result = await Promise.all(
54
- pages.map((page) =>
55
- Promise.all(
56
- page.posts.map((post) =>
57
- cache.tryGet(`${rootURL}${post.link}`, async () => {
58
- let { data: article } = await got(`${apiURL}/wp-json/blog/v1/data`, {
59
- searchParams: {
60
- slug: post.link.replaceAll('/', '').replace('blog', ''),
61
- },
62
- });
63
- article = article.article;
54
+ $('item')
55
+ .toArray()
56
+ .map((el) =>
57
+ cache.tryGet($(el).find('link').text(), async () => {
58
+ const detailResponse = await ofetch($(el).find('link').text(), {
59
+ headers: {
60
+ accept: 'text/html',
61
+ },
62
+ });
63
+ const detail = load(detailResponse);
64
+
65
+ const scriptText = detail('script#__REDUX_STATE__').text().trim();
66
+ // The json in the script element is over-encoded
67
+ // It needs to be decoded this way before it can be parsed by JSON.parse
68
+ const jsonText = decodeURIComponent(JSON.parse(`"${scriptText}"`));
69
+ // Traverse the JSON to find the content node, which is more robust against format changes.
70
+ const contentHtml = findNode(JSON.parse(jsonText), { idKey: 'id', idValue: 'BlogArticleContent', siblingKey: 'props', childKey: 'content' }).replaceAll(String.raw`\n`, '');
64
71
 
65
- return {
66
- link: article.link,
67
- title: article.title,
68
- description: article.content,
69
- pubDate: parseDate(article.created),
70
- author: article.author,
71
- category: article.categories.map((category) => category.category_name),
72
- };
73
- })
74
- )
72
+ return {
73
+ link: $(el).find('link').text(),
74
+ title: $(el).find('title').text(),
75
+ description: contentHtml,
76
+ pubDate: parseDate($(el).find('pubDate').text()),
77
+ category: $(el)
78
+ .find('category')
79
+ .toArray()
80
+ .map((item) => $(item).text()),
81
+ };
82
+ })
75
83
  )
76
- )
77
84
  );
78
85
 
79
86
  return {
80
87
  title: `Uber Engineering Blog`,
81
88
  link: rootURL + '/blog/engineering',
82
89
  description: 'The technology behind Uber Engineering',
83
- item: result.flat(),
90
+ item: result,
84
91
  };
85
92
  }
93
+
94
+ function findNode(
95
+ json: any,
96
+ options: {
97
+ idKey?: string;
98
+ idValue: string;
99
+ siblingKey: string;
100
+ childKey: string;
101
+ }
102
+ ): any {
103
+ const { idKey = 'id', idValue, siblingKey, childKey } = options;
104
+
105
+ if (Array.isArray(json)) {
106
+ for (const item of json) {
107
+ const result = findNode(item, options);
108
+ if (result !== undefined) {
109
+ return result;
110
+ }
111
+ }
112
+ } else if (json && typeof json === 'object') {
113
+ if (json[idKey] === idValue) {
114
+ return json[siblingKey]?.[childKey];
115
+ }
116
+
117
+ for (const key in json) {
118
+ const result = findNode(json[key], options);
119
+ if (result !== undefined) {
120
+ return result;
121
+ }
122
+ }
123
+ }
124
+
125
+ return undefined;
126
+ }
@@ -17,6 +17,7 @@ export const route: Route = {
17
17
  supportBT: false,
18
18
  supportPodcast: false,
19
19
  supportScihub: false,
20
+ nsfw: true,
20
21
  },
21
22
  radar: [
22
23
  {
@@ -15,6 +15,9 @@ export const route: Route = {
15
15
  maintainers: ['SettingDust', 'Halcao'],
16
16
  handler,
17
17
  url: 'uraaka-joshi.com/',
18
+ features: {
19
+ nsfw: true,
20
+ },
18
21
  };
19
22
 
20
23
  async function handler() {
@@ -138,7 +138,7 @@ export const route: Route = {
138
138
  ],
139
139
  },
140
140
  },
141
- description: `:::tip
141
+ description: `::: tip
142
142
  若订阅 [人物](https://www.wainao.me/topics/people),网址为 \`https://www.wainao.me/topics/people\`,请截取 \`https://www.wainao.me/topics/\` 到末尾的部分 \`people\` 作为 \`id\` 参数填入,此时目标路由为 [\`/wainao/topics/people\`](https://rsshub.app/wainao/topics/people)。
143
143
  :::
144
144
 
@@ -280,7 +280,7 @@ export const route: Route = {
280
280
  ],
281
281
  },
282
282
  },
283
- description: `:::tip
283
+ description: `::: tip
284
284
  订阅 [行业标准](https://www.wdfxw.net/bookfree-00002.html),其源网址为 \`https://www.wdfxw.net/bookfree-00002.html\`,请参考该 URL 指定部分构成参数,此时路由为 [\`/wdfxw/bookfree/00002\`](https://rsshub.app/wdfxw/bookfree/00002)。
285
285
  :::
286
286