Skip to content

Commit

Permalink
feat(route): implement user timeline endpoint for misskey (#16393)
Browse files Browse the repository at this point in the history
  • Loading branch information
siygle authored Aug 9, 2024
1 parent 3274fe7 commit 815f7bd
Show file tree
Hide file tree
Showing 2 changed files with 83 additions and 1 deletion.
42 changes: 42 additions & 0 deletions lib/routes/misskey/user-timeline.ts
Original file line number Diff line number Diff line change
@@ -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),
};
}
42 changes: 41 additions & 1 deletion lib/routes/misskey/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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'];

Expand All @@ -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 };

0 comments on commit 815f7bd

Please sign in to comment.