From ec92bf47f1ba8def29ed55997be590e3491270ab Mon Sep 17 00:00:00 2001 From: anatawa12 Date: Mon, 28 Apr 2025 07:21:00 +0900 Subject: Exclude blocked instance note from most timelines (#15792) * Exclude blocked instance note from most timelines * Exclude blocked instance note from FTT timelines * Exclude blocked instance note from featured * fix type --- packages/backend/src/server/api/endpoints/notes/featured.ts | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'packages/backend/src/server/api/endpoints/notes/featured.ts') diff --git a/packages/backend/src/server/api/endpoints/notes/featured.ts b/packages/backend/src/server/api/endpoints/notes/featured.ts index dcd971360d..e7aba2d306 100644 --- a/packages/backend/src/server/api/endpoints/notes/featured.ts +++ b/packages/backend/src/server/api/endpoints/notes/featured.ts @@ -11,6 +11,7 @@ import { DI } from '@/di-symbols.js'; import { FeaturedService } from '@/core/FeaturedService.js'; import { isUserRelated } from '@/misc/is-user-related.js'; import { CacheService } from '@/core/CacheService.js'; +import { QueryService } from '@/core/QueryService.js'; export const meta = { tags: ['notes'], @@ -52,6 +53,7 @@ export default class extends Endpoint { // eslint- private cacheService: CacheService, private noteEntityService: NoteEntityService, private featuredService: FeaturedService, + private queryService: QueryService, ) { super(meta, paramDef, async (ps, me) => { let noteIds: string[]; @@ -94,6 +96,8 @@ export default class extends Endpoint { // eslint- .leftJoinAndSelect('renote.user', 'renoteUser') .leftJoinAndSelect('note.channel', 'channel'); + this.queryService.generateBlockedHostQueryForNote(query); + const notes = (await query.getMany()).filter(note => { if (me && isUserRelated(note, userIdsWhoBlockingMe)) return false; if (me && isUserRelated(note, userIdsWhoMeMuting)) return false; -- cgit v1.2.3-freya From f6eb3148f365683a5baa628c3494b590417d7542 Mon Sep 17 00:00:00 2001 From: Hazelnoot Date: Sun, 4 May 2025 08:55:26 -0400 Subject: use bucket rate limit for featured timeline --- packages/backend/src/server/api/endpoints/notes/featured.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'packages/backend/src/server/api/endpoints/notes/featured.ts') diff --git a/packages/backend/src/server/api/endpoints/notes/featured.ts b/packages/backend/src/server/api/endpoints/notes/featured.ts index 734ff31700..b5d2a71ecd 100644 --- a/packages/backend/src/server/api/endpoints/notes/featured.ts +++ b/packages/backend/src/server/api/endpoints/notes/featured.ts @@ -30,10 +30,11 @@ export const meta = { }, }, - // 10 calls per 5 seconds + // Burst of 10 calls to handle tab reload, then 4/second for refresh limit: { - duration: 1000 * 5, - max: 10, + type: 'bucket', + size: 10, + dripSize: 4, }, } as const; -- cgit v1.2.3-freya From 76597d1a4c7ee04244a35c2c4dcfe6dc5dc85ac1 Mon Sep 17 00:00:00 2001 From: Hazelnoot Date: Sun, 4 May 2025 08:55:57 -0400 Subject: check role assignments in featured timeline --- .../backend/src/server/api/endpoints/notes/featured.ts | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'packages/backend/src/server/api/endpoints/notes/featured.ts') diff --git a/packages/backend/src/server/api/endpoints/notes/featured.ts b/packages/backend/src/server/api/endpoints/notes/featured.ts index b5d2a71ecd..02d572e89b 100644 --- a/packages/backend/src/server/api/endpoints/notes/featured.ts +++ b/packages/backend/src/server/api/endpoints/notes/featured.ts @@ -12,6 +12,8 @@ import { FeaturedService } from '@/core/FeaturedService.js'; import { isUserRelated } from '@/misc/is-user-related.js'; import { CacheService } from '@/core/CacheService.js'; import { QueryService } from '@/core/QueryService.js'; +import { ApiError } from '@/server/api/error.js'; +import { RoleService } from '@/core/RoleService.js'; export const meta = { tags: ['notes'], @@ -30,6 +32,14 @@ export const meta = { }, }, + errors: { + ltlDisabled: { + message: 'Local timeline has been disabled.', + code: 'LTL_DISABLED', + id: '45a6eb02-7695-4393-b023-dd3be9aaaefd', + }, + }, + // Burst of 10 calls to handle tab reload, then 4/second for refresh limit: { type: 'bucket', @@ -61,8 +71,14 @@ export default class extends Endpoint { // eslint- private noteEntityService: NoteEntityService, private featuredService: FeaturedService, private queryService: QueryService, + private readonly roleService: RoleService, ) { super(meta, paramDef, async (ps, me) => { + const policies = await this.roleService.getUserPolicies(me ? me.id : null); + if (!policies.ltlAvailable) { + throw new ApiError(meta.errors.ltlDisabled); + } + let noteIds: string[]; if (ps.channelId) { noteIds = await this.featuredService.getInChannelNotesRanking(ps.channelId, 50); -- cgit v1.2.3-freya From dee2e19b6352197a2d8b764f81e15690967845a4 Mon Sep 17 00:00:00 2001 From: Hazelnoot Date: Sun, 11 May 2025 05:46:40 -0400 Subject: don't trend notes from non-explorable or non-trendable users --- packages/backend/src/core/NoteCreateService.ts | 27 ++++++++++++---------- packages/backend/src/core/ReactionService.ts | 24 ++++++++++++------- .../src/server/api/endpoints/notes/featured.ts | 3 ++- 3 files changed, 33 insertions(+), 21 deletions(-) (limited to 'packages/backend/src/server/api/endpoints/notes/featured.ts') diff --git a/packages/backend/src/core/NoteCreateService.ts b/packages/backend/src/core/NoteCreateService.ts index 4514f3decd..097d657ba3 100644 --- a/packages/backend/src/core/NoteCreateService.ts +++ b/packages/backend/src/core/NoteCreateService.ts @@ -633,7 +633,7 @@ export class NoteCreateService implements OnApplicationShutdown { } if (this.isRenote(data) && !this.isQuote(data) && data.renote.userId !== user.id && !user.isBot) { - this.incRenoteCount(data.renote); + this.incRenoteCount(data.renote, user); } if (data.poll && data.poll.expiresAt) { @@ -816,8 +816,8 @@ export class NoteCreateService implements OnApplicationShutdown { } @bindThis - private incRenoteCount(renote: MiNote) { - this.notesRepository.createQueryBuilder().update() + private async incRenoteCount(renote: MiNote, user: MiUser) { + await this.notesRepository.createQueryBuilder().update() .set({ renoteCount: () => '"renoteCount" + 1', }) @@ -825,15 +825,18 @@ export class NoteCreateService implements OnApplicationShutdown { .execute(); // 30%の確率、3日以内に投稿されたノートの場合ハイライト用ランキング更新 - if (Math.random() < 0.3 && (Date.now() - this.idService.parse(renote.id).date.getTime()) < 1000 * 60 * 60 * 24 * 3) { - if (renote.channelId != null) { - if (renote.replyId == null) { - this.featuredService.updateInChannelNotesRanking(renote.channelId, renote, 5); - } - } else { - if (renote.visibility === 'public' && renote.userHost == null && renote.replyId == null) { - this.featuredService.updateGlobalNotesRanking(renote, 5); - this.featuredService.updatePerUserNotesRanking(renote.userId, renote, 5); + if (user.isExplorable && Math.random() < 0.3 && (Date.now() - this.idService.parse(renote.id).date.getTime()) < 1000 * 60 * 60 * 24 * 3) { + const policies = await this.roleService.getUserPolicies(user); + if (policies.canTrend) { + if (renote.channelId != null) { + if (renote.replyId == null) { + this.featuredService.updateInChannelNotesRanking(renote.channelId, renote, 5); + } + } else { + if (renote.visibility === 'public' && renote.userHost == null && renote.replyId == null) { + this.featuredService.updateGlobalNotesRanking(renote, 5); + this.featuredService.updatePerUserNotesRanking(renote.userId, renote, 5); + } } } } diff --git a/packages/backend/src/core/ReactionService.ts b/packages/backend/src/core/ReactionService.ts index 373fea8605..a93605d2db 100644 --- a/packages/backend/src/core/ReactionService.ts +++ b/packages/backend/src/core/ReactionService.ts @@ -30,6 +30,7 @@ import { trackPromise } from '@/misc/promise-tracker.js'; import { isQuote, isRenote } from '@/misc/is-renote.js'; import { ReactionsBufferingService } from '@/core/ReactionsBufferingService.js'; import { PER_NOTE_REACTION_USER_PAIR_CACHE_MAX } from '@/const.js'; +import { CacheService } from '@/core/CacheService.js'; const FALLBACK = '\u2764'; @@ -102,6 +103,7 @@ export class ReactionService { private apDeliverManagerService: ApDeliverManagerService, private notificationService: NotificationService, private perUserReactionsChart: PerUserReactionsChart, + private readonly cacheService: CacheService, ) { } @@ -220,14 +222,20 @@ export class ReactionService { note.userId !== user.id && (Date.now() - this.idService.parse(note.id).date.getTime()) < 1000 * 60 * 60 * 24 * 3 ) { - if (note.channelId != null) { - if (note.replyId == null) { - this.featuredService.updateInChannelNotesRanking(note.channelId, note, 1); - } - } else { - if (note.visibility === 'public' && note.userHost == null && note.replyId == null) { - this.featuredService.updateGlobalNotesRanking(note, 1); - this.featuredService.updatePerUserNotesRanking(note.userId, note, 1); + const author = await this.cacheService.findUserById(note.userId); + if (author.isExplorable) { + const policies = await this.roleService.getUserPolicies(author); + if (policies.canTrend) { + if (note.channelId != null) { + if (note.replyId == null) { + this.featuredService.updateInChannelNotesRanking(note.channelId, note, 1); + } + } else { + if (note.visibility === 'public' && note.userHost == null && note.replyId == null) { + this.featuredService.updateGlobalNotesRanking(note, 1); + this.featuredService.updatePerUserNotesRanking(note.userId, note, 1); + } + } } } } diff --git a/packages/backend/src/server/api/endpoints/notes/featured.ts b/packages/backend/src/server/api/endpoints/notes/featured.ts index 02d572e89b..8ab9f72139 100644 --- a/packages/backend/src/server/api/endpoints/notes/featured.ts +++ b/packages/backend/src/server/api/endpoints/notes/featured.ts @@ -117,7 +117,8 @@ export default class extends Endpoint { // eslint- .leftJoinAndSelect('note.renote', 'renote') .leftJoinAndSelect('reply.user', 'replyUser') .leftJoinAndSelect('renote.user', 'renoteUser') - .leftJoinAndSelect('note.channel', 'channel'); + .leftJoinAndSelect('note.channel', 'channel') + .andWhere('user.isExplorable = TRUE'); this.queryService.generateBlockedHostQueryForNote(query); -- cgit v1.2.3-freya