feat: 添加饭否用户时间线、当前登录用户的时间线、用户收藏、热门话题、搜索 (#3427)

This commit is contained in:
junbaor
2019-11-21 10:59:21 +08:00
committed by DIYgod
parent a541df4ced
commit 1d61677e76
12 changed files with 280 additions and 4 deletions
+7
View File
@@ -425,3 +425,10 @@ RSSHub 支持 `memory` 和 `redis` 两种缓存方式
- `WEIBO_APP_KEY`: 微博 App Key
- `WEIBO_APP_SECRET`: 微博 App Secret
- `WEIBO_REDIRECT_URL`: 微博登录授权回调地址,默认为 `RSSHub地址/weibo/timeline/0`,自定义回调地址请确保最后可以转跳到 `RSSHub地址/weibo/timeline/0?code=xxx`
- 饭否 全部路由: [申请地址](https://github.com/FanfouAPI/FanFouAPIDoc/wiki/Oauth)
- `FANFOU_CONSUMER_KEY`: 饭否 Consumer Key
- `FANFOU_CONSUMER_SECRET`: 饭否 Consumer Secret
- `FANFOU_USERNAME`: 饭否登录用户名、邮箱、手机号
- `FANFOU_PASSWORD`: 饭否密码
+26
View File
@@ -510,6 +510,32 @@ pageClass: routes
<Route author="xyqfer" example="/douyin/like/93610979153" path="/douyin/like/:id" :paramsDesc="['用户 id, 可在 分享出去获得的用户主页 URL 中找到']"/>
## 饭否
::: warning 注意
部署时需要申请并配置饭否 Consumer Key、Consumer Secret、用户名和密码,具体见部署文档
:::
### 用户动态
<Route author="junbaor" example="/fanfou/user_timeline/wangxing" path="/fanfou/user_timeline/:uid" :paramsDesc="['用户的uid']" anticrawler="1"/>
### 当前登录用户的时间线
<Route author="junbaor" example="/fanfou/home_timeline" path="/fanfou/home_timeline" anticrawler="1"/>
### 用户收藏
<Route author="junbaor" example="/fanfou/favorites/wangxing" path="/fanfou/favorites/:uid" :paramsDesc="['用户的uid']" anticrawler="1"/>
### 热门话题
<Route author="junbaor" example="/fanfou/trends" path="/fanfou/trends" anticrawler="1"/>
### 饭否搜索
<Route author="junbaor" example="/fanfou/public_timeline/冬天" path="/fanfou/public_timeline/:keyword" :paramsDesc="['关键字']" anticrawler="1"/>
## 方格子
### 出版專題
+6
View File
@@ -100,6 +100,12 @@ const calculateValue = () => {
app_secret: envs.WEIBO_APP_SECRET,
redirect_url: envs.WEIBO_REDIRECT_URL,
},
fanfou: {
consumer_key: envs.FANFOU_CONSUMER_KEY,
consumer_secret: envs.FANFOU_CONSUMER_SECRET,
username: envs.FANFOU_USERNAME,
password: envs.FANFOU_PASSWORD,
},
};
};
calculateValue();
+7
View File
@@ -1953,4 +1953,11 @@ router.get('/alter-cn/news', require('./routes/alter-cn/news'));
// Visual Studio Code Marketplace
router.get('/vscode/marketplace/:type?', require('./routes/vscode/marketplace'));
// 饭否
router.get('/fanfou/user_timeline/:uid', require('./routes/fanfou/user_timeline'));
router.get('/fanfou/home_timeline', require('./routes/fanfou/home_timeline'));
router.get('/fanfou/favorites/:uid', require('./routes/fanfou/favorites'));
router.get('/fanfou/trends', require('./routes/fanfou/trends'));
router.get('/fanfou/public_timeline/:keyword', require('./routes/fanfou/public_timeline'));
module.exports = router;
+39
View File
@@ -0,0 +1,39 @@
const config = require('@/config').value;
const utils = require('./utils');
module.exports = async (ctx) => {
if (!config.fanfou || !config.fanfou.consumer_key || !config.fanfou.consumer_secret || !config.fanfou.username || !config.fanfou.password) {
throw 'Fanfou RSS is disabled due to the lack of <a href="https://docs.rsshub.app/install/#bu-fen-rss-mo-kuai-pei-zhi">relevant config</a>';
}
const uid = ctx.params.uid;
const fanfou = await utils.getFanfou();
const timeline = await fanfou.get(`/favorites/${uid}`, { id: uid, mode: 'lite', format: 'html' });
const result = await Promise.all(
timeline.map(async (item) => {
let img_html = '';
if (item.photo) {
img_html = `<br/><img src="${item.photo.largeurl}" alt="饭否动态图片"/>`;
}
const voItem = {
title: item.text,
author: item.user.name,
description: item.text + img_html,
pubDate: item.created_at,
link: `https://fanfou.com/statuses/${item.id}`,
};
return Promise.resolve(voItem);
})
);
const users = await fanfou.get(`/users/show`, { id: uid });
const authorName = users.screen_name;
ctx.state.data = {
title: `${authorName}的饭否收藏`,
link: `https://fanfou.com/favorites/${uid}`,
description: `${authorName}的饭否收藏`,
item: result,
};
};
+35
View File
@@ -0,0 +1,35 @@
const config = require('@/config').value;
const utils = require('./utils');
module.exports = async (ctx) => {
if (!config.fanfou || !config.fanfou.consumer_key || !config.fanfou.consumer_secret || !config.fanfou.username || !config.fanfou.password) {
throw 'Fanfou RSS is disabled due to the lack of <a href="https://docs.rsshub.app/install/#bu-fen-rss-mo-kuai-pei-zhi">relevant config</a>';
}
const fanfou = await utils.getFanfou();
const timeline = await fanfou.get('/statuses/home_timeline', { mode: 'lite', format: 'html' });
const result = await Promise.all(
timeline.map(async (item) => {
let img_html = '';
if (item.photo) {
img_html = `<br/><img src="${item.photo.originurl}" alt="饭否动态图片"/>`;
}
const voItem = {
title: item.plain_text,
author: item.user.name,
description: item.text + img_html,
pubDate: item.created_at,
link: `http://fanfou.com/statuses/${item.id}`,
};
return Promise.resolve(voItem);
})
);
ctx.state.data = {
title: `我的饭否动态`,
link: `https://fanfou.com/home`,
description: `我的饭否动态`,
item: result,
};
};
+36
View File
@@ -0,0 +1,36 @@
const config = require('@/config').value;
const utils = require('./utils');
module.exports = async (ctx) => {
if (!config.fanfou || !config.fanfou.consumer_key || !config.fanfou.consumer_secret || !config.fanfou.username || !config.fanfou.password) {
throw 'Fanfou RSS is disabled due to the lack of <a href="https://docs.rsshub.app/install/#bu-fen-rss-mo-kuai-pei-zhi">relevant config</a>';
}
const keyword = ctx.params.keyword;
const fanfou = await utils.getFanfou();
const timeline = await fanfou.get('/search/public_timeline', { q: keyword, mode: 'lite', format: 'html' });
const result = await Promise.all(
timeline.map(async (item) => {
let img_html = '';
if (item.photo) {
img_html = `<br/><img src="${item.photo.originurl}" alt="饭否动态图片"/>`;
}
const voItem = {
title: item.plain_text,
author: item.user.name,
description: item.text + img_html,
pubDate: item.created_at,
link: `https://fanfou.com/statuses/${item.id}`,
};
return Promise.resolve(voItem);
})
);
ctx.state.data = {
title: `饭否搜索-${keyword}`,
link: `https://fanfou.com/q/${keyword}`,
description: `饭否搜索-${keyword}`,
item: result,
};
};
+25
View File
@@ -0,0 +1,25 @@
const utils = require('./utils');
module.exports = async (ctx) => {
const fanfou = await utils.getFanfou();
const response = await fanfou.get(`/trends/list`);
const result = await Promise.all(
response.trends.map(async (item) => {
const voItem = {
title: item.name,
description: item.name,
pubDate: new Date(),
link: item.url,
};
return Promise.resolve(voItem);
})
);
ctx.state.data = {
title: `饭否热门话题`,
link: `https://fanfou.com/q/`,
description: `饭否热门话题`,
item: result,
};
};
+38
View File
@@ -0,0 +1,38 @@
const config = require('@/config').value;
const utils = require('./utils');
module.exports = async (ctx) => {
if (!config.fanfou || !config.fanfou.consumer_key || !config.fanfou.consumer_secret || !config.fanfou.username || !config.fanfou.password) {
throw 'Fanfou RSS is disabled due to the lack of <a href="https://docs.rsshub.app/install/#bu-fen-rss-mo-kuai-pei-zhi">relevant config</a>';
}
const uid = ctx.params.uid;
const fanfou = await utils.getFanfou();
const timeline = await fanfou.get('/statuses/user_timeline', { id: uid, mode: 'lite', format: 'html' });
const result = await Promise.all(
timeline.map(async (item) => {
let img_html = '';
if (item.photo) {
img_html = `<br/><img src="${item.photo.originurl}" alt="饭否动态图片"/>`;
}
const voItem = {
title: item.plain_text,
author: item.user.name,
description: item.text + img_html,
pubDate: item.created_at,
link: `https://fanfou.com/statuses/${item.id}`,
};
return Promise.resolve(voItem);
})
);
const authorName = result[0].author;
ctx.state.data = {
title: `${authorName}的饭否`,
link: `https://fanfou.com/${uid}`,
description: `${authorName}的饭否`,
item: result,
};
};
+34
View File
@@ -0,0 +1,34 @@
const logger = require('@/utils/logger');
const config = require('@/config').value;
const Fanfou = require('fanfou-sdk');
const consumerKey = config.fanfou.consumer_key;
const consumerSecret = config.fanfou.consumer_secret;
const username = config.fanfou.username;
const password = config.fanfou.password;
let fanfou_client;
let authed = false;
const getFanfou = async () => {
if (authed === true) {
return fanfou_client;
} else {
fanfou_client = new Fanfou({
consumerKey,
consumerSecret,
username,
password,
});
await fanfou_client.xauth();
logger.info('Fanfou login success.');
authed = true;
return fanfou_client;
}
};
module.exports = {
getFanfou,
};
+1
View File
@@ -70,6 +70,7 @@
"dotenv": "8.2.0",
"emailjs-imap-client": "3.0.7",
"etag": "1.8.1",
"fanfou-sdk": "4.0.5",
"form-data": "3.0.0",
"git-rev-sync": "1.12.0",
"googleapis": "45.0.0",
+26 -4
View File
@@ -4458,6 +4458,18 @@ extsprintf@^1.2.0:
resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.0.tgz#e2689f8f356fad62cca65a3a91c5df5f9551692f"
integrity sha1-4mifjzVvrWLMplo6kcXfX5VRaS8=
fanfou-sdk@4.0.5:
version "4.0.5"
resolved "https://registry.yarnpkg.com/fanfou-sdk/-/fanfou-sdk-4.0.5.tgz#5b3f2ab5ee8a383fc21ab58bc6c1ed97cbce7113"
integrity sha512-s3Ec5D3Am5daLQtu9IwkVWPSV40Tg//jPJVAYbLVMITLvCgq58H2ufJ5bgfsQAJrQXVL0ZhkN+mwhgp/4BJzXA==
dependencies:
form-data "^2.3.3"
got "^9.5.1"
he "^1.1.1"
hmacsha1 "^1.0.0"
oauth-1.0a "^2.2.5"
query-string "^6.2.0"
fast-deep-equal@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz#7b05218ddf9667bf7f370bf7fdb2cb15fdd0aa49"
@@ -4682,7 +4694,7 @@ form-data@3.0.0:
combined-stream "^1.0.8"
mime-types "^2.1.12"
form-data@^2.3.1, form-data@^2.5.0:
form-data@^2.3.1, form-data@^2.3.3, form-data@^2.5.0:
version "2.5.1"
resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.5.1.tgz#f2cbec57b5e59e23716e128fe44d4e5dd23895f4"
integrity sha512-m21N3WOmEEURgk6B9GLOE4RuWOFf28Lhh9qGYeNlGq4VDXUlJy2th2slBNU8Gp8EzloYZOibZJ7t5ecIrFSjVA==
@@ -5046,7 +5058,7 @@ googleapis@45.0.0:
google-auth-library "^5.2.0"
googleapis-common "^3.1.0"
got@9.6.0:
got@9.6.0, got@^9.5.1:
version "9.6.0"
resolved "https://registry.yarnpkg.com/got/-/got-9.6.0.tgz#edf45e7d67f99545705de1f7bbeeeb121765ed85"
integrity sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q==
@@ -5225,7 +5237,7 @@ hash.js@^1.0.0, hash.js@^1.0.3:
inherits "^2.0.3"
minimalistic-assert "^1.0.1"
he@1.2.0, he@1.2.x, he@^1.1.0, he@^1.2.0:
he@1.2.0, he@1.2.x, he@^1.1.0, he@^1.1.1, he@^1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f"
integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==
@@ -5249,6 +5261,11 @@ hmac-drbg@^1.0.0:
minimalistic-assert "^1.0.0"
minimalistic-crypto-utils "^1.0.1"
hmacsha1@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/hmacsha1/-/hmacsha1-1.0.0.tgz#c1b7ae03a4ea116348090af14f8148c12938a917"
integrity sha1-wbeuA6TqEWNICQrxT4FIwSk4qRc=
hogan.js@^3.0.2:
version "3.0.2"
resolved "https://registry.yarnpkg.com/hogan.js/-/hogan.js-3.0.2.tgz#4cd9e1abd4294146e7679e41d7898732b02c7bfd"
@@ -7871,6 +7888,11 @@ nwsapi@^2.0.7, nwsapi@^2.2.0:
resolved "https://registry.yarnpkg.com/nwsapi/-/nwsapi-2.2.0.tgz#204879a9e3d068ff2a55139c2c772780681a38b7"
integrity sha512-h2AatdwYH+JHiZpv7pt/gSX1XoRGb7L/qSIeuqA6GwYoF9w1vP1cw42TO0aI2pNyshRK5893hNSl+1//vHK7hQ==
oauth-1.0a@^2.2.5:
version "2.2.6"
resolved "https://registry.yarnpkg.com/oauth-1.0a/-/oauth-1.0a-2.2.6.tgz#eadbccdb3bceea412d24586e6f39b2b412f0e491"
integrity sha512-6bkxv3N4Gu5lty4viIcIAnq5GbxECviMBeKR3WX/q87SPQ8E8aursPZUtsXDnxCs787af09WPRBLqYrf/lwoYQ==
oauth-sign@~0.9.0:
version "0.9.0"
resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455"
@@ -9039,7 +9061,7 @@ qs@~6.5.2:
resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36"
integrity sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==
query-string@6.9.0:
query-string@6.9.0, query-string@^6.2.0:
version "6.9.0"
resolved "https://registry.yarnpkg.com/query-string/-/query-string-6.9.0.tgz#1c3b727c370cf00f177c99f328fda2108f8fa3dd"
integrity sha512-KG4bhCFYapExLsUHrFt+kQVEegF2agm4cpF/VNc6pZVthIfCc/GK8t8VyNIE3nyXG9DK3Tf2EGkxjR6/uRdYsA==