summaryrefslogtreecommitdiff
path: root/src/server/api/endpoints/users
diff options
context:
space:
mode:
Diffstat (limited to 'src/server/api/endpoints/users')
-rw-r--r--src/server/api/endpoints/users/followers.ts18
-rw-r--r--src/server/api/endpoints/users/following.ts14
-rw-r--r--src/server/api/endpoints/users/get_frequently_replied_users.ts6
-rw-r--r--src/server/api/endpoints/users/lists/create.ts25
-rw-r--r--src/server/api/endpoints/users/lists/list.ts13
-rw-r--r--src/server/api/endpoints/users/lists/push.ts61
-rw-r--r--src/server/api/endpoints/users/lists/show.ts23
-rw-r--r--src/server/api/endpoints/users/notes.ts22
-rw-r--r--src/server/api/endpoints/users/recommendation.ts18
-rw-r--r--src/server/api/endpoints/users/search.ts6
-rw-r--r--src/server/api/endpoints/users/search_by_username.ts10
-rw-r--r--src/server/api/endpoints/users/show.ts66
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
+ }));
+ }
});