-
+
+
+
+
+
+
+
+
作者: @{{ uid }}
@@ -69,19 +76,23 @@ export default {
type: String,
default: null
},
+ puppeteer: {
+ type: String,
+ default: null
+ },
},
methods: {
renderMarkdown(item, inline = true) {
const md = require('markdown-it')({
- html: true,
+ html: true,
});
- return inline ? md.renderInline(item) : md.render(item);
+ return inline ? md.renderInline(item) : md.render(item);
},
},
computed: {
- demoUrl: function () {
- return 'https://rsshub.app'+ this.example
- }
+ demoUrl: function () {
+ return 'https://rsshub.app'+ this.example
+ }
}
}
diff --git a/docs/.vuepress/components/RouteEn.vue b/docs/.vuepress/components/RouteEn.vue
index 92b15998b469fc..551ee5d3e3cc30 100644
--- a/docs/.vuepress/components/RouteEn.vue
+++ b/docs/.vuepress/components/RouteEn.vue
@@ -1,7 +1,14 @@
-
+
+
+
+
+
+
+
+
Author: @{{ uid }}
@@ -53,6 +60,10 @@ export default {
type: String,
default: null
},
+ supportScihub: {
+ type: String,
+ default: null
+ },
radar: {
type: String,
default: null
@@ -65,19 +76,23 @@ export default {
type: String,
default: null
},
+ puppeteer: {
+ type: String,
+ default: null
+ }
},
methods: {
renderMarkdown(item, inline = true) {
const md = require('markdown-it')({
- html: true,
+ html: true,
});
- return inline ? md.renderInline(item) : md.render(item);
+ return inline ? md.renderInline(item) : md.render(item);
},
},
computed: {
- demoUrl: function () {
- return 'https://rsshub.app'+ this.example
- }
+ demoUrl: function () {
+ return 'https://rsshub.app'+ this.example
+ }
}
}
diff --git a/docs/bbs.md b/docs/bbs.md
index 003f265bd8fb45..2f27dee6a73f24 100644
--- a/docs/bbs.md
+++ b/docs/bbs.md
@@ -208,6 +208,32 @@ pageClass: routes
+## Mobilism
+
+### 论坛
+
+
+
+| 安卓 | iPhone | iPad |
+| ------- | ------ | ---- |
+| android | iphone | ipad |
+
+| 应用 | 游戏 |
+| ---- | ----- |
+| apps | games |
+
+
+
+### 门户
+
+
+
+| 安卓应用 | 安卓游戏 | 图书 | iPad 应用 | iPad 游戏 | iPhone 应用 | iPhone 游戏 |
+| ---- | ----- | ----- | ------- | ------- | --------- | --------- |
+| aapp | agame | ebook | ipapp | ipgame | iapp | igame |
+
+
+
## NGA
### 分区帖子
@@ -564,7 +590,7 @@ pageClass: routes
### 发现
-
+
| 最新 | 推荐 | 热门 |
| --- | --------- | --- |
@@ -572,11 +598,11 @@ pageClass: routes
### 精选
-
+
### 话题
-
+
## 三星盖乐世社区
diff --git a/docs/en/bbs.md b/docs/en/bbs.md
index bce33ca4795301..eb86832bb29d12 100644
--- a/docs/en/bbs.md
+++ b/docs/en/bbs.md
@@ -36,6 +36,32 @@ pageClass: routes
+## Mobilism
+
+### Forums
+
+
+
+| Android | iPhone | iPad |
+| ------- | ------ | ---- |
+| android | iphone | ipad |
+
+| Apps | games |
+| ---- | ----- |
+| apps | games |
+
+
+
+### Portal
+
+
+
+| Android Apps | Android Games | ebook | iPad Apps | iPad Games | iPhone Apps | iPhone Games |
+| ------------ | ------------- | ----- | --------- | ---------- | ----------- | ------------ |
+| aapp | agame | ebook | ipapp | ipgame | iapp | igame |
+
+
+
## SCBOY forum
### Thread
diff --git a/docs/en/game.md b/docs/en/game.md
index 4ae63e39e51213..59c83a14f69a8f 100755
--- a/docs/en/game.md
+++ b/docs/en/game.md
@@ -60,7 +60,7 @@ Language codes
### Free games
-
+
## FINAL FANTASY XIV
diff --git a/docs/en/government.md b/docs/en/government.md
index 01f3ee3755c4a5..33447cab73f46d 100644
--- a/docs/en/government.md
+++ b/docs/en/government.md
@@ -66,7 +66,7 @@ Language
### Latest News
-
+
Category
| All | Detected Cases | Investigation Reports or Recommendations | Annual Reports | CCAC's Updates |
diff --git a/docs/en/journal.md b/docs/en/journal.md
index 55fc8f4512abb8..4e504820322863 100644
--- a/docs/en/journal.md
+++ b/docs/en/journal.md
@@ -178,9 +178,15 @@ New items may always at the end of the list, when the number of paper entries is
## Nature Journal
+::: tip Tips
+
+You can get all short name of a journal from or [Journal List](#nature-journal-journal-list).
+
+:::
+
### Latest Research
-
+
| `:journal` | Full Name of the Journal | Route |
| :-----------: | :-------------------------: | ---------------------------------------------------------------------------------- |
@@ -194,16 +200,16 @@ New items may always at the end of the list, when the number of paper entries is
| nmat | Nature Materials | [/nature/research/nmat](https://rsshub.app/nature/research/nmat) |
| natmachintell | Nature Machine Intelligence | [/nature/research/natmachintell](https://rsshub.app/nature/research/natmachintell) |
-- Using router (`/nature/research/` + “short name for a journal”) to query latest research paper for a certain journal of Nature Publishing Group.
+- Using router (`/nature/research/` + "short name for a journal") to query latest research paper for a certain journal of Nature Publishing Group.
If the `:journal` parameter is blank, then latest research of Nature will return.
- The journals from NPG are run by different group of people, and the website of may not be consitent for all the journals
-- Only the abstract section is rendered
+- Only abstract is rendered in some researches
### News & Comment
-
+
| `:journal` | Full Name of the Journal | Route |
| :-----------: | :-------------------------: | --------------------------------------------------------------------------------------------------------------------- |
@@ -216,7 +222,7 @@ New items may always at the end of the list, when the number of paper entries is
| nmat | Nature Materials | [/nature/news-and-comment/nmat](https://rsshub.app/nature/news-and-comment/nmat) |
| natmachintell | Nature Machine Intelligence | [/nature/news-and-https://rsshub.app/comment/natmachintell](https://rsshub.app/nature/news-and-comment/natmachintell) |
-- Using router (`/nature/research/` + “short name for a journal”) to query latest research paper for a certain journal of Nature Publishing Group.
+- Using router (`/nature/research/` + "short name for a journal") to query latest research paper for a certain journal of Nature Publishing Group.
- The journals from NPG are run by different group of people, and the website of may not be consitent for all the journals
@@ -229,13 +235,25 @@ Subscribe to the cover images of the Nature journals, and get the latest publica
-### News
+### Nature News
-
+
### Research Highlight
-
+
+
+::: warning Warning
+
+Only some journals are supported.
+
+:::
+
+
+
+### Journal List
+
+
## Oxford University Press
@@ -243,7 +261,7 @@ Subscribe to the cover images of the Nature journals, and get the latest publica
#### Journal
-
+
## Proceedings of The National Academy of Sciences (PNAS)
diff --git a/docs/en/new-media.md b/docs/en/new-media.md
index 9f58c6469c580e..3cbd57c22d296f 100644
--- a/docs/en/new-media.md
+++ b/docs/en/new-media.md
@@ -8,7 +8,7 @@ pageClass: routes
### 9To5 Sub-site
-
+
Supported sub-sites:
| 9To5Mac | 9To5Google | 9To5Toys |
diff --git a/docs/en/other.md b/docs/en/other.md
index e6dbed504ccf66..c4f210e9441c51 100644
--- a/docs/en/other.md
+++ b/docs/en/other.md
@@ -136,6 +136,12 @@ Official Website:
+## Lever
+
+### Recruitment
+
+
+
## MITRE
### All Publications
@@ -243,8 +249,8 @@ Type
### Homepage
-
+
### User
-
+
diff --git a/docs/en/programming.md b/docs/en/programming.md
index 72ca60ebc0c75e..328a0c8a7381d5 100644
--- a/docs/en/programming.md
+++ b/docs/en/programming.md
@@ -82,6 +82,18 @@ Category
+## CNCF
+
+### Category
+
+
+
+| Blog | News | Announcements | Reports |
+|------|------|---------------|---------|
+| blog | news | announcements | reports |
+
+
+
## Codeforces
### Latest contests
diff --git a/docs/en/reading.md b/docs/en/reading.md
index 09f23fc0de20b7..7ebac82ba5308c 100644
--- a/docs/en/reading.md
+++ b/docs/en/reading.md
@@ -38,7 +38,24 @@ Eg:
### Category
-
+
+
+## Mobilism
+
+### eBook Releases
+
+
+
+| Category | Parameter |
+| ------------------------ | ---------- |
+| Romance | romance |
+| Sci-Fi/Fantasy/Horror | scifi |
+| General Fiction/Classics | classics |
+| Magazines & Newspapers | magazines |
+| Audiobooks | audioBooks |
+| Comics | comics |
+
+
## syosetu
diff --git a/docs/en/social-media.md b/docs/en/social-media.md
index 2f724b2ae72807..0462d71757c82d 100644
--- a/docs/en/social-media.md
+++ b/docs/en/social-media.md
@@ -304,34 +304,38 @@ Due to Telegram restrictions, some channels involving pornography, copyright, an
::: warning
-Due to Twitter API restrictions, the Twitter Routes currently supports tweets within 7 days
+Due to restrictions from Twitter, currently only tweets within 7 days are available in some routes.
+
+Some routes rely on the Twitter Developer API, which requires to be specially configured to enable.\
+There are two routes (`/twitter/user` and `/twitter/keyword`) comes with Web API implementation which does not require to be specially configured to enable along with the Developer API implementation. By default, the Developer API is prioritized, but if it is not configured or errors, the Web API will be used. However, there are some differences between the two APIs, e.g. `excludeReplies` in the Developer API will treat [threads](https://blog.twitter.com/official/en_us/topics/product/2017/nicethreads.html) (self-replied tweets) as replies and exclude them, while in the Web API it will not. If you would like to exclude replies but include threads, enable `forceWebApi` in the `/twitter/user` route.
:::
-Specify options (in query string's format) in parameter `routeParams` to control some extra features for Tweets
-
-| Key | Description | Accepts | Defaults to |
-| ------ | ----------- | ------- | ------------ |
-| readable | Enable readable layout | 0/1/true/false | false |
-| authorNameBold | Display author name in bold | 0/1/true/false | false |
-| showAuthorInTitle | Show author name in title | 0/1/true/false | false (true in `/twitter/followings`) |
-| showAuthorInDesc | Show author name in description (RSS body) | 0/1/true/false | false (true in `/twitter/followings`) |
-| showQuotedAuthorAvatarInDesc | Show avatar of quoted Tweet's author in description (RSS body) (Not recommended if your RSS reader extracts images from description) | 0/1/true/false | false |
-| showAuthorAvatarInDesc | Show avatar of author in description (RSS body) (Not recommended if your RSS reader extracts images from description)| 0/1/true/false | false |
-| showEmojiForRetweetAndReply | Use "🔁" instead of "Rt", "↩️" & "💬" instead of "Re" | 0/1/true/false | false |
-| showRetweetTextInTitle | Show quote comments in title | 0/1/true/false | true |
-| addLinkForPics | Add clickable links for Tweet pictures | 0/1/true/false | false |
-| showTimestampInDescription| Show timestamp in description | 0/1/true/false | false |
-| showQuotedInTitle | Show quoted tweet in title | 0/1/true/false | false |
-| widthOfPics | Width of Tweet pictures | Unspecified/Integer | Unspecified |
-| heightOfPics | Height of Tweet pictures | Unspecified/Integer | Unspecified |
-| sizeOfAuthorAvatar | Size of author's avatar | Integer | 48 |
-| sizeOfQuotedAuthorAvatar | Size of quoted tweet's author's avatar | Integer | 24 |
-| excludeReplies | Exclude replies, only available in "User timeline" | 0/1/true/false | false |
-| includeRts | Include retweets, only available in "User timeline" | 0/1/true/false | true |
-| count | `count` parameter passed to Twitter API, only available in "User timeline" | Unspecified/Integer | Unspecified |
-
-Specify different option values than default values to improve readablility. The URL
+Specify options (in the format of query string) in parameter `routeParams` to control some extra features for Tweets
+
+| Key | Description | Accepts | Defaults to |
+|--------------------------------|--------------------------------------------------------------------------------------------------------------------------------------|------------------------|-------------------------------------------|
+| `readable` | Enable readable layout | `0`/`1`/`true`/`false` | `false` |
+| `authorNameBold` | Display author name in bold | `0`/`1`/`true`/`false` | `false` |
+| `showAuthorInTitle` | Show author name in title | `0`/`1`/`true`/`false` | `false` (`true` in `/twitter/followings`) |
+| `showAuthorInDesc` | Show author name in description (RSS body) | `0`/`1`/`true`/`false` | `false` (`true` in `/twitter/followings`) |
+| `showQuotedAuthorAvatarInDesc` | Show avatar of quoted Tweet's author in description (RSS body) (Not recommended if your RSS reader extracts images from description) | `0`/`1`/`true`/`false` | `false` |
+| `showAuthorAvatarInDesc` | Show avatar of author in description (RSS body) (Not recommended if your RSS reader extracts images from description) | `0`/`1`/`true`/`false` | `false` |
+| `showEmojiForRetweetAndReply` | Use "🔁" instead of "Rt", "↩️" & "💬" instead of "Re" | `0`/`1`/`true`/`false` | `false` |
+| `showRetweetTextInTitle` | Show quote comments in title (if `false`, only the retweeted tweet will be shown in the title) | `0`/`1`/`true`/`false` | `true` |
+| `addLinkForPics` | Add clickable links for Tweet pictures | `0`/`1`/`true`/`false` | `false` |
+| `showTimestampInDescription` | Show timestamp in description | `0`/`1`/`true`/`false` | `false` |
+| `showQuotedInTitle` | Show quoted tweet in title | `0`/`1`/`true`/`false` | `false` |
+| `widthOfPics` | Width of Tweet pictures | Unspecified/Integer | Unspecified |
+| `heightOfPics` | Height of Tweet pictures | Unspecified/Integer | Unspecified |
+| `sizeOfAuthorAvatar` | Size of author's avatar | Integer | `48` |
+| `sizeOfQuotedAuthorAvatar` | Size of quoted tweet's author's avatar | Integer | `24` |
+| `excludeReplies` | Exclude replies, only available in `/twitter/user` | `0`/`1`/`true`/`false` | `false` |
+| `includeRts` | Include retweets, only available in `/twitter/user` | `0`/`1`/`true`/`false` | `true` |
+| `forceWebApi` | Force using Web API even if Developer API is configured, only available in `/twitter/user` and `/twitter/keyword` | `0`/`1`/`true`/`false` | `false` |
+| `count` | `count` parameter passed to Twitter API, only available in `/twitter/user` | Unspecified/Integer | Unspecified |
+
+Specify different option values than default values to improve readability. The URL
```
https://rsshub.app/twitter/user/durov/readable=1&authorNameBold=1&showAuthorInTitle=1&showAuthorInDesc=1&showQuotedAuthorAvatarInDesc=1&showAuthorAvatarInDesc=1&showEmojiForRetweetAndReply=1&showRetweetTextInTitle=0&addLinkForPics=1&showTimestampInDescription=1&showQuotedInTitle=1&heightOfPics=150
@@ -343,11 +347,11 @@ generates
### User timeline
-
+
### User media
-
+
## User following timeline
@@ -371,7 +375,7 @@ This route requires Twitter token's corresponding id, therefore it's only availa
### Keyword
-
+
### Trends
diff --git a/docs/en/traditional-media.md b/docs/en/traditional-media.md
index 4eb7e1ef37897c..5495a64ac17d62 100644
--- a/docs/en/traditional-media.md
+++ b/docs/en/traditional-media.md
@@ -60,7 +60,7 @@ The following are some of the supported Channel and Topic ids.
### Topics
-
+
## BBC
@@ -502,6 +502,20 @@ Provides all of the articles by the specified Yahoo! author.
+## Yomiuri Shimbun 読売新聞
+
+### News
+
+
+
+Free articles only.
+
+| 新着・速報 | 社会 | 政治 | 経済 | スポーツ | 国際 | 科学・IT | 選挙・世論調査 | エンタメ・文化 | 囲碁・将棋 | ライフ | 地域 | 社説 | 皇室 |
+| ------- | -------- | -------- | ------- | ------ | ----- | ------- | -------- | ------- | --------- | ---- | ----- | --------- | --------- |
+| news | national | politics | economy | sports | world | science | election | culture | igoshougi | life | local | editorial | koushitsu |
+
+
+
## 公視新聞網
### Daily News
diff --git a/docs/faq.md b/docs/faq.md
index f698e839350e26..2a3752fc292722 100644
--- a/docs/faq.md
+++ b/docs/faq.md
@@ -16,9 +16,15 @@
**A:** 演示地址为 [rsshub.app](https://rsshub.app), 缓存时间 120 分钟,可以随意使用。但如果你看到路由有 标记,如微博、知乎等,意味着目标网站有严重的反爬策略,demo 无法确保可用性,建议自建来提高稳定性。
-**Q: 为什么 RSSHub 里的图片加载不出来?**
+**Q: 为什么 RSSHub 里的图片 / 视频加载不出来?**
-**A:** RSSHub 里的图片地址都是源站地址,大部分有防盗链,所以 RSSHub 给图片加了 `referrerpolicy="no-referrer"` 属性来防止跨域问题,但部分 RSS 服务会自作主张去掉这个属性,如 Feedly、Inoreader,在它们的网页端图片会触发跨域加载不出来
+**A:** RSSHub 里的图片 / 视频地址都是源站地址,部分有防盗链,所以 RSSHub 给图片加了 `referrerpolicy="no-referrer"` 属性来防止跨域问题,但部分 RSS 服务会自作主张去掉这个属性,如 Feedly、Inoreader,在它们的网页端图片会触发跨域加载不出来。部分网站则要求 Referrer 来防止盗链,这种情况可以通过设置图片反代进行处理。详情请查看文档`部署->图片处理`部分
+
+视频目前没有类似的属性,下面是一些解决方案:
+
+1. 使用不发送 Referer 的阅读器,如 [Inoreader 网页版](https://www.inoreader.com/)配合[禁用 referer 的 user script](https://greasyfork.org/zh-CN/scripts/376884-%E6%98%BE%E7%A4%BA%E9%98%B2%E7%9B%97%E9%93%BE%E5%9B%BE%E7%89%87-for-inoreader)、[RSS to Telegram Bot](https://github.com/Rongronggg9/RSS-to-Telegram-Bot) 等。如果你的阅读器能够在不启用上述两个变通解决方案时成功播放内嵌视频,那么它就是不发送 Referer 的,请考虑添加到文档里帮助更多的人。
+2. 部分路由支持生成关闭内嵌视频,直接输出视频地址,或者其他可以尝试绕开相关限制的的订阅,可尝试使用。具体说明请查看相关路由(举例:`社交媒体->抖音`)
+3. 回到原网站查看相关资源。
**Q: 没有我想订阅的网站怎么办嘤嘤嘤 QAQ**
diff --git a/docs/finance.md b/docs/finance.md
index ed6f286eeb636c..8da5887ad6177d 100644
--- a/docs/finance.md
+++ b/docs/finance.md
@@ -476,11 +476,11 @@ pageClass: routes
### 沟通交流
-
+
### 货币政策司公开市场交易公告
-
+
### 政策研究
diff --git a/docs/forecast.md b/docs/forecast.md
index 73b15b6daa975e..85369e4b553651 100644
--- a/docs/forecast.md
+++ b/docs/forecast.md
@@ -26,7 +26,17 @@ pageClass: routes
### 中国地震台
-
+
+
+| 参数 | 类型 |
+| -- | ---------------- |
+| 1 | 最近 24 小时地震信息 |
+| 2 | 最近 48 小时地震信息 |
+| 5 | 最近一年 3.0 级以上地震信息 |
+| 7 | 最近一年 3.0 级以下地震 |
+| 8 | 最近一年 4.0 级以上地震信息 |
+| 9 | 最近一年 5.0 级以上地震信息 |
+| 0 | 最近一年 6.0 级以上地震信息 |
可通过全局过滤参数订阅您感兴趣的地区.
@@ -86,11 +96,11 @@ pageClass: routes
### 95598 停电查询网
-
+
### 南京市
-
+
## 停水通知
@@ -130,7 +140,14 @@ pageClass: routes
### 武汉市
-
+
+
+| channelId | 分类 |
+| --------- | ----- |
+| 68 | 计划性停水 |
+| 69 | 突发性停水 |
+
+
## 香港天文台
diff --git a/docs/game.md b/docs/game.md
index b3feb40c752748..52152928e592f0 100644
--- a/docs/game.md
+++ b/docs/game.md
@@ -95,7 +95,7 @@ pageClass: routes
### 免费游戏
-
+
## Fate Grand Order
diff --git a/docs/government.md b/docs/government.md
index 8c104b2bd4daa7..d745e1e465363e 100644
--- a/docs/government.md
+++ b/docs/government.md
@@ -30,7 +30,7 @@ pageClass: routes
### 最新消息
-
+
| 全部 | 案件发布 | 调查报告或勘喻 | 年度报告 | 公署消息 |
| --- | ---- | ---------- | ------------ | ------- |
@@ -725,6 +725,16 @@ pageClass: routes
+### 河北省财政厅
+
+
+
+| 财政动态 | 综合新闻 | 通知公告 |
+| ---- | ---- | ---- |
+| gzdt | zhxw | tzgg |
+
+
+
### 河北省退役军人事务厅
diff --git a/docs/journal.md b/docs/journal.md
index d67c9404ff80f5..9bb41c3dcaa9f5 100644
--- a/docs/journal.md
+++ b/docs/journal.md
@@ -150,9 +150,15 @@ pageClass: routes
## Nature 系列
+::: tip Tips
+
+You can get all short name of a journal from or [期刊列表](#nature-xi-lie-qi-kan-lie-biao).
+
+:::
+
### 最新成果
-
+
| `:journal` | 期刊名 | 路由 |
| :-----------: | :-------------------------: | ---------------------------------------------------------------------------------- |
@@ -166,16 +172,16 @@ pageClass: routes
| nmat | Nature Materials | [/nature/research/nmat](https://rsshub.app/nature/research/nmat) |
| natmachintell | Nature Machine Intelligence | [/nature/research/natmachintell](https://rsshub.app/nature/research/natmachintell) |
-- 通过 `/nature/research/` + “杂志简写” 来获取对应杂志的最新文章(Latest Research)。
- 若参数置空(`/nature/research`),则默认获取主刊(Nature)的最新文章。
-- 由于 Nature 系列的刊物是分别由不同的编辑来独立运营,所以页面格式上有些差异。目前**仅**对以下杂志进行了测试。
-- 由于权限的限制,目前仅获取论文的摘要进行展示。
+- 通过 `/nature/research/` + “杂志简写” 来获取对应杂志的最新文章 (Latest Research)。
+ 若参数置空 (`/nature/research`),则默认获取主刊 (Nature) 的最新文章。
+- 由于 Nature 系列的刊物是分别由不同的编辑来独立运营,所以页面格式上有些差异。目前**仅**对以上杂志进行了测试。
+- 由于权限的限制,目前部分论文仅获取摘要进行展示。
### 新闻及评论
-
+
| `:journal` | 期刊名 | 路由 |
| :-----------: | :-------------------------: | -------------------------------------------------------------------------------------------------- |
@@ -188,9 +194,9 @@ pageClass: routes
| nmat | Nature Materials | [/nature/news-and-comment/nmat](https://rsshub.app/nature/news-and-comment/nmat) |
| natmachintell | Nature Machine Intelligence | [/nature/news-and-comment/natmachintell](https://rsshub.app/nature/news-and-comment/natmachintell) |
-- 通过 `/nature/research/` + “杂志简写” 来获取对应杂志的最新文章(Latest Research)。
+- 通过 `/nature/research/` + “杂志简写” 来获取对应杂志的最新文章 (Latest Research)。
主刊由于格式不同,该 router 并未支持,采用 `/nature/news` 来获取新闻。
-- 由于 Nature 系列的刊物是分别由不同的编辑来独立运营,所以页面格式上有些差异。目前**仅**对以下杂志进行了测试。
+- 由于 Nature 系列的刊物是分别由不同的编辑来独立运营,所以页面格式上有些差异。目前**仅**对以上杂志进行了测试。
@@ -204,11 +210,21 @@ pageClass: routes
### 主刊 - 新闻动态
-
+
+
+### 精彩研究
+
+
+
+::: warning 警告
+
+仅支持部分期刊。
+
+:::
-### 主刊 - 精彩研究
+### 期刊列表
-
+
## Oxford University Press
diff --git a/docs/multimedia.md b/docs/multimedia.md
index 4ce932dd256080..0f61f98a1db8a5 100644
--- a/docs/multimedia.md
+++ b/docs/multimedia.md
@@ -888,12 +888,14 @@ JavDB 有多个备用域名,本路由默认使用永久域名
+
| 人气 | 最新 | 发售日期 | 标题顺序 | 价格升序 | 价格降序 |
| ------- | ---- | ---- | ----- | ---- | ---- |
| popular | near | date | title | low | high |
+
+
## rs05 人生 05 电影
### rs05 电影列表
diff --git a/docs/new-media.md b/docs/new-media.md
index d1ab4fb402cd04..4925fd9870b0ac 100644
--- a/docs/new-media.md
+++ b/docs/new-media.md
@@ -104,7 +104,7 @@ pageClass: routes
### 9To5 分站
-
+
支持分站:
diff --git a/docs/other.md b/docs/other.md
index be1f00bfb260c0..5c6846a3dad067 100644
--- a/docs/other.md
+++ b/docs/other.md
@@ -613,11 +613,11 @@ type 为 all 时,category 参数不支持 cost 和 free
### 主页
-
+
### 用户
-
+
## 律师事务所文章
diff --git a/docs/programming.md b/docs/programming.md
index 1e88e5e12f6970..7d6a18bcb39c52 100644
--- a/docs/programming.md
+++ b/docs/programming.md
@@ -96,6 +96,18 @@ Rated 对象
+## CNCF
+
+### 栏目
+
+
+
+| Blog | News | Announcements | Reports |
+| ---- | ---- | ------------- | ------- |
+| blog | news | announcements | reports |
+
+
+
## Codeforces
#### 最新比赛
@@ -701,7 +713,7 @@ GitHub 官方也提供了一些 RSS:
### 分类
-
+
| 后端 | 前端 | Android | iOS | 人工智能 | 开发工具 | 代码人生 | 阅读 |
| ------- | -------- | ------- | --- | ---- | ------- | ------ | ------- |
@@ -711,11 +723,11 @@ GitHub 官方也提供了一些 RSS:
### 标签
-
+
### 热门
-
+
| category | 标签 |
| -------- | ------- |
@@ -741,13 +753,13 @@ GitHub 官方也提供了一些 RSS:
### 小册
-
+
> 掘金小册需要付费订阅,RSS 仅做更新提醒,不含付费内容.
### 沸点
-
+
| 推荐 | 热门 | 上班摸鱼 | 内推招聘 | 一图胜千言 | 今天学到了 | 每天一道算法题 | 开发工具推荐 | 树洞一下 |
| --------- | --- | ------------------- | ------------------- | ------------------- | ------------------- | ------------------- | ------------------- | ------------------- |
@@ -755,21 +767,29 @@ GitHub 官方也提供了一些 RSS:
-### 专栏
+### 用户专栏
-
+
### 收藏集
-
+
### 单个收藏夹
-
+
### 分享
-
+
+
+### 专栏
+
+
+
+### 资讯
+
+
## 开源中国
diff --git a/docs/reading.md b/docs/reading.md
index 780a1fb33dbc90..f54ce36f87bf5c 100644
--- a/docs/reading.md
+++ b/docs/reading.md
@@ -54,9 +54,20 @@ pageClass: routes
## Mobilism
-### eBook Releases
+### 电子书
-
+
+
+| 分类名 | 参数 |
+| -------- | ---------- |
+| 浪漫 | romance |
+| 科幻、幻想、恐怖 | scifi |
+| 普通小说、经典 | classics |
+| 杂志、报纸 | magazines |
+| 有声读物 | audioBooks |
+| 漫画 | comics |
+
+
## SoBooks
diff --git a/docs/social-media.md b/docs/social-media.md
index 7ad81f93a8c4b4..6b3c46ebc10b50 100644
--- a/docs/social-media.md
+++ b/docs/social-media.md
@@ -667,32 +667,36 @@ Instagram Stories 没有可靠的 guid,你的 RSS 阅读器可能将同一条
::: warning 注意
-由于 Twitter Api 限制,关于 Twitter 相关的 RSS 接口目前仅支持 7 天内推文检索
+由于 Twitter 的限制,部分路由目前仅支持 7 天内推文检索。
+
+部分路由的实现依赖 Twitter Developer API,需要特别配置以启用。\
+`/twitter/user` 及 `/twitter/keyword` 两个路由除 Developer API 外,尚有不需特别配置以启用的 Web API 实现。默认情况下,Developer API 优先级更高,只有当其未配置或出错时才会使用 Web API。然而,两个 API 在某些方面存在不同特性,如,`excludeReplies` 在 Developer API 中会将推文串([Thread](https://blog.twitter.com/official/en_us/topics/product/2017/nicethreads.html),回复自己推文的推文)视作回复一并排除,而在 Web API 中则不会。如有需要在 `/twitter/user` 中排除回复但包含推文串,请启用 `forceWebApi`。
:::
对于推文内容,在 `routeParams` 参数中以 query string 格式指定选项,可以控制额外的功能
-| 键 | 含义 | 接受的值 | 默认值 |
-| ---------------------------- | -------------------------------------- | -------------- | ------------------------------------ |
-| readable | 是否开启细节排版可读性优化 | 0/1/true/false | false |
-| authorNameBold | 是否加粗作者名字 | 0/1/true/false | false |
-| showAuthorInTitle | 是否在标题处显示作者 | 0/1/true/false | false(`/twitter/followings` 中为 true) |
-| showAuthorInDesc | 是否在正文处显示作者 | 0/1/true/false | false(`/twitter/followings` 中为 true) |
-| showQuotedAuthorAvatarInDesc | 是否在正文处显示被转推的推文的作者头像(若阅读器会提取正文图片,不建议开启) | 0/1/true/false | false |
-| showAuthorAvatarInDesc | 是否在正文处显示作者头像(若阅读器会提取正文图片,不建议开启) | 0/1/true/false | false |
-| showEmojiForRetweetAndReply | 显示 “🔁” 取代 “Rt”、“↩️” 取代 “Re” | 0/1/true/false | false |
-| showRetweetTextInTitle | 在标题处显示转推评论(置为 false 则在标题只显示被转推推文) | 0/1/true/false | true |
-| addLinkForPics | 为图片添加可点击的链接 | 0/1/true/false | false |
-| showTimestampInDescription | 在正文处显示推特的时间戳 | 0/1/true/false | false |
-| showQuotedInTitle | 在标题处显示被引用的推文 | 0/1/true/false | false |
-| widthOfPics | 推文配图宽(生效取决于阅读器) | 不指定 / 数字 | 不指定 |
-| heightOfPics | 推文配图高(生效取决于阅读器) | 不指定 / 数字 | 不指定 |
-| sizeOfAuthorAvatar | 作者头像大小 | 数字 | 48 |
-| sizeOfQuotedAuthorAvatar | 被转推推文作者头像大小 | 数字 | 24 |
-| excludeReplies | 排除回复,只在用户时间线有效 | 0/1/true/false | false |
-| includeRts | 包括转推,只在用户时间线有效 | 0/1/true/false | true |
-| count | 传递给 Twitter API 的 `count` 参数,只在用户时间线有效 | 不指定 / 数字 | 不指定 |
+| 键 | 含义 | 接受的值 | 默认值 |
+| ------------------------------ | ----------------------------------------------------------------------------- | ---------------------- | ----------------------------------------- |
+| `readable` | 是否开启细节排版可读性优化 | `0`/`1`/`true`/`false` | `false` |
+| `authorNameBold` | 是否加粗作者名字 | `0`/`1`/`true`/`false` | `false` |
+| `showAuthorInTitle` | 是否在标题处显示作者 | `0`/`1`/`true`/`false` | `false` (`/twitter/followings` 中为 `true`) |
+| `showAuthorInDesc` | 是否在正文处显示作者 | `0`/`1`/`true`/`false` | `false` (`/twitter/followings` 中为 `true`) |
+| `showQuotedAuthorAvatarInDesc` | 是否在正文处显示被转推的推文的作者头像(若阅读器会提取正文图片,不建议开启) | `0`/`1`/`true`/`false` | `false` |
+| `showAuthorAvatarInDesc` | 是否在正文处显示作者头像(若阅读器会提取正文图片,不建议开启) | `0`/`1`/`true`/`false` | `false` |
+| `showEmojiForRetweetAndReply` | 显示 “🔁” 取代 “Rt”、“↩️” 取代 “Re” | `0`/`1`/`true`/`false` | `false` |
+| `showRetweetTextInTitle` | 在标题处显示转推评论(置为 `false` 则在标题只显示被转推推文) | `0`/`1`/`true`/`false` | `true` |
+| `addLinkForPics` | 为图片添加可点击的链接 | `0`/`1`/`true`/`false` | `false` |
+| `showTimestampInDescription` | 在正文处显示推特的时间戳 | `0`/`1`/`true`/`false` | `false` |
+| `showQuotedInTitle` | 在标题处显示被引用的推文 | `0`/`1`/`true`/`false` | `false` |
+| `widthOfPics` | 推文配图宽(生效取决于阅读器) | 不指定 / 数字 | 不指定 |
+| `heightOfPics` | 推文配图高(生效取决于阅读器) | 不指定 / 数字 | 不指定 |
+| `sizeOfAuthorAvatar` | 作者头像大小 | 数字 | `48` |
+| `sizeOfQuotedAuthorAvatar` | 被转推推文作者头像大小 | 数字 | `24` |
+| `excludeReplies` | 排除回复,只在 `/twitter/user` 中有效 | `0`/`1`/`true`/`false` | `false` |
+| `includeRts` | 包括转推,只在 `/twitter/user` 中有效 | `0`/`1`/`true`/`false` | `true` |
+| `forceWebApi` | 强制使用 Web API,即使 Developer API 已配置,只在 `/twitter/user` 和 `/twitter/keyword` 中有效 | `0`/`1`/`true`/`false` | `false` |
+| `count` | 传递给 Twitter API 的 `count` 参数,只在 `/twitter/user` 中有效 | 不指定 / 数字 | 不指定 |
指定更多与默认值不同的参数选项可以改善 RSS 的可读性,如
@@ -704,11 +708,11 @@ Instagram Stories 没有可靠的 guid,你的 RSS 阅读器可能将同一条
### 用户时间线
-
+
### 用户媒体时间线
-
+
### 用户关注时间线
@@ -732,7 +736,7 @@ Instagram Stories 没有可靠的 guid,你的 RSS 阅读器可能将同一条
### 关键词
-
+
### Trends
@@ -844,7 +848,7 @@ YouTube 官方亦有提供频道 RSS,形如
+
| 键 | 含义 | 值 | 默认值 |
| -------- | ----------------------------------- | ---------------------- | ------- |
@@ -891,9 +895,9 @@ YouTube 官方亦有提供频道 RSS,形如
-| 一周口碑电影榜 | 一周口碑剧集榜 | 华语口碑剧集榜 |
-| ----------------- | -------------- | ---------------------- |
-| movie_weekly_best | tv_weekly_best | tv_chinese_best_weekly |
+| 一周口碑电影榜 | 华语口碑剧集榜 |
+| ----------------- | ---------------------- |
+| movie_weekly_best | tv_chinese_best_weekly |
@@ -1306,15 +1310,15 @@ rule
### 用户笔记和专辑
-
+
### 用户专辑
-
+
### 专辑
-
+
## 新榜
@@ -1389,7 +1393,7 @@ rule
### 问题
-
+
### 话题
diff --git a/docs/study.md b/docs/study.md
index 996acf738fbe67..ddafa83616c979 100644
--- a/docs/study.md
+++ b/docs/study.md
@@ -85,7 +85,7 @@ path="/ctfhub/upcoming/:limit?"
### 最新消息
-
+
## MarginNote
diff --git a/docs/traditional-media.md b/docs/traditional-media.md
index 9ad98eca09191a..fc34f0e6d26f3a 100644
--- a/docs/traditional-media.md
+++ b/docs/traditional-media.md
@@ -66,9 +66,12 @@ pageClass: routes
### 话题
-
+
+
采用了 `puppeteer` 规避 `Project Shield`,无全文抓取,建议自建。
+
+
## BBC
### BBC 英文
@@ -722,9 +725,9 @@ IT・科学 tech_science
无料全文,综合页 (新着・速報) 文章标题补充板块标签。
-| 新着・速報 | 社会 | 政治 | 経済 | スポーツ | 国際 | 科学・IT | 選挙・世論調査 | エンタメ・文化 | 囲碁・将棋 | ライフ | 地域 | 社説 |
-| ------- | -------- | -------- | ------- | ------ | ----- | ------- | -------- | ------- | --------- | ---- | ----- | --------- |
-| news | national | politics | economy | sports | world | science | election | culture | igoshougi | life | local | editorial |
+| 新着・速報 | 社会 | 政治 | 経済 | スポーツ | 国際 | 科学・IT | 選挙・世論調査 | エンタメ・文化 | 囲碁・将棋 | ライフ | 地域 | 社説 | 皇室 |
+| ------- | -------- | -------- | ------- | ------ | ----- | ------- | -------- | ------- | --------- | ---- | ----- | --------- | --------- |
+| news | national | politics | economy | sports | world | science | election | culture | igoshougi | life | local | editorial | koushitsu |
@@ -1221,7 +1224,7 @@ category 对应的关键词有
### 新闻
-
+
通过提取文章全文,以提供比官方源更佳的阅读体验。
diff --git a/docs/university.md b/docs/university.md
index a96043bc9ca008..c6e725c411ebd3 100644
--- a/docs/university.md
+++ b/docs/university.md
@@ -861,7 +861,7 @@ xskb1 对应
### 信息与通信工程学院
-
+
### 信息与软件工程学院
@@ -1308,7 +1308,7 @@ jsjxy.hbut.edu.cn 证书链不全,自建 RSSHub 可设置环境变量 NODE_TLS
### 学校通知
-
+
## 华东理工大学
@@ -1651,7 +1651,7 @@ jsjxy.hbut.edu.cn 证书链不全,自建 RSSHub 可设置环境变量 NODE_TLS
### 人才招聘网
-
+
| 信息发布 | 教研类岗位 | 管理岗位及其他 |
| ---- | ----- | ------- |
@@ -1707,7 +1707,7 @@ jsjxy.hbut.edu.cn 证书链不全,自建 RSSHub 可设置环境变量 NODE_TLS
### 教务处
-
+
| 通知公告 | 教学服务 | 教学建设 | 学生培养 | 教学资源 |
| ---- | ---- | ---- | ---- | ---- |
@@ -1717,7 +1717,7 @@ jsjxy.hbut.edu.cn 证书链不全,自建 RSSHub 可设置环境变量 NODE_TLS
### 计算机科学与技术学院
-
+
| 通知公告 | 热点新闻 | 学科科研 | 教学动态 | 本科生培养 | 研究生培养 | 学生工作 |
| ---- | ---- | ---- | ---- | ----- | ----- | ---- |
@@ -1739,7 +1739,7 @@ jsjxy.hbut.edu.cn 证书链不全,自建 RSSHub 可设置环境变量 NODE_TLS
### 教务处
-
+
| 教师通知 | 学生通知 | 新闻 | 学院动态 |
| ---- | ---- | -- | ---- |
@@ -1749,7 +1749,7 @@ jsjxy.hbut.edu.cn 证书链不全,自建 RSSHub 可设置环境变量 NODE_TLS
### 财务处
-
+
| 通知公告 | 办事流程 |
| ---- | ---- |
@@ -1759,7 +1759,7 @@ jsjxy.hbut.edu.cn 证书链不全,自建 RSSHub 可设置环境变量 NODE_TLS
### 研究生院
-
+
| 首页通知公告 | 首页新闻动态 | 最新通知 | 招生信息 | 培养信息 | 学术活动 |
| ----------- | ------ | ----- | ----- | ----- | ------- |
@@ -1769,7 +1769,7 @@ jsjxy.hbut.edu.cn 证书链不全,自建 RSSHub 可设置环境变量 NODE_TLS
### 电光学院
-
+
| 通知公告 | 新闻动态 |
| ---- | ---- |
@@ -1779,7 +1779,7 @@ jsjxy.hbut.edu.cn 证书链不全,自建 RSSHub 可设置环境变量 NODE_TLS
### 电光学院研学网
-
+
| 公示通知 | 学术文化 | 就业指导 |
| ---- | ---- | ---- |
@@ -1789,7 +1789,7 @@ jsjxy.hbut.edu.cn 证书链不全,自建 RSSHub 可设置环境变量 NODE_TLS
### 电光学院年级网站
-
+
`grade` 列表:
@@ -2347,6 +2347,18 @@ jsjxy.hbut.edu.cn 证书链不全,自建 RSSHub 可设置环境变量 NODE_TLS
+## 苏州科技大学
+
+### 教务处
+
+
+
+| 类型 | 教务动态 | 公告在线 | 选课通知 |
+| -- | ---- | ---- | ---- |
+| | jwdt | ggzx | xktz |
+
+
+
## 太原师范学院
diff --git a/lib/config.js b/lib/config.js
index c6f99851892bad..f20428a6ab3eb4 100644
--- a/lib/config.js
+++ b/lib/config.js
@@ -2,7 +2,6 @@ require('dotenv').config();
const randUserAgent = require('@/utils/rand-user-agent');
let envs = process.env;
let value;
-
const calculateValue = () => {
const bilibili_cookies = {};
const twitter_tokens = {};
diff --git a/lib/radar-rules.js b/lib/radar-rules.js
index 8075b44deb3935..08c3f1017b8f89 100644
--- a/lib/radar-rules.js
+++ b/lib/radar-rules.js
@@ -154,111 +154,6 @@ module.exports = {
},
],
},
- 'zhihu.com': {
- _name: '知乎',
- www: [
- {
- title: '收藏夹',
- docs: 'https://docs.rsshub.app/social-media.html#zhi-hu',
- source: '/collection/:id',
- target: '/zhihu/collection/:id',
- },
- {
- title: '用户动态',
- docs: 'https://docs.rsshub.app/social-media.html#zhi-hu',
- source: '/people/:id',
- target: '/zhihu/people/activities/:id',
- },
- {
- title: '用户回答',
- docs: 'https://docs.rsshub.app/social-media.html#zhi-hu',
- source: '/people/:id/answers',
- target: '/zhihu/people/answers/:id',
- },
- {
- title: '用户想法',
- docs: 'https://docs.rsshub.app/social-media.html#zhi-hu',
- source: '/people/:id/pins',
- target: '/zhihu/people/pins/:id',
- },
- {
- title: '用户文章',
- docs: 'https://docs.rsshub.app/social-media.html#zhi-hu',
- source: '/:usertype/:id/posts',
- target: '/zhihu/posts/:usertype/:id',
- },
-
- {
- title: '热榜',
- docs: 'https://docs.rsshub.app/social-media.html#zhi-hu',
- source: '/hot',
- target: '/zhihu/hotlist',
- },
- {
- title: '想法热榜',
- docs: 'https://docs.rsshub.app/social-media.html#zhi-hu',
- target: '/zhihu/pin/hotlist',
- },
- {
- title: '问题',
- docs: 'https://docs.rsshub.app/social-media.html#zhi-hu',
- source: '/question/:questionId',
- target: '/zhihu/question/:questionId',
- },
- {
- title: '话题',
- docs: 'https://docs.rsshub.app/social-media.html#zhi-hu',
- source: '/topic/:topicId/:type',
- target: '/zhihu/topic/:topicId',
- },
- {
- title: '新书',
- docs: 'https://docs.rsshub.app/social-media.html#zhi-hu',
- source: '/zhihu/bookstore/newest',
- target: '/zhihu/pin/hotlist',
- },
- {
- title: '想法-24 小时新闻汇总',
- docs: 'https://docs.rsshub.app/social-media.html#zhi-hu',
- source: '/pin/special/972884951192113152',
- target: '/zhihu/pin/daily',
- },
- {
- title: '书店-周刊',
- docs: 'https://docs.rsshub.app/social-media.html#zhi-hu',
- source: '/pub/weekly',
- target: '/zhihu/weekly',
- },
- {
- title: '专栏',
- docs: 'https://docs.rsshub.app/social-media.html#zhi-hu',
- source: '/column/:id',
- target: '/zhihu/zhuanlan/:id',
- },
- ],
- zhuanlan: [
- {
- title: '专栏',
- docs: 'https://docs.rsshub.app/social-media.html#zhi-hu',
- source: '/:id',
- target: '/zhihu/zhuanlan/:id',
- },
- ],
- daily: [
- {
- title: '日报',
- docs: 'https://docs.rsshub.app/social-media.html#zhi-hu',
- source: '',
- target: '/zhihu/daily',
- },
- {
- title: '日报',
- docs: 'https://docs.rsshub.app/social-media.html#zhi-hu',
- source: '/*tpath',
- target: '/zhihu/daily',
- },
- ],
- },
'smzdm.com': {
_name: '什么值得买',
www: [
@@ -312,47 +207,6 @@ module.exports = {
},
],
},
- 'juejin.cn': {
- _name: '掘金',
- '.': [
- {
- title: '标签',
- docs: 'https://docs.rsshub.app/programming.html#jue-jin-biao-qian',
- source: '/tag/:tag',
- target: '/juejin/tag/:tag',
- },
- {
- title: '小册',
- docs: 'https://docs.rsshub.app/programming.html#jue-jin-xiao-ce',
- source: '/books',
- target: '/juejin/books',
- },
- {
- title: '沸点',
- docs: 'https://docs.rsshub.app/programming.html#jue-jin-fei-dian',
- source: ['/pins/:type', '/pins/topic/:type'],
- target: (params) => (params.type !== 'recommended' ? '/juejin/pins/:type' : '/juejin/pins'),
- },
- {
- title: '专栏',
- docs: 'https://docs.rsshub.app/programming.html#jue-jin-zhuan-lan',
- source: ['/user/:id', '/user/:id/posts'],
- target: '/juejin/posts/:id',
- },
- {
- title: '收藏集',
- docs: 'https://docs.rsshub.app/programming.html#jue-jin-shou-cang-ji',
- source: ['/user/:id', '/user/:id/collections'],
- target: '/juejin/collections/:id',
- },
- {
- title: '单个收藏夹',
- docs: 'https://docs.rsshub.app/programming.html#jue-jin-dan-ge-shou-cang-jia',
- source: '/collection/:collectionId',
- target: '/juejin/collection/:collectionId',
- },
- ],
- },
'anime1.me': {
_name: 'Anime1',
'.': [
diff --git a/lib/router.js b/lib/router.js
index 70d418b84b3e22..c424bd6627fbe4 100644
--- a/lib/router.js
+++ b/lib/router.js
@@ -68,17 +68,18 @@ router.get('/ncm/artist/:id', lazyloadRouteHandler('./routes/ncm/artist'));
router.get('/ncm/djradio/:id', lazyloadRouteHandler('./routes/ncm/djradio'));
router.get('/ncm/user/playrecords/:uid/:type?', lazyloadRouteHandler('./routes/ncm/userplayrecords'));
-// 掘金
-router.get('/juejin/category/:category', lazyloadRouteHandler('./routes/juejin/category'));
-router.get('/juejin/tag/:tag', lazyloadRouteHandler('./routes/juejin/tag'));
-router.get('/juejin/trending/:category/:type', lazyloadRouteHandler('./routes/juejin/trending'));
-router.get('/juejin/books', lazyloadRouteHandler('./routes/juejin/books'));
-router.get('/juejin/pins/:type?', lazyloadRouteHandler('./routes/juejin/pins'));
-router.get('/juejin/posts/:id', lazyloadRouteHandler('./routes/juejin/posts'));
-router.get('/juejin/collections/:userId', lazyloadRouteHandler('./routes/juejin/favorites'));
-router.get('/juejin/collection/:collectionId', lazyloadRouteHandler('./routes/juejin/collection'));
-router.get('/juejin/shares/:userId', lazyloadRouteHandler('./routes/juejin/shares'));
-router.get('/juejin/column/:id', lazyloadRouteHandler('./routes/juejin/column'));
+// 掘金 migrated to v2
+// router.get('/juejin/category/:category', lazyloadRouteHandler('./routes/juejin/category'));
+// router.get('/juejin/tag/:tag', lazyloadRouteHandler('./routes/juejin/tag'));
+// router.get('/juejin/trending/:category/:type', lazyloadRouteHandler('./routes/juejin/trending'));
+// router.get('/juejin/books', lazyloadRouteHandler('./routes/juejin/books'));
+// router.get('/juejin/pins/:type?', lazyloadRouteHandler('./routes/juejin/pins'));
+// router.get('/juejin/posts/:id', lazyloadRouteHandler('./routes/juejin/posts'));
+// router.get('/juejin/news/:id', lazyloadRouteHandler('./routes/juejin/news'));
+// router.get('/juejin/collections/:userId', lazyloadRouteHandler('./routes/juejin/favorites'));
+// router.get('/juejin/collection/:collectionId', lazyloadRouteHandler('./routes/juejin/collection'));
+// router.get('/juejin/shares/:userId', lazyloadRouteHandler('./routes/juejin/shares'));
+// router.get('/juejin/column/:id', lazyloadRouteHandler('./routes/juejin/column'));
// 自如
router.get('/ziroom/room/:city/:iswhole/:room/:keyword', lazyloadRouteHandler('./routes/ziroom/room'));
@@ -89,24 +90,24 @@ router.get('/jianshu/trending/:timeframe', lazyloadRouteHandler('./routes/jiansh
router.get('/jianshu/collection/:id', lazyloadRouteHandler('./routes/jianshu/collection'));
router.get('/jianshu/user/:id', lazyloadRouteHandler('./routes/jianshu/user'));
-// 知乎
-router.get('/zhihu/collection/:id/:getAll?', lazyloadRouteHandler('./routes/zhihu/collection'));
-router.get('/zhihu/people/activities/:id', lazyloadRouteHandler('./routes/zhihu/activities'));
-router.get('/zhihu/people/answers/:id', lazyloadRouteHandler('./routes/zhihu/answers'));
-router.get('/zhihu/posts/:usertype/:id', lazyloadRouteHandler('./routes/zhihu/posts'));
-router.get('/zhihu/zhuanlan/:id', lazyloadRouteHandler('./routes/zhihu/zhuanlan'));
-router.get('/zhihu/daily', lazyloadRouteHandler('./routes/zhihu/daily'));
-router.get('/zhihu/daily/section/:sectionId', lazyloadRouteHandler('./routes/zhihu/daily_section'));
-router.get('/zhihu/hotlist', lazyloadRouteHandler('./routes/zhihu/hotlist'));
-router.get('/zhihu/pin/hotlist', lazyloadRouteHandler('./routes/zhihu/pin/hotlist'));
-router.get('/zhihu/question/:questionId', lazyloadRouteHandler('./routes/zhihu/question'));
-router.get('/zhihu/topic/:topicId', lazyloadRouteHandler('./routes/zhihu/topic'));
-router.get('/zhihu/people/pins/:id', lazyloadRouteHandler('./routes/zhihu/pin/people'));
-router.get('/zhihu/bookstore/newest', lazyloadRouteHandler('./routes/zhihu/bookstore/newest'));
-router.get('/zhihu/pin/daily', lazyloadRouteHandler('./routes/zhihu/pin/daily'));
-router.get('/zhihu/weekly', lazyloadRouteHandler('./routes/zhihu/weekly'));
-router.get('/zhihu/timeline', lazyloadRouteHandler('./routes/zhihu/timeline'));
-router.get('/zhihu/hot/:category?', lazyloadRouteHandler('./routes/zhihu/hot'));
+// 知乎 migrated to v2
+// router.get('/zhihu/collection/:id/:getAll?', lazyloadRouteHandler('./routes/zhihu/collection'));
+// router.get('/zhihu/people/activities/:id', lazyloadRouteHandler('./routes/zhihu/activities'));
+// router.get('/zhihu/people/answers/:id', lazyloadRouteHandler('./routes/zhihu/answers'));
+// router.get('/zhihu/posts/:usertype/:id', lazyloadRouteHandler('./routes/zhihu/posts'));
+// router.get('/zhihu/zhuanlan/:id', lazyloadRouteHandler('./routes/zhihu/zhuanlan'));
+// router.get('/zhihu/daily', lazyloadRouteHandler('./routes/zhihu/daily'));
+// router.get('/zhihu/daily/section/:sectionId', lazyloadRouteHandler('./routes/zhihu/daily_section'));
+// router.get('/zhihu/hotlist', lazyloadRouteHandler('./routes/zhihu/hotlist'));
+// router.get('/zhihu/pin/hotlist', lazyloadRouteHandler('./routes/zhihu/pin/hotlist'));
+// router.get('/zhihu/question/:questionId', lazyloadRouteHandler('./routes/zhihu/question'));
+// router.get('/zhihu/topic/:topicId', lazyloadRouteHandler('./routes/zhihu/topic'));
+// router.get('/zhihu/people/pins/:id', lazyloadRouteHandler('./routes/zhihu/pin/people'));
+// router.get('/zhihu/bookstore/newest', lazyloadRouteHandler('./routes/zhihu/bookstore/newest'));
+// router.get('/zhihu/pin/daily', lazyloadRouteHandler('./routes/zhihu/pin/daily'));
+// router.get('/zhihu/weekly', lazyloadRouteHandler('./routes/zhihu/weekly'));
+// router.get('/zhihu/timeline', lazyloadRouteHandler('./routes/zhihu/timeline'));
+// router.get('/zhihu/hot/:category?', lazyloadRouteHandler('./routes/zhihu/hot'));
// 妹子图
router.get('/mzitu/home/:type?', lazyloadRouteHandler('./routes/mzitu/home'));
@@ -263,16 +264,16 @@ router.get('/smzdm/baoliao/:uid', lazyloadRouteHandler('./routes/smzdm/baoliao')
router.get('/bjnews/:cat', lazyloadRouteHandler('./routes/bjnews/news'));
router.get('/bjnews/epaper/:cat', lazyloadRouteHandler('./routes/bjnews/epaper'));
-// 停水通知
-router.get('/tingshuitz/hangzhou', lazyloadRouteHandler('./routes/tingshuitz/hangzhou'));
-router.get('/tingshuitz/xiaoshan', lazyloadRouteHandler('./routes/tingshuitz/xiaoshan'));
-router.get('/tingshuitz/dalian', lazyloadRouteHandler('./routes/tingshuitz/dalian'));
-router.get('/tingshuitz/guangzhou', lazyloadRouteHandler('./routes/tingshuitz/guangzhou'));
-router.get('/tingshuitz/dongguan', lazyloadRouteHandler('./routes/tingshuitz/dongguan'));
-router.get('/tingshuitz/xian', lazyloadRouteHandler('./routes/tingshuitz/xian'));
-router.get('/tingshuitz/yangjiang', lazyloadRouteHandler('./routes/tingshuitz/yangjiang'));
-router.get('/tingshuitz/nanjing', lazyloadRouteHandler('./routes/tingshuitz/nanjing'));
-router.get('/tingshuitz/wuhan', lazyloadRouteHandler('./routes/tingshuitz/wuhan'));
+// 停水通知 migrated to v2
+// router.get('/tingshuitz/hangzhou', lazyloadRouteHandler('./routes/tingshuitz/hangzhou'));
+// router.get('/tingshuitz/xiaoshan', lazyloadRouteHandler('./routes/tingshuitz/xiaoshan'));
+// router.get('/tingshuitz/dalian', lazyloadRouteHandler('./routes/tingshuitz/dalian'));
+// router.get('/tingshuitz/guangzhou', lazyloadRouteHandler('./routes/tingshuitz/guangzhou'));
+// router.get('/tingshuitz/dongguan', lazyloadRouteHandler('./routes/tingshuitz/dongguan'));
+// router.get('/tingshuitz/xian', lazyloadRouteHandler('./routes/tingshuitz/xian'));
+// router.get('/tingshuitz/yangjiang', lazyloadRouteHandler('./routes/tingshuitz/yangjiang'));
+// router.get('/tingshuitz/nanjing', lazyloadRouteHandler('./routes/tingshuitz/nanjing'));
+// router.get('/tingshuitz/wuhan', lazyloadRouteHandler('./routes/tingshuitz/wuhan'));
// 米哈游
router.get('/mihoyo/bh3/:type', lazyloadRouteHandler('./routes/mihoyo/bh3'));
@@ -453,11 +454,10 @@ router.get('/hopper/:lowestOnly/:from/:to?', lazyloadRouteHandler('./routes/hopp
router.get('/mafengwo/note/:type', lazyloadRouteHandler('./routes/mafengwo/note'));
router.get('/mafengwo/ziyouxing/:code', lazyloadRouteHandler('./routes/mafengwo/ziyouxing'));
-// 中国地震局震情速递(与地震台网同步更新)
-router.get('/earthquake/:region?', lazyloadRouteHandler('./routes/earthquake'));
-
+// 中国地震局震情速递(与地震台网同步更新)migrated to v2
+// router.get('/earthquake/:region?', lazyloadRouteHandler('./routes/earthquake'));
// 中国地震台网
-router.get('/earthquake/ceic/:type', lazyloadRouteHandler('./routes/earthquake/ceic'));
+// router.get('/earthquake/ceic/:type', lazyloadRouteHandler('./routes/earthquake/ceic'));
// 小说
router.get('/novel/biquge/:id', lazyloadRouteHandler('./routes/novel/biquge'));
@@ -1043,7 +1043,7 @@ router.get('/gitea/blog', lazyloadRouteHandler('./routes/gitea/blog'));
router.get('/idownloadblog', lazyloadRouteHandler('./routes/idownloadblog/index'));
// 9to5
-router.get('/9to5/:subsite/:tag?', lazyloadRouteHandler('./routes/9to5/subsite'));
+// router.get('/9to5/:subsite/:tag?', lazyloadRouteHandler('./routes/9to5/subsite'));
// TesterHome
router.get('/testerhome/newest', lazyloadRouteHandler('./routes/testerhome/newest'));
@@ -1922,10 +1922,10 @@ router.get('/socialclub/events/:game?', lazyloadRouteHandler('./routes/socialclu
router.get('/ctfhub/upcoming/:limit?', lazyloadRouteHandler('./routes/ctfhub/upcoming'));
router.get('/ctfhub/search/:limit?/:form?/:class?/:title?', lazyloadRouteHandler('./routes/ctfhub/search'));
-// 阿里云
-router.get('/aliyun/database_month', lazyloadRouteHandler('./routes/aliyun/database_month'));
-router.get('/aliyun/notice/:type?', lazyloadRouteHandler('./routes/aliyun/notice'));
-router.get('/aliyun/developer/group/:type', lazyloadRouteHandler('./routes/aliyun/developer/group'));
+// 阿里云 migrated to v2
+// router.get('/aliyun/database_month', lazyloadRouteHandler('./routes/aliyun/database_month'));
+// router.get('/aliyun/notice/:type?', lazyloadRouteHandler('./routes/aliyun/notice'));
+// router.get('/aliyun/developer/group/:type', lazyloadRouteHandler('./routes/aliyun/developer/group'));
// 礼物说
router.get('/liwushuo/index', lazyloadRouteHandler('./routes/liwushuo/index.js'));
@@ -2180,12 +2180,12 @@ router.get('/pnas/:topic?', lazyloadRouteHandler('./routes/pnas/index'));
router.get('/cell/cell/:category', lazyloadRouteHandler('./routes/cell/cell/index'));
router.get('/cell/cover', lazyloadRouteHandler('./routes/cell/cover'));
-// nature + nature 子刊 [Sci Journal]
-router.get('/nature/research/:journal?', lazyloadRouteHandler('./routes/nature/research'));
-router.get('/nature/news-and-comment/:journal?', lazyloadRouteHandler('./routes/nature/news-and-comment'));
-router.get('/nature/cover', lazyloadRouteHandler('./routes/nature/cover'));
-router.get('/nature/news', lazyloadRouteHandler('./routes/nature/news'));
-router.get('/nature/highlight', lazyloadRouteHandler('./routes/nature/highlight'));
+// nature + nature 子刊 [Sci Journal] migrated to v2
+// router.get('/nature/research/:journal?', lazyloadRouteHandler('./routes/nature/research'));
+// router.get('/nature/news-and-comment/:journal?', lazyloadRouteHandler('./routes/nature/news-and-comment'));
+// router.get('/nature/cover', lazyloadRouteHandler('./routes/nature/cover'));
+// router.get('/nature/news', lazyloadRouteHandler('./routes/nature/news'));
+// router.get('/nature/highlight/:year?', lazyloadRouteHandler('./routes/nature/highlight'));
// science [Sci Journal]
router.get('/sciencemag/current/:journal?', lazyloadRouteHandler('./routes/sciencemag/current'));
@@ -2862,9 +2862,6 @@ router.get('/law/dh', lazyloadRouteHandler('./routes/law/dh'));
// 金诚同达律师事务所文章
router.get('/law/jctd', lazyloadRouteHandler('./routes/law/jctd'));
-// Mobilism
-router.get('/mobilism/release', lazyloadRouteHandler('./routes/mobilism/release'));
-
// 三星盖乐世社区
router.get('/samsungmembers/latest', lazyloadRouteHandler('./routes/samsungmembers/latest'));
@@ -3280,8 +3277,8 @@ router.get('/nobelprize/:caty?', lazyloadRouteHandler('./routes/nobelprize/index
// 中華民國國防部
router.get('/gov/taiwan/mnd', lazyloadRouteHandler('./routes/gov/taiwan/mnd'));
-// 読売新聞
-router.get('/yomiuri/:category', lazyloadRouteHandler('./routes/yomiuri/news'));
+// 読売新聞 to v2
+// router.get('/yomiuri/:category', lazyloadRouteHandler('./routes/yomiuri/news'));
// 巴哈姆特
// GNN新闻 migrated to v2
diff --git a/lib/routes/mobilism/release.js b/lib/routes/mobilism/release.js
deleted file mode 100644
index 84939058dbc296..00000000000000
--- a/lib/routes/mobilism/release.js
+++ /dev/null
@@ -1,42 +0,0 @@
-const url = require('url');
-const got = require('@/utils/got');
-const cheerio = require('cheerio');
-
-module.exports = async (ctx) => {
- const currentUrl = `https://forum.mobilism.org/viewforum.php?f=19`;
- const response = await got({
- method: 'get',
- url: currentUrl,
- });
- const $ = cheerio.load(response.data);
- const list = $('tbody')
- .eq(1)
- .find('tr')
- .map((_, item) => {
- item = $(item);
- const a = item.find('a');
- return {
- title: a.text(),
- link: url.resolve(`https://forum.mobilism.org`, a.attr('href')),
- };
- })
- .get();
-
- const items = await Promise.all(
- list.map((item) =>
- ctx.cache.tryGet(item.link, async () => {
- const res = await got({ method: 'get', url: item.link });
- const content = cheerio.load(res.data);
-
- item.description = content('div.content').html();
- return item;
- })
- )
- );
-
- ctx.state.data = {
- title: 'Mobilism - eBook Releases',
- link: currentUrl,
- item: items,
- };
-};
diff --git a/lib/routes/nature/cover.js b/lib/routes/nature/cover.js
deleted file mode 100644
index c3f6aed7c12c85..00000000000000
--- a/lib/routes/nature/cover.js
+++ /dev/null
@@ -1,90 +0,0 @@
-// The content is generateed by undocumentated API of nature journals
-// This router has **just** been tested in:
-// nature: Nature
-// nbt: Nature Biotechnology
-// neuro: Nature Neuroscience
-// ng: Nature Genetics
-// ni: Nature Immunology
-// nmeth: Nature Method
-// nchem: Nature Chemistry
-// nmat: Nature Materials
-// natmachintell: Nature Machine Intelligence
-// ncb: Nature Cell Biology
-// nplants: Nature Plants
-// natastron: Nature Astronomy
-// nphys Nature Physics
-
-const got = require('@/utils/got');
-
-module.exports = async (ctx) => {
- const baseURL = 'https://www.nature.com';
- const journalMap = new Map([
- ['nature', { id: '41586', name: 'Nature' }],
- ['nbt', { id: '41587', name: 'Nature Biotechnology' }],
- ['neuro', { id: '41593', name: 'Nature Neuroscience' }],
- ['ng', { id: '41588', name: 'Nature Genetics' }],
- ['ni', { id: '41590', name: 'Nature Immunology' }],
- ['nmeth', { id: '41592', name: 'Nature Methods' }],
- ['nchem', { id: '41590', name: 'Nature Chemistry' }],
- ['nmat', { id: '41563', name: 'Nature Material' }],
- ['natmachintell', { id: '42256', name: 'Nature Machine Intelligence' }],
- ['ncb', { id: '41556', name: 'Nature Cell Biology' }],
- ['nplants', { id: '41477', name: 'Nature Plants' }],
- ['natastron', { id: '41550', name: 'Nature Astronomy' }],
- ['nphys', { id: '41567', name: 'Nature Physics' }],
- ]);
- const journals = [...journalMap.keys()];
- const out = await Promise.all(
- journals.map(async (journal) => {
- // get the lastest volumn and issue id
- const pageURL = `${baseURL}/${journal}/current-issue`;
- const cookieData = await got
- .extend({
- prefixUrl: 'https://idp.nature.com/authorize',
- followRedirect: false,
- })
- .get(`?response_type=cookie&client_id=grover&redirect_uri=${encodeURI(pageURL)}`)
- .then((response) => response.headers['set-cookie'].join(' '));
- const issueURL = await got
- .extend({
- prefixUrl: pageURL,
- headers: {
- cookie: cookieData,
- },
- followRedirect: false,
- })
- .get('')
- .then((response) => response.headers.location);
- const capturingRegex = /volumes\/(?\d+)\/issues\/(?\d+)/;
- const { volumes, issues } = issueURL.match(capturingRegex).groups;
-
- const address = `${baseURL}${issueURL}`;
- const cache = await ctx.cache.get(address);
- if (cache) {
- return Promise.resolve(JSON.parse(cache));
- }
- const imgSize = 600;
-
- const id = journalMap.get(journal).id;
- const imageURL = `https://media.springernature.com/w${imgSize}/springer-static/cover-hires/journal/${id}/${volumes}/${issues}?as=webp`;
- const contents = ``;
-
- const single = {
- title: `${journalMap.get(journal).name} | Volume ${volumes} Issue ${issues}`,
- author: '@yech1990',
- description: contents,
- link: address,
- guid: address,
- pubDate: new Date().toUTCString(),
- };
- ctx.cache.set(address, JSON.stringify(single));
- return Promise.resolve(single);
- })
- );
- ctx.state.data = {
- title: 'Nature Covers Story',
- description: 'Find out the cover story of some Nature journals.',
- link: baseURL,
- item: out,
- };
-};
diff --git a/lib/routes/nature/highlight.js b/lib/routes/nature/highlight.js
deleted file mode 100644
index c751280449a78f..00000000000000
--- a/lib/routes/nature/highlight.js
+++ /dev/null
@@ -1,57 +0,0 @@
-const cheerio = require('cheerio');
-const got = require('@/utils/got');
-
-module.exports = async (ctx) => {
- const base = `https://www.nature.com`;
- const url = `${base}/nature/articles?type=research-highlight`;
-
- const res = await got.get(url);
- const $ = cheerio.load(res.data);
- const list = $('.border-bottom-1.pb20').get();
-
- const out = await Promise.all(
- list.slice(0, 2).map(async (item) => {
- const $ = cheerio.load(item);
- const title = $('h3 > a').text();
- const partial = $('h3 > a').attr('href');
- const address = `${base}${partial}`;
- const time = $('time').text();
- let author;
- if ($('.js-list-authors-3 li').length > 3) {
- author = $('.js-list-authors-3 li').slice(0, 1).text() + ' et al.';
- } else {
- author = $('.js-list-authors-3 li').text();
- }
- const cache = await ctx.cache.get(address);
- if (cache) {
- return Promise.resolve(JSON.parse(cache));
- }
- const res = await got.get(address);
- const capture = cheerio.load(res.data);
- let figure = capture('figure .figure--bleed').html();
- if (figure === null) {
- figure = '';
- }
- let contents = capture('.article-item--open .article-item__body').html();
- if (contents === null) {
- contents = '';
- }
- const single = {
- title,
- author,
- description: figure + contents,
- link: address,
- guid: address,
- pubDate: new Date(time).toUTCString(),
- };
- ctx.cache.set(address, JSON.stringify(single));
- return Promise.resolve(single);
- })
- );
- ctx.state.data = {
- title: `Nature | Research Highlight`,
- description: `Nature, a nature research journal`,
- link: url,
- item: out,
- };
-};
diff --git a/lib/routes/nature/news-and-comment.js b/lib/routes/nature/news-and-comment.js
deleted file mode 100644
index 3f0be383b995e4..00000000000000
--- a/lib/routes/nature/news-and-comment.js
+++ /dev/null
@@ -1,78 +0,0 @@
-// example usage: `/nature/news-and-comment/ng`
-// The journals from NPG are run by different group of people,
-// and the website of may not be consitent for all the journals
-//
-// This router has **just** been tested in:
-// nbt: Nature Biotechnology
-// neuro: Nature Neuroscience
-// ng: Nature Genetics
-// ni: Nature Immunology
-// nmeth: Nature Method
-// nchem: Nature Chemistry
-// nmat: Nature Materials
-// natmachintell: Nature Machine Intelligence
-
-const cheerio = require('cheerio');
-const got = require('@/utils/got');
-
-module.exports = async (ctx) => {
- const baseURL = `https://www.nature.com`;
-
- const journal = ctx.params.journal;
- const pageURL = `${baseURL}/${journal}/news-and-comment`;
-
- const pageResponse = await got.get(pageURL);
- const pageCapture = cheerio.load(pageResponse.data);
-
- const pageDescription = pageCapture('meta[name="description"]').attr('content') || `Nature, a nature research journal`;
- const pageTitleName = pageCapture('meta[name="WT.cg_n"]').attr('content') || `Nature (${journal})`;
- const pageTitleSub = pageCapture('meta[name="WT.cg_s"]').attr('content') || 'News & Comment';
-
- const list = pageCapture('.border-bottom-1.pb20').get();
-
- const items = list.map((el) => {
- const $ = cheerio.load(el);
- const title = $('h3 > a').text();
- const partial = $('h3 > a').attr('href');
- const address = `${baseURL}${partial}`;
- const brief = $('.hide-overflow.inline').text();
- const time = $('time').text();
- const author = $('.js-list-authors-3 li').text();
- const articleType = $('p > span').attr('data-class');
- const headerContents = `
-
-
- ${articleType}
- |
- ${author}
-
-
- `;
- let briefContents = '';
- if (brief !== '') {
- briefContents = `
-
- `;
- }
- const contents = headerContents + briefContents;
-
- return {
- title,
- author,
- description: contents,
- link: address,
- guid: address,
- pubDate: new Date(time).toUTCString(),
- };
- });
-
- ctx.state.data = {
- title: `${pageTitleName} | ${pageTitleSub}`,
- description: pageDescription,
- link: pageURL,
- item: items,
- };
-};
diff --git a/lib/routes/nature/news.js b/lib/routes/nature/news.js
deleted file mode 100644
index c1fb67ad3b0b31..00000000000000
--- a/lib/routes/nature/news.js
+++ /dev/null
@@ -1,51 +0,0 @@
-const cheerio = require('cheerio');
-const got = require('@/utils/got');
-
-module.exports = async (ctx) => {
- const base = `https://www.nature.com`;
- const url = `${base}/nature/articles?type=news`;
-
- const res = await got.get(url);
- const $ = cheerio.load(res.data);
- const list = $('.border-bottom-1.pb20').get();
-
- const out = await Promise.all(
- list.map(async (item) => {
- const $ = cheerio.load(item);
- const title = $('h3 > a').text();
- const partial = $('h3 > a').attr('href');
- const address = `${base}${partial}`;
- const time = $('time').text();
- let author;
- if ($('.js-list-authors-3 li').length > 3) {
- author = $('.js-list-authors-3 li').slice(0, 1).text() + ' et al.';
- } else {
- author = $('.js-list-authors-3 li').text();
- }
- const cache = await ctx.cache.get(address);
- if (cache) {
- return Promise.resolve(JSON.parse(cache));
- }
- const res = await got.get(address);
- const capture = cheerio.load(res.data);
- const contents = capture('.content .article__body').html();
-
- const single = {
- title,
- author,
- description: contents,
- link: address,
- guid: address,
- pubDate: new Date(time).toUTCString(),
- };
- ctx.cache.set(address, JSON.stringify(single));
- return Promise.resolve(single);
- })
- );
- ctx.state.data = {
- title: `Nature | Latest News`,
- description: `Nature, a nature research journal`,
- link: url,
- item: out,
- };
-};
diff --git a/lib/routes/nature/research.js b/lib/routes/nature/research.js
deleted file mode 100644
index 927d44fef1a262..00000000000000
--- a/lib/routes/nature/research.js
+++ /dev/null
@@ -1,184 +0,0 @@
-// example usage: `/nature/research/ng`
-// The journals from NPG are run by different group of people,
-// and the website of may not be consitent for all the journals
-//
-// This router has **just** been tested in:
-// nature: Nature
-// nbt: Nature Biotechnology
-// neuro: Nature Neuroscience
-// ng: Nature Genetics
-// ni: Nature Immunology
-// nmeth: Nature Method
-// nchem: Nature Chemistry
-// nmat: Nature Materials
-// natmachintell: Nature Machine Intelligence
-
-const cheerio = require('cheerio');
-const got = require('@/utils/got');
-
-module.exports = async (ctx) => {
- const baseURL = `https://www.nature.com`;
-
- const journal = ctx.params.journal || 'nature';
- const pageURL = `${baseURL}/${journal}/research`;
-
- const pageResponse = await got.get(pageURL);
- const pageCapture = cheerio.load(pageResponse.data);
-
- const pageDescription = pageCapture('meta[name="description"]').attr('content') || `Nature, a nature research journal`;
- const pageTitleName = pageCapture('meta[name="WT.cg_n"]').attr('content') || `Nature (${journal})`;
- const pageTitleSub = pageCapture('meta[name="WT.cg_s"]').attr('content') || 'Latest Research';
-
- const list = pageCapture('.border-bottom-1.pb20').get();
-
- const items = await Promise.all(
- list.map(async (el) => {
- const $ = cheerio.load(el);
- const title = $('h3 > a').text();
- const partial = $('h3 > a').attr('href');
- const address = `${baseURL}${partial}`;
- const brief = $('.hide-overflow.inline').text();
- const time = $('time').text();
- let author;
- if ($('.js-list-authors-3 li').length > 3) {
- author = $('.js-list-authors-3 li').slice(0, 1).text() + ' et al.';
- } else {
- author = $('.js-list-authors-3 li').text();
- }
- const cache = await ctx.cache.get(address);
- if (cache) {
- return Promise.resolve(JSON.parse(cache));
- }
- const itemResponse = await got.get(address);
- const itemCapture = cheerio.load(itemResponse.data);
-
- // Brief [obtain from entry of each item]
- let briefContents = '';
- if (brief !== '') {
- briefContents = `
-
- `;
- }
- // Abstract [obtain form address of each page]
- const abs = itemCapture('div#Abs1-content.c-article-section__content > p').html();
- let absContents = '';
- if (abs !== null) {
- absContents = `
-
- `;
- }
- // Info [obtain form address of each page]
- const subject = itemCapture('li.c-article-subject-list__subject > a')
- .map(function () {
- const link = $(this).attr('href');
- const name = $(this).text();
- if (name !== '') {
- return ``;
- } else {
- return '';
- }
- })
- .get()
- .join('');
- const subjectContents = subject !== '' ? `` : '';
- const citation = itemCapture('p.c-bibliographic-information__download-citation > a').attr('href');
- const citationContents = citation !== undefined ? `Download citation` : '';
- const doi = itemCapture('meta[name="DOI"]').attr('content');
- const doiContents = doi !== undefined ? `DOI: ${doi}` : '';
- const pdf = itemCapture('meta[name="citation_pdf_url"]').attr('content');
- const pdfContents = pdf !== undefined ? `Offical PDF` : '';
- const linkContents = '' + [citationContents, doiContents, pdfContents].filter((x) => x !== '').map((x) => ``) + '
';
- const infoContents = `
-
- `;
- // Add style
- const contentStyle = `
-
- `;
- const contents = briefContents + absContents + infoContents + contentStyle;
-
- const item = {
- title,
- author,
- description: contents,
- link: address,
- guid: address,
- pubDate: new Date(time).toUTCString(),
- };
- ctx.cache.set(address, JSON.stringify(item));
- return Promise.resolve(item);
- })
- );
- ctx.state.data = {
- title: `${pageTitleName} | ${pageTitleSub}`,
- description: pageDescription,
- link: pageURL,
- item: items,
- };
-};
diff --git a/lib/routes/tingshuitz/dalian.js b/lib/routes/tingshuitz/dalian.js
deleted file mode 100644
index 5339b68fff6482..00000000000000
--- a/lib/routes/tingshuitz/dalian.js
+++ /dev/null
@@ -1,34 +0,0 @@
-const got = require('@/utils/got');
-const cheerio = require('cheerio');
-
-module.exports = async (ctx) => {
- // const area = ctx.params.area;
- const url = 'http://www.swj.dl.gov.cn/html/tstz/';
- const response = await got({
- method: 'get',
- url,
- });
-
- const data = response.data;
- const $ = cheerio.load(data);
- const list = $('.listBox li');
-
- ctx.state.data = {
- title: $('title').text() || '停水通知 - 大连市水务局',
- link: 'http://www.swj.dl.gov.cn/html/tstz/',
- description: $('meta[name="description"]').attr('content') || $('title').text() || '停水通知 - 大连市水务局',
- item:
- list &&
- list
- .map((index, item) => {
- item = $(item);
- return {
- title: item.find('a').text(),
- description: `大连市停水通知:${item.find('a').text()}`,
- pubDate: new Date(item.find('span').text()).toUTCString(),
- link: item.find('a').attr('href'),
- };
- })
- .get(),
- };
-};
diff --git a/lib/routes/tingshuitz/wuhan.js b/lib/routes/tingshuitz/wuhan.js
deleted file mode 100644
index a49ca983991a17..00000000000000
--- a/lib/routes/tingshuitz/wuhan.js
+++ /dev/null
@@ -1,34 +0,0 @@
-const got = require('@/utils/got');
-const cheerio = require('cheerio');
-const url = require('url');
-
-module.exports = async (ctx) => {
- const baseUrl = 'https://www.whwater.com/gsfw/tstz/';
- const response = await got({
- method: 'get',
- url: baseUrl,
- });
-
- const data = response.data;
- const $ = cheerio.load(data);
- const list = $('.z4');
-
- ctx.state.data = {
- title: $('title').text() || '停水通知 - 武汉市水务集团有限公司',
- link: 'https://www.whwater.com/gsfw/tstz/',
- description: $('meta[name="description"]').attr('content') || $('title').text() || '停水通知 - 武汉市水务集团有限公司',
- item:
- list &&
- list
- .map((index, item) => {
- item = $(item);
- return {
- title: item.find('a').text(),
- description: `武汉市停水通知:${item.find('a').text()}`,
- pubDate: new Date(item.find('span').text()).toUTCString(),
- link: url.resolve(baseUrl, item.find('a').attr('href')),
- };
- })
- .get(),
- };
-};
diff --git a/lib/routes/twitter/api_fallback_common.js b/lib/routes/twitter/api_fallback_common.js
new file mode 100644
index 00000000000000..bc6bfa90eee4dd
--- /dev/null
+++ b/lib/routes/twitter/api_fallback_common.js
@@ -0,0 +1,17 @@
+const config = require('@/config').value;
+const logger = require('@/utils/logger');
+const utils = require('@/routes/twitter/utils');
+
+module.exports = async (ctx, devApiImpl, webApiImpl) => {
+ const { force_web_api } = utils.parseRouteParams(ctx.params.routeParams);
+
+ if (!force_web_api && config.twitter && config.twitter.consumer_key && config.twitter.consumer_secret) {
+ try {
+ await devApiImpl(ctx);
+ return;
+ } catch (e) {
+ logger.error(`Fallback to Twitter web API due to developer API error:\n${e.stack}`);
+ }
+ }
+ await webApiImpl(ctx);
+};
diff --git a/lib/routes/twitter/keyword.js b/lib/routes/twitter/keyword.js
index 54c470f4c1b124..5d318887756311 100644
--- a/lib/routes/twitter/keyword.js
+++ b/lib/routes/twitter/keyword.js
@@ -1,16 +1,5 @@
-const config = require('@/config').value;
-const webApiImpl = require('./web-api/search');
const devApiImpl = require('./developer-api/search');
-const logger = require('@/utils/logger');
+const webApiImpl = require('./web-api/search');
+const apiFallback = require('./api_fallback_common');
-module.exports = async (ctx) => {
- if (config.twitter && config.twitter.consumer_key && config.twitter.consumer_secret) {
- try {
- await devApiImpl(ctx);
- return;
- } catch (e) {
- logger.error(`Fallback to Twitter web API due to developer API error:\n${e.stack}`);
- }
- }
- await webApiImpl(ctx);
-};
+module.exports = (ctx) => apiFallback(ctx, devApiImpl, webApiImpl);
diff --git a/lib/routes/twitter/user.js b/lib/routes/twitter/user.js
index 60820a94e9fbfe..11a13d979e7f67 100644
--- a/lib/routes/twitter/user.js
+++ b/lib/routes/twitter/user.js
@@ -1,16 +1,5 @@
-const config = require('@/config').value;
const devApiImpl = require('./developer-api/user');
const webApiImpl = require('./web-api/user');
-const logger = require('@/utils/logger');
+const apiFallback = require('./api_fallback_common');
-module.exports = async (ctx) => {
- if (config.twitter && config.twitter.consumer_key && config.twitter.consumer_secret) {
- try {
- await devApiImpl(ctx);
- return;
- } catch (e) {
- logger.error(`Fallback to Twitter web API due to developer API error:\n${e.stack}`);
- }
- }
- await webApiImpl(ctx);
-};
+module.exports = (ctx) => apiFallback(ctx, devApiImpl, webApiImpl);
diff --git a/lib/routes/twitter/utils.js b/lib/routes/twitter/utils.js
index e406ec7edc7753..ed64f0940bf6fb 100644
--- a/lib/routes/twitter/utils.js
+++ b/lib/routes/twitter/utils.js
@@ -411,8 +411,8 @@ if (config.twitter.consumer_key && config.twitter.consumer_secret) {
}
const parseRouteParams = (routeParams) => {
- let exclude_replies, include_rts;
- let count = undefined;
+ let count, exclude_replies, include_rts;
+ let force_web_api = false;
if (routeParams === 'exclude_rts_replies' || routeParams === 'exclude_replies_rts') {
exclude_replies = true;
include_rts = false;
@@ -427,8 +427,9 @@ const parseRouteParams = (routeParams) => {
count = fallback(undefined, queryToInteger(parsed.get('count')), undefined);
exclude_replies = fallback(undefined, queryToBoolean(parsed.get('excludeReplies')), false);
include_rts = fallback(undefined, queryToBoolean(parsed.get('includeRts')), true);
+ force_web_api = fallback(undefined, queryToBoolean(parsed.get('forceWebApi')), false);
}
- return { count, exclude_replies, include_rts };
+ return { count, exclude_replies, include_rts, force_web_api };
};
module.exports = {
diff --git a/lib/routes/zhihu/question.js b/lib/routes/zhihu/question.js
deleted file mode 100644
index 3e46552e8e36e6..00000000000000
--- a/lib/routes/zhihu/question.js
+++ /dev/null
@@ -1,38 +0,0 @@
-const got = require('@/utils/got');
-const utils = require('./utils');
-
-module.exports = async (ctx) => {
- const { questionId } = ctx.params;
- const sort = 'created';
- const limit = 20;
- const include = `data[*].content.excerpt&limit=${limit}&offset=0`;
- const url = `https://www.zhihu.com/api/v4/questions/${questionId}/answers?include=${include}&sort_by=${sort}`;
- const response = await got({
- method: 'get',
- url,
- headers: {
- ...utils.header,
- Referer: `https://www.zhihu.com/question/${questionId}`,
- Authorization: 'oauth c3cef7c66a1843f8b3a9e6a1e3160e20', // hard-coded in js
- },
- });
- const listRes = response.data.data;
-
- ctx.state.data = {
- title: `知乎-${listRes[0].question.title}`,
- link: `https://www.zhihu.com/question/${questionId}`,
- item: listRes.map((item) => {
- const title = `${item.author.name}的回答:${item.excerpt}`;
- const description = `${item.author.name}的回答
${utils.ProcessImage(item.content)}`;
-
- return {
- title,
- description,
- author: item.author.name,
- pubDate: new Date(item.updated_time * 1000).toUTCString(),
- guid: item.id.toString(),
- link: `https://www.zhihu.com/question/${questionId}/answer/${item.id}`,
- };
- }),
- };
-};
diff --git a/lib/utils/parse-date.js b/lib/utils/parse-date.js
index f19cf1fbbd553e..2412432a98a79a 100644
--- a/lib/utils/parse-date.js
+++ b/lib/utils/parse-date.js
@@ -129,7 +129,7 @@ module.exports = {
// 将 `\d+年\d+月...\d+秒前` 分割成 `['\d+年', ..., '\d+秒前']`
- const matches = theDate.match(/(?:\D+)?\d+(?!:|-|\/)\D+/g);
+ const matches = theDate.match(/(?:\D+)?\d+(?!:|-|\/|(a|p)m)\D+/g);
if (matches) {
// 获得最后的时间单元,如 `\d+秒前`
@@ -187,7 +187,9 @@ module.exports = {
for (const w of words) {
const wordMatches = w.regExp.exec(theDate);
if (wordMatches) {
- return dayjs(`${w.startAt.format('YYYY-MM-DD')} ${wordMatches[1]}`).toDate();
+ // The default parser of dayjs() can parse '8:00 pm' but not '8:00pm'
+ // so we need to insert a space in between
+ return dayjs(`${w.startAt.format('YYYY-MM-DD')} ${/a|pm$/.test(wordMatches[1]) ? wordMatches[1].replace(/a|pm/, ' $&') : wordMatches[1]}`).toDate();
}
}
}
diff --git a/lib/v2/9to5/maintainer.js b/lib/v2/9to5/maintainer.js
new file mode 100644
index 00000000000000..724098c3c56e5a
--- /dev/null
+++ b/lib/v2/9to5/maintainer.js
@@ -0,0 +1,3 @@
+module.exports = {
+ '/9to5/:subsite/:tag?': ['HenryQW'],
+};
diff --git a/lib/v2/9to5/radar.js b/lib/v2/9to5/radar.js
new file mode 100644
index 00000000000000..431667891254df
--- /dev/null
+++ b/lib/v2/9to5/radar.js
@@ -0,0 +1,35 @@
+module.exports = {
+ '9to5toys.com': {
+ _name: '9to5',
+ '.': [
+ {
+ title: 'Toys 分站',
+ docs: 'https://docs.rsshub.app/new-media.html#_9to5',
+ source: ['/', '/guides/:tag'],
+ target: '/9to5/toys/:tag?',
+ },
+ ],
+ },
+ '9to5mac.com': {
+ _name: '9to5',
+ '.': [
+ {
+ title: 'Mac 分站',
+ docs: 'https://docs.rsshub.app/new-media.html#_9to5',
+ source: ['/', '/guides/:tag'],
+ target: '/9to5/mac/:tag?',
+ },
+ ],
+ },
+ '9to5google.com': {
+ _name: '9to5',
+ '.': [
+ {
+ title: 'Google 分站',
+ docs: 'https://docs.rsshub.app/new-media.html#_9to5',
+ source: ['/', '/guides/:tag'],
+ target: '/9to5/google/:tag?',
+ },
+ ],
+ },
+};
diff --git a/lib/v2/9to5/router.js b/lib/v2/9to5/router.js
new file mode 100644
index 00000000000000..cedd24b33c222b
--- /dev/null
+++ b/lib/v2/9to5/router.js
@@ -0,0 +1,3 @@
+module.exports = function (router) {
+ router.get('/:subsite/:tag?', require('./subsite'));
+};
diff --git a/lib/routes/9to5/subsite.js b/lib/v2/9to5/subsite.js
similarity index 60%
rename from lib/routes/9to5/subsite.js
rename to lib/v2/9to5/subsite.js
index 3764a2f1542209..15adbdcb0192b7 100644
--- a/lib/routes/9to5/subsite.js
+++ b/lib/v2/9to5/subsite.js
@@ -31,31 +31,34 @@ module.exports = async (ctx) => {
}
if (ctx.params.tag) {
- link = `${link}/guides/${ctx.params.tag}/feed`;
+ link = `${link}/guides/${ctx.params.tag}/feed/`;
title = `${ctx.params.tag} | ${title}`;
} else {
- link = `${link}/feed`;
+ link = `${link}/feed/`;
}
const feed = await parser.parseURL(link);
const items = await Promise.all(
- feed.items.splice(0, 10).map(async (item) => {
- const response = await got({
- method: 'get',
- url: item.link,
- });
- const description = utils.ProcessFeed(response.data);
+ feed.items.splice(0, ctx.query.limit ? parseInt(ctx.query.limit) : 10).map((item) =>
+ ctx.cache.tryGet(item.link, async () => {
+ const response = await got({
+ method: 'get',
+ url: item.link,
+ });
+ const description = utils.ProcessFeed(response.data);
- const single = {
- title: item.title,
- description,
- pubDate: item.pubDate,
- link: item.link,
- author: item['dc:creator'],
- };
- return Promise.resolve(single);
- })
+ const single = {
+ title: item.title,
+ description,
+ pubDate: item.pubDate,
+ link: item.link,
+ author: item['dc:creator'],
+ };
+
+ return single;
+ })
+ )
);
ctx.state.data = {
diff --git a/lib/routes/9to5/utils.js b/lib/v2/9to5/utils.js
similarity index 86%
rename from lib/routes/9to5/utils.js
rename to lib/v2/9to5/utils.js
index 444f2fbdadd2fd..94a48c143a4963 100644
--- a/lib/routes/9to5/utils.js
+++ b/lib/v2/9to5/utils.js
@@ -2,7 +2,7 @@ const cheerio = require('cheerio');
const ProcessFeed = (data) => {
const $ = cheerio.load(data);
- const content = $('div[itemprop="articleBody"]');
+ const content = $('div.post-body');
const cover = $('meta[property="og:image"]');
if (cover.length > 0) {
@@ -16,6 +16,9 @@ const ProcessFeed = (data) => {
$(e).remove();
});
+ // remove ad
+ content.find('div.ad-disclaimer-container').remove();
+
content.find('div').each((i, e) => {
if ($(e)[0].attribs.class) {
const classes = $(e)[0].attribs.class;
diff --git a/lib/routes/aliyun/database_month.js b/lib/v2/aliyun/database_month.js
similarity index 58%
rename from lib/routes/aliyun/database_month.js
rename to lib/v2/aliyun/database_month.js
index 817006e1040d45..a3a176478cdab1 100644
--- a/lib/routes/aliyun/database_month.js
+++ b/lib/v2/aliyun/database_month.js
@@ -10,7 +10,7 @@ module.exports = async (ctx) => {
.map((i, e) => {
const element = $(e);
const title = element.find('a').text().trim();
- const link = 'http://mysql.taobao.org' + element.find('a').attr('href').trim();
+ const link = `http://mysql.taobao.org${element.find('a').attr('href').trim()}/`;
return {
title,
description: '',
@@ -20,20 +20,15 @@ module.exports = async (ctx) => {
.get();
const result = await Promise.all(
- list.map(async (item) => {
+ list.map((item) => {
const link = item.link;
- const cache = await ctx.cache.get(link);
- if (cache) {
- return Promise.resolve(JSON.parse(cache));
- }
-
- const itemReponse = await got.get(link);
- const itemElement = cheerio.load(itemReponse.data);
- item.description = itemElement('.content').html();
-
- ctx.cache.set(link, JSON.stringify(item));
- return item;
+ return ctx.cache.tryGet(link, async () => {
+ const itemReponse = await got(link);
+ const itemElement = cheerio.load(itemReponse.data);
+ item.description = itemElement('.content').html();
+ return item;
+ });
})
);
diff --git a/lib/routes/aliyun/developer/group.js b/lib/v2/aliyun/developer/group.js
similarity index 72%
rename from lib/routes/aliyun/developer/group.js
rename to lib/v2/aliyun/developer/group.js
index 940cb23e39caf5..1027b3056d0c2b 100644
--- a/lib/routes/aliyun/developer/group.js
+++ b/lib/v2/aliyun/developer/group.js
@@ -1,5 +1,6 @@
const got = require('@/utils/got');
const cheerio = require('cheerio');
+const { parseDate } = require('@/utils/parse-date');
module.exports = async (ctx) => {
const type = ctx.params.type;
@@ -34,9 +35,13 @@ module.exports = async (ctx) => {
list
.map((index, item) => {
item = $(item);
+ const desc = item.find('.question-desc');
+ const description = item.find('.browse').text() + ' ' + desc.find('.answer').text();
return {
- title: item.find('p').first().text().trim(),
+ title: item.find('.question-title').text().trim() || item.find('a p').text().trim(),
link: item.find('a').attr('href'),
+ pubDate: parseDate(item.find('.time').text()),
+ description,
};
})
.get(),
diff --git a/lib/v2/aliyun/maintainer.js b/lib/v2/aliyun/maintainer.js
new file mode 100644
index 00000000000000..224bdb6fe7ee19
--- /dev/null
+++ b/lib/v2/aliyun/maintainer.js
@@ -0,0 +1,5 @@
+module.exports = {
+ '/database_month': ['junbaor'],
+ '/developer/group/:type': ['umm233'],
+ '/notice/:type?': ['muzea'],
+};
diff --git a/lib/routes/aliyun/notice.js b/lib/v2/aliyun/notice.js
similarity index 59%
rename from lib/routes/aliyun/notice.js
rename to lib/v2/aliyun/notice.js
index 47cb41787432ab..42b6490889e0de 100644
--- a/lib/routes/aliyun/notice.js
+++ b/lib/v2/aliyun/notice.js
@@ -1,9 +1,7 @@
const got = require('@/utils/got');
const cheerio = require('cheerio');
-const dayjs = require('dayjs');
-const customParseFormat = require('dayjs/plugin/customParseFormat');
-
-dayjs.extend(customParseFormat);
+const { parseDate } = require('@/utils/parse-date');
+const timezone = require('@/utils/timezone');
const typeMap = {
0: '9004748',
@@ -28,32 +26,26 @@ module.exports = async (ctx) => {
const title = element.find('a').text().trim();
const link = 'https://help.aliyun.com' + element.find('a').attr('href').trim();
const date = element.find('.y-right').text();
- const pubDate = dayjs(`${date} +0800`, 'YYYY-MM-DDHH:mm:ss ZZ');
+ const pubDate = timezone(parseDate(date), +8);
return {
title,
description: '',
link,
- pubDate: pubDate.toString(),
+ pubDate,
};
})
.get();
const result = await Promise.all(
- list.map(async (item) => {
- const link = item.link;
-
- const cache = await ctx.cache.get(link);
- if (cache) {
- return Promise.resolve(JSON.parse(cache));
- }
-
- const itemReponse = await got.get(link);
- const itemElement = cheerio.load(itemReponse.data);
- item.description = itemElement('#se-knowledge').html();
-
- ctx.cache.set(link, JSON.stringify(item));
- return item;
- })
+ list.map((item) =>
+ ctx.cache.tryGet(item.link, async () => {
+ const itemReponse = await got(item.link);
+ const itemElement = cheerio.load(itemReponse.data);
+ item.description = itemElement('#se-knowledge').html();
+
+ return item;
+ })
+ )
);
ctx.state.data = {
diff --git a/lib/v2/aliyun/radar.js b/lib/v2/aliyun/radar.js
new file mode 100644
index 00000000000000..9d2490ff03740f
--- /dev/null
+++ b/lib/v2/aliyun/radar.js
@@ -0,0 +1,32 @@
+module.exports = {
+ 'aliyun.com': {
+ _name: '阿里云',
+ developer: [
+ {
+ title: '开发者社区 - 主题',
+ docs: 'https://docs.rsshub.app/programming.html#a-li-yun',
+ source: ['/group/:type'],
+ target: '/aliyun/developer/group/:type',
+ },
+ ],
+ help: [
+ {
+ title: '公告',
+ docs: 'https://docs.rsshub.app/programming.html#a-li-yun',
+ source: ['/noticelist/:type', '/'],
+ target: (params) => `/aliyun/notice${params.type ? '/' + params.type.replace('.html', '') : ''}`,
+ },
+ ],
+ },
+ 'taobao.org': {
+ _name: '阿里云',
+ mysql: [
+ {
+ title: '数据库内核月报',
+ docs: 'https://docs.rsshub.app/programming.html#a-li-yun',
+ source: ['/monthly', '/'],
+ target: '/aliyun/database_month',
+ },
+ ],
+ },
+};
diff --git a/lib/v2/aliyun/router.js b/lib/v2/aliyun/router.js
new file mode 100644
index 00000000000000..0e812d1744a43a
--- /dev/null
+++ b/lib/v2/aliyun/router.js
@@ -0,0 +1,5 @@
+module.exports = (router) => {
+ router.get('/database_month', require('./database_month'));
+ router.get('/developer/group/:type', require('./developer/group'));
+ router.get('/notice/:type?', require('./notice'));
+};
diff --git a/lib/v2/cncf/index.js b/lib/v2/cncf/index.js
new file mode 100644
index 00000000000000..89597dc276d3a9
--- /dev/null
+++ b/lib/v2/cncf/index.js
@@ -0,0 +1,43 @@
+const got = require('@/utils/got');
+const cheerio = require('cheerio');
+const { parseDate } = require('@/utils/parse-date');
+
+const rootURL = 'https://www.cncf.io';
+
+module.exports = async (ctx) => {
+ const cate = ctx.params.cate ?? 'blog';
+ const url = `${rootURL}/${cate}/`;
+
+ const response = await got(url);
+ const $ = cheerio.load(response.data);
+ const title = $('h1.is-style-page-title').text();
+ const list = $('div.post-archive__item')
+ .map((_index, item) => ({
+ title: $(item).find('span.post-archive__title').text().trim(),
+ link: $(item).find('span.post-archive__title > a').attr('href'),
+ pubDate: parseDate($(item).find('span.post-archive__item_date').text().split('|')[0]),
+ }))
+ .get();
+
+ const items = await Promise.all(
+ list.map((item) =>
+ ctx.cache.tryGet(item.link, async () => {
+ const detailResponse = await got(item.link);
+ const content = cheerio.load(detailResponse.data);
+
+ content('div.post-author').remove();
+ content('div.social-share').remove();
+
+ item.description = content('article').html();
+
+ return item;
+ })
+ )
+ );
+
+ ctx.state.data = {
+ title: `CNCF - ${title}`,
+ link: url,
+ item: items,
+ };
+};
diff --git a/lib/v2/cncf/maintainer.js b/lib/v2/cncf/maintainer.js
new file mode 100644
index 00000000000000..b09f2060426ff6
--- /dev/null
+++ b/lib/v2/cncf/maintainer.js
@@ -0,0 +1,3 @@
+module.exports = {
+ '/:cate?': ['Fatpandac'],
+};
diff --git a/lib/v2/cncf/radar.js b/lib/v2/cncf/radar.js
new file mode 100644
index 00000000000000..d30db690010b1d
--- /dev/null
+++ b/lib/v2/cncf/radar.js
@@ -0,0 +1,31 @@
+module.exports = {
+ 'cncf.io': {
+ _name: 'CNCF',
+ '.': [
+ {
+ title: 'Blog',
+ docs: 'https://docs.rsshub.app/programming.html#cncf',
+ source: ['/blog'],
+ target: '/cncf/blog',
+ },
+ {
+ title: 'News',
+ docs: 'https://docs.rsshub.app/programming.html#cncf',
+ source: ['/news'],
+ target: '/cncf/news',
+ },
+ {
+ title: 'Announcements',
+ docs: 'https://docs.rsshub.app/programming.html#cncf',
+ source: ['/announcements'],
+ target: '/cncf/announcements',
+ },
+ {
+ title: 'Reports',
+ docs: 'https://docs.rsshub.app/programming.html#cncf',
+ source: ['/reports'],
+ target: '/cncf/reports',
+ },
+ ],
+ },
+};
diff --git a/lib/v2/cncf/reports.js b/lib/v2/cncf/reports.js
new file mode 100644
index 00000000000000..e4214417d264a7
--- /dev/null
+++ b/lib/v2/cncf/reports.js
@@ -0,0 +1,38 @@
+const got = require('@/utils/got');
+const cheerio = require('cheerio');
+const { parseDate } = require('@/utils/parse-date');
+
+const rootURL = 'https://www.cncf.io';
+
+module.exports = async (ctx) => {
+ const url = `${rootURL}/reports/`;
+
+ const response = await got(url);
+ const $ = cheerio.load(response.data);
+ const list = $('div.report-item')
+ .map((_index, item) => ({
+ title: $(item).find('a.report-item__link').attr('title'),
+ link: $(item).find('a.report-item__link').attr('href'),
+ }))
+ .get();
+
+ const items = await Promise.all(
+ list.map((item) =>
+ ctx.cache.tryGet(item.link, async () => {
+ const detailResponse = await got(item.link);
+ const content = cheerio.load(detailResponse.data);
+
+ item.parseDate = parseDate(content('p.is-style-spaced-uppercase').splice(':')[1]);
+ item.description = content('article > div.has-background').html();
+
+ return item;
+ })
+ )
+ );
+
+ ctx.state.data = {
+ title: `CNCF - Reports`,
+ link: url,
+ item: items,
+ };
+};
diff --git a/lib/v2/cncf/router.js b/lib/v2/cncf/router.js
new file mode 100644
index 00000000000000..9d730a432e70e2
--- /dev/null
+++ b/lib/v2/cncf/router.js
@@ -0,0 +1,4 @@
+module.exports = function (router) {
+ router.get('/reports', require('./reports'));
+ router.get('/:cate?', require('./index'));
+};
diff --git a/lib/routes/earthquake/ceic.js b/lib/v2/earthquake/ceic.js
similarity index 91%
rename from lib/routes/earthquake/ceic.js
rename to lib/v2/earthquake/ceic.js
index 1181c46d248509..2fc25177d44927 100644
--- a/lib/routes/earthquake/ceic.js
+++ b/lib/v2/earthquake/ceic.js
@@ -1,4 +1,6 @@
const got = require('@/utils/got');
+const { parseDate } = require('@/utils/parse-date');
+const timezone = require('@/utils/timezone');
module.exports = async (ctx) => {
let type = Number(ctx.params.type);
@@ -57,7 +59,7 @@ module.exports = async (ctx) => {
return {
title: `${entity.LOCATION_C}发生${entity.M}级地震`,
link: `${baseUrl}/${NEW_DID}.html`,
- pubDate: new Date(entity.O_TIME).toUTCString(),
+ pubDate: timezone(parseDate(entity.O_TIME, 'YYYY-MM-DD HH:mm:ss'), +8),
description: contentBuilder.join('
'),
guid: NEW_DID,
};
diff --git a/lib/routes/earthquake/index.js b/lib/v2/earthquake/index.js
similarity index 83%
rename from lib/routes/earthquake/index.js
rename to lib/v2/earthquake/index.js
index 974d48af8b1285..da27abe04ef97a 100644
--- a/lib/routes/earthquake/index.js
+++ b/lib/v2/earthquake/index.js
@@ -1,7 +1,9 @@
const got = require('@/utils/got');
+const { parseDate } = require('@/utils/parse-date');
+const timezone = require('@/utils/timezone');
module.exports = async (ctx) => {
- const region = ctx.params.region || 1;
+ const region = ctx.params.region ?? 1;
const api = 'https://www.cea.gov.cn/eportal/ui?struts.portlet.mode=view&struts.portlet.action=/portlet/expressEarthquake!queryExpressEarthquakeList.action&pageId=363409&moduleId=a852ba487b534470a84a30f00e7d6670';
const link = 'https://www.cea.gov.cn/cea/xwzx/zqsd/index.html';
const response = await got({
@@ -18,14 +20,14 @@ module.exports = async (ctx) => {
const out = data.map((item) => {
const { id, epicenter, latitudes, longitudes, depth } = item;
- const date = item.orig_time.slice(0, -2);
+ const date = item.orig_time;
const num = item.num_mag;
const description = `北京时间${date},${epicenter}(纬度${latitudes}度,经度${longitudes}度)发生${num}级地震,震源深度${depth}千米`;
return {
title: `${epicenter}发生${num}级地震`,
link: `https://www.cea.gov.cn/eportal/ui?struts.portlet.mode=view&struts.portlet.action=/portlet/expressEarthquake!toNewInfoView.action&pageId=366521&id=${id}`,
- pubDate: new Date(date).toUTCString(),
+ pubDate: timezone(parseDate(date, 'YYYY-MM-DD HH:mm:ss'), +8),
description,
};
});
diff --git a/lib/v2/earthquake/maintainer.js b/lib/v2/earthquake/maintainer.js
new file mode 100644
index 00000000000000..291da67fd91491
--- /dev/null
+++ b/lib/v2/earthquake/maintainer.js
@@ -0,0 +1,4 @@
+module.exports = {
+ '/ceic/:type?': ['SettingDust'],
+ '/:region?': ['LogicJake'],
+};
diff --git a/lib/v2/earthquake/radar.js b/lib/v2/earthquake/radar.js
new file mode 100644
index 00000000000000..08e0fa38b59378
--- /dev/null
+++ b/lib/v2/earthquake/radar.js
@@ -0,0 +1,24 @@
+module.exports = {
+ 'ac.cn': {
+ _name: '地震速报',
+ 'www.ceic': [
+ {
+ title: '中国地震台',
+ docs: 'https://docs-rsshub.pages.dev/forecast.html#di-zhen-su-bao',
+ source: ['/speedsearch', '/'],
+ target: '/earthquake/ceic',
+ },
+ ],
+ },
+ 'cea.gov.cn': {
+ _name: '地震速报',
+ www: [
+ {
+ title: '中国地震局',
+ docs: 'https://docs-rsshub.pages.dev/forecast.html#di-zhen-su-bao',
+ source: ['/cea/xwzx/zqsd/index.html', '/'],
+ target: '/earthquake',
+ },
+ ],
+ },
+};
diff --git a/lib/v2/earthquake/router.js b/lib/v2/earthquake/router.js
new file mode 100644
index 00000000000000..d10ad2bf9e06d6
--- /dev/null
+++ b/lib/v2/earthquake/router.js
@@ -0,0 +1,4 @@
+module.exports = (router) => {
+ router.get('/ceic/:type?', require('./ceic'));
+ router.get('/:region?', require('./index'));
+};
diff --git a/lib/v2/epicgames/index.js b/lib/v2/epicgames/index.js
index ced794d1b7a3e2..9aad773ce2ce79 100644
--- a/lib/v2/epicgames/index.js
+++ b/lib/v2/epicgames/index.js
@@ -3,7 +3,6 @@ const { parseDate } = require('@/utils/parse-date');
const { art } = require('@/utils/render');
const path = require('path');
const dayjs = require('dayjs');
-dayjs.extend(require('dayjs/plugin/isSameOrBefore'));
module.exports = async (ctx) => {
const locale = ctx.params.locale ?? 'en-US';
@@ -18,17 +17,25 @@ module.exports = async (ctx) => {
url: apiUrl,
});
+ const now = dayjs();
const items = response.data.data.Catalog.searchStore.elements
- .filter((item) => dayjs().subtract(7, 'days').isSameOrBefore(parseDate(item.effectiveDate)) && item.seller.name !== 'Epic Dev Test Account')
+ .filter(
+ (item) =>
+ item.promotions &&
+ item.promotions.promotionalOffers &&
+ item.promotions.promotionalOffers[0] &&
+ dayjs(item.promotions.promotionalOffers[0].promotionalOffers[0].startDate) <= now &&
+ dayjs(item.promotions.promotionalOffers[0].promotionalOffers[0].endDate) > now
+ )
.map((item) => ({
title: item.title,
author: item.seller.name,
- link: `${rootUrl}/en-US/p/${item.offerMappings.length > 0 ? item.offerMappings[0].pageSlug : item.urlSlug}`,
+ link: `${rootUrl}/${locale}/p/${item.catalogNs.mappings.length > 0 ? item.catalogNs.mappings[0].pageSlug : item.offerMappings.length > 0 ? item.offerMappings[0].pageSlug : item.urlSlug}`,
description: art(path.join(__dirname, 'templates/description.art'), {
description: item.description,
image: item.keyImages[0].url,
}),
- pubDate: parseDate(item.effectiveDate),
+ pubDate: parseDate(item.promotions.promotionalOffers[0].promotionalOffers[0].startDate),
}));
ctx.state.data = {
diff --git a/lib/v2/epicgames/maintainer.js b/lib/v2/epicgames/maintainer.js
index 3ca92881aac642..8dcb0fb08e681c 100644
--- a/lib/v2/epicgames/maintainer.js
+++ b/lib/v2/epicgames/maintainer.js
@@ -1,3 +1,3 @@
module.exports = {
- '/freegames/:locale?/:country?': ['DIYgod', 'NeverBehave', 'Zyx-A', 'junfengP', 'nczitzk'],
+ '/freegames/:locale?/:country?': ['DIYgod', 'NeverBehave', 'Zyx-A', 'junfengP', 'nczitzk', 'KotaHv'],
};
diff --git a/lib/v2/gov/hebei/czt.js b/lib/v2/gov/hebei/czt.js
new file mode 100644
index 00000000000000..d5603de56526c7
--- /dev/null
+++ b/lib/v2/gov/hebei/czt.js
@@ -0,0 +1,53 @@
+const got = require('@/utils/got');
+const cheerio = require('cheerio');
+const { parseDate } = require('@/utils/parse-date');
+
+module.exports = async (ctx) => {
+ const category = ctx.params.category ?? 'gzdt';
+
+ const rootUrl = 'http://czt.hebei.gov.cn';
+ const currentUrl = `${rootUrl}/xwdt/${category}`;
+
+ const response = await got({
+ method: 'get',
+ url: currentUrl,
+ });
+
+ const $ = cheerio.load(response.data);
+
+ let items = $('td li a[title]')
+ .toArray()
+ .map((item) => {
+ item = $(item);
+
+ return {
+ title: item.text(),
+ link: `${rootUrl}${/^\.\.\/\.\./.test(item.attr('href')) ? item.attr('href').replace(/^\.\.\/\.\./, '') : `/xwdt/${category}${item.attr('href').replace(/^\./, '')}`}`,
+ };
+ });
+
+ items = await Promise.all(
+ items.map((item) =>
+ ctx.cache.tryGet(item.link, async () => {
+ const detailResponse = await got({
+ method: 'get',
+ url: item.link,
+ });
+
+ const content = cheerio.load(detailResponse.data);
+
+ item.author = content('meta[name="ContentSource"]').attr('content');
+ item.pubDate = parseDate(content('meta[name="PubDate"]').attr('content'));
+ item.description = content('.TRS_Editor, .content').html();
+
+ return item;
+ })
+ )
+ );
+
+ ctx.state.data = {
+ title: $('title').text(),
+ link: currentUrl,
+ item: items,
+ };
+};
diff --git a/lib/v2/gov/maintainer.js b/lib/v2/gov/maintainer.js
index 00ff01a1d9bb59..7645d58fc4c78c 100644
--- a/lib/v2/gov/maintainer.js
+++ b/lib/v2/gov/maintainer.js
@@ -17,6 +17,7 @@ module.exports = {
'/anhui/kjt/:path?': ['nczitzk'],
'/beijing/kw/:channel': ['Fatpandac'],
+ '/hebei/czt/xwdt/:category?': ['nczitzk'],
'/shenzhen/hrss/szksy/:caty/:page?': ['zlasd'],
'/shenzhen/zzb/:caty/:page?': ['zlasd'],
'/shanghai/rsj/ksxm': ['Fatpandac'],
diff --git a/lib/v2/gov/radar.js b/lib/v2/gov/radar.js
index 116cf0090fd632..9bbbb47ff337bd 100644
--- a/lib/v2/gov/radar.js
+++ b/lib/v2/gov/radar.js
@@ -300,6 +300,41 @@ module.exports = {
},
],
},
+ 'hebei.gov.cn': {
+ _name: '河北省人民政府',
+ czt: [
+ {
+ title: '河北省财政厅 - 财政动态',
+ docs: 'https://docs.rsshub.app/government.html#he-bei-sheng-cai-zheng-ting-cai-zheng-dong-tai',
+ source: ['/xwdt/:category'],
+ target: (params) => {
+ if (params.category === 'gzdt') {
+ return '/gov/hebei/czt/xwdt/:category';
+ }
+ },
+ },
+ {
+ title: '河北省财政厅 - 综合新闻',
+ docs: 'https://docs.rsshub.app/government.html#he-bei-sheng-cai-zheng-ting-zong-he-xin-wen',
+ source: ['/xwdt/:category'],
+ target: (params) => {
+ if (params.category === 'zhxw') {
+ return '/gov/hebei/czt/xwdt/:category';
+ }
+ },
+ },
+ {
+ title: '河北省财政厅 - 通知公告',
+ docs: 'https://docs.rsshub.app/government.html#he-bei-sheng-cai-zheng-ting-tong-zhi-gong-gao',
+ source: ['/xwdt/:category'],
+ target: (params) => {
+ if (params.category === 'tzgg') {
+ return '/gov/hebei/czt/xwdt/:category';
+ }
+ },
+ },
+ ],
+ },
'homeaffairs.gov.au': {
_name: 'Department of Home Affairs',
immi: [
diff --git a/lib/v2/gov/router.js b/lib/v2/gov/router.js
index e285591b044d6a..853d6c35f80c15 100644
--- a/lib/v2/gov/router.js
+++ b/lib/v2/gov/router.js
@@ -18,6 +18,7 @@ module.exports = function (router) {
// province
router.get(/anhui\/kjt\/([\w\d/-]+)?/, require('./anhui/kjt'));
router.get('/beijing/kw/:channel', require('./beijing/kw/index'));
+ router.get('/hebei/czt/xwdt/:category?', require('./hebei/czt'));
router.get('/shenzhen/hrss/szksy/:caty/:page?', require('./shenzhen/hrss/szksy/index'));
router.get('/shenzhen/zzb/:caty/:page?', require('./shenzhen/zzb/index'));
router.get('/shanghai/rsj/ksxm', require('./shanghai/rsj/ksxm'));
diff --git a/lib/routes/juejin/books.js b/lib/v2/juejin/books.js
similarity index 89%
rename from lib/routes/juejin/books.js
rename to lib/v2/juejin/books.js
index a414643d7f291c..29120e0eb441ab 100644
--- a/lib/routes/juejin/books.js
+++ b/lib/v2/juejin/books.js
@@ -1,4 +1,5 @@
const got = require('@/utils/got');
+const { parseDate } = require('@/utils/parse-date');
module.exports = async (ctx) => {
const response = await got({
@@ -17,7 +18,7 @@ module.exports = async (ctx) => {
${base_info.summary}
价格: ${base_info.price / 100}元
`,
- pubDate: new Date(base_info.ctime * 1000).toUTCString(),
+ pubDate: parseDate(base_info.ctime * 1000),
guid: base_info.booklet_id,
}));
diff --git a/lib/routes/juejin/category.js b/lib/v2/juejin/category.js
similarity index 95%
rename from lib/routes/juejin/category.js
rename to lib/v2/juejin/category.js
index 3a5e46d69cb6af..f3d3b6be3a1aba 100644
--- a/lib/routes/juejin/category.js
+++ b/lib/v2/juejin/category.js
@@ -26,7 +26,7 @@ module.exports = async (ctx) => {
let originalData = [];
if (response.data.data) {
- originalData = response.data.data.slice(0, 5);
+ originalData = response.data.data;
}
const resultItems = await util.ProcessFeed(originalData, ctx.cache);
diff --git a/lib/routes/juejin/collection.js b/lib/v2/juejin/collection.js
similarity index 100%
rename from lib/routes/juejin/collection.js
rename to lib/v2/juejin/collection.js
diff --git a/lib/routes/juejin/column.js b/lib/v2/juejin/column.js
similarity index 100%
rename from lib/routes/juejin/column.js
rename to lib/v2/juejin/column.js
diff --git a/lib/routes/juejin/favorites.js b/lib/v2/juejin/favorites.js
similarity index 100%
rename from lib/routes/juejin/favorites.js
rename to lib/v2/juejin/favorites.js
diff --git a/lib/v2/juejin/maintainer.js b/lib/v2/juejin/maintainer.js
new file mode 100644
index 00000000000000..8121cf2f1faef0
--- /dev/null
+++ b/lib/v2/juejin/maintainer.js
@@ -0,0 +1,13 @@
+module.exports = {
+ '/books': ['xyqfer'],
+ '/category/:category': ['DIYgod'],
+ '/collection/:collectionId': ['isQ'],
+ '/collections/:userId': ['isQ'],
+ '/column/:id': ['xiangzy1'],
+ '/news/:id': ['CancerGary'],
+ '/pins/:type?': ['xyqfer', 'laampui'],
+ '/posts/:id': ['Maecenas'],
+ '/shares/:userId': ['qiwihui'],
+ '/tag/:tag': ['isheng5'],
+ '/trending/:category/:type': ['moaix'],
+};
diff --git a/lib/v2/juejin/news.js b/lib/v2/juejin/news.js
new file mode 100644
index 00000000000000..494660f536596a
--- /dev/null
+++ b/lib/v2/juejin/news.js
@@ -0,0 +1,25 @@
+const got = require('@/utils/got');
+const util = require('./utils');
+
+module.exports = async (ctx) => {
+ const { id } = ctx.params;
+
+ const response = await got({
+ method: 'post',
+ url: 'https://api.juejin.cn/content_api/v1/news/list_user',
+ json: {
+ user_id: id,
+ sort_type: 2,
+ },
+ });
+ const { data } = response.data;
+ const username = data[0] && data[0].author_user_info && data[0].author_user_info.user_name;
+ const resultItems = await util.ProcessFeed(data, ctx.cache);
+
+ ctx.state.data = {
+ title: `掘金资讯-${username}`,
+ link: `https://juejin.cn/user/${id}/news`,
+ description: `掘金资讯-${username}`,
+ item: resultItems,
+ };
+};
diff --git a/lib/routes/juejin/pins.js b/lib/v2/juejin/pins.js
similarity index 91%
rename from lib/routes/juejin/pins.js
rename to lib/v2/juejin/pins.js
index 06cf3911736dbd..7c149dd1b541fd 100644
--- a/lib/routes/juejin/pins.js
+++ b/lib/v2/juejin/pins.js
@@ -1,7 +1,8 @@
const got = require('@/utils/got');
+const { parseDate } = require('@/utils/parse-date');
module.exports = async (ctx) => {
- const type = ctx.params.type || 'recommend';
+ const type = ctx.params.type ?? 'recommend';
const title = {
recommend: '推荐',
hot: '热门',
@@ -35,7 +36,7 @@ module.exports = async (ctx) => {
const title = content;
const guid = item.msg_id;
const link = `https://juejin.cn/pin/${guid}`;
- const pubDate = new Date(parseInt(item.msg_Info.ctime) * 1000).toUTCString();
+ const pubDate = parseDate(item.msg_Info.ctime * 1000);
const author = item.author_user_info.user_name;
const imgs = item.msg_Info.pic_list.reduce((imgs, item) => {
imgs += `
diff --git a/lib/routes/juejin/posts.js b/lib/v2/juejin/posts.js
similarity index 100%
rename from lib/routes/juejin/posts.js
rename to lib/v2/juejin/posts.js
diff --git a/lib/v2/juejin/radar.js b/lib/v2/juejin/radar.js
new file mode 100644
index 00000000000000..c86595dc6e9d78
--- /dev/null
+++ b/lib/v2/juejin/radar.js
@@ -0,0 +1,61 @@
+module.exports = {
+ 'juejin.cn': {
+ _name: '掘金',
+ '.': [
+ {
+ title: '标签',
+ docs: 'https://docs.rsshub.app/programming.html#jue-jin-biao-qian',
+ source: '/tag/:tag',
+ target: '/juejin/tag/:tag',
+ },
+ {
+ title: '小册',
+ docs: 'https://docs.rsshub.app/programming.html#jue-jin-xiao-ce',
+ source: '/books',
+ target: '/juejin/books',
+ },
+ {
+ title: '沸点',
+ docs: 'https://docs.rsshub.app/programming.html#jue-jin-fei-dian',
+ source: ['/pins/:type', '/pins/topic/:type'],
+ target: (params) => (params.type !== 'recommended' ? '/juejin/pins/:type' : '/juejin/pins'),
+ },
+ {
+ title: '用户专栏',
+ docs: 'https://docs.rsshub.app/programming.html#jue-jin-zhuan-lan',
+ source: ['/user/:id', '/user/:id/posts'],
+ target: '/juejin/posts/:id',
+ },
+ {
+ title: '收藏集',
+ docs: 'https://docs.rsshub.app/programming.html#jue-jin-shou-cang-ji',
+ source: ['/user/:id', '/user/:id/collections'],
+ target: '/juejin/collections/:id',
+ },
+ {
+ title: '单个收藏夹',
+ docs: 'https://docs.rsshub.app/programming.html#jue-jin-dan-ge-shou-cang-jia',
+ source: '/collection/:collectionId',
+ target: '/juejin/collection/:collectionId',
+ },
+ {
+ title: '分享',
+ docs: 'https://docs.rsshub.app/programming.html#jue-jin',
+ source: ['/user/:userId', '/user/:userId/shares'],
+ target: '/juejin/shares/:userId',
+ },
+ {
+ title: '专栏',
+ docs: 'https://docs.rsshub.app/programming.html#jue-jin',
+ source: '/column/:id',
+ target: '/juejin/column/:id',
+ },
+ {
+ title: '资讯',
+ docs: 'https://docs.rsshub.app/programming.html#jue-jin',
+ source: ['/user/:id', '/user/:id/news'],
+ target: '/juejin/news/:userId',
+ },
+ ],
+ },
+};
diff --git a/lib/v2/juejin/router.js b/lib/v2/juejin/router.js
new file mode 100644
index 00000000000000..a3f4a2ea18ba4b
--- /dev/null
+++ b/lib/v2/juejin/router.js
@@ -0,0 +1,13 @@
+module.exports = (router) => {
+ router.get('/books', require('./books'));
+ router.get('/category/:category', require('./category'));
+ router.get('/collection/:collectionId', require('./collection'));
+ router.get('/collections/:userId', require('./favorites'));
+ router.get('/column/:id', require('./column'));
+ router.get('/news/:id', require('./news'));
+ router.get('/pins/:type?', require('./pins'));
+ router.get('/posts/:id', require('./posts'));
+ router.get('/shares/:userId', require('./shares'));
+ router.get('/tag/:tag', require('./tag'));
+ router.get('/trending/:category/:type', require('./trending'));
+};
diff --git a/lib/routes/juejin/shares.js b/lib/v2/juejin/shares.js
similarity index 100%
rename from lib/routes/juejin/shares.js
rename to lib/v2/juejin/shares.js
diff --git a/lib/routes/juejin/tag.js b/lib/v2/juejin/tag.js
similarity index 100%
rename from lib/routes/juejin/tag.js
rename to lib/v2/juejin/tag.js
diff --git a/lib/routes/juejin/trending.js b/lib/v2/juejin/trending.js
similarity index 100%
rename from lib/routes/juejin/trending.js
rename to lib/v2/juejin/trending.js
diff --git a/lib/routes/juejin/utils.js b/lib/v2/juejin/utils.js
similarity index 54%
rename from lib/routes/juejin/utils.js
rename to lib/v2/juejin/utils.js
index b62591cd089cf0..50a9faafe4394e 100644
--- a/lib/routes/juejin/utils.js
+++ b/lib/v2/juejin/utils.js
@@ -1,6 +1,6 @@
const got = require('@/utils/got');
+const cheerio = require('cheerio');
const { parseDate } = require('@/utils/parse-date');
-const timezone = require('@/utils/timezone');
const md = require('markdown-it')({
html: true,
});
@@ -15,21 +15,29 @@ async function load(id) {
});
let description;
if (response.data.data) {
- description = md.render(response.data.data.article_info.mark_content);
+ description = md.render(response.data.data.article_info.mark_content) || response.data.data.article_info.content;
}
return { description };
}
+const loadNews = async (link) => {
+ const response = await got(link);
+ const $ = cheerio.load(response.data);
+ $('h1.title, .main-box .message').remove();
+ return { description: $('.main-box .article').html() };
+};
+
const ProcessFeed = (list, caches) =>
Promise.all(
list.map(async (item) => {
- const pubDate = timezone(parseDate(parseInt(item.article_info.ctime) * 1000), +8);
- const link = `https://juejin.cn/post/${item.article_id}`;
+ const isArticle = !!item.article_info;
+ const pubDate = parseDate((isArticle ? item.article_info.ctime : item.content_info.ctime) * 1000);
+ const link = `https://juejin.cn${isArticle ? '/post/' + item.article_id : '/news/' + item.content_id}`;
// 列表上提取到的信息
const single = {
- title: item.article_info.title,
- description: (item.article_info.brief_content || '无描述').replace(/[\x00-\x08\x0b-\x0c\x0e-\x1f\x7f]/g, ''),
+ title: isArticle ? item.article_info.title : item.content_info.title,
+ description: ((isArticle ? item.article_info.brief_content : item.content_info.brief) || '无描述').replace(/[\x00-\x08\x0b-\x0c\x0e-\x1f\x7f]/g, ''),
pubDate,
author: item.author_user_info.user_name,
link,
@@ -37,7 +45,7 @@ const ProcessFeed = (list, caches) =>
// 使用tryGet方法从缓存获取内容。
// 当缓存中无法获取到链接内容的时候,则使用load方法加载文章内容。
- const other = await caches.tryGet(link, () => load(item.article_id));
+ const other = await caches.tryGet(link, () => (isArticle ? load(item.article_id) : loadNews(link)));
// 合并解析后的结果集作为该篇文章最终的输出结果
return { ...single, ...other };
})
diff --git a/lib/v2/lever/index.js b/lib/v2/lever/index.js
new file mode 100644
index 00000000000000..a8672a4ca5008d
--- /dev/null
+++ b/lib/v2/lever/index.js
@@ -0,0 +1,28 @@
+const got = require('@/utils/got');
+const { parseDate } = require('@/utils/parse-date');
+
+// Initiate a HTTP GET request
+module.exports = async (ctx) => {
+ const domain = ctx.params.domain;
+ const response = await got(`https://api.lever.co/v0/postings/${domain}?mode=json`);
+ const data = response.data;
+ ctx.state.data = {
+ // the source title
+ title: `${domain}'s Job feed in RSS`,
+ // the source link
+ link: `https://api.lever.co/v0/postings/${domain}`,
+ // the source description
+ description: `Auto Generated RSS Spec for ${domain}`,
+ // iterate through all leaf objects
+ item: data.map((item) => ({
+ // the article title
+ title: item.text,
+ // the article content
+ description: item.descriptionPlain,
+ // the article publish time
+ pubDate: parseDate(item.createdAt),
+ // the article link
+ link: item.hostedUrl,
+ })),
+ };
+};
diff --git a/lib/v2/lever/maintainer.js b/lib/v2/lever/maintainer.js
new file mode 100644
index 00000000000000..550490aac09ddb
--- /dev/null
+++ b/lib/v2/lever/maintainer.js
@@ -0,0 +1,3 @@
+module.exports = {
+ '/:domain': ['tsarlewey'],
+};
diff --git a/lib/v2/lever/radar.js b/lib/v2/lever/radar.js
new file mode 100644
index 00000000000000..ff990059c6ecd2
--- /dev/null
+++ b/lib/v2/lever/radar.js
@@ -0,0 +1,13 @@
+module.exports = {
+ 'lever.co': {
+ _name: 'Lever',
+ '.': [
+ {
+ title: 'Lever HRIS Job Boards Feed',
+ docs: 'https://docs.rsshub.app/other.html#lever',
+ source: ['/:domain'],
+ target: '/lever/:domain',
+ },
+ ],
+ },
+};
diff --git a/lib/v2/lever/router.js b/lib/v2/lever/router.js
new file mode 100644
index 00000000000000..6d4b80086d5113
--- /dev/null
+++ b/lib/v2/lever/router.js
@@ -0,0 +1,3 @@
+module.exports = function (router) {
+ router.get('/:domain', require('./index.js'));
+};
diff --git a/lib/v2/lfsyd/templates/video.art b/lib/v2/lfsyd/templates/video.art
new file mode 100644
index 00000000000000..5aab94d67917f3
--- /dev/null
+++ b/lib/v2/lfsyd/templates/video.art
@@ -0,0 +1 @@
+{{ url }}
\ No newline at end of file
diff --git a/lib/v2/lfsyd/utils.js b/lib/v2/lfsyd/utils.js
index c65df4e159318c..eab0dc21574456 100644
--- a/lib/v2/lfsyd/utils.js
+++ b/lib/v2/lfsyd/utils.js
@@ -74,6 +74,16 @@ const cleanHtml = (htmlString) => {
$(e).find('.audio-area.hidden').attr('class', 'audio-area');
});
+ $('.yingdi-video iframe').each((i, e) => {
+ const bvid = $(e)
+ .attr('src')
+ .match(/bvid=(.*?)&/)[1];
+ if (bvid) {
+ const url = `https://www.bilibili.com/video/${bvid}`;
+ $(e).after(art(path.join(__dirname, 'templates/video.art'), { url }));
+ }
+ });
+
// 用户头像
$('.yingdi-card.user').each((i, e) => {
$(e).prev('p').remove();
diff --git a/lib/v2/mobilism/forums.js b/lib/v2/mobilism/forums.js
new file mode 100644
index 00000000000000..a7e7ed4508414f
--- /dev/null
+++ b/lib/v2/mobilism/forums.js
@@ -0,0 +1,75 @@
+const got = require('@/utils/got');
+const cheerio = require('cheerio');
+const { toTitleCase } = require('@/utils/common-utils');
+const { parseDate, parseRelativeDate } = require('@/utils/parse-date');
+const rootUrl = `https://forum.mobilism.org/viewforum.php?f=`;
+const categeoryMap = {
+ books: {
+ romance: 1292,
+ scifi: 1293,
+ classics: 121,
+ magazines: 123,
+ audioBooks: 124,
+ comics: 311,
+ },
+ android: {
+ apps: 399,
+ games: 408,
+ },
+ iphone: {
+ apps: 316,
+ games: 320,
+ },
+ ipad: {
+ apps: 951,
+ games: 988,
+ },
+};
+module.exports = async (ctx) => {
+ const { category, type, fulltext } = ctx.params;
+ const currentUrl = rootUrl + categeoryMap[category][type];
+ const response = await got(currentUrl);
+ const $ = cheerio.load(cheerio.load(response.data)('tbody')[1]);
+ const lists = $('tbody > tr');
+ const list = lists
+ .map((index, item) => {
+ item = $(item);
+ const title = item.find('td').first().find('a[title]').text();
+ const link = new URL(item.find('td').first().find('a[title]').attr('href'), 'https://forum.mobilism.org');
+ const author = item.find('td').first().find('a.username-coloured').text();
+ const pubDate = item.find('td').first().find('small').text();
+ link.searchParams.delete('sid');
+ return {
+ title,
+ link: link.toString(),
+ author,
+ pubDate: /ago|day/.test(pubDate) ? parseRelativeDate(pubDate) : parseDate(pubDate, 'MMM D, YYYY, h:mm a'),
+ };
+ })
+ .get()
+ .sort((a, b) => b.pubDate - a.pubDate)
+ .slice(0, ctx.query.limit ? parseInt(ctx.query.limit) : 35);
+ // server will return 520 if concurrency > 37 when fulltext is used
+ let items;
+ if (fulltext === 'y') {
+ items = await Promise.all(
+ list.map((item) =>
+ ctx.cache.tryGet(item.link, async () => {
+ const detailResponse = await got(item.link);
+ const content = cheerio.load(detailResponse.data);
+ item.description = content('div.content').html();
+ return item;
+ })
+ )
+ );
+ } else {
+ items = list;
+ }
+
+ ctx.state.data = {
+ title: `Mobilism Forums ${toTitleCase(category)} ${toTitleCase(type)} Release`,
+ link: currentUrl,
+ description: `Mobilism Forums ${toTitleCase(category)} ${toTitleCase(type)} RSS`,
+ item: items,
+ };
+};
diff --git a/lib/v2/mobilism/maintainer.js b/lib/v2/mobilism/maintainer.js
new file mode 100644
index 00000000000000..23853f51f2c86c
--- /dev/null
+++ b/lib/v2/mobilism/maintainer.js
@@ -0,0 +1,4 @@
+module.exports = {
+ '/forums/:category/:type/:fulltext?': ['nitezs'],
+ '/portal/:type/:fulltext?': ['nitezs'],
+};
diff --git a/lib/v2/mobilism/portal.js b/lib/v2/mobilism/portal.js
new file mode 100644
index 00000000000000..f61cd83a3c7b45
--- /dev/null
+++ b/lib/v2/mobilism/portal.js
@@ -0,0 +1,54 @@
+const got = require('@/utils/got');
+const cheerio = require('cheerio');
+const { toTitleCase } = require('@/utils/common-utils');
+const { parseDate, parseRelativeDate } = require('@/utils/parse-date');
+
+const get = (data) => {
+ const $ = cheerio.load(data);
+ const posts = $('div.span9 > section');
+ const items = posts
+ .map((index, item) => {
+ item = $(item);
+ const link = new URL(item.find('div.well > a').attr('href'), 'https://forum.mobilism.org');
+ const pubDate = item.find('div.well > span.muted > em').text().replace(item.find('div.well > span.muted > em > strong').text(), '').replace(' at ', '').split(' in ')[0];
+ link.searchParams.delete('sid');
+ return {
+ title: item.find('div.page-header > h3').text(),
+ link: link.toString(),
+ author: item.find('div.well > span.muted > em > strong').text().replace('Posted by: ', ''),
+ description: item.find('div.well > div.postbody').text(),
+ pubDate: /ago|day/.test(pubDate) ? parseRelativeDate(pubDate) : parseDate(pubDate, 'MMM D, YYYY, h:mm a'),
+ };
+ })
+ .get();
+ return items;
+};
+
+module.exports = async (ctx) => {
+ const { type, fulltext } = ctx.params;
+ const url = `https://forum.mobilism.org/portal.php?mode=articles&block=${type}&sk=t&sd=d&start=0`;
+ const response = await got(url);
+ const list = get(response.data);
+ let items;
+ if (fulltext === 'y') {
+ items = await Promise.all(
+ list.map((item) =>
+ ctx.cache.tryGet(item.link, async () => {
+ const detailResponse = await got(item.link);
+ const content = cheerio.load(detailResponse.data);
+ item.description = content('div.content').html();
+ return item;
+ })
+ )
+ );
+ } else {
+ items = list;
+ }
+
+ ctx.state.data = {
+ title: `Mobilism Portal ${toTitleCase(type)} Release`,
+ link: url,
+ description: `Mobilism Portal ${toTitleCase(type)} RSS`,
+ item: items,
+ };
+};
diff --git a/lib/v2/mobilism/radar.js b/lib/v2/mobilism/radar.js
new file mode 100644
index 00000000000000..1ac08d61997175
--- /dev/null
+++ b/lib/v2/mobilism/radar.js
@@ -0,0 +1,23 @@
+module.exports = {
+ 'mobilism.org': {
+ _name: 'Mobilism',
+ '.': [
+ {
+ title: '论坛',
+ docs: 'https://docs.rsshub.app/bbs.html#mobilism',
+ source: '/',
+ },
+ {
+ title: '门户',
+ docs: 'https://docs.rsshub.app/bbs.html#mobilism',
+ source: '/portal.php',
+ target: (_params, url) => `/mobilism/portal/${new URL(url).searchParams.get('block')}`,
+ },
+ {
+ title: '电子书',
+ docs: 'https://docs.rsshub.app/reading.html#mobilism',
+ source: '/',
+ },
+ ],
+ },
+};
diff --git a/lib/v2/mobilism/router.js b/lib/v2/mobilism/router.js
new file mode 100644
index 00000000000000..0d4647855e2430
--- /dev/null
+++ b/lib/v2/mobilism/router.js
@@ -0,0 +1,4 @@
+module.exports = function (router) {
+ router.get('/forums/:category/:type/:fulltext?', require('./forums'));
+ router.get('/portal/:type/:fulltext?', require('./portal'));
+};
diff --git a/lib/v2/nature/cover.js b/lib/v2/nature/cover.js
new file mode 100644
index 00000000000000..c08bb161d467c5
--- /dev/null
+++ b/lib/v2/nature/cover.js
@@ -0,0 +1,77 @@
+// The content is generateed by undocumentated API of nature journals
+// This router has **just** been tested in:
+// nature: Nature
+// nbt: Nature Biotechnology
+// neuro: Nature Neuroscience
+// ng: Nature Genetics
+// ni: Nature Immunology
+// nmeth: Nature Method
+// nchem: Nature Chemistry
+// nmat: Nature Materials
+// natmachintell: Nature Machine Intelligence
+// ncb: Nature Cell Biology
+// nplants: Nature Plants
+// natastron: Nature Astronomy
+// nphys Nature Physics
+
+const got = require('@/utils/got');
+const cheerio = require('cheerio');
+const { parseDate } = require('@/utils/parse-date');
+const { baseUrl, journalMap } = require('./utils');
+
+module.exports = async (ctx) => {
+ const journals = journalMap.items;
+ const out = await Promise.all(
+ journals
+ .filter((j) => j.id)
+ .map(async (journal) => {
+ // get the lastest volumn and issue id
+ const pageURL = `${baseUrl}/${journal.title}/current-issue`;
+ const cookieData = await got
+ .extend({
+ prefixUrl: 'https://idp.nature.com/authorize',
+ followRedirect: false,
+ })
+ .get(`?response_type=cookie&client_id=grover&redirect_uri=${encodeURI(pageURL)}`)
+ .then((response) => response.headers['set-cookie'].join(' '));
+ const issueURL = await got
+ .extend({
+ prefixUrl: pageURL,
+ headers: {
+ cookie: cookieData,
+ },
+ followRedirect: false,
+ })
+ .get('')
+ .then((response) => response.headers.location);
+ const capturingRegex = /volumes\/(?\d+)\/issues\/(?\d+)/;
+ const { volumes, issues } = issueURL.match(capturingRegex).groups;
+
+ const address = `${baseUrl}${issueURL}`;
+ return ctx.cache.tryGet(address, async () => {
+ const id = journal.id;
+ const imageURL = `https://media.springernature.com/full/springer-static/cover-hires/journal/${id}/${volumes}/${issues}?as=webp`;
+ const contents = ``;
+
+ const response = await got(address);
+ const $ = cheerio.load(response.data);
+ const date = $('title').text().split(',')[1].trim();
+ const issueDescription = $('div[data-test=issue-description]').html() ?? '';
+
+ const single = {
+ title: `${journal.name} | Volume ${volumes} Issue ${issues}`,
+ description: contents + issueDescription,
+ link: address,
+ pubDate: parseDate(date, 'MMMM YYYY'),
+ };
+ return single;
+ });
+ })
+ );
+ ctx.state.data = {
+ title: 'Nature Covers Story',
+ description: 'Find out the cover story of some Nature journals.',
+ link: baseUrl,
+ item: out,
+ };
+};
diff --git a/lib/v2/nature/highlight.js b/lib/v2/nature/highlight.js
new file mode 100644
index 00000000000000..f8a4bf0cd652ca
--- /dev/null
+++ b/lib/v2/nature/highlight.js
@@ -0,0 +1,22 @@
+const cheerio = require('cheerio');
+const got = require('@/utils/got');
+const { baseUrl, getArticleList, getArticle } = require('./utils');
+
+module.exports = async (ctx) => {
+ const { journal = 'nature' } = ctx.params;
+ const url = `${baseUrl}/${journal}/articles?type=research-highlight`;
+
+ const res = await got(url);
+ const $ = cheerio.load(res.data);
+
+ let items = getArticleList($);
+
+ items = await Promise.all(items.map((item) => getArticle(item, ctx)));
+
+ ctx.state.data = {
+ title: $('title').text().trim(),
+ description: $('meta[name=description]').attr('content'),
+ link: url,
+ item: items,
+ };
+};
diff --git a/lib/v2/nature/maintainer.js b/lib/v2/nature/maintainer.js
new file mode 100644
index 00000000000000..cd003d9d010b1b
--- /dev/null
+++ b/lib/v2/nature/maintainer.js
@@ -0,0 +1,8 @@
+module.exports = {
+ '/cover': ['yech1990'],
+ '/highlight/:journal?/:year?': ['yech1990', 'TonyRL'],
+ '/news': ['yech1990', 'TonyRL'],
+ '/news-and-comment/:journal?': ['yech1990', 'TonyRL'],
+ '/research/:journal?': ['yech1990', 'TonyRL'],
+ '/siteindex': ['TonyRL'],
+};
diff --git a/lib/v2/nature/news-and-comment.js b/lib/v2/nature/news-and-comment.js
new file mode 100644
index 00000000000000..9b0ebd046c3e6b
--- /dev/null
+++ b/lib/v2/nature/news-and-comment.js
@@ -0,0 +1,37 @@
+// example usage: `/nature/news-and-comment/ng`
+// The journals from NPG are run by different group of people,
+// and the website of may not be consitent for all the journals
+//
+// This router has **just** been tested in:
+// nbt: Nature Biotechnology
+// neuro: Nature Neuroscience
+// ng: Nature Genetics
+// ni: Nature Immunology
+// nmeth: Nature Method
+// nchem: Nature Chemistry
+// nmat: Nature Materials
+// natmachintell: Nature Machine Intelligence
+
+const cheerio = require('cheerio');
+const got = require('@/utils/got');
+const { baseUrl, getArticleList, getArticle } = require('./utils');
+
+module.exports = async (ctx) => {
+ const journal = ctx.params.journal;
+ const pageURL = `${baseUrl}/${journal}/news-and-comment`;
+
+ const pageResponse = await got(pageURL);
+ const pageCapture = cheerio.load(pageResponse.data);
+ const pageDescription = pageCapture('meta[name=description]').attr('content') || 'Nature, a nature research journal';
+
+ let items = getArticleList(pageCapture);
+
+ items = await Promise.all(items.map((item) => getArticle(item, ctx)));
+
+ ctx.state.data = {
+ title: pageCapture('title').text(),
+ description: pageDescription,
+ link: pageURL,
+ item: items,
+ };
+};
diff --git a/lib/v2/nature/news.js b/lib/v2/nature/news.js
new file mode 100644
index 00000000000000..911edf0e60904e
--- /dev/null
+++ b/lib/v2/nature/news.js
@@ -0,0 +1,30 @@
+const cheerio = require('cheerio');
+const got = require('@/utils/got');
+const { parseDate } = require('@/utils/parse-date');
+const { baseUrl, getArticle } = require('./utils');
+
+module.exports = async (ctx) => {
+ const url = `${baseUrl}/latest-news`;
+ const res = await got(url);
+ const $ = cheerio.load(res.data);
+
+ let items = $('.c-article-item__content')
+ .toArray()
+ .map((item) => {
+ item = $(item);
+ return {
+ title: item.find('h3').text(),
+ link: baseUrl + item.find('a').attr('href'),
+ pubDate: parseDate(item.find('.c-article-item__date').text()),
+ };
+ });
+
+ items = await Promise.all(items.map((item) => ctx.cache.tryGet(item.link, () => getArticle(item, ctx))));
+
+ ctx.state.data = {
+ title: 'Nature | Latest News',
+ description: $('meta[name=description]').attr('content'),
+ link: url,
+ item: items,
+ };
+};
diff --git a/lib/v2/nature/radar.js b/lib/v2/nature/radar.js
new file mode 100644
index 00000000000000..d2cecfaa57383a
--- /dev/null
+++ b/lib/v2/nature/radar.js
@@ -0,0 +1,37 @@
+module.exports = {
+ 'nature.com': {
+ _name: 'Nature',
+ '.': [
+ {
+ title: '最新成果',
+ docs: 'https://docs.rsshub.app/journal.html#nature-xi-lie',
+ source: ['/:journal/research-articles', '/:journal', '/'],
+ target: '/nature/research/:journal',
+ },
+ {
+ title: '新闻及评论',
+ docs: 'https://docs.rsshub.app/journal.html#nature-xi-lie',
+ source: ['/:journal/news-and-comment', '/:journal', '/'],
+ target: '/nature/news-and-comment/:journal',
+ },
+ {
+ title: '封面故事',
+ docs: 'https://docs.rsshub.app/journal.html#nature-xi-lie',
+ source: ['/'],
+ target: '/nature/cover',
+ },
+ {
+ title: '主刊 - 新闻动态',
+ docs: 'https://docs.rsshub.app/journal.html#nature-xi-lie',
+ source: ['/latest-news', '/news', '/'],
+ target: '/nature/news',
+ },
+ {
+ title: '精彩研究',
+ docs: 'https://docs.rsshub.app/journal.html#nature-xi-lie',
+ source: ['/:journal/articles?type=research-highlight', '/:journal', '/'],
+ target: '/nature/highlight/:journal',
+ },
+ ],
+ },
+};
diff --git a/lib/v2/nature/research.js b/lib/v2/nature/research.js
new file mode 100644
index 00000000000000..3d683bb31a16f4
--- /dev/null
+++ b/lib/v2/nature/research.js
@@ -0,0 +1,39 @@
+// example usage: `/nature/research/ng`
+// The journals from NPG are run by different group of people,
+// and the website of may not be consitent for all the journals
+//
+// This router has **just** been tested in:
+// nature: Nature
+// nbt: Nature Biotechnology
+// neuro: Nature Neuroscience
+// ng: Nature Genetics
+// ni: Nature Immunology
+// nmeth: Nature Method
+// nchem: Nature Chemistry
+// nmat: Nature Materials
+// natmachintell: Nature Machine Intelligence
+
+const cheerio = require('cheerio');
+const got = require('@/utils/got');
+const { baseUrl, getArticleList, getDataLayer, getArticle } = require('./utils');
+
+module.exports = async (ctx) => {
+ const journal = ctx.params.journal ?? 'nature';
+ const pageURL = `${baseUrl}/${journal}/research-articles`;
+
+ const pageResponse = await got(pageURL);
+ const pageCapture = cheerio.load(pageResponse.data);
+
+ const pageTitle = getDataLayer(pageCapture).content.journal.title;
+
+ let items = getArticleList(pageCapture);
+
+ items = await Promise.all(items.map((item) => getArticle(item, ctx)));
+
+ ctx.state.data = {
+ title: `Nature (${pageTitle}) | Latest Research`,
+ description: pageCapture('meta[name="description"]').attr('content') || `Nature, a nature research journal`,
+ link: pageURL,
+ item: items,
+ };
+};
diff --git a/lib/v2/nature/router.js b/lib/v2/nature/router.js
new file mode 100644
index 00000000000000..7bee4c0c75839f
--- /dev/null
+++ b/lib/v2/nature/router.js
@@ -0,0 +1,8 @@
+module.exports = (router) => {
+ router.get('/cover', require('./cover'));
+ router.get('/highlight/:journal?', require('./highlight'));
+ router.get('/news', require('./news'));
+ router.get('/news-and-comment/:journal?', require('./news-and-comment'));
+ router.get('/research/:journal?', require('./research'));
+ router.get('/siteindex', require('./siteindex'));
+};
diff --git a/lib/v2/nature/siteindex.js b/lib/v2/nature/siteindex.js
new file mode 100644
index 00000000000000..055e67f0d1e52d
--- /dev/null
+++ b/lib/v2/nature/siteindex.js
@@ -0,0 +1,48 @@
+const got = require('@/utils/got');
+const cheerio = require('cheerio');
+const { baseUrl } = require('./utils');
+
+module.exports = async (ctx) => {
+ const response = await got(`${baseUrl}/siteindex`);
+ const $ = cheerio.load(response.data);
+
+ let items = $('li[class^="grid mq640-grid-12"]')
+ .toArray()
+ .map((item) => {
+ item = $(item);
+ return {
+ title: item.find('a').attr('href').replace('/', ''),
+ name: item.find('a').text(),
+ link: baseUrl + item.find('a').attr('href'),
+ };
+ });
+
+ items = await Promise.all(
+ items.map((item) =>
+ ctx.cache.tryGet(`nature:siteindex:${item.title}`, async () => {
+ const response = await got(item.link);
+ const $ = cheerio.load(response.data);
+
+ delete item.link;
+ try {
+ item.id = $('.app-latest-issue-row__image img')
+ .attr('src')
+ .match(/.*\/journal\/(\d{5})/)[1];
+ item.description = item.id;
+ } catch (e) {
+ //
+ }
+ return item;
+ })
+ )
+ );
+
+ ctx.state.data = {
+ title: 'Nature siteindex',
+ link: baseUrl + '/siteindex',
+ item: items,
+ };
+ ctx.state.json = {
+ items,
+ };
+};
diff --git a/lib/v2/nature/utils.js b/lib/v2/nature/utils.js
new file mode 100644
index 00000000000000..ce7dfe6f83047b
--- /dev/null
+++ b/lib/v2/nature/utils.js
@@ -0,0 +1,980 @@
+const got = require('@/utils/got');
+const cheerio = require('cheerio');
+const { parseDate } = require('@/utils/parse-date');
+
+const baseUrl = 'https://www.nature.com';
+
+const fixFigure = (html) => {
+ html('picture source').each((_, i) => {
+ i = html(i);
+ if (
+ i.attr('srcset') &&
+ (i.attr('srcset').startsWith('//media.springernature.com/lw685/') ||
+ i.attr('srcset').startsWith('//media.springernature.com/m312/') ||
+ i.attr('srcset').startsWith('//media.springernature.com/relative-r300-703_m1050/') ||
+ i.attr('srcset').startsWith('//media.springernature.com/w300/'))
+ ) {
+ i.attr('srcset', i.attr('srcset').replace('//media.springernature.com/lw685/', '//media.springernature.com/full/'));
+ i.attr('srcset', i.attr('srcset').replace('//media.springernature.com/m312/', '//media.springernature.com/full/'));
+ i.attr('srcset', i.attr('srcset').replace('//media.springernature.com/relative-r300-703_m1050/', '//media.springernature.com/full/'));
+ i.attr('srcset', i.attr('srcset').replace('//media.springernature.com/w300/', '//media.springernature.com/full/'));
+ }
+ });
+ html('img').each((_, i) => {
+ i = html(i);
+ if (
+ i.attr('src') &&
+ (i.attr('src').startsWith('//media.springernature.com/lw685/') ||
+ i.attr('src').startsWith('//media.springernature.com/m312/') ||
+ i.attr('src').startsWith('//media.springernature.com/relative-r300-703_m1050/') ||
+ i.attr('src').startsWith('//media.springernature.com/w300/'))
+ ) {
+ i.attr('src', i.attr('src').replace('//media.springernature.com/lw685/', '//media.springernature.com/full/'));
+ i.attr('src', i.attr('src').replace('//media.springernature.com/m312/', '//media.springernature.com/full/'));
+ i.attr('src', i.attr('src').replace('//media.springernature.com/relative-r300-703_m1050/', '//media.springernature.com/full/'));
+ i.attr('src', i.attr('src').replace('//media.springernature.com/w300/', '//media.springernature.com/full/'));
+ }
+ });
+};
+
+const getArticleList = (html) =>
+ html('.app-article-list-row__item')
+ .toArray()
+ .map((item) => {
+ item = html(item);
+ return {
+ title: item.find('a').text(),
+ link: baseUrl + item.find('a').attr('href'),
+ pubDate: parseDate(item.find('.c-meta time').attr('datetime'), 'YYYY-MM-DD'),
+ };
+ });
+
+const getArticle = (item, ctx) =>
+ ctx.cache.tryGet(item.link, async () => {
+ const response = await got(item.link);
+ const $ = cheerio.load(response.data);
+ const responseUrl = new URL(response.url);
+
+ if (responseUrl.pathname.startsWith('/immersive/')) {
+ const meta = getDataLayer($);
+ item.doi = meta.content.article?.doi;
+ item.author = meta.content.contentInfo.authors.join(', ');
+ item.pubDate = parseDate(meta.content.contentInfo.publishedAt * 1000) || item.pubDate;
+ } else {
+ const meta = JSON.parse($('script[type="application/ld+json"]').html());
+ const freeAccess = meta.mainEntity.isAccessibleForFree;
+ let description;
+
+ if (meta.mainEntity.sameAs.startsWith('https://doi.org/')) {
+ item.doi = meta.mainEntity.sameAs.replace('https://doi.org/', '');
+ }
+ item.author = meta.mainEntity.author.map((author) => author.name.replace(', ', ' ')).join(', ');
+ item.category = meta.mainEntity.keywords.split(',');
+ item.pubDate = parseDate(meta.mainEntity.datePublished) || item.pubDate;
+
+ fixFigure($);
+
+ $('section[data-recommended=jobs], span[data-recommended=jobs]').remove();
+ $('#further-reading-section').remove();
+ $('figure div.u-text-right.u-hide-print').remove();
+
+ if (!freeAccess) {
+ $('div.c-article-access-provider, h2#access-options, div[data-component=entitlement-box],div[class^=LiveAreaSection-], nav.c-access-options').remove();
+ description =
+ $('.c-article-body').html() ||
+ ($('.c-article-teaser-text').html() ?? '') + ($('div.u-clear-both.c-article-wide-figure').html() ?? '') + $('.article__teaser').html() + ($('.c-article-references__container').html() ?? '');
+ } else {
+ description = $('.c-article-body').html();
+ }
+
+ if ($('div.c-pdf-download').length) {
+ // Please don't use meta[name=citation_pdf_url] because some of them point to an URL that needs to be logged in.
+ // e.g., https://www.nature.com/articles/s41593-022-01079-5
+ description += `Download PDF`;
+ }
+
+ item.description = description;
+ }
+ return item;
+ });
+
+const getDataLayer = (html) =>
+ JSON.parse(
+ html('script[data-test=dataLayer]')
+ .html()
+ .match(/window\.dataLayer = \[(.*)\];/s)[1]
+ );
+
+/**
+ * This is generated by /nature/siteindex.debug.json
+ */
+const journalMap = {
+ items: [
+ {
+ title: 'aps',
+ name: 'Acta Pharmacologica Sinica',
+ id: '41401',
+ description: '41401',
+ },
+ {
+ title: 'bdjinpractice',
+ name: 'BDJ In Practice',
+ id: '41404',
+ description: '41404',
+ },
+ {
+ title: 'bdjopen',
+ name: 'BDJ Open',
+ },
+ {
+ title: 'bdjstudent',
+ name: 'BDJ Student',
+ id: '41406',
+ description: '41406',
+ },
+ {
+ title: 'bdjteam',
+ name: 'BDJ Team',
+ id: '41407',
+ description: '41407',
+ },
+ {
+ title: 'biopharmdeal',
+ name: 'Biopharma Dealmakers',
+ id: '43747',
+ description: '43747',
+ },
+ {
+ title: 'bcj',
+ name: 'Blood Cancer Journal',
+ },
+ {
+ title: 'bmt',
+ name: 'Bone Marrow Transplantation',
+ id: '41409',
+ description: '41409',
+ },
+ {
+ title: 'boneres',
+ name: 'Bone Research',
+ },
+ {
+ title: 'bdj',
+ name: 'British Dental Journal',
+ id: '41415',
+ description: '41415',
+ },
+ {
+ title: 'bjc',
+ name: 'British Journal of Cancer',
+ id: '41416',
+ description: '41416',
+ },
+ {
+ title: 'cgt',
+ name: 'Cancer Gene Therapy',
+ id: '41417',
+ description: '41417',
+ },
+ {
+ title: 'cdd',
+ name: 'Cell Death & Differentiation',
+ id: '41418',
+ description: '41418',
+ },
+ {
+ title: 'cddis',
+ name: 'Cell Death & Disease',
+ },
+ {
+ title: 'cddiscovery',
+ name: 'Cell Death Discovery',
+ },
+ {
+ title: 'celldisc',
+ name: 'Cell Discovery',
+ },
+ {
+ title: 'cr',
+ name: 'Cell Research',
+ id: '41422',
+ description: '41422',
+ },
+ {
+ title: 'cmi',
+ name: 'Cellular & Molecular Immunology',
+ id: '41423',
+ description: '41423',
+ },
+ {
+ title: 'commsbio',
+ name: 'Communications Biology',
+ },
+ {
+ title: 'commschem',
+ name: 'Communications Chemistry',
+ },
+ {
+ title: 'commsenv',
+ name: 'Communications Earth & Environment',
+ },
+ {
+ title: 'commseng',
+ name: 'Communications Engineering',
+ },
+ {
+ title: 'commsmat',
+ name: 'Communications Materials',
+ },
+ {
+ title: 'commsmed',
+ name: 'Communications Medicine',
+ },
+ {
+ title: 'commsphys',
+ name: 'Communications Physics',
+ },
+ {
+ title: 'ejcn',
+ name: 'European Journal of Clinical Nutrition',
+ id: '41430',
+ description: '41430',
+ },
+ {
+ title: 'ejhg',
+ name: 'European Journal of Human Genetics',
+ id: '41431',
+ description: '41431',
+ },
+ {
+ title: 'ebd',
+ name: 'Evidence-Based Dentistry',
+ id: '41432',
+ description: '41432',
+ },
+ {
+ title: 'emm',
+ name: 'Experimental & Molecular Medicine',
+ id: '12276',
+ description: '12276',
+ },
+ {
+ title: 'eye',
+ name: 'Eye',
+ id: '41433',
+ description: '41433',
+ },
+ {
+ title: 'gt',
+ name: 'Gene Therapy',
+ id: '41434',
+ description: '41434',
+ },
+ {
+ title: 'gene',
+ name: 'Genes & Immunity',
+ id: '41435',
+ description: '41435',
+ },
+ {
+ title: 'hdy',
+ name: 'Heredity',
+ id: '41437',
+ description: '41437',
+ },
+ {
+ title: 'hgv',
+ name: 'Human Genome Variation',
+ },
+ {
+ title: 'palcomms',
+ name: 'Humanities and Social Sciences Communications',
+ },
+ {
+ title: 'hr',
+ name: 'Hypertension Research',
+ id: '41440',
+ description: '41440',
+ },
+ {
+ title: 'ijir',
+ name: 'International Journal of Impotence Research',
+ id: '41443',
+ description: '41443',
+ },
+ {
+ title: 'ijo',
+ name: 'International Journal of Obesity',
+ id: '41366',
+ description: '41366',
+ },
+ {
+ title: 'ijosup',
+ name: 'International Journal of Obesity Supplements',
+ id: '41367',
+ description: '41367',
+ },
+ {
+ title: 'ijos',
+ name: 'International Journal of Oral Science',
+ },
+ {
+ title: 'ismecomms',
+ name: 'ISME Communications',
+ },
+ {
+ title: 'ismej',
+ name: 'The ISME Journal',
+ id: '41396',
+ description: '41396',
+ },
+ {
+ title: 'ja',
+ name: 'The Journal of Antibiotics',
+ id: '41429',
+ description: '41429',
+ },
+ {
+ title: 'jes',
+ name: 'Journal of Exposure Science & Environmental Epidemiology',
+ id: '41370',
+ description: '41370',
+ },
+ {
+ title: 'jhg',
+ name: 'Journal of Human Genetics',
+ id: '10038',
+ description: '10038',
+ },
+ {
+ title: 'jhh',
+ name: 'Journal of Human Hypertension',
+ id: '41371',
+ description: '41371',
+ },
+ {
+ title: 'jp',
+ name: 'Journal of Perinatology',
+ id: '41372',
+ description: '41372',
+ },
+ {
+ title: 'laban',
+ name: 'Lab Animal',
+ id: '41684',
+ description: '41684',
+ },
+ {
+ title: 'labinvest',
+ name: 'Laboratory Investigation',
+ id: '41374',
+ description: '41374',
+ },
+ {
+ title: 'leu',
+ name: 'Leukemia',
+ id: '41375',
+ description: '41375',
+ },
+ {
+ title: 'leusup',
+ name: 'Leukemia Supplements',
+ id: '41376',
+ description: '41376',
+ },
+ {
+ title: 'lsa',
+ name: 'Light: Science & Applications',
+ },
+ {
+ title: 'micronano',
+ name: 'Microsystems & Nanoengineering',
+ },
+ {
+ title: 'modpathol',
+ name: 'Modern Pathology',
+ id: '41379',
+ description: '41379',
+ },
+ {
+ title: 'mp',
+ name: 'Molecular Psychiatry',
+ id: '41380',
+ description: '41380',
+ },
+ {
+ title: 'mi',
+ name: 'Mucosal Immunology',
+ id: '41385',
+ description: '41385',
+ },
+ {
+ title: 'nature',
+ name: 'Nature',
+ },
+ {
+ title: 'natafrica',
+ name: 'Nature Africa',
+ },
+ {
+ title: 'nataging',
+ name: 'Nature Aging',
+ id: '43587',
+ description: '43587',
+ },
+ {
+ title: 'natastron',
+ name: 'Nature Astronomy',
+ id: '41550',
+ description: '41550',
+ },
+ {
+ title: 'natbiomedeng',
+ name: 'Nature Biomedical Engineering',
+ id: '41551',
+ description: '41551',
+ },
+ {
+ title: 'nbt',
+ name: 'Nature Biotechnology',
+ id: '41587',
+ description: '41587',
+ },
+ {
+ title: 'natcancer',
+ name: 'Nature Cancer',
+ id: '43018',
+ description: '43018',
+ },
+ {
+ title: 'natcardiovascres',
+ name: 'Nature Cardiovascular Research',
+ id: '44161',
+ description: '44161',
+ },
+ {
+ title: 'natcatal',
+ name: 'Nature Catalysis',
+ id: '41929',
+ description: '41929',
+ },
+ {
+ title: 'ncb',
+ name: 'Nature Cell Biology',
+ id: '41556',
+ description: '41556',
+ },
+ {
+ title: 'nchembio',
+ name: 'Nature Chemical Biology',
+ id: '41589',
+ description: '41589',
+ },
+ {
+ title: 'nchem',
+ name: 'Nature Chemistry',
+ id: '41557',
+ description: '41557',
+ },
+ {
+ title: 'nclimate',
+ name: 'Nature Climate Change',
+ id: '41558',
+ description: '41558',
+ },
+ {
+ title: 'ncomms',
+ name: 'Nature Communications',
+ },
+ {
+ title: 'natcomputsci',
+ name: 'Nature Computational Science',
+ id: '43588',
+ description: '43588',
+ },
+ {
+ title: 'ndigest',
+ name: 'Nature Digest',
+ },
+ {
+ title: 'natecolevol',
+ name: 'Nature Ecology & Evolution',
+ id: '41559',
+ description: '41559',
+ },
+ {
+ title: 'natelectron',
+ name: 'Nature Electronics',
+ id: '41928',
+ description: '41928',
+ },
+ {
+ title: 'nenergy',
+ name: 'Nature Energy',
+ id: '41560',
+ description: '41560',
+ },
+ {
+ title: 'natfood',
+ name: 'Nature Food',
+ id: '43016',
+ description: '43016',
+ },
+ {
+ title: 'ng',
+ name: 'Nature Genetics',
+ id: '41588',
+ description: '41588',
+ },
+ {
+ title: 'ngeo',
+ name: 'Nature Geoscience',
+ id: '41561',
+ description: '41561',
+ },
+ {
+ title: 'nathumbehav',
+ name: 'Nature Human Behaviour',
+ id: '41562',
+ description: '41562',
+ },
+ {
+ title: 'ni',
+ name: 'Nature Immunology',
+ id: '41590',
+ description: '41590',
+ },
+ {
+ title: 'natindia',
+ name: 'Nature India',
+ },
+ {
+ title: 'natitaly',
+ name: 'Nature Italy',
+ },
+ {
+ title: 'natmachintell',
+ name: 'Nature Machine Intelligence',
+ id: '42256',
+ description: '42256',
+ },
+ {
+ title: 'nmat',
+ name: 'Nature Materials',
+ id: '41563',
+ description: '41563',
+ },
+ {
+ title: 'nm',
+ name: 'Nature Medicine',
+ id: '41591',
+ description: '41591',
+ },
+ {
+ title: 'natmentalhealth',
+ name: 'Nature Mental Health',
+ },
+ {
+ title: 'natmetab',
+ name: 'Nature Metabolism',
+ id: '42255',
+ description: '42255',
+ },
+ {
+ title: 'nmeth',
+ name: 'Nature Methods',
+ id: '41592',
+ description: '41592',
+ },
+ {
+ title: 'nmicrobiol',
+ name: 'Nature Microbiology',
+ id: '41564',
+ description: '41564',
+ },
+ {
+ title: 'nnano',
+ name: 'Nature Nanotechnology',
+ id: '41565',
+ description: '41565',
+ },
+ {
+ title: 'neuro',
+ name: 'Nature Neuroscience',
+ id: '41593',
+ description: '41593',
+ },
+ {
+ title: 'nphoton',
+ name: 'Nature Photonics',
+ id: '41566',
+ description: '41566',
+ },
+ {
+ title: 'nphys',
+ name: 'Nature Physics',
+ id: '41567',
+ description: '41567',
+ },
+ {
+ title: 'nplants',
+ name: 'Nature Plants',
+ id: '41477',
+ description: '41477',
+ },
+ {
+ title: 'nprot',
+ name: 'Nature Protocols',
+ id: '41596',
+ description: '41596',
+ },
+ {
+ title: 'natrevbioeng',
+ name: 'Nature Reviews Bioengineering',
+ },
+ {
+ title: 'nrc',
+ name: 'Nature Reviews Cancer',
+ id: '41568',
+ description: '41568',
+ },
+ {
+ title: 'nrcardio',
+ name: 'Nature Reviews Cardiology',
+ id: '41569',
+ description: '41569',
+ },
+ {
+ title: 'natrevchem',
+ name: 'Nature Reviews Chemistry',
+ id: '41570',
+ description: '41570',
+ },
+ {
+ title: 'nrclinonc',
+ name: 'Nature Reviews Clinical Oncology',
+ id: '41571',
+ description: '41571',
+ },
+ {
+ title: 'nrdp',
+ name: 'Nature Reviews Disease Primers',
+ },
+ {
+ title: 'nrd',
+ name: 'Nature Reviews Drug Discovery',
+ id: '41573',
+ description: '41573',
+ },
+ {
+ title: 'natrevearthenviron',
+ name: 'Nature Reviews Earth & Environment',
+ id: '43017',
+ description: '43017',
+ },
+ {
+ title: 'nrendo',
+ name: 'Nature Reviews Endocrinology',
+ id: '41574',
+ description: '41574',
+ },
+ {
+ title: 'nrgastro',
+ name: 'Nature Reviews Gastroenterology & Hepatology',
+ id: '41575',
+ description: '41575',
+ },
+ {
+ title: 'nrg',
+ name: 'Nature Reviews Genetics',
+ id: '41576',
+ description: '41576',
+ },
+ {
+ title: 'nri',
+ name: 'Nature Reviews Immunology',
+ id: '41577',
+ description: '41577',
+ },
+ {
+ title: 'natrevmats',
+ name: 'Nature Reviews Materials',
+ id: '41578',
+ description: '41578',
+ },
+ {
+ title: 'nrmp',
+ name: 'Nature Reviews Methods Primers',
+ },
+ {
+ title: 'nrmicro',
+ name: 'Nature Reviews Microbiology',
+ id: '41579',
+ description: '41579',
+ },
+ {
+ title: 'nrm',
+ name: 'Nature Reviews Molecular Cell Biology',
+ id: '41580',
+ description: '41580',
+ },
+ {
+ title: 'nrneph',
+ name: 'Nature Reviews Nephrology',
+ id: '41581',
+ description: '41581',
+ },
+ {
+ title: 'nrneurol',
+ name: 'Nature Reviews Neurology',
+ id: '41582',
+ description: '41582',
+ },
+ {
+ title: 'nrn',
+ name: 'Nature Reviews Neuroscience',
+ id: '41583',
+ description: '41583',
+ },
+ {
+ title: 'natrevphys',
+ name: 'Nature Reviews Physics',
+ id: '42254',
+ description: '42254',
+ },
+ {
+ title: 'nrpsychol',
+ name: 'Nature Reviews Psychology',
+ id: '44159',
+ description: '44159',
+ },
+ {
+ title: 'nrrheum',
+ name: 'Nature Reviews Rheumatology',
+ id: '41584',
+ description: '41584',
+ },
+ {
+ title: 'nrurol',
+ name: 'Nature Reviews Urology',
+ id: '41585',
+ description: '41585',
+ },
+ {
+ title: 'nsmb',
+ name: 'Nature Structural & Molecular Biology',
+ id: '41594',
+ description: '41594',
+ },
+ {
+ title: 'natsustain',
+ name: 'Nature Sustainability',
+ id: '41893',
+ description: '41893',
+ },
+ {
+ title: 'natsynth',
+ name: 'Nature Synthesis',
+ id: '44160',
+ description: '44160',
+ },
+ {
+ title: 'natwater',
+ name: 'Nature Water',
+ },
+ {
+ title: 'npp',
+ name: 'Neuropsychopharmacology',
+ id: '41386',
+ description: '41386',
+ },
+ {
+ title: 'am',
+ name: 'NPG Asia Materials',
+ },
+ {
+ title: 'npj2dmaterials',
+ name: 'npj 2D Materials and Applications',
+ },
+ {
+ title: 'npjamd',
+ name: 'npj Aging',
+ },
+ {
+ title: 'npjbiodivers',
+ name: 'npj Biodiversity',
+ },
+ {
+ title: 'npjbiofilms',
+ name: 'npj Biofilms and Microbiomes',
+ },
+ {
+ title: 'npjbcancer',
+ name: 'npj Breast Cancer',
+ },
+ {
+ title: 'npjcleanwater',
+ name: 'npj Clean Water',
+ },
+ {
+ title: 'npjclimatsci',
+ name: 'npj Climate and Atmospheric Science',
+ },
+ {
+ title: 'npjcompumats',
+ name: 'npj Computational Materials',
+ },
+ {
+ title: 'npjdigitalmed',
+ name: 'npj Digital Medicine',
+ },
+ {
+ title: 'npjflexelectron',
+ name: 'npj Flexible Electronics',
+ },
+ {
+ title: 'npjgenmed',
+ name: 'npj Genomic Medicine',
+ },
+ {
+ title: 'npjmatdeg',
+ name: 'npj Materials Degradation',
+ },
+ {
+ title: 'npjmentalhealth',
+ name: 'npj Mental Health Research',
+ },
+ {
+ title: 'npjmgrav',
+ name: 'npj Microgravity',
+ },
+ {
+ title: 'npjparkd',
+ name: "npj Parkinson's Disease",
+ },
+ {
+ title: 'npjprecisiononcology',
+ name: 'npj Precision Oncology',
+ },
+ {
+ title: 'npjpcrm',
+ name: 'npj Primary Care Respiratory Medicine',
+ },
+ {
+ title: 'npjqi',
+ name: 'npj Quantum Information',
+ },
+ {
+ title: 'npjquantmats',
+ name: 'npj Quantum Materials',
+ },
+ {
+ title: 'npjregenmed',
+ name: 'npj Regenerative Medicine',
+ },
+ {
+ title: 'npjscifood',
+ name: 'npj Science of Food',
+ },
+ {
+ title: 'npjscilearn',
+ name: 'npj Science of Learning',
+ },
+ {
+ title: 'npjsba',
+ name: 'npj Systems Biology and Applications',
+ },
+ {
+ title: 'npjurbansustain',
+ name: 'npj Urban Sustainability',
+ },
+ {
+ title: 'npjvaccines',
+ name: 'npj Vaccines',
+ },
+ {
+ title: 'nutd',
+ name: 'Nutrition & Diabetes',
+ },
+ {
+ title: 'onc',
+ name: 'Oncogene',
+ id: '41388',
+ description: '41388',
+ },
+ {
+ title: 'oncsis',
+ name: 'Oncogenesis',
+ },
+ {
+ title: 'pr',
+ name: 'Pediatric Research',
+ id: '41390',
+ description: '41390',
+ },
+ {
+ title: 'tpj',
+ name: 'The Pharmacogenomics Journal',
+ id: '41397',
+ description: '41397',
+ },
+ {
+ title: 'pj',
+ name: 'Polymer Journal',
+ id: '41428',
+ description: '41428',
+ },
+ {
+ title: 'pcan',
+ name: 'Prostate Cancer and Prostatic Diseases',
+ id: '41391',
+ description: '41391',
+ },
+ {
+ title: 'npjschz',
+ name: 'Schizophrenia',
+ },
+ {
+ title: 'scientificamerican',
+ name: 'Scientific American',
+ },
+ {
+ title: 'scientificamericanmind',
+ name: 'Scientific American Mind',
+ },
+ {
+ title: 'sdata',
+ name: 'Scientific Data',
+ },
+ {
+ title: 'srep',
+ name: 'Scientific Reports',
+ },
+ {
+ title: 'sigtrans',
+ name: 'Signal Transduction and Targeted Therapy',
+ },
+ {
+ title: 'sc',
+ name: 'Spinal Cord',
+ id: '41393',
+ description: '41393',
+ },
+ {
+ title: 'scsandc',
+ name: 'Spinal Cord Series and Cases',
+ },
+ {
+ title: 'tp',
+ name: 'Translational Psychiatry',
+ },
+ ],
+};
+
+module.exports = {
+ baseUrl,
+ getArticle,
+ getArticleList,
+ getDataLayer,
+ journalMap,
+};
diff --git a/lib/v2/tingshuitz/dalian.js b/lib/v2/tingshuitz/dalian.js
new file mode 100644
index 00000000000000..f976ad07bcd4dc
--- /dev/null
+++ b/lib/v2/tingshuitz/dalian.js
@@ -0,0 +1,29 @@
+const got = require('@/utils/got');
+const cheerio = require('cheerio');
+const { parseDate } = require('@/utils/parse-date');
+
+module.exports = async (ctx) => {
+ const url =
+ 'https://swj.dl.gov.cn/module/web/jpage/dataproxy.jsp?page=1&webid=28&path=https://swj.dl.gov.cn/&columnid=4296&unitid=31227&webname=%25E5%25A4%25A7%25E8%25BF%259E%25E5%25B8%2582%25E6%25B0%25B4%25E5%258A%25A1%25E5%25B1%2580&permissiontype=0';
+ const response = await got(url);
+
+ const $ = cheerio.load(response.data);
+ const items = $('recordset record')
+ .toArray()
+ .map((item) => {
+ item = $(item);
+ return {
+ title: item.find('a').text().trim(),
+ description: `大连市停水通知:${item.find('a').text().trim()}`,
+ pubDate: parseDate(item.find('span').text(), 'YYYY-MM-DD'),
+ link: item.find('a').attr('href'),
+ };
+ });
+
+ ctx.state.data = {
+ title: '停水通知 - 大连市水务局',
+ link: 'https://swj.dl.gov.cn/col/col4296/index.html',
+ description: '停水通知 - 大连市水务局',
+ item: items,
+ };
+};
diff --git a/lib/routes/tingshuitz/dongguan.js b/lib/v2/tingshuitz/dongguan.js
similarity index 88%
rename from lib/routes/tingshuitz/dongguan.js
rename to lib/v2/tingshuitz/dongguan.js
index 979470cd619270..e77c6e96dfabd7 100644
--- a/lib/routes/tingshuitz/dongguan.js
+++ b/lib/v2/tingshuitz/dongguan.js
@@ -1,5 +1,6 @@
const got = require('@/utils/got');
const cheerio = require('cheerio');
+const { parseDate } = require('@/utils/parse-date');
module.exports = async (ctx) => {
const url = 'http://www.djsw.com.cn/news/tstz/index.html';
@@ -24,7 +25,7 @@ module.exports = async (ctx) => {
return {
title: item.find('a').text(),
description: `东莞市停水通知:${item.find('a').text()}`,
- pubDate: new Date($(item.contents()[1]).text().slice(1, -1)).toUTCString(),
+ pubDate: parseDate($(item.contents()[1]).text().slice(1, -1)),
link: item.find('a').attr('href'),
};
})
diff --git a/lib/routes/tingshuitz/guangzhou.js b/lib/v2/tingshuitz/guangzhou.js
similarity index 100%
rename from lib/routes/tingshuitz/guangzhou.js
rename to lib/v2/tingshuitz/guangzhou.js
diff --git a/lib/routes/tingshuitz/hangzhou.js b/lib/v2/tingshuitz/hangzhou.js
similarity index 100%
rename from lib/routes/tingshuitz/hangzhou.js
rename to lib/v2/tingshuitz/hangzhou.js
diff --git a/lib/v2/tingshuitz/maintainer.js b/lib/v2/tingshuitz/maintainer.js
new file mode 100644
index 00000000000000..6976a2f9e6c1cf
--- /dev/null
+++ b/lib/v2/tingshuitz/maintainer.js
@@ -0,0 +1,11 @@
+module.exports = {
+ '/dalian': ['DIYgod'],
+ '/dongguan': ['victoriqueko'],
+ '/guangzhou': ['xyqfer'],
+ '/hangzhou': ['znhocn'],
+ '/nanjing': ['ocleo1'],
+ '/wuhan': ['MoonBegonia'],
+ '/xian': ['ciaranchen'],
+ '/xiaoshan': ['znhocn'],
+ '/yangjiang': ['ciaranchen'],
+};
diff --git a/lib/routes/tingshuitz/nanjing.js b/lib/v2/tingshuitz/nanjing.js
similarity index 56%
rename from lib/routes/tingshuitz/nanjing.js
rename to lib/v2/tingshuitz/nanjing.js
index 924b02bfec5173..fbb1fb25209c33 100644
--- a/lib/routes/tingshuitz/nanjing.js
+++ b/lib/v2/tingshuitz/nanjing.js
@@ -1,15 +1,15 @@
const got = require('@/utils/got');
const cheerio = require('cheerio');
-
+const { parseDate } = require('@/utils/parse-date');
const HOME_PAGE = 'http://www.jlwater.com/';
module.exports = async (ctx) => {
- const url = `${HOME_PAGE}portal.do?method=news&subjectchildid=8`;
- const response = await got.get(url);
+ const url = `${HOME_PAGE}portal/10000013`;
+ const response = await got(url);
const data = response.data;
const $ = cheerio.load(data);
- const list = $('.maincol-list ul li');
+ const list = $('.list-content ul li');
ctx.state.data = {
title: $('head title').text(),
@@ -17,14 +17,12 @@ module.exports = async (ctx) => {
item: list
.map((index, item) => {
const $item = $(item);
- const $title = $item.find('.rtitle');
- const link = $title.find('a').attr('href');
-
- let pubDate = $item.find('.rtime').text();
- pubDate = new Date(pubDate.substring(1, pubDate.length - 1)).toUTCString();
-
+ const title = $item.find('a span').text();
+ const link = $item.find('a').attr('href');
+ const listTime = $item.find('.list-time').text();
+ const pubDate = parseDate(listTime);
return {
- title: $title.text(),
+ title: `${title} ${listTime}`,
description: '南京市停水通知',
link: `${HOME_PAGE}${link}`,
pubDate,
diff --git a/lib/v2/tingshuitz/radar.js b/lib/v2/tingshuitz/radar.js
new file mode 100644
index 00000000000000..a40f04245300a9
--- /dev/null
+++ b/lib/v2/tingshuitz/radar.js
@@ -0,0 +1,68 @@
+module.exports = {
+ 'dl.gov.cn': {
+ _name: '停水通知',
+ swj: [
+ {
+ title: '大连市',
+ docs: 'https://docs.rsshub.app/forecast.html#ting-shui-tong-zhi',
+ source: ['/col/col4296/index.html', '/'],
+ target: '/tingshuitz/dalian',
+ },
+ ],
+ },
+ 'hzwgc.com': {
+ _name: '停水通知',
+ www: [
+ {
+ title: '杭州市',
+ docs: 'https://docs.rsshub.app/forecast.html#ting-shui-tong-zhi',
+ source: ['/public/stop_the_water', '/'],
+ target: '/tingshuitz/hangzhou',
+ },
+ ],
+ },
+ 'jlwater.com': {
+ _name: '停水通知',
+ '.': [
+ {
+ title: '南京市',
+ docs: 'https://docs.rsshub.app/forecast.html#ting-shui-tong-zhi',
+ source: ['/portal/10000013', '/'],
+ target: '/tingshuitz/nanjing',
+ },
+ ],
+ },
+ 'whwater.com': {
+ _name: '停水通知',
+ '.': [
+ {
+ title: '武汉市',
+ docs: 'https://docs.rsshub.app/forecast.html#ting-shui-tong-zhi',
+ source: ['/IWater.shtml', '/'],
+ target: '/tingshuitz/wuhan',
+ },
+ ],
+ },
+ 'xswater.com': {
+ _name: '停水通知',
+ www: [
+ {
+ title: '萧山区',
+ docs: 'https://docs.rsshub.app/forecast.html#ting-shui-tong-zhi',
+ source: ['/gongshui/channels/227.html', '/'],
+ target: '/tingshuitz/xiaoshan',
+ },
+ ],
+ },
+ 'yjsswjt.com': {
+ _name: '停水通知',
+ '.': [
+ {
+ title: '阳江市',
+ docs: 'https://docs.rsshub.app/forecast.html#ting-shui-tong-zhi',
+ source: ['/zxdt_list.jsp', '/'],
+ target: '/tingshuitz/yangjiang',
+ },
+ ],
+ },
+};
diff --git a/lib/v2/tingshuitz/router.js b/lib/v2/tingshuitz/router.js
new file mode 100644
index 00000000000000..c90302af7b0845
--- /dev/null
+++ b/lib/v2/tingshuitz/router.js
@@ -0,0 +1,11 @@
+module.exports = (router) => {
+ router.get('/dalian', require('./dalian'));
+ router.get('/dongguan', require('./dongguan'));
+ router.get('/guangzhou', require('./guangzhou'));
+ router.get('/hangzhou', require('./hangzhou'));
+ router.get('/nanjing', require('./nanjing'));
+ router.get('/wuhan/:channelId?', require('./wuhan'));
+ router.get('/xian', require('./xian'));
+ router.get('/xiaoshan', require('./xiaoshan'));
+ router.get('/yangjiang', require('./yangjiang'));
+};
diff --git a/lib/v2/tingshuitz/wuhan.js b/lib/v2/tingshuitz/wuhan.js
new file mode 100644
index 00000000000000..17f19722c30e96
--- /dev/null
+++ b/lib/v2/tingshuitz/wuhan.js
@@ -0,0 +1,32 @@
+const got = require('@/utils/got');
+const { parseDate } = require('@/utils/parse-date');
+const baseUrl = 'https://www.whwater.com';
+
+module.exports = async (ctx) => {
+ const { channelId = 68 } = ctx.params;
+ const response = await got.post('https://manager.whwater.com:8900/website/article/findChannelArticle', {
+ form: {
+ channelId,
+ searchKey: '',
+ thumbnailStatus: 0,
+ topStatus: 0,
+ recommendStatus: 0,
+ page: 1,
+ size: ctx.query.limit ? parseInt(ctx.query.limit) : 30,
+ },
+ });
+
+ const data = response.data.data;
+ const items = data.articleArray.map((item) => ({
+ title: item.title,
+ description: item.content,
+ pubDate: parseDate(item.publishTime),
+ link: `https://${baseUrl}/IPolicyDetails.shtml?id=31&sid=${channelId}${item.articleLink}`,
+ }));
+
+ ctx.state.data = {
+ title: `${data.channelName}通知 - 武汉市水务集团有限公司`,
+ link: `${baseUrl}/IWater.shtml?id=31&sid=48`,
+ item: items,
+ };
+};
diff --git a/lib/routes/tingshuitz/xian.js b/lib/v2/tingshuitz/xian.js
similarity index 95%
rename from lib/routes/tingshuitz/xian.js
rename to lib/v2/tingshuitz/xian.js
index 56472e1f00af2a..47bdc3c9bfc0e8 100644
--- a/lib/routes/tingshuitz/xian.js
+++ b/lib/v2/tingshuitz/xian.js
@@ -4,7 +4,7 @@ const iconv = require('iconv-lite');
module.exports = async (ctx) => {
const url = 'http://www.xazls.com/tsgg/index.htm';
- const response = await got.get(url, {
+ const response = await got(url, {
responseType: 'buffer',
});
diff --git a/lib/routes/tingshuitz/xiaoshan.js b/lib/v2/tingshuitz/xiaoshan.js
similarity index 100%
rename from lib/routes/tingshuitz/xiaoshan.js
rename to lib/v2/tingshuitz/xiaoshan.js
diff --git a/lib/routes/tingshuitz/yangjiang.js b/lib/v2/tingshuitz/yangjiang.js
similarity index 66%
rename from lib/routes/tingshuitz/yangjiang.js
rename to lib/v2/tingshuitz/yangjiang.js
index 1c1da60ebc50eb..5f406e60233979 100644
--- a/lib/routes/tingshuitz/yangjiang.js
+++ b/lib/v2/tingshuitz/yangjiang.js
@@ -1,20 +1,17 @@
const got = require('@/utils/got');
const cheerio = require('cheerio');
-const iconv = require('iconv-lite');
+const { parseDate } = require('@/utils/parse-date');
module.exports = async (ctx) => {
- const url = 'http://www.yjsswjt.com/zxdt_list.jsp?flbz=7';
- const response = await got.get(url, {
- responseType: 'buffer',
- });
+ const url = 'https://www.yjsswjt.com/zxdt_list.jsp?flbz=7';
+ const response = await got(url);
- const data = response.data;
- const $ = cheerio.load(iconv.decode(data, 'gb2312'));
+ const $ = cheerio.load(response.data);
const list = $('div.list_ul_div > ul > li');
ctx.state.data = {
title: '停水通知 - 阳江市水务集团有限公司',
- link: 'http://www.yjsswjt.com/zxdt_list.jsp?flbz=7',
+ link: 'https://www.yjsswjt.com/zxdt_list.jsp?flbz=7',
item: list
.map((_, el) => {
const item = $(el);
@@ -24,6 +21,7 @@ module.exports = async (ctx) => {
title: item.find('span').text().trim(),
description: item.find('span').text().trim(),
link: 'http://www.yjsswjt.com/list.jsp?id=' + id,
+ pubDate: parseDate(item.find('.datetime').text(), 'YYYY.MM.DD'),
};
})
.get(),
diff --git a/lib/v2/usts/jwch.js b/lib/v2/usts/jwch.js
new file mode 100644
index 00000000000000..ccc366f5072ce5
--- /dev/null
+++ b/lib/v2/usts/jwch.js
@@ -0,0 +1,56 @@
+const got = require('@/utils/got');
+const cheerio = require('cheerio');
+const { parseDate } = require('@/utils/parse-date');
+const timezone = require('@/utils/timezone');
+
+const rootURL = 'http://jwch.usts.edu.cn/index';
+
+module.exports = async (ctx) => {
+ const type = ctx.params.type ?? 'jwdt';
+ const url = `${rootURL}/${type}.htm`;
+ const response = await got(url);
+
+ const $ = cheerio.load(response.data);
+ const title = $('div.mainWrap.cleafix > div > div.right.fr > div.local.fl > h3').text();
+ const list = $('div.list > ul > li')
+ .map((_index, item) => ({
+ title: $(item).find('a').text(),
+ link: new URL($(item).find('a').attr('href'), rootURL).href,
+ }))
+ .get();
+
+ const items = await Promise.all(
+ list.map((item) =>
+ ctx.cache.tryGet(item.link, async () => {
+ const detailResponse = await got(item.link);
+ const content = cheerio.load(detailResponse.data);
+
+ let author = null;
+ let pubDate = null;
+ content('div.content-title.fl > i')
+ .text()
+ .split(' ')
+ .forEach((item) => {
+ if (item.includes('作者:')) {
+ author = item.split(':')[1];
+ }
+ if (item.includes('时间:')) {
+ pubDate = item.split(':')[1];
+ }
+ });
+
+ item.description = content('div#vsb_content').html();
+ item.author = author;
+ item.pubDate = timezone(parseDate(pubDate), +8);
+
+ return item;
+ })
+ )
+ );
+
+ ctx.state.data = {
+ title: `苏州科技大学 教务处 - ${title}`,
+ link: url,
+ item: items,
+ };
+};
diff --git a/lib/v2/usts/maintainer.js b/lib/v2/usts/maintainer.js
new file mode 100644
index 00000000000000..7ba955b2f28ae5
--- /dev/null
+++ b/lib/v2/usts/maintainer.js
@@ -0,0 +1,3 @@
+module.exports = {
+ '/juch/:type?': ['Fatpandac'],
+};
diff --git a/lib/v2/usts/radar.js b/lib/v2/usts/radar.js
new file mode 100644
index 00000000000000..d51cf8fb9ee9d3
--- /dev/null
+++ b/lib/v2/usts/radar.js
@@ -0,0 +1,25 @@
+module.exports = {
+ 'usts.edu.cn': {
+ _name: '苏州科技大学',
+ jwch: [
+ {
+ title: '教务动态',
+ docs: 'https://docs.rsshub.app/university.html#su-zhou-ke-ji-da-xue',
+ source: ['/jwdt.htm'],
+ target: '/wsts/jwch/jwdt',
+ },
+ {
+ title: '公告在线',
+ docs: 'https://docs.rsshub.app/university.html#su-zhou-ke-ji-da-xue',
+ source: ['/ggzx.htm'],
+ target: '/wsts/jwch/ggzx',
+ },
+ {
+ title: '选课通知',
+ docs: 'https://docs.rsshub.app/university.html#su-zhou-ke-ji-da-xue',
+ source: ['/xktz.htm'],
+ target: '/wsts/jwch/xktz',
+ },
+ ],
+ },
+};
diff --git a/lib/v2/usts/router.js b/lib/v2/usts/router.js
new file mode 100644
index 00000000000000..4575402d3aef16
--- /dev/null
+++ b/lib/v2/usts/router.js
@@ -0,0 +1,3 @@
+module.exports = function (router) {
+ router.get('/jwch/:type?', require('./jwch'));
+};
diff --git a/lib/v2/vimeo/templates/description.art b/lib/v2/vimeo/templates/description.art
index 2ea8f44f7ea744..91ed43dafea606 100644
--- a/lib/v2/vimeo/templates/description.art
+++ b/lib/v2/vimeo/templates/description.art
@@ -1,4 +1,4 @@
-
-{{ if vdescription }}
- {{@ vdescription }}
-{{ /if }}
+
+{{ if vdescription }}
+ {{@ vdescription }}
+{{ /if }}
diff --git a/lib/v2/yomiuri/maintainer.js b/lib/v2/yomiuri/maintainer.js
new file mode 100644
index 00000000000000..219f20c4d3cd03
--- /dev/null
+++ b/lib/v2/yomiuri/maintainer.js
@@ -0,0 +1,3 @@
+module.exports = {
+ '/yomiuri/:category?': ['Arracc'],
+};
diff --git a/lib/routes/yomiuri/news.js b/lib/v2/yomiuri/news.js
similarity index 78%
rename from lib/routes/yomiuri/news.js
rename to lib/v2/yomiuri/news.js
index 75d23a7c4a67c0..f5c5bb58669e43 100644
--- a/lib/routes/yomiuri/news.js
+++ b/lib/v2/yomiuri/news.js
@@ -1,6 +1,7 @@
const got = require('@/utils/got');
const cheerio = require('cheerio');
const timezone = require('@/utils/timezone');
+const { parseDate } = require('@/utils/parse-date');
module.exports = async (ctx) => {
const category = ctx.params.category;
@@ -17,26 +18,8 @@ module.exports = async (ctx) => {
let list = null;
if (category === 'news') {
categoryName = '新着・速報';
- const urlPrefix = 'https://www.yomiuri.co.jp/y_ajax/';
- // get list1
- const param1 = $('input#latest_list_news_other_params').val();
- const response1 = await got({
- method: 'get',
- url: urlPrefix + 'latest_list_news/' + param1 + '/?action=latest_list_news&others=' + param1,
- });
- const data1 = response1.data;
- const firstArticleList = cheerio.load(data1);
-
- // get list2
- const param2 = $('input#latest_list_news_other_params2').val();
- const response2 = await got({
- method: 'get',
- url: urlPrefix + 'latest_list_news2/' + param2 + '/?action=latest_list_news2&others=' + param2,
- });
- const data2 = response2.data;
- const secondArticleList = cheerio.load(data2);
- list = secondArticleList('article').add(firstArticleList('article'));
+ list = $('div#latest_list_news').find('article').append($('div#latest_list_news_more').find('article'));
list = list.map((index, item) => {
item = $(item);
@@ -74,8 +57,9 @@ module.exports = async (ctx) => {
}
// format category name
+ let formattedCategoryName = categoryName;
if (categoryName !== '') {
- categoryName = ' - ' + categoryName.trim();
+ formattedCategoryName = ' - ' + categoryName.trim();
}
const items = await Promise.all(
@@ -91,7 +75,7 @@ module.exports = async (ctx) => {
}
const description = await ctx.cache.tryGet(link, async () => {
- const response = await got.get(link);
+ const response = await got(link);
const $ = cheerio.load(response.data);
const mainContent = $('div.p-main-contents');
// remove articles recomended
@@ -120,6 +104,7 @@ module.exports = async (ctx) => {
editorial: '社説',
medical: '医療・健康',
olympic: 'オリンピック',
+ koushitsu: '皇室',
};
const tag_value = tag_table[link.split('/')[3]];
tag = tag_value ? tag_value : 'その他';
@@ -129,7 +114,7 @@ module.exports = async (ctx) => {
return {
title: tag + item.find('a').text(),
description,
- pubDate: timezone(new Date(item.find('time').prop('datetime')), +9),
+ pubDate: timezone(parseDate(item.find('time').prop('datetime')), +9),
link,
};
})
@@ -137,7 +122,7 @@ module.exports = async (ctx) => {
);
ctx.state.data = {
- title: '読売新聞' + categoryName,
+ title: '読売新聞' + formattedCategoryName,
link: url,
item: items,
};
diff --git a/lib/v2/yomiuri/radar.js b/lib/v2/yomiuri/radar.js
new file mode 100644
index 00000000000000..5030af25ba645b
--- /dev/null
+++ b/lib/v2/yomiuri/radar.js
@@ -0,0 +1,13 @@
+module.exports = {
+ 'yomiuri.co.jp': {
+ _name: '読売新聞',
+ www: [
+ {
+ title: '読売新聞',
+ docs: 'https://docs.rsshub.app/traditional-media.html#du-mai-xin-wen',
+ source: ['/:category'],
+ target: '/yomiuri/:category',
+ },
+ ],
+ },
+};
diff --git a/lib/v2/yomiuri/router.js b/lib/v2/yomiuri/router.js
new file mode 100644
index 00000000000000..6f4894d9acf4b9
--- /dev/null
+++ b/lib/v2/yomiuri/router.js
@@ -0,0 +1,3 @@
+module.exports = function (router) {
+ router.get('/:category?', require('./news'));
+};
diff --git a/lib/routes/zhihu/activities.js b/lib/v2/zhihu/activities.js
similarity index 97%
rename from lib/routes/zhihu/activities.js
rename to lib/v2/zhihu/activities.js
index 8ee0c8d4058d0a..e4a5af3a353355 100644
--- a/lib/routes/zhihu/activities.js
+++ b/lib/v2/zhihu/activities.js
@@ -1,5 +1,6 @@
const got = require('@/utils/got');
const utils = require('./utils');
+const { parseDate } = require('@/utils/parse-date');
module.exports = async (ctx) => {
const id = ctx.params.id;
@@ -101,7 +102,7 @@ module.exports = async (ctx) => {
title: `${data[0].actor.name}${item.action_text}: ${title}`,
author,
description,
- pubDate: new Date(item.created_time * 1000).toUTCString(),
+ pubDate: parseDate(item.created_time * 1000),
link: url,
};
}),
diff --git a/lib/routes/zhihu/answers.js b/lib/v2/zhihu/answers.js
similarity index 94%
rename from lib/routes/zhihu/answers.js
rename to lib/v2/zhihu/answers.js
index b15c767e03a918..d5789a404c9e46 100644
--- a/lib/routes/zhihu/answers.js
+++ b/lib/v2/zhihu/answers.js
@@ -1,5 +1,6 @@
const got = require('@/utils/got');
const utils = require('./utils');
+const { parseDate } = require('@/utils/parse-date');
module.exports = async (ctx) => {
const id = ctx.params.id;
@@ -48,7 +49,7 @@ module.exports = async (ctx) => {
return {
title,
description,
- pubDate: new Date(item.created_time * 1000).toUTCString(),
+ pubDate: parseDate(item.created_time * 1000),
link,
};
})
diff --git a/lib/routes/zhihu/bookstore/newest.js b/lib/v2/zhihu/bookstore/newest.js
similarity index 100%
rename from lib/routes/zhihu/bookstore/newest.js
rename to lib/v2/zhihu/bookstore/newest.js
diff --git a/lib/routes/zhihu/collection.js b/lib/v2/zhihu/collection.js
similarity index 93%
rename from lib/routes/zhihu/collection.js
rename to lib/v2/zhihu/collection.js
index ef80a49ef6e6c2..251448469ff7a5 100644
--- a/lib/routes/zhihu/collection.js
+++ b/lib/v2/zhihu/collection.js
@@ -2,6 +2,7 @@ const got = require('@/utils/got');
const cheerio = require('cheerio');
const utils = require('./utils');
const { generateData } = require('./pin/utils');
+const { parseDate } = require('@/utils/parse-date');
module.exports = async (ctx) => {
const id = ctx.params.id;
@@ -69,7 +70,7 @@ module.exports = async (ctx) => {
title: item.content.type === 'article' || item.content.type === 'zvideo' ? item.content.title : item.content.question.title,
link: item.content.url,
description: item.content.type === 'zvideo' ? `` : item.content.content,
- pubDate: new Date((item.content.type === 'article' ? item.content.updated : item.content.updated_time) * 1000).toUTCString(),
+ pubDate: parseDate((item.content.type === 'article' ? item.content.updated : item.content.updated_time) * 1000),
}
),
};
diff --git a/lib/routes/zhihu/daily.js b/lib/v2/zhihu/daily.js
similarity index 100%
rename from lib/routes/zhihu/daily.js
rename to lib/v2/zhihu/daily.js
diff --git a/lib/routes/zhihu/daily_section.js b/lib/v2/zhihu/daily_section.js
similarity index 83%
rename from lib/routes/zhihu/daily_section.js
rename to lib/v2/zhihu/daily_section.js
index 41492dedcdc472..22853fb1cdc508 100644
--- a/lib/routes/zhihu/daily_section.js
+++ b/lib/v2/zhihu/daily_section.js
@@ -15,21 +15,16 @@ module.exports = async (ctx) => {
},
});
// 根据api的说明,过滤掉极个别站外链接
- const storyList = listRes.data.stories.filter((el) => el.url.includes('daily.zhihu.com'));
+ const storyList = listRes.data.stories.filter((el) => el.url.startsWith('https://daily.zhihu.com/'));
const resultItem = await Promise.all(
- storyList.map(async (story) => {
+ storyList.map((story) => {
const url = 'https://news-at.zhihu.com/api/7/news/' + story.id;
const item = {
title: story.title,
description: '',
link: 'https://daily.zhihu.com/story/' + story.id,
};
- const key = 'daily' + story.id;
- const value = await ctx.cache.get(key);
-
- if (value) {
- item.description = value;
- } else {
+ return ctx.cache.tryGet(`https://daily.zhihu.com/story/${story.id}`, async () => {
const storyDetail = await got({
method: 'get',
url,
@@ -38,10 +33,9 @@ module.exports = async (ctx) => {
},
});
item.description = utils.ProcessImage(storyDetail.data.body.replace(/([\s\S]*?)<\/div>/g, '
$1').replace(/<\/?h2.*?>/g, ''));
- ctx.cache.set(key, item.description);
- }
- return item;
+ return item;
+ });
})
);
diff --git a/lib/v2/zhihu/execlib/g_encrypt.js b/lib/v2/zhihu/execlib/g_encrypt.js
new file mode 100644
index 00000000000000..ea45882c187ff2
--- /dev/null
+++ b/lib/v2/zhihu/execlib/g_encrypt.js
@@ -0,0 +1,407 @@
+/* eslint-disable space-in-parens */
+/* eslint-disable no-eval */
+/* eslint-disable block-scoped-var */
+/* eslint-disable no-var */
+/* eslint-disable eqeqeq */
+/* eslint-disable no-unused-vars */
+/* eslint-disable no-func-assign */
+/**
+ * Generate x-zse-96
+ *
+ * taken from https://github.com/srx-2000/spider_collection/blob/3b9f3cc8badc01e3f3e3035c14139d4d5fd1382f/zhihuAnswerSpider/spider/g_encrypt.js
+ */
+
+const jsdom = require('jsdom');
+const { JSDOM } = jsdom;
+const dom = new JSDOM(`
Hello world
`);
+const window = dom.window;
+
+function t(e) {
+ return (t =
+ 'function' === typeof Symbol && 'symbol' === typeof Symbol.A
+ ? function (e) {
+ return typeof e;
+ }
+ : function (e) {
+ return e && 'function' === typeof Symbol && e.constructor === Symbol && e !== Symbol.prototype ? 'symbol' : typeof e;
+ })(e);
+}
+
+Object.defineProperty(exports, '__esModule', {
+ value: !0,
+});
+const A = '2.0',
+ __g = {};
+
+function s() {}
+
+function i(e) {
+ (this.t = (2048 & e) >> 11), (this.s = (1536 & e) >> 9), (this.i = 511 & e), (this.h = 511 & e);
+}
+
+function h(e) {
+ (this.s = (3072 & e) >> 10), (this.h = 1023 & e);
+}
+
+function a(e) {
+ (this.a = (3072 & e) >> 10), (this.c = (768 & e) >> 8), (this.n = (192 & e) >> 6), (this.t = 63 & e);
+}
+
+function c(e) {
+ (this.s = (e >> 10) & 3), (this.i = 1023 & e);
+}
+
+function n() {}
+
+function e(e) {
+ (this.a = (3072 & e) >> 10), (this.c = (768 & e) >> 8), (this.n = (192 & e) >> 6), (this.t = 63 & e);
+}
+
+function o(e) {
+ (this.h = (4095 & e) >> 2), (this.t = 3 & e);
+}
+
+function r(e) {
+ (this.s = (e >> 10) & 3), (this.i = (e >> 2) & 255), (this.t = 3 & e);
+}
+
+(s.prototype.e = function (e) {
+ e.o = !1;
+}),
+ (i.prototype.e = function (e) {
+ switch (this.t) {
+ case 0:
+ e.r[this.s] = this.i;
+ break;
+ case 1:
+ e.r[this.s] = e.k[this.h];
+ }
+ }),
+ (h.prototype.e = function (e) {
+ e.k[this.h] = e.r[this.s];
+ }),
+ (a.prototype.e = function (e) {
+ switch (this.t) {
+ case 0:
+ e.r[this.a] = e.r[this.c] + e.r[this.n];
+ break;
+ case 1:
+ e.r[this.a] = e.r[this.c] - e.r[this.n];
+ break;
+ case 2:
+ e.r[this.a] = e.r[this.c] * e.r[this.n];
+ break;
+ case 3:
+ e.r[this.a] = e.r[this.c] / e.r[this.n];
+ break;
+ case 4:
+ e.r[this.a] = e.r[this.c] % e.r[this.n];
+ break;
+ case 5:
+ e.r[this.a] = e.r[this.c] == e.r[this.n];
+ break;
+ case 6:
+ e.r[this.a] = e.r[this.c] >= e.r[this.n];
+ break;
+ case 7:
+ e.r[this.a] = e.r[this.c] || e.r[this.n];
+ break;
+ case 8:
+ e.r[this.a] = e.r[this.c] && e.r[this.n];
+ break;
+ case 9:
+ e.r[this.a] = e.r[this.c] !== e.r[this.n];
+ break;
+ case 10:
+ e.r[this.a] = t(e.r[this.c]);
+ break;
+ case 11:
+ e.r[this.a] = e.r[this.c] in e.r[this.n];
+ break;
+ case 12:
+ e.r[this.a] = e.r[this.c] > e.r[this.n];
+ break;
+ case 13:
+ e.r[this.a] = -e.r[this.c];
+ break;
+ case 14:
+ e.r[this.a] = e.r[this.c] < e.r[this.n];
+ break;
+ case 15:
+ e.r[this.a] = e.r[this.c] & e.r[this.n];
+ break;
+ case 16:
+ e.r[this.a] = e.r[this.c] ^ e.r[this.n];
+ break;
+ case 17:
+ e.r[this.a] = e.r[this.c] << e.r[this.n];
+ break;
+ case 18:
+ e.r[this.a] = e.r[this.c] >>> e.r[this.n];
+ break;
+ case 19:
+ e.r[this.a] = e.r[this.c] | e.r[this.n];
+ break;
+ case 20:
+ e.r[this.a] = !e.r[this.c];
+ }
+ }),
+ (c.prototype.e = function (e) {
+ e.Q.push(e.C), e.B.push(e.k), (e.C = e.r[this.s]), (e.k = []);
+ for (let t = 0; t < this.i; t++) {
+ e.k.unshift(e.f.pop());
+ }
+ e.g.push(e.f), (e.f = []);
+ }),
+ (n.prototype.e = function (e) {
+ (e.C = e.Q.pop()), (e.k = e.B.pop()), (e.f = e.g.pop());
+ }),
+ (e.prototype.e = function (e) {
+ switch (this.t) {
+ case 0:
+ e.u = e.r[this.a] >= e.r[this.c];
+ break;
+ case 1:
+ e.u = e.r[this.a] <= e.r[this.c];
+ break;
+ case 2:
+ e.u = e.r[this.a] > e.r[this.c];
+ break;
+ case 3:
+ e.u = e.r[this.a] < e.r[this.c];
+ break;
+ case 4:
+ e.u = e.r[this.a] == e.r[this.c];
+ break;
+ case 5:
+ e.u = e.r[this.a] != e.r[this.c];
+ break;
+ case 6:
+ e.u = e.r[this.a];
+ break;
+ case 7:
+ e.u = !e.r[this.a];
+ }
+ }),
+ (o.prototype.e = function (e) {
+ switch (this.t) {
+ case 0:
+ e.C = this.h;
+ break;
+ case 1:
+ e.u && (e.C = this.h);
+ break;
+ case 2:
+ e.u || (e.C = this.h);
+ break;
+ case 3:
+ (e.C = this.h), (e.w = null);
+ }
+ e.u = !1;
+ }),
+ (r.prototype.e = function (e) {
+ switch (this.t) {
+ case 0:
+ for (var t = [], n = 0; n < this.i; n++) {
+ t.unshift(e.f.pop());
+ }
+ e.r[3] = e.r[this.s](t[0], t[1]);
+ break;
+ case 1:
+ for (var r = e.f.pop(), i = [], o = 0; o < this.i; o++) {
+ i.unshift(e.f.pop());
+ }
+ e.r[3] = e.r[this.s][r](i[0], i[1]);
+ break;
+ case 2:
+ for (var a = [], c = 0; c < this.i; c++) {
+ a.unshift(e.f.pop());
+ }
+ e.r[3] = new e.r[this.s](a[0], a[1]);
+ }
+ });
+const k = function (e) {
+ for (var t = 66, n = [], r = 0; r < e.length; r++) {
+ const i = 24 ^ e.charCodeAt(r) ^ t;
+ n.push(String.fromCharCode(i)), (t = i);
+ }
+ return n.join('');
+};
+
+function Q(e) {
+ (this.t = (4095 & e) >> 10), (this.s = (1023 & e) >> 8), (this.i = 1023 & e), (this.h = 63 & e);
+}
+
+function C(e) {
+ (this.t = (4095 & e) >> 10), (this.a = (1023 & e) >> 8), (this.c = (255 & e) >> 6);
+}
+
+function B(e) {
+ (this.s = (3072 & e) >> 10), (this.h = 1023 & e);
+}
+
+function f(e) {
+ this.h = 4095 & e;
+}
+
+function g(e) {
+ this.s = (3072 & e) >> 10;
+}
+
+function u(e) {
+ this.h = 4095 & e;
+}
+
+function w(e) {
+ (this.t = (3840 & e) >> 8), (this.s = (192 & e) >> 6), (this.i = 63 & e);
+}
+
+function G() {
+ (this.r = [0, 0, 0, 0]),
+ (this.C = 0),
+ (this.Q = []),
+ (this.k = []),
+ (this.B = []),
+ (this.f = []),
+ (this.g = []),
+ (this.u = !1),
+ (this.G = []),
+ (this.b = []),
+ (this.o = !1),
+ (this.w = null),
+ (this.U = null),
+ (this.F = []),
+ (this.R = 0),
+ (this.J = {
+ 0: s,
+ 1: i,
+ 2: h,
+ 3: a,
+ 4: c,
+ 5: n,
+ 6: e,
+ 7: o,
+ 8: r,
+ 9: Q,
+ 10: C,
+ 11: B,
+ 12: f,
+ 13: g,
+ 14: u,
+ 15: w,
+ });
+}
+
+(Q.prototype.e = function (e) {
+ switch (this.t) {
+ case 0:
+ e.f.push(e.r[this.s]);
+ break;
+ case 1:
+ e.f.push(this.i);
+ break;
+ case 2:
+ e.f.push(e.k[this.h]);
+ break;
+ case 3:
+ e.f.push(k(e.b[this.h]));
+ }
+}),
+ (C.prototype.e = function (A) {
+ switch (this.t) {
+ case 0:
+ var t = A.f.pop();
+ A.r[this.a] = A.r[this.c][t];
+ break;
+ case 1:
+ var s = A.f.pop(),
+ i = A.f.pop();
+ A.r[this.c][s] = i;
+ break;
+ case 2:
+ var h = A.f.pop();
+ A.r[this.a] = eval(h);
+ }
+ }),
+ (B.prototype.e = function (e) {
+ e.r[this.s] = k(e.b[this.h]);
+ }),
+ (f.prototype.e = function (e) {
+ e.w = this.h;
+ }),
+ (g.prototype.e = function (e) {
+ throw e.r[this.s];
+ }),
+ (u.prototype.e = function (e) {
+ const t = this,
+ n = [0];
+ e.k.forEach((e) => {
+ n.push(e);
+ });
+ const r = function (r) {
+ const i = new G();
+ return (i.k = n), (i.k[0] = r), i.v(e.G, t.h, e.b, e.F), i.r[3];
+ };
+ (r.toString = function () {
+ return '() { [native code] }';
+ }),
+ (e.r[3] = r);
+ }),
+ (w.prototype.e = function (e) {
+ switch (this.t) {
+ case 0:
+ for (var t = {}, n = 0; n < this.i; n++) {
+ const r = e.f.pop();
+ t[e.f.pop()] = r;
+ }
+ e.r[this.s] = t;
+ break;
+ case 1:
+ for (var i = [], o = 0; o < this.i; o++) {
+ i.unshift(e.f.pop());
+ }
+ e.r[this.s] = i;
+ }
+ }),
+ (G.prototype.D = function (e) {
+ for (var t = window.atob(e), n = (t.charCodeAt(0) << 8) | t.charCodeAt(1), r = [], i = 2; i < n + 2; i += 2) {
+ r.push((t.charCodeAt(i) << 8) | t.charCodeAt(i + 1));
+ }
+ this.G = r;
+ for (var o = [], a = n + 2; a < t.length; ) {
+ const c = (t.charCodeAt(a) << 8) | t.charCodeAt(a + 1),
+ u = t.slice(a + 2, a + 2 + c);
+ o.push(u), (a += c + 2);
+ }
+ this.b = o;
+ }),
+ (G.prototype.v = function (e, t, n) {
+ for (t = t || 0, n = n || [], this.C = t, 'string' === typeof e ? this.D(e) : ((this.G = e), (this.b = n)), this.o = !0, this.R = Date.now(); this.o; ) {
+ const r = this.G[this.C++];
+ if ('number' !== typeof r) {
+ break;
+ }
+ const i = Date.now();
+ if (500 < i - this.R) {
+ return;
+ }
+ this.R = i;
+ try {
+ this.e(r);
+ } catch (e) {
+ (this.U = e), this.w && (this.C = this.w);
+ }
+ }
+ }),
+ (G.prototype.e = function (e) {
+ const t = (61440 & e) >> 12;
+ new this.J[t](e).e(this);
+ }),
+ 'undefined' !== typeof window &&
+ new G().v(
+ 'AxjgB5MAnACoAJwBpAAAABAAIAKcAqgAMAq0AzRJZAZwUpwCqACQACACGAKcBKAAIAOcBagAIAQYAjAUGgKcBqFAuAc5hTSHZAZwqrAIGgA0QJEAJAAYAzAUGgOcCaFANRQ0R2QGcOKwChoANECRACQAsAuQABgDnAmgAJwMgAGcDYwFEAAzBmAGcSqwDhoANECRACQAGAKcD6AAGgKcEKFANEcYApwRoAAxB2AGcXKwEhoANECRACQAGAKcE6AAGgKcFKFANEdkBnGqsBUaADRAkQAkABgCnBagAGAGcdKwFxoANECRACQAGAKcGKAAYAZx+rAZGgA0QJEAJAAYA5waoABgBnIisBsaADRAkQAkABgCnBygABoCnB2hQDRHZAZyWrAeGgA0QJEAJAAYBJwfoAAwFGAGcoawIBoANECRACQAGAOQALAJkAAYBJwfgAlsBnK+sCEaADRAkQAkABgDkACwGpAAGAScH4AJbAZy9rAiGgA0QJEAJACwI5AAGAScH6AAkACcJKgAnCWgAJwmoACcJ4AFnA2MBRAAMw5gBnNasCgaADRAkQAkABgBEio0R5EAJAGwKSAFGACcKqAAEgM0RCQGGAYSATRFZAZzshgAtCs0QCQAGAYSAjRFZAZz1hgAtCw0QCQAEAAgB7AtIAgYAJwqoAASATRBJAkYCRIANEZkBnYqEAgaBxQBOYAoBxQEOYQ0giQKGAmQABgAnC6ABRgBGgo0UhD/MQ8zECALEAgaBxQBOYAoBxQEOYQ0gpEAJAoYARoKNFIQ/zEPkAAgChgLGgkUATmBkgAaAJwuhAUaCjdQFAg5kTSTJAsQCBoHFAE5gCgHFAQ5hDSCkQAkChgBGgo0UhD/MQ+QACAKGAsaCRQCOYGSABoAnC6EBRoKN1AUEDmRNJMkCxgFGgsUPzmPkgAaCJwvhAU0wCQFGAUaCxQGOZISPzZPkQAaCJwvhAU0wCQFGAUaCxQMOZISPzZPkQAaCJwvhAU0wCQFGAUaCxQSOZISPzZPkQAaCJwvhAU0wCQFGAkSAzRBJAlz/B4FUAAAAwUYIAAIBSITFQkTERwABi0GHxITAAAJLwMSGRsXHxMZAAk0Fw8HFh4NAwUABhU1EBceDwAENBcUEAAGNBkTGRcBAAFKAAkvHg4PKz4aEwIAAUsACDIVHB0QEQ4YAAsuAzs7AAoPKToKDgAHMx8SGQUvMQABSAALORoVGCQgERcCAxoACAU3ABEXAgMaAAsFGDcAERcCAxoUCgABSQAGOA8LGBsPAAYYLwsYGw8AAU4ABD8QHAUAAU8ABSkbCQ4BAAFMAAktCh8eDgMHCw8AAU0ADT4TGjQsGQMaFA0FHhkAFz4TGjQsGQMaFA0FHhk1NBkCHgUbGBEPAAFCABg9GgkjIAEmOgUHDQ8eFSU5DggJAwEcAwUAAUMAAUAAAUEADQEtFw0FBwtdWxQTGSAACBwrAxUPBR4ZAAkqGgUDAwMVEQ0ACC4DJD8eAx8RAAQ5GhUYAAFGAAAABjYRExELBAACWhgAAVoAQAg/PTw0NxcQPCQ5C3JZEBs9fkcnDRcUAXZia0Q4EhQgXHojMBY3MWVCNT0uDhMXcGQ7AUFPHigkQUwQFkhaAkEACjkTEQspNBMZPC0ABjkTEQsrLQ=='
+ );
+const b = function (e) {
+ return __g._encrypt(encodeURIComponent(e));
+};
+module.exports = b;
diff --git a/lib/routes/zhihu/execlib/jsencrypt.js b/lib/v2/zhihu/execlib/jsencrypt.js
similarity index 99%
rename from lib/routes/zhihu/execlib/jsencrypt.js
rename to lib/v2/zhihu/execlib/jsencrypt.js
index 73bb6da2436c61..23ccdace08a490 100644
--- a/lib/routes/zhihu/execlib/jsencrypt.js
+++ b/lib/v2/zhihu/execlib/jsencrypt.js
@@ -375,6 +375,5 @@ function G() {
const b = function (e) {
return __g._encrypt(encodeURIComponent(e));
};
-(exports.ENCRYPT_VERSION = A), (exports.default = b);
module.exports = b;
diff --git a/lib/routes/zhihu/hot.js b/lib/v2/zhihu/hot.js
similarity index 94%
rename from lib/routes/zhihu/hot.js
rename to lib/v2/zhihu/hot.js
index 819a18d660f432..d252a9bbc159c6 100644
--- a/lib/routes/zhihu/hot.js
+++ b/lib/v2/zhihu/hot.js
@@ -16,7 +16,7 @@ const titles = {
};
module.exports = async (ctx) => {
- const category = ctx.params.category || 'total';
+ const category = ctx.params.category ?? 'total';
const response = await got({
method: 'get',
diff --git a/lib/routes/zhihu/hotlist.js b/lib/v2/zhihu/hotlist.js
similarity index 88%
rename from lib/routes/zhihu/hotlist.js
rename to lib/v2/zhihu/hotlist.js
index 7a5ce1921a976b..cffd2f3b1081ba 100644
--- a/lib/routes/zhihu/hotlist.js
+++ b/lib/v2/zhihu/hotlist.js
@@ -1,5 +1,6 @@
const got = require('@/utils/got');
const utils = require('./utils');
+const { parseDate } = require('@/utils/parse-date');
module.exports = async (ctx) => {
const {
@@ -20,7 +21,7 @@ module.exports = async (ctx) => {
title: item.target.question.title,
description: `${item.target.author.name}的回答
${utils.ProcessImage(item.target.content)}`,
author: item.target.author.name,
- pubDate: new Date(item.target.updated_time * 1000).toUTCString(),
+ pubDate: parseDate(item.target.updated_time * 1000),
guid: item.target.id.toString(),
link: `https://www.zhihu.com/question/${item.target.question.id}/answer/${item.target.id}`,
};
@@ -29,7 +30,7 @@ module.exports = async (ctx) => {
title: item.target.title,
description: `${item.target.author.name}的文章
${utils.ProcessImage(item.target.content)}`,
author: item.target.author.name,
- pubDate: new Date(item.updated * 1000).toUTCString(),
+ pubDate: parseDate(item.updated * 1000),
guid: item.target.id.toString(),
link: `https://zhuanlan.zhihu.com/p/${item.target.id}`,
};
@@ -37,7 +38,6 @@ module.exports = async (ctx) => {
return {
title: '未知类型',
description: '请点击链接提交issue',
- pubDate: new Date().toUTCString(),
guid: item.target.type,
link: 'https://github.com/DIYgod/RSSHub/issues',
};
diff --git a/lib/v2/zhihu/maintainer.js b/lib/v2/zhihu/maintainer.js
new file mode 100644
index 00000000000000..11609cf77cc12d
--- /dev/null
+++ b/lib/v2/zhihu/maintainer.js
@@ -0,0 +1,19 @@
+module.exports = {
+ '/bookstore/newest': ['xyqfer'],
+ '/collection/:id/:getAll?': ['huruji', 'Colin-XKL', 'Fatpandac'],
+ '/daily': ['DHPO'],
+ '/daily/section/:sectionId': ['ccbikai'],
+ '/hot/:category?': ['nczitzk'],
+ '/hotlist': ['DIYgod'],
+ '/people/activities/:id': ['DIYgod'],
+ '/people/answers/:id': ['DIYgod', 'prnake'],
+ '/people/pins/:id': ['xyqfer'],
+ '/pin/daily': ['xyqfer'],
+ '/pin/hotlist': ['xyqfer'],
+ '/posts/:usertype/:id': ['whtsky', 'Colin-XKL'],
+ '/question/:questionId': ['xyqfer', 'hacklu'],
+ '/timeline': ['SeanChao'],
+ '/topic/:topicId': ['xyqfer'],
+ '/weekly': ['LogicJake'],
+ '/zhuanlan/:id': ['DIYgod'],
+};
diff --git a/lib/routes/zhihu/pin/daily.js b/lib/v2/zhihu/pin/daily.js
similarity index 100%
rename from lib/routes/zhihu/pin/daily.js
rename to lib/v2/zhihu/pin/daily.js
diff --git a/lib/routes/zhihu/pin/hotlist.js b/lib/v2/zhihu/pin/hotlist.js
similarity index 100%
rename from lib/routes/zhihu/pin/hotlist.js
rename to lib/v2/zhihu/pin/hotlist.js
diff --git a/lib/routes/zhihu/pin/people.js b/lib/v2/zhihu/pin/people.js
similarity index 100%
rename from lib/routes/zhihu/pin/people.js
rename to lib/v2/zhihu/pin/people.js
diff --git a/lib/routes/zhihu/pin/utils.js b/lib/v2/zhihu/pin/utils.js
similarity index 95%
rename from lib/routes/zhihu/pin/utils.js
rename to lib/v2/zhihu/pin/utils.js
index 6cc3ae04c40592..6359583244b55b 100644
--- a/lib/routes/zhihu/pin/utils.js
+++ b/lib/v2/zhihu/pin/utils.js
@@ -1,8 +1,10 @@
+const { parseDate } = require('@/utils/parse-date');
+
module.exports = {
generateData: (data) =>
data.map((item) => {
const target = item.target ? item.target : item;
- const pubDate = new Date(target.created * 1000).toUTCString();
+ const pubDate = parseDate(target.created * 1000);
const author = target.author.name;
const title = `${author}:${target.excerpt_title}`;
const link = `https://www.zhihu.com/pin/${target.id}`;
diff --git a/lib/routes/zhihu/posts.js b/lib/v2/zhihu/posts.js
similarity index 96%
rename from lib/routes/zhihu/posts.js
rename to lib/v2/zhihu/posts.js
index 6d9181bce80ebb..74ce0c1492ef5f 100644
--- a/lib/routes/zhihu/posts.js
+++ b/lib/v2/zhihu/posts.js
@@ -36,7 +36,7 @@ module.exports = async (ctx) => {
item:
list.length > 0 &&
list.map((item) => ({
- title: String(item.title),
+ title: item.title,
description: item.content,
link: item.url,
pubDate: parseDate(item.updated * 1000),
diff --git a/lib/v2/zhihu/question.js b/lib/v2/zhihu/question.js
new file mode 100644
index 00000000000000..69a1c070433fd5
--- /dev/null
+++ b/lib/v2/zhihu/question.js
@@ -0,0 +1,78 @@
+const got = require('@/utils/got');
+const utils = require('./utils');
+const md5 = require('@/utils/md5');
+const g_encrypt = require('./execlib/g_encrypt');
+const { parseDate } = require('@/utils/parse-date');
+
+module.exports = async (ctx) => {
+ const { questionId } = ctx.params;
+ // Because the API of zhihu.com has changed, we must use the value of `d_c0` (extracted from cookies) to calculate
+ // `x-zse-96`. So first get `d_c0`, then get the actual data of a ZhiHu question. In this way, we don't need to
+ // require users to set the cookie in environmental variables anymore.
+
+ // fisrt: get cookie(dc_0) from zhihu.com
+ const cookie_mes = await ctx.cache.tryGet('zhihu:cookies:d_c0', async () => {
+ const response = await got({
+ method: 'get',
+ url: `https://www.zhihu.com/question/${questionId}`,
+ headers: {
+ ...utils.header,
+ },
+ });
+
+ const cookie_org = response.headers['set-cookie'];
+ const cookie = cookie_org.toString();
+ const match = cookie.match(/d_c0=(\S+?)(?:;|$)/);
+ const cookie_mes = match && match[1];
+ if (!cookie_mes) {
+ throw Error('Failed to extract `d_c0` from cookies');
+ }
+ return cookie_mes;
+ });
+ const cookie = `d_c0=${cookie_mes}`;
+
+ // second: get real data from zhihu
+ const sort = 'updated'; // or default,created
+ const limit = 20;
+ const include =
+ 'data%5B*%5D.is_normal%2Cadmin_closed_comment%2Creward_info%2Cis_collapsed%2Cannotation_action%2Cannotation_detail%2Ccollapse_reason%2Cis_sticky%2Ccollapsed_by%2Csuggest_edit%2Ccomment_count%2Ccan_comment%2Ccontent%2Ceditable_content%2Cattachment%2Cvoteup_count%2Creshipment_settings%2Ccomment_permission%2Ccreated_time%2Cupdated_time%2Creview_info%2Crelevant_info%2Cquestion%2Cexcerpt%2Cis_labeled%2Cpaid_info%2Cpaid_info_content%2Crelationship.is_authorized%2Cis_author%2Cvoting%2Cis_thanked%2Cis_nothelp%2Cis_recognized%3Bdata%5B*%5D.mark_infos%5B*%5D.url%3Bdata%5B*%5D.author.follower_count%2Cbadge%5B*%5D.topics%3Bdata%5B*%5D.settings.table_of_content.enabled&offset=0';
+ const rootUrl = 'https://www.zhihu.com';
+ const apiPath = `/api/v4/questions/${questionId}/answers?include=${include}&limit=${limit}&sort_by=${sort}&platform=desktop`;
+ const url = rootUrl + apiPath;
+
+ // calculate x-zse-96, refer to https://github.com/srx-2000/spider_collection/issues/18
+ const f = `101_3_2.0+${apiPath}+${cookie_mes}`;
+ const xzse96 = '2.0_' + g_encrypt(md5(f));
+ const _header = { cookie, 'x-zse-96': xzse96, 'x-app-za': 'OS=Web', 'x-zse-93': '101_3_2.0' };
+
+ const response = await got({
+ method: 'get',
+ url,
+ headers: {
+ ...utils.header,
+ ..._header,
+ Referer: `https://www.zhihu.com/question/${questionId}`,
+ // Authorization: 'oauth c3cef7c66a1843f8b3a9e6a1e3160e20', // previously hard-coded in js, outdated
+ },
+ });
+
+ const listRes = response.data.data;
+
+ ctx.state.data = {
+ title: `知乎-${listRes[0].question.title}`,
+ link: `https://www.zhihu.com/question/${questionId}`,
+ item: listRes.map((item) => {
+ const title = `${item.author.name}的回答:${item.excerpt}`;
+ const description = `${item.author.name}的回答
${utils.ProcessImage(item.content)}`;
+
+ return {
+ title,
+ description,
+ author: item.author.name,
+ pubDate: parseDate(item.updated_time * 1000),
+ guid: item.id.toString(),
+ link: `https://www.zhihu.com/question/${questionId}/answer/${item.id}`,
+ };
+ }),
+ };
+};
diff --git a/lib/v2/zhihu/radar.js b/lib/v2/zhihu/radar.js
new file mode 100644
index 00000000000000..8bf6f289ba68fe
--- /dev/null
+++ b/lib/v2/zhihu/radar.js
@@ -0,0 +1,107 @@
+module.exports = {
+ 'zhihu.com': {
+ _name: '知乎',
+ www: [
+ {
+ title: '收藏夹',
+ docs: 'https://docs.rsshub.app/social-media.html#zhi-hu',
+ source: '/collection/:id',
+ target: '/zhihu/collection/:id',
+ },
+ {
+ title: '用户动态',
+ docs: 'https://docs.rsshub.app/social-media.html#zhi-hu',
+ source: '/people/:id',
+ target: '/zhihu/people/activities/:id',
+ },
+ {
+ title: '用户回答',
+ docs: 'https://docs.rsshub.app/social-media.html#zhi-hu',
+ source: '/people/:id/answers',
+ target: '/zhihu/people/answers/:id',
+ },
+ {
+ title: '用户想法',
+ docs: 'https://docs.rsshub.app/social-media.html#zhi-hu',
+ source: '/people/:id/pins',
+ target: '/zhihu/people/pins/:id',
+ },
+ {
+ title: '用户文章',
+ docs: 'https://docs.rsshub.app/social-media.html#zhi-hu',
+ source: '/:usertype/:id/posts',
+ target: '/zhihu/posts/:usertype/:id',
+ },
+
+ {
+ title: '热榜',
+ docs: 'https://docs.rsshub.app/social-media.html#zhi-hu',
+ source: '/hot',
+ target: '/zhihu/hotlist',
+ },
+ {
+ title: '想法热榜',
+ docs: 'https://docs.rsshub.app/social-media.html#zhi-hu',
+ target: '/zhihu/pin/hotlist',
+ },
+ {
+ title: '问题',
+ docs: 'https://docs.rsshub.app/social-media.html#zhi-hu',
+ source: '/question/:questionId',
+ target: '/zhihu/question/:questionId',
+ },
+ {
+ title: '话题',
+ docs: 'https://docs.rsshub.app/social-media.html#zhi-hu',
+ source: '/topic/:topicId/:type',
+ target: '/zhihu/topic/:topicId',
+ },
+ {
+ title: '新书',
+ docs: 'https://docs.rsshub.app/social-media.html#zhi-hu',
+ source: '/zhihu/bookstore/newest',
+ target: '/zhihu/pin/hotlist',
+ },
+ {
+ title: '想法-24 小时新闻汇总',
+ docs: 'https://docs.rsshub.app/social-media.html#zhi-hu',
+ source: '/pin/special/972884951192113152',
+ target: '/zhihu/pin/daily',
+ },
+ {
+ title: '书店-周刊',
+ docs: 'https://docs.rsshub.app/social-media.html#zhi-hu',
+ source: '/pub/weekly',
+ target: '/zhihu/weekly',
+ },
+ {
+ title: '专栏',
+ docs: 'https://docs.rsshub.app/social-media.html#zhi-hu',
+ source: '/column/:id',
+ target: '/zhihu/zhuanlan/:id',
+ },
+ ],
+ zhuanlan: [
+ {
+ title: '专栏',
+ docs: 'https://docs.rsshub.app/social-media.html#zhi-hu',
+ source: '/:id',
+ target: '/zhihu/zhuanlan/:id',
+ },
+ ],
+ daily: [
+ {
+ title: '日报',
+ docs: 'https://docs.rsshub.app/social-media.html#zhi-hu',
+ source: '',
+ target: '/zhihu/daily',
+ },
+ {
+ title: '日报',
+ docs: 'https://docs.rsshub.app/social-media.html#zhi-hu',
+ source: '/*tpath',
+ target: '/zhihu/daily',
+ },
+ ],
+ },
+};
diff --git a/lib/v2/zhihu/router.js b/lib/v2/zhihu/router.js
new file mode 100644
index 00000000000000..b275fed88f5d78
--- /dev/null
+++ b/lib/v2/zhihu/router.js
@@ -0,0 +1,19 @@
+module.exports = (router) => {
+ router.get('/bookstore/newest', require('./bookstore/newest'));
+ router.get('/collection/:id/:getAll?', require('./collection'));
+ router.get('/daily', require('./daily'));
+ router.get('/daily/section/:sectionId', require('./daily_section'));
+ router.get('/hot/:category?', require('./hot'));
+ router.get('/hotlist', require('./hotlist'));
+ router.get('/people/activities/:id', require('./activities'));
+ router.get('/people/answers/:id', require('./answers'));
+ router.get('/people/pins/:id', require('./pin/people'));
+ router.get('/pin/daily', require('./pin/daily'));
+ router.get('/pin/hotlist', require('./pin/hotlist'));
+ router.get('/posts/:usertype/:id', require('./posts'));
+ router.get('/question/:questionId', require('./question'));
+ router.get('/timeline', require('./timeline'));
+ router.get('/topic/:topicId', require('./topic'));
+ router.get('/weekly', require('./weekly'));
+ router.get('/zhuanlan/:id', require('./zhuanlan'));
+};
diff --git a/lib/routes/zhihu/timeline.js b/lib/v2/zhihu/timeline.js
similarity index 94%
rename from lib/routes/zhihu/timeline.js
rename to lib/v2/zhihu/timeline.js
index 3c6cc490727ed9..ed648dc19109ea 100644
--- a/lib/routes/zhihu/timeline.js
+++ b/lib/v2/zhihu/timeline.js
@@ -1,6 +1,7 @@
const got = require('@/utils/got');
const config = require('@/config').value;
const utils = require('./utils');
+const { parseDate } = require('@/utils/parse-date');
module.exports = async (ctx) => {
const cookie = config.zhihu.cookies;
@@ -59,7 +60,7 @@ module.exports = async (ctx) => {
return {
title: `${e.action_text_tpl.replace('{}', buildActors(e))}: ${getOne([e.target.title, e.target.question ? e.target.question.title : ''])}`,
description: utils.ProcessImage(getOne([e.target.content, e.target.detail, e.target.excerpt, ''])),
- pubDate: new Date(e.updated_time * 1000),
+ pubDate: parseDate(e.updated_time * 1000),
link: buildLink(e),
author: e.target.author ? e.target.author.name : '',
guid: this.link,
@@ -79,7 +80,7 @@ module.exports = async (ctx) => {
.map((e) => `
${e.title}${e.description}
`)
.join('')
: '';
- const pubDate = e.list && Array.isArray(e.list) && e.list.length > 0 ? new Date(e.list[0].updated_time * 1000) : new Date();
+ const pubDate = e.list && Array.isArray(e.list) && e.list.length > 0 ? parseDate(e.list[0].updated_time * 1000) : new Date();
const guid = `${title} ${pubDate}`;
return {
title,
diff --git a/lib/routes/zhihu/topic.js b/lib/v2/zhihu/topic.js
similarity index 100%
rename from lib/routes/zhihu/topic.js
rename to lib/v2/zhihu/topic.js
diff --git a/lib/routes/zhihu/utils.js b/lib/v2/zhihu/utils.js
similarity index 100%
rename from lib/routes/zhihu/utils.js
rename to lib/v2/zhihu/utils.js
diff --git a/lib/routes/zhihu/weekly.js b/lib/v2/zhihu/weekly.js
similarity index 83%
rename from lib/routes/zhihu/weekly.js
rename to lib/v2/zhihu/weekly.js
index 44b3fd26f123e5..572ca121056d77 100644
--- a/lib/routes/zhihu/weekly.js
+++ b/lib/v2/zhihu/weekly.js
@@ -1,12 +1,11 @@
const got = require('@/utils/got');
const cheerio = require('cheerio');
-const url = require('url');
const host = 'https://www.zhihu.com';
module.exports = async (ctx) => {
const link = 'https://www.zhihu.com/pub/weekly';
- const response = await got.get(link);
+ const response = await got(link);
const $ = cheerio.load(response.data);
const description = $('p.Weekly-description').text();
@@ -15,7 +14,7 @@ module.exports = async (ctx) => {
.map(function () {
const info = {
title: $(this).find('span.PubBookListItem-title').text(),
- link: url.resolve(host, $(this).find('a.PubBookListItem-buttonWrapper').attr('href')),
+ link: new URL($(this).find('a.PubBookListItem-buttonWrapper').attr('href'), host).href,
description: $(this).find('div.PubBookListItem-description').text(),
author: $(this).find('span.PubBookListItem-author').text(),
};
diff --git a/lib/routes/zhihu/zhuanlan.js b/lib/v2/zhihu/zhuanlan.js
similarity index 90%
rename from lib/routes/zhihu/zhuanlan.js
rename to lib/v2/zhihu/zhuanlan.js
index 907685563dab85..0e54194d401161 100644
--- a/lib/routes/zhihu/zhuanlan.js
+++ b/lib/v2/zhihu/zhuanlan.js
@@ -1,9 +1,10 @@
const got = require('@/utils/got');
const utils = require('./utils');
const cheerio = require('cheerio');
+const { parseDate } = require('@/utils/parse-date');
module.exports = async (ctx) => {
- const id = String(ctx.params.id);
+ const id = ctx.params.id;
const listRes = await got({
method: 'get',
@@ -31,7 +32,7 @@ module.exports = async (ctx) => {
url = `https://www.zhihu.com/column/${id}`;
}
- const infoRes = await got.get(url);
+ const infoRes = await got(url);
const $ = cheerio.load(infoRes.data);
const title = $('.css-zyehvu').text();
const description = $('.css-1bnklpv').text();
@@ -54,18 +55,18 @@ module.exports = async (ctx) => {
title = item.question.title;
author = item.question.author ? item.question.author.name : '';
link = `https://www.zhihu.com/question/${item.question.id}/answer/${item.id}`;
- pubDate = new Date(item.created_time * 1000);
+ pubDate = parseDate(item.created_time * 1000);
} else if (item.type === 'article') {
title = item.title;
link = item.url;
author = item.author.name;
- pubDate = new Date(item.created * 1000);
+ pubDate = parseDate(item.created * 1000);
} else if (item.type === 'zvideo') {
// 官方 api 没有提供视频类的源 url, 故返回专栏页面 url
title = item.title;
link = url;
author = item.author.name;
- pubDate = new Date(item.created_at * 1000);
+ pubDate = parseDate(item.created_at * 1000);
// 判断是否存在视频简介
if (item.description) {
description = `${item.description}
视频内容请跳转至原页面观看`;
diff --git a/now.json b/now.json
deleted file mode 100644
index 6691f392a1427b..00000000000000
--- a/now.json
+++ /dev/null
@@ -1,7 +0,0 @@
-{
- "version": 2,
- "routes": [
- { "src": "/api/.*", "dest": "/api/now.js" },
- { "src": "/.*", "dest": "/api/now.js" }
- ]
-}
diff --git a/package.json b/package.json
index c1ec8a24c63849..41b92a56d8b855 100644
--- a/package.json
+++ b/package.json
@@ -43,17 +43,16 @@
"devDependencies": {
"@napi-rs/pinyin": "1.7.0",
"@types/koa": "2.13.4",
- "@vercel/nft": "0.18.2",
+ "@vercel/nft": "0.19.0",
"@vuepress/plugin-back-to-top": "1.9.7",
"@vuepress/plugin-google-analytics": "1.9.7",
"@vuepress/plugin-pwa": "1.9.7",
"@vuepress/shared-utils": "1.9.7",
- "ci-info": "3.3.0",
"cross-env": "7.0.3",
"eslint": "8.15.0",
"eslint-config-prettier": "8.5.0",
"eslint-plugin-prettier": "4.0.0",
- "eslint-plugin-yml": "0.14.0",
+ "eslint-plugin-yml": "1.0.0",
"fs-extra": "10.1.0",
"jest": "28.1.0",
"mockdate": "3.0.5",
@@ -66,12 +65,14 @@
"remark-frontmatter": "3.0.0",
"remark-gfm": "1.0.0",
"remark-pangu": "2.2.0",
+ "remark-parse": "9.0.0",
"remark-preset-prettier": "0.5.1",
"remark-stringify": "9.0.1",
"staged-git-files": "1.3.0",
"string-width": "4.2.3",
"supertest": "6.2.3",
"tosource": "2.0.0-alpha.3",
+ "unified": "9.2.2",
"vuepress": "1.9.7",
"yorkie": "2.0.0"
},
@@ -99,8 +100,7 @@
"https-proxy-agent": "5.0.1",
"iconv-lite": "0.6.3",
"instagram-private-api": "1.45.3",
- "ioredis": "5.0.4",
- "ip": "*",
+ "ioredis": "5.0.5",
"ip-regex": "4.3.0",
"is-localhost-ip": "1.4.0",
"jsdom": "19.0.0",
@@ -122,7 +122,7 @@
"puppeteer-extra": "3.2.3",
"puppeteer-extra-plugin-stealth": "2.9.0",
"query-string": "7.1.1",
- "rand-user-agent": "1.0.62",
+ "rand-user-agent": "1.0.63",
"require-all": "3.0.0",
"rss-parser": "3.12.0",
"showdown": "2.1.0",
diff --git a/scripts/docker/minify-docker.js b/scripts/docker/minify-docker.js
index 908eb490124a22..c12274a6018df1 100644
--- a/scripts/docker/minify-docker.js
+++ b/scripts/docker/minify-docker.js
@@ -6,7 +6,7 @@ const { nodeFileTrace } = require('@vercel/nft');
const projectRoot = path.resolve(process.env.PROJECT_ROOT || path.join(__dirname, '../..'));
const resultFolder = path.join(projectRoot, 'app-minimal'); // no need to resolve, ProjectRoot is always absolute
-const files = ['lib/index.js', 'api/now.js'].map((file) => path.join(projectRoot, file));
+const files = ['lib/index.js', 'api/vercel.js'].map((file) => path.join(projectRoot, file));
(async () => {
console.log('Start analyzing, project root:', projectRoot);
diff --git a/scripts/workflow/build-radar.js b/scripts/workflow/build-radar.js
index 822b33afe5f74b..40929b803fb4af 100644
--- a/scripts/workflow/build-radar.js
+++ b/scripts/workflow/build-radar.js
@@ -1,6 +1,8 @@
const fs = require('fs');
const path = require('path');
-const target = path.join(__dirname, '../../assets/build/radar-rules.js');
+const targetJs = path.join(__dirname, '../../assets/build/radar-rules.js');
+const targetJson = path.join(__dirname, '../../assets/build/radar-rules.json');
const radar = require(path.join(__dirname, '../../lib/radar.js'));
-fs.writeFileSync(target, radar.toSource());
+fs.writeFileSync(targetJs, radar.toSource());
+fs.writeFileSync(targetJson, JSON.stringify(radar.rules, undefined, 2));
diff --git a/scripts/workflow/test-issue/call-maintainer.js b/scripts/workflow/test-issue/call-maintainer.js
new file mode 100644
index 00000000000000..4dd312660e5d39
--- /dev/null
+++ b/scripts/workflow/test-issue/call-maintainer.js
@@ -0,0 +1,176 @@
+const unified = require('unified');
+const parse = require('remark-parse');
+const got = require('got');
+
+// @TODO maybe we could use label or some other better ways to distinguish bug/feature issues
+const matchTitle = ['路由地址', 'Routes'];
+const maintainerURL = 'https://raw.githubusercontent.com/DIYgod/RSSHub/gh-pages/build/maintainer.json';
+const successTag = 'Bug Ping: Pinged';
+const parseFailTag = 'Bug Ping: Parsing Failed';
+const failTag = 'Bug Ping: Not Found';
+const v1route = 'Route: v1';
+const v2route = 'Route: v2';
+
+// DnD (do-not-disturb) usernames, add yours here to avoid being notified
+const dndUsernames = new Set([]);
+
+async function parseBodyRoutes(body, core) {
+ const ast = await unified().use(parse).parse(body);
+
+ // Is this a bug report?
+ const title = ast.children[0].children[0].value.trim();
+ core.debug(`title: ${title}`);
+ if (!matchTitle.some((ele) => ele.localeCompare(title) === 0)) {
+ return null;
+ }
+
+ let routes = ast.children[1].value.trim();
+ core.debug(`routes: ${JSON.stringify(routes)}`);
+ if (routes.localeCompare('NOROUTE') === 0) {
+ return null;
+ }
+
+ if (routes) {
+ routes = routes.split(/\r?\n/).filter((n) => n);
+ const dedup = [...new Set(routes)];
+ if (dedup.length !== routes.length) {
+ core.warning('Duplication detected.');
+ }
+ core.debug(dedup);
+ return dedup;
+ }
+
+ throw 'unable to parse the issue body: route does not exist';
+}
+
+async function getMaintainersByRoutes(routes, core) {
+ const maintainers = await got(maintainerURL).json();
+
+ return routes.map((e) => {
+ const m = maintainers[e];
+ if (m === undefined) {
+ core.warning(`Route ${e} not found`);
+ }
+
+ return m;
+ });
+}
+
+module.exports = async ({ github, context, core }) => {
+ const body = context.payload.issue.body;
+ const issue_facts = {
+ issue_number: context.issue.number,
+ owner: context.repo.owner,
+ repo: context.repo.repo,
+ };
+
+ const routes = await parseBodyRoutes(body, core).catch((e) => {
+ core.warning(e);
+ });
+
+ if (routes === null) {
+ return; // Not a bug report, or NOROUTE
+ }
+
+ if (routes === undefined) {
+ await github.rest.issues
+ .addLabels({
+ ...issue_facts,
+ labels: [parseFailTag],
+ })
+ .catch((e) => {
+ core.warning(e);
+ });
+ return;
+ }
+
+ const maintainers = await getMaintainersByRoutes(routes, core);
+
+ let successCount = 0;
+ let emptyCount = 0;
+ let failedCount = 0;
+ let comments = '##### Searching for maintainers: \n\n';
+
+ for (let i = 0; i < routes.length; i++) {
+ const route = routes[i];
+ const main = maintainers[i];
+ if (main === undefined) {
+ comments += `- \`${route}\`: **Route not found**\n`;
+ failedCount += 1;
+ continue;
+ }
+
+ if (main.length === 0) {
+ comments += `- \`${route}\`: No maintainer listed, possibly a v1 or misconfigured route\n`;
+ emptyCount += 1;
+ continue;
+ }
+
+ if (main.length > 0) {
+ const pingStr = main
+ .map((e) => {
+ if (e in dndUsernames) {
+ return `\`@${e}\``; // Wrap in an inline code block to make sure no mention will be sent
+ }
+ return `@${e}`;
+ })
+ .join(' ');
+ comments += `- \`${route}\`: ${pingStr}\n`;
+ successCount += 1;
+ }
+ }
+
+ const labels = [`Count: ${successCount}/${routes.length}`];
+
+ if (failedCount > 0) {
+ labels.push(failTag);
+ } else {
+ labels.push(successTag);
+ }
+
+ if (emptyCount > 0) {
+ labels.push(v1route);
+ }
+
+ if (successCount > 0) {
+ labels.push(v2route);
+ }
+
+ // Write labels (status, affected route count)
+ await github.rest.issues
+ .addLabels({
+ ...issue_facts,
+ labels,
+ })
+ .catch((e) => {
+ core.warning(e);
+ });
+
+ // Reply to the issue and notify the maintainers (if any)
+ await github.rest.issues
+ .createComment({
+ ...issue_facts,
+ body: `${comments}
+
+
+> To maintainers: if you are not willing to be disturbed, list your username in \`scripts/workflow/test-issue/call-maintainer.js\`. In this way, your username will be wrapped in an inline code block when tagged so you will not be notified.
+
+如果有任何路由无法匹配,issue 将会被自动关闭。如果 issue 和路由无关,请使用 \`NOROUTE\` 关键词,或者留下评论。我们会重新审核。
+If there is any route not found, the issue will be closed automatically. Please use \`NOROUTE\` for a route-irrelevant issue or leave a comment if it is a mistake.
+`,
+ })
+ .catch((e) => {
+ core.warning(e);
+ });
+
+ if (failedCount > 0) {
+ await github.rest.issues
+ .update({
+ ...issue_facts,
+ state: 'closed',
+ })
+ .catch((e) => {
+ core.warning(e);
+ });
+ }
+};
diff --git a/test/utils/parse-date.js b/test/utils/parse-date.js
index 87e170ffe257f9..682b9118518577 100644
--- a/test/utils/parse-date.js
+++ b/test/utils/parse-date.js
@@ -112,6 +112,10 @@ describe('parseRelativeDate', () => {
expect(+new Date(parseRelativeDate('Today 08:00'))).toBe(+date + 8 * hour);
});
+ it('Today, h:m a', () => {
+ expect(+new Date(parseRelativeDate('Today, 8:00 pm'))).toBe(+date + 20 * hour);
+ });
+
it('TDA H:m:s', () => {
expect(+new Date(parseRelativeDate('TDA 08:00:00'))).toBe(+date + 8 * hour);
});
diff --git a/vercel.json b/vercel.json
new file mode 100644
index 00000000000000..b2b787b45a10bd
--- /dev/null
+++ b/vercel.json
@@ -0,0 +1,6 @@
+{
+ "routes": [
+ { "src": "/api/.*", "dest": "/api/vercel.js" },
+ { "src": "/.*", "dest": "/api/vercel.js" }
+ ]
+}
diff --git a/yarn.lock b/yarn.lock
index 66426f7b715815..8a70507058ddaa 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1257,24 +1257,24 @@
"@jridgewell/sourcemap-codec" "^1.4.10"
"@jridgewell/resolve-uri@^3.0.3":
- version "3.0.6"
- resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.0.6.tgz#4ac237f4dabc8dd93330386907b97591801f7352"
- integrity sha512-R7xHtBSNm+9SyvpJkdQl+qrM3Hm2fea3Ef197M3mUug+v+yR+Rhfbs7PBtcBUVnIWJ4JcAdjvij+c8hXS9p5aw==
+ version "3.0.7"
+ resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.0.7.tgz#30cd49820a962aff48c8fffc5cd760151fca61fe"
+ integrity sha512-8cXDaBBHOr2pQ7j77Y6Vp5VDT2sIqWyWQ56TjEq4ih/a4iST3dItRe8Q9fp0rrIl9DoKhWQtUQz/YpOxLkXbNA==
"@jridgewell/set-array@^1.0.0":
- version "1.1.0"
- resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.1.0.tgz#1179863356ac8fbea64a5a4bcde93a4871012c01"
- integrity sha512-SfJxIxNVYLTsKwzB3MoOQ1yxf4w/E6MdkvTgrgAt1bfxjSrLUoHMKrDOykwN14q65waezZIdqDneUIPh4/sKxg==
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.1.1.tgz#36a6acc93987adcf0ba50c66908bd0b70de8afea"
+ integrity sha512-Ct5MqZkLGEXTVmQYbGtx9SVqD2fqwvdubdps5D3djjAkgkKwT918VNOz65pEHFaYTeWcukmJmH5SwsA9Tn2ObQ==
"@jridgewell/sourcemap-codec@^1.4.10":
- version "1.4.11"
- resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.11.tgz#771a1d8d744eeb71b6adb35808e1a6c7b9b8c8ec"
- integrity sha512-Fg32GrJo61m+VqYSdRSjRXMjQ06j8YIYfcTqndLYVAaHmroZHLJZCydsWBOTDqXS2v+mjxohBWEMfg97GXmYQg==
+ version "1.4.13"
+ resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.13.tgz#b6461fb0c2964356c469e115f504c95ad97ab88c"
+ integrity sha512-GryiOJmNcWbovBxTfZSF71V/mXbgcV3MewDe3kIMCLyIh5e7SKAeUZs+rMnJ8jkMolZ/4/VsdBmMrw3l+VdZ3w==
"@jridgewell/trace-mapping@^0.3.7", "@jridgewell/trace-mapping@^0.3.9":
- version "0.3.9"
- resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz#6534fd5933a53ba7cbf3a17615e273a0d1273ff9"
- integrity sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==
+ version "0.3.13"
+ resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.13.tgz#dcfe3e95f224c8fe97a87a5235defec999aa92ea"
+ integrity sha512-o1xbKhp9qnIAoHJSWd6KlCZfqslL4valSF81H8ImioOAxluWYWOpWkpyktY2vnt4tbrX9XYaxovq6cgowaJp2w==
dependencies:
"@jridgewell/resolve-uri" "^3.0.3"
"@jridgewell/sourcemap-codec" "^1.4.10"
@@ -1674,9 +1674,9 @@
"@types/node" "*"
"@types/content-disposition@*":
- version "0.5.4"
- resolved "https://registry.yarnpkg.com/@types/content-disposition/-/content-disposition-0.5.4.tgz#de48cf01c79c9f1560bcfd8ae43217ab028657f8"
- integrity sha512-0mPF08jn9zYI0n0Q/Pnz7C4kThdSt+6LD4amsrYDDpgBfrVWa3TcCOxKX1zkGgYniGagRv8heN2cbh+CAn+uuQ==
+ version "0.5.5"
+ resolved "https://registry.yarnpkg.com/@types/content-disposition/-/content-disposition-0.5.5.tgz#650820e95de346e1f84e30667d168c8fd25aa6e3"
+ integrity sha512-v6LCdKfK6BwcqMo+wYW05rLS12S0ZO0Fl4w1h4aaZMD7bqT3gVUns6FvLJKGZHQmYn3SX55JWGpziwJRwVgutA==
"@types/cookies@*":
version "0.7.7"
@@ -1750,9 +1750,9 @@
integrity sha512-EqX+YQxINb+MeXaIqYDASb6U6FCHbWjkj4a1CKDBks3d/QiB2+PqBLyO72vLDgAO1wUI4O+9gweRcQK11bTL/w==
"@types/http-proxy@^1.17.5":
- version "1.17.8"
- resolved "https://registry.yarnpkg.com/@types/http-proxy/-/http-proxy-1.17.8.tgz#968c66903e7e42b483608030ee85800f22d03f55"
- integrity sha512-5kPLG5BKpWYkw/LVOGWpiq3nEVqxiN32rTgI53Sk12/xHFQ2rG3ehI9IO+O3W2QoKeyB92dJkoka8SUm6BX1pA==
+ version "1.17.9"
+ resolved "https://registry.yarnpkg.com/@types/http-proxy/-/http-proxy-1.17.9.tgz#7f0e7931343761efde1e2bf48c40f02f3f75705a"
+ integrity sha512-QsbSjA/fSk7xB+UXlCT3wHBy5ai9wOcNDWwZAtud+jXhwOM3l+EYZh8Lng4+/6n8uar0J7xILzqftJdJ/Wdfkw==
dependencies:
"@types/node" "*"
@@ -1861,14 +1861,14 @@
integrity sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==
"@types/node@*":
- version "17.0.31"
- resolved "https://registry.yarnpkg.com/@types/node/-/node-17.0.31.tgz#a5bb84ecfa27eec5e1c802c6bbf8139bdb163a5d"
- integrity sha512-AR0x5HbXGqkEx9CadRH3EBYx/VkiUgZIhP4wvPn/+5KIsgpNoyFaRlVe0Zlx9gRtg8fA06a9tskE2MSN7TcG4Q==
+ version "17.0.33"
+ resolved "https://registry.yarnpkg.com/@types/node/-/node-17.0.33.tgz#3c1879b276dc63e73030bb91165e62a4509cd506"
+ integrity sha512-miWq2m2FiQZmaHfdZNcbpp9PuXg34W5JZ5CrJ/BaS70VuhoJENBEQybeiYSaPBRNq6KQGnjfEnc/F3PN++D+XQ==
"@types/prettier@^2.1.5":
- version "2.6.0"
- resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-2.6.0.tgz#efcbd41937f9ae7434c714ab698604822d890759"
- integrity sha512-G/AdOadiZhnJp0jXCaBQU449W2h716OW/EoXeYkCytxKL06X1WCXB4DZpp8TpZ8eyIJVS1cw4lrlkkSYU21cDw==
+ version "2.6.1"
+ resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-2.6.1.tgz#76e72d8a775eef7ce649c63c8acae1a0824bbaed"
+ integrity sha512-XFjFHmaLVifrAKaZ+EKghFHtHSUonyw8P2Qmy2/+osBnrKbH9UYtlK10zg8/kCt47MFilll/DEDKy3DHfJ0URw==
"@types/puppeteer@*":
version "5.4.6"
@@ -2008,10 +2008,10 @@
dependencies:
"@types/node" "*"
-"@vercel/nft@0.18.2":
- version "0.18.2"
- resolved "https://registry.yarnpkg.com/@vercel/nft/-/nft-0.18.2.tgz#46ab17e1d631220bfc21c8fe299d10e36514e897"
- integrity sha512-Oxy4y5JDh7CMbaxEGjKKzHcnQ1gRQqtfp+x3xvOmZYixXHwaD2RMJDTzaPz0b2B3pgVbbPOHY87wffJPFDaoFg==
+"@vercel/nft@0.19.0":
+ version "0.19.0"
+ resolved "https://registry.yarnpkg.com/@vercel/nft/-/nft-0.19.0.tgz#56f2a17e0685b5c052158aafec3a9f31552de5b4"
+ integrity sha512-diHIP3/OHq/4wSkS4JJ7LqY6NAQOpCr83vpNZuKqx2PV7zrhwUH8CZ9QCu0SHkZh3LYaV0zcbGusVxTNw3DMvA==
dependencies:
"@mapbox/node-pre-gyp" "^1.0.5"
acorn "^8.6.0"
@@ -3628,9 +3628,9 @@ caniuse-api@^3.0.0:
lodash.uniq "^4.5.0"
caniuse-lite@^1.0.0, caniuse-lite@^1.0.30001109, caniuse-lite@^1.0.30001332:
- version "1.0.30001335"
- resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001335.tgz#899254a0b70579e5a957c32dced79f0727c61f2a"
- integrity sha512-ddP1Tgm7z2iIxu6QTtbZUv6HJxSaV/PZeSrWFZtbY4JZ69tOeNhBCl3HyRQgeNZKE5AOn1kpV7fhljigy0Ty3w==
+ version "1.0.30001340"
+ resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001340.tgz#029a2f8bfc025d4820fafbfaa6259fd7778340c7"
+ integrity sha512-jUNz+a9blQTQVu4uFcn17uAD8IDizPzQkIKh3LCJfg9BkyIqExYYdyc/ZSlWUSKb8iYiXxKsxbv4zYSvkqjrxw==
caseless@~0.12.0:
version "0.12.0"
@@ -3810,11 +3810,6 @@ chrono-node@2.3.8:
dependencies:
dayjs "^1.10.0"
-ci-info@3.3.0, ci-info@^3.1.1, ci-info@^3.2.0:
- version "3.3.0"
- resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-3.3.0.tgz#b4ed1fb6818dea4803a55c623041f9165d2066b2"
- integrity sha512-riT/3vI5YpVH6/qomlDnJow6TBee2PBKSEpx3O32EGPYbWGIRsIlGRms3Sm74wYE1JMo8RnO04Hb12+v1J5ICw==
-
ci-info@^1.5.0:
version "1.6.0"
resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-1.6.0.tgz#2ca20dbb9ceb32d4524a683303313f0304b1e497"
@@ -3825,6 +3820,11 @@ ci-info@^2.0.0:
resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-2.0.0.tgz#67a9e964be31a51e15e5010d58e6f12834002f46"
integrity sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==
+ci-info@^3.1.1, ci-info@^3.2.0:
+ version "3.3.1"
+ resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-3.3.1.tgz#58331f6f472a25fe3a50a351ae3052936c2c7f32"
+ integrity sha512-SXgeMX9VwDe7iFFaEWkA5AstuER9YKqy4EhHqr4DVqkwmD9rpVimkMKWHdjn30Ja45txyjhSn63lVX69eVCckg==
+
cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3:
version "1.0.4"
resolved "https://registry.yarnpkg.com/cipher-base/-/cipher-base-1.0.4.tgz#8760e4ecc272f4c363532f926d874aae2c1397de"
@@ -4052,10 +4052,10 @@ component-emitter@^1.2.0, component-emitter@^1.2.1, component-emitter@^1.3.0:
resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.3.0.tgz#16e4070fba8ae29b679f2215853ee181ab2eabc0"
integrity sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==
-compress-brotli@^1.3.6:
- version "1.3.6"
- resolved "https://registry.yarnpkg.com/compress-brotli/-/compress-brotli-1.3.6.tgz#64bd6f21f4f3e9841dbac392f4c29218caf5e9d9"
- integrity sha512-au99/GqZtUtiCBliqLFbWlhnCxn+XSYjwZ77q6mKN4La4qOXDoLVPZ50iXr0WmAyMxl8yqoq3Yq4OeQNPPkyeQ==
+compress-brotli@^1.3.8:
+ version "1.3.8"
+ resolved "https://registry.yarnpkg.com/compress-brotli/-/compress-brotli-1.3.8.tgz#0c0a60c97a989145314ec381e84e26682e7b38db"
+ integrity sha512-lVcQsjhxhIXsuupfy9fmZUFtAIdBmXA7EGY6GBdgZ++qkM9zG4YFT8iU7FoBxzryNDMOpD1HIFHUSX4D87oqhQ==
dependencies:
"@types/json-buffer" "~3.0.0"
json-buffer "~3.0.1"
@@ -4222,9 +4222,9 @@ copy-webpack-plugin@^5.0.2:
webpack-log "^2.0.0"
core-js-compat@^3.21.0, core-js-compat@^3.22.1, core-js-compat@^3.6.5:
- version "3.22.3"
- resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.22.3.tgz#9b10d786052d042bc97ee8df9c0d1fb6a49c2005"
- integrity sha512-wliMbvPI2idgFWpFe7UEyHMvu6HWgW8WA+HnDRtgzoSDYvXFMpoGX1H3tPDDXrcfUSyXafCLDd7hOeMQHEZxGw==
+ version "3.22.5"
+ resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.22.5.tgz#7fffa1d20cb18405bd22756ca1353c6f1a0e8614"
+ integrity sha512-rEF75n3QtInrYICvJjrAgV03HwKiYvtKHdPtaba1KucG+cNZ4NJnH9isqt979e67KZlhpbCOTwnsvnIr+CVeOg==
dependencies:
browserslist "^4.20.3"
semver "7.0.0"
@@ -4235,9 +4235,9 @@ core-js@^2.4.0, core-js@^2.6.12:
integrity sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ==
core-js@^3.6.4, core-js@^3.6.5:
- version "3.22.3"
- resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.22.3.tgz#498c41d997654cb00e81c7a54b44f0ab21ab01d5"
- integrity sha512-1t+2a/d2lppW1gkLXx3pKPVGbBdxXAkqztvWb1EJ8oF8O2gIGiytzflNiFEehYwVK/t2ryUsGBoOFFvNx95mbg==
+ version "3.22.5"
+ resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.22.5.tgz#a5f5a58e663d5c0ebb4e680cd7be37536fb2a9cf"
+ integrity sha512-VP/xYuvJ0MJWRAobcmQ8F2H6Bsn+s7zqAAjFaHGBMc5AQm7zaelhD1LGduFn2EehEcQcU+br6t+fwbpQ5d1ZWA==
core-util-is@1.0.2:
version "1.0.2"
@@ -4752,7 +4752,7 @@ defer-to-connect@^2.0.0:
resolved "https://registry.yarnpkg.com/defer-to-connect/-/defer-to-connect-2.0.1.tgz#8016bdb4143e4632b77a3449c6236277de520587"
integrity sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==
-define-properties@^1.1.2, define-properties@^1.1.3:
+define-properties@^1.1.2, define-properties@^1.1.3, define-properties@^1.1.4:
version "1.1.4"
resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.4.tgz#0b14d7bd7fbeb2f3572c3a7eda80ea5d57fb05b1"
integrity sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA==
@@ -5110,9 +5110,9 @@ ee-first@1.1.1:
integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=
electron-to-chromium@^1.4.118:
- version "1.4.129"
- resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.129.tgz#c675793885721beefff99da50f57c6525c2cd238"
- integrity sha512-GgtN6bsDtHdtXJtlMYZWGB/uOyjZWjmRDumXTas7dGBaB9zUyCjzHet1DY2KhyHN8R0GLbzZWqm4efeddqqyRQ==
+ version "1.4.137"
+ resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.137.tgz#186180a45617283f1c012284458510cd99d6787f"
+ integrity sha512-0Rcpald12O11BUogJagX3HsCN3FE83DSqWjgXoHo5a72KUKMSfI39XBgJpgNNxS9fuGzytaFjE06kZkiVFy2qA==
ellipsize@0.1.0:
version "0.1.0"
@@ -5302,17 +5302,19 @@ error-inject@^1.0.0:
resolved "https://registry.yarnpkg.com/error-inject/-/error-inject-1.0.0.tgz#e2b3d91b54aed672f309d950d154850fa11d4f37"
integrity sha1-4rPZG1Su1nLzCdlQ0VSFD6EdTzc=
-es-abstract@^1.17.2, es-abstract@^1.19.1:
- version "1.19.5"
- resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.19.5.tgz#a2cb01eb87f724e815b278b0dd0d00f36ca9a7f1"
- integrity sha512-Aa2G2+Rd3b6kxEUKTF4TaW67czBLyAv3z7VOhYRU50YBx+bbsYZ9xQP4lMNazePuFlybXI0V4MruPos7qUo5fA==
+es-abstract@^1.17.2, es-abstract@^1.19.0, es-abstract@^1.19.1, es-abstract@^1.19.5:
+ version "1.20.0"
+ resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.20.0.tgz#b2d526489cceca004588296334726329e0a6bfb6"
+ integrity sha512-URbD8tgRthKD3YcC39vbvSDrX23upXnPcnGAjQfgxXF5ID75YcENawc9ZX/9iTP9ptUyfCLIxTTuMYoRfiOVKA==
dependencies:
call-bind "^1.0.2"
es-to-primitive "^1.2.1"
function-bind "^1.1.1"
+ function.prototype.name "^1.1.5"
get-intrinsic "^1.1.1"
get-symbol-description "^1.0.0"
has "^1.0.3"
+ has-property-descriptors "^1.0.0"
has-symbols "^1.0.3"
internal-slot "^1.0.3"
is-callable "^1.2.4"
@@ -5324,9 +5326,10 @@ es-abstract@^1.17.2, es-abstract@^1.19.1:
object-inspect "^1.12.0"
object-keys "^1.1.1"
object.assign "^4.1.2"
- string.prototype.trimend "^1.0.4"
- string.prototype.trimstart "^1.0.4"
- unbox-primitive "^1.0.1"
+ regexp.prototype.flags "^1.4.1"
+ string.prototype.trimend "^1.0.5"
+ string.prototype.trimstart "^1.0.5"
+ unbox-primitive "^1.0.2"
es-to-primitive@^1.2.1:
version "1.2.1"
@@ -5516,15 +5519,15 @@ eslint-plugin-prettier@4.0.0:
dependencies:
prettier-linter-helpers "^1.0.0"
-eslint-plugin-yml@0.14.0:
- version "0.14.0"
- resolved "https://registry.yarnpkg.com/eslint-plugin-yml/-/eslint-plugin-yml-0.14.0.tgz#110e1126ebe983d830e4ab8754e437f2279d2b72"
- integrity sha512-+0+bBV/07txENbxfrHF9olGoLCHez64vmnOmjWOoLwmXOwfdaSRleBSPIi4nWQs7WwX8lm/fSLadOjbVEcsXQQ==
+eslint-plugin-yml@1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/eslint-plugin-yml/-/eslint-plugin-yml-1.0.0.tgz#9a1bd81176d2d70201b8db048533c0f1faebb35e"
+ integrity sha512-0RVoUFh5vpznE2DIP5agSpWO/nU8GgAWwoTAHWopU2X+1SCB5ykHU6DwS0GrZ5Hvejtk6CcADQllpQQJB4C5QA==
dependencies:
debug "^4.3.2"
lodash "^4.17.21"
natural-compare "^1.4.0"
- yaml-eslint-parser "^0.5.0"
+ yaml-eslint-parser "^1.0.0"
eslint-scope@^4.0.3:
version "4.0.3"
@@ -5679,9 +5682,9 @@ events@^3.0.0:
integrity sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==
eventsource@^1.1.0:
- version "1.1.0"
- resolved "https://registry.yarnpkg.com/eventsource/-/eventsource-1.1.0.tgz#00e8ca7c92109e94b0ddf32dac677d841028cfaf"
- integrity sha512-VSJjT5oCNrFvCS6igjzPAt5hBzQ2qPBFIbJ03zLI9SE0mxwZpMw6BfJrbFHm1a141AavMEB8JHmBhWAd66PfCg==
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/eventsource/-/eventsource-1.1.1.tgz#4544a35a57d7120fba4fa4c86cb4023b2c09df2f"
+ integrity sha512-qV5ZC0h7jYIAOhArFJgSfdyz6rALJyb270714o7ZtNnw2WSJ+eexhKtE0O8LYPRsHZHf2osHKZBxGPvm3kPkCA==
dependencies:
original "^1.0.0"
@@ -6102,9 +6105,9 @@ fn.name@1.x.x:
integrity sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw==
follow-redirects@^1.0.0:
- version "1.14.9"
- resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.14.9.tgz#dd4ea157de7bfaf9ea9b3fbd85aa16951f78d8d7"
- integrity sha512-MQDfihBQYMcyy5dhRDJUHcw7lb2Pv/TuE6xP1vyraLukNDHKbDxDNaOE3NbCAdKQApno+GPRyo1YAp89yCjK4w==
+ version "1.15.0"
+ resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.0.tgz#06441868281c86d0dda4ad8bdaead2d02dca89d4"
+ integrity sha512-aExlJShTV4qOUOL7yF1U5tvLCB0xQuudbf6toyYA0E/acBNw71mvjFTnLaRp50aQaYocMR0a/RMMBIHeZnGyjQ==
for-in@^0.1.3:
version "0.1.8"
@@ -6124,9 +6127,9 @@ for-own@^0.1.3:
for-in "^1.0.1"
foreach@^2.0.5:
- version "2.0.5"
- resolved "https://registry.yarnpkg.com/foreach/-/foreach-2.0.5.tgz#0bee005018aeb260d0a3af3ae658dd0136ec1b99"
- integrity sha1-C+4AUBiusmDQo6865ljdATbsG5k=
+ version "2.0.6"
+ resolved "https://registry.yarnpkg.com/foreach/-/foreach-2.0.6.tgz#87bcc8a1a0e74000ff2bf9802110708cfb02eb6e"
+ integrity sha512-k6GAGDyqLe9JaebCsFCoudPPWfihKu8pylYXRlqP1J7ms39iPoTtk2fviNglIeQEwdh0bQeKJ01ZPyuyQvKzwg==
forever-agent@~0.6.1:
version "0.6.1"
@@ -6315,6 +6318,16 @@ function-bind@^1.1.1:
resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d"
integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==
+function.prototype.name@^1.1.5:
+ version "1.1.5"
+ resolved "https://registry.yarnpkg.com/function.prototype.name/-/function.prototype.name-1.1.5.tgz#cce0505fe1ffb80503e6f9e46cc64e46a12a9621"
+ integrity sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA==
+ dependencies:
+ call-bind "^1.0.2"
+ define-properties "^1.1.3"
+ es-abstract "^1.19.0"
+ functions-have-names "^1.2.2"
+
functional-red-black-tree@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327"
@@ -6539,9 +6552,9 @@ globals@^11.1.0:
integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==
globals@^13.6.0, globals@^13.9.0:
- version "13.13.0"
- resolved "https://registry.yarnpkg.com/globals/-/globals-13.13.0.tgz#ac32261060d8070e2719dd6998406e27d2b5727b"
- integrity sha512-EQ7Q18AJlPwp3vUDL4mKA0KXrXyNIQyWon6T6XQiBQF0XHvRsiCSrWmmeATpUzdJN2HhWZU6Pdl0a9zdep5p6A==
+ version "13.15.0"
+ resolved "https://registry.yarnpkg.com/globals/-/globals-13.15.0.tgz#38113218c907d2f7e98658af246cef8b77e90bac"
+ integrity sha512-bpzcOlgDhMG070Av0Vy5Owklpv1I6+j96GhUI7Rh7IzDCKLzboflLrrfqMu8NquDbiR4EOQk7XzJwqVJxicxog==
dependencies:
type-fest "^0.20.2"
@@ -7411,10 +7424,10 @@ interpret@^1.0.0:
resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.4.0.tgz#665ab8bc4da27a774a40584e812e3e0fa45b1a1e"
integrity sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==
-ioredis@5.0.4:
- version "5.0.4"
- resolved "https://registry.yarnpkg.com/ioredis/-/ioredis-5.0.4.tgz#0d4abfd818adfc5ef5029fddac4b8f503a1433b7"
- integrity sha512-qFJw3MnPNsJF1lcIOP3vztbsasOXK3nDdNAgjQj7t7/Bn/w10PGchTOpqylQNxjzPbLoYDu34LjeJtSWiKBntQ==
+ioredis@5.0.5:
+ version "5.0.5"
+ resolved "https://registry.yarnpkg.com/ioredis/-/ioredis-5.0.5.tgz#94e51284631b30e15b359cd17de59c48945230fb"
+ integrity sha512-H+u9YB/cBckDO5lt5+S34gGN1EuIBjjaXk31LivQWfX3G1cqZPYCiwF9qCOkqK2NsKVk+saoUN+fLBz5tc2gFw==
dependencies:
"@ioredis/commands" "^1.1.1"
cluster-key-slot "^1.1.0"
@@ -7436,10 +7449,10 @@ ip-regex@^2.1.0:
resolved "https://registry.yarnpkg.com/ip-regex/-/ip-regex-2.1.0.tgz#fa78bf5d2e6913c911ce9f819ee5146bb6d844e9"
integrity sha1-+ni/XS5pE8kRzp+BnuUUa7bYROk=
-ip@*, ip@^1.1.0, ip@^1.1.5:
- version "1.1.5"
- resolved "https://registry.yarnpkg.com/ip/-/ip-1.1.5.tgz#bdded70114290828c0a039e72ef25f5aaec4354a"
- integrity sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=
+ip@^1.1.0, ip@^1.1.5:
+ version "1.1.8"
+ resolved "https://registry.yarnpkg.com/ip/-/ip-1.1.8.tgz#ae05948f6b075435ed3307acce04629da8cdbf48"
+ integrity sha512-PuExPYUiu6qMBQb4l06ecm6T6ujzhmh+MeJcW9wa89PoAz5pvd4zPgN5WJV104mb6S2T1AwNIAaB70JNrLQWhg==
ipaddr.js@1.9.1, ipaddr.js@^1.9.0:
version "1.9.1"
@@ -8582,11 +8595,11 @@ keyv@^3.0.0:
json-buffer "3.0.0"
keyv@^4.0.0:
- version "4.2.2"
- resolved "https://registry.yarnpkg.com/keyv/-/keyv-4.2.2.tgz#4b6f602c0228ef4d8214c03c520bef469ed6b768"
- integrity sha512-uYS0vKTlBIjNCAUqrjlxmruxOEiZxZIHXyp32sdcGmP+ukFrmWUnE//RcPXJH3Vxrni1H2gsQbjHE0bH7MtMQQ==
+ version "4.2.8"
+ resolved "https://registry.yarnpkg.com/keyv/-/keyv-4.2.8.tgz#6c91189fe6134d8a526cb360566693c095fcfb60"
+ integrity sha512-IZZo6krhHWPhgsP5mBkEdPopVPN/stgCnBVuqi6dda/Nm5mDTOSVTrFMkWqlJsDum+B0YSe887tNxdjDWkO7aQ==
dependencies:
- compress-brotli "^1.3.6"
+ compress-brotli "^1.3.8"
json-buffer "3.0.1"
killable@^1.0.1:
@@ -10537,9 +10550,9 @@ path-to-regexp@0.1.7:
integrity sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=
path-to-regexp@^6.1.0:
- version "6.2.0"
- resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-6.2.0.tgz#f7b3803336104c346889adece614669230645f38"
- integrity sha512-f66KywYG6+43afgE/8j/GoiNyygk/bnoCbps++3ErRKsIYkGGupyv07R2Ok5m9i67Iqc+T2g1eAUGUPzWhYTyg==
+ version "6.2.1"
+ resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-6.2.1.tgz#d54934d6798eb9e5ef14e7af7962c945906918e5"
+ integrity sha512-JLyh7xT1kizaEvcaXOQwOc2/Yhw6KZOvPf1S8401UyLk86CU79LN3vl7ztXGm/pZ+YjoyAJ4rxmHwbkBXJX+yw==
path-type@^3.0.0:
version "3.0.0"
@@ -11409,10 +11422,10 @@ ramda@^0.26.1:
resolved "https://registry.yarnpkg.com/ramda/-/ramda-0.26.1.tgz#8d41351eb8111c55353617fc3bbffad8e4d35d06"
integrity sha512-hLWjpy7EnsDBb0p+Z3B7rPi3GDeRG5ZtiI33kJhTt+ORCd38AbAIjB/9zRIUoeTbE/AVX5ZkU7m6bznsvrf8eQ==
-rand-user-agent@1.0.62:
- version "1.0.62"
- resolved "https://registry.yarnpkg.com/rand-user-agent/-/rand-user-agent-1.0.62.tgz#50b648c7df1c26e1b62724506570d547c2c8824b"
- integrity sha512-gtgj9qp+Unim6N5vDvHY1UdSQQhAT9JmGHXQXVrUDKnUc2Hf8uM/O1X/WwiX1BJTXOUmMsvEHJLs3Of9Yzko3Q==
+rand-user-agent@1.0.63:
+ version "1.0.63"
+ resolved "https://registry.yarnpkg.com/rand-user-agent/-/rand-user-agent-1.0.63.tgz#eadb7ed4b7a1d0ffb07bca10d40c60346961e205"
+ integrity sha512-asYTDQa/bGvHKqm4XGHYnQZtdMAzE/X/C3roQdJzM3ShfykDx6jCrv12BIR8bF1okhb+6Va7x6UABA/j04Pm4g==
randexp@0.4.6:
version "0.4.6"
@@ -11583,7 +11596,7 @@ regex-not@^1.0.0, regex-not@^1.0.2:
extend-shallow "^3.0.2"
safe-regex "^1.1.0"
-regexp.prototype.flags@^1.2.0:
+regexp.prototype.flags@^1.2.0, regexp.prototype.flags@^1.4.1:
version "1.4.3"
resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz#87cab30f80f66660181a3bb7bf5981a872b367ac"
integrity sha512-fjggEOO3slI6Wvgjwflkc4NFRCTZAu5CnNfBd5qOMYhWdn67nJBBu34/TkD++eeFmd8C9r9jfXJ27+nSiRkSUA==
@@ -11670,7 +11683,7 @@ remark-pangu@2.2.0:
unist-util-is "^4.0.2"
unist-util-visit "^2.0.2"
-remark-parse@^9.0.0:
+remark-parse@9.0.0, remark-parse@^9.0.0:
version "9.0.0"
resolved "https://registry.yarnpkg.com/remark-parse/-/remark-parse-9.0.0.tgz#4d20a299665880e4f4af5d90b7c7b8a935853640"
integrity sha512-geKatMwSzEXKHuzBNU1z676sGcDcFoChMK38TgdHJNAYfFtsfHDQG7MoJAjs6sgYMqyLduCYWDIWZIxiPeafEw==
@@ -12652,21 +12665,23 @@ string-width@^3.0.0, string-width@^3.1.0:
is-fullwidth-code-point "^2.0.0"
strip-ansi "^5.1.0"
-string.prototype.trimend@^1.0.4:
- version "1.0.4"
- resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz#e75ae90c2942c63504686c18b287b4a0b1a45f80"
- integrity sha512-y9xCjw1P23Awk8EvTpcyL2NIr1j7wJ39f+k6lvRnSMz+mz9CGz9NYPelDk42kOz6+ql8xjfK8oYzy3jAP5QU5A==
+string.prototype.trimend@^1.0.5:
+ version "1.0.5"
+ resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.5.tgz#914a65baaab25fbdd4ee291ca7dde57e869cb8d0"
+ integrity sha512-I7RGvmjV4pJ7O3kdf+LXFpVfdNOxtCW/2C8f6jNiW4+PQchwxkCDzlk1/7p+Wl4bqFIZeF47qAHXLuHHWKAxog==
dependencies:
call-bind "^1.0.2"
- define-properties "^1.1.3"
+ define-properties "^1.1.4"
+ es-abstract "^1.19.5"
-string.prototype.trimstart@^1.0.4:
- version "1.0.4"
- resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz#b36399af4ab2999b4c9c648bd7a3fb2bb26feeed"
- integrity sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw==
+string.prototype.trimstart@^1.0.5:
+ version "1.0.5"
+ resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.5.tgz#5466d93ba58cfa2134839f81d7f42437e8c01fef"
+ integrity sha512-THx16TJCGlsN0o6dl2o6ncWUsdgnLRSA23rRE5pyGBw/mLr3Ej/R2LaqCtgP8VNMGZsvMWnf9ooZPyY2bHvUFg==
dependencies:
call-bind "^1.0.2"
- define-properties "^1.1.3"
+ define-properties "^1.1.4"
+ es-abstract "^1.19.5"
string_decoder@^1.0.0, string_decoder@^1.1.1:
version "1.3.0"
@@ -13388,7 +13403,7 @@ uglify-js@3.4.x:
commander "~2.19.0"
source-map "~0.6.1"
-unbox-primitive@^1.0.1:
+unbox-primitive@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/unbox-primitive/-/unbox-primitive-1.0.2.tgz#29032021057d5e6cdbd08c5129c226dff8ed6f9e"
integrity sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==
@@ -13434,7 +13449,7 @@ unicode-property-aliases-ecmascript@^2.0.0:
resolved "https://registry.yarnpkg.com/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.0.0.tgz#0a36cb9a585c4f6abd51ad1deddb285c165297c8"
integrity sha512-5Zfuy9q/DFr4tfO7ZPeVXb1aPoeQSdeFMLpYuFebehDAhbuevLs5yxSZmIFN1tP5F9Wl4IpJrYojg85/zgyZHQ==
-unified@^9.1.0:
+unified@9.2.2, unified@^9.1.0:
version "9.2.2"
resolved "https://registry.yarnpkg.com/unified/-/unified-9.2.2.tgz#67649a1abfc3ab85d2969502902775eb03146975"
integrity sha512-Sg7j110mtefBD+qunSLO1lqOEKdrwBFBrR6Qd8f4uwkhWNlbkaqwHse6e7QvD3AP/MNoJdEDLaf8OxYyoWgorQ==
@@ -14536,19 +14551,19 @@ yallist@^4.0.0:
resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72"
integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==
-yaml-eslint-parser@^0.5.0:
- version "0.5.0"
- resolved "https://registry.yarnpkg.com/yaml-eslint-parser/-/yaml-eslint-parser-0.5.0.tgz#01d4e4d992a820769ea85ef5fd526dfc20ebc6f5"
- integrity sha512-nJeyLA3YHAzhBTZbRAbu3W6xrSCucyxExmA+ZDtEdUFpGllxAZpto2Zxo2IG0r0eiuEiBM4e+wiAdxTziTq94g==
+yaml-eslint-parser@^1.0.0:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/yaml-eslint-parser/-/yaml-eslint-parser-1.0.1.tgz#f1f867dc2e4c5101a3b60533b1cd181bed8cca3e"
+ integrity sha512-acQYWneSXwnJgPQbTyJvDxWx9zlJ/rq267p/zzQMSCE7ljJxQ8elefsQase1gEIJMo+pIqmLRczoo7fPt6VbKQ==
dependencies:
eslint-visitor-keys "^3.0.0"
lodash "^4.17.21"
- yaml "^1.10.2"
+ yaml "^2.0.0"
-yaml@^1.10.2:
- version "1.10.2"
- resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.2.tgz#2301c5ffbf12b467de8da2333a459e29e7920e4b"
- integrity sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==
+yaml@^2.0.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.1.0.tgz#96ba62ff4dd990c0eb16bd96c6254a085d288b80"
+ integrity sha512-OuAINfTsoJrY5H7CBWnKZhX6nZciXBydrMtTHr1dC4nP40X5jyTIVlogZHxSlVZM8zSgXRfgZGsaHF4+pV+JRw==
yargs-parser@^13.1.2:
version "13.1.2"
@@ -14588,9 +14603,9 @@ yargs@^13.3.2:
yargs-parser "^13.1.2"
yargs@^17.3.1:
- version "17.4.1"
- resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.4.1.tgz#ebe23284207bb75cee7c408c33e722bfb27b5284"
- integrity sha512-WSZD9jgobAg3ZKuCQZSa3g9QOJeCCqLoLAykiWgmXnDo9EPnn4RPf5qVTtzgOx66o6/oqhcA5tHtJXpG8pMt3g==
+ version "17.5.0"
+ resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.5.0.tgz#2706c5431f8c119002a2b106fc9f58b9bb9097a3"
+ integrity sha512-3sLxVhbAB5OC8qvVRebCLWuouhwh/rswsiDYx3WGxajUk/l4G20SKfrKKFeNIHboUFt2JFgv2yfn+5cgOr/t5A==
dependencies:
cliui "^7.0.2"
escalade "^3.1.1"
From 753ae31fa966082d94017f94018266bef2e4ed35 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Thu, 2 Nov 2023 21:28:14 +0000
Subject: [PATCH 2/2] chore(deps-dev): bump @vuepress/plugin-google-analytics
Bumps [@vuepress/plugin-google-analytics](https://github.com/vuejs/vuepress/tree/HEAD/packages/@vuepress/plugin-google-analytics) from 1.9.7 to 1.9.10.
- [Release notes](https://github.com/vuejs/vuepress/releases)
- [Changelog](https://github.com/vuejs/vuepress/blob/master/CHANGELOG.md)
- [Commits](https://github.com/vuejs/vuepress/commits/v1.9.10/packages/@vuepress/plugin-google-analytics)
---
updated-dependencies:
- dependency-name: "@vuepress/plugin-google-analytics"
dependency-type: direct:development
update-type: version-update:semver-patch
...
Signed-off-by: dependabot[bot]
---
package.json | 2 +-
yarn.lock | 19 ++++++++++++++-----
2 files changed, 15 insertions(+), 6 deletions(-)
diff --git a/package.json b/package.json
index 41b92a56d8b855..0226350ba5dd31 100644
--- a/package.json
+++ b/package.json
@@ -45,7 +45,7 @@
"@types/koa": "2.13.4",
"@vercel/nft": "0.19.0",
"@vuepress/plugin-back-to-top": "1.9.7",
- "@vuepress/plugin-google-analytics": "1.9.7",
+ "@vuepress/plugin-google-analytics": "1.9.10",
"@vuepress/plugin-pwa": "1.9.7",
"@vuepress/shared-utils": "1.9.7",
"cross-env": "7.0.3",
diff --git a/yarn.lock b/yarn.lock
index 8a70507058ddaa..c7bea2905a3e64 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -2248,12 +2248,12 @@
"@vuepress/types" "1.9.7"
lodash.debounce "^4.0.8"
-"@vuepress/plugin-google-analytics@1.9.7":
- version "1.9.7"
- resolved "https://registry.yarnpkg.com/@vuepress/plugin-google-analytics/-/plugin-google-analytics-1.9.7.tgz#0162e7bb28686422298c04a12f2e7727a2708d90"
- integrity sha512-ZpsYrk23JdwbcJo9xArVcdqYHt5VyTX9UN9bLqNrLJRgRTV0X2jKUkM63dlKTJMpBf+0K1PQMJbGBXgOO7Yh0Q==
+"@vuepress/plugin-google-analytics@1.9.10":
+ version "1.9.10"
+ resolved "https://registry.yarnpkg.com/@vuepress/plugin-google-analytics/-/plugin-google-analytics-1.9.10.tgz#3cd93245007f4b384f4eb169e72e538dc87f8b0e"
+ integrity sha512-AyQ3IFbYIHhuTQCUBMez6qpgvqOYT05cVoxuezuCpmBQBp+xSDjTXB+C9YjP+5w3thY5x1K+13QPJfFWW8S0mA==
dependencies:
- "@vuepress/types" "1.9.7"
+ "@vuepress/types" "1.9.10"
"@vuepress/plugin-last-updated@1.9.7":
version "1.9.7"
@@ -2327,6 +2327,15 @@
vuepress-plugin-container "^2.0.2"
vuepress-plugin-smooth-scroll "^0.0.3"
+"@vuepress/types@1.9.10":
+ version "1.9.10"
+ resolved "https://registry.yarnpkg.com/@vuepress/types/-/types-1.9.10.tgz#5b8d112a0d7dbaffce1e5d39b66754412c83ecc6"
+ integrity sha512-TDNQn4og85onmBpLTTXXmncW3rUnYGr2MkuI8OIFJZetDNM49t1WbjNVlrT+kx7C6qXi6okDQgrHGYXajHZWfg==
+ dependencies:
+ "@types/markdown-it" "^10.0.0"
+ "@types/webpack-dev-server" "^3"
+ webpack-chain "^6.0.0"
+
"@vuepress/types@1.9.7":
version "1.9.7"
resolved "https://registry.yarnpkg.com/@vuepress/types/-/types-1.9.7.tgz#aeb772fd0f7c2a10c6ec1d3c803a2e4b1d756c24"