diff options
Diffstat (limited to 'src/server/api/endpoints/users')
| -rw-r--r-- | src/server/api/endpoints/users/followers.ts | 18 | ||||
| -rw-r--r-- | src/server/api/endpoints/users/following.ts | 14 | ||||
| -rw-r--r-- | src/server/api/endpoints/users/get_frequently_replied_users.ts | 6 | ||||
| -rw-r--r-- | src/server/api/endpoints/users/lists/create.ts | 25 | ||||
| -rw-r--r-- | src/server/api/endpoints/users/lists/list.ts | 13 | ||||
| -rw-r--r-- | src/server/api/endpoints/users/lists/push.ts | 61 | ||||
| -rw-r--r-- | src/server/api/endpoints/users/lists/show.ts | 23 | ||||
| -rw-r--r-- | src/server/api/endpoints/users/notes.ts | 22 | ||||
| -rw-r--r-- | src/server/api/endpoints/users/recommendation.ts | 18 | ||||
| -rw-r--r-- | src/server/api/endpoints/users/search.ts | 6 | ||||
| -rw-r--r-- | src/server/api/endpoints/users/search_by_username.ts | 10 | ||||
| -rw-r--r-- | src/server/api/endpoints/users/show.ts | 66 |
12 files changed, 207 insertions, 75 deletions
diff --git a/src/server/api/endpoints/users/followers.ts b/src/server/api/endpoints/users/followers.ts index 0222313e81..810cd7341b 100644 --- a/src/server/api/endpoints/users/followers.ts +++ b/src/server/api/endpoints/users/followers.ts @@ -1,34 +1,30 @@ /** * Module dependencies */ -import $ from 'cafy'; +import $ from 'cafy'; import ID from '../../../../cafy-id'; 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 - * - * @param {any} params - * @param {any} me - * @return {Promise<any>} */ module.exports = (params, me) => new Promise(async (res, rej) => { // Get 'userId' parameter - const [userId, userIdErr] = $(params.userId).id().$; + const [userId, userIdErr] = $.type(ID).get(params.userId); if (userIdErr) return rej('invalid userId param'); // Get 'iknow' parameter - const [iknow = false, iknowErr] = $(params.iknow).optional.boolean().$; + const [iknow = false, iknowErr] = $.bool.optional().get(params.iknow); if (iknowErr) return rej('invalid iknow param'); // Get 'limit' parameter - const [limit = 10, limitErr] = $(params.limit).optional.number().range(1, 100).$; + const [limit = 10, limitErr] = $.num.optional().range(1, 100).get(params.limit); if (limitErr) return rej('invalid limit param'); // Get 'cursor' parameter - const [cursor = null, cursorErr] = $(params.cursor).optional.id().$; + const [cursor = null, cursorErr] = $.type(ID).optional().get(params.cursor); if (cursorErr) return rej('invalid cursor param'); // Lookup user @@ -52,7 +48,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..3373b9d632 100644 --- a/src/server/api/endpoints/users/following.ts +++ b/src/server/api/endpoints/users/following.ts @@ -1,11 +1,11 @@ /** * Module dependencies */ -import $ from 'cafy'; +import $ from 'cafy'; import ID from '../../../../cafy-id'; 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 @@ -16,19 +16,19 @@ import getFriends from '../../common/get-friends'; */ module.exports = (params, me) => new Promise(async (res, rej) => { // Get 'userId' parameter - const [userId, userIdErr] = $(params.userId).id().$; + const [userId, userIdErr] = $.type(ID).get(params.userId); if (userIdErr) return rej('invalid userId param'); // Get 'iknow' parameter - const [iknow = false, iknowErr] = $(params.iknow).optional.boolean().$; + const [iknow = false, iknowErr] = $.bool.optional().get(params.iknow); if (iknowErr) return rej('invalid iknow param'); // Get 'limit' parameter - const [limit = 10, limitErr] = $(params.limit).optional.number().range(1, 100).$; + const [limit = 10, limitErr] = $.num.optional().range(1, 100).get(params.limit); if (limitErr) return rej('invalid limit param'); // Get 'cursor' parameter - const [cursor = null, cursorErr] = $(params.cursor).optional.id().$; + const [cursor = null, cursorErr] = $.type(ID).optional().get(params.cursor); if (cursorErr) return rej('invalid cursor param'); // Lookup 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/get_frequently_replied_users.ts b/src/server/api/endpoints/users/get_frequently_replied_users.ts index 7a98f44e98..64d737a06b 100644 --- a/src/server/api/endpoints/users/get_frequently_replied_users.ts +++ b/src/server/api/endpoints/users/get_frequently_replied_users.ts @@ -1,17 +1,17 @@ /** * Module dependencies */ -import $ from 'cafy'; +import $ from 'cafy'; import ID from '../../../../cafy-id'; import Note from '../../../../models/note'; import User, { pack } from '../../../../models/user'; module.exports = (params, me) => new Promise(async (res, rej) => { // Get 'userId' parameter - const [userId, userIdErr] = $(params.userId).id().$; + const [userId, userIdErr] = $.type(ID).get(params.userId); if (userIdErr) return rej('invalid userId param'); // Get 'limit' parameter - const [limit = 10, limitErr] = $(params.limit).optional.number().range(1, 100).$; + const [limit = 10, limitErr] = $.num.optional().range(1, 100).get(params.limit); if (limitErr) return rej('invalid limit param'); // Lookup user diff --git a/src/server/api/endpoints/users/lists/create.ts b/src/server/api/endpoints/users/lists/create.ts new file mode 100644 index 0000000000..100a78b872 --- /dev/null +++ b/src/server/api/endpoints/users/lists/create.ts @@ -0,0 +1,25 @@ +/** + * Module dependencies + */ +import $ from 'cafy'; +import UserList, { pack } from '../../../../../models/user-list'; + +/** + * Create a user list + */ +module.exports = async (params, user) => new Promise(async (res, rej) => { + // Get 'title' parameter + const [title, titleErr] = $.str.range(1, 100).get(params.title); + if (titleErr) return rej('invalid title param'); + + // insert + const userList = await UserList.insert({ + createdAt: new Date(), + userId: user._id, + title: title, + userIds: [] + }); + + // Response + res(await pack(userList)); +}); diff --git a/src/server/api/endpoints/users/lists/list.ts b/src/server/api/endpoints/users/lists/list.ts new file mode 100644 index 0000000000..d19339a1f5 --- /dev/null +++ b/src/server/api/endpoints/users/lists/list.ts @@ -0,0 +1,13 @@ +import UserList, { pack } from '../../../../../models/user-list'; + +/** + * Add a user to a user list + */ +module.exports = async (params, me) => new Promise(async (res, rej) => { + // Fetch lists + const userLists = await UserList.find({ + userId: me._id, + }); + + res(await Promise.all(userLists.map(x => pack(x)))); +}); diff --git a/src/server/api/endpoints/users/lists/push.ts b/src/server/api/endpoints/users/lists/push.ts new file mode 100644 index 0000000000..da5a9a134c --- /dev/null +++ b/src/server/api/endpoints/users/lists/push.ts @@ -0,0 +1,61 @@ +import $ from 'cafy'; import ID from '../../../../../cafy-id'; +import UserList from '../../../../../models/user-list'; +import User, { pack as packUser, isRemoteUser, getGhost } from '../../../../../models/user'; +import { publishUserListStream } from '../../../../../publishers/stream'; +import ap from '../../../../../remote/activitypub/renderer'; +import renderFollow from '../../../../../remote/activitypub/renderer/follow'; +import { deliver } from '../../../../../queue'; + +/** + * Add a user to a user list + */ +module.exports = async (params, me) => new Promise(async (res, rej) => { + // Get 'listId' parameter + const [listId, listIdErr] = $.type(ID).get(params.listId); + if (listIdErr) return rej('invalid listId param'); + + // Fetch the list + const userList = await UserList.findOne({ + _id: listId, + userId: me._id, + }); + + if (userList == null) { + return rej('list not found'); + } + + // Get 'userId' parameter + const [userId, userIdErr] = $.type(ID).get(params.userId); + if (userIdErr) return rej('invalid userId param'); + + // Fetch the user + const user = await User.findOne({ + _id: userId + }); + + if (user == null) { + return rej('user not found'); + } + + if (userList.userIds.map(id => id.toHexString()).includes(user._id.toHexString())) { + return rej('the user already added'); + } + + // Push the user + await UserList.update({ _id: userList._id }, { + $push: { + userIds: user._id + } + }); + + res(); + + publishUserListStream(userList._id, 'userAdded', await packUser(user)); + + // このインスタンス内にこのリモートユーザーをフォローしているユーザーがいなくても投稿を受け取るためにダミーのユーザーがフォローしたということにする + if (isRemoteUser(user)) { + const ghost = await getGhost(); + const content = ap(renderFollow(ghost, user)); + deliver(ghost, content, user.inbox); + } +}); diff --git a/src/server/api/endpoints/users/lists/show.ts b/src/server/api/endpoints/users/lists/show.ts new file mode 100644 index 0000000000..16cb3382fd --- /dev/null +++ b/src/server/api/endpoints/users/lists/show.ts @@ -0,0 +1,23 @@ +import $ from 'cafy'; import ID from '../../../../../cafy-id'; +import UserList, { pack } from '../../../../../models/user-list'; + +/** + * Show a user list + */ +module.exports = async (params, me) => new Promise(async (res, rej) => { + // Get 'listId' parameter + const [listId, listIdErr] = $.type(ID).get(params.listId); + if (listIdErr) return rej('invalid listId param'); + + // Fetch the list + const userList = await UserList.findOne({ + _id: listId, + userId: me._id, + }); + + if (userList == null) { + return rej('list not found'); + } + + res(await pack(userList)); +}); diff --git a/src/server/api/endpoints/users/notes.ts b/src/server/api/endpoints/users/notes.ts index bd4247c79c..061c363d0f 100644 --- a/src/server/api/endpoints/users/notes.ts +++ b/src/server/api/endpoints/users/notes.ts @@ -1,7 +1,7 @@ /** * Module dependencies */ -import $ from 'cafy'; +import $ from 'cafy'; import ID from '../../../../cafy-id'; import getHostLower from '../../common/get-host-lower'; import Note, { pack } from '../../../../models/note'; import User from '../../../../models/user'; @@ -11,11 +11,11 @@ import User from '../../../../models/user'; */ module.exports = (params, me) => new Promise(async (res, rej) => { // Get 'userId' parameter - const [userId, userIdErr] = $(params.userId).optional.id().$; + const [userId, userIdErr] = $.type(ID).optional().get(params.userId); if (userIdErr) return rej('invalid userId param'); // Get 'username' parameter - const [username, usernameErr] = $(params.username).optional.string().$; + const [username, usernameErr] = $.str.optional().get(params.username); if (usernameErr) return rej('invalid username param'); if (userId === undefined && username === undefined) { @@ -23,7 +23,7 @@ module.exports = (params, me) => new Promise(async (res, rej) => { } // Get 'host' parameter - const [host, hostErr] = $(params.host).optional.string().$; + const [host, hostErr] = $.str.optional().get(params.host); if (hostErr) return rej('invalid host param'); if (userId === undefined && host === undefined) { @@ -31,31 +31,31 @@ module.exports = (params, me) => new Promise(async (res, rej) => { } // Get 'includeReplies' parameter - const [includeReplies = true, includeRepliesErr] = $(params.includeReplies).optional.boolean().$; + const [includeReplies = true, includeRepliesErr] = $.bool.optional().get(params.includeReplies); if (includeRepliesErr) return rej('invalid includeReplies param'); // Get 'withMedia' parameter - const [withMedia = false, withMediaErr] = $(params.withMedia).optional.boolean().$; + const [withMedia = false, withMediaErr] = $.bool.optional().get(params.withMedia); if (withMediaErr) return rej('invalid withMedia param'); // Get 'limit' parameter - const [limit = 10, limitErr] = $(params.limit).optional.number().range(1, 100).$; + const [limit = 10, limitErr] = $.num.optional().range(1, 100).get(params.limit); if (limitErr) return rej('invalid limit param'); // Get 'sinceId' parameter - const [sinceId, sinceIdErr] = $(params.sinceId).optional.id().$; + const [sinceId, sinceIdErr] = $.type(ID).optional().get(params.sinceId); if (sinceIdErr) return rej('invalid sinceId param'); // Get 'untilId' parameter - const [untilId, untilIdErr] = $(params.untilId).optional.id().$; + const [untilId, untilIdErr] = $.type(ID).optional().get(params.untilId); if (untilIdErr) return rej('invalid untilId param'); // Get 'sinceDate' parameter - const [sinceDate, sinceDateErr] = $(params.sinceDate).optional.number().$; + const [sinceDate, sinceDateErr] = $.num.optional().get(params.sinceDate); if (sinceDateErr) throw 'invalid sinceDate param'; // Get 'untilDate' parameter - const [untilDate, untilDateErr] = $(params.untilDate).optional.number().$; + const [untilDate, untilDateErr] = $.num.optional().get(params.untilDate); if (untilDateErr) throw 'invalid untilDate param'; // Check if only one of sinceId, untilId, sinceDate, untilDate specified diff --git a/src/server/api/endpoints/users/recommendation.ts b/src/server/api/endpoints/users/recommendation.ts index e367e65a6c..620ae17ca2 100644 --- a/src/server/api/endpoints/users/recommendation.ts +++ b/src/server/api/endpoints/users/recommendation.ts @@ -4,7 +4,8 @@ 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'; /** * Get recommended users @@ -15,23 +16,28 @@ import getFriends from '../../common/get-friends'; */ module.exports = (params, me) => new Promise(async (res, rej) => { // Get 'limit' parameter - const [limit = 10, limitErr] = $(params.limit).optional.number().range(1, 100).$; + const [limit = 10, limitErr] = $.num.optional().range(1, 100).get(params.limit); if (limitErr) return rej('invalid limit param'); // Get 'offset' parameter - const [offset = 0, offsetErr] = $(params.offset).optional.number().min(0).$; + const [offset = 0, offsetErr] = $.num.optional().min(0).get(params.offset); 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({ + muterId: me._id + })).map(m => m.muteeId); const users = await User .find({ _id: { - $nin: followingIds + $nin: followingIds.concat(mutedUserIds) }, $or: [{ - 'lastUsedAt': { + lastUsedAt: { $gte: new Date(Date.now() - ms('7days')) } }, { diff --git a/src/server/api/endpoints/users/search.ts b/src/server/api/endpoints/users/search.ts index da30f47c2a..cfbdc337bf 100644 --- a/src/server/api/endpoints/users/search.ts +++ b/src/server/api/endpoints/users/search.ts @@ -16,15 +16,15 @@ const escapeRegexp = require('escape-regexp'); */ module.exports = (params, me) => new Promise(async (res, rej) => { // Get 'query' parameter - const [query, queryError] = $(params.query).string().pipe(x => x != '').$; + const [query, queryError] = $.str.pipe(x => x != '').get(params.query); if (queryError) return rej('invalid query param'); // Get 'offset' parameter - const [offset = 0, offsetErr] = $(params.offset).optional.number().min(0).$; + const [offset = 0, offsetErr] = $.num.optional().min(0).get(params.offset); if (offsetErr) return rej('invalid offset param'); // Get 'max' parameter - const [max = 10, maxErr] = $(params.max).optional.number().range(1, 30).$; + const [max = 10, maxErr] = $.num.optional().range(1, 30).get(params.max); if (maxErr) return rej('invalid max param'); // If Elasticsearch is available, search by $ diff --git a/src/server/api/endpoints/users/search_by_username.ts b/src/server/api/endpoints/users/search_by_username.ts index 5f6ececff9..5927d00faf 100644 --- a/src/server/api/endpoints/users/search_by_username.ts +++ b/src/server/api/endpoints/users/search_by_username.ts @@ -6,22 +6,18 @@ import User, { pack } from '../../../../models/user'; /** * Search a user by username - * - * @param {any} params - * @param {any} me - * @return {Promise<any>} */ module.exports = (params, me) => new Promise(async (res, rej) => { // Get 'query' parameter - const [query, queryError] = $(params.query).string().$; + const [query, queryError] = $.str.get(params.query); if (queryError) return rej('invalid query param'); // Get 'offset' parameter - const [offset = 0, offsetErr] = $(params.offset).optional.number().min(0).$; + const [offset = 0, offsetErr] = $.num.optional().min(0).get(params.offset); if (offsetErr) return rej('invalid offset param'); // Get 'limit' parameter - const [limit = 10, limitErr] = $(params.limit).optional.number().range(1, 100).$; + const [limit = 10, limitErr] = $.num.optional().range(1, 100).get(params.limit); if (limitErr) return rej('invalid limit param'); const users = await User diff --git a/src/server/api/endpoints/users/show.ts b/src/server/api/endpoints/users/show.ts index 7e7f5dc488..b8c6ff25c4 100644 --- a/src/server/api/endpoints/users/show.ts +++ b/src/server/api/endpoints/users/show.ts @@ -1,56 +1,68 @@ /** * Module dependencies */ -import $ from 'cafy'; +import $ from 'cafy'; import ID from '../../../../cafy-id'; import User, { pack } from '../../../../models/user'; import resolveRemoteUser from '../../../../remote/resolve-user'; const cursorOption = { fields: { data: false } }; /** - * Show a user + * Show user(s) */ module.exports = (params, me) => new Promise(async (res, rej) => { let user; // Get 'userId' parameter - const [userId, userIdErr] = $(params.userId).optional.id().$; + const [userId, userIdErr] = $.type(ID).optional().get(params.userId); if (userIdErr) return rej('invalid userId param'); + // Get 'userIds' parameter + const [userIds, userIdsErr] = $.arr($.type(ID)).optional().get(params.userIds); + if (userIdsErr) return rej('invalid userIds param'); + // Get 'username' parameter - const [username, usernameErr] = $(params.username).optional.string().$; + const [username, usernameErr] = $.str.optional().get(params.username); if (usernameErr) return rej('invalid username param'); // Get 'host' parameter - const [host, hostErr] = $(params.host).nullable.optional.string().$; + const [host, hostErr] = $.str.optional().nullable().get(params.host); if (hostErr) return rej('invalid host param'); - if (userId === undefined && typeof username !== 'string') { - return rej('userId or pair of username and host is required'); - } + if (userIds) { + const users = await User.find({ + _id: { + $in: userIds + } + }); - // Lookup user - if (typeof host === 'string') { - try { - user = await resolveRemoteUser(username, host, cursorOption); - } catch (e) { - console.warn(`failed to resolve remote user: ${e}`); - return rej('failed to resolve remote user'); - } + res(await Promise.all(users.map(u => pack(u, me, { + detail: true + })))); } else { - const q = userId !== undefined - ? { _id: userId } - : { usernameLower: username.toLowerCase(), host: null }; + // Lookup user + if (typeof host === 'string') { + try { + user = await resolveRemoteUser(username, host, cursorOption); + } catch (e) { + console.warn(`failed to resolve remote user: ${e}`); + return rej('failed to resolve remote user'); + } + } else { + const q = userId !== undefined + ? { _id: userId } + : { usernameLower: username.toLowerCase(), host: null }; - user = await User.findOne(q, cursorOption); + user = await User.findOne(q, cursorOption); - if (user === null) { - return rej('user not found'); + if (user === null) { + return rej('user not found'); + } } - } - // Send response - res(await pack(user, me, { - detail: true - })); + // Send response + res(await pack(user, me, { + detail: true + })); + } }); |