summaryrefslogtreecommitdiff
path: root/packages/backend/src/server/api/endpoints/notes
diff options
context:
space:
mode:
authordakkar <dakkar@thenautilus.net>2024-10-07 17:15:33 +0000
committerdakkar <dakkar@thenautilus.net>2024-10-07 17:15:33 +0000
commit32a97a5a057941d88868b94b01b320e61b8d0e15 (patch)
treea12a4a05b616459bfad4f385759898a70c01261d /packages/backend/src/server/api/endpoints/notes
parentmerge: Add controls to delete all files or sever all relations with a remote ... (diff)
parentupdate autogen types (diff)
downloadsharkey-32a97a5a057941d88868b94b01b320e61b8d0e15.tar.gz
sharkey-32a97a5a057941d88868b94b01b320e61b8d0e15.tar.bz2
sharkey-32a97a5a057941d88868b94b01b320e61b8d0e15.zip
merge: Add feed of latest posts by followed users (!640)
View MR for information: https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/640 Approved-by: dakkar <dakkar@thenautilus.net> Approved-by: Marie <github@yuugi.dev>
Diffstat (limited to 'packages/backend/src/server/api/endpoints/notes')
-rw-r--r--packages/backend/src/server/api/endpoints/notes/following.ts95
1 files changed, 95 insertions, 0 deletions
diff --git a/packages/backend/src/server/api/endpoints/notes/following.ts b/packages/backend/src/server/api/endpoints/notes/following.ts
new file mode 100644
index 0000000000..436160f250
--- /dev/null
+++ b/packages/backend/src/server/api/endpoints/notes/following.ts
@@ -0,0 +1,95 @@
+/*
+ * SPDX-FileCopyrightText: hazelnoot and other Sharkey contributors
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+import { Inject, Injectable } from '@nestjs/common';
+import { LatestNote, MiFollowing } from '@/models/_.js';
+import type { NotesRepository } from '@/models/_.js';
+import { Endpoint } from '@/server/api/endpoint-base.js';
+import { NoteEntityService } from '@/core/entities/NoteEntityService.js';
+import { DI } from '@/di-symbols.js';
+import { QueryService } from '@/core/QueryService.js';
+
+export const meta = {
+ tags: ['notes'],
+
+ requireCredential: true,
+ kind: 'read:account',
+ allowGet: true,
+
+ res: {
+ type: 'array',
+ optional: false, nullable: false,
+ items: {
+ type: 'object',
+ optional: false, nullable: false,
+ ref: 'Note',
+ },
+ },
+} as const;
+
+export const paramDef = {
+ type: 'object',
+ properties: {
+ mutualsOnly: { type: 'boolean', default: false },
+ limit: { type: 'integer', minimum: 1, maximum: 100, default: 10 },
+ sinceId: { type: 'string', format: 'misskey:id' },
+ untilId: { type: 'string', format: 'misskey:id' },
+ sinceDate: { type: 'integer' },
+ untilDate: { type: 'integer' },
+ },
+ required: [],
+} as const;
+
+@Injectable()
+export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-disable-line import/no-default-export
+ constructor(
+ @Inject(DI.notesRepository)
+ private notesRepository: NotesRepository,
+
+ private noteEntityService: NoteEntityService,
+ private queryService: QueryService,
+ ) {
+ super(meta, paramDef, async (ps, me) => {
+ let query = this.notesRepository
+ .createQueryBuilder('note')
+ .setParameter('me', me.id)
+
+ // Limit to latest notes
+ .innerJoin(LatestNote, 'latest', 'note.id = latest.note_id')
+
+ // Avoid N+1 queries from the "pack" method
+ .innerJoinAndSelect('note.user', 'user')
+ .leftJoinAndSelect('note.reply', 'reply')
+ .leftJoinAndSelect('note.renote', 'renote')
+ .leftJoinAndSelect('reply.user', 'replyUser')
+ .leftJoinAndSelect('renote.user', 'renoteUser')
+ .leftJoinAndSelect('note.channel', 'channel')
+
+ // Limit to followers
+ .innerJoin(MiFollowing, 'following', 'latest.user_id = following."followeeId"')
+ .andWhere('following."followerId" = :me');
+
+ // Limit to mutuals, if requested
+ if (ps.mutualsOnly) {
+ query = query
+ .innerJoin(MiFollowing, 'mutuals', 'latest.user_id = mutuals."followerId" AND mutuals."followeeId" = :me');
+ }
+
+ // Respect blocks and mutes
+ this.queryService.generateBlockedUserQuery(query, me);
+ this.queryService.generateMutedUserQuery(query, me);
+
+ // Support pagination
+ query = this.queryService
+ .makePaginationQuery(query, ps.sinceId, ps.untilId, ps.sinceDate, ps.untilDate)
+ .orderBy('note.id', 'DESC')
+ .take(ps.limit);
+
+ // Query and return the next page
+ const notes = await query.getMany();
+ return await this.noteEntityService.packMany(notes, me);
+ });
+ }
+}