fix(route): allow Mastodon without extra config (#12672)
* fix(route): allow Mastodon without extra config * Maintain zh/en doc consistency and enhance the desc of reqs * Add description about Mastodon out of the box * refactor: migrate to v2 ---------
This commit is contained in:
parent
96209ceaab
commit
ef497881a7
|
|
@ -769,9 +769,9 @@ See docs of the specified route and `lib/config.js` for detailed information.
|
|||
|
||||
- Mastodon user timeline: apply API here `https://mastodon.example/settings/applications`(repalce `mastodon.example`), please check scope `read:search`
|
||||
|
||||
- `MASTODON_API_HOST`: API instance domain
|
||||
- `MASTODON_API_HOST`: API instance domain, only domain, no `http://` or `https://` protocol header
|
||||
- `MASTODON_API_ACCESS_TOKEN`: user access token
|
||||
- `MASTODON_API_ACCT_DOMAIN`: acct domain for particular instance
|
||||
- `MASTODON_API_ACCT_DOMAIN`: acct domain for particular instance, Webfinger account URI, like `user@host`
|
||||
|
||||
- Medium related routes: Open the console, copy the cookie (in theory, only uid and sid are required)
|
||||
|
||||
|
|
|
|||
|
|
@ -217,26 +217,36 @@ Official user RSS:
|
|||
- RSS: `https://**:instance**/users/**:username**.rss` ([Example](https://pawoo.net/users/pawoo_support.rss))
|
||||
- Atom: ~~`https://**:instance**/users/**:username**.atom`~~ (Only for pawoo.net, [example](https://pawoo.net/users/pawoo_support.atom))
|
||||
|
||||
These feed do not include boosts (a.k.a. reblogs). RSSHub provides a feed for user timeline based on the Mastodon API, but to use that, you will need to create application on a Mastodon instance, and configure your RSSHub instance. Check the [Deploy Guide](/en/install/#route-specific-configurations) for route-specific configurations.
|
||||
These feed do not include boosts (a.k.a. reblogs). RSSHub provides a feed for user timeline based on the Mastodon API, but to use that, you may need to create application on a Mastodon instance, and configure your RSSHub instance. Check the [Deploy Guide](/en/install/#route-specific-configurations) for route-specific configurations.
|
||||
|
||||
:::
|
||||
|
||||
### User timeline
|
||||
|
||||
<RouteEn author="notofoe" example="/mastodon/acct/CatWhitney@mastodon.social/statuses" path="/mastodon/acct/:acct/statuses/:only_media?" :paramsDesc="['Webfinger account URI', 'whether only display media content, default to false, any value to true']"/>
|
||||
<RouteEn author="notofoe" example="/mastodon/acct/CatWhitney@mastodon.social/statuses" path="/mastodon/acct/:acct/statuses/:only_media?" :paramsDesc="['Webfinger account URI, like `user@host`', 'whether only display media content, default to false, any value to true']"/>
|
||||
|
||||
Started from Mastodon v4.0.0, the use of the `search` API in the route no longer requires a user token.
|
||||
If the domain of your Webfinger account URI is the same as the API host of the instance (i.e., no delegation called in some other protocols), then no configuration is required and the route is available out of the box.
|
||||
However, you can still specify these route-specific configurations if you need to override them.
|
||||
|
||||
### Instance timeline (local)
|
||||
|
||||
<RouteEn author="hoilc" example="/mastodon/timeline/pawoo.net/true" path="/mastodon/timeline/:site/:only_media?" :paramsDesc="['instance address, only domain, no `http://` or `https://` protocol header', 'whether only display media content, default to false, any value to true']"/>
|
||||
|
||||
If the instance address is not `mastodon.social` or `pawoo.net`, then the route requires `ALLOW_USER_SUPPLY_UNSAFE_DOMAIN` to be `true`.
|
||||
|
||||
### Instance timeline (federated)
|
||||
|
||||
<RouteEn author="hoilc" example="/mastodon/remote/pawoo.net/true" path="/mastodon/remote/:site/:only_media?" :paramsDesc="['instance address, only domain, no `http://` or `https://` protocol header', 'whether only display media content, default to false, any value to true']"/>
|
||||
|
||||
If the instance address is not `mastodon.social` or `pawoo.net`, then the route requires `ALLOW_USER_SUPPLY_UNSAFE_DOMAIN` to be `true`.
|
||||
|
||||
### User timeline (backup)
|
||||
|
||||
<RouteEn author="notofoe" example="/mastodon/account_id/mastodon.social/23634/statuses/only_media" path="/mastodon/account/:site/:account_id/statuses/:only_media?" :paramsDesc="['instance address, only domain, no `http://` or `https://` protocol header', 'account id. login your instance, then search for the user profile; the account id is in the url', 'whether only display media content, default to false, any value to true']"/>
|
||||
|
||||
If the instance address is not `mastodon.social` or `pawoo.net`, then the route requires `ALLOW_USER_SUPPLY_UNSAFE_DOMAIN` to be `true`.
|
||||
|
||||
## Misskey
|
||||
|
||||
### Featured Notes
|
||||
|
|
|
|||
|
|
@ -799,9 +799,9 @@ RSSHub 支持使用访问密钥 / 码,白名单和黑名单三种方式进行
|
|||
|
||||
- Mastodon 用户时间线路由:访问 `https://mastodon.example/settings/applications` 申请(替换掉 `mastodon.example`)。需要 `read:search` 权限
|
||||
|
||||
- `MASTODON_API_HOST`: API 请求的实例
|
||||
- `MASTODON_API_HOST`: API 请求的实例,仅域名,不包括 `http://` 或 `https://` 协议头
|
||||
- `MASTODON_API_ACCESS_TOKEN`: 用户 access token, 申请应用后,在应用配置页可以看到申请者的 access token
|
||||
- `MASTODON_API_ACCT_DOMAIN`: 该实例本地用户 acct 标识的域名
|
||||
- `MASTODON_API_ACCT_DOMAIN`: 该实例本地用户 acct 标识的域名,Webfinger account URI,形如 `user@host`
|
||||
|
||||
- Medium 相关路由:打开控制台,复制 Cookie(理论上只需要 uid 和 sid 即可)
|
||||
|
||||
|
|
|
|||
|
|
@ -549,7 +549,7 @@ Tiny Tiny RSS 会给所有 iframe 元素添加 `sandbox="allow-scripts"` 属性
|
|||
|
||||
例如:<https://pawoo.net/users/pawoo_support.rss> 或 <https://pawoo.net/users/pawoo_support.atom>
|
||||
|
||||
上述订阅源的内容不包括用户的转嘟。RSSHub 提供基于 Mastodon API 的订阅源,但需要您在某个 Mastodon 实例申请 API,并对 RSSHub 实例进行配置。详情见部署页面的配置模块。
|
||||
上述订阅源的内容不包括用户的转嘟。RSSHub 提供基于 Mastodon API 的订阅源,但可能需要您在某个 Mastodon 实例申请 API,并对 RSSHub 实例进行配置。详情见部署页面的[配置模块](/install/#route-specific-configurations)。
|
||||
|
||||
:::
|
||||
|
||||
|
|
@ -557,18 +557,28 @@ Tiny Tiny RSS 会给所有 iframe 元素添加 `sandbox="allow-scripts"` 属性
|
|||
|
||||
<Route author="notofoe" example="/mastodon/acct/CatWhitney@mastodon.social/statuses" path="/mastodon/acct/:acct/statuses/:only_media?" :paramsDesc="['Webfinger account URI, 形如 `user@host`', '是否只显示包含媒体(图片或视频)的推文, 默认置空为否, 任意值为是']"/>
|
||||
|
||||
自 Mastodon v4.0.0 起,本路由中对于 `search` API 的使用不再需要访问令牌。
|
||||
如果你的 Webfinger account URI 域和实例的 API 服务器域名是一样的(即没有一些其他协议称呼的 deletation),那么此路由不需要额外配置且开箱即用。
|
||||
不过,你依然可以提供这些路由特定的配置来覆盖它们。
|
||||
|
||||
### 实例公共时间线(本站)
|
||||
|
||||
<Route author="hoilc" example="/mastodon/timeline/pawoo.net/true" path="/mastodon/timeline/:site/:only_media?" :paramsDesc="['实例地址, 仅域名, 不包括`http://`或`https://`协议头', '是否只显示包含媒体(图片或视频)的推文, 默认置空为否, 任意值为是']"/>
|
||||
|
||||
实例地址不为 `mastodon.social` 或 `pawoo.net` 的情况下均需要 `ALLOW_USER_SUPPLY_UNSAFE_DOMAIN` 为 `true`。
|
||||
|
||||
### 实例公共时间线(跨站)
|
||||
|
||||
<Route author="hoilc" example="/mastodon/remote/pawoo.net/true" path="/mastodon/remote/:site/:only_media?" :paramsDesc="['实例地址, 仅域名, 不包括`http://`或`https://`协议头', '是否只显示包含媒体(图片或视频)的推文, 默认置空为否, 任意值为是']"/>
|
||||
|
||||
实例地址不为 `mastodon.social` 或 `pawoo.net` 的情况下均需要 `ALLOW_USER_SUPPLY_UNSAFE_DOMAIN` 为 `true`。
|
||||
|
||||
### 用户公共时间线(备用)
|
||||
|
||||
<Route author="notofoe" example="/mastodon/account_id/mastodon.social/23634/statuses/only_media" path="/mastodon/account/:site/:account_id/statuses/:only_media?" :paramsDesc="['实例地址, 仅域名, 不包括`http://`或`https://`协议头', '用户 ID. 登录实例后, 搜索用户并进入用户页, 在地址中可以找到这串数字', '是否只显示包含媒体(图片或视频)的推文, 默认置空为否, 任意值为是']"/>
|
||||
|
||||
实例地址不为 `mastodon.social` 或 `pawoo.net` 的情况下均需要 `ALLOW_USER_SUPPLY_UNSAFE_DOMAIN` 为 `true`。
|
||||
|
||||
## Misskey
|
||||
|
||||
### 精选笔记
|
||||
|
|
|
|||
|
|
@ -2281,10 +2281,10 @@ router.get('/755/user/:username', lazyloadRouteHandler('./routes/755/user'));
|
|||
// router.get('/ikea/uk/offer', lazyloadRouteHandler('./routes/ikea/uk/offer'));
|
||||
|
||||
// Mastodon
|
||||
router.get('/mastodon/timeline/:site/:only_media?', lazyloadRouteHandler('./routes/mastodon/timeline_local'));
|
||||
router.get('/mastodon/remote/:site/:only_media?', lazyloadRouteHandler('./routes/mastodon/timeline_remote'));
|
||||
router.get('/mastodon/account_id/:site/:account_id/statuses/:only_media?', lazyloadRouteHandler('./routes/mastodon/account_id'));
|
||||
router.get('/mastodon/acct/:acct/statuses/:only_media?', lazyloadRouteHandler('./routes/mastodon/acct'));
|
||||
// router.get('/mastodon/timeline/:site/:only_media?', lazyloadRouteHandler('./routes/mastodon/timeline_local'));
|
||||
// router.get('/mastodon/remote/:site/:only_media?', lazyloadRouteHandler('./routes/mastodon/timeline_remote'));
|
||||
// router.get('/mastodon/account_id/:site/:account_id/statuses/:only_media?', lazyloadRouteHandler('./routes/mastodon/account_id'));
|
||||
// router.get('/mastodon/acct/:acct/statuses/:only_media?', lazyloadRouteHandler('./routes/mastodon/acct'));
|
||||
|
||||
// Kernel Aliyun
|
||||
router.get('/aliyun-kernel/index', lazyloadRouteHandler('./routes/aliyun-kernel/index'));
|
||||
|
|
|
|||
|
|
@ -0,0 +1,6 @@
|
|||
module.exports = {
|
||||
'/account_id/:site/:account_id/statuses/:only_media?': ['notofoe'],
|
||||
'/acct/:acct/statuses/:only_media?': ['notofoe'],
|
||||
'/remote/:site/:only_media?': ['hoilc'],
|
||||
'/timeline/:site/:only_media?': ['hoilc'],
|
||||
};
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
module.exports = {
|
||||
'mastodon.social': {
|
||||
_name: 'Mastodon',
|
||||
'.': [
|
||||
{
|
||||
title: '用户公共时间线',
|
||||
docs: 'https://docs.rsshub.app/social-media.html#mastodon',
|
||||
source: ['/:acct'],
|
||||
target: (params, url) => (params.acct.startsWith('@') ? `/mastodon/acct/${params.substring(1)}@${new URL(url).host}/statuses` : ''),
|
||||
},
|
||||
{
|
||||
title: '实例公共时间线(本站)',
|
||||
docs: 'https://docs.rsshub.app/social-media.html#mastodon',
|
||||
source: ['/'],
|
||||
target: (_, url) => `/mastodon/timeline/${new URL(url).host}`,
|
||||
},
|
||||
{
|
||||
title: '实例公共时间线(跨站)',
|
||||
docs: 'https://docs.rsshub.app/social-media.html#mastodon',
|
||||
source: ['/'],
|
||||
target: (_, url) => `/mastodon/remote/${new URL(url).host}`,
|
||||
},
|
||||
{
|
||||
title: '用户公共时间线(备用)',
|
||||
docs: 'https://docs.rsshub.app/social-media.html#mastodon',
|
||||
source: ['/:acct'],
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
module.exports = (router) => {
|
||||
router.get('/account_id/:site/:account_id/statuses/:only_media?', require('./account_id'));
|
||||
router.get('/acct/:acct/statuses/:only_media?', require('./acct'));
|
||||
router.get('/remote/:site/:only_media?', require('./timeline_remote'));
|
||||
router.get('/timeline/:site/:only_media?', require('./timeline_local'));
|
||||
};
|
||||
|
|
@ -16,7 +16,7 @@ module.exports = async (ctx) => {
|
|||
|
||||
ctx.state.data = {
|
||||
title: `Local Public${ctx.params.only_media ? ' Media' : ''} Timeline on ${site}`,
|
||||
link: `http://${site}`,
|
||||
link: `https://${site}`,
|
||||
item: utils.parseStatuses(list),
|
||||
};
|
||||
};
|
||||
|
|
@ -16,7 +16,7 @@ module.exports = async (ctx) => {
|
|||
|
||||
ctx.state.data = {
|
||||
title: `Federated Public${ctx.params.only_media ? ' Media' : ''} Timeline on ${site}`,
|
||||
link: `http://${site}`,
|
||||
link: `https://${site}`,
|
||||
item: utils.parseStatuses(list),
|
||||
};
|
||||
};
|
||||
|
|
@ -53,7 +53,7 @@ const parseStatuses = (data) =>
|
|||
});
|
||||
|
||||
async function getAccountStatuses(site, account_id, only_media) {
|
||||
const statuses_url = `http://${site}/api/v1/accounts/${account_id}/statuses?only_media=${only_media}`;
|
||||
const statuses_url = `https://${site}/api/v1/accounts/${account_id}/statuses?only_media=${only_media}`;
|
||||
const statuses_response = await got({
|
||||
method: 'get',
|
||||
url: statuses_url,
|
||||
|
|
@ -64,7 +64,7 @@ async function getAccountStatuses(site, account_id, only_media) {
|
|||
if (data.length !== 0 && data[0].account !== null) {
|
||||
account_data = data[0].account;
|
||||
} else {
|
||||
const account_url = `http://${site}/api/v1/accounts/${account_id}`;
|
||||
const account_url = `https://${site}/api/v1/accounts/${account_id}`;
|
||||
const account_response = await got({
|
||||
method: 'get',
|
||||
url: account_url,
|
||||
|
|
@ -79,13 +79,15 @@ async function getAccountIdByAcct(acct, ctx) {
|
|||
const config = require('@/config').value;
|
||||
const mastodonConfig = config.mastodon;
|
||||
|
||||
if (!(mastodonConfig.apiHost && mastodonConfig.accessToken && mastodonConfig.acctDomain)) {
|
||||
throw 'this route require api configuration, please check <a href="https://docs.rsshub.app/en/install/#configuration">documentation</a>';
|
||||
// acctHost is from the acct param of the request, and acctDomain is from either acctHost or the config
|
||||
const acctHost = acct.split('@').filter((e) => e)[1];
|
||||
const site = mastodonConfig.apiHost || acctHost;
|
||||
const acctDomain = mastodonConfig.acctDomain || acctHost;
|
||||
if (!(site && acctDomain)) {
|
||||
throw Error('Mastodon RSS is disabled due to the lack of <a href="https://docs.rsshub.app/en/install/#configuration-route-specific-configurations">relevant config</a>');
|
||||
}
|
||||
|
||||
const site = mastodonConfig.apiHost;
|
||||
|
||||
const search_url = `http://${site}/api/v2/search`;
|
||||
const search_url = `https://${site}/api/v2/search`;
|
||||
const cacheUid = `mastodon_acct_id/${site}/${acct}`;
|
||||
|
||||
const account_id = await ctx.cache.tryGet(cacheUid, async () => {
|
||||
|
|
@ -93,7 +95,7 @@ async function getAccountIdByAcct(acct, ctx) {
|
|||
method: 'get',
|
||||
url: search_url,
|
||||
headers: {
|
||||
Authorization: `Bearer ${mastodonConfig.accessToken}`,
|
||||
...(mastodonConfig.accessToken ? { Authorization: `Bearer ${mastodonConfig.accessToken}` } : {}),
|
||||
},
|
||||
searchParams: {
|
||||
q: acct,
|
||||
|
|
@ -104,7 +106,7 @@ async function getAccountIdByAcct(acct, ctx) {
|
|||
let acctOnServer;
|
||||
|
||||
if (acctHost) {
|
||||
if (acctHost === mastodonConfig.acctDomain) {
|
||||
if (acctHost === acctDomain) {
|
||||
acctOnServer = acctUser;
|
||||
} else {
|
||||
acctOnServer = acctUser + '@' + acctHost;
|
||||
Loading…
Reference in New Issue