rsshub 1.0.0-master.f2f43f7 → 1.0.0-master.f3315cd

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 (503) hide show
  1. package/README.md +4 -11
  2. package/lib/api/category/one.ts +54 -0
  3. package/lib/api/index.ts +10 -4
  4. package/lib/app.tsx +2 -0
  5. package/lib/config.ts +57 -17
  6. package/lib/errors/index.test.ts +9 -5
  7. package/lib/errors/index.tsx +10 -3
  8. package/lib/index.ts +5 -2
  9. package/lib/middleware/anti-hotlink.test.ts +6 -6
  10. package/lib/middleware/cache.ts +21 -6
  11. package/lib/middleware/logger.ts +5 -1
  12. package/lib/middleware/template.tsx +15 -11
  13. package/lib/middleware/trace.ts +25 -0
  14. package/lib/registry.ts +8 -2
  15. package/lib/router.js +0 -6
  16. package/lib/routes/2048/index.ts +13 -10
  17. package/lib/routes/3dmgame/news-center.ts +1 -1
  18. package/lib/routes/69shu/article.ts +8 -8
  19. package/lib/routes/69shu/namespace.ts +1 -1
  20. package/lib/routes/6v123/latest-movies.ts +1 -1
  21. package/lib/routes/6v123/latest-tvseries.ts +1 -1
  22. package/lib/routes/6v123/utils.ts +7 -1
  23. package/lib/routes/81/81rc/index.ts +68 -32
  24. package/lib/routes/81/namespace.ts +3 -1
  25. package/lib/routes/academia/namespace.ts +6 -0
  26. package/lib/routes/academia/topics.ts +49 -0
  27. package/lib/routes/alipan/files.ts +80 -0
  28. package/lib/routes/alipan/namespace.ts +7 -0
  29. package/lib/routes/alipan/types.ts +62 -0
  30. package/lib/routes/alistapart/utils.ts +2 -2
  31. package/lib/routes/alpinelinux/namespace.ts +11 -0
  32. package/lib/routes/alpinelinux/pkgs.ts +104 -0
  33. package/lib/routes/apnews/rss.ts +11 -5
  34. package/lib/routes/apnews/topics.ts +11 -5
  35. package/lib/routes/apnews/utils.ts +35 -12
  36. package/lib/routes/apple/apps.ts +30 -8
  37. package/lib/routes/asmr-200/index.ts +66 -0
  38. package/lib/routes/{arknights → asmr-200}/namespace.ts +2 -2
  39. package/lib/routes/asmr-200/templates/work.art +7 -0
  40. package/lib/routes/asmr-200/type.ts +96 -0
  41. package/lib/routes/bbc/index.ts +9 -2
  42. package/lib/routes/bc3ts/list.ts +72 -0
  43. package/lib/routes/bc3ts/namespace.ts +7 -0
  44. package/lib/routes/bc3ts/templates/media.art +10 -0
  45. package/lib/routes/bc3ts/types.ts +118 -0
  46. package/lib/routes/beijingprice/index.ts +193 -0
  47. package/lib/routes/beijingprice/namespace.ts +8 -0
  48. package/lib/routes/bilibili/dynamic.ts +32 -19
  49. package/lib/routes/bilibili/namespace.ts +1 -1
  50. package/lib/routes/bilibili/ranking.ts +100 -9
  51. package/lib/routes/bilibili/video.ts +4 -6
  52. package/lib/routes/bing/daily-wallpaper.ts +57 -18
  53. package/lib/routes/bjtu/gs.ts +224 -0
  54. package/lib/routes/bjtu/namespace.ts +8 -0
  55. package/lib/routes/bjx/fd.ts +54 -0
  56. package/lib/routes/bjx/namespace.ts +1 -1
  57. package/lib/routes/bluearchive/namespace.ts +7 -0
  58. package/lib/routes/bluearchive/news.ts +88 -0
  59. package/lib/routes/bt0/mv.ts +65 -0
  60. package/lib/routes/bt0/namespace.ts +9 -0
  61. package/lib/routes/bt0/tlist.ts +67 -0
  62. package/lib/routes/bt0/util.ts +51 -0
  63. package/lib/routes/buaa/jiaowu.ts +124 -0
  64. package/lib/routes/buaa/news/index.ts +15 -13
  65. package/lib/routes/buaa/sme.ts +5 -3
  66. package/lib/routes/bugzilla/bug.ts +59 -0
  67. package/lib/routes/bugzilla/namespace.ts +11 -0
  68. package/lib/routes/cara/constant.ts +5 -0
  69. package/lib/routes/cara/likes.ts +56 -0
  70. package/lib/routes/cara/namespace.ts +6 -0
  71. package/lib/routes/cara/portfolio.ts +40 -0
  72. package/lib/routes/cara/templates/post.art +6 -0
  73. package/lib/routes/cara/timeline.ts +56 -0
  74. package/lib/routes/cara/types.ts +45 -0
  75. package/lib/routes/cara/utils.ts +62 -0
  76. package/lib/routes/cbaigui/utils.ts +1 -1
  77. package/lib/routes/cccfna/index.ts +82 -0
  78. package/lib/routes/cccfna/namespace.ts +6 -0
  79. package/lib/routes/cfr/index.ts +58 -0
  80. package/lib/routes/cfr/namespace.ts +6 -0
  81. package/lib/routes/cfr/types.ts +30 -0
  82. package/lib/routes/cfr/utils.ts +284 -0
  83. package/lib/routes/chaping/newsflash.ts +2 -2
  84. package/lib/routes/chinaisa/index.ts +18 -8
  85. package/lib/routes/cnbc/rss.ts +1 -1
  86. package/lib/routes/codeforces/contests.ts +2 -2
  87. package/lib/routes/codeforces/recent-actions.ts +2 -2
  88. package/lib/routes/dangdang/namespace.ts +6 -0
  89. package/lib/routes/dangdang/notice.ts +69 -0
  90. package/lib/routes/dataguidance/index.ts +66 -0
  91. package/lib/routes/dataguidance/namespace.ts +7 -0
  92. package/lib/routes/dblp/publication.ts +4 -6
  93. package/lib/routes/deadbydaylight/index.ts +69 -0
  94. package/lib/routes/deadbydaylight/namespace.ts +12 -0
  95. package/lib/routes/dewu/declaration.ts +86 -0
  96. package/lib/routes/dewu/namespace.ts +6 -0
  97. package/lib/routes/dhu/jiaowu/news.ts +53 -24
  98. package/lib/routes/dhu/namespace.ts +1 -1
  99. package/lib/routes/dhu/xxgk/news.ts +48 -20
  100. package/lib/routes/discourse/notifications.ts +2 -1
  101. package/lib/routes/dlnews/utils.ts +2 -2
  102. package/lib/routes/dockerhub/build.ts +12 -7
  103. package/lib/routes/domp4/detail.ts +1 -1
  104. package/lib/routes/domp4/latest-movie-bt.ts +71 -0
  105. package/lib/routes/douban/other/group.ts +25 -4
  106. package/lib/routes/duckdb/namespace.ts +6 -0
  107. package/lib/routes/duckdb/news.ts +65 -0
  108. package/lib/routes/dushu/fuzhou/index.ts +10 -11
  109. package/lib/routes/epicgames/index.ts +14 -4
  110. package/lib/routes/famitsu/category.ts +110 -43
  111. package/lib/routes/famitsu/templates/description.art +7 -0
  112. package/lib/routes/famitsu/types.ts +117 -0
  113. package/lib/routes/fanbox/namespace.ts +1 -1
  114. package/lib/routes/fanqienovel/namespace.ts +7 -0
  115. package/lib/routes/fanqienovel/page.ts +100 -0
  116. package/lib/routes/fansly/post.ts +1 -2
  117. package/lib/routes/fansly/tag.ts +1 -2
  118. package/lib/routes/fansly/utils.ts +5 -4
  119. package/lib/routes/fashionnetwork/index.ts +192 -0
  120. package/lib/routes/fashionnetwork/namespace.ts +8 -0
  121. package/lib/routes/fashionnetwork/templates/description.art +17 -0
  122. package/lib/routes/fediverse/namespace.ts +6 -0
  123. package/lib/routes/fediverse/timeline.ts +81 -0
  124. package/lib/routes/finology/bullets.ts +0 -9
  125. package/lib/routes/finology/category.ts +60 -0
  126. package/lib/routes/finology/most-viewed.ts +4 -12
  127. package/lib/routes/finology/tag.ts +42 -63
  128. package/lib/routes/finology/utils.ts +3 -2
  129. package/lib/routes/finviz/news.ts +4 -4
  130. package/lib/routes/foresightnews/util.ts +1 -1
  131. package/lib/routes/fortunechina/index.ts +24 -14
  132. package/lib/routes/freebuf/index.ts +3 -3
  133. package/lib/routes/ft/namespace.ts +1 -1
  134. package/lib/routes/{ft → ftchinese}/channel.ts +5 -5
  135. package/lib/routes/ftchinese/namespace.ts +6 -0
  136. package/lib/routes/getitfree/util.ts +1 -1
  137. package/lib/routes/github/activity.ts +55 -0
  138. package/lib/routes/github/issue.ts +27 -4
  139. package/lib/routes/github/notifications.ts +8 -14
  140. package/lib/routes/github/star.ts +4 -3
  141. package/lib/routes/github/trending.ts +27 -5
  142. package/lib/routes/google/citations.ts +2 -2
  143. package/lib/routes/google/scholar.ts +2 -2
  144. package/lib/routes/gov/beijing/bphc/index.ts +3 -3
  145. package/lib/routes/gov/immiau/news.ts +2 -2
  146. package/lib/routes/gov/sh/fgw/index.ts +155 -0
  147. package/lib/routes/gov/sh/fgw/templates/description.art +17 -0
  148. package/lib/routes/gov/sh/namespace.ts +8 -0
  149. package/lib/routes/gov/{shanghai → sh}/rsj/ksxm.ts +2 -2
  150. package/lib/routes/gov/{shanghai → sh}/wgj/wgj.ts +3 -3
  151. package/lib/routes/gov/{shanghai → sh}/wsjkw/yqtb/index.ts +2 -2
  152. package/lib/routes/gov/{shanghai → sh}/yjj/index.ts +3 -3
  153. package/lib/routes/gov/stats/index.ts +8 -8
  154. package/lib/routes/gov/zhengce/index.ts +3 -6
  155. package/lib/routes/grist/utils.ts +2 -2
  156. package/lib/routes/guangdiu/search.ts +1 -1
  157. package/lib/routes/guokr/utils.ts +1 -1
  158. package/lib/routes/hitcon/zeroday.ts +1 -1
  159. package/lib/routes/hrbeu/job/calendar.ts +8 -6
  160. package/lib/routes/huxiu/util.ts +2 -2
  161. package/lib/routes/{arknights → hypergryph/arknights}/announce.ts +27 -24
  162. package/lib/routes/hypergryph/arknights/arktca.ts +124 -0
  163. package/lib/routes/hypergryph/arknights/japan.ts +78 -0
  164. package/lib/routes/hypergryph/arknights/news.ts +118 -0
  165. package/lib/routes/hypergryph/namespace.ts +7 -0
  166. package/lib/routes/ieee/journal.ts +50 -67
  167. package/lib/routes/ieee/templates/description.art +1 -1
  168. package/lib/routes/imdb/chart.ts +61 -0
  169. package/lib/routes/imdb/namespace.ts +6 -0
  170. package/lib/routes/imdb/templates/chart.art +15 -0
  171. package/lib/routes/imdb/types.ts +103 -0
  172. package/lib/routes/informedainews/docs.ts +78 -0
  173. package/lib/routes/informedainews/namespace.ts +18 -0
  174. package/lib/routes/instagram/private-api/index.ts +27 -5
  175. package/lib/routes/investor/index.ts +213 -0
  176. package/lib/routes/investor/namespace.ts +8 -0
  177. package/lib/routes/iplaysoft/index.ts +68 -0
  178. package/lib/routes/iplaysoft/namespace.ts +6 -0
  179. package/lib/routes/j-test/namespace.ts +6 -0
  180. package/lib/routes/j-test/news.ts +64 -0
  181. package/lib/routes/japanpost/namespace.ts +7 -1
  182. package/lib/routes/japanpost/router.ts +40 -0
  183. package/lib/routes/japanpost/track.ts +1 -23
  184. package/lib/routes/javbus/index.ts +15 -7
  185. package/lib/routes/javdb/index.ts +4 -3
  186. package/lib/routes/javdb/series.ts +1 -1
  187. package/lib/routes/javdb/utils.ts +6 -0
  188. package/lib/routes/javdb/videocodes.ts +56 -0
  189. package/lib/routes/jingzhengu/namespace.ts +6 -0
  190. package/lib/routes/jingzhengu/news.ts +77 -0
  191. package/lib/routes/jingzhengu/types.ts +39 -0
  192. package/lib/routes/jingzhengu/utils.ts +35 -0
  193. package/lib/routes/jinritemai/docs.ts +74 -0
  194. package/lib/routes/jinritemai/namespace.ts +6 -0
  195. package/lib/routes/jiuyangongshe/community.ts +147 -0
  196. package/lib/routes/jiuyangongshe/namespace.ts +7 -0
  197. package/lib/routes/jiuyangongshe/templates/community-description.art +4 -0
  198. package/lib/routes/jjwxc/book.ts +4 -3
  199. package/lib/routes/jlu/ccst/xwzx/index.ts +63 -0
  200. package/lib/routes/jlu/jwc.ts +55 -0
  201. package/lib/routes/jlu/namespace.ts +6 -0
  202. package/lib/routes/kadokawa/blog.ts +134 -0
  203. package/lib/routes/kadokawa/namespace.ts +8 -0
  204. package/lib/routes/kadokawa/templates/description.art +21 -0
  205. package/lib/routes/kelownacapnews/namespace.ts +6 -0
  206. package/lib/routes/kelownacapnews/news.ts +93 -0
  207. package/lib/routes/kyodonews/index.ts +1 -1
  208. package/lib/routes/leetcode/articles.ts +19 -21
  209. package/lib/routes/line/today.ts +1 -1
  210. package/lib/routes/lofter/user.ts +3 -2
  211. package/lib/routes/logclub/index.ts +1 -2
  212. package/lib/routes/luogu/user-blog.ts +6 -6
  213. package/lib/routes/luolei/index.ts +1 -2
  214. package/lib/routes/maccms/index.ts +72 -0
  215. package/lib/routes/maccms/namespace.ts +9 -0
  216. package/lib/routes/maccms/templates/vod.art +12 -0
  217. package/lib/routes/maccms/type.ts +102 -0
  218. package/lib/routes/mangadex/namespace.ts +1 -1
  219. package/lib/routes/manyvids/namespace.ts +7 -0
  220. package/lib/routes/manyvids/templates/video.art +3 -0
  221. package/lib/routes/manyvids/types.ts +89 -0
  222. package/lib/routes/manyvids/video.ts +51 -0
  223. package/lib/routes/matters/author.ts +63 -0
  224. package/lib/routes/matters/latest.ts +74 -0
  225. package/lib/routes/matters/namespace.ts +7 -0
  226. package/lib/routes/matters/tags.ts +85 -0
  227. package/lib/routes/matters/utils.ts +30 -0
  228. package/lib/routes/meituan/namespace.ts +6 -0
  229. package/lib/routes/meituan/tech.ts +67 -0
  230. package/lib/routes/metacritic/index.ts +10 -0
  231. package/lib/routes/metrics.ts +12 -0
  232. package/lib/routes/microsoft/mcr.ts +63 -0
  233. package/lib/routes/microsoft/namespace.ts +2 -2
  234. package/lib/routes/mihoyo/bbs/img-ranking.ts +4 -4
  235. package/lib/routes/mihoyo/bbs/static-data.ts +7 -0
  236. package/lib/routes/minecraft/version.ts +1 -1
  237. package/lib/routes/mirrormedia/category.ts +101 -0
  238. package/lib/routes/mirrormedia/index.ts +43 -0
  239. package/lib/routes/mirrormedia/namespace.ts +6 -0
  240. package/lib/routes/mirrormedia/utils.ts +19 -0
  241. package/lib/routes/modb/topic.ts +5 -6
  242. package/lib/routes/my-formosa/index.ts +78 -0
  243. package/lib/routes/my-formosa/namespace.ts +6 -0
  244. package/lib/routes/myfans/namespace.ts +6 -0
  245. package/lib/routes/myfans/post.ts +64 -0
  246. package/lib/routes/myfans/templates/post.art +8 -0
  247. package/lib/routes/myfans/types.ts +104 -0
  248. package/lib/routes/myfans/utils.ts +39 -0
  249. package/lib/routes/nasa/apod.ts +4 -3
  250. package/lib/routes/nasa/namespace.ts +1 -1
  251. package/lib/routes/neea/index.ts +47 -19
  252. package/lib/routes/neea/jlpt.ts +12 -15
  253. package/lib/routes/neea/namespace.ts +2 -2
  254. package/lib/routes/newrank/utils.ts +1 -1
  255. package/lib/routes/newzmz/util.ts +1 -1
  256. package/lib/routes/nextjs/blog.ts +63 -0
  257. package/lib/routes/nextjs/namespace.ts +6 -0
  258. package/lib/routes/nga/forum.ts +3 -2
  259. package/lib/routes/nhentai/{other.ts → index.ts} +3 -8
  260. package/lib/routes/nhentai/namespace.ts +1 -0
  261. package/lib/routes/nhentai/search.ts +0 -5
  262. package/lib/routes/nhentai/util.ts +7 -7
  263. package/lib/routes/nikkei/asia/index.ts +1 -10
  264. package/lib/routes/nikkei/cn/index.ts +39 -3
  265. package/lib/routes/nikkei/index.ts +5 -4
  266. package/lib/routes/nikkei/namespace.ts +1 -1
  267. package/lib/routes/nikkei/news.ts +2 -2
  268. package/lib/routes/nmc/weatheralarm.ts +1 -0
  269. package/lib/routes/notion/release.ts +81 -0
  270. package/lib/routes/npm/package.ts +15 -8
  271. package/lib/routes/nyaa/main.ts +2 -3
  272. package/lib/routes/nyaa/namespace.ts +10 -0
  273. package/lib/routes/ollama/blog.ts +39 -0
  274. package/lib/routes/ollama/models.ts +7 -4
  275. package/lib/routes/oschina/news.ts +4 -2
  276. package/lib/routes/picnob/namespace.ts +1 -4
  277. package/lib/routes/picnob/user.ts +3 -2
  278. package/lib/routes/picuki/namespace.ts +1 -4
  279. package/lib/routes/picuki/profile.ts +11 -7
  280. package/lib/routes/pixiv/ranking.ts +74 -11
  281. package/lib/routes/pixiv/search.ts +39 -7
  282. package/lib/routes/pixiv/user.ts +4 -2
  283. package/lib/routes/podwise/collections.ts +46 -0
  284. package/lib/routes/podwise/episodes.ts +119 -0
  285. package/lib/routes/podwise/namespace.ts +9 -0
  286. package/lib/routes/pornhub/pornstar.ts +2 -2
  287. package/lib/routes/ps/monthly-games.ts +3 -2
  288. package/lib/routes/psyche/namespace.ts +6 -0
  289. package/lib/routes/psyche/templates/essay.art +3 -0
  290. package/lib/routes/psyche/templates/video.art +10 -0
  291. package/lib/routes/psyche/topic.ts +46 -0
  292. package/lib/routes/psyche/type.ts +53 -0
  293. package/lib/routes/psyche/utils.ts +107 -0
  294. package/lib/routes/pubscholar/explore.ts +62 -0
  295. package/lib/routes/pubscholar/namespace.ts +7 -0
  296. package/lib/routes/pubscholar/types.ts +41 -0
  297. package/lib/routes/pubscholar/utils.ts +44 -0
  298. package/lib/routes/pwc/sustainability.ts +53 -49
  299. package/lib/routes/qidian/chapter.ts +4 -3
  300. package/lib/routes/qq/cfhd/index.ts +140 -0
  301. package/lib/routes/qq/namespace.ts +4 -2
  302. package/lib/routes/raycast/changelog.ts +54 -0
  303. package/lib/routes/raycast/namespace.ts +7 -0
  304. package/lib/routes/react/blog.ts +57 -0
  305. package/lib/routes/react/namespace.ts +6 -0
  306. package/lib/routes/readwise/list.ts +152 -0
  307. package/lib/routes/readwise/namespace.ts +6 -0
  308. package/lib/routes/reuters/common.ts +3 -2
  309. package/lib/routes/reuters/namespace.ts +1 -1
  310. package/lib/routes/rss3/index.ts +148 -0
  311. package/lib/routes/rss3/namespace.ts +7 -0
  312. package/lib/routes/rsshub/routes.ts +19 -3
  313. package/lib/routes/ruc/ai.ts +87 -0
  314. package/lib/routes/ruc/namespace.ts +5 -2
  315. package/lib/routes/samd/namespace.ts +6 -0
  316. package/lib/routes/samd/news.ts +74 -0
  317. package/lib/routes/sciencedirect/cf-email.ts +0 -1
  318. package/lib/routes/sehuatang/index.ts +33 -14
  319. package/lib/routes/shisu/en.ts +75 -0
  320. package/lib/routes/shisu/namespace.ts +1 -1
  321. package/lib/routes/shisu/news.ts +12 -12
  322. package/lib/routes/sicau/jiaowu.ts +77 -0
  323. package/lib/routes/sicau/jk.ts +210 -0
  324. package/lib/routes/sicau/namespace.ts +1 -1
  325. package/lib/routes/sjtu/yzb/zkxx.ts +36 -16
  326. package/lib/routes/smzdm/keyword.ts +3 -2
  327. package/lib/routes/smzdm/ranking.ts +180 -46
  328. package/lib/routes/spotify/artist.ts +16 -18
  329. package/lib/routes/spotify/artists-top.ts +7 -8
  330. package/lib/routes/spotify/playlist.ts +10 -10
  331. package/lib/routes/spotify/saved.ts +7 -8
  332. package/lib/routes/spotify/show.ts +7 -8
  333. package/lib/routes/spotify/tracks-top.ts +7 -8
  334. package/lib/routes/spotify/utils.ts +22 -22
  335. package/lib/routes/sspai/author.ts +7 -1
  336. package/lib/routes/sspai/index.ts +9 -3
  337. package/lib/routes/sspai/matrix.ts +7 -1
  338. package/lib/routes/sspai/prime-community.ts +83 -0
  339. package/lib/routes/sspai/tag.ts +7 -1
  340. package/lib/routes/sspai/topic.ts +7 -1
  341. package/lib/routes/sspai/topics.ts +1 -1
  342. package/lib/routes/steam/sharefile-changelog.ts +65 -0
  343. package/lib/routes/steam/templates/workshop-search-description.art +5 -0
  344. package/lib/routes/steam/workshop-search.ts +109 -0
  345. package/lib/routes/stockedge/utils.ts +9 -11
  346. package/lib/routes/stream-capital/namespace.ts +6 -0
  347. package/lib/routes/stream-capital/search.ts +79 -0
  348. package/lib/routes/stream-capital/types.ts +44 -0
  349. package/lib/routes/stream-capital/utils.ts +18 -0
  350. package/lib/routes/sustainabilitymag/articles.ts +144 -0
  351. package/lib/routes/sustainabilitymag/namespace.ts +6 -0
  352. package/lib/routes/swjtu/gsee/yjs.ts +76 -0
  353. package/lib/routes/swpu/bgw.ts +31 -33
  354. package/lib/routes/swpu/dean.ts +27 -29
  355. package/lib/routes/swpu/dxy.ts +26 -28
  356. package/lib/routes/swpu/scs.ts +29 -31
  357. package/lib/routes/telecompaper/news.ts +1 -1
  358. package/lib/routes/telegram/channel.ts +35 -31
  359. package/lib/routes/tencent/cloud/developer/column.ts +81 -0
  360. package/lib/routes/tencent/namespace.ts +2 -2
  361. package/lib/routes/tesla/cx.ts +1 -1
  362. package/lib/routes/test/index.ts +5 -1
  363. package/lib/routes/test/namespace.ts +1 -1
  364. package/lib/routes/theblockbeats/index.ts +49 -18
  365. package/lib/routes/theblockbeats/namespace.ts +2 -2
  366. package/lib/routes/theblockbeats/templates/description.art +5 -0
  367. package/lib/routes/theinitium/channel.ts +1 -1
  368. package/lib/routes/theinitium/follow.ts +1 -6
  369. package/lib/routes/theinitium/utils.ts +2 -18
  370. package/lib/routes/thoughtworks/index.ts +71 -0
  371. package/lib/routes/thoughtworks/namespace.ts +6 -0
  372. package/lib/routes/trending/all-trending.ts +2 -2
  373. package/lib/routes/tsdm39/bd.ts +101 -0
  374. package/lib/routes/tsdm39/namespace.ts +7 -0
  375. package/lib/routes/twitter/api/developer-api/search.ts +1 -1
  376. package/lib/routes/twitter/api/developer-api/user.ts +1 -1
  377. package/lib/routes/twitter/api/index.ts +1 -1
  378. package/lib/routes/twitter/api/mobile-api/api.ts +10 -7
  379. package/lib/routes/twitter/api/mobile-api/constants.ts +1 -1
  380. package/lib/routes/twitter/api/mobile-api/login.ts +161 -138
  381. package/lib/routes/twitter/api/mobile-api/token.ts +16 -22
  382. package/lib/routes/twitter/api/web-api/api.ts +1 -0
  383. package/lib/routes/twitter/api/web-api/constants.ts +1 -1
  384. package/lib/routes/twitter/api/web-api/utils.ts +77 -19
  385. package/lib/routes/twitter/home.ts +3 -3
  386. package/lib/routes/twitter/keyword.ts +6 -5
  387. package/lib/routes/twitter/likes.ts +2 -2
  388. package/lib/routes/twitter/list.ts +3 -3
  389. package/lib/routes/twitter/media.ts +7 -6
  390. package/lib/routes/twitter/namespace.ts +4 -4
  391. package/lib/routes/twitter/trends.ts +1 -1
  392. package/lib/routes/twitter/tweet.ts +1 -1
  393. package/lib/routes/twitter/user.ts +7 -6
  394. package/lib/routes/twitter/utils.ts +21 -14
  395. package/lib/routes/twreporter/category.ts +67 -22
  396. package/lib/routes/twreporter/fetch-article.ts +11 -5
  397. package/lib/routes/twreporter/newest.ts +2 -2
  398. package/lib/routes/typst/universe.ts +34 -8
  399. package/lib/routes/udn/breaking-news.ts +9 -0
  400. package/lib/routes/utgd/category.ts +18 -59
  401. package/lib/routes/utgd/timeline.ts +9 -45
  402. package/lib/routes/utgd/topic.ts +9 -51
  403. package/lib/routes/utgd/utils.ts +41 -0
  404. package/lib/routes/v2ex/tab.ts +3 -2
  405. package/lib/routes/v2ex/topics.ts +19 -3
  406. package/lib/routes/vice/namespace.ts +6 -0
  407. package/lib/routes/vice/templates/article.art +19 -0
  408. package/lib/routes/vice/topic.ts +103 -0
  409. package/lib/routes/watasuke/blog.ts +1 -1
  410. package/lib/routes/weibo/friends.ts +1 -0
  411. package/lib/routes/weibo/group.ts +1 -0
  412. package/lib/routes/weibo/keyword.ts +4 -3
  413. package/lib/routes/weibo/namespace.ts +1 -1
  414. package/lib/routes/weibo/search/hot.ts +12 -7
  415. package/lib/routes/weibo/user-bookmarks.ts +191 -0
  416. package/lib/routes/weibo/user.ts +12 -9
  417. package/lib/routes/weibo/utils.ts +12 -2
  418. package/lib/routes/wfu/news.ts +1 -1
  419. package/lib/routes/wired/namespace.ts +7 -0
  420. package/lib/routes/wired/tag.ts +97 -0
  421. package/lib/routes/wired/types.ts +81 -0
  422. package/lib/routes/wordpress/util.ts +1 -1
  423. package/lib/routes/worldofwarships/devblog.ts +76 -0
  424. package/lib/routes/worldofwarships/namespace.ts +13 -0
  425. package/lib/routes/xiaoheihe/news.ts +2 -1
  426. package/lib/routes/xiaoyuzhou/podcast.ts +3 -2
  427. package/lib/routes/ximalaya/album.ts +29 -21
  428. package/lib/routes/ximalaya/types.ts +68 -0
  429. package/lib/routes/ximalaya/utils.ts +38 -1
  430. package/lib/routes/xinhuanet/app.ts +109 -0
  431. package/lib/routes/xinhuanet/namespace.ts +8 -0
  432. package/lib/routes/xsijishe/forum.ts +23 -3
  433. package/lib/routes/xsijishe/rank.ts +23 -3
  434. package/lib/routes/xueqiu/user-stock.ts +19 -10
  435. package/lib/routes/xueqiu/user.ts +1 -1
  436. package/lib/routes/yahoo/news/index.ts +148 -0
  437. package/lib/routes/yahoo/news/{tw/provider-helper.ts → provider-helper.ts} +9 -4
  438. package/lib/routes/yahoo/news/{tw/provider.ts → provider.ts} +21 -6
  439. package/lib/routes/yahoo/news/{tw/utils.ts → utils.ts} +16 -13
  440. package/lib/routes/ymgal/article.ts +1 -1
  441. package/lib/routes/youtube/channel.ts +1 -0
  442. package/lib/routes/youtube/custom.ts +2 -0
  443. package/lib/routes/youtube/live.ts +1 -0
  444. package/lib/routes/youtube/playlist.ts +1 -0
  445. package/lib/routes/youtube/subscriptions.ts +1 -0
  446. package/lib/routes/youtube/user.ts +17 -5
  447. package/lib/routes/zaobao/interactive.ts +2 -11
  448. package/lib/routes/zaobao/{index.ts → other.ts} +2 -10
  449. package/lib/routes/zaobao/realtime.ts +0 -8
  450. package/lib/routes/zaobao/util.ts +14 -10
  451. package/lib/routes/zcool/discover.ts +2 -1
  452. package/lib/routes/zhihu/activities.ts +14 -41
  453. package/lib/routes/zhihu/answers.ts +3 -3
  454. package/lib/routes/zhihu/collection.ts +4 -4
  455. package/lib/routes/zhihu/daily-section.ts +3 -3
  456. package/lib/routes/zhihu/daily.ts +3 -3
  457. package/lib/routes/zhihu/hot.ts +56 -7
  458. package/lib/routes/zhihu/posts.ts +46 -39
  459. package/lib/routes/zhihu/question.ts +13 -41
  460. package/lib/routes/zhihu/timeline.ts +2 -2
  461. package/lib/routes/zhihu/topic.ts +8 -28
  462. package/lib/routes/zhihu/types.ts +104 -0
  463. package/lib/routes/zhihu/utils.ts +95 -46
  464. package/lib/routes/zhihu/xhu/activities.ts +8 -6
  465. package/lib/routes/zhihu/xhu/answers.ts +1 -1
  466. package/lib/routes/zhihu/xhu/collection.ts +1 -1
  467. package/lib/routes/zhihu/xhu/posts.ts +1 -1
  468. package/lib/routes/zhihu/xhu/question.ts +3 -3
  469. package/lib/routes/zhihu/xhu/topic.ts +4 -4
  470. package/lib/routes/zhihu/zhuanlan.ts +11 -5
  471. package/lib/routes/zhubai/top20.ts +2 -2
  472. package/lib/routes/zhuwang/index.ts +1 -1
  473. package/lib/routes/zjgtjy/index.ts +3 -9
  474. package/lib/types.ts +35 -2
  475. package/lib/utils/ofetch.ts +15 -1
  476. package/lib/utils/otel/index.ts +2 -0
  477. package/lib/utils/otel/metric.ts +66 -0
  478. package/lib/utils/otel/trace.ts +28 -0
  479. package/lib/utils/request-rewriter/fetch.ts +21 -2
  480. package/lib/utils/request-rewriter.test.ts +14 -0
  481. package/lib/views/atom.tsx +2 -2
  482. package/lib/views/error.tsx +4 -4
  483. package/lib/views/index.tsx +2 -2
  484. package/lib/views/json.ts +1 -1
  485. package/lib/views/rss.tsx +3 -2
  486. package/lib/views/rss3.test.ts +99 -0
  487. package/package.json +61 -49
  488. package/lib/routes/arknights/japan.ts +0 -50
  489. package/lib/routes/arknights/news.ts +0 -68
  490. package/lib/routes/ieee/earlyaccess.ts +0 -100
  491. package/lib/routes/ieee/recent.ts +0 -107
  492. package/lib/routes/yahoo/news/tw/index.ts +0 -80
  493. package/lib/routes/yahoo/news/us/index.ts +0 -55
  494. package/lib/routes/zhihu/hotlist.ts +0 -72
  495. package/lib/routes-deprecated/iplay/home.js +0 -26
  496. package/lib/routes-deprecated/iplay/utils.js +0 -57
  497. package/lib/routes-deprecated/matters/author.js +0 -49
  498. package/lib/routes-deprecated/matters/latest.js +0 -69
  499. package/lib/routes-deprecated/matters/tags.js +0 -56
  500. package/lib/routes-deprecated/universities/bjtu/gs/index.js +0 -130
  501. /package/lib/routes/{ft → ftchinese}/utils.ts +0 -0
  502. /package/lib/routes/gov/{shanghai → sh}/rsj/templates/ksxm.art +0 -0
  503. /package/lib/routes/gov/{shanghai → sh}/wgj/templates/wgj.art +0 -0
package/README.md CHANGED
@@ -10,8 +10,9 @@
10
10
  [![npm publish](https://img.shields.io/npm/dt/rsshub?label=npm%20downloads&logo=npm&style=flat-square)](https://www.npmjs.com/package/rsshub)
11
11
  [![test](https://img.shields.io/github/actions/workflow/status/DIYgod/RSSHub/test.yml?branch=master&label=test&logo=github&style=flat-square)](https://github.com/DIYgod/RSSHub/actions/workflows/test.yml?query=event%3Apush+branch%3Amaster)
12
12
  [![Test coverage](https://img.shields.io/codecov/c/github/DIYgod/RSSHub.svg?style=flat-square&logo=codecov)](https://app.codecov.io/gh/DIYgod/RSSHub/branch/master)
13
+ [![Visitors](https://hits.seeyoufarm.com/api/count/incr/badge.svg?url=https%3A%2F%2Fgithub.com%2FDIYgod%2FRSSHub&count_bg=%23FF752E&title_bg=%23555555&icon=rss.svg&icon_color=%23FF752E&title=RSS+lovers&edge_flat=true)](https://github.com/DIYgod/RSSHub)
13
14
 
14
- [![Telegram group](https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Fapi.swo.moe%2Fstats%2Ftelegram%2Frsshub&query=count&color=2CA5E0&label=Telegram%20Group&logo=telegram&cacheSeconds=3600&style=flat-square)](https://t.me/rsshub) [![Telegram channel](https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Fapi.swo.moe%2Fstats%2Ftelegram%2FawesomeRSSHub&query=count&color=2CA5E0&label=Telegram%20Channel&logo=telegram&cacheSeconds=3600&style=flat-square)](https://t.me/awesomeRSSHub) [![Twitter](https://img.shields.io/badge/any_text-Follow-blue?color=2CA5E0&label=Twitter&logo=twitter&cacheSeconds=3600&style=flat-square)](https://twitter.com/intent/follow?screen_name=_RSSHub)
15
+ [![Telegram group](https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Fapi.swo.moe%2Fstats%2Ftelegram%2Frsshub&query=count&color=2CA5E0&label=Telegram%20Group&logo=telegram&cacheSeconds=3600&style=flat-square)](https://t.me/rsshub) [![Telegram channel](https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Fapi.swo.moe%2Fstats%2Ftelegram%2FawesomeRSSHub&query=count&color=2CA5E0&label=Telegram%20Channel&logo=telegram&cacheSeconds=3600&style=flat-square)](https://t.me/awesomeRSSHub) [![Twitter](https://img.shields.io/badge/any_text-Follow-blue?color=2CA5E0&label=Twitter&logo=twitter&cacheSeconds=3600&style=flat-square)](https://x.com/intent/follow?screen_name=_RSSHub)
15
16
 
16
17
  ## Introduction
17
18
 
@@ -21,18 +22,10 @@ RSSHub delivers millions of contents aggregated from all kinds of sources, our v
21
22
 
22
23
  RSSHub can be used with browser extension [RSSHub Radar](https://github.com/DIYgod/RSSHub-Radar) and mobile auxiliary app [RSSBud](https://github.com/Cay-Zhang/RSSBud) (iOS) and [RSSAid](https://github.com/LeetaoGoooo/RSSAid) (Android)
23
24
 
24
- [English docs](https://docs.rsshub.app) | [Telegram Group](https://t.me/rsshub) | [Telegram Channel](https://t.me/awesomeRSSHub) | [Twitter](https://twitter.com/intent/follow?screen_name=_RSSHub) | [中文文档](https://docs.rsshub.app/zh/)
25
+ [English docs](https://docs.rsshub.app) | [Telegram Group](https://t.me/rsshub) | [Telegram Channel](https://t.me/awesomeRSSHub) | [Twitter](https://x.com/intent/follow?screen_name=_RSSHub) | [中文文档](https://docs.rsshub.app/zh/)
25
26
 
26
27
  ## Special Thanks
27
28
 
28
- ### Special Sponsors
29
-
30
- <p>
31
- <a href="https://rss3.io" target="_blank"><img height="50px" src="https://i.imgur.com/lb1dDGK.png"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="https://xlog.app/" target="_blank"><img height="50px" src="https://i.imgur.com/JuhHTKD.png"></a>
32
- </p>
33
-
34
- [![](https://opencollective.com/static/images/become_sponsor.svg)](https://docs.rsshub.app/sponsor/)
35
-
36
29
  ### Contributors
37
30
 
38
31
  [![](https://opencollective.com/RSSHub/contributors.svg?width=890)](https://github.com/DIYgod/RSSHub/graphs/contributors)
@@ -99,4 +92,4 @@ Open source is a very expensive thing. RSSHub would not be possible without the
99
92
  **RSSHub** © [DIYgod](https://github.com/DIYgod), Released under the [MIT](./LICENSE) License.<br>
100
93
  Authored and maintained by DIYgod with help from contributors ([list](https://github.com/DIYgod/RSSHub/contributors)).
101
94
 
102
- > Blog [@DIYgod](https://diygod.cc) · GitHub [@DIYgod](https://github.com/DIYgod) · Twitter [@DIYgod](https://twitter.com/DIYgod) · Telegram Channel [@awesomeDIYgod](https://t.me/awesomeDIYgod)
95
+ > Blog [@DIYgod](https://diygod.cc) · GitHub [@DIYgod](https://github.com/DIYgod) · Twitter [@DIYgod](https://x.com/DIYgod) · Telegram Channel [@awesomeDIYgod](https://t.me/awesomeDIYgod)
@@ -0,0 +1,54 @@
1
+ import { namespaces } from '@/registry';
2
+ import { z, createRoute, RouteHandler } from '@hono/zod-openapi';
3
+
4
+ const categoryList: Record<string, typeof namespaces> = {};
5
+
6
+ for (const namespace in namespaces) {
7
+ for (const path in namespaces[namespace].routes) {
8
+ if (namespaces[namespace].routes[path].categories?.length) {
9
+ for (const category of namespaces[namespace].routes[path].categories!) {
10
+ if (!categoryList[category]) {
11
+ categoryList[category] = {};
12
+ }
13
+ if (!categoryList[category][namespace]) {
14
+ categoryList[category][namespace] = {
15
+ ...namespaces[namespace],
16
+ routes: {},
17
+ };
18
+ }
19
+ categoryList[category][namespace].routes[path] = namespaces[namespace].routes[path];
20
+ }
21
+ }
22
+ }
23
+ }
24
+
25
+ const ParamsSchema = z.object({
26
+ category: z.string().openapi({
27
+ param: {
28
+ name: 'category',
29
+ in: 'path',
30
+ },
31
+ example: 'popular',
32
+ }),
33
+ });
34
+
35
+ const route = createRoute({
36
+ method: 'get',
37
+ path: '/category/{category}',
38
+ tags: ['Category'],
39
+ request: {
40
+ params: ParamsSchema,
41
+ },
42
+ responses: {
43
+ 200: {
44
+ description: 'Namespace list by category',
45
+ },
46
+ },
47
+ });
48
+
49
+ const handler: RouteHandler<typeof route> = (ctx) => {
50
+ const { category } = ctx.req.valid('param');
51
+ return ctx.json(categoryList[category]);
52
+ };
53
+
54
+ export { route, handler };
package/lib/api/index.ts CHANGED
@@ -3,8 +3,9 @@ import { route as namespaceAllRoute, handler as namespaceAllHandler } from '@/ap
3
3
  import { route as namespaceOneRoute, handler as namespaceOneHandler } from '@/api/namespace/one';
4
4
  import { route as radarRulesAllRoute, handler as radarRulesAllHandler } from '@/api/radar/rules/all';
5
5
  import { route as radarRulesOneRoute, handler as radarRulesOneHandler } from '@/api/radar/rules/one';
6
+ import { route as categoryOneRoute, handler as categoryOneHandler } from '@/api/category/one';
6
7
  import { OpenAPIHono } from '@hono/zod-openapi';
7
- import { swaggerUI } from '@hono/swagger-ui';
8
+ import { apiReference } from '@scalar/hono-api-reference';
8
9
 
9
10
  const app = new OpenAPIHono();
10
11
 
@@ -12,6 +13,7 @@ app.openapi(namespaceAllRoute, namespaceAllHandler);
12
13
  app.openapi(namespaceOneRoute, namespaceOneHandler);
13
14
  app.openapi(radarRulesAllRoute, radarRulesAllHandler);
14
15
  app.openapi(radarRulesOneRoute, radarRulesOneHandler);
16
+ app.openapi(categoryOneRoute, categoryOneHandler);
15
17
 
16
18
  const docs = app.getOpenAPI31Document({
17
19
  openapi: '3.1.0',
@@ -24,8 +26,12 @@ for (const path in docs.paths) {
24
26
  docs.paths[`/api${path}`] = docs.paths[path];
25
27
  delete docs.paths[path];
26
28
  }
27
- app.get('/docs', (ctx) => ctx.json(docs));
28
-
29
- app.get('/ui', swaggerUI({ url: '/api/docs' }));
29
+ app.get('/openapi.json', (ctx) => ctx.json(docs));
30
+ app.get(
31
+ '/reference',
32
+ apiReference({
33
+ spec: { content: docs },
34
+ })
35
+ );
30
36
 
31
37
  export default app;
package/lib/app.tsx CHANGED
@@ -12,6 +12,7 @@ import debug from '@/middleware/debug';
12
12
  import header from '@/middleware/header';
13
13
  import antiHotlink from '@/middleware/anti-hotlink';
14
14
  import parameter from '@/middleware/parameter';
15
+ import trace from '@/middleware/trace';
15
16
  import { jsxRenderer } from 'hono/jsx-renderer';
16
17
  import { trimTrailingSlash } from 'hono/trailing-slash';
17
18
 
@@ -37,6 +38,7 @@ app.use(
37
38
  })
38
39
  );
39
40
  app.use(mLogger);
41
+ app.use(trace);
40
42
  app.use(sentry);
41
43
  app.use(accessControl);
42
44
  app.use(debug);
package/lib/config.ts CHANGED
@@ -1,5 +1,5 @@
1
- import 'dotenv/config';
2
1
  import randUserAgent from '@/utils/rand-user-agent';
2
+ import 'dotenv/config';
3
3
  import { ofetch } from 'ofetch';
4
4
 
5
5
  let envs = process.env;
@@ -39,8 +39,8 @@ export type Config = {
39
39
  port?: string;
40
40
  auth?: string;
41
41
  url_regex: string;
42
+ strategy: 'on_retry' | 'all';
42
43
  };
43
- proxyStrategy: string;
44
44
  pacUri?: string;
45
45
  pacScript?: string;
46
46
  accessKey?: string;
@@ -154,7 +154,6 @@ export type Config = {
154
154
  username?: string;
155
155
  password?: string;
156
156
  bearertoken?: string;
157
- iap_receipt?: string;
158
157
  };
159
158
  instagram: {
160
159
  username?: string;
@@ -233,6 +232,9 @@ export type Config = {
233
232
  qingting: {
234
233
  id?: string;
235
234
  };
235
+ readwise: {
236
+ accessToken?: string;
237
+ };
236
238
  saraba1st: {
237
239
  cookie?: string;
238
240
  };
@@ -250,19 +252,23 @@ export type Config = {
250
252
  clientSecret?: string;
251
253
  refreshToken?: string;
252
254
  };
255
+ sspai: {
256
+ bearertoken?: string;
257
+ };
253
258
  telegram: {
254
259
  token?: string;
255
260
  };
256
261
  tophub: {
257
262
  cookie?: string;
258
263
  };
264
+ tsdm39: {
265
+ cookie: string;
266
+ };
259
267
  twitter: {
260
- oauthTokens?: string[];
261
- oauthTokenSecrets?: string[];
262
- username?: string;
263
- password?: string;
264
- authenticationSecret?: string;
265
- cookie?: string;
268
+ username?: string[];
269
+ password?: string[];
270
+ authenticationSecret?: string[];
271
+ authToken?: string[];
266
272
  };
267
273
  weibo: {
268
274
  app_key?: string;
@@ -283,6 +289,10 @@ export type Config = {
283
289
  ximalaya: {
284
290
  token?: string;
285
291
  };
292
+ xsijishe: {
293
+ cookie?: string;
294
+ userAgent?: string;
295
+ };
286
296
  xueqiu: {
287
297
  cookies?: string;
288
298
  };
@@ -388,8 +398,8 @@ const calculateValue = () => {
388
398
  port: envs.PROXY_PORT,
389
399
  auth: envs.PROXY_AUTH,
390
400
  url_regex: envs.PROXY_URL_REGEX || '.*',
401
+ strategy: envs.PROXY_STRATEGY || 'all', // all / on_retry
391
402
  },
392
- proxyStrategy: envs.PROXY_STRATEGY || 'all', // all / on_retry
393
403
  pacUri: envs.PAC_URI,
394
404
  pacScript: envs.PAC_SCRIPT,
395
405
  // access control
@@ -510,7 +520,6 @@ const calculateValue = () => {
510
520
  username: envs.INITIUM_USERNAME,
511
521
  password: envs.INITIUM_PASSWORD,
512
522
  bearertoken: envs.INITIUM_BEARER_TOKEN,
513
- iap_receipt: envs.INITIUM_IAP_RECEIPT,
514
523
  },
515
524
  instagram: {
516
525
  username: envs.IG_USERNAME,
@@ -589,6 +598,9 @@ const calculateValue = () => {
589
598
  qingting: {
590
599
  id: envs.QINGTING_ID,
591
600
  },
601
+ readwise: {
602
+ accessToken: envs.READWISE_ACCESS_TOKEN,
603
+ },
592
604
  saraba1st: {
593
605
  cookie: envs.SARABA1ST_COOKIE,
594
606
  },
@@ -606,6 +618,9 @@ const calculateValue = () => {
606
618
  clientSecret: envs.SPOTIFY_CLIENT_SECRET,
607
619
  refreshToken: envs.SPOTIFY_REFRESHTOKEN,
608
620
  },
621
+ sspai: {
622
+ bearertoken: envs.SSPAI_BEARERTOKEN,
623
+ },
609
624
  telegram: {
610
625
  token: envs.TELEGRAM_TOKEN,
611
626
  session: envs.TELEGRAM_SESSION,
@@ -616,13 +631,14 @@ const calculateValue = () => {
616
631
  tophub: {
617
632
  cookie: envs.TOPHUB_COOKIE,
618
633
  },
634
+ tsdm39: {
635
+ cookie: envs.TSDM39_COOKIES,
636
+ },
619
637
  twitter: {
620
- oauthTokens: envs.TWITTER_OAUTH_TOKEN?.split(','),
621
- oauthTokenSecrets: envs.TWITTER_OAUTH_TOKEN_SECRET?.split(','),
622
- username: envs.TWITTER_USERNAME,
623
- password: envs.TWITTER_PASSWORD,
624
- authenticationSecret: envs.TWITTER_AUTHENTICATION_SECRET,
625
- cookie: envs.TWITTER_COOKIE,
638
+ username: envs.TWITTER_USERNAME?.split(','),
639
+ password: envs.TWITTER_PASSWORD?.split(','),
640
+ authenticationSecret: envs.TWITTER_AUTHENTICATION_SECRET?.split(','),
641
+ authToken: envs.TWITTER_AUTH_TOKEN?.split(','),
626
642
  },
627
643
  weibo: {
628
644
  app_key: envs.WEIBO_APP_KEY,
@@ -643,6 +659,10 @@ const calculateValue = () => {
643
659
  ximalaya: {
644
660
  token: envs.XIMALAYA_TOKEN,
645
661
  },
662
+ xsijishe: {
663
+ cookie: envs.XSIJISHE_COOKIE,
664
+ user_agent: envs.XSIJISHE_USER_AGENT,
665
+ },
646
666
  xueqiu: {
647
667
  cookies: envs.XUEQIU_COOKIES,
648
668
  },
@@ -693,6 +713,26 @@ calculateValue();
693
713
  logger.error('Remote config load failed.', error);
694
714
  }
695
715
  }
716
+
717
+ if (!envs.DISABLE_UMAMI && envs.NODE_ENV === 'production') {
718
+ ofetch(`https://umami.rss3.io/api/send`, {
719
+ method: 'POST',
720
+ headers: {
721
+ 'content-type': 'application/json',
722
+ 'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36',
723
+ },
724
+ body: JSON.stringify({
725
+ payload: {
726
+ hostname: 'rsshub.app',
727
+ language: 'en-US',
728
+ referrer: 'rsshub.app',
729
+ url: 'rsshub.app',
730
+ website: '239067cd-231f-4a3f-a478-cced11a84876',
731
+ },
732
+ type: 'event',
733
+ }),
734
+ });
735
+ }
696
736
  })();
697
737
 
698
738
  // @ts-expect-error value is set
@@ -27,8 +27,12 @@ describe('httperror', () => {
27
27
  });
28
28
 
29
29
  describe('RequestInProgressError', () => {
30
- it(`RequestInProgressError`, async () => {
30
+ it(`RequestInProgressError with retry`, async () => {
31
31
  const responses = await Promise.all([request.get('/test/slow'), request.get('/test/slow')]);
32
+ expect(new Set(responses.map((r) => r.status))).toEqual(new Set([200, 200]));
33
+ });
34
+ it(`RequestInProgressError`, async () => {
35
+ const responses = await Promise.all([request.get('/test/slow4'), request.get('/test/slow4')]);
32
36
  expect(new Set(responses.map((r) => r.status))).toEqual(new Set([200, 503]));
33
37
  expect(new Set(responses.map((r) => r.headers['cache-control']))).toEqual(new Set([`public, max-age=${config.cache.routeExpire}`, `public, max-age=${config.requestTimeout / 1000}`]));
34
38
  expect(responses.filter((r) => r.text.includes('RequestInProgressError: This path is currently fetching, please come back later!'))).toHaveLength(1);
@@ -63,19 +67,19 @@ describe('route throws an error', () => {
63
67
  const value = $(item).find('.debug-value').html()?.trim();
64
68
  switch (key) {
65
69
  case 'Request Amount:':
66
- expect(value).toBe('9');
70
+ expect(value).toBe('11');
67
71
  break;
68
72
  case 'Hot Routes:':
69
- expect(value).toBe('6 /test/:id/:params?<br>');
73
+ expect(value).toBe('8 /test/:id/:params?<br>');
70
74
  break;
71
75
  case 'Hot Paths:':
72
- expect(value).toBe('2 /test/error<br>2 /test/slow<br>1 /test/httperror<br>1 /test/config-not-found-error<br>1 /test/invalid-parameter-error<br>1 /thisDoesNotExist<br>1 /<br>');
76
+ expect(value).toBe('2 /test/error<br>2 /test/slow<br>2 /test/slow4<br>1 /test/httperror<br>1 /test/config-not-found-error<br>1 /test/invalid-parameter-error<br>1 /thisDoesNotExist<br>1 /<br>');
73
77
  break;
74
78
  case 'Hot Error Routes:':
75
79
  expect(value).toBe('5 /test/:id/:params?<br>');
76
80
  break;
77
81
  case 'Hot Error Paths:':
78
- expect(value).toBe('2 /test/error<br>1 /test/httperror<br>1 /test/slow<br>1 /test/config-not-found-error<br>1 /test/invalid-parameter-error<br>1 /thisDoesNotExist<br>');
82
+ expect(value).toBe('2 /test/error<br>1 /test/httperror<br>1 /test/slow4<br>1 /test/config-not-found-error<br>1 /test/invalid-parameter-error<br>1 /thisDoesNotExist<br>');
79
83
  break;
80
84
  default:
81
85
  }
@@ -1,20 +1,26 @@
1
1
  import { type NotFoundHandler, type ErrorHandler } from 'hono';
2
2
  import { getDebugInfo, setDebugInfo } from '@/utils/debug-info';
3
3
  import { config } from '@/config';
4
- import Sentry from '@sentry/node';
4
+ import * as Sentry from '@sentry/node';
5
5
  import logger from '@/utils/logger';
6
6
  import Error from '@/views/error';
7
7
 
8
8
  import NotFoundError from './types/not-found';
9
9
 
10
+ import { requestMetric } from '@/utils/otel';
11
+
10
12
  export const errorHandler: ErrorHandler = (error, ctx) => {
11
13
  const requestPath = ctx.req.path;
12
14
  const matchedRoute = ctx.req.routePath;
13
15
  const hasMatchedRoute = matchedRoute !== '/*';
14
16
 
15
17
  const debug = getDebugInfo();
16
- if (ctx.res.headers.get('RSSHub-Cache-Status')) {
17
- debug.hitCache++;
18
+ try {
19
+ if (ctx.res.headers.get('RSSHub-Cache-Status')) {
20
+ debug.hitCache++;
21
+ }
22
+ } catch {
23
+ // ignore
18
24
  }
19
25
  debug.error++;
20
26
 
@@ -61,6 +67,7 @@ export const errorHandler: ErrorHandler = (error, ctx) => {
61
67
  const message = `${error.name}: ${errorMessage}`;
62
68
 
63
69
  logger.error(`Error in ${requestPath}: ${message}`);
70
+ requestMetric.error({ path: requestPath, method: ctx.req.method, status: ctx.res.status });
64
71
 
65
72
  return config.isPackage
66
73
  ? ctx.json({
package/lib/index.ts CHANGED
@@ -10,12 +10,15 @@ const hostIPList = getLocalhostAddress();
10
10
  logger.info(`🎉 RSSHub is running on port ${port}! Cheers!`);
11
11
  logger.info('💖 Can you help keep this open source project alive? Please sponsor 👉 https://docs.rsshub.app/sponsor');
12
12
  logger.info(`🔗 Local: 👉 http://localhost:${port}`);
13
- for (const ip of hostIPList) {
14
- logger.info(`🔗 Network: 👉 http://${ip}:${port}`);
13
+ if (config.listenInaddrAny) {
14
+ for (const ip of hostIPList) {
15
+ logger.info(`🔗 Network: 👉 http://${ip}:${port}`);
16
+ }
15
17
  }
16
18
 
17
19
  const server = serve({
18
20
  fetch: app.fetch,
21
+ hostname: config.listenInaddrAny ? undefined : '127.0.0.1',
19
22
  port,
20
23
  });
21
24
 
@@ -36,7 +36,7 @@ const expects = {
36
36
  `<a href="https://mock.com/DIYgod/RSSHub"></a>
37
37
  <img src="https://mock.com/DIYgod/RSSHub.jpg" referrerpolicy="no-referrer">`,
38
38
  ],
39
- desc: '<img src="http://mock.com/DIYgod/DIYgod/RSSHub"> - Made with love by RSSHub(https://github.com/DIYgod/RSSHub)',
39
+ desc: '<img src="http://mock.com/DIYgod/DIYgod/RSSHub"> - Powered by RSSHub',
40
40
  },
41
41
  processed: {
42
42
  items: [
@@ -54,7 +54,7 @@ const expects = {
54
54
  `<a href="https://mock.com/DIYgod/RSSHub"></a>
55
55
  <img src="https://i3.wp.com/mock.com/DIYgod/RSSHub.jpg" referrerpolicy="no-referrer">`,
56
56
  ],
57
- desc: '<img src="https://i3.wp.com/mock.com/DIYgod/DIYgod/RSSHub"> - Made with love by RSSHub(https://github.com/DIYgod/RSSHub)',
57
+ desc: '<img src="https://i3.wp.com/mock.com/DIYgod/DIYgod/RSSHub"> - Powered by RSSHub',
58
58
  },
59
59
  urlencoded: {
60
60
  items: [
@@ -72,7 +72,7 @@ const expects = {
72
72
  `<a href="https://mock.com/DIYgod/RSSHub"></a>
73
73
  <img src="https://images.weserv.nl?url=https%3A%2F%2Fmock.com%2FDIYgod%2FRSSHub.jpg" referrerpolicy="no-referrer">`,
74
74
  ],
75
- desc: '<img src="https://images.weserv.nl?url=http%3A%2F%2Fmock.com%2FDIYgod%2FDIYgod%2FRSSHub"> - Made with love by RSSHub(https://github.com/DIYgod/RSSHub)',
75
+ desc: '<img src="https://images.weserv.nl?url=http%3A%2F%2Fmock.com%2FDIYgod%2FDIYgod%2FRSSHub"> - Powered by RSSHub',
76
76
  },
77
77
  },
78
78
  multimedia: {
@@ -87,7 +87,7 @@ const expects = {
87
87
  <audio src="https://mock.com/DIYgod/RSSHub.mp3"></audio>
88
88
  <iframe src="https://mock.com/DIYgod/RSSHub.html" referrerpolicy="no-referrer"></iframe>`,
89
89
  ],
90
- desc: '<video src="http://mock.com/DIYgod/DIYgod/RSSHub"></video> - Made with love by RSSHub(https://github.com/DIYgod/RSSHub)',
90
+ desc: '<video src="http://mock.com/DIYgod/DIYgod/RSSHub"></video> - Powered by RSSHub',
91
91
  },
92
92
  relayed: {
93
93
  items: [
@@ -100,7 +100,7 @@ const expects = {
100
100
  <audio src="https://i3.wp.com/mock.com/DIYgod/RSSHub.mp3"></audio>
101
101
  <iframe src="https://mock.com/DIYgod/RSSHub.html" referrerpolicy="no-referrer"></iframe>`,
102
102
  ],
103
- desc: '<video src="https://i3.wp.com/mock.com/DIYgod/DIYgod/RSSHub"></video> - Made with love by RSSHub(https://github.com/DIYgod/RSSHub)',
103
+ desc: '<video src="https://i3.wp.com/mock.com/DIYgod/DIYgod/RSSHub"></video> - Powered by RSSHub',
104
104
  },
105
105
  partlyRelayed: {
106
106
  items: [
@@ -113,7 +113,7 @@ const expects = {
113
113
  <audio src="https://i3.wp.com/mock.com/DIYgod/RSSHub.mp3"></audio>
114
114
  <iframe src="https://mock.com/DIYgod/RSSHub.html" referrerpolicy="no-referrer"></iframe>`,
115
115
  ],
116
- desc: '<video src="https://i3.wp.com/mock.com/DIYgod/DIYgod/RSSHub"></video> - Made with love by RSSHub(https://github.com/DIYgod/RSSHub)',
116
+ desc: '<video src="https://i3.wp.com/mock.com/DIYgod/DIYgod/RSSHub"></video> - Powered by RSSHub',
117
117
  },
118
118
  },
119
119
  };
@@ -6,23 +6,38 @@ import RequestInProgressError from '@/errors/types/request-in-progress';
6
6
  import cacheModule from '@/utils/cache/index';
7
7
  import { Data } from '@/types';
8
8
 
9
+ const bypassList = new Set(['/', '/robots.txt', '/logo.png', '/favicon.ico']);
9
10
  // only give cache string, as the `!` condition tricky
10
11
  // md5 is used to shrink key size
11
12
  // plz, write these tips in comments!
12
13
  const middleware: MiddlewareHandler = async (ctx, next) => {
13
- const { h64ToString } = await xxhash();
14
- const key = 'rsshub:koa-redis-cache:' + h64ToString(ctx.req.path);
15
- const controlKey = 'rsshub:path-requested:' + h64ToString(ctx.req.path);
16
-
17
- if (!cacheModule.status.available) {
14
+ if (!cacheModule.status.available || bypassList.has(ctx.req.path)) {
18
15
  await next();
19
16
  return;
20
17
  }
21
18
 
19
+ const { h64ToString } = await xxhash();
20
+ const key = 'rsshub:koa-redis-cache:' + h64ToString(ctx.req.path);
21
+ const controlKey = 'rsshub:path-requested:' + h64ToString(ctx.req.path);
22
+
22
23
  const isRequesting = await cacheModule.globalCache.get(controlKey);
23
24
 
24
25
  if (isRequesting === '1') {
25
- throw new RequestInProgressError('This path is currently fetching, please come back later!');
26
+ let retryTimes = process.env.NODE_ENV === 'test' ? 1 : 10;
27
+ let bypass = false;
28
+ while (retryTimes > 0) {
29
+ // eslint-disable-next-line no-await-in-loop
30
+ await new Promise((resolve) => setTimeout(resolve, process.env.NODE_ENV === 'test' ? 3000 : 6000));
31
+ // eslint-disable-next-line no-await-in-loop
32
+ if ((await cacheModule.globalCache.get(controlKey)) !== '1') {
33
+ bypass = true;
34
+ break;
35
+ }
36
+ retryTimes--;
37
+ }
38
+ if (!bypass) {
39
+ throw new RequestInProgressError('This path is currently fetching, please come back later!');
40
+ }
26
41
  }
27
42
 
28
43
  const value = await cacheModule.globalCache.get(key);
@@ -1,3 +1,4 @@
1
+ import { requestMetric } from '@/utils/otel';
1
2
  import { MiddlewareHandler } from 'hono';
2
3
  import logger from '@/utils/logger';
3
4
  import { getPath, time } from '@/utils/helpers';
@@ -34,7 +35,10 @@ const middleware: MiddlewareHandler = async (ctx, next) => {
34
35
 
35
36
  await next();
36
37
 
37
- logger.info(`${LogPrefix.Outgoing} ${method} ${path} ${colorStatus(ctx.res.status)} ${time(start)}`);
38
+ const status = ctx.res.status;
39
+
40
+ logger.info(`${LogPrefix.Outgoing} ${method} ${path} ${colorStatus(status)} ${time(start)}`);
41
+ requestMetric.success(Date.now() - start, { path, method, status });
38
42
  };
39
43
 
40
44
  export default middleware;
@@ -53,7 +53,7 @@ const middleware: MiddlewareHandler = async (ctx, next) => {
53
53
  // https://stackoverflow.com/questions/1497885/remove-control-characters-from-php-string/1497928#1497928
54
54
  // remove unicode control characters
55
55
  // see #14940 #14943 #15262
56
- item.description = item.description.replaceAll(/[\u0000-\u0009\u000B\u000C\u000E-\u001F\u007F]/g, '');
56
+ item.description = item.description.replaceAll(/[\u0000-\u0009\u000B\u000C\u000E-\u001F\u007F\u200B\uFFFF]/g, '');
57
57
  }
58
58
 
59
59
  if (typeof item.author === 'string') {
@@ -94,18 +94,22 @@ const middleware: MiddlewareHandler = async (ctx, next) => {
94
94
  return ctx.json(result);
95
95
  }
96
96
 
97
- // retain .ums for backward compatibility
98
- if (outputType === 'ums' || outputType === 'rss3') {
99
- return ctx.json(rss3(result));
100
- } else if (outputType === 'json') {
101
- ctx.header('Content-Type', 'application/feed+json; charset=UTF-8');
102
- return ctx.body(json(result));
103
- } else if (ctx.get('no-content')) {
97
+ if (ctx.get('no-content')) {
104
98
  return ctx.body(null);
105
- } else if (outputType === 'atom') {
106
- return ctx.render(<Atom data={result} />);
107
99
  } else {
108
- return ctx.render(<RSS data={result} />);
100
+ // retain .ums for backward compatibility
101
+ switch (outputType) {
102
+ case 'ums':
103
+ case 'rss3':
104
+ return ctx.json(rss3(result));
105
+ case 'json':
106
+ ctx.header('Content-Type', 'application/feed+json; charset=UTF-8');
107
+ return ctx.body(json(result));
108
+ case 'atom':
109
+ return ctx.render(<Atom data={result} />);
110
+ default:
111
+ return ctx.render(<RSS data={result} />);
112
+ }
109
113
  }
110
114
  };
111
115
 
@@ -0,0 +1,25 @@
1
+ import { MiddlewareHandler } from 'hono';
2
+ import { getPath } from '@/utils/helpers';
3
+ import { config } from '@/config';
4
+ import { tracer } from '@/utils/otel';
5
+
6
+ const middleware: MiddlewareHandler = async (ctx, next) => {
7
+ if (config.debugInfo) {
8
+ // Only enable tracing in debug mode
9
+ const { method, raw } = ctx.req;
10
+ const path = getPath(raw);
11
+
12
+ const span = tracer.startSpan(`${method} ${path}`, {
13
+ kind: 1, // server
14
+ attributes: {},
15
+ });
16
+ span.addEvent('invoking handleRequest');
17
+ await next();
18
+ span.end();
19
+ } else {
20
+ // Skip
21
+ await next();
22
+ }
23
+ };
24
+
25
+ export default middleware;
package/lib/registry.ts CHANGED
@@ -4,9 +4,11 @@ import { Hono, type Handler } from 'hono';
4
4
  import path from 'node:path';
5
5
  import { fileURLToPath } from 'node:url';
6
6
  import { serveStatic } from '@hono/node-server/serve-static';
7
+ import { config } from '@/config';
7
8
 
8
9
  import index from '@/routes/index';
9
10
  import robotstxt from '@/routes/robots.txt';
11
+ import metrics from '@/routes/metrics';
10
12
 
11
13
  const __dirname = path.dirname(fileURLToPath(import.meta.url));
12
14
 
@@ -84,7 +86,7 @@ const app = new Hono();
84
86
  for (const namespace in namespaces) {
85
87
  const subApp = app.basePath(`/${namespace}`);
86
88
  for (const path in namespaces[namespace].routes) {
87
- const wrapedHandler: Handler = async (ctx) => {
89
+ const wrappedHandler: Handler = async (ctx) => {
88
90
  if (!ctx.get('data')) {
89
91
  if (typeof namespaces[namespace].routes[path].handler !== 'function') {
90
92
  const { route } = await import(`./routes/${namespace}/${namespaces[namespace].routes[path].location}`);
@@ -93,12 +95,16 @@ for (const namespace in namespaces) {
93
95
  ctx.set('data', await namespaces[namespace].routes[path].handler(ctx));
94
96
  }
95
97
  };
96
- subApp.get(path, wrapedHandler);
98
+ subApp.get(path, wrappedHandler);
97
99
  }
98
100
  }
99
101
 
100
102
  app.get('/', index);
101
103
  app.get('/robots.txt', robotstxt);
104
+ if (config.debugInfo) {
105
+ // Only enable tracing in debug mode
106
+ app.get('/metrics', metrics);
107
+ }
102
108
  app.use(
103
109
  '/*',
104
110
  serveStatic({
package/lib/router.js CHANGED
@@ -594,12 +594,6 @@ router.get('/zucc/cssearch/latest/:webVpn/:key', lazyloadRouteHandler('./routes/
594
594
  // checkee
595
595
  router.get('/checkee/:dispdate', lazyloadRouteHandler('./routes/checkee/index'));
596
596
 
597
- // Matters
598
- router.get('/matters/latest/:type?', lazyloadRouteHandler('./routes/matters/latest'));
599
- router.redirect('/matters/hot', '/matters/latest/heat'); // Deprecated
600
- router.get('/matters/tags/:tid', lazyloadRouteHandler('./routes/matters/tags'));
601
- router.get('/matters/author/:uid', lazyloadRouteHandler('./routes/matters/author'));
602
-
603
597
  // 古诗文网
604
598
  router.get('/gushiwen/recommend/:annotation?', lazyloadRouteHandler('./routes/gushiwen/recommend'));
605
599