rsshub 1.0.0-master.fe69819 → 1.0.0-master.fee75c6

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 (276) hide show
  1. package/lib/config.js +4 -0
  2. package/lib/radar-rules.js +0 -162
  3. package/lib/router.js +82 -83
  4. package/lib/routes/dsndsht23/index.js +2 -1
  5. package/lib/routes/ehentai/ehapi.js +16 -6
  6. package/lib/routes/ehentai/favorites.js +14 -7
  7. package/lib/routes/ehentai/search.js +14 -5
  8. package/lib/routes/ehentai/tag.js +14 -5
  9. package/lib/routes/mofish/index.js +21 -9
  10. package/lib/routes/mofish/templates/description.art +4 -0
  11. package/lib/routes/or/index.js +1 -1
  12. package/lib/routes/prestige-av/series.js +3 -6
  13. package/lib/routes/tencent/wechat/tgchannel.js +84 -29
  14. package/lib/routes/weibo/timeline.js +18 -1
  15. package/lib/routes/weibo/user.js +19 -3
  16. package/lib/routes/weibo/utils.js +113 -5
  17. package/lib/routes/zhihu/hot.js +3 -2
  18. package/lib/v2/36kr/maintainer.js +7 -0
  19. package/lib/{routes → v2}/36kr/motif.js +2 -1
  20. package/lib/v2/36kr/news.js +56 -0
  21. package/lib/{routes → v2}/36kr/newsflashes.js +2 -1
  22. package/lib/v2/36kr/radar.js +37 -0
  23. package/lib/v2/36kr/router.js +7 -0
  24. package/lib/{routes → v2}/36kr/search/article.js +3 -2
  25. package/lib/{routes → v2}/36kr/user.js +2 -1
  26. package/lib/v2/52hrtt/index.js +57 -0
  27. package/lib/v2/52hrtt/maintainer.js +4 -0
  28. package/lib/v2/52hrtt/radar.js +19 -0
  29. package/lib/v2/52hrtt/router.js +4 -0
  30. package/lib/v2/52hrtt/symposium.js +57 -0
  31. package/lib/v2/8kcos/article.js +24 -0
  32. package/lib/v2/8kcos/cat.js +22 -0
  33. package/lib/{routes → v2}/8kcos/const.js +0 -0
  34. package/lib/v2/8kcos/latest.js +23 -0
  35. package/lib/v2/8kcos/maintainer.js +5 -0
  36. package/lib/v2/8kcos/radar.js +25 -0
  37. package/lib/v2/8kcos/router.js +5 -0
  38. package/lib/v2/8kcos/tag.js +23 -0
  39. package/lib/{routes → v2}/95mm/category.js +5 -3
  40. package/lib/v2/95mm/maintainer.js +5 -0
  41. package/lib/v2/95mm/radar.js +25 -0
  42. package/lib/v2/95mm/router.js +5 -0
  43. package/lib/v2/95mm/tab.js +9 -0
  44. package/lib/v2/95mm/tag.js +9 -0
  45. package/lib/v2/95mm/templates/description.art +3 -0
  46. package/lib/v2/95mm/utils.js +59 -0
  47. package/lib/v2/abskoop/index.js +52 -0
  48. package/lib/v2/abskoop/maintainer.js +3 -0
  49. package/lib/v2/abskoop/radar.js +13 -0
  50. package/lib/v2/abskoop/router.js +3 -0
  51. package/lib/v2/abskoop/templates/description.art +3 -0
  52. package/lib/v2/apple/exchange_repair.js +40 -0
  53. package/lib/v2/apple/maintainer.js +3 -0
  54. package/lib/v2/apple/radar.js +13 -0
  55. package/lib/v2/apple/router.js +3 -0
  56. package/lib/{routes/apple → v2}/appstore/gofans.js +3 -3
  57. package/lib/{routes/apple → v2}/appstore/in-app-purchase.js +0 -0
  58. package/lib/v2/appstore/maintainer.js +7 -0
  59. package/lib/{routes/apple → v2}/appstore/price.js +0 -0
  60. package/lib/v2/appstore/radar.js +41 -0
  61. package/lib/v2/appstore/router.js +7 -0
  62. package/lib/{routes/apple → v2}/appstore/update.js +0 -0
  63. package/lib/{routes/apple → v2}/appstore/xianmian.js +3 -2
  64. package/lib/{routes/universities → v2}/bjfu/grs.js +0 -0
  65. package/lib/v2/bjfu/it/index.js +49 -0
  66. package/lib/v2/bjfu/it/utils.js +64 -0
  67. package/lib/{routes/universities → v2}/bjfu/jwc/index.js +0 -0
  68. package/lib/{routes/universities → v2}/bjfu/jwc/utils.js +10 -9
  69. package/lib/{routes/universities → v2}/bjfu/kjc.js +0 -0
  70. package/lib/v2/bjfu/maintainer.js +7 -0
  71. package/lib/{routes/universities → v2}/bjfu/news/index.js +0 -0
  72. package/lib/{routes/universities → v2}/bjfu/news/utils.js +10 -9
  73. package/lib/v2/bjfu/radar.js +45 -0
  74. package/lib/v2/bjfu/router.js +7 -0
  75. package/lib/v2/dahecube/index.js +66 -0
  76. package/lib/v2/dahecube/maintainer.js +3 -0
  77. package/lib/v2/dahecube/radar.js +23 -0
  78. package/lib/v2/dahecube/router.js +3 -0
  79. package/lib/v2/dahecube/utils.js +47 -0
  80. package/lib/v2/dhu/jiaowu/news.js +37 -0
  81. package/lib/v2/dhu/maintainer.js +4 -0
  82. package/lib/v2/dhu/radar.js +17 -0
  83. package/lib/v2/dhu/router.js +4 -0
  84. package/lib/v2/dhu/xxgk/news.js +32 -0
  85. package/lib/v2/douban/people/wish.js +2 -1
  86. package/lib/{routes → v2}/dtcj/datahero.js +3 -2
  87. package/lib/v2/dtcj/datainsight.js +53 -0
  88. package/lib/v2/dtcj/maintainer.js +4 -0
  89. package/lib/v2/dtcj/radar.js +25 -0
  90. package/lib/v2/dtcj/router.js +4 -0
  91. package/lib/v2/eastday/24.js +90 -0
  92. package/lib/v2/eastday/maintainer.js +2 -0
  93. package/lib/v2/eastday/radar.js +16 -0
  94. package/lib/v2/eastday/router.js +2 -0
  95. package/lib/{routes → v2}/eastday/sh.js +6 -11
  96. package/lib/v2/eastmoney/radar.js +13 -0
  97. package/lib/v2/eastmoney/router.js +3 -0
  98. package/lib/v2/eastmoney/ttjj/user.js +65 -0
  99. package/lib/v2/ems/apple.js +42 -0
  100. package/lib/v2/ems/maintainer.js +4 -0
  101. package/lib/{routes → v2}/ems/news.js +0 -0
  102. package/lib/v2/ems/radar.js +19 -0
  103. package/lib/v2/ems/router.js +4 -0
  104. package/lib/v2/ems/templates/apple.art +6 -0
  105. package/lib/{routes → v2}/flyert/creditcard.js +0 -0
  106. package/lib/v2/flyert/maintainer.js +4 -0
  107. package/lib/{routes → v2}/flyert/preferential.js +0 -0
  108. package/lib/v2/flyert/radar.js +19 -0
  109. package/lib/v2/flyert/router.js +4 -0
  110. package/lib/{routes → v2}/flyert/utils.js +2 -1
  111. package/lib/v2/hdu/cs/index.js +57 -0
  112. package/lib/v2/hdu/maintainer.js +3 -0
  113. package/lib/v2/hdu/radar.js +13 -0
  114. package/lib/v2/hdu/router.js +4 -0
  115. package/lib/v2/hellobtc/information.js +51 -0
  116. package/lib/v2/hellobtc/kepu.js +64 -0
  117. package/lib/v2/hellobtc/maintainer.js +6 -0
  118. package/lib/v2/hellobtc/news.js +29 -0
  119. package/lib/v2/hellobtc/radar.js +85 -0
  120. package/lib/v2/hellobtc/router.js +6 -0
  121. package/lib/v2/hellobtc/topic.js +43 -0
  122. package/lib/v2/ielts/index.js +58 -0
  123. package/lib/v2/ielts/maintainer.js +3 -0
  124. package/lib/v2/ielts/radar.js +13 -0
  125. package/lib/v2/ielts/router.js +3 -0
  126. package/lib/{routes → v2}/javbus/genre.js +0 -0
  127. package/lib/{routes → v2}/javbus/home.js +0 -0
  128. package/lib/v2/javbus/label.js +7 -0
  129. package/lib/v2/javbus/maintainer.js +16 -0
  130. package/lib/v2/javbus/radar.js +99 -0
  131. package/lib/v2/javbus/router.js +16 -0
  132. package/lib/{routes → v2}/javbus/series.js +0 -0
  133. package/lib/{routes → v2}/javbus/star.js +0 -0
  134. package/lib/v2/javbus/studio.js +7 -0
  135. package/lib/{routes → v2}/javbus/uncensored/genre.js +0 -0
  136. package/lib/{routes → v2}/javbus/uncensored/home.js +0 -0
  137. package/lib/{routes → v2}/javbus/uncensored/series.js +0 -0
  138. package/lib/{routes → v2}/javbus/uncensored/star.js +0 -0
  139. package/lib/{routes → v2}/javbus/util.js +5 -9
  140. package/lib/{routes → v2}/javbus/western/genre.js +0 -0
  141. package/lib/{routes → v2}/javbus/western/home.js +0 -0
  142. package/lib/{routes → v2}/javbus/western/series.js +0 -0
  143. package/lib/{routes → v2}/javbus/western/star.js +0 -0
  144. package/lib/v2/javlibrary/utils.js +1 -1
  145. package/lib/v2/kbs/maintainer.js +4 -0
  146. package/lib/v2/kbs/news.js +67 -0
  147. package/lib/v2/kbs/radar.js +19 -0
  148. package/lib/v2/kbs/router.js +4 -0
  149. package/lib/{routes → v2}/kbs/today.js +1 -1
  150. package/lib/v2/lofter/maintainer.js +4 -0
  151. package/lib/v2/lofter/radar.js +17 -0
  152. package/lib/v2/lofter/router.js +4 -0
  153. package/lib/{routes → v2}/lofter/tag.js +4 -4
  154. package/lib/v2/lofter/user.js +52 -0
  155. package/lib/v2/lvv2/maintainer.js +4 -0
  156. package/lib/v2/lvv2/news.js +75 -0
  157. package/lib/v2/lvv2/radar.js +79 -0
  158. package/lib/v2/lvv2/router.js +4 -0
  159. package/lib/v2/lvv2/templates/outlink.art +1 -0
  160. package/lib/v2/lvv2/top.js +77 -0
  161. package/lib/v2/nbd/article.js +50 -0
  162. package/lib/{routes → v2}/nbd/index.js +8 -5
  163. package/lib/v2/nbd/maintainer.js +4 -0
  164. package/lib/v2/nbd/radar.js +19 -0
  165. package/lib/v2/nbd/router.js +4 -0
  166. package/lib/v2/njnu/ceai/ceai.js +44 -0
  167. package/lib/v2/njnu/ceai/utils.js +55 -0
  168. package/lib/v2/njnu/jwc/jwc.js +43 -0
  169. package/lib/v2/njnu/jwc/utils.js +59 -0
  170. package/lib/v2/njnu/maintainer.js +4 -0
  171. package/lib/v2/njnu/radar.js +21 -0
  172. package/lib/v2/njnu/router.js +4 -0
  173. package/lib/v2/nltimes/maintainer.js +3 -0
  174. package/lib/v2/nltimes/news.js +89 -0
  175. package/lib/v2/nltimes/radar.js +19 -0
  176. package/lib/v2/nltimes/router.js +3 -0
  177. package/lib/{routes → v2}/nowcoder/discuss.js +17 -22
  178. package/lib/v2/nowcoder/experience.js +48 -0
  179. package/lib/{routes → v2}/nowcoder/jobcenter.js +0 -0
  180. package/lib/v2/nowcoder/maintainer.js +7 -0
  181. package/lib/v2/nowcoder/radar.js +40 -0
  182. package/lib/{routes → v2}/nowcoder/recommend.js +1 -1
  183. package/lib/v2/nowcoder/router.js +7 -0
  184. package/lib/{routes → v2}/nowcoder/schedule.js +4 -3
  185. package/lib/v2/odaily/post.js +10 -8
  186. package/lib/v2/oilchem/index.js +67 -0
  187. package/lib/v2/oilchem/maintainer.js +3 -0
  188. package/lib/v2/oilchem/radar.js +11 -0
  189. package/lib/v2/oilchem/router.js +3 -0
  190. package/lib/v2/oilchem/routes.js +671 -0
  191. package/lib/v2/picuki/maintainer.js +3 -0
  192. package/lib/v2/picuki/profile.js +167 -0
  193. package/lib/v2/picuki/radar.js +13 -0
  194. package/lib/v2/picuki/router.js +3 -0
  195. package/lib/v2/picuki/templates/post.art +7 -0
  196. package/lib/v2/qq88/index.js +60 -0
  197. package/lib/v2/qq88/maintainer.js +3 -0
  198. package/lib/v2/qq88/radar.js +13 -0
  199. package/lib/v2/qq88/router.js +3 -0
  200. package/lib/v2/readhub/index.js +106 -0
  201. package/lib/v2/readhub/maintainer.js +3 -0
  202. package/lib/v2/readhub/radar.js +13 -0
  203. package/lib/v2/readhub/router.js +6 -0
  204. package/lib/v2/shmeea/maintainer.js +1 -0
  205. package/lib/v2/shmeea/radar.js +6 -0
  206. package/lib/v2/shmeea/router.js +2 -1
  207. package/lib/v2/shmeea/self-study.js +61 -0
  208. package/lib/{routes/universities/sysu/sdcs.js → v2/sysu/cse.js} +3 -3
  209. package/lib/v2/sysu/maintainer.js +3 -0
  210. package/lib/v2/sysu/radar.js +13 -0
  211. package/lib/v2/sysu/router.js +3 -0
  212. package/lib/v2/telegram/channel.js +446 -112
  213. package/lib/v2/telegram/maintainer.js +1 -1
  214. package/lib/v2/telegram/router.js +1 -1
  215. package/lib/v2/telegram/templates/video.art +3 -1
  216. package/lib/v2/tencent/maintainer.js +3 -0
  217. package/lib/v2/tencent/qq/sdk/changelog.js +56 -0
  218. package/lib/v2/tencent/radar.js +56 -0
  219. package/lib/v2/tencent/router.js +3 -0
  220. package/lib/v2/tokeninsight/blog.js +52 -0
  221. package/lib/v2/tokeninsight/bulletin.js +44 -0
  222. package/lib/v2/tokeninsight/maintainer.js +5 -0
  223. package/lib/v2/tokeninsight/radar.js +25 -0
  224. package/lib/v2/tokeninsight/report.js +52 -0
  225. package/lib/v2/tokeninsight/router.js +5 -0
  226. package/lib/v2/txrjy/fornumtopic.js +72 -0
  227. package/lib/v2/txrjy/maintainer.js +3 -0
  228. package/lib/v2/txrjy/radar.js +17 -0
  229. package/lib/v2/txrjy/router.js +3 -0
  230. package/lib/v2/txrjy/templates/fornumtopic.art +6 -0
  231. package/lib/v2/wfu/jwc.js +54 -0
  232. package/lib/v2/wfu/maintainer.js +4 -0
  233. package/lib/v2/wfu/news.js +96 -0
  234. package/lib/v2/wfu/radar.js +21 -0
  235. package/lib/v2/wfu/router.js +4 -0
  236. package/lib/v2/who/maintainer.js +5 -0
  237. package/lib/v2/who/news-room.js +76 -0
  238. package/lib/{routes → v2}/who/news.js +1 -1
  239. package/lib/v2/who/radar.js +25 -0
  240. package/lib/v2/who/router.js +5 -0
  241. package/lib/{routes → v2}/who/speeches.js +0 -0
  242. package/lib/v2/wikinews/index.js +43 -0
  243. package/lib/v2/wikinews/maintainer.js +3 -0
  244. package/lib/v2/wikinews/radar.js +13 -0
  245. package/lib/v2/wikinews/router.js +4 -0
  246. package/lib/{routes → v2}/wsj/index.js +6 -4
  247. package/lib/v2/wsj/maintainer.js +3 -0
  248. package/lib/v2/wsj/radar.js +21 -0
  249. package/lib/v2/wsj/router.js +3 -0
  250. package/lib/v2/xiaoyuzhou/maintainer.js +1 -1
  251. package/lib/v2/xiaoyuzhou/podcast.js +1 -1
  252. package/lib/v2/xmanhua/index.js +74 -0
  253. package/lib/v2/xmanhua/radar.js +13 -0
  254. package/lib/v2/xmanhua/router.js +3 -0
  255. package/lib/{routes → v2}/zhibo8/forum.js +8 -16
  256. package/lib/v2/zhibo8/maintainer.js +5 -0
  257. package/lib/v2/zhibo8/more.js +82 -0
  258. package/lib/{routes → v2}/zhibo8/post.js +1 -1
  259. package/lib/v2/zhibo8/radar.js +27 -0
  260. package/lib/v2/zhibo8/router.js +5 -0
  261. package/package.json +10 -9
  262. package/lib/routes/36kr/news.js +0 -94
  263. package/lib/routes/8kcos/article.js +0 -17
  264. package/lib/routes/8kcos/cat.js +0 -28
  265. package/lib/routes/8kcos/latest.js +0 -27
  266. package/lib/routes/95mm/tab.js +0 -9
  267. package/lib/routes/95mm/tag.js +0 -7
  268. package/lib/routes/95mm/utils.js +0 -51
  269. package/lib/routes/apple/exchange_repair.js +0 -47
  270. package/lib/routes/eastmoney/user.js +0 -30
  271. package/lib/routes/lofter/posts.js +0 -54
  272. package/lib/routes/nbd/article.js +0 -60
  273. package/lib/routes/picuki/profile.js +0 -90
  274. package/lib/routes/readhub/category.js +0 -102
  275. package/lib/routes/who/news-room.js +0 -56
  276. package/lib/routes/zhibo8/more.js +0 -45
@@ -17,9 +17,18 @@ module.exports = async (ctx) => {
17
17
  if (match !== null) {
18
18
  title = match[1];
19
19
  }
20
- ctx.state.data = {
21
- title: title + ' - E-Hentai Search ',
22
- link: `https://e-hentai.org/?${params}`,
23
- item: items,
24
- };
20
+
21
+ if (EhAPI.from_ex) {
22
+ ctx.state.data = {
23
+ title: title + ' - ExHentai Search ',
24
+ link: `https://exhentai.org/?${params}`,
25
+ item: items,
26
+ };
27
+ } else {
28
+ ctx.state.data = {
29
+ title: title + ' - E-Hentai Search ',
30
+ link: `https://e-hentai.org/?${params}`,
31
+ item: items,
32
+ };
33
+ }
25
34
  };
@@ -5,9 +5,18 @@ module.exports = async (ctx) => {
5
5
  const tag = ctx.params.tag;
6
6
  const bittorrent = ctx.params.bittorrent || false;
7
7
  const items = await EhAPI.getTagItems(ctx.cache, tag, page, bittorrent);
8
- ctx.state.data = {
9
- title: tag + ' - E-Hentai Tag',
10
- link: `https://e-hentai.org/tag/${tag}`,
11
- item: items,
12
- };
8
+
9
+ if (EhAPI.from_ex) {
10
+ ctx.state.data = {
11
+ title: tag + ' - ExHentai Tag',
12
+ link: `https://exhentai.org/tag/${tag}`,
13
+ item: items,
14
+ };
15
+ } else {
16
+ ctx.state.data = {
17
+ title: tag + ' - E-Hentai Tag',
18
+ link: `https://e-hentai.org/tag/${tag}`,
19
+ item: items,
20
+ };
21
+ }
13
22
  };
@@ -1,4 +1,7 @@
1
1
  const got = require('@/utils/got');
2
+ const { parseDate } = require('@/utils/parse-date');
3
+ const { art } = require('@/utils/render');
4
+ const path = require('path');
2
5
 
3
6
  module.exports = async (ctx) => {
4
7
  const id = ctx.params.id;
@@ -13,17 +16,26 @@ module.exports = async (ctx) => {
13
16
 
14
17
  const data = response.data.Data.data;
15
18
 
16
- const title = `鱼塘热榜`;
19
+ const title = '鱼塘热榜';
17
20
 
18
21
  ctx.state.data = {
19
22
  title,
20
- link: `https://mo.fish/`,
21
- description: title,
22
- item: data.map((item) => ({
23
- title: item.Title,
24
- pubDate: new Date(item.releaseTime).toUTCString(),
25
- link: item.Url,
26
- guid: item.id,
27
- })),
23
+ link: 'https://mo.fish/',
24
+ item: data.map((item) => {
25
+ const isImage = Number(id) === 136 && item.Url.endsWith('.gif');
26
+ const description = isImage
27
+ ? art(path.join(__dirname, 'templates/description.art'), {
28
+ imageUrl: item.Url,
29
+ })
30
+ : title;
31
+
32
+ return {
33
+ title: item.Title,
34
+ description,
35
+ pubDate: parseDate(item.CreateTime * 1000),
36
+ link: item.Url,
37
+ guid: item.id,
38
+ };
39
+ }),
28
40
  };
29
41
  };
@@ -0,0 +1,4 @@
1
+ <p>
2
+ <img src="{{ imageUrl }}" referrerpolicy="no-referrer">
3
+ <br>
4
+ </p>
@@ -1,7 +1,7 @@
1
1
  const got = require('@/utils/got');
2
2
  const cheerio = require('cheerio');
3
3
  const timezone = require('@/utils/timezone');
4
- const parseDate = require('@/utils/parse-date');
4
+ const { parseDate } = require('@/utils/parse-date');
5
5
 
6
6
  module.exports = async (ctx) => {
7
7
  const id = ctx.params.id || '';
@@ -1,18 +1,15 @@
1
1
  const cheerio = require('cheerio');
2
- const puppeteer = require('puppeteer');
3
2
 
4
3
  module.exports = async (ctx) => {
5
- const browser = await puppeteer.launch({
6
- args: ['--disable-dev-shm-usage'],
7
- });
4
+ const browser = await require('@/utils/puppeteer')();
8
5
 
9
6
  const id = ctx.params.mid;
10
- const sort = ctx.params.sort || 'near';
7
+ const sort = ctx.params.sort ?? 'near';
11
8
 
12
9
  const page = await browser.newPage();
13
10
  const link = `https://www.prestige-av.com/goods/goods_list.php?mode=series&mid=${id}&sort=${sort}`;
14
11
  await page.goto(link);
15
- await page.waitForSelector('.button_r18_prestige');
12
+ await page.waitForSelector('.buttons');
16
13
  await page.click('#AC');
17
14
  await page.waitForSelector('#body_goods');
18
15
  const bodyHandle = await page.$('body');
@@ -4,8 +4,15 @@ const cheerio = require('cheerio');
4
4
  module.exports = async (ctx) => {
5
5
  const id = ctx.params.id;
6
6
  const mpName = ctx.params.mpName ?? '';
7
+ let searchQueryType = ctx.params.searchQueryType ?? '0';
8
+ if (searchQueryType !== '0' && searchQueryType !== '1' && searchQueryType !== '2') {
9
+ searchQueryType = '0';
10
+ }
11
+ searchQueryType = +searchQueryType; // 将字符串转换为数字
7
12
 
8
- const { data } = await got.get(`https://t.me/s/${id}`);
13
+ const channelUrl = `https://t.me/s/${id}`;
14
+ const searchQuery = mpName && searchQueryType ? (searchQueryType === 2 ? `?q=%23${mpName}` : `?q=${mpName}`) : '';
15
+ const { data } = await got.get(`${channelUrl}${searchQuery}`);
9
16
  const $ = cheerio.load(data);
10
17
  const list = $('.tgme_widget_message_wrap').slice(-20);
11
18
 
@@ -14,49 +21,97 @@ module.exports = async (ctx) => {
14
21
  .map(async (index, item) => {
15
22
  item = $(item);
16
23
 
24
+ if (searchQuery) {
25
+ // 删除关键字高亮 <mark class="highlight">
26
+ const highlightMarks = item.find('mark.highlight').get();
27
+ highlightMarks.forEach((mark) => {
28
+ mark = $(mark);
29
+ const markInnerHtml = mark.html();
30
+ mark.replaceWith(markInnerHtml);
31
+ });
32
+ if (highlightMarks) {
33
+ item = $(item.html()); // 删除关键字高亮后,相邻的裸文本节点不会被自动合并,重新生成 cheerio 对象以确保后续流程正常运行
34
+ }
35
+ }
36
+
17
37
  // [ div.tgme_widget_message_text 格式简略说明 ]
18
38
  // 若频道只订阅一个公众号:
19
- // 第 1 个元素: <a href="${用于 link priview 的预览图 url}"><i><b>${emoji(链接)}</b></i></a>
39
+ // 第 1 个元素: <a href="${用于 link priview 的预览图 url}"><i><b>🔗</b></i></a>
20
40
  // 第 2 个元素: <a href="${文章 url}">${文章标题}</a>
21
41
  // (余下是文章简介,一般是裸文本,这里用不到)
22
42
  //
23
43
  // 若频道订阅多于一个公众号:
24
- // 第 1 个元素: <i><b>${emoji(标注消息来源于什么 slave,这里是表示微信的对话气泡)}</b></i>
25
- // 第 2 个元素: <i><b>${emoji(标注对话类型,这里是表示私聊的半身人像)</b></i>
44
+ // 第 1 个元素: <i><b>${emoji(标注消息来源于什么 slave,这里是表示微信的💬)}</b></i>
45
+ // 第 2 个元素: <i><b>${emoji(标注对话类型,这里是表示私聊的👤)</b></i>
26
46
  // 裸文本: (半角空格)${公众号名}(半角冒号)
27
47
  // 第 3 个元素: <br />
28
- // 第 4 个元素: <a href="${用于 link priview 的预览图 url}"><i><b>${emoji(链接)}</b></i></a>
48
+ // 第 4 个元素: <a href="${用于 link priview 的预览图 url}"><i><b>🔗</b></i></a>
29
49
  // 第 5 个元素: <a href="${文章 url}">${文章标题}</a>
30
50
  // (余下是文章简介,一般是裸文本,这里用不到)
51
+ //
52
+ // 若启用 efb-patch-middleware 且频道订阅多于一个公众号:
53
+ // 第 1 个元素: <i><b>${emoji(标注消息来源于什么 slave,这里是表示微信的💬)}</b></i>
54
+ // 第 2 个元素: <i><b>${emoji(标注对话类型,这里是表示私聊的👤)</b></i>
55
+ // 第 3 个元素: <a href="${?q=%23url-encoded公众号名}">#${公众号名}</a>
56
+ // 裸文本: ${公众号名余下部分 (若 hashtag 不合法 (遇到空格、标点) 导致被截断才会有)}(半角冒号)
57
+ // 第 4 个元素: <br />
58
+ // 第 5 个元素: <a href="${用于 link priview 的预览图 url}"><i><b>🔗</b></i></a>
59
+ // 第 6 个元素: <a href="${文章 url}">${文章标题}</a>
60
+ // (余下是文章简介,一般是裸文本,这里用不到)
61
+
62
+ let author = '';
63
+ let titleElemIs3thA = false;
64
+
65
+ const brNode = item.find('.tgme_widget_message_text > br:nth-of-type(1)').get(0); // 获取第一个换行
66
+ const authorNode = brNode && brNode.prev; // brNode 不为 undefined 时获取它的前一个节点
67
+ const authorNodePrev = authorNode && authorNode.prev; // authorNode 不为 undefined 时获取它的前一个节点
68
+ if (authorNode && authorNode.type === 'text') {
69
+ // 只有这个节点是一个裸文本时它才可能是公众号名,开始找寻公众号名
70
+ if (authorNodePrev && authorNodePrev.type === 'tag' && authorNodePrev.name === 'a' && authorNodePrev.attribs.href && authorNodePrev.attribs.href.startsWith('?q=%23')) {
71
+ // authorNode 前一个节点是链接, 且是个 hashtag,表示启用了 efb-patch-middleware,这个节点是公众号名
72
+ // 有两种可能:
73
+ // 带 # 的完整公众号名 (efb-patch-middleware 启用,且 hashtag 完全合法)
74
+ // 被截断的公众号名前半部分 (efb-patch-middleware 启用,但 hashtag 被空格或标点截断)
75
+ // (若 efb-patch-middleware 未启用,或 hashtag 完全不合法,不会进入此流程)
76
+ titleElemIs3thA = true;
77
+ author += $(authorNodePrev).text();
78
+ }
31
79
 
32
- const title_elem = item.find('.tgme_widget_message_text > a:nth-of-type(2)'); // 第二个 a 元素会是文章链接
80
+ const spaceIndex = authorNode.data.indexOf(' ');
81
+ const colonIndex = authorNode.data.indexOf(':');
82
+ if (authorNode.data.length > 1 && colonIndex !== -1 && (spaceIndex !== -1 || titleElemIs3thA)) {
83
+ // 有三种可能:
84
+ // 不带 # 的完整公众号名 (efb-patch-middleware 未启用)
85
+ // 带 # 的完整公众号名 (efb-patch-middleware 启用,但 hashtag 完全不合法)
86
+ // 被截断的公众号名后半部分 (efb-patch-middleware 启用,但 hashtag 被空格或标点截断,此时空格有意义)
87
+ // (若 efb-patch-middleware 启用,且 hashtag 完全合法,不会进入此流程)
88
+ const sliceStart = titleElemIs3thA ? 0 : spaceIndex + 1;
89
+ author += authorNode.data.slice(sliceStart, colonIndex); // 提取作者
90
+ }
91
+
92
+ if (author.startsWith('#')) {
93
+ author = author.slice(1); // 去掉开头的 #
94
+ }
95
+ }
33
96
 
34
- if (title_elem.length === 0) {
35
- // 获取不到第二个 a 元素,这可能是公众号发的服务消息,丢弃它
97
+ // 如果启用了 efb-patch-middleware 且 hashtag (部分)合法,第三个 a 元素会是文章链接,否则是第二个
98
+ const titleElemNth = titleElemIs3thA ? 3 : 2;
99
+ const titleElem = item.find(`.tgme_widget_message_text > a:nth-of-type(${titleElemNth})`);
100
+
101
+ if (titleElem.length === 0) {
102
+ // 获取不到标题 a 元素,这可能是公众号发的服务消息,丢弃它
36
103
  return;
37
104
  }
38
105
 
39
- let author;
40
- let title = title_elem.text();
41
- const link = title_elem.attr('href');
42
-
43
- const br_node = item.find('.tgme_widget_message_text > br:nth-of-type(1)').get(0); // 获取第一个换行
44
- const author_node = br_node && br_node.prev; // br_node 不为 undefined 时获取它的前一个节点
45
- if (author_node && author_node.type === 'text') {
46
- // 只有这个节点是一个裸文本时它才可能是公众号名
47
- const spaceIndex = author_node.data.indexOf(' ');
48
- const colonIndex = author_node.data.indexOf(':');
49
- if (spaceIndex !== -1 && colonIndex !== -1) {
50
- // 找到了公众号名,说明这个频道订阅了多个公众号
51
- author = author_node.data.slice(spaceIndex + 1, colonIndex); // 提取作者
52
- if (mpName && author !== mpName) {
53
- // 指定了要筛选的公众号名,且该文章不是该公众号发的
54
- return; // 丢弃
55
- } else if (!mpName) {
56
- // 没有指定要筛选的公众号名
57
- title = author + ': ' + title; // 给标题里加上获取到的作者
58
- }
59
- }
106
+ let title = titleElem.text();
107
+ const link = titleElem.attr('href');
108
+
109
+ if (mpName && author !== mpName) {
110
+ // 指定了要筛选的公众号名,且该文章不是该公众号发的
111
+ return; // 丢弃
112
+ } else if (!mpName && author) {
113
+ // 没有指定要筛选的公众号名,且匹配到了作者
114
+ title = author + ': ' + title; // 给标题里加上获取到的作者
60
115
  }
61
116
 
62
117
  const pubDate = new Date(item.find('.tgme_widget_message_date time').attr('datetime')).toUTCString();
@@ -11,12 +11,14 @@ module.exports = async (ctx) => {
11
11
  const routeParams = ctx.params.routeParams || undefined;
12
12
  const token = await ctx.cache.get('weibotimelineuid' + uid, false);
13
13
  let displayVideo = '1';
14
+ let displayArticle = '0';
14
15
  if (routeParams) {
15
16
  if (routeParams === '1' || routeParams === '0') {
16
17
  displayVideo = routeParams;
17
18
  } else {
18
19
  const routeParams = querystring.parse(ctx.params.routeParams);
19
20
  displayVideo = fallback(undefined, queryToBoolean(routeParams.displayVideo), true) ? '1' : '0';
21
+ displayArticle = fallback(undefined, queryToBoolean(routeParams.displayArticle), false) ? '1' : '0';
20
22
  }
21
23
  }
22
24
 
@@ -76,7 +78,22 @@ module.exports = async (ctx) => {
76
78
 
77
79
  // 视频的处理
78
80
  if (displayVideo === '1') {
79
- description = weiboUtils.formatVideo(description, item);
81
+ // 含被转发微博时需要从被转发微博中获取视频
82
+ if (item.retweeted_status) {
83
+ description = weiboUtils.formatVideo(description, item.retweeted_status);
84
+ } else {
85
+ description = weiboUtils.formatVideo(description, item);
86
+ }
87
+ }
88
+
89
+ // 文章的处理
90
+ if (displayArticle === '1') {
91
+ // 含被转发微博时需要从被转发微博中获取文章
92
+ if (item.retweeted_status) {
93
+ description = await weiboUtils.formatArticle(ctx, description, item.retweeted_status);
94
+ } else {
95
+ description = await weiboUtils.formatArticle(ctx, description, item);
96
+ }
80
97
  }
81
98
 
82
99
  return {
@@ -8,12 +8,14 @@ const { fallback, queryToBoolean } = require('@/utils/readable-social');
8
8
  module.exports = async (ctx) => {
9
9
  const uid = ctx.params.uid;
10
10
  let displayVideo = '1';
11
+ let displayArticle = '0';
11
12
  if (ctx.params.routeParams) {
12
13
  if (ctx.params.routeParams === '1' || ctx.params.routeParams === '0') {
13
14
  displayVideo = ctx.params.routeParams;
14
15
  } else {
15
16
  const routeParams = querystring.parse(ctx.params.routeParams);
16
17
  displayVideo = fallback(undefined, queryToBoolean(routeParams.displayVideo), true) ? '1' : '0';
18
+ displayArticle = fallback(undefined, queryToBoolean(routeParams.displayArticle), false) ? '1' : '0';
17
19
  }
18
20
  }
19
21
 
@@ -92,13 +94,27 @@ module.exports = async (ctx) => {
92
94
  const link = `https://weibo.com/${uid}/${item.mblog.bid}`;
93
95
  const formatExtended = weiboUtils.formatExtended(ctx, item.mblog);
94
96
  let description = formatExtended.description;
95
- const formattedTitle = formatExtended.title;
96
- const title = formattedTitle;
97
+ const title = formatExtended.title;
97
98
  const pubDate = item.mblog.created_at;
98
99
 
99
100
  // 视频的处理
100
101
  if (displayVideo === '1') {
101
- description = weiboUtils.formatVideo(description, item.mblog);
102
+ // 含被转发微博时需要从被转发微博中获取视频
103
+ if (item.mblog.retweeted_status) {
104
+ description = weiboUtils.formatVideo(description, item.mblog.retweeted_status);
105
+ } else {
106
+ description = weiboUtils.formatVideo(description, item.mblog);
107
+ }
108
+ }
109
+
110
+ // 文章的处理
111
+ if (displayArticle === '1') {
112
+ // 含被转发微博时需要从被转发微博中获取文章
113
+ if (item.mblog.retweeted_status) {
114
+ description = await weiboUtils.formatArticle(ctx, description, item.mblog.retweeted_status);
115
+ } else {
116
+ description = await weiboUtils.formatArticle(ctx, description, item.mblog);
117
+ }
102
118
  }
103
119
 
104
120
  return {
@@ -1,5 +1,6 @@
1
1
  const querystring = require('querystring');
2
2
  const got = require('@/utils/got');
3
+ const cheerio = require('cheerio');
3
4
  const { fallback, queryToBoolean, queryToInteger } = require('@/utils/readable-social');
4
5
 
5
6
  const weiboUtils = {
@@ -50,12 +51,12 @@ const weiboUtils = {
50
51
  let htmlNewLineUnreplaced = (status.longText && status.longText.longTextContent) || status.text || '';
51
52
  // 表情图标转换为文字
52
53
  if (!showEmojiInDescription) {
53
- htmlNewLineUnreplaced = htmlNewLineUnreplaced.replace(/<span class="url-icon"><img.*?alt="?(.*?)"? [\s\S]*?\/><\/span>/g, '$1');
54
+ htmlNewLineUnreplaced = htmlNewLineUnreplaced.replace(/<span class=["']url-icon["']><img\s[^>]*?alt=["']?([^>]+?)["']?\s[^>]*?\/><\/span>/g, '$1');
54
55
  }
55
- // 去掉外部链接的图标,保留 a 标签链接
56
- htmlNewLineUnreplaced = htmlNewLineUnreplaced.replace(/<span class=["|']url-icon["|']>.*?(<a.*?>).*?<\/span><span class="surl-text">(.*?)<\/span>/g, '$1$2</a>');
57
- // 去掉乱七八糟的图标
58
- // htmlNewLineUnreplaced = htmlNewLineUnreplaced.replace(/<span class=["|']url-icon["|']>(.*?)<\/span>/g, '');
56
+ // 去掉外部链接的图标,保留 a 标签链接 // 不能去掉,否则像超话这样的有意义的图标也会被去掉
57
+ // htmlNewLineUnreplaced = htmlNewLineUnreplaced.replace(/(<a\s[^>]*>)<span class=["']url-icon["']><img\s[^>]*><\/span>[^<>]*?<span class="surl-text">([^<>]*?)<\/span><\/a>/g, '$1$2</a>');
58
+ // 去掉乱七八糟的图标 // 不能去掉,否则像超话这样的有意义的图标也会被去掉
59
+ // htmlNewLineUnreplaced = htmlNewLineUnreplaced.replace(/<span class=["']url-icon["']>(<img\s[^>]*?>)<\/span>/g, '');
59
60
  // 去掉全文
60
61
  htmlNewLineUnreplaced = htmlNewLineUnreplaced.replace(/全文<br>/g, '<br>');
61
62
  htmlNewLineUnreplaced = htmlNewLineUnreplaced.replace(/<a href="(.*?)">全文<\/a>/g, '');
@@ -83,6 +84,22 @@ const weiboUtils = {
83
84
  html = usernameAndAvatar + html;
84
85
  }
85
86
 
87
+ // 添加文章头图,此处不需要回落到被转发的微博,后续处理被转发的微博时,还会执行到这里
88
+ if (status.page_info && status.page_info.type === 'article' && status.page_info.page_pic && status.page_info.page_pic.url) {
89
+ // 如果以后后续流程会用到其他字段,记得修改这里
90
+ const pagePic = {
91
+ large: {
92
+ url: status.page_info.page_pic.url,
93
+ },
94
+ };
95
+ // 文章微博一般不会有配图,但也有可能有:https://weibo.com/6882481489/Lh85BkS3m
96
+ if (status.pics) {
97
+ status.pics.push(pagePic);
98
+ } else {
99
+ status.pics = [pagePic];
100
+ }
101
+ }
102
+
86
103
  // 添加微博配图
87
104
  if (status.pics) {
88
105
  if (readable) {
@@ -174,6 +191,8 @@ const weiboUtils = {
174
191
  }
175
192
  if (!status.retweeted_status || showRetweetTextInTitle) {
176
193
  title += htmlNewLineUnreplaced
194
+ .replace(/<span class=["']url-icon["']><img\s[^>]*?alt=["']?([^>]+?)["']?\s[^>]*?\/><\/span>/g, '$1') // 表情转换
195
+ .replace(/<span class=["']url-icon["']>(<img\s[^>]*?>)<\/span>/g, '') // 去掉所有图标
177
196
  .replace(/<img[\s\S]*?>/g, '[图片]')
178
197
  .replace(/<.*?>/g, '')
179
198
  .replace('\n', '');
@@ -181,6 +200,8 @@ const weiboUtils = {
181
200
  if (status.retweeted_status) {
182
201
  title += showEmojiForRetweet ? '🔁 ' : ' - 转发 ';
183
202
  title += retweeted
203
+ .replace(/<span class=["']url-icon["']><img\s[^>]*?alt=["']?([^>]+?)["']?\s[^>]*?\/><\/span>/g, '$1') // 表情转换
204
+ .replace(/<span class=["']url-icon["']>(<img\s[^>]*?>)<\/span>/g, '') // 去掉所有图标
184
205
  .replace(/<img[\s\S]*?>/g, '[图片]')
185
206
  .replace(/<.*?>/g, '')
186
207
  .replace('\n', '');
@@ -240,6 +261,93 @@ const weiboUtils = {
240
261
  }
241
262
  return itemDesc;
242
263
  },
264
+ formatArticle: async (ctx, itemDesc, status) => {
265
+ const pageInfo = status.page_info;
266
+ if (pageInfo && pageInfo.type === 'article' && pageInfo.page_url) {
267
+ const pageUrl = pageInfo.page_url;
268
+ const articleIdMatch = pageUrl.match(/id=(\d+)/);
269
+ if (!articleIdMatch) {
270
+ return itemDesc;
271
+ }
272
+ const articleId = articleIdMatch[1];
273
+ const link = `https://card.weibo.com/article/m/aj/detail?id=${articleId}`;
274
+ const response = await ctx.cache.tryGet(link, async () => {
275
+ const _response = await got.get(link, {
276
+ headers: {
277
+ Referer: `https://card.weibo.com/article/m/show/id/${articleId}`,
278
+ 'MWeibo-Pwa': 1,
279
+ 'X-Requested-With': 'XMLHttpRequest',
280
+ 'User-Agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A372 Safari/604.1',
281
+ },
282
+ });
283
+ return _response.data;
284
+ }); // cache it!
285
+ const article = response.data;
286
+ if (article && article.title && article.content) {
287
+ const title = article.title;
288
+ const content = article.content;
289
+ const summary = article.summary;
290
+ const createAt = article.create_at;
291
+ const readCount = article.read_count;
292
+ const isOriginal = article.is_original;
293
+ const isArticleNonFree = article.is_article_free; // 微博起错了字段名,它为 1 时才是收费文章
294
+
295
+ // 许多微博文章都给文字设置了白色背景,这里也只好使用白色背景了
296
+ let html = '<br clear="both" /><br clear="both" />';
297
+ html += '<div style="clear: both"></div><div style="background: #fff;border:5px solid #80808030;margin:0;padding:3% 5%;overflow-wrap: break-word">';
298
+
299
+ html += `<h1 style="font-size: 1.5rem;line-height: 1.25;color: #333;">${title}</h1>`; // 加入标题
300
+
301
+ // 加入文章信息
302
+ const iconStyle =
303
+ 'display: inline-block;margin-inline: 0.25rem;width: 2.25rem; height: 1.125rem; background: #eee; border-radius: 2px; box-sizing: border-box; text-align: center; line-height: 1.0625rem; font-size: 0.75rem; color: #aaa;';
304
+ let articleMeta = '<p style="line-height: 1.66; color: #999;margin: 0 0 0.75rem;font-size: 0.75rem;padding: 0">';
305
+ if (isArticleNonFree) {
306
+ articleMeta += `<span style="${iconStyle}">试读</span> `;
307
+ }
308
+ if (isOriginal) {
309
+ articleMeta += `<span style="${iconStyle}">原创</span> `;
310
+ }
311
+ articleMeta += `<span style="margin-inline: 0.25rem;">发布时间: ${createAt}</span> `; // 发布时间
312
+ articleMeta += `<span style="margin-inline: 0.25rem;">阅读量: ${readCount}</span> `; // 阅读量
313
+ articleMeta += '</p>';
314
+ html += articleMeta;
315
+
316
+ if (summary) {
317
+ html += `<p style="color: #999;line-height: 1.5rem;padding: 0.0625rem 0 0.875rem;margin: 0">${summary}</p>`; // 摘要
318
+ }
319
+
320
+ html += '<div style="height: 0;border-bottom: 1px dashed #999;margin-bottom: 0.75rem;"></div>'; // 分割线
321
+
322
+ // 正文处理,加入一些在微博文章页的 CSS 中定义的不可或缺的样式
323
+ const $ = cheerio.load(content);
324
+ $('p').each((_, elem) => {
325
+ elem = $(elem);
326
+ let style = elem.attr('style') || '';
327
+ style = 'margin: 0;padding: 0;border: 0;' + style;
328
+ elem.attr('style', style);
329
+ });
330
+ $('.image').each((_, elem) => {
331
+ elem = $(elem);
332
+ let style = elem.attr('style') || '';
333
+ style = 'display: table;text-align: center;margin-left: auto;margin-right: auto;clear: both;min-width: 50px;' + style;
334
+ elem.attr('style', style);
335
+ });
336
+ $('img').each((_, elem) => {
337
+ elem = $(elem);
338
+ let style = elem.attr('style') || '';
339
+ style = 'display: block;max-width: 100%;margin-left: auto;margin-right: auto;min-width: 50px;' + style;
340
+ elem.attr('style', style);
341
+ });
342
+ const contentHtml = $.html();
343
+ html += `<div style="line-height: 1.59;text-align: justify;font-size: 1.0625rem;color: #333;">${contentHtml}</div>`; // 正文
344
+
345
+ html += '</div>';
346
+ itemDesc += html;
347
+ }
348
+ }
349
+ return itemDesc;
350
+ },
243
351
  };
244
352
 
245
353
  module.exports = weiboUtils;
@@ -1,4 +1,5 @@
1
1
  const got = require('@/utils/got');
2
+ const { parseDate } = require('@/utils/parse-date');
2
3
 
3
4
  const titles = {
4
5
  total: '全站',
@@ -23,9 +24,9 @@ module.exports = async (ctx) => {
23
24
  });
24
25
 
25
26
  const items = response.data.data.map((item) => ({
26
- link: item.target.url,
27
+ link: `https://www.zhihu.com/question/${item.target.id}`,
27
28
  title: item.target.title,
28
- pubDate: new Date(item.target.created * 1000).toUTCString(),
29
+ pubDate: parseDate(item.target.created * 1000),
29
30
  description: item.target.excerpt ? `<p>${item.target.excerpt}</p>` : '',
30
31
  }));
31
32
 
@@ -0,0 +1,7 @@
1
+ module.exports = {
2
+ '/motif/:mid': ['nczitzk'],
3
+ '/news/:category?': ['nczitzk'],
4
+ '/newsflashes': ['hillerliao'],
5
+ '/search/article/:keyword': ['xyqfer', 'kt286'],
6
+ '/user/:uid': ['nczitzk'],
7
+ };
@@ -1,4 +1,5 @@
1
1
  const got = require('@/utils/got');
2
+ const { parseDate } = require('@/utils/parse-date');
2
3
 
3
4
  module.exports = async (ctx) => {
4
5
  const motifUrl = `https://36kr.com/motif/${ctx.params.mid}`;
@@ -13,7 +14,7 @@ module.exports = async (ctx) => {
13
14
  const articleList = motifArticleList.map((item) => ({
14
15
  title: item.templateMaterial.widgetTitle,
15
16
  link: `https://36kr.com/${item.route.split('?')[0] === 'detail_video' ? 'video' : 'p'}/${item.itemId}`,
16
- pubDate: new Date(item.templateMaterial.publishTime).toUTCString(),
17
+ pubDate: parseDate(item.templateMaterial.publishTime),
17
18
  }));
18
19
 
19
20
  ctx.state.data = {
@@ -0,0 +1,56 @@
1
+ const got = require('@/utils/got');
2
+ const cheerio = require('cheerio');
3
+ const { parseDate } = require('@/utils/parse-date');
4
+
5
+ const links = {
6
+ latest: 'information/web_news',
7
+ recommend: 'information/web_recommend',
8
+ life: 'information/happy_life',
9
+ estate: 'information/real_estate',
10
+ workplace: 'information/web_zhichang',
11
+ };
12
+
13
+ module.exports = async (ctx) => {
14
+ const category = ctx.params.category ?? 'latest';
15
+
16
+ const rootUrl = 'https://36kr.com';
17
+ const currentUrl = `${rootUrl}/${links.hasOwnProperty(category) ? links[category] : `information/${category}`}`;
18
+
19
+ const response = await got({
20
+ method: 'get',
21
+ url: currentUrl,
22
+ });
23
+
24
+ const data = JSON.parse(response.data.match(/<script>window\.initialState=(.*?)<\/script>/)[1]);
25
+
26
+ const list = data.information.informationList.itemList
27
+ .filter((item) => item.itemType === 10)
28
+ .map((item) => ({
29
+ title: item.templateMaterial.widgetTitle,
30
+ link: `${rootUrl}/p/${item.itemId} `,
31
+ pubDate: parseDate(item.templateMaterial.publishTime),
32
+ }));
33
+
34
+ const items = await Promise.all(
35
+ list.map((item) =>
36
+ ctx.cache.tryGet(item.link, async () => {
37
+ const detailResponse = await got({
38
+ method: 'get',
39
+ url: item.link,
40
+ });
41
+
42
+ const content = cheerio.load(detailResponse.data);
43
+
44
+ item.description = content('.articleDetailContent').html();
45
+
46
+ return item;
47
+ })
48
+ )
49
+ );
50
+
51
+ ctx.state.data = {
52
+ title: `${response.data.match(/shareTitle: "(.*)频道.*",/)[1]} - 36氪资讯`,
53
+ link: currentUrl,
54
+ item: items,
55
+ };
56
+ };
@@ -1,4 +1,5 @@
1
1
  const got = require('@/utils/got');
2
+ const { parseDate } = require('@/utils/parse-date');
2
3
 
3
4
  module.exports = async (ctx) => {
4
5
  const response = await got({
@@ -21,7 +22,7 @@ module.exports = async (ctx) => {
21
22
  const single = {
22
23
  title,
23
24
  link,
24
- pubDate: new Date(date).toUTCString(),
25
+ pubDate: parseDate(date),
25
26
  description,
26
27
  };
27
28