From 5eca0a31f78493f2cff0fd5f097ee9d007991a87 Mon Sep 17 00:00:00 2001
From: MeiMei <30769358+mei23@users.noreply.github.com>
Date: Fri, 25 Jan 2019 00:06:20 +0900
Subject: [PATCH] Filter hidden replies / mentions (#3981)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

* Fix: 非公開投稿が返信一覧に出てくる

* Fix: 非公開投稿がメンション一覧に出てくる

* 非公開投稿は通知/メンション通知しない

* repliesにフォロワー限定がかからなかったのを修正

* Fix: ホームにフォロワー限定投稿が表示されない

* 認証必須エンドポイントで user == null にはならない

* mentionsにフォロワー限定がかからなかったのを修正
---
 src/server/api/endpoints/notes/mentions.ts | 24 ++++++++++++++--
 src/server/api/endpoints/notes/replies.ts  | 33 ++++++++++++++++++----
 src/server/api/endpoints/notes/timeline.ts |  2 +-
 src/server/api/stream/channels/main.ts     |  5 ++++
 4 files changed, 56 insertions(+), 8 deletions(-)

diff --git a/src/server/api/endpoints/notes/mentions.ts b/src/server/api/endpoints/notes/mentions.ts
index 4c7c397c77..8747590606 100644
--- a/src/server/api/endpoints/notes/mentions.ts
+++ b/src/server/api/endpoints/notes/mentions.ts
@@ -1,6 +1,6 @@
 import $ from 'cafy'; import ID, { transform } from '../../../../misc/cafy-id';
 import Note from '../../../../models/note';
-import { getFriendIds } from '../../common/get-friends';
+import { getFriendIds, getFriends } from '../../common/get-friends';
 import { packMany } from '../../../../models/note';
 import define from '../../define';
 import read from '../../../../services/note/read';
@@ -47,8 +47,28 @@ export default define(meta, (ps, user) => new Promise(async (res, rej) => {
 		return rej('cannot set sinceId and untilId');
 	}
 
+	// フォローを取得
+	const followings = await getFriends(user._id);
+
+	const visibleQuery = [{
+		visibility: { $in: [ 'public', 'home' ] }
+	}, {
+		// myself (for specified/private)
+		userId: user._id
+	}, {
+		// to me (for specified)
+		visibleUserIds: { $in: [ user._id ] }
+	}, {
+		visibility: 'followers',
+		userId: { $in: followings.map(f => f.id) }
+	}];
+
 	const query = {
-		deletedAt: null,
+		$and: [{
+			deletedAt: null,
+		}, {
+			$or: visibleQuery,
+		}],
 
 		$or: [{
 			mentions: user._id
diff --git a/src/server/api/endpoints/notes/replies.ts b/src/server/api/endpoints/notes/replies.ts
index 8386d60684..112156403d 100644
--- a/src/server/api/endpoints/notes/replies.ts
+++ b/src/server/api/endpoints/notes/replies.ts
@@ -2,6 +2,7 @@ import $ from 'cafy'; import ID, { transform } from '../../../../misc/cafy-id';
 import Note, { packMany } from '../../../../models/note';
 import define from '../../define';
 import Mute from '../../../../models/mute';
+import { getFriends } from '../../common/get-friends';
 
 export const meta = {
 	desc: {
@@ -34,13 +35,35 @@ export const meta = {
 };
 
 export default define(meta, (ps, user) => new Promise(async (res, rej) => {
-	// ミュートしているユーザーを取得
-	const mutedUserIds = user ? (await Mute.find({
-		muterId: user._id
-	})).map(m => m.muteeId) : null;
+	const [followings, mutedUserIds] = await Promise.all([
+		// フォローを取得
+		// Fetch following
+		user ? getFriends(user._id) : [],
+
+		// ミュートしているユーザーを取得
+		user ? (await Mute.find({
+			muterId: user._id
+		})).map(m => m.muteeId) : null
+	]);
+
+	const visibleQuery = user == null ? [{
+		visibility: { $in: [ 'public', 'home' ] }
+	}] : [{
+		visibility: { $in: [ 'public', 'home' ] }
+	}, {
+		// myself (for specified/private)
+		userId: user._id
+	}, {
+		// to me (for specified)
+		visibleUserIds: { $in: [ user._id ] }
+	}, {
+		visibility: 'followers',
+		userId: { $in: followings.map(f => f.id) }
+	}];
 
 	const q = {
-		replyId: ps.noteId
+		replyId: ps.noteId,
+		$or: visibleQuery
 	} as any;
 
 	if (mutedUserIds && mutedUserIds.length > 0) {
diff --git a/src/server/api/endpoints/notes/timeline.ts b/src/server/api/endpoints/notes/timeline.ts
index 94f4fb72d3..ead57e2d56 100644
--- a/src/server/api/endpoints/notes/timeline.ts
+++ b/src/server/api/endpoints/notes/timeline.ts
@@ -141,7 +141,7 @@ export default define(meta, (ps, user) => new Promise(async (res, rej) => {
 	const visibleQuery = user == null ? [{
 		visibility: { $in: [ 'public', 'home' ] }
 	}] : [{
-		visibility: { $in: [ 'public', 'home' ] }
+		visibility: { $in: [ 'public', 'home', 'followers' ] }
 	}, {
 		// myself (for specified/private)
 		userId: user._id
diff --git a/src/server/api/stream/channels/main.ts b/src/server/api/stream/channels/main.ts
index 5b0705f1d3..175d914fa5 100644
--- a/src/server/api/stream/channels/main.ts
+++ b/src/server/api/stream/channels/main.ts
@@ -19,6 +19,11 @@ export default class extends Channel {
 			switch (type) {
 				case 'notification': {
 					if (mutedUserIds.includes(body.userId)) return;
+					if (body.note && body.note.isHidden) return;
+					break;
+				}
+				case 'mention': {
+					if (body.isHidden) return;
 					break;
 				}
 			}