細かいミュートの処理の修正 (#13695)
* fix: some replies are removed from global timeline * refactor: 各チャンネルのミュートとブロックの処理をまとめる * fix: リノートをミュートでその人のノートのリノートをミュートしていたを修正 * refactor: isPureRenotePackedを他のところでも使う * docs(changelog): CHANGELOGを更新 * test: withReplies = falseでフォローしてる人によるリプライが流れてくる * test: ノートミュートしているユーザーの通常ノートのリノートが流れてくる/含まれる
This commit is contained in:
		| @@ -4,7 +4,6 @@ | ||||
|  */ | ||||
|  | ||||
| import { Injectable } from '@nestjs/common'; | ||||
| import { isUserRelated } from '@/misc/is-user-related.js'; | ||||
| import { NoteEntityService } from '@/core/entities/NoteEntityService.js'; | ||||
| import { bindThis } from '@/decorators.js'; | ||||
| import type { GlobalEvents } from '@/core/GlobalEventService.js'; | ||||
| @@ -40,12 +39,7 @@ class AntennaChannel extends Channel { | ||||
| 		if (data.type === 'note') { | ||||
| 			const note = await this.noteEntityService.pack(data.body.id, this.user, { detail: true }); | ||||
|  | ||||
| 			// 流れてきたNoteがミュートしているユーザーが関わるものだったら無視する | ||||
| 			if (isUserRelated(note, this.userIdsWhoMeMuting)) return; | ||||
| 			// 流れてきたNoteがブロックされているユーザーが関わるものだったら無視する | ||||
| 			if (isUserRelated(note, this.userIdsWhoBlockingMe)) return; | ||||
|  | ||||
| 			if (note.renote && !note.text && isUserRelated(note, this.userIdsWhoMeMutingRenotes)) return; | ||||
| 			if (this.isNoteMutedOrBlocked(note)) return; | ||||
|  | ||||
| 			this.connection.cacheNote(note); | ||||
|  | ||||
|   | ||||
| @@ -4,10 +4,10 @@ | ||||
|  */ | ||||
|  | ||||
| import { Injectable } from '@nestjs/common'; | ||||
| import { isUserRelated } from '@/misc/is-user-related.js'; | ||||
| import type { Packed } from '@/misc/json-schema.js'; | ||||
| import { NoteEntityService } from '@/core/entities/NoteEntityService.js'; | ||||
| import { bindThis } from '@/decorators.js'; | ||||
| import { isRenotePacked, isQuotePacked } from '@/misc/is-renote.js'; | ||||
| import Channel, { type MiChannelService } from '../channel.js'; | ||||
|  | ||||
| class ChannelChannel extends Channel { | ||||
| @@ -38,14 +38,9 @@ class ChannelChannel extends Channel { | ||||
| 	private async onNote(note: Packed<'Note'>) { | ||||
| 		if (note.channelId !== this.channelId) return; | ||||
|  | ||||
| 		// 流れてきたNoteがミュートしているユーザーが関わるものだったら無視する | ||||
| 		if (isUserRelated(note, this.userIdsWhoMeMuting)) return; | ||||
| 		// 流れてきたNoteがブロックされているユーザーが関わるものだったら無視する | ||||
| 		if (isUserRelated(note, this.userIdsWhoBlockingMe)) return; | ||||
| 		if (this.isNoteMutedOrBlocked(note)) return; | ||||
|  | ||||
| 		if (note.renote && !note.text && isUserRelated(note, this.userIdsWhoMeMutingRenotes)) return; | ||||
|  | ||||
| 		if (this.user && note.renoteId && !note.text) { | ||||
| 		if (this.user && isRenotePacked(note) && !isQuotePacked(note)) { | ||||
| 			if (note.renote && Object.keys(note.renote.reactions).length > 0) { | ||||
| 				const myRenoteReaction = await this.noteEntityService.populateMyReaction(note.renote, this.user.id); | ||||
| 				note.renote.myReaction = myRenoteReaction; | ||||
|   | ||||
| @@ -4,14 +4,12 @@ | ||||
|  */ | ||||
|  | ||||
| import { Injectable } from '@nestjs/common'; | ||||
| import { checkWordMute } from '@/misc/check-word-mute.js'; | ||||
| import { isInstanceMuted } from '@/misc/is-instance-muted.js'; | ||||
| import { isUserRelated } from '@/misc/is-user-related.js'; | ||||
| import type { Packed } from '@/misc/json-schema.js'; | ||||
| import { MetaService } from '@/core/MetaService.js'; | ||||
| import { NoteEntityService } from '@/core/entities/NoteEntityService.js'; | ||||
| import { bindThis } from '@/decorators.js'; | ||||
| import { RoleService } from '@/core/RoleService.js'; | ||||
| import { isRenotePacked, isQuotePacked } from '@/misc/is-renote.js'; | ||||
| import Channel, { type MiChannelService } from '../channel.js'; | ||||
|  | ||||
| class GlobalTimelineChannel extends Channel { | ||||
| @@ -52,26 +50,11 @@ class GlobalTimelineChannel extends Channel { | ||||
| 		if (note.visibility !== 'public') return; | ||||
| 		if (note.channelId != null) return; | ||||
|  | ||||
| 		// 関係ない返信は除外 | ||||
| 		if (note.reply && !this.following[note.userId]?.withReplies) { | ||||
| 			const reply = note.reply; | ||||
| 			// 「チャンネル接続主への返信」でもなければ、「チャンネル接続主が行った返信」でもなければ、「投稿者の投稿者自身への返信」でもない場合 | ||||
| 			if (reply.userId !== this.user!.id && note.userId !== this.user!.id && reply.userId !== note.userId) return; | ||||
| 		} | ||||
| 		if (isRenotePacked(note) && !isQuotePacked(note) && !this.withRenotes) return; | ||||
|  | ||||
| 		if (note.renote && note.text == null && (note.fileIds == null || note.fileIds.length === 0) && !this.withRenotes) return; | ||||
| 		if (this.isNoteMutedOrBlocked(note)) return; | ||||
|  | ||||
| 		// Ignore notes from instances the user has muted | ||||
| 		if (isInstanceMuted(note, new Set<string>(this.userProfile?.mutedInstances ?? []))) return; | ||||
|  | ||||
| 		// 流れてきたNoteがミュートしているユーザーが関わるものだったら無視する | ||||
| 		if (isUserRelated(note, this.userIdsWhoMeMuting)) return; | ||||
| 		// 流れてきたNoteがブロックされているユーザーが関わるものだったら無視する | ||||
| 		if (isUserRelated(note, this.userIdsWhoBlockingMe)) return; | ||||
|  | ||||
| 		if (note.renote && !note.text && isUserRelated(note, this.userIdsWhoMeMutingRenotes)) return; | ||||
|  | ||||
| 		if (this.user && note.renoteId && !note.text) { | ||||
| 		if (this.user && isRenotePacked(note) && !isQuotePacked(note)) { | ||||
| 			if (note.renote && Object.keys(note.renote.reactions).length > 0) { | ||||
| 				const myRenoteReaction = await this.noteEntityService.populateMyReaction(note.renote, this.user.id); | ||||
| 				note.renote.myReaction = myRenoteReaction; | ||||
|   | ||||
| @@ -5,10 +5,10 @@ | ||||
|  | ||||
| import { Injectable } from '@nestjs/common'; | ||||
| import { normalizeForSearch } from '@/misc/normalize-for-search.js'; | ||||
| import { isUserRelated } from '@/misc/is-user-related.js'; | ||||
| import type { Packed } from '@/misc/json-schema.js'; | ||||
| import { NoteEntityService } from '@/core/entities/NoteEntityService.js'; | ||||
| import { bindThis } from '@/decorators.js'; | ||||
| import { isRenotePacked, isQuotePacked } from '@/misc/is-renote.js'; | ||||
| import Channel, { type MiChannelService } from '../channel.js'; | ||||
|  | ||||
| class HashtagChannel extends Channel { | ||||
| @@ -43,14 +43,9 @@ class HashtagChannel extends Channel { | ||||
| 		const matched = this.q.some(tags => tags.every(tag => noteTags.includes(normalizeForSearch(tag)))); | ||||
| 		if (!matched) return; | ||||
|  | ||||
| 		// 流れてきたNoteがミュートしているユーザーが関わるものだったら無視する | ||||
| 		if (isUserRelated(note, this.userIdsWhoMeMuting)) return; | ||||
| 		// 流れてきたNoteがブロックされているユーザーが関わるものだったら無視する | ||||
| 		if (isUserRelated(note, this.userIdsWhoBlockingMe)) return; | ||||
| 		if (this.isNoteMutedOrBlocked(note)) return; | ||||
|  | ||||
| 		if (note.renote && !note.text && isUserRelated(note, this.userIdsWhoMeMutingRenotes)) return; | ||||
|  | ||||
| 		if (this.user && note.renoteId && !note.text) { | ||||
| 		if (this.user && isRenotePacked(note) && !isQuotePacked(note)) { | ||||
| 			if (note.renote && Object.keys(note.renote.reactions).length > 0) { | ||||
| 				const myRenoteReaction = await this.noteEntityService.populateMyReaction(note.renote, this.user.id); | ||||
| 				note.renote.myReaction = myRenoteReaction; | ||||
|   | ||||
| @@ -4,12 +4,10 @@ | ||||
|  */ | ||||
|  | ||||
| import { Injectable } from '@nestjs/common'; | ||||
| import { checkWordMute } from '@/misc/check-word-mute.js'; | ||||
| import { isUserRelated } from '@/misc/is-user-related.js'; | ||||
| import { isInstanceMuted } from '@/misc/is-instance-muted.js'; | ||||
| import type { Packed } from '@/misc/json-schema.js'; | ||||
| import { NoteEntityService } from '@/core/entities/NoteEntityService.js'; | ||||
| import { bindThis } from '@/decorators.js'; | ||||
| import { isRenotePacked, isQuotePacked } from '@/misc/is-renote.js'; | ||||
| import Channel, { type MiChannelService } from '../channel.js'; | ||||
|  | ||||
| class HomeTimelineChannel extends Channel { | ||||
| @@ -51,9 +49,6 @@ class HomeTimelineChannel extends Channel { | ||||
| 			if (!isMe && !Object.hasOwn(this.following, note.userId)) return; | ||||
| 		} | ||||
|  | ||||
| 		// Ignore notes from instances the user has muted | ||||
| 		if (isInstanceMuted(note, new Set<string>(this.userProfile!.mutedInstances))) return; | ||||
|  | ||||
| 		if (note.visibility === 'followers') { | ||||
| 			if (!isMe && !Object.hasOwn(this.following, note.userId)) return; | ||||
| 		} else if (note.visibility === 'specified') { | ||||
| @@ -72,7 +67,7 @@ class HomeTimelineChannel extends Channel { | ||||
| 		} | ||||
|  | ||||
| 		// 純粋なリノート(引用リノートでないリノート)の場合 | ||||
| 		if (note.renote && note.text == null && (note.fileIds == null || note.fileIds.length === 0) && note.poll == null) { | ||||
| 		if (isRenotePacked(note) && !isQuotePacked(note) && note.renote) { | ||||
| 			if (!this.withRenotes) return; | ||||
| 			if (note.renote.reply) { | ||||
| 				const reply = note.renote.reply; | ||||
| @@ -81,14 +76,9 @@ class HomeTimelineChannel extends Channel { | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		// 流れてきたNoteがミュートしているユーザーが関わるものだったら無視する | ||||
| 		if (isUserRelated(note, this.userIdsWhoMeMuting)) return; | ||||
| 		// 流れてきたNoteがブロックされているユーザーが関わるものだったら無視する | ||||
| 		if (isUserRelated(note, this.userIdsWhoBlockingMe)) return; | ||||
| 		if (this.isNoteMutedOrBlocked(note)) return; | ||||
|  | ||||
| 		if (note.renote && !note.text && isUserRelated(note, this.userIdsWhoMeMutingRenotes)) return; | ||||
|  | ||||
| 		if (this.user && note.renoteId && !note.text) { | ||||
| 		if (this.user && isRenotePacked(note) && !isQuotePacked(note)) { | ||||
| 			if (note.renote && Object.keys(note.renote.reactions).length > 0) { | ||||
| 				const myRenoteReaction = await this.noteEntityService.populateMyReaction(note.renote, this.user.id); | ||||
| 				note.renote.myReaction = myRenoteReaction; | ||||
|   | ||||
| @@ -4,14 +4,12 @@ | ||||
|  */ | ||||
|  | ||||
| import { Injectable } from '@nestjs/common'; | ||||
| import { checkWordMute } from '@/misc/check-word-mute.js'; | ||||
| import { isUserRelated } from '@/misc/is-user-related.js'; | ||||
| import { isInstanceMuted } from '@/misc/is-instance-muted.js'; | ||||
| import type { Packed } from '@/misc/json-schema.js'; | ||||
| import { MetaService } from '@/core/MetaService.js'; | ||||
| import { NoteEntityService } from '@/core/entities/NoteEntityService.js'; | ||||
| import { bindThis } from '@/decorators.js'; | ||||
| import { RoleService } from '@/core/RoleService.js'; | ||||
| import { isRenotePacked, isQuotePacked } from '@/misc/is-renote.js'; | ||||
| import Channel, { type MiChannelService } from '../channel.js'; | ||||
|  | ||||
| class HybridTimelineChannel extends Channel { | ||||
| @@ -71,8 +69,7 @@ class HybridTimelineChannel extends Channel { | ||||
| 			if (!isMe && !note.visibleUserIds!.includes(this.user!.id)) return; | ||||
| 		} | ||||
|  | ||||
| 		// Ignore notes from instances the user has muted | ||||
| 		if (isInstanceMuted(note, new Set<string>(this.userProfile!.mutedInstances))) return; | ||||
| 		if (this.isNoteMutedOrBlocked(note)) return; | ||||
|  | ||||
| 		if (note.reply) { | ||||
| 			const reply = note.reply; | ||||
| @@ -85,14 +82,7 @@ class HybridTimelineChannel extends Channel { | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		if (note.renote && note.text == null && (note.fileIds == null || note.fileIds.length === 0) && !this.withRenotes) return; | ||||
|  | ||||
| 		// 流れてきたNoteがミュートしているユーザーが関わるものだったら無視する | ||||
| 		if (isUserRelated(note, this.userIdsWhoMeMuting)) return; | ||||
| 		// 流れてきたNoteがブロックされているユーザーが関わるものだったら無視する | ||||
| 		if (isUserRelated(note, this.userIdsWhoBlockingMe)) return; | ||||
|  | ||||
| 		if (note.renote && !note.text && isUserRelated(note, this.userIdsWhoMeMutingRenotes)) return; | ||||
| 		if (isRenotePacked(note) && !isQuotePacked(note) && !this.withRenotes) return; | ||||
|  | ||||
| 		if (this.user && note.renoteId && !note.text) { | ||||
| 			if (note.renote && Object.keys(note.renote.reactions).length > 0) { | ||||
|   | ||||
| @@ -4,13 +4,12 @@ | ||||
|  */ | ||||
|  | ||||
| import { Injectable } from '@nestjs/common'; | ||||
| import { checkWordMute } from '@/misc/check-word-mute.js'; | ||||
| import { isUserRelated } from '@/misc/is-user-related.js'; | ||||
| import type { Packed } from '@/misc/json-schema.js'; | ||||
| import { MetaService } from '@/core/MetaService.js'; | ||||
| import { NoteEntityService } from '@/core/entities/NoteEntityService.js'; | ||||
| import { bindThis } from '@/decorators.js'; | ||||
| import { RoleService } from '@/core/RoleService.js'; | ||||
| import { isQuotePacked, isRenotePacked } from '@/misc/is-renote.js'; | ||||
| import Channel, { type MiChannelService } from '../channel.js'; | ||||
|  | ||||
| class LocalTimelineChannel extends Channel { | ||||
| @@ -61,16 +60,11 @@ class LocalTimelineChannel extends Channel { | ||||
| 			if (reply.userId !== this.user.id && note.userId !== this.user.id && reply.userId !== note.userId) return; | ||||
| 		} | ||||
|  | ||||
| 		if (note.renote && note.text == null && (note.fileIds == null || note.fileIds.length === 0) && !this.withRenotes) return; | ||||
| 		if (isRenotePacked(note) && !isQuotePacked(note) && !this.withRenotes) return; | ||||
|  | ||||
| 		// 流れてきたNoteがミュートしているユーザーが関わるものだったら無視する | ||||
| 		if (isUserRelated(note, this.userIdsWhoMeMuting)) return; | ||||
| 		// 流れてきたNoteがブロックされているユーザーが関わるものだったら無視する | ||||
| 		if (isUserRelated(note, this.userIdsWhoBlockingMe)) return; | ||||
| 		if (this.isNoteMutedOrBlocked(note)) return; | ||||
|  | ||||
| 		if (note.renote && !note.text && isUserRelated(note, this.userIdsWhoMeMutingRenotes)) return; | ||||
|  | ||||
| 		if (this.user && note.renoteId && !note.text) { | ||||
| 		if (this.user && isRenotePacked(note) && !isQuotePacked(note)) { | ||||
| 			if (note.renote && Object.keys(note.renote.reactions).length > 0) { | ||||
| 				const myRenoteReaction = await this.noteEntityService.populateMyReaction(note.renote, this.user.id); | ||||
| 				note.renote.myReaction = myRenoteReaction; | ||||
|   | ||||
| @@ -4,8 +4,6 @@ | ||||
|  */ | ||||
|  | ||||
| import { Injectable } from '@nestjs/common'; | ||||
| import { isUserRelated } from '@/misc/is-user-related.js'; | ||||
| import type { Packed } from '@/misc/json-schema.js'; | ||||
| import { NoteEntityService } from '@/core/entities/NoteEntityService.js'; | ||||
| import { bindThis } from '@/decorators.js'; | ||||
| import { RoleService } from '@/core/RoleService.js'; | ||||
| @@ -46,12 +44,7 @@ class RoleTimelineChannel extends Channel { | ||||
| 			} | ||||
| 			if (note.visibility !== 'public') return; | ||||
|  | ||||
| 			// 流れてきたNoteがミュートしているユーザーが関わるものだったら無視する | ||||
| 			if (isUserRelated(note, this.userIdsWhoMeMuting)) return; | ||||
| 			// 流れてきたNoteがブロックされているユーザーが関わるものだったら無視する | ||||
| 			if (isUserRelated(note, this.userIdsWhoBlockingMe)) return; | ||||
|  | ||||
| 			if (note.renote && !note.text && isUserRelated(note, this.userIdsWhoMeMutingRenotes)) return; | ||||
| 			if (this.isNoteMutedOrBlocked(note)) return; | ||||
|  | ||||
| 			this.send('note', note); | ||||
| 		} else { | ||||
|   | ||||
| @@ -5,12 +5,11 @@ | ||||
|  | ||||
| import { Inject, Injectable } from '@nestjs/common'; | ||||
| import type { MiUserListMembership, UserListMembershipsRepository, UserListsRepository } from '@/models/_.js'; | ||||
| import { isUserRelated } from '@/misc/is-user-related.js'; | ||||
| import type { Packed } from '@/misc/json-schema.js'; | ||||
| import { NoteEntityService } from '@/core/entities/NoteEntityService.js'; | ||||
| import { DI } from '@/di-symbols.js'; | ||||
| import { bindThis } from '@/decorators.js'; | ||||
| import { isInstanceMuted } from '@/misc/is-instance-muted.js'; | ||||
| import { isRenotePacked, isQuotePacked } from '@/misc/is-renote.js'; | ||||
| import Channel, { type MiChannelService } from '../channel.js'; | ||||
|  | ||||
| class UserListChannel extends Channel { | ||||
| @@ -106,25 +105,17 @@ class UserListChannel extends Channel { | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		if (note.renote && note.text == null && (note.fileIds == null || note.fileIds.length === 0) && !this.withRenotes) return; | ||||
| 		if (isRenotePacked(note) && !isQuotePacked(note) && !this.withRenotes) return; | ||||
|  | ||||
| 		// 流れてきたNoteがミュートしているユーザーが関わるものだったら無視する | ||||
| 		if (isUserRelated(note, this.userIdsWhoMeMuting)) return; | ||||
| 		// 流れてきたNoteがブロックされているユーザーが関わるものだったら無視する | ||||
| 		if (isUserRelated(note, this.userIdsWhoBlockingMe)) return; | ||||
| 		if (this.isNoteMutedOrBlocked(note)) return; | ||||
|  | ||||
| 		if (note.renote && !note.text && isUserRelated(note, this.userIdsWhoMeMutingRenotes)) return; | ||||
|  | ||||
| 		if (this.user && note.renoteId && !note.text) { | ||||
| 		if (this.user && isRenotePacked(note) && !isQuotePacked(note)) { | ||||
| 			if (note.renote && Object.keys(note.renote.reactions).length > 0) { | ||||
| 				const myRenoteReaction = await this.noteEntityService.populateMyReaction(note.renote, this.user.id); | ||||
| 				note.renote.myReaction = myRenoteReaction; | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		// 流れてきたNoteがミュートしているインスタンスに関わるものだったら無視する | ||||
| 		if (isInstanceMuted(note, this.userMutedInstances)) return; | ||||
|  | ||||
| 		this.connection.cacheNote(note); | ||||
|  | ||||
| 		this.send('note', note); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 anatawa12
					anatawa12