diff options
| author | syuilo <syuilotan@yahoo.co.jp> | 2018-04-19 12:43:25 +0900 |
|---|---|---|
| committer | syuilo <syuilotan@yahoo.co.jp> | 2018-04-19 12:43:25 +0900 |
| commit | 0d5bc3be6611a6877a71233ac57c0987027c0398 (patch) | |
| tree | 28c6b736dc870b6de5893ee52b712c20973b7298 /src/server/api | |
| parent | Merge pull request #1514 from syuilo/greenkeeper/style-loader-0.21.0 (diff) | |
| download | sharkey-0d5bc3be6611a6877a71233ac57c0987027c0398.tar.gz sharkey-0d5bc3be6611a6877a71233ac57c0987027c0398.tar.bz2 sharkey-0d5bc3be6611a6877a71233ac57c0987027c0398.zip | |
ストーキング実装
Closes #1511
Diffstat (limited to 'src/server/api')
| -rw-r--r-- | src/server/api/common/get-friends.ts | 29 | ||||
| -rw-r--r-- | src/server/api/endpoints.ts | 18 | ||||
| -rw-r--r-- | src/server/api/endpoints/following/stalk.ts | 36 | ||||
| -rw-r--r-- | src/server/api/endpoints/following/unstalk.ts | 35 | ||||
| -rw-r--r-- | src/server/api/endpoints/i/notifications.ts | 4 | ||||
| -rw-r--r-- | src/server/api/endpoints/mute/list.ts | 4 | ||||
| -rw-r--r-- | src/server/api/endpoints/notes/mentions.ts | 4 | ||||
| -rw-r--r-- | src/server/api/endpoints/notes/search.ts | 4 | ||||
| -rw-r--r-- | src/server/api/endpoints/notes/timeline.ts | 60 | ||||
| -rw-r--r-- | src/server/api/endpoints/users/followers.ts | 4 | ||||
| -rw-r--r-- | src/server/api/endpoints/users/following.ts | 4 | ||||
| -rw-r--r-- | src/server/api/endpoints/users/recommendation.ts | 4 |
12 files changed, 171 insertions, 35 deletions
diff --git a/src/server/api/common/get-friends.ts b/src/server/api/common/get-friends.ts index c1cc3957d8..50ba71ea96 100644 --- a/src/server/api/common/get-friends.ts +++ b/src/server/api/common/get-friends.ts @@ -1,10 +1,10 @@ import * as mongodb from 'mongodb'; import Following from '../../../models/following'; -export default async (me: mongodb.ObjectID, includeMe: boolean = true) => { +export const getFriendIds = async (me: mongodb.ObjectID, includeMe = true) => { // Fetch relation to other users who the I follows // SELECT followee - const myfollowing = await Following + const followings = await Following .find({ followerId: me }, { @@ -14,7 +14,7 @@ export default async (me: mongodb.ObjectID, includeMe: boolean = true) => { }); // ID list of other users who the I follows - const myfollowingIds = myfollowing.map(follow => follow.followeeId); + const myfollowingIds = followings.map(following => following.followeeId); if (includeMe) { myfollowingIds.push(me); @@ -22,3 +22,26 @@ export default async (me: mongodb.ObjectID, includeMe: boolean = true) => { return myfollowingIds; }; + +export const getFriends = async (me: mongodb.ObjectID, includeMe = true) => { + // Fetch relation to other users who the I follows + const followings = await Following + .find({ + followerId: me + }); + + // ID list of other users who the I follows + const myfollowings = followings.map(following => ({ + id: following.followeeId, + stalk: following.stalk + })); + + if (includeMe) { + myfollowings.push({ + id: me, + stalk: true + }); + } + + return myfollowings; +}; diff --git a/src/server/api/endpoints.ts b/src/server/api/endpoints.ts index e0223c23e0..7cf49debe9 100644 --- a/src/server/api/endpoints.ts +++ b/src/server/api/endpoints.ts @@ -426,6 +426,24 @@ const endpoints: Endpoint[] = [ }, kind: 'following-write' }, + { + name: 'following/stalk', + withCredential: true, + limit: { + duration: ms('1hour'), + max: 100 + }, + kind: 'following-write' + }, + { + name: 'following/unstalk', + withCredential: true, + limit: { + duration: ms('1hour'), + max: 100 + }, + kind: 'following-write' + }, { name: 'notes' diff --git a/src/server/api/endpoints/following/stalk.ts b/src/server/api/endpoints/following/stalk.ts new file mode 100644 index 0000000000..fc8be4924d --- /dev/null +++ b/src/server/api/endpoints/following/stalk.ts @@ -0,0 +1,36 @@ +import $ from 'cafy'; +import Following from '../../../../models/following'; +import { isLocalUser } from '../../../../models/user'; + +/** + * Stalk a user + */ +module.exports = (params, user) => new Promise(async (res, rej) => { + const follower = user; + + // Get 'userId' parameter + const [userId, userIdErr] = $(params.userId).id().$; + if (userIdErr) return rej('invalid userId param'); + + // Fetch following + const following = await Following.findOne({ + followerId: follower._id, + followeeId: userId + }); + + if (following === null) { + return rej('following not found'); + } + + // Stalk + await Following.update({ _id: following._id }, { + $set: { + stalk: true + } + }); + + // Send response + res(); + + // TODO: イベント +}); diff --git a/src/server/api/endpoints/following/unstalk.ts b/src/server/api/endpoints/following/unstalk.ts new file mode 100644 index 0000000000..d7593bcd00 --- /dev/null +++ b/src/server/api/endpoints/following/unstalk.ts @@ -0,0 +1,35 @@ +import $ from 'cafy'; +import Following from '../../../../models/following'; + +/** + * Unstalk a user + */ +module.exports = (params, user) => new Promise(async (res, rej) => { + const follower = user; + + // Get 'userId' parameter + const [userId, userIdErr] = $(params.userId).id().$; + if (userIdErr) return rej('invalid userId param'); + + // Fetch following + const following = await Following.findOne({ + followerId: follower._id, + followeeId: userId + }); + + if (following === null) { + return rej('following not found'); + } + + // Stalk + await Following.update({ _id: following._id }, { + $set: { + stalk: false + } + }); + + // Send response + res(); + + // TODO: イベント +}); diff --git a/src/server/api/endpoints/i/notifications.ts b/src/server/api/endpoints/i/notifications.ts index 3b4899682d..69a8910898 100644 --- a/src/server/api/endpoints/i/notifications.ts +++ b/src/server/api/endpoints/i/notifications.ts @@ -5,7 +5,7 @@ import $ from 'cafy'; import Notification from '../../../../models/notification'; import Mute from '../../../../models/mute'; import { pack } from '../../../../models/notification'; -import getFriends from '../../common/get-friends'; +import { getFriendIds } from '../../common/get-friends'; import read from '../../common/read-notification'; /** @@ -62,7 +62,7 @@ module.exports = (params, user) => new Promise(async (res, rej) => { if (following) { // ID list of the user itself and other users who the user follows - const followingIds = await getFriends(user._id); + const followingIds = await getFriendIds(user._id); query.$and.push({ notifierId: { diff --git a/src/server/api/endpoints/mute/list.ts b/src/server/api/endpoints/mute/list.ts index bd80401445..0b8262d6c5 100644 --- a/src/server/api/endpoints/mute/list.ts +++ b/src/server/api/endpoints/mute/list.ts @@ -4,7 +4,7 @@ import $ from 'cafy'; import Mute from '../../../../models/mute'; import { pack } from '../../../../models/user'; -import getFriends from '../../common/get-friends'; +import { getFriendIds } from '../../common/get-friends'; /** * Get muted users of a user @@ -34,7 +34,7 @@ module.exports = (params, me) => new Promise(async (res, rej) => { if (iknow) { // Get my friends - const myFriends = await getFriends(me._id); + const myFriends = await getFriendIds(me._id); query.muteeId = { $in: myFriends diff --git a/src/server/api/endpoints/notes/mentions.ts b/src/server/api/endpoints/notes/mentions.ts index c507acbaec..2d95606b3f 100644 --- a/src/server/api/endpoints/notes/mentions.ts +++ b/src/server/api/endpoints/notes/mentions.ts @@ -3,7 +3,7 @@ */ import $ from 'cafy'; import Note from '../../../../models/note'; -import getFriends from '../../common/get-friends'; +import { getFriendIds } from '../../common/get-friends'; import { pack } from '../../../../models/note'; /** @@ -46,7 +46,7 @@ module.exports = (params, user) => new Promise(async (res, rej) => { }; if (following) { - const followingIds = await getFriends(user._id); + const followingIds = await getFriendIds(user._id); query.userId = { $in: followingIds diff --git a/src/server/api/endpoints/notes/search.ts b/src/server/api/endpoints/notes/search.ts index bfa17b000e..3ff3fbbafa 100644 --- a/src/server/api/endpoints/notes/search.ts +++ b/src/server/api/endpoints/notes/search.ts @@ -6,7 +6,7 @@ const escapeRegexp = require('escape-regexp'); import Note from '../../../../models/note'; import User from '../../../../models/user'; import Mute from '../../../../models/mute'; -import getFriends from '../../common/get-friends'; +import { getFriendIds } from '../../common/get-friends'; import { pack } from '../../../../models/note'; /** @@ -156,7 +156,7 @@ async function search( } if (following != null && me != null) { - const ids = await getFriends(me._id, false); + const ids = await getFriendIds(me._id, false); push({ userId: following ? { $in: ids diff --git a/src/server/api/endpoints/notes/timeline.ts b/src/server/api/endpoints/notes/timeline.ts index b5feaac817..8cd23fd369 100644 --- a/src/server/api/endpoints/notes/timeline.ts +++ b/src/server/api/endpoints/notes/timeline.ts @@ -2,11 +2,10 @@ * Module dependencies */ import $ from 'cafy'; -import rap from '@prezzemolo/rap'; import Note from '../../../../models/note'; import Mute from '../../../../models/mute'; import ChannelWatching from '../../../../models/channel-watching'; -import getFriends from '../../common/get-friends'; +import { getFriends } from '../../common/get-friends'; import { pack } from '../../../../models/note'; /** @@ -38,41 +37,66 @@ module.exports = async (params, user, app) => { throw 'only one of sinceId, untilId, sinceDate, untilDate can be specified'; } - const { followingIds, watchingChannelIds, mutedUserIds } = await rap({ - // ID list of the user itself and other users who the user follows - followingIds: getFriends(user._id), + const [followings, watchingChannelIds, mutedUserIds] = await Promise.all([ + // フォローを取得 + // Fetch following + getFriends(user._id), // Watchしているチャンネルを取得 - watchingChannelIds: ChannelWatching.find({ + ChannelWatching.find({ userId: user._id, // 削除されたドキュメントは除く deletedAt: { $exists: false } }).then(watches => watches.map(w => w.channelId)), // ミュートしているユーザーを取得 - mutedUserIds: Mute.find({ + Mute.find({ muterId: user._id }).then(ms => ms.map(m => m.muteeId)) - }); + ]); //#region Construct query const sort = { _id: -1 }; + const followQuery = followings.map(f => f.stalk ? { + userId: f.id + } : { + userId: f.id, + + // ストーキングしてないならリプライは含めない(ただし投稿者自身の投稿へのリプライ、自分の投稿へのリプライ、自分のリプライは含める) + $or: [{ + // リプライでない + replyId: null + }, { // または + // リプライだが返信先が投稿者自身の投稿 + $expr: { + '$_reply.userId': '$userId' + } + }, { // または + // リプライだが返信先が自分(フォロワー)の投稿 + '_reply.userId': user._id + }, { // または + // 自分(フォロワー)が送信したリプライ + userId: user._id + }] + }); + const query = { $or: [{ - // フォローしている人のタイムラインへの投稿 - userId: { - $in: followingIds - }, - // 「タイムラインへの」投稿に限定するためにチャンネルが指定されていないもののみに限る - $or: [{ - channelId: { - $exists: false - } + $and: [{ + // フォローしている人のタイムラインへの投稿 + $or: followQuery }, { - channelId: null + // 「タイムラインへの」投稿に限定するためにチャンネルが指定されていないもののみに限る + $or: [{ + channelId: { + $exists: false + } + }, { + channelId: null + }] }] }, { // Watchしているチャンネルへの投稿 diff --git a/src/server/api/endpoints/users/followers.ts b/src/server/api/endpoints/users/followers.ts index 0222313e81..5f03326be8 100644 --- a/src/server/api/endpoints/users/followers.ts +++ b/src/server/api/endpoints/users/followers.ts @@ -5,7 +5,7 @@ import $ from 'cafy'; import User from '../../../../models/user'; import Following from '../../../../models/following'; import { pack } from '../../../../models/user'; -import getFriends from '../../common/get-friends'; +import { getFriendIds } from '../../common/get-friends'; /** * Get followers of a user @@ -52,7 +52,7 @@ module.exports = (params, me) => new Promise(async (res, rej) => { // ログインしていてかつ iknow フラグがあるとき if (me && iknow) { // Get my friends - const myFriends = await getFriends(me._id); + const myFriends = await getFriendIds(me._id); query.followerId = { $in: myFriends diff --git a/src/server/api/endpoints/users/following.ts b/src/server/api/endpoints/users/following.ts index 2372f57fbe..9fb135b24d 100644 --- a/src/server/api/endpoints/users/following.ts +++ b/src/server/api/endpoints/users/following.ts @@ -5,7 +5,7 @@ import $ from 'cafy'; import User from '../../../../models/user'; import Following from '../../../../models/following'; import { pack } from '../../../../models/user'; -import getFriends from '../../common/get-friends'; +import { getFriendIds } from '../../common/get-friends'; /** * Get following users of a user @@ -52,7 +52,7 @@ module.exports = (params, me) => new Promise(async (res, rej) => { // ログインしていてかつ iknow フラグがあるとき if (me && iknow) { // Get my friends - const myFriends = await getFriends(me._id); + const myFriends = await getFriendIds(me._id); query.followeeId = { $in: myFriends diff --git a/src/server/api/endpoints/users/recommendation.ts b/src/server/api/endpoints/users/recommendation.ts index 2a6d36b75b..f72bb04bf1 100644 --- a/src/server/api/endpoints/users/recommendation.ts +++ b/src/server/api/endpoints/users/recommendation.ts @@ -4,7 +4,7 @@ const ms = require('ms'); import $ from 'cafy'; import User, { pack } from '../../../../models/user'; -import getFriends from '../../common/get-friends'; +import { getFriendIds } from '../../common/get-friends'; import Mute from '../../../../models/mute'; /** @@ -24,7 +24,7 @@ module.exports = (params, me) => new Promise(async (res, rej) => { if (offsetErr) return rej('invalid offset param'); // ID list of the user itself and other users who the user follows - const followingIds = await getFriends(me._id); + const followingIds = await getFriendIds(me._id); // ミュートしているユーザーを取得 const mutedUserIds = (await Mute.find({ |