From 9cda544336fc0a8e1e9c111852b9ebc084be9380 Mon Sep 17 00:00:00 2001 From: omargamal10 Date: Sat, 13 Dec 2025 16:18:32 +0200 Subject: [PATCH 1/2] fix: differentiate validation of following authors from interest authors --- src/tweets/timeline/timeline.service.ts | 17 +++++++++++++---- src/tweets/tweets.repository.ts | 7 ++++++- 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/src/tweets/timeline/timeline.service.ts b/src/tweets/timeline/timeline.service.ts index 52b81f4a..64023bd5 100644 --- a/src/tweets/timeline/timeline.service.ts +++ b/src/tweets/timeline/timeline.service.ts @@ -1238,6 +1238,7 @@ export class TimelineService { // 2. Get tweet candidates from the Following timeline cache const followingTweets = await this.getFollowingTimelineCandidates(userId, FOR_YOU_FEED_SIZE); const followingTweetIds = new Set(followingTweets.map((t) => t.id)); // Keep track of which IDs came from this source + const followingAuthorIds = new Set(followingTweets.map((t) => t.authorId)); this.logger.debug( `Got ${followingTweets.length} candidate tweets from Following timeline for user ${userId}`, @@ -1272,14 +1273,22 @@ export class TimelineService { } const candidateTweetIds = candidates.map((c) => BigInt(c.id)); - const candidateAuthorIds = new Set(candidates.map((c) => BigInt(c.authorId))); + const candidateAuthorIds = Array.from(new Set(candidates.map((c) => BigInt(c.authorId)))); - const [validAuthorIds, validTweetIds] = await Promise.all([ - this.tweetsRepository.filterNonMutedAuthors(userId, Array.from(candidateAuthorIds)), + const followingCandidateAuthorIds = candidateAuthorIds.filter((id) => + followingAuthorIds.has(id.toString()), + ); + const interestCandidateAuthorIds = candidateAuthorIds.filter( + (id) => !followingAuthorIds.has(id.toString()), + ); + + const [validFollowingAuthorIds, validInterestAuthorIds, validTweetIds] = await Promise.all([ + this.tweetsRepository.filterValidAuthors(userId, followingCandidateAuthorIds), + this.tweetsRepository.filterNonMutedNonBlockedAuthors(userId, interestCandidateAuthorIds), this.tweetsRepository.filterValidTweets(candidateTweetIds), ]); - validAuthorIds.push(userId); + const validAuthorIds = [userId, ...validFollowingAuthorIds, ...validInterestAuthorIds]; const validAuthorSet = new Set(validAuthorIds.map((id) => id.toString())); const validTweetSet = new Set(validTweetIds.map((id) => id.toString())); diff --git a/src/tweets/tweets.repository.ts b/src/tweets/tweets.repository.ts index be3b72e6..58276155 100644 --- a/src/tweets/tweets.repository.ts +++ b/src/tweets/tweets.repository.ts @@ -1419,7 +1419,7 @@ export class TweetsRepository { return validFollows.map((f) => f.followedId); } - async filterNonMutedAuthors(userId: bigint, authorIds: bigint[]): Promise { + async filterNonMutedNonBlockedAuthors(userId: bigint, authorIds: bigint[]): Promise { const validAuthors = await this.prisma.user.findMany({ where: { id: { in: authorIds }, @@ -1429,6 +1429,11 @@ export class TweetsRepository { userId: userId, }, }, + blockedBy: { + none: { + userId: userId, + }, + }, }, select: { id: true }, }); From 1c159de2fff1d807dfd24c3b79d29e8ed132214f Mon Sep 17 00:00:00 2001 From: omargamal10 Date: Mon, 15 Dec 2025 15:43:48 +0200 Subject: [PATCH 2/2] fix: ensure author did not block user too in for-you --- src/tweets/tweets.repository.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/tweets/tweets.repository.ts b/src/tweets/tweets.repository.ts index 047725e5..49c84868 100644 --- a/src/tweets/tweets.repository.ts +++ b/src/tweets/tweets.repository.ts @@ -1465,6 +1465,11 @@ export class TweetsRepository { userId: userId, }, }, + blockedUsers: { + none: { + blockedId: userId, + }, + }, }, select: { id: true }, });