mirror of
https://github.com/misskey-dev/misskey.git
synced 2025-01-11 01:00:07 +09:00
feat(backend): implement liked
collection of ActivityPub actors
This commit is contained in:
parent
f50941389d
commit
4ad43bca42
@ -486,6 +486,7 @@ export class ApRendererService {
|
|||||||
outbox: `${id}/outbox`,
|
outbox: `${id}/outbox`,
|
||||||
followers: `${id}/followers`,
|
followers: `${id}/followers`,
|
||||||
following: `${id}/following`,
|
following: `${id}/following`,
|
||||||
|
liked: `${id}/liked`,
|
||||||
featured: `${id}/collections/featured`,
|
featured: `${id}/collections/featured`,
|
||||||
sharedInbox: `${this.config.url}/inbox`,
|
sharedInbox: `${this.config.url}/inbox`,
|
||||||
endpoints: { sharedInbox: `${this.config.url}/inbox` },
|
endpoints: { sharedInbox: `${this.config.url}/inbox` },
|
||||||
|
@ -13,7 +13,7 @@ import accepts from 'accepts';
|
|||||||
import vary from 'vary';
|
import vary from 'vary';
|
||||||
import secureJson from 'secure-json-parse';
|
import secureJson from 'secure-json-parse';
|
||||||
import { DI } from '@/di-symbols.js';
|
import { DI } from '@/di-symbols.js';
|
||||||
import type { FollowingsRepository, NotesRepository, EmojisRepository, NoteReactionsRepository, UserProfilesRepository, UserNotePiningsRepository, UsersRepository, FollowRequestsRepository } from '@/models/_.js';
|
import type { FollowingsRepository, NotesRepository, EmojisRepository, NoteReactionsRepository, UserProfilesRepository, UserNotePiningsRepository, UsersRepository, FollowRequestsRepository, MiNoteReaction } from '@/models/_.js';
|
||||||
import * as url from '@/misc/prelude/url.js';
|
import * as url from '@/misc/prelude/url.js';
|
||||||
import type { Config } from '@/config.js';
|
import type { Config } from '@/config.js';
|
||||||
import { ApRendererService } from '@/core/activitypub/ApRendererService.js';
|
import { ApRendererService } from '@/core/activitypub/ApRendererService.js';
|
||||||
@ -351,6 +351,94 @@ export class ActivityPubServerService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@bindThis
|
||||||
|
private async liked(
|
||||||
|
request: FastifyRequest<{ Params: { user: string; }; Querystring: { cursor?: string; page?: string; }; }>,
|
||||||
|
reply: FastifyReply,
|
||||||
|
) {
|
||||||
|
const userId = request.params.user;
|
||||||
|
|
||||||
|
const cursor = request.query.cursor;
|
||||||
|
if (cursor != null && typeof cursor !== 'string') {
|
||||||
|
reply.code(400);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const page = request.query.page === 'true';
|
||||||
|
|
||||||
|
const user = await this.usersRepository.findOneBy({
|
||||||
|
id: userId,
|
||||||
|
host: IsNull(),
|
||||||
|
});
|
||||||
|
|
||||||
|
if (user == null) {
|
||||||
|
reply.code(404);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const profile = await this.userProfilesRepository.findOneByOrFail({ userId: user.id });
|
||||||
|
|
||||||
|
if (!profile.publicReactions) {
|
||||||
|
reply.code(403);
|
||||||
|
reply.header('Cache-Control', 'public, max-age=30');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const limit = 10;
|
||||||
|
const partOf = `${this.config.url}/users/${userId}/liked`;
|
||||||
|
const query = {
|
||||||
|
userId: user.id,
|
||||||
|
} as FindOptionsWhere<MiNoteReaction>;
|
||||||
|
|
||||||
|
if (page) {
|
||||||
|
// カーソルが指定されている場合
|
||||||
|
if (cursor) {
|
||||||
|
query.id = LessThan(cursor);
|
||||||
|
}
|
||||||
|
|
||||||
|
const [reactions, reactionsCount] = await Promise.all([
|
||||||
|
this.noteReactionsRepository.find({
|
||||||
|
where: query,
|
||||||
|
take: limit + 1,
|
||||||
|
order: { id: -1 },
|
||||||
|
}),
|
||||||
|
this.noteReactionsRepository.count({ where: query }),
|
||||||
|
]);
|
||||||
|
|
||||||
|
// 「次のページ」があるかどうか
|
||||||
|
const inStock = reactions.length === limit + 1;
|
||||||
|
if (inStock) reactions.pop();
|
||||||
|
|
||||||
|
const renderedLikes = await Promise.all(reactions.map(reaction => this.apRendererService.renderLike(reaction, { uri: null })));
|
||||||
|
const rendered = this.apRendererService.renderOrderedCollectionPage(
|
||||||
|
`${partOf}?${url.query({
|
||||||
|
page: 'true',
|
||||||
|
cursor,
|
||||||
|
})}`,
|
||||||
|
reactionsCount, renderedLikes, partOf,
|
||||||
|
undefined,
|
||||||
|
inStock ? `${partOf}?${url.query({
|
||||||
|
page: 'true',
|
||||||
|
cursor: reactions.at(-1)!.id,
|
||||||
|
})}` : undefined,
|
||||||
|
);
|
||||||
|
|
||||||
|
this.setResponseType(request, reply);
|
||||||
|
return (this.apRendererService.addContext(rendered));
|
||||||
|
} else {
|
||||||
|
// index page
|
||||||
|
const reactionsCount = await this.noteReactionsRepository.count({ where: query });
|
||||||
|
const rendered = this.apRendererService.renderOrderedCollection(
|
||||||
|
partOf,
|
||||||
|
reactionsCount,
|
||||||
|
`${partOf}?page=true`,
|
||||||
|
);
|
||||||
|
reply.header('Cache-Control', 'public, max-age=180');
|
||||||
|
this.setResponseType(request, reply);
|
||||||
|
return (this.apRendererService.addContext(rendered));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@bindThis
|
@bindThis
|
||||||
private async featured(request: FastifyRequest<{ Params: { user: string; }; }>, reply: FastifyReply) {
|
private async featured(request: FastifyRequest<{ Params: { user: string; }; }>, reply: FastifyReply) {
|
||||||
const userId = request.params.user;
|
const userId = request.params.user;
|
||||||
@ -618,6 +706,12 @@ export class ActivityPubServerService {
|
|||||||
Querystring: { cursor?: string; page?: string; };
|
Querystring: { cursor?: string; page?: string; };
|
||||||
}>('/users/:user/following', async (request, reply) => await this.following(request, reply));
|
}>('/users/:user/following', async (request, reply) => await this.following(request, reply));
|
||||||
|
|
||||||
|
// liked
|
||||||
|
fastify.get<{
|
||||||
|
Params: { user: string; };
|
||||||
|
Querystring: { cursor?: string; page?: string; };
|
||||||
|
}>('/users/:user/liked', async (request, reply) => await this.liked(request, reply));
|
||||||
|
|
||||||
// featured
|
// featured
|
||||||
fastify.get<{ Params: { user: string; }; }>('/users/:user/collections/featured', async (request, reply) => await this.featured(request, reply));
|
fastify.get<{ Params: { user: string; }; }>('/users/:user/collections/featured', async (request, reply) => await this.featured(request, reply));
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user