From c7ebf6f990660b5c8b2a6bb53dbd9ef6ff058531 Mon Sep 17 00:00:00 2001
From: MeiMei <30769358+mei23@users.noreply.github.com>
Date: Fri, 1 Feb 2019 09:57:51 +0900
Subject: [PATCH] Hide suspended users (#4075)

---
 src/server/api/common/get-hide-users.ts       | 20 ++++++++++++
 src/server/api/endpoints/i/notifications.ts   |  8 ++---
 .../api/endpoints/notes/global-timeline.ts    | 16 ++++------
 .../api/endpoints/notes/hybrid-timeline.ts    | 18 +++++------
 .../api/endpoints/notes/local-timeline.ts     | 16 ++++------
 src/server/api/endpoints/notes/mentions.ts    | 16 ++++------
 .../endpoints/notes/polls/recommendation.ts   | 10 +++---
 src/server/api/endpoints/notes/replies.ts     | 14 ++++----
 .../api/endpoints/notes/search_by_tag.ts      | 32 ++++++++-----------
 src/server/api/endpoints/notes/timeline.ts    | 16 ++++------
 .../api/endpoints/notes/user-list-timeline.ts | 16 ++++------
 .../api/endpoints/users/recommendation.ts     | 10 +++---
 12 files changed, 94 insertions(+), 98 deletions(-)
 create mode 100644 src/server/api/common/get-hide-users.ts

diff --git a/src/server/api/common/get-hide-users.ts b/src/server/api/common/get-hide-users.ts
new file mode 100644
index 0000000000..b3ddcec1f5
--- /dev/null
+++ b/src/server/api/common/get-hide-users.ts
@@ -0,0 +1,20 @@
+import * as mongo from 'mongodb';
+import Mute from '../../../models/mute';
+import User, { IUser } from '../../../models/user';
+import { unique } from '../../../prelude/array';
+
+export async function getHideUserIds(me: IUser) {
+	return me ? await getHideUserIdsById(me._id) : [];
+}
+
+export async function getHideUserIdsById(meId: mongo.ObjectID) {
+	const suspended = (await User.find({
+		isSuspended: true
+	})).map(user => user._id);
+
+	const muted = meId ? (await Mute.find({
+		muterId: meId
+	})).map(mute => mute.muteeId) : [];
+
+	return unique(suspended.concat(muted));
+}
diff --git a/src/server/api/endpoints/i/notifications.ts b/src/server/api/endpoints/i/notifications.ts
index 028d67a018..4d8aee0caa 100644
--- a/src/server/api/endpoints/i/notifications.ts
+++ b/src/server/api/endpoints/i/notifications.ts
@@ -1,10 +1,10 @@
 import $ from 'cafy'; import ID, { transform } from '../../../../misc/cafy-id';
 import Notification from '../../../../models/notification';
-import Mute from '../../../../models/mute';
 import { packMany } from '../../../../models/notification';
 import { getFriendIds } from '../../common/get-friends';
 import read from '../../common/read-notification';
 import define from '../../define';
+import { getHideUserIds } from '../../common/get-hide-users';
 
 export const meta = {
 	desc: {
@@ -60,15 +60,13 @@ export default define(meta, (ps, user) => new Promise(async (res, rej) => {
 		return rej('cannot set sinceId and untilId');
 	}
 
-	const mute = await Mute.find({
-		muterId: user._id
-	});
+	const hideUserIds = await getHideUserIds(user);
 
 	const query = {
 		notifieeId: user._id,
 		$and: [{
 			notifierId: {
-				$nin: mute.map(m => m.muteeId)
+				$nin: hideUserIds
 			}
 		}]
 	} as any;
diff --git a/src/server/api/endpoints/notes/global-timeline.ts b/src/server/api/endpoints/notes/global-timeline.ts
index f0d052ff98..48dbaefed8 100644
--- a/src/server/api/endpoints/notes/global-timeline.ts
+++ b/src/server/api/endpoints/notes/global-timeline.ts
@@ -1,10 +1,10 @@
 import $ from 'cafy'; import ID, { transform } from '../../../../misc/cafy-id';
 import Note from '../../../../models/note';
-import Mute from '../../../../models/mute';
 import { packMany } from '../../../../models/note';
 import define from '../../define';
 import { countIf } from '../../../../prelude/array';
 import fetchMeta from '../../../../misc/fetch-meta';
+import { getHideUserIds } from '../../common/get-hide-users';
 
 export const meta = {
 	desc: {
@@ -64,10 +64,8 @@ export default define(meta, (ps, user) => new Promise(async (res, rej) => {
 		return rej('only one of sinceId, untilId, sinceDate, untilDate can be specified');
 	}
 
-	// ミュートしているユーザーを取得
-	const mutedUserIds = user ? (await Mute.find({
-		muterId: user._id
-	})).map(m => m.muteeId) : null;
+	// 隠すユーザーを取得
+	const hideUserIds = await getHideUserIds(user);
 
 	//#region Construct query
 	const sort = {
@@ -83,17 +81,17 @@ export default define(meta, (ps, user) => new Promise(async (res, rej) => {
 		replyId: null
 	} as any;
 
-	if (mutedUserIds && mutedUserIds.length > 0) {
+	if (hideUserIds && hideUserIds.length > 0) {
 		query.userId = {
-			$nin: mutedUserIds
+			$nin: hideUserIds
 		};
 
 		query['_reply.userId'] = {
-			$nin: mutedUserIds
+			$nin: hideUserIds
 		};
 
 		query['_renote.userId'] = {
-			$nin: mutedUserIds
+			$nin: hideUserIds
 		};
 	}
 
diff --git a/src/server/api/endpoints/notes/hybrid-timeline.ts b/src/server/api/endpoints/notes/hybrid-timeline.ts
index 8318479d13..4b716d0c76 100644
--- a/src/server/api/endpoints/notes/hybrid-timeline.ts
+++ b/src/server/api/endpoints/notes/hybrid-timeline.ts
@@ -1,12 +1,12 @@
 import $ from 'cafy'; import ID, { transform } from '../../../../misc/cafy-id';
 import Note from '../../../../models/note';
-import Mute from '../../../../models/mute';
 import { getFriends } from '../../common/get-friends';
 import { packMany } from '../../../../models/note';
 import define from '../../define';
 import { countIf } from '../../../../prelude/array';
 import fetchMeta from '../../../../misc/fetch-meta';
 import activeUsersChart from '../../../../chart/active-users';
+import { getHideUserIds } from '../../common/get-hide-users';
 
 export const meta = {
 	desc: {
@@ -103,15 +103,13 @@ export default define(meta, (ps, user) => new Promise(async (res, rej) => {
 		return rej('only one of sinceId, untilId, sinceDate, untilDate can be specified');
 	}
 
-	const [followings, mutedUserIds] = await Promise.all([
+	const [followings, hideUserIds] = await Promise.all([
 		// フォローを取得
 		// Fetch following
 		getFriends(user._id, true, false),
 
-		// ミュートしているユーザーを取得
-		Mute.find({
-			muterId: user._id
-		}).then(ms => ms.map(m => m.muteeId))
+		// 隠すユーザーを取得
+		getHideUserIds(user)
 	]);
 
 	//#region Construct query
@@ -175,15 +173,15 @@ export default define(meta, (ps, user) => new Promise(async (res, rej) => {
 				'_user.host': null
 			}],
 
-			// mute
+			// hide
 			userId: {
-				$nin: mutedUserIds
+				$nin: hideUserIds
 			},
 			'_reply.userId': {
-				$nin: mutedUserIds
+				$nin: hideUserIds
 			},
 			'_renote.userId': {
-				$nin: mutedUserIds
+				$nin: hideUserIds
 			},
 		}]
 	} as any;
diff --git a/src/server/api/endpoints/notes/local-timeline.ts b/src/server/api/endpoints/notes/local-timeline.ts
index d5b622d1f0..e84d981c22 100644
--- a/src/server/api/endpoints/notes/local-timeline.ts
+++ b/src/server/api/endpoints/notes/local-timeline.ts
@@ -1,11 +1,11 @@
 import $ from 'cafy'; import ID, { transform } from '../../../../misc/cafy-id';
 import Note from '../../../../models/note';
-import Mute from '../../../../models/mute';
 import { packMany } from '../../../../models/note';
 import define from '../../define';
 import { countIf } from '../../../../prelude/array';
 import fetchMeta from '../../../../misc/fetch-meta';
 import activeUsersChart from '../../../../chart/active-users';
+import { getHideUserIds } from '../../common/get-hide-users';
 
 export const meta = {
 	desc: {
@@ -80,10 +80,8 @@ export default define(meta, (ps, user) => new Promise(async (res, rej) => {
 		return rej('only one of sinceId, untilId, sinceDate, untilDate can be specified');
 	}
 
-	// ミュートしているユーザーを取得
-	const mutedUserIds = user ? (await Mute.find({
-		muterId: user._id
-	})).map(m => m.muteeId) : null;
+	// 隠すユーザーを取得
+	const hideUserIds = await getHideUserIds(user);
 
 	//#region Construct query
 	const sort = {
@@ -103,17 +101,17 @@ export default define(meta, (ps, user) => new Promise(async (res, rej) => {
 		'_user.host': null
 	} as any;
 
-	if (mutedUserIds && mutedUserIds.length > 0) {
+	if (hideUserIds && hideUserIds.length > 0) {
 		query.userId = {
-			$nin: mutedUserIds
+			$nin: hideUserIds
 		};
 
 		query['_reply.userId'] = {
-			$nin: mutedUserIds
+			$nin: hideUserIds
 		};
 
 		query['_renote.userId'] = {
-			$nin: mutedUserIds
+			$nin: hideUserIds
 		};
 	}
 
diff --git a/src/server/api/endpoints/notes/mentions.ts b/src/server/api/endpoints/notes/mentions.ts
index e37d475df7..48814279e7 100644
--- a/src/server/api/endpoints/notes/mentions.ts
+++ b/src/server/api/endpoints/notes/mentions.ts
@@ -4,7 +4,7 @@ import { getFriendIds, getFriends } from '../../common/get-friends';
 import { packMany } from '../../../../models/note';
 import define from '../../define';
 import read from '../../../../services/note/read';
-import Mute from '../../../../models/mute';
+import { getHideUserIds } from '../../common/get-hide-users';
 
 export const meta = {
 	desc: {
@@ -86,22 +86,20 @@ export default define(meta, (ps, user) => new Promise(async (res, rej) => {
 		}]
 	} as any;
 
-	// ミュートしているユーザーを取得
-	const mutedUserIds = (await Mute.find({
-		muterId: user._id
-	})).map(m => m.muteeId);
+	// 隠すユーザーを取得
+	const hideUserIds = await getHideUserIds(user);
 
-	if (mutedUserIds && mutedUserIds.length > 0) {
+	if (hideUserIds && hideUserIds.length > 0) {
 		query.userId = {
-			$nin: mutedUserIds
+			$nin: hideUserIds
 		};
 
 		query['_reply.userId'] = {
-			$nin: mutedUserIds
+			$nin: hideUserIds
 		};
 
 		query['_renote.userId'] = {
-			$nin: mutedUserIds
+			$nin: hideUserIds
 		};
 	}
 
diff --git a/src/server/api/endpoints/notes/polls/recommendation.ts b/src/server/api/endpoints/notes/polls/recommendation.ts
index ddb0892791..2fe0a78970 100644
--- a/src/server/api/endpoints/notes/polls/recommendation.ts
+++ b/src/server/api/endpoints/notes/polls/recommendation.ts
@@ -2,7 +2,7 @@ import $ from 'cafy';
 import Vote from '../../../../../models/poll-vote';
 import Note, { pack } from '../../../../../models/note';
 import define from '../../../define';
-import Mute from '../../../../../models/mute';
+import { getHideUserIds } from '../../../common/get-hide-users';
 
 export const meta = {
 	desc: {
@@ -38,10 +38,8 @@ export default define(meta, (ps, user) => new Promise(async (res, rej) => {
 
 	const nin = votes && votes.length != 0 ? votes.map(v => v.noteId) : [];
 
-	// ミュートしているユーザーを取得
-	const mutedUserIds = await Mute.find({
-		muterId: user._id
-	}).then(ms => ms.map(m => m.muteeId));
+	// 隠すユーザーを取得
+	const hideUserIds = await getHideUserIds(user);
 
 	const notes = await Note
 		.find({
@@ -51,7 +49,7 @@ export default define(meta, (ps, user) => new Promise(async (res, rej) => {
 			},
 			userId: {
 				$ne: user._id,
-				$nin: mutedUserIds
+				$nin: hideUserIds
 			},
 			poll: {
 				$exists: true,
diff --git a/src/server/api/endpoints/notes/replies.ts b/src/server/api/endpoints/notes/replies.ts
index 199139c8e5..9308c440b1 100644
--- a/src/server/api/endpoints/notes/replies.ts
+++ b/src/server/api/endpoints/notes/replies.ts
@@ -1,8 +1,8 @@
 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';
+import { getHideUserIds } from '../../common/get-hide-users';
 
 export const meta = {
 	desc: {
@@ -35,15 +35,13 @@ export const meta = {
 };
 
 export default define(meta, (ps, user) => new Promise(async (res, rej) => {
-	const [followings, mutedUserIds] = await Promise.all([
+	const [followings, hideUserIds] = await Promise.all([
 		// フォローを取得
 		// Fetch following
 		user ? getFriends(user._id) : [],
 
-		// ミュートしているユーザーを取得
-		user ? (await Mute.find({
-			muterId: user._id
-		})).map(m => m.muteeId) : null
+		// 隠すユーザーを取得
+		getHideUserIds(user)
 	]);
 
 	const visibleQuery = user == null ? [{
@@ -75,9 +73,9 @@ export default define(meta, (ps, user) => new Promise(async (res, rej) => {
 		$or: visibleQuery
 	} as any;
 
-	if (mutedUserIds && mutedUserIds.length > 0) {
+	if (hideUserIds && hideUserIds.length > 0) {
 		q['userId'] = {
-			$nin: mutedUserIds
+			$nin: hideUserIds
 		};
 	}
 
diff --git a/src/server/api/endpoints/notes/search_by_tag.ts b/src/server/api/endpoints/notes/search_by_tag.ts
index db2f716497..995030e03a 100644
--- a/src/server/api/endpoints/notes/search_by_tag.ts
+++ b/src/server/api/endpoints/notes/search_by_tag.ts
@@ -1,9 +1,9 @@
 import $ from 'cafy'; import ID, { transform } from '../../../../misc/cafy-id';
 import Note from '../../../../models/note';
-import Mute from '../../../../models/mute';
 import { getFriendIds } from '../../common/get-friends';
 import { packMany } from '../../../../models/note';
 import define from '../../define';
+import { getHideUserIds } from '../../common/get-hide-users';
 
 export const meta = {
 	desc: {
@@ -143,47 +143,43 @@ export default define(meta, (ps, me) => new Promise(async (res, rej) => {
 	}
 
 	if (me != null) {
-		const mutes = await Mute.find({
-			muterId: me._id,
-			deletedAt: { $exists: false }
-		});
-		const mutedUserIds = mutes.map(m => m.muteeId);
+		const hideUserIds = await getHideUserIds(me);
 
 		switch (ps.mute) {
 			case 'mute_all':
 				push({
 					userId: {
-						$nin: mutedUserIds
+						$nin: hideUserIds
 					},
 					'_reply.userId': {
-						$nin: mutedUserIds
+						$nin: hideUserIds
 					},
 					'_renote.userId': {
-						$nin: mutedUserIds
+						$nin: hideUserIds
 					}
 				});
 				break;
 			case 'mute_related':
 				push({
 					'_reply.userId': {
-						$nin: mutedUserIds
+						$nin: hideUserIds
 					},
 					'_renote.userId': {
-						$nin: mutedUserIds
+						$nin: hideUserIds
 					}
 				});
 				break;
 			case 'mute_direct':
 				push({
 					userId: {
-						$nin: mutedUserIds
+						$nin: hideUserIds
 					}
 				});
 				break;
 			case 'direct_only':
 				push({
 					userId: {
-						$in: mutedUserIds
+						$in: hideUserIds
 					}
 				});
 				break;
@@ -191,11 +187,11 @@ export default define(meta, (ps, me) => new Promise(async (res, rej) => {
 				push({
 					$or: [{
 						'_reply.userId': {
-							$in: mutedUserIds
+							$in: hideUserIds
 						}
 					}, {
 						'_renote.userId': {
-							$in: mutedUserIds
+							$in: hideUserIds
 						}
 					}]
 				});
@@ -204,15 +200,15 @@ export default define(meta, (ps, me) => new Promise(async (res, rej) => {
 				push({
 					$or: [{
 						userId: {
-							$in: mutedUserIds
+							$in: hideUserIds
 						}
 					}, {
 						'_reply.userId': {
-							$in: mutedUserIds
+							$in: hideUserIds
 						}
 					}, {
 						'_renote.userId': {
-							$in: mutedUserIds
+							$in: hideUserIds
 						}
 					}]
 				});
diff --git a/src/server/api/endpoints/notes/timeline.ts b/src/server/api/endpoints/notes/timeline.ts
index ead57e2d56..6c3142b091 100644
--- a/src/server/api/endpoints/notes/timeline.ts
+++ b/src/server/api/endpoints/notes/timeline.ts
@@ -1,11 +1,11 @@
 import $ from 'cafy'; import ID, { transform } from '../../../../misc/cafy-id';
 import Note from '../../../../models/note';
-import Mute from '../../../../models/mute';
 import { getFriends } from '../../common/get-friends';
 import { packMany } from '../../../../models/note';
 import define from '../../define';
 import { countIf } from '../../../../prelude/array';
 import activeUsersChart from '../../../../chart/active-users';
+import { getHideUserIds } from '../../common/get-hide-users';
 
 export const meta = {
 	desc: {
@@ -101,15 +101,13 @@ export default define(meta, (ps, user) => new Promise(async (res, rej) => {
 		return;
 	}
 
-	const [followings, mutedUserIds] = await Promise.all([
+	const [followings, hideUserIds] = await Promise.all([
 		// フォローを取得
 		// Fetch following
 		getFriends(user._id),
 
-		// ミュートしているユーザーを取得
-		Mute.find({
-			muterId: user._id
-		}).then(ms => ms.map(m => m.muteeId))
+		// 隠すユーザーを取得
+		getHideUserIds(user)
 	]);
 
 	//#region Construct query
@@ -164,13 +162,13 @@ export default define(meta, (ps, user) => new Promise(async (res, rej) => {
 
 			// mute
 			userId: {
-				$nin: mutedUserIds
+				$nin: hideUserIds
 			},
 			'_reply.userId': {
-				$nin: mutedUserIds
+				$nin: hideUserIds
 			},
 			'_renote.userId': {
-				$nin: mutedUserIds
+				$nin: hideUserIds
 			},
 		}]
 	} as any;
diff --git a/src/server/api/endpoints/notes/user-list-timeline.ts b/src/server/api/endpoints/notes/user-list-timeline.ts
index 861bbd9b29..0cceeb95da 100644
--- a/src/server/api/endpoints/notes/user-list-timeline.ts
+++ b/src/server/api/endpoints/notes/user-list-timeline.ts
@@ -1,10 +1,10 @@
 import $ from 'cafy'; import ID, { transform } from '../../../../misc/cafy-id';
 import Note from '../../../../models/note';
-import Mute from '../../../../models/mute';
 import { packMany } from '../../../../models/note';
 import UserList from '../../../../models/user-list';
 import define from '../../define';
 import { getFriends } from '../../common/get-friends';
+import { getHideUserIds } from '../../common/get-hide-users';
 
 export const meta = {
 	desc: {
@@ -102,7 +102,7 @@ export const meta = {
 };
 
 export default define(meta, (ps, user) => new Promise(async (res, rej) => {
-	const [list, followings, mutedUserIds] = await Promise.all([
+	const [list, followings, hideUserIds] = await Promise.all([
 		// リストを取得
 		// Fetch the list
 		UserList.findOne({
@@ -114,10 +114,8 @@ export default define(meta, (ps, user) => new Promise(async (res, rej) => {
 		// Fetch following
 		getFriends(user._id, true, false),
 
-		// ミュートしているユーザーを取得
-		Mute.find({
-			muterId: user._id
-		}).then(ms => ms.map(m => m.muteeId))
+		// 隠すユーザーを取得
+		getHideUserIds(user)
 	]);
 
 	if (list.userIds.length == 0) {
@@ -178,13 +176,13 @@ export default define(meta, (ps, user) => new Promise(async (res, rej) => {
 
 			// mute
 			userId: {
-				$nin: mutedUserIds
+				$nin: hideUserIds
 			},
 			'_reply.userId': {
-				$nin: mutedUserIds
+				$nin: hideUserIds
 			},
 			'_renote.userId': {
-				$nin: mutedUserIds
+				$nin: hideUserIds
 			},
 		}]
 	} as any;
diff --git a/src/server/api/endpoints/users/recommendation.ts b/src/server/api/endpoints/users/recommendation.ts
index bacace6a6a..8320c2bd01 100644
--- a/src/server/api/endpoints/users/recommendation.ts
+++ b/src/server/api/endpoints/users/recommendation.ts
@@ -2,12 +2,12 @@ const ms = require('ms');
 import $ from 'cafy';
 import User, { pack, ILocalUser } from '../../../../models/user';
 import { getFriendIds } from '../../common/get-friends';
-import Mute from '../../../../models/mute';
 import * as request from 'request-promise-native';
 import config from '../../../../config';
 import define from '../../define';
 import fetchMeta from '../../../../misc/fetch-meta';
 import resolveUser from '../../../../remote/resolve-user';
+import { getHideUserIds } from '../../common/get-hide-users';
 
 export const meta = {
 	desc: {
@@ -62,15 +62,13 @@ export default define(meta, (ps, me) => new Promise(async (res, rej) => {
 		// ID list of the user itself and other users who the user follows
 		const followingIds = await getFriendIds(me._id);
 
-		// ミュートしているユーザーを取得
-		const mutedUserIds = (await Mute.find({
-			muterId: me._id
-		})).map(m => m.muteeId);
+	// 隠すユーザーを取得
+	const hideUserIds = await getHideUserIds(me);
 
 		const users = await User
 			.find({
 				_id: {
-					$nin: followingIds.concat(mutedUserIds)
+					$nin: followingIds.concat(hideUserIds)
 				},
 				isLocked: { $ne: true },
 				updatedAt: {