diff options
| author | syuilo <Syuilotan@yahoo.co.jp> | 2021-11-12 02:02:25 +0900 |
|---|---|---|
| committer | syuilo <Syuilotan@yahoo.co.jp> | 2021-11-12 02:02:25 +0900 |
| commit | 0e4a111f81cceed275d9bec2695f6e401fb654d8 (patch) | |
| tree | 40874799472fa07416f17b50a398ac33b7771905 /packages/backend/src/server/activitypub/following.ts | |
| parent | update deps (diff) | |
| download | misskey-0e4a111f81cceed275d9bec2695f6e401fb654d8.tar.gz misskey-0e4a111f81cceed275d9bec2695f6e401fb654d8.tar.bz2 misskey-0e4a111f81cceed275d9bec2695f6e401fb654d8.zip | |
refactoring
Resolve #7779
Diffstat (limited to 'packages/backend/src/server/activitypub/following.ts')
| -rw-r--r-- | packages/backend/src/server/activitypub/following.ts | 103 |
1 files changed, 103 insertions, 0 deletions
diff --git a/packages/backend/src/server/activitypub/following.ts b/packages/backend/src/server/activitypub/following.ts new file mode 100644 index 0000000000..b9eb806c3c --- /dev/null +++ b/packages/backend/src/server/activitypub/following.ts @@ -0,0 +1,103 @@ +import * as Router from '@koa/router'; +import config from '@/config/index'; +import $ from 'cafy'; +import { ID } from '@/misc/cafy-id'; +import * as url from '@/prelude/url'; +import { renderActivity } from '@/remote/activitypub/renderer/index'; +import renderOrderedCollection from '@/remote/activitypub/renderer/ordered-collection'; +import renderOrderedCollectionPage from '@/remote/activitypub/renderer/ordered-collection-page'; +import renderFollowUser from '@/remote/activitypub/renderer/follow-user'; +import { setResponseType } from '../activitypub'; +import { Users, Followings, UserProfiles } from '@/models/index'; +import { LessThan, FindConditions } from 'typeorm'; +import { Following } from '@/models/entities/following'; + +export default async (ctx: Router.RouterContext) => { + const userId = ctx.params.user; + + // Get 'cursor' parameter + const [cursor, cursorErr] = $.optional.type(ID).get(ctx.request.query.cursor); + + // Get 'page' parameter + const pageErr = !$.optional.str.or(['true', 'false']).ok(ctx.request.query.page); + const page: boolean = ctx.request.query.page === 'true'; + + // Validate parameters + if (cursorErr || pageErr) { + ctx.status = 400; + return; + } + + // Verify user + const user = await Users.findOne({ + id: userId, + host: null + }); + + if (user == null) { + ctx.status = 404; + return; + } + + //#region Check ff visibility + const profile = await UserProfiles.findOneOrFail(user.id); + + if (profile.ffVisibility === 'private') { + ctx.status = 403; + ctx.set('Cache-Control', 'public, max-age=30'); + return; + } else if (profile.ffVisibility === 'followers') { + ctx.status = 403; + ctx.set('Cache-Control', 'public, max-age=30'); + return; + } + //#endregion + + const limit = 10; + const partOf = `${config.url}/users/${userId}/following`; + + if (page) { + const query = { + followerId: user.id + } as FindConditions<Following>; + + // カーソルが指定されている場合 + if (cursor) { + query.id = LessThan(cursor); + } + + // Get followings + const followings = await Followings.find({ + where: query, + take: limit + 1, + order: { id: -1 } + }); + + // 「次のページ」があるかどうか + const inStock = followings.length === limit + 1; + if (inStock) followings.pop(); + + const renderedFollowees = await Promise.all(followings.map(following => renderFollowUser(following.followeeId))); + const rendered = renderOrderedCollectionPage( + `${partOf}?${url.query({ + page: 'true', + cursor + })}`, + user.followingCount, renderedFollowees, partOf, + undefined, + inStock ? `${partOf}?${url.query({ + page: 'true', + cursor: followings[followings.length - 1].id + })}` : undefined + ); + + ctx.body = renderActivity(rendered); + setResponseType(ctx); + } else { + // index page + const rendered = renderOrderedCollection(partOf, user.followingCount, `${partOf}?page=true`); + ctx.body = renderActivity(rendered); + ctx.set('Cache-Control', 'public, max-age=180'); + setResponseType(ctx); + } +}; |