rsshub 1.0.0-master.f7cdf8b → 1.0.0-master.f7f8b7a

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 (273) hide show
  1. package/README.md +3 -3
  2. package/lib/config.js +21 -8
  3. package/lib/middleware/cache/index.js +4 -3
  4. package/lib/middleware/cache/redis.js +3 -3
  5. package/lib/middleware/onerror.js +8 -0
  6. package/lib/middleware/template.js +79 -85
  7. package/lib/router.js +7 -7
  8. package/lib/routes/index.js +6 -13
  9. package/lib/utils/common-utils.js +2 -6
  10. package/lib/utils/render.js +2 -0
  11. package/lib/v2/1point3acres/maintainer.js +2 -2
  12. package/lib/v2/95mm/utils.js +3 -2
  13. package/lib/v2/aliyun/notice.js +1 -1
  14. package/lib/v2/amazon/maintainer.js +1 -1
  15. package/lib/v2/apnews/topics.js +1 -1
  16. package/lib/v2/arcteryx/maintainer.js +3 -3
  17. package/lib/v2/bangumi/maintainer.js +1 -0
  18. package/lib/v2/bangumi/radar.js +6 -0
  19. package/lib/v2/bangumi/router.js +1 -0
  20. package/lib/v2/bangumi/tv/user/wish.js +38 -0
  21. package/lib/v2/bellroy/maintainer.js +1 -1
  22. package/lib/v2/bilibili/cache.js +10 -7
  23. package/lib/v2/bilibili/maintainer.js +1 -0
  24. package/lib/v2/bilibili/platform.js +43 -0
  25. package/lib/v2/bilibili/radar.js +8 -0
  26. package/lib/v2/bilibili/router.js +1 -0
  27. package/lib/v2/bilibili/video.js +8 -1
  28. package/lib/v2/bossdesign/index.js +41 -0
  29. package/lib/v2/bossdesign/maintainer.js +3 -0
  30. package/lib/v2/bossdesign/radar.js +13 -0
  31. package/lib/v2/bossdesign/router.js +3 -0
  32. package/lib/v2/brave/latest.js +4 -2
  33. package/lib/v2/buaa/maintainer.js +4 -0
  34. package/lib/v2/buaa/news/index.js +46 -0
  35. package/lib/v2/buaa/radar.js +21 -0
  36. package/lib/v2/buaa/router.js +4 -0
  37. package/lib/v2/buaa/sme.js +59 -0
  38. package/lib/v2/cfachina/analygarden.js +60 -0
  39. package/lib/v2/cfachina/maintainer.js +3 -0
  40. package/lib/v2/cfachina/radar.js +13 -0
  41. package/lib/v2/cfachina/router.js +3 -0
  42. package/lib/v2/cna/maintainer.js +1 -0
  43. package/lib/v2/cna/radar.js +6 -0
  44. package/lib/v2/cna/router.js +1 -0
  45. package/lib/v2/cna/web/index.js +62 -0
  46. package/lib/v2/cste/radar.js +1 -1
  47. package/lib/v2/dahecube/radar.js +40 -4
  48. package/lib/v2/dongqiudi/utils.js +1 -1
  49. package/lib/v2/douban/maintainer.js +1 -0
  50. package/lib/v2/douban/other/discussion.js +58 -0
  51. package/lib/v2/douban/radar.js +8 -0
  52. package/lib/v2/douban/router.js +1 -0
  53. package/lib/v2/dut/defaults.js +4 -0
  54. package/lib/v2/dut/index.js +21 -9
  55. package/lib/v2/dut/maintainer.js +8 -7
  56. package/lib/v2/dut/radar.js +37 -29
  57. package/lib/v2/dut/shortcuts.js +5 -0
  58. package/lib/v2/egsea/flash.js +30 -0
  59. package/lib/v2/egsea/maintainer.js +3 -0
  60. package/lib/v2/egsea/radar.js +13 -0
  61. package/lib/v2/egsea/router.js +3 -0
  62. package/lib/v2/fisher-spb/news.js +1 -2
  63. package/lib/v2/fosshub/radar.js +1 -1
  64. package/lib/v2/fxiaoke/crm.js +63 -0
  65. package/lib/v2/fxiaoke/maintainer.js +3 -0
  66. package/lib/v2/fxiaoke/radar.js +37 -0
  67. package/lib/v2/fxiaoke/router.js +3 -0
  68. package/lib/v2/gdsrx/index.js +72 -0
  69. package/lib/v2/gdsrx/maintainer.js +3 -0
  70. package/lib/v2/gdsrx/radar.js +61 -0
  71. package/lib/v2/gdsrx/router.js +3 -0
  72. package/lib/v2/gogoanimehd/radar.js +1 -1
  73. package/lib/v2/gogoanimehd/recent-releases.js +1 -1
  74. package/lib/v2/google/alerts.js +33 -0
  75. package/lib/v2/google/maintainer.js +1 -0
  76. package/lib/v2/google/router.js +1 -0
  77. package/lib/v2/gov/maintainer.js +9 -2
  78. package/lib/v2/gov/moa/zdscxx.js +104 -0
  79. package/lib/v2/gov/mot/index.js +66 -0
  80. package/lib/v2/gov/nea/ghs.js +58 -0
  81. package/lib/v2/gov/nifdc/index.js +40 -33
  82. package/lib/v2/gov/radar.js +232 -4
  83. package/lib/v2/gov/router.js +10 -2
  84. package/lib/v2/gov/safe/business.js +8 -0
  85. package/lib/v2/gov/safe/complaint.js +8 -0
  86. package/lib/v2/gov/safe/templates/message.art +25 -0
  87. package/lib/v2/gov/safe/util.js +87 -0
  88. package/lib/v2/gov/zhengce/index.js +99 -0
  89. package/lib/v2/greasyfork/maintainer.js +1 -0
  90. package/lib/v2/greasyfork/router.js +1 -0
  91. package/lib/v2/greasyfork/scripts.js +25 -20
  92. package/lib/{routes/universities → v2}/harvard/health/blog.js +8 -7
  93. package/lib/v2/harvard/maintainer.js +3 -0
  94. package/lib/v2/harvard/radar.js +13 -0
  95. package/lib/v2/harvard/router.js +3 -0
  96. package/lib/v2/huxiu/briefColumn.js +13 -25
  97. package/lib/v2/huxiu/channel.js +28 -0
  98. package/lib/v2/huxiu/club.js +30 -0
  99. package/lib/v2/huxiu/collection.js +14 -26
  100. package/lib/v2/huxiu/maintainer.js +8 -5
  101. package/lib/v2/huxiu/member.js +27 -0
  102. package/lib/v2/huxiu/moment.js +11 -25
  103. package/lib/v2/huxiu/radar.js +24 -16
  104. package/lib/v2/huxiu/router.js +7 -4
  105. package/lib/v2/huxiu/search.js +16 -21
  106. package/lib/v2/huxiu/tag.js +13 -25
  107. package/lib/v2/huxiu/templates/description.art +46 -0
  108. package/lib/v2/huxiu/util.js +460 -0
  109. package/lib/v2/ifi-audio/maintainer.js +1 -1
  110. package/lib/v2/imiker/jinghua.js +87 -0
  111. package/lib/v2/imiker/maintainer.js +3 -0
  112. package/lib/v2/imiker/radar.js +13 -0
  113. package/lib/v2/imiker/router.js +3 -0
  114. package/lib/v2/imiker/templates/description.art +32 -0
  115. package/lib/v2/inoreader/maintainer.js +1 -1
  116. package/lib/v2/instagram/common-utils.js +7 -4
  117. package/lib/v2/instagram/templates/images.art +9 -2
  118. package/lib/v2/instagram/templates/video.art +4 -1
  119. package/lib/v2/instagram/web-api/index.js +30 -9
  120. package/lib/v2/instagram/web-api/utils.js +149 -25
  121. package/lib/v2/kemono/index.js +26 -2
  122. package/lib/v2/kemono/radar.js +1 -1
  123. package/lib/v2/kepu/live.js +89 -0
  124. package/lib/v2/kepu/maintainer.js +3 -0
  125. package/lib/v2/kepu/radar.js +13 -0
  126. package/lib/v2/kepu/router.js +3 -0
  127. package/lib/v2/kepu/templates/description.art +33 -0
  128. package/lib/v2/leetcode/maintainer.js +1 -1
  129. package/lib/v2/lightnovel/lightNovel.js +62 -0
  130. package/lib/v2/lightnovel/maintainer.js +3 -0
  131. package/lib/v2/lightnovel/radar.js +13 -0
  132. package/lib/v2/lightnovel/router.js +3 -0
  133. package/lib/v2/line/radar.js +1 -1
  134. package/lib/v2/liquipedia/cs_matches.js +52 -0
  135. package/lib/v2/liquipedia/dota2_matches.js +47 -0
  136. package/lib/v2/liquipedia/maintainer.js +4 -0
  137. package/lib/v2/liquipedia/radar.js +19 -0
  138. package/lib/v2/liquipedia/router.js +4 -0
  139. package/lib/v2/magazinelib/maintainer.js +1 -1
  140. package/lib/v2/mihoyo/radar.js +1 -1
  141. package/lib/v2/missav/maintainer.js +3 -0
  142. package/lib/v2/missav/new.js +36 -0
  143. package/lib/v2/missav/radar.js +13 -0
  144. package/lib/v2/missav/router.js +3 -0
  145. package/lib/v2/missav/templates/preview.art +3 -0
  146. package/lib/v2/modb/maintainer.js +3 -0
  147. package/lib/v2/modb/radar.js +13 -0
  148. package/lib/v2/modb/router.js +3 -0
  149. package/lib/v2/modb/topic.js +59 -0
  150. package/lib/v2/nature/cover.js +32 -42
  151. package/lib/v2/nature/highlight.js +2 -2
  152. package/lib/v2/nature/news-and-comment.js +2 -2
  153. package/lib/v2/nature/news.js +2 -2
  154. package/lib/v2/nature/research.js +2 -2
  155. package/lib/v2/nature/siteindex.js +5 -5
  156. package/lib/v2/nature/utils.js +124 -5
  157. package/lib/v2/ncu/jwc.js +33 -0
  158. package/lib/v2/ncu/maintainer.js +3 -0
  159. package/lib/v2/ncu/radar.js +13 -0
  160. package/lib/v2/ncu/router.js +3 -0
  161. package/lib/v2/nmtv/radar.js +1 -1
  162. package/lib/v2/oo-software/radar.js +1 -1
  163. package/lib/v2/patagonia/maintainer.js +1 -1
  164. package/lib/v2/phoronix/index.js +177 -48
  165. package/lib/v2/phoronix/maintainer.js +1 -1
  166. package/lib/v2/phoronix/radar.js +3 -3
  167. package/lib/v2/phoronix/router.js +1 -1
  168. package/lib/v2/picnob/maintainer.js +1 -1
  169. package/lib/v2/picnob/templates/desc.art +3 -3
  170. package/lib/v2/picnob/user.js +74 -37
  171. package/lib/v2/picnob/utils.js +24 -0
  172. package/lib/v2/qbitai/category.js +27 -0
  173. package/lib/v2/qbitai/maintainer.js +4 -0
  174. package/lib/v2/qbitai/radar.js +19 -0
  175. package/lib/v2/qbitai/router.js +4 -0
  176. package/lib/v2/qbitai/tag.js +27 -0
  177. package/lib/v2/questmobile/maintainer.js +3 -0
  178. package/lib/v2/questmobile/radar.js +18 -0
  179. package/lib/v2/questmobile/report.js +127 -0
  180. package/lib/v2/questmobile/router.js +3 -0
  181. package/lib/v2/questmobile/templates/description.art +17 -0
  182. package/lib/v2/readhub/daily.js +43 -0
  183. package/lib/v2/readhub/index.js +19 -72
  184. package/lib/v2/readhub/maintainer.js +1 -0
  185. package/lib/v2/readhub/radar.js +6 -0
  186. package/lib/v2/readhub/router.js +1 -0
  187. package/lib/v2/readhub/util.js +69 -0
  188. package/lib/v2/routledge/book-series.js +78 -0
  189. package/lib/v2/routledge/maintainer.js +3 -0
  190. package/lib/v2/routledge/radar.js +13 -0
  191. package/lib/v2/routledge/router.js +3 -0
  192. package/lib/v2/routledge/templates/description.art +7 -0
  193. package/lib/v2/showstart/artist.js +15 -0
  194. package/lib/v2/showstart/brand.js +15 -0
  195. package/lib/v2/showstart/const.js +4 -0
  196. package/lib/v2/showstart/event.js +18 -0
  197. package/lib/v2/showstart/maintainer.js +6 -0
  198. package/lib/v2/showstart/radar.js +40 -0
  199. package/lib/v2/showstart/router.js +6 -0
  200. package/lib/v2/showstart/search.js +51 -0
  201. package/lib/v2/showstart/service.js +166 -0
  202. package/lib/v2/showstart/utils.js +92 -0
  203. package/lib/v2/snowpeak/maintainer.js +1 -1
  204. package/lib/v2/sony/maintainer.js +1 -1
  205. package/lib/v2/sse/disclosure.js +4 -3
  206. package/lib/v2/sspu/jwc.js +44 -0
  207. package/lib/v2/sspu/maintainer.js +3 -0
  208. package/lib/v2/sspu/radar.js +13 -0
  209. package/lib/v2/sspu/router.js +3 -0
  210. package/lib/v2/techcrunch/maintainer.js +1 -1
  211. package/lib/v2/theatlantic/maintainer.js +1 -1
  212. package/lib/v2/thepaper/radar.js +2 -2
  213. package/lib/v2/threads/index.js +20 -150
  214. package/lib/v2/threads/utils.js +147 -0
  215. package/lib/v2/twitter/keyword.js +1 -3
  216. package/lib/v2/twitter/media.js +1 -5
  217. package/lib/v2/twitter/user.js +1 -3
  218. package/lib/v2/twitter/utils.js +5 -3
  219. package/lib/v2/twitter/web-api/constants.js +80 -68
  220. package/lib/v2/twitter/web-api/twitter-api.js +96 -103
  221. package/lib/v2/uniqlo/maintainer.js +3 -0
  222. package/lib/v2/uniqlo/new.js +62 -0
  223. package/lib/v2/uniqlo/radar.js +12 -0
  224. package/lib/v2/uniqlo/router.js +3 -0
  225. package/lib/v2/wechat/maintainer.js +1 -1
  226. package/lib/v2/weibo/maintainer.js +1 -1
  227. package/lib/v2/weibo/radar.js +1 -1
  228. package/lib/v2/weibo/router.js +1 -1
  229. package/lib/v2/weibo/search/hot.js +118 -7
  230. package/lib/v2/weibo/search/template/digest.art +17 -0
  231. package/lib/v2/xiaohongshu/util.js +17 -7
  232. package/lib/v2/xmnn/docs.js +0 -0
  233. package/lib/v2/xmnn/maintainer.js +1 -0
  234. package/lib/v2/xmnn/news.js +65 -0
  235. package/lib/v2/xmnn/radar.js +67 -1
  236. package/lib/v2/xmnn/router.js +1 -0
  237. package/lib/v2/xsijishe/maintainer.js +1 -0
  238. package/lib/v2/xsijishe/radar.js +12 -0
  239. package/lib/v2/xsijishe/rank.js +60 -0
  240. package/lib/v2/xsijishe/router.js +1 -0
  241. package/lib/v2/yahoo/maintainer.js +2 -0
  242. package/lib/v2/yahoo/news/tw/index.js +24 -0
  243. package/lib/v2/yahoo/news/tw/provider-helper.js +22 -0
  244. package/lib/v2/yahoo/news/tw/provider.js +24 -0
  245. package/lib/v2/yahoo/news/tw/utils.js +129 -0
  246. package/lib/v2/yahoo/radar.js +29 -1
  247. package/lib/v2/yahoo/router.js +4 -1
  248. package/lib/v2/yahoo/templates/youtube.art +1 -0
  249. package/lib/v2/yuque/book.js +6 -1
  250. package/lib/v2/yuque/utils.js +16 -0
  251. package/lib/v2/zagg/maintainer.js +1 -1
  252. package/lib/views/error.art +1 -1
  253. package/lib/views/rss3-ums.js +62 -0
  254. package/lib/views/welcome.art +1 -1
  255. package/package.json +45 -39
  256. package/lib/routes/egsea/flash.js +0 -40
  257. package/lib/routes/gov/moa/sjzxfb.js +0 -20
  258. package/lib/routes/liquipedia/dota2_matches.js +0 -50
  259. package/lib/routes/questmobile/report.js +0 -121
  260. package/lib/routes/uniqlo/stylingbook.js +0 -24
  261. package/lib/routes/universities/buaa/news/index.js +0 -66
  262. package/lib/routes/universities/buaa/utils.js +0 -57
  263. package/lib/v2/gov/zhengce/zuixin.js +0 -39
  264. package/lib/v2/huxiu/article.js +0 -33
  265. package/lib/v2/huxiu/author.js +0 -36
  266. package/lib/v2/huxiu/templates/brief.art +0 -22
  267. package/lib/v2/huxiu/templates/img.art +0 -3
  268. package/lib/v2/huxiu/templates/moment.art +0 -16
  269. package/lib/v2/huxiu/templates/video.art +0 -7
  270. package/lib/v2/huxiu/utils.js +0 -154
  271. package/lib/v2/twitter/web-api/twitter-got.js +0 -113
  272. /package/lib/{routes → v2}/gov/moa/moa.js +0 -0
  273. /package/lib/v2/yahoo/news/{index.js → us/index.js} +0 -0
package/README.md CHANGED
@@ -30,7 +30,7 @@ RSSHub can be used with browser extension [RSSHub Radar](https://github.com/DIYg
30
30
  ### Special Sponsors
31
31
 
32
32
  <p>
33
- <a href="https://xlog.app/" target="_blank"><img height="100px" src="https://i.imgur.com/JuhHTKD.png"></a>
33
+ <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>
34
34
  </p>
35
35
 
36
36
  [![](https://opencollective.com/static/images/become_sponsor.svg)](https://docs.rsshub.app/support/)
@@ -43,7 +43,7 @@ Logo designer [sheldonrrr](https://dribbble.com/sheldonrrr)
43
43
 
44
44
  ### Backers
45
45
 
46
- <a href="https://www.cloudflare.com" target="_blank"><img height="50px" src="https://i.imgur.com/7Ph27Fq.png"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="https://www.netlify.com" target="_blank"><img height="40px" src="https://i.imgur.com/cU01915.png"></a>
46
+ <a href="https://www.cloudflare.com" target="_blank"><img height="50px" src="https://i.imgur.com/7Ph27Fq.png"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="https://www.netlify.com" target="_blank"><img height="40px" src="https://i.imgur.com/cU01915.png"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="https://1password.com" target="_blank"><img height="40px" src="https://i.imgur.com/a2XjflO.png"></a>
47
47
 
48
48
  ## Related Projects
49
49
 
@@ -78,7 +78,7 @@ Recurring donors will be rewarded via express issue response, or even have your
78
78
  - Become a Sponser on [Patreon](https://www.patreon.com/DIYgod)
79
79
  - Become a Sponser on [Open Collective](https://opencollective.com/RSSHub)
80
80
  - Become a Sponser on [爱发电](https://afdian.net/@diygod)
81
- - Contact us directly: i@diygod.me
81
+ - Contact us directly: <i@diygod.me>
82
82
 
83
83
  ### One-time Donation
84
84
 
package/lib/config.js CHANGED
@@ -1,12 +1,12 @@
1
1
  require('dotenv').config();
2
2
  const randUserAgent = require('./utils/rand-user-agent');
3
+ const got = require('got');
3
4
  let envs = process.env;
4
5
  let value;
5
6
  const TRUE_UA = 'RSSHub/1.0 (+http://github.com/DIYgod/RSSHub; like FeedFetcher-Google)';
6
7
 
7
8
  const calculateValue = () => {
8
9
  const bilibili_cookies = {};
9
- const twitter_tokens = {};
10
10
  const email_config = {};
11
11
  const discuz_cookies = {};
12
12
  const medium_cookies = {};
@@ -16,9 +16,6 @@ const calculateValue = () => {
16
16
  if (name.startsWith('BILIBILI_COOKIE_')) {
17
17
  const uid = name.slice(16);
18
18
  bilibili_cookies[uid] = envs[name];
19
- } else if (name.startsWith('TWITTER_TOKEN_')) {
20
- const id = name.slice(14);
21
- twitter_tokens[id] = envs[name];
22
19
  } else if (name.startsWith('EMAIL_CONFIG_')) {
23
20
  const id = name.slice(13);
24
21
  email_config[id] = envs[name];
@@ -222,6 +219,9 @@ const calculateValue = () => {
222
219
  lastfm: {
223
220
  api_key: envs.LASTFM_API_KEY,
224
221
  },
222
+ lightnovel: {
223
+ cookie: envs.SECURITY_KEY,
224
+ },
225
225
  manhuagui: {
226
226
  cookie: envs.MHGUI_COOKIE,
227
227
  },
@@ -295,10 +295,8 @@ const calculateValue = () => {
295
295
  cookie: envs.TOPHUB_COOKIE,
296
296
  },
297
297
  twitter: {
298
- consumer_key: envs.TWITTER_CONSUMER_KEY,
299
- consumer_secret: envs.TWITTER_CONSUMER_SECRET,
300
- tokens: twitter_tokens,
301
- authorization: envs.TWITTER_WEBAPI_AUTHORIZAION && envs.TWITTER_WEBAPI_AUTHORIZAION.split(','),
298
+ oauthTokens: envs.TWITTER_OAUTH_TOKEN?.split(','),
299
+ oauthTokenSecrets: envs.TWITTER_OAUTH_TOKEN_SECRET?.split(','),
302
300
  },
303
301
  weibo: {
304
302
  app_key: envs.WEIBO_APP_KEY,
@@ -335,6 +333,21 @@ const calculateValue = () => {
335
333
  };
336
334
  calculateValue();
337
335
 
336
+ if (envs.REMOTE_CONFIG) {
337
+ got.get(envs.REMOTE_CONFIG)
338
+ .then((response) => {
339
+ const data = JSON.parse(response.body);
340
+ if (data) {
341
+ envs = Object.assign(envs, data);
342
+ calculateValue();
343
+ require('@/utils/logger').info('Remote config loaded.');
344
+ }
345
+ })
346
+ .catch((error) => {
347
+ require('@/utils/logger').error('Remote config load failed.', error);
348
+ });
349
+ }
350
+
338
351
  module.exports = {
339
352
  set: (env) => {
340
353
  envs = Object.assign(process.env, env);
@@ -1,4 +1,4 @@
1
- const md5 = require('@/utils/md5');
1
+ const xxhash = require('xxhash-wasm');
2
2
  const config = require('@/config').value;
3
3
  const logger = require('@/utils/logger');
4
4
  const { RequestInProgressError } = require('@/errors');
@@ -81,8 +81,9 @@ module.exports = function (app) {
81
81
  };
82
82
 
83
83
  return async (ctx, next) => {
84
- const key = 'koa-redis-cache:' + md5(ctx.request.path);
85
- const controlKey = 'path-requested:' + md5(ctx.request.path);
84
+ const { h64ToString } = await xxhash();
85
+ const key = 'rsshub:koa-redis-cache:' + h64ToString(ctx.request.path);
86
+ const controlKey = 'rsshub:path-requested:' + h64ToString(ctx.request.path);
86
87
 
87
88
  if (!status.available) {
88
89
  return next();
@@ -19,10 +19,10 @@ redisClient.on('connect', () => {
19
19
  });
20
20
 
21
21
  const getCacheTtlKey = (key) => {
22
- if (key.startsWith('cacheTtl:')) {
23
- throw Error('"cacheTtl:" prefix is reserved for the internal usage, please change your cache key'); // blocking any attempt to get/set the cacheTtl
22
+ if (key.startsWith('rsshub:cacheTtl:')) {
23
+ throw Error('"rsshub:cacheTtl:" prefix is reserved for the internal usage, please change your cache key'); // blocking any attempt to get/set the cacheTtl
24
24
  }
25
- return `cacheTtl:${key}`;
25
+ return `rsshub:cacheTtl:${key}`;
26
26
  };
27
27
 
28
28
  module.exports = {
@@ -39,6 +39,14 @@ module.exports = async (ctx, next) => {
39
39
  });
40
40
  }
41
41
  } catch (err) {
42
+ if (err instanceof Error && !err.stack.split('\n')[1].includes('lib/middleware/parameter.js')) {
43
+ // Append v2 route path if a route throws an error
44
+ // since koa-mount will remove the mount path from ctx.request.path
45
+ // https://github.com/koajs/mount/issues/62
46
+ ctx.request.path = (ctx.mountPath ?? '') + ctx.request.path;
47
+ ctx._matchedRoute = ctx._matchedRoute ? (ctx.mountPath ?? '') + ctx._matchedRoute : ctx._matchedRoute;
48
+ }
49
+
42
50
  let message = err;
43
51
  if (err.name && (err.name === 'HTTPError' || err.name === 'RequestError')) {
44
52
  message = `${err.message}: target website might be blocking our access, you can <a href="https://docs.rsshub.app/install/">host your own RSSHub instance</a> for a better usability.`;
@@ -1,7 +1,7 @@
1
- const { art, json } = require('@/utils/render');
1
+ const { art, json, rss3Ums } = require('@/utils/render');
2
2
  const path = require('path');
3
3
  const config = require('@/config').value;
4
- const typeRegex = /\.(atom|rss|debug\.json|json|\d+\.debug\.html)$/;
4
+ const typeRegex = /\.(atom|rss|ums|debug\.json|json|\d+\.debug\.html)$/;
5
5
  const { collapseWhitespace, convertDateToISO8601 } = require('@/utils/common-utils');
6
6
 
7
7
  module.exports = async (ctx, next) => {
@@ -16,111 +16,105 @@ module.exports = async (ctx, next) => {
16
16
 
17
17
  const outputType = ctx.state.type[1] || 'rss';
18
18
 
19
- if (outputType === 'debug.json' && config.debugInfo) {
20
- ctx.set({
21
- 'Content-Type': 'application/json; charset=UTF-8',
22
- });
23
- if (ctx.state.json) {
24
- ctx.body = JSON.stringify(ctx.state.json, null, 4);
25
- } else {
26
- ctx.body = JSON.stringify({ message: 'plugin does not set debug json' });
27
- }
28
- }
29
- if (outputType.endsWith('.debug.html') && config.debugInfo) {
30
- ctx.set({
31
- 'Content-Type': 'text/html; charset=UTF-8',
32
- });
33
-
34
- const index = parseInt(outputType.match(/(\d+)\.debug\.html$/)[1]);
35
- if (!(ctx.state.data && ctx.state.data.item && ctx.state.data.item[index])) {
36
- ctx.body = `ctx.state.data.item[${index}] not found`;
37
- } else {
38
- ctx.body = ctx.state.data.item[index].description;
19
+ // only enable when debugInfo=true
20
+ if (config.debugInfo) {
21
+ if (outputType === 'debug.json') {
22
+ ctx.set({
23
+ 'Content-Type': 'application/json; charset=UTF-8',
24
+ });
25
+ if (ctx.state.json) {
26
+ ctx.body = JSON.stringify(ctx.state.json, null, 4);
27
+ } else {
28
+ ctx.body = JSON.stringify({ message: 'plugin does not set debug json' });
29
+ }
39
30
  }
40
- }
41
31
 
42
- if (outputType === 'json') {
43
- ctx.set({ 'Content-Type': 'application/feed+json; charset=UTF-8' });
32
+ if (outputType.endsWith('.debug.html')) {
33
+ ctx.set({
34
+ 'Content-Type': 'text/html; charset=UTF-8',
35
+ });
36
+
37
+ const index = parseInt(outputType.match(/(\d+)\.debug\.html$/)[1]);
38
+ if (!(ctx.state.data && ctx.state.data.item && ctx.state.data.item[index])) {
39
+ ctx.body = `ctx.state.data.item[${index}] not found`;
40
+ } else {
41
+ ctx.body = ctx.state.data.item[index].description;
42
+ }
43
+ }
44
44
  }
45
45
 
46
46
  if (!ctx.body) {
47
- let template;
48
-
49
- switch (outputType) {
50
- case 'atom':
51
- template = path.resolve(__dirname, '../views/atom.art');
52
- break;
53
- case 'rss':
54
- template = path.resolve(__dirname, '../views/rss.art');
55
- break;
56
- default:
57
- template = path.resolve(__dirname, '../views/rss.art');
58
- break;
59
- }
47
+ const templateName = outputType === 'atom' ? 'atom.art' : 'rss.art';
48
+ const template = path.resolve(__dirname, `../views/${templateName}`);
60
49
 
61
50
  if (ctx.state.data) {
62
- ctx.state.data.title = collapseWhitespace(ctx.state.data.title);
63
- ctx.state.data.subtitle = collapseWhitespace(ctx.state.data.subtitle);
64
- ctx.state.data.author = collapseWhitespace(ctx.state.data.author);
65
-
66
- ctx.state.data.item &&
67
- ctx.state.data.item.forEach((item) => {
68
- if (item.title) {
69
- item.title = collapseWhitespace(item.title);
70
- // trim title length
71
- for (let length = 0, i = 0; i < item.title.length; i++) {
72
- length += Buffer.from(item.title[i]).length !== 1 ? 2 : 1;
73
- if (length > config.titleLengthLimit) {
74
- item.title = `${item.title.slice(0, i)}...`;
75
- break;
76
- }
77
- }
51
+ const collapseWhitespaceForProperties = (properties, obj) => {
52
+ properties.forEach((prop) => {
53
+ if (obj[prop]) {
54
+ obj[prop] = collapseWhitespace(obj[prop]);
78
55
  }
79
-
80
- if (typeof item.author === 'string') {
81
- item.author = collapseWhitespace(item.author);
82
- } else if (typeof item.author === 'object' && item.author !== null) {
83
- for (const a of item.author) {
84
- a.name = collapseWhitespace(a.name);
85
- }
86
- if (outputType !== 'json') {
87
- item.author = item.author.map((a) => a.name).join(', ');
56
+ });
57
+ };
58
+
59
+ collapseWhitespaceForProperties(['title', 'subtitle', 'author'], ctx.state.data);
60
+
61
+ ctx.state.data.item?.forEach((item) => {
62
+ if (item.title) {
63
+ item.title = collapseWhitespace(item.title);
64
+ // trim title length
65
+ for (let length = 0, i = 0; i < item.title.length; i++) {
66
+ length += Buffer.from(item.title[i]).length !== 1 ? 2 : 1;
67
+ if (length > config.titleLengthLimit) {
68
+ item.title = `${item.title.slice(0, i)}...`;
69
+ break;
88
70
  }
89
71
  }
90
-
91
- if (item.itunes_duration && ((typeof item.itunes_duration === 'string' && item.itunes_duration.indexOf(':') === -1) || (typeof item.itunes_duration === 'number' && !isNaN(item.itunes_duration)))) {
92
- item.itunes_duration = +item.itunes_duration;
93
- item.itunes_duration =
94
- Math.floor(item.itunes_duration / 3600) + ':' + (Math.floor((item.itunes_duration % 3600) / 60) / 100).toFixed(2).slice(-2) + ':' + (((item.itunes_duration % 3600) % 60) / 100).toFixed(2).slice(-2);
95
- }
96
-
97
- if (outputType !== 'rss') {
98
- item.pubDate = convertDateToISO8601(item.pubDate);
99
- item.updated = convertDateToISO8601(item.updated);
72
+ }
73
+
74
+ if (typeof item.author === 'string') {
75
+ item.author = collapseWhitespace(item.author);
76
+ } else if (typeof item.author === 'object' && item.author !== null) {
77
+ item.author.forEach((a) => (a.name = collapseWhitespace(a.name)));
78
+ if (outputType !== 'json') {
79
+ item.author = item.author.map((a) => a.name).join(', ');
100
80
  }
101
- });
81
+ }
82
+
83
+ if (item.itunes_duration && ((typeof item.itunes_duration === 'string' && item.itunes_duration.indexOf(':') === -1) || (typeof item.itunes_duration === 'number' && !isNaN(item.itunes_duration)))) {
84
+ item.itunes_duration = +item.itunes_duration;
85
+ item.itunes_duration =
86
+ Math.floor(item.itunes_duration / 3600) + ':' + (Math.floor((item.itunes_duration % 3600) / 60) / 100).toFixed(2).slice(-2) + ':' + (((item.itunes_duration % 3600) % 60) / 100).toFixed(2).slice(-2);
87
+ }
88
+
89
+ if (outputType !== 'rss') {
90
+ item.pubDate = convertDateToISO8601(item.pubDate);
91
+ item.updated = convertDateToISO8601(item.updated);
92
+ }
93
+ });
102
94
  }
103
95
 
104
- const routeTtl = (config.cache.routeExpire / 60) | 0;
105
-
96
+ const currentDate = new Date();
106
97
  const data = {
107
- lastBuildDate: new Date().toUTCString(),
108
- updated: new Date().toISOString(),
109
- ttl: routeTtl,
98
+ lastBuildDate: currentDate.toUTCString(),
99
+ updated: currentDate.toISOString(),
100
+ ttl: (config.cache.routeExpire / 60) | 0,
110
101
  atomlink: ctx.request.href,
111
102
  ...ctx.state.data,
112
103
  };
104
+
113
105
  if (config.isPackage) {
114
106
  ctx.body = data;
115
107
  return;
116
108
  }
117
- if (!template) {
118
- return;
119
- }
120
- if (outputType !== 'json') {
109
+
110
+ if (outputType === 'ums') {
111
+ ctx.set({ 'Content-Type': 'application/json; charset=UTF-8' });
112
+ ctx.body = rss3Ums(data);
113
+ } else if (outputType === 'json') {
114
+ ctx.set({ 'Content-Type': 'application/feed+json; charset=UTF-8' });
115
+ ctx.body = json(data);
116
+ } else {
121
117
  ctx.body = art(template, data);
122
- return;
123
118
  }
124
- ctx.body = json(data);
125
119
  }
126
120
  };
package/lib/router.js CHANGED
@@ -171,7 +171,7 @@ router.get('/wikipedia/mainland', lazyloadRouteHandler('./routes/wikipedia/mainl
171
171
  router.get('/un/scveto', lazyloadRouteHandler('./routes/un/scveto'));
172
172
 
173
173
  // e 公司
174
- router.get('/egsea/flash', lazyloadRouteHandler('./routes/egsea/flash'));
174
+ // router.get('/egsea/flash', lazyloadRouteHandler('./routes/egsea/flash'));
175
175
 
176
176
  // 选股宝
177
177
  router.get('/xuangubao/subject/:subject_id', lazyloadRouteHandler('./routes/xuangubao/subject'));
@@ -374,7 +374,7 @@ router.get('/henu/:type?', lazyloadRouteHandler('./routes/universities/henu/news
374
374
  router.get('/nku/jwc/:type?', lazyloadRouteHandler('./routes/universities/nku/jwc/index'));
375
375
 
376
376
  // 北京航空航天大学
377
- router.get('/buaa/news/:type', lazyloadRouteHandler('./routes/universities/buaa/news/index'));
377
+ // router.get('/buaa/news/:type', lazyloadRouteHandler('./routes/universities/buaa/news/index'));
378
378
 
379
379
  // 浙江工业大学
380
380
  router.get('/zjut/:type', lazyloadRouteHandler('./routes/universities/zjut/index'));
@@ -1047,8 +1047,8 @@ router.get('/im2maker/:channel?', lazyloadRouteHandler('./routes/im2maker/index'
1047
1047
  router.get('/cninfo/announcement/:column/:code/:orgId/:category?/:search?', lazyloadRouteHandler('./routes/cninfo/announcement'));
1048
1048
 
1049
1049
  // 中华人民共和国农业农村部
1050
- router.get('/gov/moa/sjzxfb', lazyloadRouteHandler('./routes/gov/moa/sjzxfb'));
1051
- router.get('/gov/moa/:suburl(.*)', lazyloadRouteHandler('./routes/gov/moa/moa'));
1050
+ // router.get('/gov/moa/sjzxfb', lazyloadRouteHandler('./routes/gov/moa/sjzxfb'));
1051
+ // router.get('/gov/moa/:suburl(.*)', lazyloadRouteHandler('./routes/gov/moa/moa'));
1052
1052
 
1053
1053
  // 香水时代
1054
1054
  router.get('/nosetime/:id/:type/:sort?', lazyloadRouteHandler('./routes/nosetime/comment'));
@@ -2116,7 +2116,7 @@ router.get('/sagawa/:id', lazyloadRouteHandler('./routes/sagawa/index'));
2116
2116
  router.get('/qnap/release-notes/:id', lazyloadRouteHandler('./routes/qnap/release-notes'));
2117
2117
 
2118
2118
  // Liquipedia
2119
- router.get('/liquipedia/dota2/matches/:id', lazyloadRouteHandler('./routes/liquipedia/dota2_matches.js'));
2119
+ // router.get('/liquipedia/dota2/matches/:id', lazyloadRouteHandler('./routes/liquipedia/dota2_matches.js'));
2120
2120
 
2121
2121
  // 哈尔滨市科技局
2122
2122
  router.get('/gov/harbin/kjj', lazyloadRouteHandler('./routes/gov/harbin/kjj'));
@@ -2594,7 +2594,7 @@ router.get('/cbndata/information/:category?', lazyloadRouteHandler('./routes/cbn
2594
2594
  router.get('/tanchinese/:category?', lazyloadRouteHandler('./routes/tanchinese'));
2595
2595
 
2596
2596
  // Harvard
2597
- router.get('/harvard/health/blog', lazyloadRouteHandler('./routes/universities/harvard/health/blog'));
2597
+ // router.get('/harvard/health/blog', lazyloadRouteHandler('./routes/universities/harvard/health/blog'));
2598
2598
 
2599
2599
  // yuzu emulator
2600
2600
  router.get('/yuzu-emu/entry', lazyloadRouteHandler('./routes/yuzu-emu/entry'));
@@ -2665,7 +2665,7 @@ router.get('/netflix/newsroom/:category?/:region?', lazyloadRouteHandler('./rout
2665
2665
  router.get('/sbs/chinese/:category?/:id?/:dialect?/:language?', lazyloadRouteHandler('./routes/sbs/chinese'));
2666
2666
 
2667
2667
  // QuestMobile
2668
- router.get('/questmobile/report/:category?/:label?', lazyloadRouteHandler('./routes/questmobile/report'));
2668
+ // router.get('/questmobile/report/:category?/:label?', lazyloadRouteHandler('./routes/questmobile/report'));
2669
2669
 
2670
2670
  // Fashion Network
2671
2671
  router.get('/fashionnetwork/news/:sectors?/:categories?/:language?', lazyloadRouteHandler('./routes/fashionnetwork/news.js'));
@@ -1,7 +1,6 @@
1
1
  const config = require('@/config').value;
2
2
  const art = require('art-template');
3
3
  const path = require('path');
4
- const pidusage = require('pidusage');
5
4
 
6
5
  let gitHash;
7
6
  try {
@@ -10,7 +9,9 @@ try {
10
9
  gitHash = (process.env.HEROKU_SLUG_COMMIT && process.env.HEROKU_SLUG_COMMIT.slice(0, 7)) || (process.env.VERCEL_GIT_COMMIT_SHA && process.env.VERCEL_GIT_COMMIT_SHA.slice(0, 7)) || 'unknown';
11
10
  }
12
11
 
13
- module.exports = async (ctx) => {
12
+ const startTime = Date.now();
13
+
14
+ module.exports = (ctx) => {
14
15
  ctx.set({
15
16
  'Content-Type': 'text/html; charset=UTF-8',
16
17
  'Cache-Control': 'no-cache',
@@ -47,7 +48,7 @@ module.exports = async (ctx) => {
47
48
  }
48
49
  const { disallowRobot } = config;
49
50
 
50
- const stats = await pidusage(process.pid);
51
+ const duration = Date.now() - startTime;
51
52
 
52
53
  ctx.body = art(path.resolve(__dirname, '../views/welcome.art'), {
53
54
  showDebug,
@@ -69,7 +70,7 @@ module.exports = async (ctx) => {
69
70
  },
70
71
  {
71
72
  name: 'Request Frequency',
72
- value: ((ctx.debug.request / (stats.elapsed / 1000)) * 60).toFixed(3) + ' times/minute',
73
+ value: ((ctx.debug.request / (duration / 1000)) * 60).toFixed(3) + ' times/minute',
73
74
  },
74
75
  {
75
76
  name: 'Cache Hit Ratio',
@@ -79,17 +80,9 @@ module.exports = async (ctx) => {
79
80
  name: 'ETag Matched',
80
81
  value: ctx.debug.etag,
81
82
  },
82
- {
83
- name: 'Memory Usage',
84
- value: stats.memory / 1000000 + ' MB',
85
- },
86
- {
87
- name: 'CPU Usage',
88
- value: stats.cpu + '%',
89
- },
90
83
  {
91
84
  name: 'Run Time',
92
- value: (stats.elapsed / 3600000).toFixed(2) + ' hour(s)',
85
+ value: (duration / 3600000).toFixed(2) + ' hour(s)',
93
86
  },
94
87
  {
95
88
  name: 'Hot Routes',
@@ -1,12 +1,8 @@
1
1
  const { parseDate } = require('@/utils/parse-date');
2
+ const title = require('title');
2
3
 
3
4
  // convert a string into title case
4
- const toTitleCase = (str) =>
5
- str
6
- .toLowerCase()
7
- .split(' ')
8
- .map((word) => word.replace(word[0], word[0].toUpperCase()))
9
- .join(' ');
5
+ const toTitleCase = (str) => title(str);
10
6
 
11
7
  const rWhiteSpace = /\s+/;
12
8
  const rAllWhiteSpace = /\s+/g;
@@ -1,9 +1,11 @@
1
1
  const art = require('art-template');
2
2
  const json = require('@/views/json');
3
+ const rss3Ums = require('@/views/rss3-ums');
3
4
 
4
5
  // We may add more control over it later
5
6
 
6
7
  module.exports = {
7
8
  art,
8
9
  json, // This should be used by RSSHub middleware only.
10
+ rss3Ums,
9
11
  };
@@ -1,8 +1,8 @@
1
1
  module.exports = {
2
2
  '/blog/:category?': ['nczitzk'],
3
3
  '/category/:id?/:type?/:order?': ['nczitzk'],
4
- '/offer/:year?/:major?/:school?': ['NavePnow'],
5
- '/post/:type?/:order?': ['NavePnow', 'DIYgod', 'nczitzk'],
4
+ '/offer/:year?/:major?/:school?': ['EthanWng97'],
5
+ '/post/:type?/:order?': ['EthanWng97', 'DIYgod', 'nczitzk'],
6
6
  '/section/:id?/:type?/:order?': ['nczitzk'],
7
7
  '/user/:id/posts': ['Maecenas'],
8
8
  '/user/:id/threads': ['Maecenas'],
@@ -3,7 +3,7 @@ const cheerio = require('cheerio');
3
3
  const { art } = require('@/utils/render');
4
4
  const path = require('path');
5
5
 
6
- const rootUrl = 'https://www.95mm.org';
6
+ const rootUrl = 'https://www.95mm.vip';
7
7
 
8
8
  module.exports = {
9
9
  rootUrl,
@@ -28,6 +28,7 @@ module.exports = {
28
28
  return {
29
29
  title: a.text(),
30
30
  link: a.attr('href'),
31
+ guid: a.attr('href').replace('95mm.vip', '95mm.org'),
31
32
  };
32
33
  });
33
34
 
@@ -42,7 +43,7 @@ module.exports = {
42
43
  const images = detailResponse.data.match(/src": '(.*?)',"width/g);
43
44
 
44
45
  item.description = art(path.join(__dirname, 'templates/description.art'), {
45
- images: images.map((i) => i.split("'")[1]),
46
+ images: images.map((i) => i.split("'")[1].replaceAll('\\/', '/')),
46
47
  });
47
48
 
48
49
  return item;
@@ -20,7 +20,7 @@ module.exports = async (ctx) => {
20
20
  const url = `https://help.aliyun.com/noticelist/${typeMap[type] || typeMap[0]}.html`;
21
21
  const response = await got({ method: 'get', url });
22
22
  const $ = cheerio.load(response.data);
23
- const list = $('ul > li.y-clear')
23
+ const list = $('ul > li.notice-li')
24
24
  .map((i, e) => {
25
25
  const element = $(e);
26
26
  const title = element.find('a').text().trim();
@@ -1,4 +1,4 @@
1
1
  module.exports = {
2
2
  '/awsblogs/:locale?': ['HankChow'],
3
- '/kindle/software-updates': ['NavePnow'],
3
+ '/kindle/software-updates': ['EthanWng97'],
4
4
  };
@@ -10,7 +10,7 @@ module.exports = async (ctx) => {
10
10
  const $ = cheerio.load(response.data);
11
11
 
12
12
  const items = await Promise.all(
13
- $('.PagePromo-content')
13
+ $('.PagePromo-content bsp-custom-headline')
14
14
  .get()
15
15
  .slice(0, ctx.query.limit ? parseInt(ctx.query.limit) : Infinity)
16
16
  .map((e) => ({
@@ -1,5 +1,5 @@
1
1
  module.exports = {
2
- '/new-arrivals/:country/:gender': ['NavePnow'],
3
- '/outlet/:country/:gender': ['NavePnow'],
4
- '/regear/new-arrivals': ['NavePnow'],
2
+ '/new-arrivals/:country/:gender': ['EthanWng97'],
3
+ '/outlet/:country/:gender': ['EthanWng97'],
4
+ '/regear/new-arrivals': ['EthanWng97'],
5
5
  };
@@ -16,4 +16,5 @@ module.exports = {
16
16
  '/tv/subject/:id/:type?/:showOriginalName?': ['JimenezLi'],
17
17
  '/tv/topic/:id': ['ylc395'],
18
18
  '/tv/user/blog/:id': ['nczitzk'],
19
+ '/tv/user/wish/:id': ['honue'],
19
20
  };
@@ -61,6 +61,12 @@ const bangumiTV = {
61
61
  source: '/anime',
62
62
  target: '/bangumi/tv/followrank',
63
63
  },
64
+ {
65
+ title: '用户想看',
66
+ docs: 'https://docs.rsshub.app/routes/anime#bangumi-fan-zu-ji-hua',
67
+ source: '/anime/list/:id/wish',
68
+ target: '/bangumi/tv/user/wish/:id',
69
+ },
64
70
  ],
65
71
  };
66
72
 
@@ -11,4 +11,5 @@ module.exports = function (router) {
11
11
  router.get('/tv/subject/:id/:type?/:showOriginalName?', require('./tv/subject'));
12
12
  router.get('/tv/topic/:id', require('./tv/group/reply'));
13
13
  router.get('/tv/user/blog/:id', require('./tv/user/blog'));
14
+ router.get('/tv/user/wish/:id', require('./tv/user/wish'));
14
15
  };
@@ -0,0 +1,38 @@
1
+ const got = require('@/utils/got');
2
+ const cheerio = require('cheerio');
3
+ const timezone = require('@/utils/timezone');
4
+ const { parseDate } = require('@/utils/parse-date');
5
+ const config = require('@/config').value;
6
+ module.exports = async (ctx) => {
7
+ const userid = ctx.params.id;
8
+ const url = `https://bgm.tv/anime/list/${userid}/wish`;
9
+ const response = await got({
10
+ url,
11
+ method: 'get',
12
+ headers: {
13
+ 'User-Agent': config.trueUA,
14
+ },
15
+ });
16
+ const $ = cheerio.load(response.body);
17
+
18
+ const username = $('.name').find('a').html();
19
+ const items = $('#browserItemList')
20
+ .find('li')
21
+ .toArray()
22
+ .map((item) => {
23
+ const aTag = $(item).find('h3').children('a');
24
+ const jdate = $(item).find('.collectInfo').find('span').html();
25
+ return {
26
+ title: aTag.html(),
27
+ link: 'https://bgm.tv' + aTag.attr('href'),
28
+ pubDate: timezone(parseDate(jdate), 0),
29
+ };
30
+ });
31
+
32
+ ctx.state.data = {
33
+ title: `${username}想看的动画`,
34
+ link: url,
35
+ item: items,
36
+ description: `${username}想看的动画列表`,
37
+ };
38
+ };
@@ -1,3 +1,3 @@
1
1
  module.exports = {
2
- '/new-releases': ['NavePnow'],
2
+ '/new-releases': ['EthanWng97'],
3
3
  };