mirror of
https://github.com/DIYgod/RSSHub.git
synced 2026-09-01 14:57:14 +08:00
feat(route): implement user timeline endpoint for misskey (#16393)
This commit is contained in:
@@ -0,0 +1,42 @@
|
||||
import { Route } from '@/types';
|
||||
import utils from './utils';
|
||||
import { config } from '@/config';
|
||||
import ConfigNotFoundError from '@/errors/types/config-not-found';
|
||||
import InvalidParameterError from '@/errors/types/invalid-parameter';
|
||||
|
||||
export const route: Route = {
|
||||
path: '/users/notes/:username',
|
||||
categories: ['social-media'],
|
||||
example: '/misskey/users/notes/support@misskey.io',
|
||||
parameters: { username: 'misskey username format, like support@misskey.io' },
|
||||
features: {
|
||||
requireConfig: false,
|
||||
requirePuppeteer: false,
|
||||
antiCrawler: false,
|
||||
supportBT: false,
|
||||
supportPodcast: false,
|
||||
supportScihub: false,
|
||||
},
|
||||
name: 'User timeline',
|
||||
maintainers: ['siygle'],
|
||||
handler,
|
||||
};
|
||||
|
||||
async function handler(ctx) {
|
||||
const username = ctx.req.param('username');
|
||||
const [, pureUsername, site] = username.match(/@?(\w+)@(\w+\.\w+)/) || [];
|
||||
if (!pureUsername || !site) {
|
||||
throw new InvalidParameterError('Provide a valid Misskey username');
|
||||
}
|
||||
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'.`);
|
||||
}
|
||||
|
||||
const { accountData } = await utils.getUserTimelineByUsername(pureUsername, site);
|
||||
|
||||
return {
|
||||
title: `User timeline for ${username} on ${site}`,
|
||||
link: `https://${site}/@${pureUsername}`,
|
||||
item: utils.parseNotes(accountData, site),
|
||||
};
|
||||
}
|
||||
@@ -4,6 +4,8 @@ const __dirname = getCurrentPath(import.meta.url);
|
||||
import { art } from '@/utils/render';
|
||||
import { parseDate } from '@/utils/parse-date';
|
||||
import path from 'node:path';
|
||||
import cache from '@/utils/cache';
|
||||
import got from '@/utils/got';
|
||||
|
||||
const allowSiteList = ['misskey.io', 'madost.one', 'mk.nixnet.social'];
|
||||
|
||||
@@ -28,4 +30,42 @@ const parseNotes = (data, site) =>
|
||||
};
|
||||
});
|
||||
|
||||
export default { parseNotes, allowSiteList };
|
||||
async function getUserTimelineByUsername(username, site) {
|
||||
const searchUrl = `https://${site}/api/users/search-by-username-and-host`;
|
||||
const cacheUid = `misskey_username/${site}/${username}`;
|
||||
|
||||
const accountId = await cache.tryGet(cacheUid, async () => {
|
||||
const searchResponse = await got({
|
||||
method: 'post',
|
||||
url: searchUrl,
|
||||
json: {
|
||||
username,
|
||||
host: site,
|
||||
detail: true,
|
||||
limit: 1,
|
||||
},
|
||||
});
|
||||
const userData = searchResponse.data.find((item) => item.username === username);
|
||||
|
||||
if (userData.length === 0) {
|
||||
throw new Error(`username ${username} not found`);
|
||||
}
|
||||
return userData.id;
|
||||
});
|
||||
|
||||
const usernotesUrl = `https://${site}/api/users/notes`;
|
||||
const usernotesResponse = await got({
|
||||
method: 'post',
|
||||
url: usernotesUrl,
|
||||
json: {
|
||||
userId: accountId,
|
||||
withChannelNotes: true,
|
||||
limit: 10,
|
||||
offset: 0,
|
||||
},
|
||||
});
|
||||
const accountData = usernotesResponse.data;
|
||||
return { site, accountId, accountData };
|
||||
}
|
||||
|
||||
export default { parseNotes, getUserTimelineByUsername, allowSiteList };
|
||||
|
||||
Reference in New Issue
Block a user