diff --git a/.travis.yml b/.travis.yml index aecb04383..022e8cce5 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,6 +2,8 @@ language: node_js node_js: stable +before_install: + install: - yarn @@ -11,12 +13,16 @@ script: - echo 'rsshub.js.org' > CNAME after_script: - - git init - - git config user.name "Travis CI" - - git config user.email "no-reply@html.love" - - git add -A - - git commit -m 'deploy' - - git push -f "https://${GH_TOKEN}@github.com/DIYgod/RSSHub.git" master:gh-pages + - | + if git diff --name-only $TRAVIS_COMMIT_RANGE | grep '^docs/' + then + git init + git config user.name "Travis CI" + git config user.email "no-reply@html.love" + git add -A + git commit -m 'deploy' + git push -f "https://${GH_TOKEN}@github.com/DIYgod/RSSHub.git" master:gh-pages + fi cache: yarn: true diff --git a/README.md b/README.md index 156486316..00c5c02eb 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,7 @@ -# RSSHub +

+RSSHub +

+

RSSHub

> 🍭 使用 RSS 连接全世界 @@ -50,6 +53,7 @@ RSSHub 是一个轻量、易于扩展的 RSS 生成器,可以给任何奇奇 - 专题详情 - 详情 - pixiv + - 用户收藏 - 用户动态 - 排行榜 - 豆瓣 @@ -65,14 +69,29 @@ RSSHub 是一个轻量、易于扩展的 RSS 生成器,可以给任何奇奇 - 周报 - 腾讯吐个槽 - 吐槽新帖 +- 笔趣阁 + - 小说章节 +- 开发者头条 + - 今天头条 + - 独家号 +- Disqus + - 评论 ## 参与我们 如果有任何想法或需求,可以在 [issue](https://github.com/DIYgod/RSSHub/issues) 中告诉我们,同时我们欢迎各种 pull requests -可以通过以下途径参与讨论: +### 提交新的 RSS 内容 -- [Telegram 群](https://t.me/rsshub) +1. 在 [/router.js](https://github.com/DIYgod/RSSHub/blob/master/router.js) 里添加路由 + +1. 在 [/routes/](https://github.com/DIYgod/RSSHub/tree/master/routes) 中的路由对应路径添加获取 RSS 内容的脚本 + +1. 更新 README 和文档: [/README.md](https://github.com/DIYgod/RSSHub/blob/master/README.md) [/docs/README.md](https://github.com/DIYgod/RSSHub/blob/master/docs/README.md) + +### 参与讨论 + +1. [Telegram 群](https://t.me/rsshub) ## 搭建 diff --git a/config.js b/config.js index c6cc5bb3a..42be03170 100644 --- a/config.js +++ b/config.js @@ -8,5 +8,8 @@ module.exports = { client_secret: 'lsACyCD94FhDUtGTXi3QzcFE2uU1hqtDaKeqrdwj', username: 'rsshub@tmpmail.org', password: 'rsshubpixiv' + }, + disqus: { + api_key: 'E8Uh5l5fHZ6gD8U3KycjAIAk46f68Zw7C6eW8WSjZvCLXebZ7p0r1yrYDrLilk2F', } }; \ No newline at end of file diff --git a/docs/.vuepress/override.styl b/docs/.vuepress/override.styl new file mode 100644 index 000000000..cfbbddc28 --- /dev/null +++ b/docs/.vuepress/override.styl @@ -0,0 +1,22 @@ +$accentColor = #F5712C + +.navbar .site-name { + color: $accentColor; +} + +.page .custom-block.tip { + border-color: $accentColor; +} + +a.sidebar-link { + font-weight: bold; +} + +.sidebar-sub-header a.sidebar-link { + font-weight: 400; +} + +.page .content .logo { + padding-top: 2.6rem; + padding-bottom: 2rem; +} \ No newline at end of file diff --git a/docs/README.md b/docs/README.md index b85f581a5..d7de3bd05 100644 --- a/docs/README.md +++ b/docs/README.md @@ -2,17 +2,22 @@ sidebar: auto --- -# 使用 +

+RSSHub +

+

RSSHub

RSSHub 是一个轻量、易于扩展的 RSS 生成器,可以给任何奇奇怪怪的内容生成 RSS 订阅源 -演示域名为 rss.now.sh,缓存时间 5 分钟 +::: tip 提示 +演示域名为 [rss.now.sh](https://rss.now.sh),缓存时间 5 分钟,可以随意使用 +::: ## bilibili ### 番剧 -举例: https://rss.now.sh/bilibili/bangumi/21680 +举例: [https://rss.now.sh/bilibili/bangumi/21680](https://rss.now.sh/bilibili/bangumi/21680) 路由: `/bilibili/bangumi/:seasonid` @@ -20,7 +25,7 @@ RSSHub 是一个轻量、易于扩展的 RSS 生成器,可以给任何奇奇 ### UP 主投稿 -举例: https://rss.now.sh/bilibili/user/video/2267573 +举例: [https://rss.now.sh/bilibili/user/video/2267573](https://rss.now.sh/bilibili/user/video/2267573) 路由: `/bilibili/user/video/:uid` @@ -28,7 +33,7 @@ RSSHub 是一个轻量、易于扩展的 RSS 生成器,可以给任何奇奇 ### UP 主动态 -举例: https://rss.now.sh/bilibili/user/dynamic/2267573 +举例: [https://rss.now.sh/bilibili/user/dynamic/2267573](https://rss.now.sh/bilibili/user/dynamic/2267573) 路由: `/bilibili/user/dynamic/:uid` @@ -36,7 +41,7 @@ RSSHub 是一个轻量、易于扩展的 RSS 生成器,可以给任何奇奇 ### UP 主收藏夹 -举例: https://rss.now.sh/bilibili/user/fav/2267573 +举例: [https://rss.now.sh/bilibili/user/fav/2267573](https://rss.now.sh/bilibili/user/fav/2267573) 路由: `/bilibili/user/fav/:uid` @@ -44,7 +49,7 @@ RSSHub 是一个轻量、易于扩展的 RSS 生成器,可以给任何奇奇 ### UP 主投币视频 -举例: https://rss.now.sh/bilibili/user/coin/2267573 +举例: [https://rss.now.sh/bilibili/user/coin/2267573](https://rss.now.sh/bilibili/user/coin/2267573) 路由: `/bilibili/user/coin/:uid` @@ -52,7 +57,7 @@ RSSHub 是一个轻量、易于扩展的 RSS 生成器,可以给任何奇奇 ### UP 主粉丝 -举例: https://rss.now.sh/bilibili/user/followers/2267573 +举例: [https://rss.now.sh/bilibili/user/followers/2267573](https://rss.now.sh/bilibili/user/followers/2267573) 路由: `/bilibili/user/followers/:uid` @@ -60,7 +65,7 @@ RSSHub 是一个轻量、易于扩展的 RSS 生成器,可以给任何奇奇 ### UP 主关注用户 -举例: https://rss.now.sh/bilibili/user/followings/2267573 +举例: [https://rss.now.sh/bilibili/user/followings/2267573](https://rss.now.sh/bilibili/user/followings/2267573) 路由: `/bilibili/user/followings/:uid` @@ -68,7 +73,7 @@ RSSHub 是一个轻量、易于扩展的 RSS 生成器,可以给任何奇奇 ### 分区视频 -举例: https://rss.now.sh/bilibili/partion/33 +举例: [https://rss.now.sh/bilibili/partion/33](https://rss.now.sh/bilibili/partion/33) 路由: `/bilibili/partion/:tid` @@ -154,17 +159,17 @@ s ### 视频评论 -举例: https://rss.now.sh/bilibili/video/reply/7 +举例: [https://rss.now.sh/bilibili/video/reply/21669336](https://rss.now.sh/bilibili/video/reply/21669336) -路由: `/bilibili/video/reply/:avid` +路由: `/bilibili/video/reply/:aid` -参数: avid,视频 AV 号(仅数字) +参数: aid,可在视频页 URL 中找到 ## 微博 ### 博主 -举例: https://rss.now.sh/weibo/user/3306934123 +举例: [https://rss.now.sh/weibo/user/3306934123](https://rss.now.sh/weibo/user/3306934123) 路由: `/weibo/user/:uid` @@ -174,7 +179,7 @@ s ### 歌单歌曲 -举例: https://rss.now.sh/ncm/playlist/35798529 +举例: [https://rss.now.sh/ncm/playlist/35798529](https://rss.now.sh/ncm/playlist/35798529) 路由: `/ncm/playlist/:id` @@ -182,7 +187,7 @@ s ### 用户歌单 -举例: https://rss.now.sh/ncm/user/playlist/45441555 +举例: [https://rss.now.sh/ncm/user/playlist/45441555](https://rss.now.sh/ncm/user/playlist/45441555) 路由: `/ncm/user/playlist/:uid` @@ -190,7 +195,7 @@ s ### 歌手专辑 -举例: https://rss.now.sh/ncm/artist/2116 +举例: [https://rss.now.sh/ncm/artist/2116](https://rss.now.sh/ncm/artist/2116) 路由: `/ncm/artist/:id` @@ -200,7 +205,7 @@ s ### 分类 -举例: https://rss.now.sh/juejin/category/frontend +举例: [https://rss.now.sh/juejin/category/frontend](https://rss.now.sh/juejin/category/frontend) 路由: `/juejin/category/:category` @@ -214,7 +219,7 @@ s ### 首页 -举例: https://rss.now.sh/jianshu/home +举例: [https://rss.now.sh/jianshu/home](https://rss.now.sh/jianshu/home) 路由: `/jianshu/home` @@ -222,7 +227,7 @@ s ### 7 日热门 -举例: https://rss.now.sh/jianshu/trending/weekly +举例: [https://rss.now.sh/jianshu/trending/weekly](https://rss.now.sh/jianshu/trending/weekly) 路由: `/jianshu/trending/weekly` @@ -230,7 +235,7 @@ s ### 30 日热门 -举例: https://rss.now.sh/jianshu/trending/monthly +举例: [https://rss.now.sh/jianshu/trending/monthly](https://rss.now.sh/jianshu/trending/monthly) 路由: `/jianshu/trending/monthly` @@ -238,7 +243,7 @@ s ### 专题 -举例: https://rss.now.sh/jianshu/collection/xYuZYD +举例: [https://rss.now.sh/jianshu/collection/xYuZYD](https://rss.now.sh/jianshu/collection/xYuZYD) 路由: `/jianshu/collection/:id` @@ -246,7 +251,7 @@ s ### 作者 -举例: https://rss.now.sh/jianshu/user/yZq3ZV +举例: [https://rss.now.sh/jianshu/user/yZq3ZV](https://rss.now.sh/jianshu/user/yZq3ZV) 路由: `/jianshu/user/:id` @@ -257,7 +262,7 @@ s ### 收藏夹 -举例: https://rss.now.sh/zhihu/collection/26444956 +举例: [https://rss.now.sh/zhihu/collection/26444956](https://rss.now.sh/zhihu/collection/26444956) 路由: `/zhihu/collection/:id` @@ -265,7 +270,7 @@ s ### 用户动态 -举例: https://rss.now.sh/zhihu/people/activities/diygod +举例: [https://rss.now.sh/zhihu/people/activities/diygod](https://rss.now.sh/zhihu/people/activities/diygod) 路由: `/zhihu/people/activities/:id` @@ -273,7 +278,7 @@ s ### 专栏 -举例: https://rss.now.sh/zhihu/zhuanlan/googledevelopers +举例: [https://rss.now.sh/zhihu/zhuanlan/googledevelopers](https://rss.now.sh/zhihu/zhuanlan/googledevelopers) 路由: `/zhihu/zhuanlan/:id` @@ -283,7 +288,7 @@ s ### 房源 -举例: https://rss.now.sh/ziroom/room/sh/1/2/五角场 +举例: [https://rss.now.sh/ziroom/room/sh/1/2/五角场](https://rss.now.sh/ziroom/room/sh/1/2/五角场) 路由: `/ziroom/room/:city/:iswhole/:room/:keyword` @@ -299,11 +304,11 @@ keyword: 关键词 ## 快递 -

- 快递送达后请及时取消订阅,以免不必要地浪费服务器资源 -

+::: warning 注意 +快递送达后请及时取消订阅,以免不必要地浪费服务器资源 +::: -举例: https://rss.now.sh/express/youzhengguoji/CV054432809US +举例: [https://rss.now.sh/express/youzhengguoji/CV054432809US](https://rss.now.sh/express/youzhengguoji/CV054432809US) 路由: `/express/:company/:number` @@ -315,13 +320,9 @@ number: 快递单号 ## 贴吧 -

- 吧名如果包含中文,应该使用 `encodeURIComponent` 编码后使用 -

- ### 帖子列表 -举例: https://rss.now.sh/tieba/forum/女图 +举例: [https://rss.now.sh/tieba/forum/女图](https://rss.now.sh/tieba/forum/女图) 路由: `/tieba/forum/:kw` @@ -329,15 +330,19 @@ number: 快递单号 ## 妹子图 +::: warning 注意 +该网站在国外无法访问,故以下演示无效 +::: + ### 首页(最新) -举例: https://rss.now.sh/mzitu +举例: [https://rss.now.sh/mzitu](https://rss.now.sh/mzitu) 路由: `/mzitu/` ### 分类 -举例: https://rss.now.sh/mzitu/category/hot +举例: [https://rss.now.sh/mzitu/category/hot](https://rss.now.sh/mzitu/category/hot) 路由: `/mzitu/category/:category` @@ -350,13 +355,13 @@ number: 快递单号 ### 所有专题 -举例: https://rss.now.sh/mzitu/tags +举例: [https://rss.now.sh/mzitu/tags](https://rss.now.sh/mzitu/tags) 路由: `/mzitu/tags` ### 专题详情 -举例: https://rss.now.sh/mzitu/tag/shishen +举例: [https://rss.now.sh/mzitu/tag/shishen](https://rss.now.sh/mzitu/tag/shishen) 路由: `/mzitu/tag/:tag` @@ -364,7 +369,7 @@ number: 快递单号 ### 详情 -举例: https://rss.now.sh/mzitu/post/129452 +举例: [https://rss.now.sh/mzitu/post/129452](https://rss.now.sh/mzitu/post/129452) 路由: `/mzitu/post/:id` @@ -372,9 +377,17 @@ number: 快递单号 ## pixiv +### 用户收藏 + +举例: [https://rss.now.sh/pixiv/user/bookmarks/15288095](https://rss.now.sh/pixiv/user/bookmarks/15288095) + +路由: `/pixiv/user/bookmarks/:id` + +参数: id,用户 id,可在用户主页 URL 中找到 + ### 用户动态 -举例: https://rss.now.sh/pixiv/user/11 +举例: [https://rss.now.sh/pixiv/user/11](https://rss.now.sh/pixiv/user/11) 路由: `/pixiv/user/:id` @@ -382,7 +395,7 @@ number: 快递单号 ### 排行榜 -举例: https://rss.now.sh/pixiv/ranking/week +举例: [https://rss.now.sh/pixiv/ranking/week](https://rss.now.sh/pixiv/ranking/week) 路由: `/pixiv/ranking/:mode/:date?` @@ -391,11 +404,11 @@ number: 快递单号 mode: 排行榜类型 | pixiv 日排行 | pixiv 周排行 | pixiv 月排行 | pixiv 受男性欢迎排行 | pixiv 受女性欢迎排行 | pixiv 原创作品排行 | pixiv 新人排行 | -| --------- | --------- |-------------- | ------------------ | ------------------ | -------------- | -------------- | +| --------- | --------- | --------- | ------------- | ------------- | ------------- | ----------- | | day | week | month | day_male | day_female | week_original | week_rookie | | pixiv R-18 日排行 | pixiv R-18 受男性欢迎排行 | pixiv R-18 受女性欢迎排行 | pixiv R-18 周排行 | pixiv R-18G 排行 | -| --------- | ------------- | ------------- | ------------- | ----------- | +| -------------- | ------------------ | ------------------ | -------------- | -------------- | | day_r18 | day_male_r18 | day_female_r18 | week_r18 | week_r18g | date: 日期,取值形如 `2018-4-25` @@ -404,7 +417,7 @@ date: 日期,取值形如 `2018-4-25` ### 正在上映的电影 -举例: https://rss.now.sh/douban/movie/playing +举例: [https://rss.now.sh/douban/movie/playing](https://rss.now.sh/douban/movie/playing) 路由: `/douban/movie/playing` @@ -412,7 +425,7 @@ date: 日期,取值形如 `2018-4-25` ### 正在上映的高分电影 -举例: https://rss.now.sh/douban/movie/playing/7.5 +举例: [https://rss.now.sh/douban/movie/playing/7.5](https://rss.now.sh/douban/movie/playing/7.5) 路由 @@ -428,7 +441,7 @@ city: 城市的中文名,可选,默认北京 ### 即将上映的电影 -举例: https://rss.now.sh/douban/movie/later +举例: [https://rss.now.sh/douban/movie/later](https://rss.now.sh/douban/movie/later) 路由: `/douban/movie/later` @@ -436,7 +449,7 @@ city: 城市的中文名,可选,默认北京 ### 北美票房榜 -举例: https://rss.now.sh/douban/movie/ustop +举例: [https://rss.now.sh/douban/movie/ustop](https://rss.now.sh/douban/movie/ustop) 路由: `/douban/movie/ustop` @@ -446,7 +459,7 @@ city: 城市的中文名,可选,默认北京 ### 无聊图 -举例: https://rss.now.sh/jandan/pic +举例: [https://rss.now.sh/jandan/pic](https://rss.now.sh/jandan/pic) 路由: `/jandan/pic` @@ -456,7 +469,7 @@ city: 城市的中文名,可选,默认北京 ### 图卦 -举例: https://rss.now.sh/dapenti/tugua +举例: [https://rss.now.sh/dapenti/tugua](https://rss.now.sh/dapenti/tugua) 路由: `/dapenti/tugua` @@ -466,7 +479,7 @@ city: 城市的中文名,可选,默认北京 ### 周报 -举例: https://rss.now.sh/dockone/weekly +举例: [https://rss.now.sh/dockone/weekly](https://rss.now.sh/dockone/weekly) 路由: `/dockone/weekly` @@ -476,7 +489,7 @@ city: 城市的中文名,可选,默认北京 ### 吐槽新帖 -举例: https://rss.now.sh/tucaoqq/post/28564/CdRI0728 +举例: [https://rss.now.sh/tucaoqq/post/28564/CdRI0728](https://rss.now.sh/tucaoqq/post/28564/CdRI0728) 路由: `/tucaoqq/post/:project/:key` @@ -490,8 +503,34 @@ key: 产品密钥 ### 小说章节 -举例: https://rss.now.sh/biquge/novel/latestchapter/52_52542 +举例: [https://rss.now.sh/biquge/novel/latestchapter/52_52542](https://rss.now.sh/biquge/novel/latestchapter/52_52542) 路由: `/biquge/novel/latestchapter/:id` -参数: id,小说 id,可在对应小说页 URL 中找到 \ No newline at end of file +参数: id,小说 id,可在对应小说页 URL 中找到 + +## 开发者头条 + +### 今天头条 + +举例: [https://rss.now.sh/toutiao/today](https://rss.now.sh/toutiao/today) + +路由: `/toutiao/today` + +### 独家号 + +举例: [https://rss.now.sh/toutiao/user/140544](https://rss.now.sh/toutiao/user/140544) + +路由: `/toutiao/user/:id` + +参数: id,独家号 id,可在对应独家号页 URL 中找到 + +## Disqus + +### 评论 + +举例: [https://rss.now.sh/disqus/posts/diygod-me](https://rss.now.sh/disqus/posts/diygod-me) + +路由: `/disqus/posts/:forum` + +参数: forum,网站的 disqus name \ No newline at end of file diff --git a/docs/joinus/README.md b/docs/joinus/README.md index b00a400af..8f3f39494 100644 --- a/docs/joinus/README.md +++ b/docs/joinus/README.md @@ -8,8 +8,8 @@ 1. 在 [/routes/](https://github.com/DIYgod/RSSHub/tree/master/routes) 中的路由对应路径添加获取 RSS 内容的脚本 -1. 更新文档 [/docs/README.md](https://github.com/DIYgod/RSSHub/blob/master/docs/README.md) +1. 更新 README 和文档: [/README.md](https://github.com/DIYgod/RSSHub/blob/master/README.md) [/docs/README.md](https://github.com/DIYgod/RSSHub/blob/master/docs/README.md) ## 参与讨论 -- [Telegram 群](https://t.me/rsshub) \ No newline at end of file +1. [Telegram 群](https://t.me/rsshub) \ No newline at end of file diff --git a/middleware/onerror.js b/middleware/onerror.js index 3ce9e0fc6..75bc9c408 100644 --- a/middleware/onerror.js +++ b/middleware/onerror.js @@ -4,7 +4,7 @@ module.exports = async (ctx, next) => { try { await next(); } catch (err) { - logger.error('Promise error: ' + err); + logger.error('Promise error: ' + (err instanceof Error ? err.stack : err)); ctx.set({ 'Content-Type': 'text/html; charset=UTF-8', }); diff --git a/package.json b/package.json index d771dfdef..07e23b5b8 100644 --- a/package.json +++ b/package.json @@ -31,7 +31,6 @@ "crypto": "1.0.1", "eslint": "4.19.1", "form-data": "^2.3.2", - "js-md5": "^0.7.3", "json-bigint": "0.2.3", "koa": "2.5.0", "koa-redis-cache": "3.0.0", diff --git a/router.js b/router.js index 7db416ce4..8847c75d0 100644 --- a/router.js +++ b/router.js @@ -19,7 +19,7 @@ router.get('/bilibili/user/followers/:uid', require('./routes/bilibili/followers router.get('/bilibili/user/followings/:uid', require('./routes/bilibili/followings')); router.get('/bilibili/partion/:tid', require('./routes/bilibili/partion')); router.get('/bilibili/bangumi/:seasonid', require('./routes/bilibili/bangumi')); -router.get('/bilibili/video/reply/:avid', require('./routes/bilibili/videoReply')); +router.get('/bilibili/video/reply/:aid', require('./routes/bilibili/reply')); // // 微博 router.get('/weibo/user/:uid', require('./routes/weibo/user')); @@ -61,7 +61,8 @@ router.get('/mzitu/post/:id', require('./routes/mzitu/post')); router.get('/mzitu/tag/:tag', require('./routes/mzitu/tag')); // // Pixiv -router.get('/pixiv/user/:id', require('./routes/pixiv/user')); +router.get('/pixiv/user/bookmarks/:id', require('./routes/pixiv/bookmarks')); +router.get('/pixiv/user/:id/', require('./routes/pixiv/user')); router.get('/pixiv/ranking/:mode/:date?', require('./routes/pixiv/ranking')); // 豆瓣 @@ -86,4 +87,11 @@ router.get('/tucaoqq/post/:project/:key', require('./routes/tucaoqq/post')); // 笔趣阁 router.get('/biquge/novel/latestchapter/:id', require('./routes/biquge/chapter')); +// 开发者头条 +router.get('/toutiao/today', require('./routes/toutiao/today')); +router.get('/toutiao/user/:id', require('./routes/toutiao/user')); + +// Disqus +router.get('/disqus/posts/:forum', require('./routes/disqus/posts')); + module.exports = router; diff --git a/routes/bilibili/bangumi.js b/routes/bilibili/bangumi.js index c57559b98..030cd5ed6 100644 --- a/routes/bilibili/bangumi.js +++ b/routes/bilibili/bangumi.js @@ -1,6 +1,5 @@ const axios = require('axios'); -const art = require('art-template'); -const path = require('path'); +const template = require('../../utils/template'); const config = require('../../config'); module.exports = async (ctx) => { @@ -17,11 +16,10 @@ module.exports = async (ctx) => { const data = JSON.parse(response.data.match(/^seasonListCallback\((.*)\);$/)[1]).result || {}; - ctx.body = art(path.resolve(__dirname, '../../views/rss.art'), { + ctx.body = template({ title: data.title, link: `https://bangumi.bilibili.com/anime/${seasonid}/`, description: data.evaluate, - lastBuildDate: new Date().toUTCString(), item: data.episodes && data.episodes.map((item) => ({ title: `第${item.index}话 ${item.index_title}`, description: `更新时间:${item.update_time}`, diff --git a/routes/bilibili/coin.js b/routes/bilibili/coin.js index f06902b0e..7c7b7005e 100644 --- a/routes/bilibili/coin.js +++ b/routes/bilibili/coin.js @@ -1,7 +1,6 @@ const axios = require('axios'); const qs = require('querystring'); -const art = require('art-template'); -const path = require('path'); +const template = require('../../utils/template'); const config = require('../../config'); module.exports = async (ctx) => { @@ -31,11 +30,10 @@ module.exports = async (ctx) => { }); const data = response.data; - ctx.body = art(path.resolve(__dirname, '../../views/rss.art'), { + ctx.body = template({ title: `${name} 的 bilibili 投币视频`, link: `https://space.bilibili.com/${uid}`, description: `${name} 的 bilibili 投币视频`, - lastBuildDate: new Date().toUTCString(), item: data.data && data.data.list && data.data.list.map((item) => ({ title: item.title, description: `${item.title}
`, diff --git a/routes/bilibili/dynamic.js b/routes/bilibili/dynamic.js index a922631b6..5cb6b2470 100644 --- a/routes/bilibili/dynamic.js +++ b/routes/bilibili/dynamic.js @@ -1,6 +1,5 @@ const axios = require('axios'); -const art = require('art-template'); -const path = require('path'); +const template = require('../../utils/template'); const JSONbig = require('json-bigint'); const config = require('../../config'); @@ -17,11 +16,10 @@ module.exports = async (ctx) => { }); const data = response.data.data.cards; - ctx.body = art(path.resolve(__dirname, '../../views/rss.art'), { + ctx.body = template({ title: `${data[0].desc.user_profile.info.uname} 的 bilibili 动态`, link: `https://space.bilibili.com/${uid}/#/dynamic`, description: `${data[0].desc.user_profile.info.uname} 的 bilibili 动态`, - lastBuildDate: new Date().toUTCString(), item: data.map((item) => { const parsed = JSONbig.parse(item.card); const data = parsed.item || parsed; diff --git a/routes/bilibili/fav.js b/routes/bilibili/fav.js index 94f769823..ce77ef9d7 100644 --- a/routes/bilibili/fav.js +++ b/routes/bilibili/fav.js @@ -1,7 +1,6 @@ const axios = require('axios'); const qs = require('querystring'); -const art = require('art-template'); -const path = require('path'); +const template = require('../../utils/template'); const config = require('../../config'); module.exports = async (ctx) => { @@ -31,11 +30,11 @@ module.exports = async (ctx) => { }); const data = response.data; - ctx.body = art(path.resolve(__dirname, '../../views/rss.art'), { + ctx.body = template({ title: `${name} 的 bilibili 收藏夹`, link: `https://space.bilibili.com/${uid}/#/favlist`, description: `${name} 的 bilibili 收藏夹`, - lastBuildDate: new Date().toUTCString(), + item: data.data && data.data.archives && data.data.archives.map((item) => ({ title: item.title, description: `${item.desc}
`, diff --git a/routes/bilibili/followers.js b/routes/bilibili/followers.js index 5626f03bf..6f0a29ede 100644 --- a/routes/bilibili/followers.js +++ b/routes/bilibili/followers.js @@ -1,7 +1,6 @@ const axios = require('axios'); const qs = require('querystring'); -const art = require('art-template'); -const path = require('path'); +const template = require('../../utils/template'); const config = require('../../config'); module.exports = async (ctx) => { @@ -41,11 +40,10 @@ module.exports = async (ctx) => { }); const data = response.data.data.list; - ctx.body = art(path.resolve(__dirname, '../../views/rss.art'), { + ctx.body = template({ title: `${name} 的 bilibili 粉丝`, link: `https://space.bilibili.com/${uid}/#/fans/fans`, description: `${name} 的 bilibili 粉丝`, - lastBuildDate: new Date().toUTCString(), item: data.map((item) => ({ title: `${name} 新粉丝 ${item.uname}`, description: `${item.uname}
${item.sign}
总计${count}`, diff --git a/routes/bilibili/followings.js b/routes/bilibili/followings.js index e978773bc..7683255cc 100644 --- a/routes/bilibili/followings.js +++ b/routes/bilibili/followings.js @@ -1,7 +1,6 @@ const axios = require('axios'); const qs = require('querystring'); -const art = require('art-template'); -const path = require('path'); +const template = require('../../utils/template'); const config = require('../../config'); module.exports = async (ctx) => { @@ -41,11 +40,10 @@ module.exports = async (ctx) => { }); const data = response.data.data.list; - ctx.body = art(path.resolve(__dirname, '../../views/rss.art'), { + ctx.body = template({ title: `${name} 的 bilibili 关注`, link: `https://space.bilibili.com/${uid}/#/fans/follow`, description: `${name} 的 bilibili 关注`, - lastBuildDate: new Date().toUTCString(), item: data.map((item) => ({ title: `${name} 新关注 ${item.uname}`, description: `${item.uname}
${item.sign}
总计${count}`, diff --git a/routes/bilibili/partion.js b/routes/bilibili/partion.js index e589e921a..c9e68998f 100644 --- a/routes/bilibili/partion.js +++ b/routes/bilibili/partion.js @@ -1,6 +1,5 @@ const axios = require('axios'); -const art = require('art-template'); -const path = require('path'); +const template = require('../../utils/template'); const config = require('../../config'); module.exports = async (ctx) => { @@ -21,11 +20,10 @@ module.exports = async (ctx) => { name = list[0].tname; } - ctx.body = art(path.resolve(__dirname, '../../views/rss.art'), { + ctx.body = template({ title: `bilibili ${name}分区`, link: 'https://www.bilibili.com', description: `bilibili ${name}分区`, - lastBuildDate: new Date().toUTCString(), item: list && list.map((item) => ({ title: `${item.title} - ${item.owner.name}`, description: `${item.desc}`, diff --git a/routes/bilibili/videoReply.js b/routes/bilibili/reply.js similarity index 67% rename from routes/bilibili/videoReply.js rename to routes/bilibili/reply.js index 7ef076a6a..16759d2c1 100644 --- a/routes/bilibili/videoReply.js +++ b/routes/bilibili/reply.js @@ -1,16 +1,15 @@ const axios = require('axios'); -const art = require('art-template'); -const path = require('path'); +const template = require('../../utils/template'); const config = require('../../config'); const cheerio = require('cheerio'); const iconv = require('iconv-lite'); module.exports = async (ctx) => { - const avid = ctx.params.avid; + const aid = ctx.params.aid; const nameResponse = await axios({ method: 'get', - url: `https://www.bilibili.com/video/av${avid}`, + url: `https://www.bilibili.com/video/av${aid}`, headers: { 'User-Agent': config.ua, }, @@ -23,25 +22,24 @@ module.exports = async (ctx) => { const response = await axios({ method: 'get', - url: `https://api.bilibili.com/x/v2/reply?type=1&oid=${avid}&sort=0`, + url: `https://api.bilibili.com/x/v2/reply?type=1&oid=${aid}&sort=0`, headers: { 'User-Agent': config.ua, - 'Referer': `https://www.bilibili.com/video/av${avid}`, + 'Referer': `https://www.bilibili.com/video/av${aid}`, } }); const data = response.data.data.replies; - ctx.body = art(path.resolve(__dirname, '../../views/rss.art'), { + ctx.body = template({ title: `${name} 的 评论`, - link: `https://www.bilibili.com/video/av${avid}`, - description: `${name} 的 评论`, - lastBuildDate: new Date().toUTCString(), + link: `https://www.bilibili.com/video/av${aid}`, + description: `${name} 的评论`, item: data.map((item) => ({ title: `${item.member.uname} : ${item.content.message}`, description: `#${item.floor}
${item.member.uname} : ${item.content.message}`, pubDate: new Date(item.ctime * 1000).toUTCString(), - link: `https://www.bilibili.com/video/av${avid}/#reply${item.rpid}` + link: `https://www.bilibili.com/video/av${aid}/#reply${item.rpid}` })), }); }; \ No newline at end of file diff --git a/routes/bilibili/video.js b/routes/bilibili/video.js index 7245fe47a..de79faed6 100644 --- a/routes/bilibili/video.js +++ b/routes/bilibili/video.js @@ -1,7 +1,6 @@ const axios = require('axios'); const qs = require('querystring'); -const art = require('art-template'); -const path = require('path'); +const template = require('../../utils/template'); const config = require('../../config'); module.exports = async (ctx) => { @@ -31,11 +30,10 @@ module.exports = async (ctx) => { }); const data = response.data; - ctx.body = art(path.resolve(__dirname, '../../views/rss.art'), { + ctx.body = template({ title: `${name} 的 bilibili 空间`, link: `https://space.bilibili.com/${uid}`, description: `${name} 的 bilibili 空间`, - lastBuildDate: new Date().toUTCString(), item: data.data && data.data.vlist && data.data.vlist.map((item) => ({ title: item.title, description: `${item.description}
`, diff --git a/routes/biquge/chapter.js b/routes/biquge/chapter.js index 0d45c436b..7cc29b265 100644 --- a/routes/biquge/chapter.js +++ b/routes/biquge/chapter.js @@ -1,6 +1,5 @@ const axios = require('axios'); -const art = require('art-template'); -const path = require('path'); +const template = require('../../utils/template'); const cheerio = require('cheerio'); const config = require('../../config'); const iconv = require('iconv-lite'); @@ -38,12 +37,11 @@ module.exports = async (ctx) => { chapter_item.push(item); } // console.log('chapter_item',chapter_item) - ctx.body = art(path.resolve(__dirname, '../../views/rss.art'), { + ctx.body = template({ title: `笔趣阁 ${title}`, link: `${baseUrl}${id}/`, image: cover_url, description: description, - lastBuildDate: new Date().toUTCString(), item: chapter_item, }); }; diff --git a/routes/dapenti/tugua.js b/routes/dapenti/tugua.js index 94da8deac..1b49c491f 100644 --- a/routes/dapenti/tugua.js +++ b/routes/dapenti/tugua.js @@ -1,6 +1,5 @@ const axios = require('axios'); -const art = require('art-template'); -const path = require('path'); +const template = require('../../utils/template'); const cheerio = require('cheerio'); const config = require('../../config'); const iconv = require('iconv-lite'); @@ -47,11 +46,10 @@ module.exports = async (ctx) => { result_item.push(item) } - ctx.body = art(path.resolve(__dirname, '../../views/rss.art'), { + ctx.body = template({ title: `喷嚏图卦`, link: `https://www.dapenti.com/blog/blog.asp?name=xilei&subjectid=70`, description: `喷嚏图卦`, - lastBuildDate: new Date().toUTCString(), item: result_item, }); }; diff --git a/routes/disqus/posts.js b/routes/disqus/posts.js new file mode 100644 index 000000000..914960e47 --- /dev/null +++ b/routes/disqus/posts.js @@ -0,0 +1,53 @@ +const axios = require('axios'); +const template = require('../../utils/template'); +const config = require('../../config'); + +module.exports = async (ctx) => { + const forum = ctx.params.forum; + + const response = await axios({ + method: 'get', + url: `https://disqus.com/api/3.0/forums/listPosts.json?api_key=${config.disqus.api_key}&forum=${forum}`, + headers: { + 'User-Agent': config.ua, + 'Referer': 'https://disqus.com/' + } + }); + + const data = response.data.response; + + const threadsObj = {}; + data.forEach((item) => { + threadsObj[item.thread] = 1; + }); + let threadsQuery = ''; + Object.keys(threadsObj).forEach((item) => { + threadsQuery += `&thread=${item}`; + }); + + const responseThreads = await axios({ + method: 'get', + url: `https://disqus.com/api/3.0/forums/listThreads.json?api_key=${config.disqus.api_key}&forum=${forum}${threadsQuery}`, + headers: { + 'User-Agent': config.ua, + 'Referer': 'https://disqus.com/' + } + }); + + const threads = responseThreads.data.response; + + ctx.body = template({ + title: `${forum} 的评论`, + link: `https://disqus.com/home/forums/${forum}`, + description: `${forum} 的 disqus 评论`, + item: data.map((item) => { + const thread = threads.filter((i) => i.id === item.thread)[0]; + return { + title: `${item.author.name}: ${item.raw_message > 24 ? item.raw_message.slice(0, 24) + '...' : item.raw_message}`, + description: `${item.author.name} 在《${thread.clean_title}》中发表评论: ${item.message}`, + pubDate: new Date(item.createdAt).toUTCString(), + link: `${thread.link}/#comment-${item.id}` + }; + }), + }); +}; \ No newline at end of file diff --git a/routes/dockone/weekly.js b/routes/dockone/weekly.js index e1cb23bb9..f150e9a99 100644 --- a/routes/dockone/weekly.js +++ b/routes/dockone/weekly.js @@ -1,6 +1,5 @@ const axios = require('axios'); -const art = require('art-template'); -const path = require('path'); +const template = require('../../utils/template'); const cheerio = require('cheerio'); const config = require('../../config'); @@ -27,11 +26,10 @@ module.exports = async (ctx) => { const list = $('ul.i.issues>li'); - ctx.body = art(path.resolve(__dirname, '../../views/rss.art'), { + ctx.body = template({ title: $('title').text(), link: url, description: $('meta[name="description"]').attr('content') || $('title').text(), - lastBuildDate: new Date().toUTCString(), item: list && list.map((item,index) => { item=$(index); return { diff --git a/routes/douban/later.js b/routes/douban/later.js index 26adc5072..546434a20 100644 --- a/routes/douban/later.js +++ b/routes/douban/later.js @@ -1,6 +1,5 @@ const axios = require('axios'); -const art = require('art-template'); -const path = require('path'); +const template = require('../../utils/template'); module.exports = async (ctx) => { const response = await axios({ @@ -9,10 +8,9 @@ module.exports = async (ctx) => { }); const movieList = response.data.subjects; - ctx.body = art(path.resolve(__dirname, '../../views/rss.art'), { + ctx.body = template({ title: '即将上映的电影', link: 'https://movie.douban.com/cinema/later/', - lastBuildDate: new Date().toUTCString(), item: movieList.map((item) => ({ title: item.title, description: `标题:${item.title}
影片类型:${item.genres.join(' | ')}
评分:${item.rating.stars === '00' ? '无' : item.rating.average}
`, diff --git a/routes/douban/playing.js b/routes/douban/playing.js index 8735a1f0e..f82f9e694 100644 --- a/routes/douban/playing.js +++ b/routes/douban/playing.js @@ -1,6 +1,5 @@ const axios = require('axios'); -const art = require('art-template'); -const path = require('path'); +const template = require('../../utils/template'); module.exports = async (ctx) => { const city = ctx.params.city; @@ -12,10 +11,9 @@ module.exports = async (ctx) => { }); const movieList = score ? response.data.subjects.filter((item) => item.rating.average >= score) : response.data.subjects; - ctx.body = art(path.resolve(__dirname, '../../views/rss.art'), { + ctx.body = template({ title: `${city ? city : ''}正在上映的${score ? `超过 ${score} 分的` : ''}电影`, link: 'https://movie.douban.com/cinema/nowplaying/', - lastBuildDate: new Date().toUTCString(), item: movieList.map((item) => ({ title: item.title, description: `标题:${item.title}
影片类型:${item.genres.join(' | ')}
评分:${item.rating.average}
`, diff --git a/routes/douban/ustop.js b/routes/douban/ustop.js index 2f635206f..e0f7655ac 100644 --- a/routes/douban/ustop.js +++ b/routes/douban/ustop.js @@ -1,6 +1,5 @@ const axios = require('axios'); -const art = require('art-template'); -const path = require('path'); +const template = require('../../utils/template'); module.exports = async (ctx) => { const response = await axios({ @@ -9,10 +8,9 @@ module.exports = async (ctx) => { }); const movieList = response.data.subjects; - ctx.body = art(path.resolve(__dirname, '../../views/rss.art'), { + ctx.body = template({ title: '豆瓣电影北美票房榜', link: 'https://movie.douban.com/chart', - lastBuildDate: new Date().toUTCString(), item: movieList.map((item) => { item = item.subject; return { diff --git a/routes/express/express.js b/routes/express/express.js index 0ed128fc2..893aab278 100644 --- a/routes/express/express.js +++ b/routes/express/express.js @@ -1,6 +1,5 @@ const axios = require('axios'); -const art = require('art-template'); -const path = require('path'); +const template = require('../../utils/template'); const config = require('../../config'); module.exports = async (ctx) => { @@ -18,11 +17,10 @@ module.exports = async (ctx) => { const data = response.data.data; - ctx.body = art(path.resolve(__dirname, '../../views/rss.art'), { + ctx.body = template({ title: `快递 ${company}-${number}`, link: 'https://www.kuaidi100.com', description: `快递 ${company}-${number}`, - lastBuildDate: new Date().toUTCString(), item: data.map((item) => ({ title: item.context, description: item.context, diff --git a/routes/jandan/pic.js b/routes/jandan/pic.js index 0c9dbf01a..6bdc164b7 100644 --- a/routes/jandan/pic.js +++ b/routes/jandan/pic.js @@ -1,6 +1,5 @@ const axios = require('axios'); -const art = require('art-template'); -const path = require('path'); +const template = require('../../utils/template'); const cheerio = require('cheerio'); const crypto = require('crypto'); const config = require('../../config'); @@ -122,11 +121,10 @@ module.exports = async (ctx) => { }); }); - ctx.body = art(path.resolve(__dirname, '../../views/rss.art'), { + ctx.body = template({ title: '煎蛋无聊图', link: 'http://jandan.net/pic', description: '煎蛋官方无聊图,无限活力的热门图区。', - lastBuildDate: new Date().toUTCString(), item: items }); }; diff --git a/routes/jianshu/collection.js b/routes/jianshu/collection.js index b288f3b96..91eacdf12 100644 --- a/routes/jianshu/collection.js +++ b/routes/jianshu/collection.js @@ -1,6 +1,5 @@ const axios = require('axios'); -const art = require('art-template'); -const path = require('path'); +const template = require('../../utils/template'); const cheerio = require('cheerio'); const config = require('../../config'); @@ -21,11 +20,10 @@ module.exports = async (ctx) => { const $ = cheerio.load(data); const list = $('.note-list li'); - ctx.body = art(path.resolve(__dirname, '../../views/rss.art'), { + ctx.body = template({ title: $('title').text(), link: `https://www.jianshu.com/c/${id}`, description: $('meta[name="description"]').attr('content') || $('title').text(), - lastBuildDate: new Date().toUTCString(), item: list && list.map((index, item) => { item = $(item); return { diff --git a/routes/jianshu/home.js b/routes/jianshu/home.js index 720fe4167..dbb15e36b 100644 --- a/routes/jianshu/home.js +++ b/routes/jianshu/home.js @@ -1,6 +1,5 @@ const axios = require('axios'); -const art = require('art-template'); -const path = require('path'); +const template = require('../../utils/template'); const cheerio = require('cheerio'); const config = require('../../config'); @@ -19,11 +18,10 @@ module.exports = async (ctx) => { const $ = cheerio.load(data); const list = $('.note-list li'); - ctx.body = art(path.resolve(__dirname, '../../views/rss.art'), { + ctx.body = template({ title: '简书首页', link: 'https://www.jianshu.com', description: $('meta[name="description"]').attr('content'), - lastBuildDate: new Date().toUTCString(), item: list && list.map((index, item) => { item = $(item); return { diff --git a/routes/jianshu/monthly.js b/routes/jianshu/monthly.js index 621c81f01..8b1e1aef7 100644 --- a/routes/jianshu/monthly.js +++ b/routes/jianshu/monthly.js @@ -1,6 +1,5 @@ const axios = require('axios'); -const art = require('art-template'); -const path = require('path'); +const template = require('../../utils/template'); const cheerio = require('cheerio'); const config = require('../../config'); @@ -19,11 +18,10 @@ module.exports = async (ctx) => { const $ = cheerio.load(data); const list = $('.note-list li'); - ctx.body = art(path.resolve(__dirname, '../../views/rss.art'), { + ctx.body = template({ title: '简书 30 日热门', link: 'https://www.jianshu.com/trending/monthly', description: '简书 30 日热门', - lastBuildDate: new Date().toUTCString(), item: list && list.map((index, item) => { item = $(item); return { diff --git a/routes/jianshu/user.js b/routes/jianshu/user.js index 94ff5fcd1..7dc4b842b 100644 --- a/routes/jianshu/user.js +++ b/routes/jianshu/user.js @@ -1,6 +1,5 @@ const axios = require('axios'); -const art = require('art-template'); -const path = require('path'); +const template = require('../../utils/template'); const cheerio = require('cheerio'); const config = require('../../config'); @@ -21,11 +20,10 @@ module.exports = async (ctx) => { const $ = cheerio.load(data); const list = $('.note-list li'); - ctx.body = art(path.resolve(__dirname, '../../views/rss.art'), { + ctx.body = template({ title: $('title').text(), link: `https://www.jianshu.com/u/${id}`, description: $('meta[name="description"]').attr('content') || $('title').text(), - lastBuildDate: new Date().toUTCString(), item: list && list.map((index, item) => { item = $(item); return { diff --git a/routes/jianshu/weekly.js b/routes/jianshu/weekly.js index 1fcf2d890..1edcb182e 100644 --- a/routes/jianshu/weekly.js +++ b/routes/jianshu/weekly.js @@ -1,6 +1,5 @@ const axios = require('axios'); -const art = require('art-template'); -const path = require('path'); +const template = require('../../utils/template'); const cheerio = require('cheerio'); const config = require('../../config'); @@ -19,11 +18,10 @@ module.exports = async (ctx) => { const $ = cheerio.load(data); const list = $('.note-list li'); - ctx.body = art(path.resolve(__dirname, '../../views/rss.art'), { + ctx.body = template({ title: '简书 7 日热门', link: 'https://www.jianshu.com/trending/weekly', description: '简书 7 日热门', - lastBuildDate: new Date().toUTCString(), item: list && list.map((index, item) => { item = $(item); return { diff --git a/routes/juejin/category.js b/routes/juejin/category.js index 082a2a92d..efbf75903 100644 --- a/routes/juejin/category.js +++ b/routes/juejin/category.js @@ -1,6 +1,5 @@ const axios = require('axios'); -const art = require('art-template'); -const path = require('path'); +const template = require('../../utils/template'); const config = require('../../config'); module.exports = async (ctx) => { @@ -33,11 +32,10 @@ module.exports = async (ctx) => { const data = response.data; - ctx.body = art(path.resolve(__dirname, '../../views/rss.art'), { + ctx.body = template({ title: `掘金${cat.name}`, link: `https://juejin.im/welcome/${category}`, description: `掘金${cat.name}`, - lastBuildDate: new Date().toUTCString(), item: data.d && data.d.entrylist && data.d.entrylist.map((item) => ({ title: item.title, description: `${(item.content || item.summaryInfo || '无描述').replace(/[\x00-\x08\x0b-\x0c\x0e-\x1f\x7f]/g, '')}`, diff --git a/routes/mzitu/category.js b/routes/mzitu/category.js index cb85367ba..90f2a7ad6 100644 --- a/routes/mzitu/category.js +++ b/routes/mzitu/category.js @@ -1,6 +1,5 @@ const axios = require('axios'); -const art = require('art-template'); -const path = require('path'); +const template = require('../../utils/template'); const cheerio = require('cheerio'); const config = require('../../config'); @@ -24,11 +23,10 @@ module.exports = async (ctx) => { const $ = cheerio.load(data); const list = $('#pins li'); - ctx.body = art(path.resolve(__dirname, '../../views/rss.art'), { + ctx.body = template({ title: $('title').text(), link: url, description: $('meta[name="description"]').attr('content') || $('title').text(), - lastBuildDate: new Date().toUTCString(), item: list && list.map((item, index) => { item = $(index); const linkA = item.find('a'); diff --git a/routes/mzitu/post.js b/routes/mzitu/post.js index 8a0262e64..a8de2435b 100644 --- a/routes/mzitu/post.js +++ b/routes/mzitu/post.js @@ -1,6 +1,5 @@ const axios = require('axios'); -const art = require('art-template'); -const path = require('path'); +const template = require('../../utils/template'); const cheerio = require('cheerio'); const config = require('../../config'); @@ -50,11 +49,10 @@ module.exports = async (ctx) => { const reg = /[1-9]\d{3}-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1])\s+(20|21|22|23|[0-1]\d):[0-5]\d:[0-5]\d/; - ctx.body = art(path.resolve(__dirname, '../../views/rss.art'), { + ctx.body = template({ title: title, link: url, description: $('meta[name="description"]').attr('content') || title, - lastBuildDate: new Date().toUTCString(), item: list && list.map((item) => { let date = new Date(); const dateStr = $('.main-meta > span:nth-child(2)').text(); diff --git a/routes/mzitu/tag.js b/routes/mzitu/tag.js index ea52b6871..290751258 100644 --- a/routes/mzitu/tag.js +++ b/routes/mzitu/tag.js @@ -1,6 +1,5 @@ const axios = require('axios'); -const art = require('art-template'); -const path = require('path'); +const template = require('../../utils/template'); const cheerio = require('cheerio'); const config = require('../../config'); @@ -23,11 +22,10 @@ module.exports = async (ctx) => { const $ = cheerio.load(data); const list = $('#pins li'); - ctx.body = art(path.resolve(__dirname, '../../views/rss.art'), { + ctx.body = template({ title: $('title').text(), link: url, description: $('meta[name="description"]').attr('content') || $('title').text(), - lastBuildDate: new Date().toUTCString(), item: list && list.map((item, index) => { item = $(index); const linkA = item.find('a'); diff --git a/routes/mzitu/tags.js b/routes/mzitu/tags.js index 7ddb752c6..c29a9072a 100644 --- a/routes/mzitu/tags.js +++ b/routes/mzitu/tags.js @@ -1,6 +1,5 @@ const axios = require('axios'); -const art = require('art-template'); -const path = require('path'); +const template = require('../../utils/template'); const cheerio = require('cheerio'); const config = require('../../config'); @@ -21,11 +20,10 @@ module.exports = async (ctx) => { const $ = cheerio.load(data); const list = $('.main-content > div.postlist > dl > dd'); - ctx.body = art(path.resolve(__dirname, '../../views/rss.art'), { + ctx.body = template({ title: $('title').text(), link: url, description: $('meta[name="description"]').attr('content') || $('title').text(), - lastBuildDate: new Date().toUTCString(), item: list && list.map((item, index) => { item = $(index); const linkA = item.find('a'); diff --git a/routes/ncm/artist.js b/routes/ncm/artist.js index 1a8b7c534..657b53e23 100644 --- a/routes/ncm/artist.js +++ b/routes/ncm/artist.js @@ -1,6 +1,5 @@ const axios = require('axios'); -const art = require('art-template'); -const path = require('path'); +const template = require('../../utils/template'); const config = require('../../config'); module.exports = async (ctx) => { @@ -17,11 +16,10 @@ module.exports = async (ctx) => { const data = response.data; - ctx.body = art(path.resolve(__dirname, '../../views/rss.art'), { + ctx.body = template({ title: data.artist.name, link: `https://music.163.com/#/artist/album?id=${id}`, description: `网易云音乐歌手专辑 - ${data.artist.name}`, - lastBuildDate: new Date().toUTCString(), item: data.hotAlbums.map((item) => { const singer = item.artists.length === 1 ? item.artists[0].name : item.artists.reduce((prev, cur) => (prev.name || prev) + '/' + cur.name); return { diff --git a/routes/ncm/playlist.js b/routes/ncm/playlist.js index 663b50be9..555aed878 100644 --- a/routes/ncm/playlist.js +++ b/routes/ncm/playlist.js @@ -1,7 +1,6 @@ const axios = require('axios'); const qs = require('querystring'); -const art = require('art-template'); -const path = require('path'); +const template = require('../../utils/template'); const config = require('../../config'); module.exports = async (ctx) => { @@ -22,11 +21,10 @@ module.exports = async (ctx) => { const data = response.data.playlist; - ctx.body = art(path.resolve(__dirname, '../../views/rss.art'), { + ctx.body = template({ title: data.name, link: `https://music.163.com/#/playlist?id=${id}`, description: `网易云音乐歌单 - ${data.name}`, - lastBuildDate: new Date().toUTCString(), item: data.tracks && data.tracks.map((item) => { const singer = item.ar.length === 1 ? item.ar[0].name : item.ar.reduce((prev, cur) => (prev.name || prev) + '/' + cur.name); return { diff --git a/routes/ncm/userplaylist.js b/routes/ncm/userplaylist.js index 0c0fc716c..af2f3e97d 100644 --- a/routes/ncm/userplaylist.js +++ b/routes/ncm/userplaylist.js @@ -1,7 +1,6 @@ const axios = require('axios'); const qs = require('querystring'); -const art = require('art-template'); -const path = require('path'); +const template = require('../../utils/template'); const config = require('../../config'); module.exports = async (ctx) => { @@ -28,11 +27,10 @@ module.exports = async (ctx) => { const { nickname, signature } = creator; - ctx.body = art(path.resolve(__dirname, '../../views/rss.art'), { + ctx.body = template({ title: `${nickname} 的所有歌单`, link: `http://music.163.com/user/home?id=${uid}`, description: signature, - lastBuildDate: new Date().toUTCString(), item: playlist.map((pl) => ({ title: pl.name, description: pl.description, diff --git a/routes/pixiv/api/getBookmarks.js b/routes/pixiv/api/getBookmarks.js new file mode 100644 index 000000000..b218b26e6 --- /dev/null +++ b/routes/pixiv/api/getBookmarks.js @@ -0,0 +1,25 @@ + +const axios = require('axios'); +const maskHeader = require('../constants').maskHeader; + +/** + * 获取用户的收藏 + * + * @param {string} user_id 目标用户id + * @param {string} token pixiv oauth token + * @returns {Promise>} + */ +module.exports = async function getBookmarks(user_id, token) { + return await axios({ + method: 'get', + url: 'https://app-api.pixiv.net/v1/user/bookmarks/illust', + headers: { + ...maskHeader, + 'Authorization': 'Bearer ' + token + }, + params: { + user_id: user_id, + restrict: 'public' + }, + }); +} \ No newline at end of file diff --git a/routes/pixiv/api/getIllusts.js b/routes/pixiv/api/getIllusts.js new file mode 100644 index 000000000..de6d11b59 --- /dev/null +++ b/routes/pixiv/api/getIllusts.js @@ -0,0 +1,24 @@ +const axios = require('axios'); +const maskHeader = require('../constants').maskHeader; + +/** + * 获取用户插画作品 + * @param {string} user_id 目标用户id + * @param {string} token pixiv oauth token + * @returns {Promise>} + */ +module.exports = async function getIllusts(user_id, token) { + return await axios({ + method: 'get', + url: 'https://app-api.pixiv.net/v1/user/illusts', + headers: { + ...maskHeader, + 'Authorization': 'Bearer ' + token + }, + params: { + user_id: user_id, + filter: 'for_ios', + type: 'illust' + }, + }) +} diff --git a/routes/pixiv/api/getRanking.js b/routes/pixiv/api/getRanking.js new file mode 100644 index 000000000..1f30dbef0 --- /dev/null +++ b/routes/pixiv/api/getRanking.js @@ -0,0 +1,33 @@ +const axios = require('axios'); +const maskHeader = require('../constants').maskHeader; +const assert = require('assert'); + +const allowMode = [ + 'day', 'week', 'month', 'day_male', 'day_female', 'week_original', 'week_rookie', 'day_r18', 'day_male_r18', 'day_female_r18', 'week_r18', 'week_r18g' +]; + +/** + * 获取某天的排行榜 + * @param {string} mode 模式 + * @param {Date} date 日期 + * @param {string} token pixiv oauth token + * @returns {Promise>} + */ +module.exports = async function getRanking(mode, date, token) { + assert(allowMode.includes(mode), 'Mode not allow.'); + return await axios({ + method: 'get', + url: 'https://app-api.pixiv.net/v1/illust/ranking', + headers: { + ...maskHeader, + 'Authorization': 'Bearer ' + token + }, + params: { + mode: mode, + filter: 'for_ios', + ...(date && { + date: `${date.getFullYear()}-${date.getMonth() + 1}-${date.getDate()}` + }) + }, + }); +} \ No newline at end of file diff --git a/routes/pixiv/api/getUserDetail.js b/routes/pixiv/api/getUserDetail.js new file mode 100644 index 000000000..45c718090 --- /dev/null +++ b/routes/pixiv/api/getUserDetail.js @@ -0,0 +1,29 @@ + +const axios = require('axios'); +const maskHeader = require('../constants').maskHeader; + +/** + * pixiv 用户 + * @typedef {{user: {id: number, name: string, account: string, profile_image_urls: any, comment: string}, profile: any} userDetail + */ + +/** + * 获取用户信息 + * + * @param {string} user_id 目标用户id + * @param {string} token pixiv oauth token + * @returns {Promise>} + */ +module.exports = async function getUserDetail(user_id, token) { + return await axios({ + method: 'get', + url: 'https://app-api.pixiv.net/v1/user/detail', + headers: { + ...maskHeader, + 'Authorization': 'Bearer ' + token + }, + params: { + user_id: user_id + }, + }); +} \ No newline at end of file diff --git a/routes/pixiv/bookmarks.js b/routes/pixiv/bookmarks.js new file mode 100644 index 000000000..8b2ff56e7 --- /dev/null +++ b/routes/pixiv/bookmarks.js @@ -0,0 +1,51 @@ +const config = require('../../config'); + +const pixivConfig = config.pixiv; + +if (!pixivConfig) { + module.exports = () => {}; + return; +} + +const template = require('../../utils/template'); +const getToken = require('./token'); +const getBookmarks = require('./api/getBookmarks'); +const getUserDetail = require('./api/getUserDetail'); + +module.exports = async (ctx) => { + const id = ctx.params.id; + + if (typeof getToken() === 'null') { + ctx.throw(500); + return; + } + + const [bookmarksResponse, userDetailResponse] = await Promise.all([ + getBookmarks(id, getToken()), + getUserDetail(id, getToken()) + ]); + + const illusts = bookmarksResponse.data.illusts; + const username = userDetailResponse.data.user.name + + ctx.body = template({ + title: `${username} 的收藏`, + link: `https://www.pixiv.net/bookmark.php?id=${id}`, + description: `${username} 的 pixiv 最新收藏`, + item: illusts.map((illust, index) => { + const images = []; + if (illust.page_count === 1) { + images.push(`

`); + } else { + for (let i = 0; i < illust.page_count; i++) { + images.push(`

`); + } + } + return { + title: `${illust.title}`, + description: `

画师:${illust.user.name} - 上传于:${new Date(illust.create_date).toLocaleString('zh-cn')} - 阅览数:${illust.total_view} - 收藏数:${illust.total_bookmarks}

${images.join('')}`, + link: `https://www.pixiv.net/member_illust.php?mode=medium&illust_id=${illust.id}` + }; + }) + }); +}; \ No newline at end of file diff --git a/routes/pixiv/ranking.js b/routes/pixiv/ranking.js index 24566d2cb..37a1ef8bf 100644 --- a/routes/pixiv/ranking.js +++ b/routes/pixiv/ranking.js @@ -8,18 +8,9 @@ if (!pixivConfig) { return; } -const axios = require('axios'); -const art = require('art-template'); -const path = require('path'); -const FormData = require('form-data'); +const template = require('../../utils/template'); const getToken = require('./token'); -const maskHeader = require('./constants').maskHeader; -const assert = require('assert'); -const util = require('util'); - -const allowMode = [ - 'day', 'week', 'month', 'day_male', 'day_female', 'week_original', 'week_rookie', 'day_r18', 'day_male_r18', 'day_female_r18', 'week_r18', 'week_r18g' -]; +const getRanking = require('./api/getRanking'); const titles = { 'day': 'pixiv 日排行', @@ -55,38 +46,21 @@ module.exports = async (ctx) => { const mode = ctx.params.mode; const date = ctx.params.date ? new Date(ctx.params.date) : new Date(); - assert(allowMode.includes(mode), 'Mode not allow.'); - if (typeof getToken() === 'null') { ctx.throw(500); return; } - const response = await axios({ - method: 'get', - url: 'https://app-api.pixiv.net/v1/illust/ranking', - headers: { - ...maskHeader, - 'Authorization': 'Bearer ' + getToken() - }, - params: { - mode: mode, - filter: 'for_ios', - ...(ctx.params.date && { - date: `${date.getFullYear()}-${date.getMonth() + 1}-${date.getDate()}` - }) - }, - }); + const response = await getRanking(mode, ctx.params.date && date, getToken()); const illusts = response.data.illusts; const dateStr = `${date.getFullYear()}年${date.getMonth() + 1}月${date.getDate()}日 `; - ctx.body = art(path.resolve(__dirname, '../../views/rss.art'), { + ctx.body = template({ title: (ctx.params.date ? dateStr : '') + titles[mode], link: links[mode], description: dateStr + titles[mode], - lastBuildDate: new Date().toUTCString(), item: illusts.map((illust, index) => { const images = []; if (illust.page_count === 1) { diff --git a/routes/pixiv/user.js b/routes/pixiv/user.js index b76d426c9..644bb2ce4 100644 --- a/routes/pixiv/user.js +++ b/routes/pixiv/user.js @@ -8,12 +8,9 @@ if (!pixivConfig) { return; } -const axios = require('axios'); -const art = require('art-template'); -const path = require('path'); -const FormData = require('form-data'); +const template = require('../../utils/template'); const getToken = require('./token'); -const maskHeader = require('./constants').maskHeader; +const getIllusts = require('./api/getIllusts'); module.exports = async (ctx) => { const id = ctx.params.id; @@ -23,28 +20,15 @@ module.exports = async (ctx) => { return; } - const response = await axios({ - method: 'get', - url: 'https://app-api.pixiv.net/v1/user/illusts', - headers: { - ...maskHeader, - 'Authorization': 'Bearer ' + getToken() - }, - params: { - user_id: id, - filter: 'for_ios', - type: 'illust' - }, - }); + const response = await getIllusts(id, getToken()); const illusts = response.data.illusts; const username = illusts[0].user.name - ctx.body = art(path.resolve(__dirname, '../../views/rss.art'), { + ctx.body = template({ title: `${username} 的 pixiv 动态`, link: `https://www.pixiv.net/member.php?id=${id}`, description: `${username} 的 pixiv 最新动态`, - lastBuildDate: new Date().toUTCString(), item: illusts.map((illust) => { const images = []; if (illust.page_count === 1) { diff --git a/routes/tieba/forum.js b/routes/tieba/forum.js index 4ecaed97d..e2f41ed8f 100644 --- a/routes/tieba/forum.js +++ b/routes/tieba/forum.js @@ -1,6 +1,5 @@ const axios = require('axios'); -const art = require('art-template'); -const path = require('path'); +const template = require('../../utils/template'); const cheerio = require('cheerio'); const config = require('../../config'); @@ -55,10 +54,9 @@ module.exports = async (ctx) => { const $ = cheerio.load(threadListHTML); const list = $('#thread_list > .j_thread_list[data-field]'); - ctx.body = art(path.resolve(__dirname, '../../views/rss.art'), { + ctx.body = template({ title: `${kw}吧`, link: `https://tieba.baidu.com/f?kw=${encodeURIComponent(kw)}`, - lastBuildDate: new Date().toUTCString(), item: list && list. diff --git a/routes/toutiao/today.js b/routes/toutiao/today.js new file mode 100644 index 000000000..e2fb65b1a --- /dev/null +++ b/routes/toutiao/today.js @@ -0,0 +1,35 @@ +const axios = require('axios'); +const template = require('../../utils/template'); +const cheerio = require('cheerio'); +const config = require('../../config'); + +const baseUrl = 'https://toutiao.io' +module.exports = async (ctx)=>{ + const response = await axios({ + method:'get', + url:baseUrl, + headers: { + 'User-Agent': config.ua, + 'Host':'toutiao.io' + }, + responseType: 'text' + }); + const $ = cheerio.load(response.data); + const title = $('#daily').find('.date>span').eq(0).text() + ' ' + $('#daily').find('.date>small').eq(0).text(); + + const list = $('.posts>.post', '#daily'); + const article_item = []; + for(let i=0;i{ + const id = ctx.params.id; + let requestUrl = `${baseUrl}/subjects/${id}?f=new`; + const response = await axios({ + method:'get', + url:requestUrl, + headers: { + 'User-Agent': config.ua, + 'Host':'toutiao.io' + }, + responseType: 'text' + }); + const $ = cheerio.load(response.data); + const image = $('#main').find('.text-center>.subject-cover>img').eq(0).attr('src'); + const link = requestUrl; + const title = $('#main').find('.text-center>h3').eq(0).text(); + const description = $('#main').find('.social-share-button').eq(0).attr('data-title'); + + const list = $('.posts>.post', '#main'); + const article_item = []; + for(let i=0;i { const projectID = ctx.params.project; @@ -19,11 +19,10 @@ module.exports = async (ctx) => { }); const data = response.data.data; - ctx.body = art(path.resolve(__dirname, '../../views/rss.art'), { + ctx.body = template({ title: `${projectID} 的 吐个槽新帖`, link: `https://support.qq.com/product/${projectID}`, description: `${projectID} 的 吐个槽新帖`, - lastBuildDate: new Date().toUTCString(), item: data.map((item) => { let pubdate = new Date(item.created_at.replace(' ', 'T') + "+08:00"); let imgHTML = ''; diff --git a/routes/weibo/user.js b/routes/weibo/user.js index ed5129960..f61318155 100644 --- a/routes/weibo/user.js +++ b/routes/weibo/user.js @@ -1,6 +1,5 @@ const axios = require('axios'); -const art = require('art-template'); -const path = require('path'); +const template = require('../../utils/template'); const config = require('../../config'); // 格式化每条微博的HTML @@ -42,7 +41,6 @@ function format (status) { // 格式化时间 function getTime (html) { - console.log(html); let math; let date = new Date(); if (/(\d+)分钟前/.exec(html)) { @@ -63,7 +61,15 @@ function getTime (html) { return date.toUTCString(); } else if (/(\d+)月(\d+)日 (\d+):(\d+)/.exec(html)) { math = /(\d+)月(\d+)日 (\d+):(\d+)/.exec(html); - date = new Date(date.getFullYear(), math[1] - 1, parseInt(math[2]), math[3], math[4]); + date = new Date(date.getFullYear(), parseInt(math[1]) - 1, math[2], math[3], math[4]); + return date.toUTCString(); + } else if (/(\d+)-(\d+)-(\d+)/.exec(html)) { + math = /(\d+)-(\d+)-(\d+)/.exec(html); + date = new Date(math[1], parseInt(math[2]) - 1, math[3]); + return date.toUTCString(); + } else if (/(\d+)-(\d+)/.exec(html)) { + math = /(\d+)-(\d+)/.exec(html); + date = new Date(date.getFullYear(), parseInt(math[1]) - 1, math[2]); return date.toUTCString(); } return html; @@ -92,11 +98,10 @@ module.exports = async (ctx) => { } }); - ctx.body = art(path.resolve(__dirname, '../../views/rss.art'), { + ctx.body = template({ title: `${name}的微博`, link: `http://weibo.com/${uid}/`, description: `${name}的微博`, - lastBuildDate: new Date().toUTCString(), item: response.data.data.cards.filter((item) => item.mblog && !item.mblog.isTop).map((item) => { const title = item.mblog.text.replace(/<.*?>/g, ''); return { diff --git a/routes/zhihu/activities.js b/routes/zhihu/activities.js index 5caeaf33c..cb22c561c 100644 --- a/routes/zhihu/activities.js +++ b/routes/zhihu/activities.js @@ -1,6 +1,5 @@ const axios = require('axios'); -const art = require('art-template'); -const path = require('path'); +const template = require('../../utils/template'); const cheerio = require('cheerio'); const config = require('../../config'); @@ -24,11 +23,10 @@ module.exports = async (ctx) => { const name = data.users[id].name; const list = Object.values(data.activities).sort((a, b) => b.createdTime - a.createdTime); - ctx.body = art(path.resolve(__dirname, '../../views/rss.art'), { + ctx.body = template({ title: `${name}的知乎动态`, link: `https://www.zhihu.com/people/${id}/activities`, description: data.users[id].headline || data.users[id].description, - lastBuildDate: new Date().toUTCString(), item: list && list.map((item) => { const type = item.target.schema; const detail = data[`${type}s`][item.target.id]; @@ -49,7 +47,19 @@ module.exports = async (ctx) => { break; case 'pin': title = detail.excerptTitle.length > 17 ? detail.excerptTitle.slice(0, 17) + '...' : detail.excerptTitle; - description = detail.excerptTitle; + const images = []; + let text = ""; + let link = ""; + detail.content.forEach(contentItem => { + if (contentItem.type === "text") { + text = `

${contentItem.ownText}

`; + } else if (contentItem.type === "image") { + images.push(`

`); + } else if (contentItem.type === "link") { + link = `

${contentItem.title}

` + } + }) + description = `${text}${link}${images.join('')}`; url = `https://www.zhihu.com/pin/${detail.id}`; break; case 'question': @@ -57,6 +67,11 @@ module.exports = async (ctx) => { description = detail.excerpt; url = `https://www.zhihu.com/question/${detail.id}`; break; + case 'column': + title = detail.title; + description = `

${detail.intro}

`; + url = `${detail.url}`; + break; } return { @@ -67,4 +82,4 @@ module.exports = async (ctx) => { }; }), }); -}; \ No newline at end of file +}; diff --git a/routes/zhihu/collection.js b/routes/zhihu/collection.js index c3375b48a..2f0dbecfa 100644 --- a/routes/zhihu/collection.js +++ b/routes/zhihu/collection.js @@ -1,6 +1,5 @@ const axios = require('axios'); -const art = require('art-template'); -const path = require('path'); +const template = require('../../utils/template'); const cheerio = require('cheerio'); const config = require('../../config'); @@ -20,14 +19,13 @@ module.exports = async (ctx) => { const $ = cheerio.load(data); const list = $('div.zm-item'); - ctx.body = art(path.resolve(__dirname, '../../views/rss.art'), { + ctx.body = template({ title: $('title').text(), link: `https://www.zhihu.com/collection/${id}`, description: `${$('#zh-fav-head-description').text()}`, - lastBuildDate: new Date().toUTCString(), item: list && list.map((index, item) => { item = $(item); - let linkUrl = item.find('.zm-item-title a').attr('href'); + let linkUrl = item.find('link').attr('href'); if (linkUrl.startsWith('/')) linkUrl = 'https://www.zhihu.com' + linkUrl; return { title: item.find('.zm-item-title a').text(), diff --git a/routes/zhihu/zhuanlan.js b/routes/zhihu/zhuanlan.js index e77e9c887..549c68781 100644 --- a/routes/zhihu/zhuanlan.js +++ b/routes/zhihu/zhuanlan.js @@ -1,6 +1,5 @@ const axios = require('axios'); -const art = require('art-template'); -const path = require('path'); +const template = require('../../utils/template'); const config = require('../../config'); module.exports = async (ctx) => { @@ -26,11 +25,10 @@ module.exports = async (ctx) => { const list = listRes.data; const info = infoRes.data; - ctx.body = art(path.resolve(__dirname, '../../views/rss.art'), { + ctx.body = template({ title: `知乎专栏-${info.name}`, link: `https://zhuanlan.zhihu.com/${id}`, description: info.description, - lastBuildDate: new Date().toUTCString(), item: list.map((item) => ({ title: item.title, description: item.content.replace(/ ({ title: item.title, description: `${item.room_name}`, diff --git a/utils/md5.js b/utils/md5.js new file mode 100644 index 000000000..d656c1dca --- /dev/null +++ b/utils/md5.js @@ -0,0 +1,5 @@ +const crypto = require('crypto'); + +module.exports = function md5(date) { + return crypto.createHash('md5').update(date).digest("hex"); +} diff --git a/utils/template.js b/utils/template.js new file mode 100644 index 000000000..bc3ba1bf0 --- /dev/null +++ b/utils/template.js @@ -0,0 +1,11 @@ +const art = require('art-template'); +const path = require('path'); +const config = require('../config'); + +module.exports = function (options) { + return art(path.resolve(__dirname, '../views/rss.art'), { + lastBuildDate: new Date().toUTCString(), + ttl: config.cacheExpire, + ...options, + }); +}; \ No newline at end of file diff --git a/views/rss.art b/views/rss.art index 375284955..e6a09f46d 100644 --- a/views/rss.art +++ b/views/rss.art @@ -2,7 +2,7 @@ <![CDATA[{{ title || 'RSSHub' }}]]> - {{ link }} + {{ link || 'https://github.com/DIYgod/RSSHub' }} RSSHub i@html.love @@ -15,7 +15,7 @@ {{ /if }} {{ lastBuildDate }} - 300 + {{ ttl }} {{ each item }} <![CDATA[{{ $value.title }}]]>