feat(route/twitter): allow force using Web API (#9760)
Signed-off-by: Rongrong <i@rong.moe>
This commit is contained in:
parent
9e32a7971e
commit
bab100a487
|
|
@ -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
|
||||
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 | 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 |
|
||||
| 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 readablility. The URL
|
||||
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
|
||||
|
||||
<RouteEn path="/twitter/user/:id/:routeParams?" example="/twitter/user/DIYgod" :paramsDesc="['user id', 'extra parameters, see the table above; particularly when `routeParams=exclude_replies`, replies are excluded; `routeParams=exclude_rts` excludes retweets,`routeParams=exclude_rts_replies` exclude replies and retweets; for default include all.']" radar="1" rssbud="1"/>
|
||||
<RouteEn author="DIYgod yindaheng98 Rongronggg9" path="/twitter/user/:id/:routeParams?" example="/twitter/user/DIYgod" :paramsDesc="['user id', 'extra parameters, see the table above; particularly when `routeParams=exclude_replies`, replies are excluded; `routeParams=exclude_rts` excludes retweets,`routeParams=exclude_rts_replies` exclude replies and retweets; for default include all.']" radar="1" rssbud="1"/>
|
||||
|
||||
### User media
|
||||
|
||||
<RouteEn author="yindaheng98" path="/twitter/media/:id/:routeParams?" example="/twitter/media/DIYgod" :paramsDesc="['user id', 'extra parameters, see the table above.']" radar="1" rssbud="1"/>
|
||||
<RouteEn author="yindaheng98 Rongronggg9" path="/twitter/media/:id/:routeParams?" example="/twitter/media/DIYgod" :paramsDesc="['user id', 'extra parameters, see the table above.']" radar="1" rssbud="1"/>
|
||||
|
||||
## User following timeline
|
||||
|
||||
|
|
@ -371,7 +375,7 @@ This route requires Twitter token's corresponding id, therefore it's only availa
|
|||
|
||||
### Keyword
|
||||
|
||||
<RouteEn author="DIYgod" example="/twitter/keyword/RSSHub" path="/twitter/keyword/:keyword/:routeParams?" :paramsDesc="['keyword', 'extra parameters, see the table above']" radar="1" rssbud="1"/>
|
||||
<RouteEn author="DIYgod yindaheng98 Rongronggg9" example="/twitter/keyword/RSSHub" path="/twitter/keyword/:keyword/:routeParams?" :paramsDesc="['keyword', 'extra parameters, see the table above']" radar="1" rssbud="1"/>
|
||||
|
||||
### Trends
|
||||
|
||||
|
|
|
|||
|
|
@ -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 阅读器可能将同一条
|
|||
|
||||
### 用户时间线
|
||||
|
||||
<Route author="DIYgod" example="/twitter/user/DIYgod" path="/twitter/user/:id/:routeParams?" :paramsDesc="['用户名', '额外参数;请参阅上面的说明和表格;特别地,当 `routeParams=exclude_replies`时去除回复,`routeParams=exclude_rts`去除转推,`routeParams=exclude_rts_replies`去除回复和转推,默认包含全部回复和转推。']" radar="1" rssbud="1"/>
|
||||
<Route author="DIYgod yindaheng98 Rongronggg9" example="/twitter/user/DIYgod" path="/twitter/user/:id/:routeParams?" :paramsDesc="['用户名', '额外参数;请参阅上面的说明和表格;特别地,当 `routeParams=exclude_replies`时去除回复,`routeParams=exclude_rts`去除转推,`routeParams=exclude_rts_replies`去除回复和转推,默认包含全部回复和转推。']" radar="1" rssbud="1"/>
|
||||
|
||||
### 用户媒体时间线
|
||||
|
||||
<Route author="yindaheng98" example="/twitter/media/DIYgod" path="/twitter/media/:id/:routeParams?" :paramsDesc="['用户名', '额外参数;请参阅上面的说明和表格。']" radar="1" rssbud="1"/>
|
||||
<Route author="yindaheng98 Rongronggg9" example="/twitter/media/DIYgod" path="/twitter/media/:id/:routeParams?" :paramsDesc="['用户名', '额外参数;请参阅上面的说明和表格。']" radar="1" rssbud="1"/>
|
||||
|
||||
### 用户关注时间线
|
||||
|
||||
|
|
@ -732,7 +736,7 @@ Instagram Stories 没有可靠的 guid,你的 RSS 阅读器可能将同一条
|
|||
|
||||
### 关键词
|
||||
|
||||
<Route author="DIYgod" example="/twitter/keyword/RSSHub" path="/twitter/keyword/:keyword/:routeParams?/limit?" :paramsDesc="['关键词', '额外参数;请参阅上面的说明和表格', '查询前多少条']" radar="1" rssbud="1"/>
|
||||
<Route author="DIYgod yindaheng98 Rongronggg9" example="/twitter/keyword/RSSHub" path="/twitter/keyword/:keyword/:routeParams?/limit?" :paramsDesc="['关键词', '额外参数;请参阅上面的说明和表格', '查询前多少条']" radar="1" rssbud="1"/>
|
||||
|
||||
### Trends
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
};
|
||||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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 = {
|
||||
|
|
|
|||
Loading…
Reference in New Issue