summaryrefslogtreecommitdiff
path: root/packages/backend/src/core
diff options
context:
space:
mode:
authoranatawa12 <anatawa12@icloud.com>2025-04-28 07:21:00 +0900
committerGitHub <noreply@github.com>2025-04-28 07:21:00 +0900
commitec92bf47f1ba8def29ed55997be590e3491270ab (patch)
tree52b8873dd146eeb9b2fda9348b1c84da4b5d8fe6 /packages/backend/src/core
parentMerge branch 'develop' of https://github.com/misskey-dev/misskey into develop (diff)
downloadsharkey-ec92bf47f1ba8def29ed55997be590e3491270ab.tar.gz
sharkey-ec92bf47f1ba8def29ed55997be590e3491270ab.tar.bz2
sharkey-ec92bf47f1ba8def29ed55997be590e3491270ab.zip
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
Diffstat (limited to 'packages/backend/src/core')
-rw-r--r--packages/backend/src/core/FanoutTimelineEndpointService.ts20
-rw-r--r--packages/backend/src/core/QueryService.ts38
-rw-r--r--packages/backend/src/core/SearchService.ts12
3 files changed, 66 insertions, 4 deletions
diff --git a/packages/backend/src/core/FanoutTimelineEndpointService.ts b/packages/backend/src/core/FanoutTimelineEndpointService.ts
index ce8cc83dfd..1ffeb4b3a4 100644
--- a/packages/backend/src/core/FanoutTimelineEndpointService.ts
+++ b/packages/backend/src/core/FanoutTimelineEndpointService.ts
@@ -8,10 +8,12 @@ import { DI } from '@/di-symbols.js';
import { bindThis } from '@/decorators.js';
import type { MiUser } from '@/models/User.js';
import type { MiNote } from '@/models/Note.js';
+import type { MiMeta } from '@/models/Meta.js';
import { Packed } from '@/misc/json-schema.js';
import type { NotesRepository } from '@/models/_.js';
import { NoteEntityService } from '@/core/entities/NoteEntityService.js';
import { FanoutTimelineName, FanoutTimelineService } from '@/core/FanoutTimelineService.js';
+import { UtilityService } from '@/core/UtilityService.js';
import { isUserRelated } from '@/misc/is-user-related.js';
import { isQuote, isRenote } from '@/misc/is-renote.js';
import { CacheService } from '@/core/CacheService.js';
@@ -30,6 +32,7 @@ type TimelineOptions = {
alwaysIncludeMyNotes?: boolean;
ignoreAuthorFromBlock?: boolean;
ignoreAuthorFromMute?: boolean;
+ ignoreAuthorFromInstanceBlock?: boolean;
excludeNoFiles?: boolean;
excludeReplies?: boolean;
excludePureRenotes: boolean;
@@ -42,9 +45,13 @@ export class FanoutTimelineEndpointService {
@Inject(DI.notesRepository)
private notesRepository: NotesRepository,
+ @Inject(DI.meta)
+ private meta: MiMeta,
+
private noteEntityService: NoteEntityService,
private cacheService: CacheService,
private fanoutTimelineService: FanoutTimelineService,
+ private utilityService: UtilityService,
) {
}
@@ -119,6 +126,19 @@ export class FanoutTimelineEndpointService {
};
}
+ {
+ const parentFilter = filter;
+ filter = (note) => {
+ if (!ps.ignoreAuthorFromInstanceBlock) {
+ if (this.utilityService.isBlockedHost(this.meta.blockedHosts, note.userHost)) return false;
+ }
+ if (note.userId !== note.renoteUserId && this.utilityService.isBlockedHost(this.meta.blockedHosts, note.renoteUserHost)) return false;
+ if (note.userId !== note.replyUserId && this.utilityService.isBlockedHost(this.meta.blockedHosts, note.replyUserHost)) return false;
+
+ return parentFilter(note);
+ };
+ }
+
const redisTimeline: MiNote[] = [];
let readFromRedis = 0;
let lastSuccessfulRate = 1; // rateをキャッシュする?
diff --git a/packages/backend/src/core/QueryService.ts b/packages/backend/src/core/QueryService.ts
index 412ab33b3f..119eb49c02 100644
--- a/packages/backend/src/core/QueryService.ts
+++ b/packages/backend/src/core/QueryService.ts
@@ -7,7 +7,7 @@ import { Inject, Injectable } from '@nestjs/common';
import { Brackets, ObjectLiteral } from 'typeorm';
import { DI } from '@/di-symbols.js';
import type { MiUser } from '@/models/User.js';
-import type { UserProfilesRepository, FollowingsRepository, ChannelFollowingsRepository, BlockingsRepository, NoteThreadMutingsRepository, MutingsRepository, RenoteMutingsRepository } from '@/models/_.js';
+import type { UserProfilesRepository, FollowingsRepository, ChannelFollowingsRepository, BlockingsRepository, NoteThreadMutingsRepository, MutingsRepository, RenoteMutingsRepository, MiMeta } from '@/models/_.js';
import { bindThis } from '@/decorators.js';
import { IdService } from '@/core/IdService.js';
import type { SelectQueryBuilder } from 'typeorm';
@@ -36,6 +36,9 @@ export class QueryService {
@Inject(DI.renoteMutingsRepository)
private renoteMutingsRepository: RenoteMutingsRepository,
+ @Inject(DI.meta)
+ private meta: MiMeta,
+
private idService: IdService,
) {
}
@@ -251,4 +254,37 @@ export class QueryService {
q.setParameters(mutingQuery.getParameters());
}
+
+ @bindThis
+ public generateBlockedHostQueryForNote(q: SelectQueryBuilder<any>, excludeAuthor?: boolean): void {
+ let nonBlockedHostQuery: (part: string) => string;
+ if (this.meta.blockedHosts.length === 0) {
+ nonBlockedHostQuery = () => '1=1';
+ } else {
+ nonBlockedHostQuery = (match: string) => `${match} NOT ILIKE ALL(ARRAY[:...blocked])`;
+ q.setParameters({ blocked: this.meta.blockedHosts.flatMap(x => [x, `%.${x}`]) });
+ }
+
+ if (excludeAuthor) {
+ const instanceSuspension = (user: string) => new Brackets(qb => qb
+ .where(`note.${user}Id IS NULL`) // no corresponding user
+ .orWhere(`note.userId = note.${user}Id`)
+ .orWhere(`note.${user}Host IS NULL`) // local
+ .orWhere(nonBlockedHostQuery(`note.${user}Host`)));
+
+ q
+ .andWhere(instanceSuspension('replyUser'))
+ .andWhere(instanceSuspension('renoteUser'));
+ } else {
+ const instanceSuspension = (user: string) => new Brackets(qb => qb
+ .where(`note.${user}Id IS NULL`) // no corresponding user
+ .orWhere(`note.${user}Host IS NULL`) // local
+ .orWhere(nonBlockedHostQuery(`note.${user}Host`)));
+
+ q
+ .andWhere(instanceSuspension('user'))
+ .andWhere(instanceSuspension('replyUser'))
+ .andWhere(instanceSuspension('renoteUser'));
+ }
+ }
}
diff --git a/packages/backend/src/core/SearchService.ts b/packages/backend/src/core/SearchService.ts
index aa787c93de..d94281920e 100644
--- a/packages/backend/src/core/SearchService.ts
+++ b/packages/backend/src/core/SearchService.ts
@@ -234,6 +234,7 @@ export class SearchService {
}
this.queryService.generateVisibilityQuery(query, me);
+ this.queryService.generateBlockedHostQueryForNote(query);
if (me) this.queryService.generateMutedUserQueryForNotes(query, me);
if (me) this.queryService.generateBlockedUserQueryForNotes(query, me);
@@ -295,9 +296,14 @@ export class SearchService {
this.cacheService.userBlockedCache.fetch(me.id),
])
: [new Set<string>(), new Set<string>()];
- const notes = (await this.notesRepository.findBy({
- id: In(res.hits.map(x => x.id)),
- })).filter(note => {
+
+ const query = this.notesRepository.createQueryBuilder('note');
+
+ query.where('note.id IN (:...noteIds)', { noteIds: res.hits.map(x => x.id) });
+
+ 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;
return true;