diff options
| author | Julia <julia@insertdomain.name> | 2025-06-19 21:35:18 +0000 |
|---|---|---|
| committer | Julia <julia@insertdomain.name> | 2025-06-19 21:35:18 +0000 |
| commit | a77c32b17da63d3932b219f74152cce023a30f4a (patch) | |
| tree | d2a05796e942c8f250bbd01369eab0cbe5a14531 /packages/backend/src/server/api/endpoints/notes/timeline.ts | |
| parent | merge: release 2025.4.2 (!1051) (diff) | |
| parent | Merge branch 'develop' into release/2025.4.3 (diff) | |
| download | sharkey-a77c32b17da63d3932b219f74152cce023a30f4a.tar.gz sharkey-a77c32b17da63d3932b219f74152cce023a30f4a.tar.bz2 sharkey-a77c32b17da63d3932b219f74152cce023a30f4a.zip | |
merge: prepare release 2025.4.3 (!1125)
View MR for information: https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/1125
Approved-by: Marie <github@yuugi.dev>
Approved-by: Julia <julia@insertdomain.name>
Diffstat (limited to 'packages/backend/src/server/api/endpoints/notes/timeline.ts')
| -rw-r--r-- | packages/backend/src/server/api/endpoints/notes/timeline.ts | 124 |
1 files changed, 25 insertions, 99 deletions
diff --git a/packages/backend/src/server/api/endpoints/notes/timeline.ts b/packages/backend/src/server/api/endpoints/notes/timeline.ts index a2dfa7fdac..44c539eaad 100644 --- a/packages/backend/src/server/api/endpoints/notes/timeline.ts +++ b/packages/backend/src/server/api/endpoints/notes/timeline.ts @@ -49,9 +49,6 @@ export const paramDef = { sinceDate: { type: 'integer' }, untilDate: { type: 'integer' }, allowPartial: { type: 'boolean', default: false }, // true is recommended but for compatibility false by default - includeMyRenotes: { type: 'boolean', default: true }, - includeRenotedMyNotes: { type: 'boolean', default: true }, - includeLocalRenotes: { type: 'boolean', default: true }, withFiles: { type: 'boolean', default: false }, withRenotes: { type: 'boolean', default: true }, withBots: { type: 'boolean', default: true }, @@ -88,9 +85,6 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint- untilId, sinceId, limit: ps.limit, - includeMyRenotes: ps.includeMyRenotes, - includeRenotedMyNotes: ps.includeRenotedMyNotes, - includeLocalRenotes: ps.includeLocalRenotes, withFiles: ps.withFiles, withRenotes: ps.withRenotes, withBots: ps.withBots, @@ -121,7 +115,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint- excludePureRenotes: !ps.withRenotes, noteFilter: note => { if (note.reply && note.reply.visibility === 'followers') { - if (!Object.hasOwn(followings, note.reply.userId) && note.reply.userId !== me.id) return false; + if (!followings.has(note.reply.userId) && note.reply.userId !== me.id) return false; } if (!ps.withBots && note.user?.isBot) return false; @@ -131,9 +125,6 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint- untilId, sinceId, limit, - includeMyRenotes: ps.includeMyRenotes, - includeRenotedMyNotes: ps.includeRenotedMyNotes, - includeLocalRenotes: ps.includeLocalRenotes, withFiles: ps.withFiles, withRenotes: ps.withRenotes, withBots: ps.withBots, @@ -148,113 +139,48 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint- }); } - private async getFromDb(ps: { untilId: string | null; sinceId: string | null; limit: number; includeMyRenotes: boolean; includeRenotedMyNotes: boolean; includeLocalRenotes: boolean; withFiles: boolean; withRenotes: boolean; withBots: boolean; }, me: MiLocalUser) { - const followees = await this.userFollowingService.getFollowees(me.id); - const followingChannels = await this.channelFollowingsRepository.find({ - where: { - followerId: me.id, - }, - }); - + private async getFromDb(ps: { untilId: string | null; sinceId: string | null; limit: number; withFiles: boolean; withRenotes: boolean; withBots: boolean; }, me: MiLocalUser) { //#region Construct query const query = this.queryService.makePaginationQuery(this.notesRepository.createQueryBuilder('note'), ps.sinceId, ps.untilId) + // 1. in a channel I follow, 2. my own post, 3. by a user I follow + .andWhere(new Brackets(qb => this.queryService + .orFollowingChannel(qb, ':meId', 'note.channelId') + .orWhere(':meId = note.userId') + .orWhere(new Brackets(qb2 => this.queryService + .andFollowingUser(qb2, ':meId', 'note.userId') + .andWhere('note.channelId IS NULL'))), + )) + // 1. Not a reply, 2. a self-reply + .andWhere(new Brackets(qb => qb + .orWhere('note.replyId IS NULL') // 返信ではない + .orWhere('note.replyUserId = note.userId'))) + .setParameters({ meId: me.id }) .innerJoinAndSelect('note.user', 'user') .leftJoinAndSelect('note.reply', 'reply') .leftJoinAndSelect('note.renote', 'renote') .leftJoinAndSelect('reply.user', 'replyUser') - .leftJoinAndSelect('renote.user', 'renoteUser'); - - if (followees.length > 0 && followingChannels.length > 0) { - // ユーザー・チャンネルともにフォローあり - const meOrFolloweeIds = [me.id, ...followees.map(f => f.followeeId)]; - const followingChannelIds = followingChannels.map(x => x.followeeId); - query.andWhere(new Brackets(qb => { - qb - .where(new Brackets(qb2 => { - qb2 - .where('note.userId IN (:...meOrFolloweeIds)', { meOrFolloweeIds: meOrFolloweeIds }) - .andWhere('note.channelId IS NULL'); - })) - .orWhere('note.channelId IN (:...followingChannelIds)', { followingChannelIds }); - })); - } else if (followees.length > 0) { - // ユーザーフォローのみ(チャンネルフォローなし) - const meOrFolloweeIds = [me.id, ...followees.map(f => f.followeeId)]; - query - .andWhere('note.channelId IS NULL') - .andWhere('note.userId IN (:...meOrFolloweeIds)', { meOrFolloweeIds: meOrFolloweeIds }); - } else if (followingChannels.length > 0) { - // チャンネルフォローのみ(ユーザーフォローなし) - const followingChannelIds = followingChannels.map(x => x.followeeId); - query.andWhere(new Brackets(qb => { - qb - .where('note.channelId IN (:...followingChannelIds)', { followingChannelIds }) - .orWhere('note.userId = :meId', { meId: me.id }); - })); - } else { - // フォローなし - query - .andWhere('note.channelId IS NULL') - .andWhere('note.userId = :meId', { meId: me.id }); - } - - query.andWhere(new Brackets(qb => { - qb - .where('note.replyId IS NULL') // 返信ではない - .orWhere(new Brackets(qb => { - qb // 返信だけど投稿者自身への返信 - .where('note.replyId IS NOT NULL') - .andWhere('note.replyUserId = note.userId'); - })); - })); + .leftJoinAndSelect('renote.user', 'renoteUser') + .limit(ps.limit); this.queryService.generateVisibilityQuery(query, me); this.queryService.generateBlockedHostQueryForNote(query); + this.queryService.generateSilencedUserQueryForNotes(query, me); this.queryService.generateMutedUserQueryForNotes(query, me); this.queryService.generateBlockedUserQueryForNotes(query, me); - this.queryService.generateMutedUserRenotesQueryForNotes(query, me); - - if (ps.includeMyRenotes === false) { - query.andWhere(new Brackets(qb => { - qb.orWhere('note.userId != :meId', { meId: me.id }); - qb.orWhere('note.renoteId IS NULL'); - qb.orWhere('note.text IS NOT NULL'); - qb.orWhere('note.fileIds != \'{}\''); - qb.orWhere('0 < (SELECT COUNT(*) FROM poll WHERE poll."noteId" = note.id)'); - })); - } - - if (ps.includeRenotedMyNotes === false) { - query.andWhere(new Brackets(qb => { - qb.orWhere('note.renoteUserId != :meId', { meId: me.id }); - qb.orWhere('note.renoteId IS NULL'); - qb.orWhere('note.text IS NOT NULL'); - qb.orWhere('note.fileIds != \'{}\''); - qb.orWhere('0 < (SELECT COUNT(*) FROM poll WHERE poll."noteId" = note.id)'); - })); - } - - if (ps.includeLocalRenotes === false) { - query.andWhere(new Brackets(qb => { - qb.orWhere('note.renoteUserHost IS NOT NULL'); - qb.orWhere('note.renoteId IS NULL'); - qb.orWhere('note.text IS NOT NULL'); - qb.orWhere('note.fileIds != \'{}\''); - qb.orWhere('0 < (SELECT COUNT(*) FROM poll WHERE poll."noteId" = note.id)'); - })); - } if (ps.withFiles) { query.andWhere('note.fileIds != \'{}\''); } - if (ps.withRenotes === false) { - query.andWhere('note.renoteId IS NULL'); - } - if (!ps.withBots) query.andWhere('user.isBot = FALSE'); + + if (!ps.withRenotes) { + this.queryService.generateExcludedRenotesQueryForNotes(query); + } else { + this.queryService.generateMutedUserRenotesQueryForNotes(query, me); + } //#endregion - return await query.limit(ps.limit).getMany(); + return await query.getMany(); } } |