mirror of
https://github.com/DIYgod/RSSHub.git
synced 2026-09-01 14:57:14 +08:00
feat: twitter following timeline
This commit is contained in:
+13
-1
@@ -251,7 +251,19 @@ If no matching results were found, the server returns only a HTTP status code `2
|
||||
|
||||
#### User timeline
|
||||
|
||||
<RouteEn path="/twitter/user/:id" example="/twitter/user/DIYgod" :paramsDesc="['user name']" />
|
||||
<RouteEn path="/twitter/user/:id" example="/twitter/user/DIYgod" :paramsDesc="['user id']" />
|
||||
|
||||
### User following timeline
|
||||
|
||||
<Route author="DIYgod" example="/twitter/followings/DIYgod" path="/twitter/followings/:id" :paramsDesc="['user id']">
|
||||
|
||||
::: warning
|
||||
|
||||
User following timeline needs Twitter token corresponding id, so this route is only for self-hosted, see Install - Route-specific Configurations for details
|
||||
|
||||
:::
|
||||
|
||||
</Route>
|
||||
|
||||
#### List timeline
|
||||
|
||||
|
||||
@@ -318,6 +318,8 @@ When adding feeds using RSS readers with HTTP Basic Authentication support, auth
|
||||
|
||||
- `TWITTER_CONSUMER_SECRET`: Twitter Consumer Secret, support multiple keys, split them with `,`
|
||||
|
||||
- `TWITTER_TOKEN_{id}`: Twitter token corresponding id, replace `{id}` with id, the value is splitting consumer_key consumer_secret access_token access_token_secret with `,`, `{consumer_key},{consumer_secret},{access_token},{access_token_secret}`
|
||||
|
||||
- `youtube`: [API Key application](https://console.developers.google.com/)
|
||||
|
||||
- `YOUTUBE_KEY`: YouTube API Key
|
||||
|
||||
@@ -384,6 +384,8 @@ RSSHub 支持 `memory` 和 `redis` 两种缓存方式
|
||||
|
||||
- `TWITTER_CONSUMER_SECRET`: Twitter Consumer Secret,支持多个 key,用英文逗号 `,` 隔开,顺序与 key 对应
|
||||
|
||||
- `TWITTER_TOKEN_{id}`: 对应 id 的 Twitter token,`{id}` 替换为 id,值为 consumer_key consumer_secret access_token access_token_secret 用逗号隔开,即:`{consumer_key},{consumer_secret},{access_token},{access_token_secret}`
|
||||
|
||||
- youtube 全部路由: [申请地址](https://console.developers.google.com/)
|
||||
|
||||
- `YOUTUBE_KEY`: YouTube API Key
|
||||
|
||||
@@ -362,6 +362,18 @@ pageClass: routes
|
||||
|
||||
<Route author="DIYgod" example="/twitter/user/DIYgod" path="/twitter/user/:id" :paramsDesc="['用户 twitter 名']"/>
|
||||
|
||||
### 用户关注时间线
|
||||
|
||||
<Route author="DIYgod" example="/twitter/followings/DIYgod" path="/twitter/followings/:id" :paramsDesc="['用户 twitter 名']">
|
||||
|
||||
::: warning 注意
|
||||
|
||||
用户关注时间线需要对应用户的 Twitter token, 所以只能自建,详情见部署页面的配置模块。
|
||||
|
||||
:::
|
||||
|
||||
</Route>
|
||||
|
||||
### 列表时间线
|
||||
|
||||
<Route author="xyqfer" example="/twitter/list/ladyleet/javascript" path="/twitter/list/:id/:name" :paramsDesc="['用户 twitter 名', 'list 名称']"/>
|
||||
|
||||
@@ -1,9 +1,13 @@
|
||||
const bilibili_cookies = {};
|
||||
const twitter_tokens = {};
|
||||
const envs = process.env;
|
||||
for (const name in envs) {
|
||||
if (name.startsWith('BILIBILI_COOKIE_')) {
|
||||
const uid = name.slice(16);
|
||||
bilibili_cookies[uid] = envs[name];
|
||||
} else if (name.startsWith('TWITTER_TOKEN_')) {
|
||||
const id = name.slice(14);
|
||||
twitter_tokens[id] = envs[name];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,6 +46,7 @@ module.exports = {
|
||||
twitter: {
|
||||
consumer_key: process.env.TWITTER_CONSUMER_KEY,
|
||||
consumer_secret: process.env.TWITTER_CONSUMER_SECRET,
|
||||
tokens: twitter_tokens,
|
||||
},
|
||||
youtube: {
|
||||
key: process.env.YOUTUBE_KEY,
|
||||
|
||||
@@ -180,6 +180,7 @@ if (config.twitter && config.twitter.consumer_key && config.twitter.consumer_sec
|
||||
} else {
|
||||
logger.warn('Twitter RSS is disabled due to the lack of token, api key or relevant config in config.js.');
|
||||
}
|
||||
router.get('/twitter/followings/:id', require('./routes/twitter/followings'));
|
||||
|
||||
// Instagram
|
||||
router.get('/instagram/user/:id', require('./routes/instagram/user'));
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
const utils = require('./utils');
|
||||
const config = require('@/config');
|
||||
const T = {};
|
||||
const Twit = require('twit');
|
||||
|
||||
module.exports = async (ctx) => {
|
||||
const id = ctx.params.id;
|
||||
const cookie = config.twitter.tokens[id];
|
||||
if (!cookie) {
|
||||
throw Error(`lacking twitter token for user ${id}`);
|
||||
} else if (!T[id]) {
|
||||
const token = cookie.split(',');
|
||||
T[id] = new Twit({
|
||||
consumer_key: token[0],
|
||||
consumer_secret: token[1],
|
||||
access_token: token[2],
|
||||
access_token_secret: token[3],
|
||||
});
|
||||
}
|
||||
|
||||
const result = await T[id].get('statuses/home_timeline', {
|
||||
tweet_mode: 'extended',
|
||||
count: 100,
|
||||
});
|
||||
const data = result.data;
|
||||
|
||||
ctx.state.data = {
|
||||
title: `${id} 的 Twitter 关注时间线`,
|
||||
link: `https://twitter.com/${id}/`,
|
||||
item: utils.ProcessFeed(
|
||||
{
|
||||
data,
|
||||
},
|
||||
true
|
||||
),
|
||||
};
|
||||
};
|
||||
@@ -2,7 +2,7 @@ const URL = require('url');
|
||||
const config = require('@/config');
|
||||
const Twit = require('twit');
|
||||
|
||||
const ProcessFeed = ({ data = [] }) => {
|
||||
const ProcessFeed = ({ data = [] }, showAuthor = false) => {
|
||||
const getQueryParams = (url) => URL.parse(url, true).query;
|
||||
const getOrigionImg = (url) => {
|
||||
// https://greasyfork.org/zh-CN/scripts/2312-resize-image-on-open-image-in-new-tab/code#n150
|
||||
@@ -100,8 +100,10 @@ const ProcessFeed = ({ data = [] }) => {
|
||||
}
|
||||
|
||||
return {
|
||||
title: `${item.in_reply_to_screen_name ? 'Re ' : ''}${formatText(item.full_text)}`,
|
||||
description: `${item.in_reply_to_screen_name ? 'Re ' : ''}${formatText(item.full_text)}${url}${img}${quote}`,
|
||||
title: `${showAuthor ? item.user.name + ': ' : ''}${item.in_reply_to_screen_name ? 'Re ' : ''}${formatText(item.full_text)}`,
|
||||
description: `${showAuthor ? `<img width="15px" referrerpolicy="no-referrer" src="${item.user.profile_image_url_https}"><strong>${item.user.name}:</strong><br><br>` : ''}${
|
||||
item.in_reply_to_screen_name ? 'Re ' : ''
|
||||
}${formatText(item.full_text)}${url}${img}${quote}`,
|
||||
pubDate: new Date(item.created_at).toUTCString(),
|
||||
link: `https://twitter.com/${item.user.screen_name}/status/${item.id_str}`,
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user