rsshub
Version:
Make RSS Great Again!
100 lines (90 loc) • 3.86 kB
text/typescript
import { config } from '@/config';
import ConfigNotFoundError from '@/errors/types/config-not-found';
import { Route, ViewType } from '@/types';
import got from '@/utils/got';
import { queryToBoolean } from '@/utils/readable-social';
import querystring from 'node:querystring';
import utils from './utils';
export const route: Route = {
path: '/timeline/home/:site/:routeParams?',
categories: ['social-media'],
view: ViewType.SocialMedia,
example: '/misskey/timeline/home/misskey.io',
parameters: {
site: 'instance address, domain only, without `http://` or `https://` protocol header',
routeParams: `
| Key | Description | Accepted Values | Default |
| -------------------- | --------------------------------------- | --------------- | ------- |
| limit | Number of notes to return | integer | 10 |
| withFiles | Only return notes containing files | 0/1/true/false | false |
| withRenotes | Include renotes in the timeline | 0/1/true/false | true |
| allowPartial | Allow partial results | 0/1/true/false | true |
| simplifyAuthor | Simplify author field in feed items | 0/1/true/false | true |
Note: If \`withFiles\` is set to true, renotes will not be included in the timeline regardless of the value of \`withRenotes\`.
Examples:
- /misskey/timeline/home/misskey.io/limit=20&withFiles=true
- /misskey/timeline/home/misskey.io/withRenotes=false
`,
},
features: {
requireConfig: [
{
name: 'MISSKEY_ACCESS_TOKEN',
optional: false,
description: `
Access token for Misskey API. Requires \`read:account\` access.
Visit the specified site's settings page to obtain an access token. E.g. https://misskey.io/settings/api
`,
},
],
requirePuppeteer: false,
antiCrawler: false,
supportBT: false,
supportPodcast: false,
supportScihub: false,
},
radar: [
{
source: ['misskey.io'],
},
],
name: 'Home Timeline',
maintainers: ['HanaokaYuzu'],
handler,
description: `::: warning
This route is only available for self-hosted instances.
:::`,
};
async function handler(ctx) {
const access_token = config.misskey.accessToken;
if (!access_token) {
throw new ConfigNotFoundError('Missing access token for Misskey API. Please set `MISSKEY_ACCESS_TOKEN` environment variable.');
}
const site = ctx.req.param('site');
if (!config.feature.allow_user_supply_unsafe_domain && !utils.allowSiteList.includes(site)) {
throw new ConfigNotFoundError(`This RSS is disabled unless 'ALLOW_USER_SUPPLY_UNSAFE_DOMAIN' is set to 'true'.`);
}
// docs on: https://misskey.io/api-doc#tag/notes/operation/notes___timeline
const url = `https://${site}/api/notes/timeline`;
const routeParams = querystring.parse(ctx.req.param('routeParams'));
const response = await got({
method: 'post',
url,
headers: {
Authorization: `Bearer ${access_token}`,
},
json: {
limit: Number(routeParams.limit ?? 10),
withFiles: queryToBoolean(routeParams.withFiles ?? false),
withRenotes: queryToBoolean(routeParams.withRenotes ?? true),
allowPartial: queryToBoolean(routeParams.allowPartial ?? true),
},
});
const list = response.data;
const simplifyAuthor = queryToBoolean(routeParams.simplifyAuthor ?? true);
return {
title: `Home Timeline on ${site}`,
link: `https://${site}`,
item: utils.parseNotes(list, site, simplifyAuthor),
};
}