diff options
| author | syuilo <Syuilotan@yahoo.co.jp> | 2018-06-18 14:43:56 +0900 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2018-06-18 14:43:56 +0900 |
| commit | 5d3943ffa8cb4090c5c111397e266d255cc2212b (patch) | |
| tree | 46f692fb21005bdc89499ea012c2436e8a2e90c0 /src/server/api/endpoints | |
| parent | New translations ja.yml (Spanish) (diff) | |
| parent | yatta (diff) | |
| download | misskey-5d3943ffa8cb4090c5c111397e266d255cc2212b.tar.gz misskey-5d3943ffa8cb4090c5c111397e266d255cc2212b.tar.bz2 misskey-5d3943ffa8cb4090c5c111397e266d255cc2212b.zip | |
Merge branch 'master' into l10n_master
Diffstat (limited to 'src/server/api/endpoints')
107 files changed, 821 insertions, 846 deletions
diff --git a/src/server/api/endpoints/aggregation/posts.ts b/src/server/api/endpoints/aggregation/posts.ts index d348cadae9..48e344312d 100644 --- a/src/server/api/endpoints/aggregation/posts.ts +++ b/src/server/api/endpoints/aggregation/posts.ts @@ -1,13 +1,10 @@ -/** - * Module dependencies - */ import $ from 'cafy'; import Note from '../../../../models/note'; /** * Aggregate notes */ -module.exports = params => new Promise(async (res, rej) => { +module.exports = (params: any) => new Promise(async (res, rej) => { // Get 'limit' parameter const [limit = 365, limitErr] = $.num.optional().range(1, 365).get(params.limit); if (limitErr) return rej('invalid limit param'); @@ -52,13 +49,13 @@ module.exports = params => new Promise(async (res, rej) => { } } ]); - datas.forEach(data => { + datas.forEach((data: any) => { data.date = data._id; delete data._id; - data.notes = (data.data.filter(x => x.type == 'note')[0] || { count: 0 }).count; - data.renotes = (data.data.filter(x => x.type == 'renote')[0] || { count: 0 }).count; - data.replies = (data.data.filter(x => x.type == 'reply')[0] || { count: 0 }).count; + data.notes = (data.data.filter((x: any) => x.type == 'note')[0] || { count: 0 }).count; + data.renotes = (data.data.filter((x: any) => x.type == 'renote')[0] || { count: 0 }).count; + data.replies = (data.data.filter((x: any) => x.type == 'reply')[0] || { count: 0 }).count; delete data.data; }); @@ -68,7 +65,7 @@ module.exports = params => new Promise(async (res, rej) => { for (let i = 0; i < limit; i++) { const day = new Date(new Date().setDate(new Date().getDate() - i)); - const data = datas.filter(d => + const data = datas.filter((d: any) => d.date.year == day.getFullYear() && d.date.month == day.getMonth() + 1 && d.date.day == day.getDate() )[0]; diff --git a/src/server/api/endpoints/aggregation/users.ts b/src/server/api/endpoints/aggregation/users.ts index b116c1454b..c084404d0a 100644 --- a/src/server/api/endpoints/aggregation/users.ts +++ b/src/server/api/endpoints/aggregation/users.ts @@ -1,13 +1,10 @@ -/** - * Module dependencies - */ import $ from 'cafy'; import User from '../../../../models/user'; /** * Aggregate users */ -module.exports = params => new Promise(async (res, rej) => { +module.exports = (params: any) => new Promise(async (res, rej) => { // Get 'limit' parameter const [limit = 365, limitErr] = $.num.optional().range(1, 365).get(params.limit); if (limitErr) return rej('invalid limit param'); diff --git a/src/server/api/endpoints/aggregation/users/activity.ts b/src/server/api/endpoints/aggregation/users/activity.ts index 9109487ac6..d4c716d65b 100644 --- a/src/server/api/endpoints/aggregation/users/activity.ts +++ b/src/server/api/endpoints/aggregation/users/activity.ts @@ -1,6 +1,3 @@ -/** - * Module dependencies - */ import $ from 'cafy'; import ID from '../../../../../cafy-id'; import User from '../../../../../models/user'; import Note from '../../../../../models/note'; @@ -10,7 +7,7 @@ import Note from '../../../../../models/note'; /** * Aggregate activity of a user */ -module.exports = (params) => new Promise(async (res, rej) => { +module.exports = (params: any) => new Promise(async (res, rej) => { // Get 'limit' parameter const [limit = 365, limitErr] = $.num.optional().range(1, 365).get(params.limit); if (limitErr) return rej('invalid limit param'); @@ -73,13 +70,13 @@ module.exports = (params) => new Promise(async (res, rej) => { } } ]); - datas.forEach(data => { + datas.forEach((data: any) => { data.date = data._id; delete data._id; - data.notes = (data.data.filter(x => x.type == 'note')[0] || { count: 0 }).count; - data.renotes = (data.data.filter(x => x.type == 'renote')[0] || { count: 0 }).count; - data.replies = (data.data.filter(x => x.type == 'reply')[0] || { count: 0 }).count; + data.notes = (data.data.filter((x: any) => x.type == 'note')[0] || { count: 0 }).count; + data.renotes = (data.data.filter((x: any) => x.type == 'renote')[0] || { count: 0 }).count; + data.replies = (data.data.filter((x: any) => x.type == 'reply')[0] || { count: 0 }).count; delete data.data; }); @@ -89,7 +86,7 @@ module.exports = (params) => new Promise(async (res, rej) => { for (let i = 0; i < limit; i++) { const day = new Date(new Date().setDate(new Date().getDate() - i)); - const data = datas.filter(d => + const data = datas.filter((d: any) => d.date.year == day.getFullYear() && d.date.month == day.getMonth() + 1 && d.date.day == day.getDate() )[0]; diff --git a/src/server/api/endpoints/aggregation/users/followers.ts b/src/server/api/endpoints/aggregation/users/followers.ts index dfcaf8462f..847f376079 100644 --- a/src/server/api/endpoints/aggregation/users/followers.ts +++ b/src/server/api/endpoints/aggregation/users/followers.ts @@ -8,7 +8,7 @@ import FollowedLog from '../../../../../models/followed-log'; /** * Aggregate followers of a user */ -module.exports = (params) => new Promise(async (res, rej) => { +module.exports = (params: any) => new Promise(async (res, rej) => { // Get 'userId' parameter const [userId, userIdErr] = $.type(ID).get(params.userId); if (userIdErr) return rej('invalid userId param'); diff --git a/src/server/api/endpoints/aggregation/users/following.ts b/src/server/api/endpoints/aggregation/users/following.ts index 5f826fd71c..6c52752f98 100644 --- a/src/server/api/endpoints/aggregation/users/following.ts +++ b/src/server/api/endpoints/aggregation/users/following.ts @@ -8,7 +8,7 @@ import FollowingLog from '../../../../../models/following-log'; /** * Aggregate following of a user */ -module.exports = (params) => new Promise(async (res, rej) => { +module.exports = (params: any) => new Promise(async (res, rej) => { // Get 'userId' parameter const [userId, userIdErr] = $.type(ID).get(params.userId); if (userIdErr) return rej('invalid userId param'); diff --git a/src/server/api/endpoints/aggregation/users/post.ts b/src/server/api/endpoints/aggregation/users/post.ts index 11f9ef14cd..28ba1482bf 100644 --- a/src/server/api/endpoints/aggregation/users/post.ts +++ b/src/server/api/endpoints/aggregation/users/post.ts @@ -1,6 +1,3 @@ -/** - * Module dependencies - */ import $ from 'cafy'; import ID from '../../../../../cafy-id'; import User from '../../../../../models/user'; import Note from '../../../../../models/note'; @@ -8,7 +5,7 @@ import Note from '../../../../../models/note'; /** * Aggregate note of a user */ -module.exports = (params) => new Promise(async (res, rej) => { +module.exports = (params: any) => new Promise(async (res, rej) => { // Get 'userId' parameter const [userId, userIdErr] = $.type(ID).get(params.userId); if (userIdErr) return rej('invalid userId param'); @@ -67,13 +64,13 @@ module.exports = (params) => new Promise(async (res, rej) => { } } ]); - datas.forEach(data => { + datas.forEach((data: any) => { data.date = data._id; delete data._id; - data.notes = (data.data.filter(x => x.type == 'note')[0] || { count: 0 }).count; - data.renotes = (data.data.filter(x => x.type == 'renote')[0] || { count: 0 }).count; - data.replies = (data.data.filter(x => x.type == 'reply')[0] || { count: 0 }).count; + data.notes = (data.data.filter((x: any) => x.type == 'note')[0] || { count: 0 }).count; + data.renotes = (data.data.filter((x: any) => x.type == 'renote')[0] || { count: 0 }).count; + data.replies = (data.data.filter((x: any) => x.type == 'reply')[0] || { count: 0 }).count; delete data.data; }); @@ -83,7 +80,7 @@ module.exports = (params) => new Promise(async (res, rej) => { for (let i = 0; i < 30; i++) { const day = new Date(new Date().setDate(new Date().getDate() - i)); - const data = datas.filter(d => + const data = datas.filter((d: any) => d.date.year == day.getFullYear() && d.date.month == day.getMonth() + 1 && d.date.day == day.getDate() )[0]; diff --git a/src/server/api/endpoints/aggregation/users/reaction.ts b/src/server/api/endpoints/aggregation/users/reaction.ts index 2de2840258..adb5acfb4e 100644 --- a/src/server/api/endpoints/aggregation/users/reaction.ts +++ b/src/server/api/endpoints/aggregation/users/reaction.ts @@ -1,17 +1,11 @@ -/** - * Module dependencies - */ import $ from 'cafy'; import ID from '../../../../../cafy-id'; import User from '../../../../../models/user'; import Reaction from '../../../../../models/note-reaction'; /** * Aggregate reaction of a user - * - * @param {any} params - * @return {Promise<any>} */ -module.exports = (params) => new Promise(async (res, rej) => { +module.exports = (params: any) => new Promise(async (res, rej) => { // Get 'userId' parameter const [userId, userIdErr] = $.type(ID).get(params.userId); if (userIdErr) return rej('invalid userId param'); @@ -48,7 +42,7 @@ module.exports = (params) => new Promise(async (res, rej) => { }} ]); - datas.forEach(data => { + datas.forEach((data: any) => { data.date = data._id; delete data._id; }); @@ -58,7 +52,7 @@ module.exports = (params) => new Promise(async (res, rej) => { for (let i = 0; i < 30; i++) { const day = new Date(new Date().setDate(new Date().getDate() - i)); - const data = datas.filter(d => + const data = datas.filter((d: any) => d.date.year == day.getFullYear() && d.date.month == day.getMonth() + 1 && d.date.day == day.getDate() )[0]; diff --git a/src/server/api/endpoints/app/create.ts b/src/server/api/endpoints/app/create.ts index 553bd2381a..c7bc91a079 100644 --- a/src/server/api/endpoints/app/create.ts +++ b/src/server/api/endpoints/app/create.ts @@ -1,9 +1,7 @@ -/** - * Module dependencies - */ import rndstr from 'rndstr'; import $ from 'cafy'; import App, { isValidNameId, pack } from '../../../../models/app'; +import { ILocalUser } from '../../../../models/user'; /** * @swagger @@ -60,12 +58,8 @@ import App, { isValidNameId, pack } from '../../../../models/app'; /** * Create an app - * - * @param {any} params - * @param {any} user - * @return {Promise<any>} */ -module.exports = async (params, user) => new Promise(async (res, rej) => { +module.exports = async (params: any, user: ILocalUser) => new Promise(async (res, rej) => { // Get 'nameId' parameter const [nameId, nameIdErr] = $.str.pipe(isValidNameId).get(params.nameId); if (nameIdErr) return rej('invalid nameId param'); diff --git a/src/server/api/endpoints/app/name_id/available.ts b/src/server/api/endpoints/app/name_id/available.ts index 135bb7d2b4..58101a7e6a 100644 --- a/src/server/api/endpoints/app/name_id/available.ts +++ b/src/server/api/endpoints/app/name_id/available.ts @@ -40,7 +40,7 @@ import { isValidNameId } from '../../../../../models/app'; * @param {any} params * @return {Promise<any>} */ -module.exports = async (params) => new Promise(async (res, rej) => { +module.exports = async (params: any) => new Promise(async (res, rej) => { // Get 'nameId' parameter const [nameId, nameIdErr] = $.str.pipe(isValidNameId).get(params.nameId); if (nameIdErr) return rej('invalid nameId param'); diff --git a/src/server/api/endpoints/app/show.ts b/src/server/api/endpoints/app/show.ts index 8d742ab182..2b98a3f142 100644 --- a/src/server/api/endpoints/app/show.ts +++ b/src/server/api/endpoints/app/show.ts @@ -1,8 +1,6 @@ -/** - * Module dependencies - */ import $ from 'cafy'; import ID from '../../../../cafy-id'; -import App, { pack } from '../../../../models/app'; +import App, { pack, IApp } from '../../../../models/app'; +import { ILocalUser } from '../../../../models/user'; /** * @swagger @@ -37,7 +35,7 @@ import App, { pack } from '../../../../models/app'; /** * Show an app */ -module.exports = (params, user, app) => new Promise(async (res, rej) => { +module.exports = (params: any, user: ILocalUser, app: IApp) => new Promise(async (res, rej) => { const isSecure = user != null && app == null; // Get 'appId' parameter diff --git a/src/server/api/endpoints/auth/accept.ts b/src/server/api/endpoints/auth/accept.ts index 695fbb0803..fc6cbc473d 100644 --- a/src/server/api/endpoints/auth/accept.ts +++ b/src/server/api/endpoints/auth/accept.ts @@ -1,12 +1,10 @@ -/** - * Module dependencies - */ import rndstr from 'rndstr'; const crypto = require('crypto'); import $ from 'cafy'; import App from '../../../../models/app'; import AuthSess from '../../../../models/auth-session'; import AccessToken from '../../../../models/access-token'; +import { ILocalUser } from '../../../../models/user'; /** * @swagger @@ -33,12 +31,8 @@ import AccessToken from '../../../../models/access-token'; /** * Accept - * - * @param {any} params - * @param {any} user - * @return {Promise<any>} */ -module.exports = (params, user) => new Promise(async (res, rej) => { +module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => { // Get 'token' parameter const [token, tokenErr] = $.str.get(params.token); if (tokenErr) return rej('invalid token param'); diff --git a/src/server/api/endpoints/auth/session/generate.ts b/src/server/api/endpoints/auth/session/generate.ts index d649a8d902..5a4d99ff3b 100644 --- a/src/server/api/endpoints/auth/session/generate.ts +++ b/src/server/api/endpoints/auth/session/generate.ts @@ -44,7 +44,7 @@ import config from '../../../../../config'; * @param {any} params * @return {Promise<any>} */ -module.exports = (params) => new Promise(async (res, rej) => { +module.exports = (params: any) => new Promise(async (res, rej) => { // Get 'appSecret' parameter const [appSecret, appSecretErr] = $.str.get(params.appSecret); if (appSecretErr) return rej('invalid appSecret param'); diff --git a/src/server/api/endpoints/auth/session/show.ts b/src/server/api/endpoints/auth/session/show.ts index 434cc264a0..3d3b6bbf61 100644 --- a/src/server/api/endpoints/auth/session/show.ts +++ b/src/server/api/endpoints/auth/session/show.ts @@ -1,8 +1,6 @@ -/** - * Module dependencies - */ import $ from 'cafy'; import AuthSess, { pack } from '../../../../../models/auth-session'; +import { ILocalUser } from '../../../../../models/user'; /** * @swagger @@ -46,12 +44,8 @@ import AuthSess, { pack } from '../../../../../models/auth-session'; /** * Show a session - * - * @param {any} params - * @param {any} user - * @return {Promise<any>} */ -module.exports = (params, user) => new Promise(async (res, rej) => { +module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => { // Get 'token' parameter const [token, tokenErr] = $.str.get(params.token); if (tokenErr) return rej('invalid token param'); diff --git a/src/server/api/endpoints/auth/session/userkey.ts b/src/server/api/endpoints/auth/session/userkey.ts index 3026b477f1..3ea48fbe34 100644 --- a/src/server/api/endpoints/auth/session/userkey.ts +++ b/src/server/api/endpoints/auth/session/userkey.ts @@ -49,7 +49,7 @@ import { pack } from '../../../../../models/user'; * @param {any} params * @return {Promise<any>} */ -module.exports = (params) => new Promise(async (res, rej) => { +module.exports = (params: any) => new Promise(async (res, rej) => { // Get 'appSecret' parameter const [appSecret, appSecretErr] = $.str.get(params.appSecret); if (appSecretErr) return rej('invalid appSecret param'); diff --git a/src/server/api/endpoints/drive.ts b/src/server/api/endpoints/drive.ts index d77ab2bbb0..9caad273c8 100644 --- a/src/server/api/endpoints/drive.ts +++ b/src/server/api/endpoints/drive.ts @@ -1,34 +1,33 @@ -/** - * Module dependencies - */ import DriveFile from '../../../models/drive-file'; +import { ILocalUser } from '../../../models/user'; /** * Get drive information - * - * @param {any} params - * @param {any} user - * @return {Promise<any>} */ -module.exports = (params, user) => new Promise(async (res, rej) => { +module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => { // Calculate drive usage - const usage = ((await DriveFile - .aggregate([ - { $match: { 'metadata.userId': user._id } }, - { - $project: { - length: true - } - }, - { - $group: { - _id: null, - usage: { $sum: '$length' } - } + const usage = await DriveFile + .aggregate([{ + $match: { + 'metadata.userId': user._id, + 'metadata.deletedAt': { $exists: false } + } + }, { + $project: { + length: true + } + }, { + $group: { + _id: null, + usage: { $sum: '$length' } + } + }]) + .then((aggregates: any[]) => { + if (aggregates.length > 0) { + return aggregates[0].usage; } - ]))[0] || { - usage: 0 - }).usage; + return 0; + }); res({ capacity: user.driveCapacity, diff --git a/src/server/api/endpoints/drive/files.ts b/src/server/api/endpoints/drive/files.ts index ab4b18cef4..efce750747 100644 --- a/src/server/api/endpoints/drive/files.ts +++ b/src/server/api/endpoints/drive/files.ts @@ -1,13 +1,11 @@ -/** - * Module dependencies - */ import $ from 'cafy'; import ID from '../../../../cafy-id'; import DriveFile, { pack } from '../../../../models/drive-file'; +import { ILocalUser } from '../../../../models/user'; /** * Get drive files */ -module.exports = async (params, user, app) => { +module.exports = async (params: any, user: ILocalUser) => { // Get 'limit' parameter const [limit = 10, limitErr] = $.num.optional().range(1, 100).get(params.limit); if (limitErr) throw 'invalid limit param'; @@ -37,10 +35,13 @@ module.exports = async (params, user, app) => { const sort = { _id: -1 }; + const query = { 'metadata.userId': user._id, - 'metadata.folderId': folderId + 'metadata.folderId': folderId, + 'metadata.deletedAt': { $exists: false } } as any; + if (sinceId) { sort._id = 1; query._id = { @@ -51,6 +52,7 @@ module.exports = async (params, user, app) => { $lt: untilId }; } + if (type) { query.contentType = new RegExp(`^${type.replace(/\*/g, '.+?')}$`); } diff --git a/src/server/api/endpoints/drive/files/create.ts b/src/server/api/endpoints/drive/files/create.ts index dd748d6bba..db2626af09 100644 --- a/src/server/api/endpoints/drive/files/create.ts +++ b/src/server/api/endpoints/drive/files/create.ts @@ -1,15 +1,13 @@ -/** - * Module dependencies - */ import * as fs from 'fs'; import $ from 'cafy'; import ID from '../../../../../cafy-id'; import { validateFileName, pack } from '../../../../../models/drive-file'; import create from '../../../../../services/drive/add-file'; +import { ILocalUser } from '../../../../../models/user'; /** * Create a file */ -module.exports = async (file, params, user): Promise<any> => { +module.exports = async (file: any, params: any, user: ILocalUser): Promise<any> => { if (file == null) { throw 'file is required'; } diff --git a/src/server/api/endpoints/drive/files/delete.ts b/src/server/api/endpoints/drive/files/delete.ts new file mode 100644 index 0000000000..17eb0eb4b9 --- /dev/null +++ b/src/server/api/endpoints/drive/files/delete.ts @@ -0,0 +1,33 @@ +import $ from 'cafy'; import ID from '../../../../../cafy-id'; +import DriveFile from '../../../../../models/drive-file'; +import del from '../../../../../services/drive/delete-file'; +import { publishDriveStream } from '../../../../../publishers/stream'; +import { ILocalUser } from '../../../../../models/user'; + +/** + * Delete a file + */ +module.exports = async (params: any, user: ILocalUser) => { + // Get 'fileId' parameter + const [fileId, fileIdErr] = $.type(ID).get(params.fileId); + if (fileIdErr) throw 'invalid fileId param'; + + // Fetch file + const file = await DriveFile + .findOne({ + _id: fileId, + 'metadata.userId': user._id + }); + + if (file === null) { + throw 'file-not-found'; + } + + // Delete + await del(file); + + // Publish file_deleted event + publishDriveStream(user._id, 'file_deleted', file._id); + + return; +}; diff --git a/src/server/api/endpoints/drive/files/find.ts b/src/server/api/endpoints/drive/files/find.ts index 98165990fe..75ab91f0a1 100644 --- a/src/server/api/endpoints/drive/files/find.ts +++ b/src/server/api/endpoints/drive/files/find.ts @@ -1,13 +1,11 @@ -/** - * Module dependencies - */ import $ from 'cafy'; import ID from '../../../../../cafy-id'; import DriveFile, { pack } from '../../../../../models/drive-file'; +import { ILocalUser } from '../../../../../models/user'; /** * Find a file(s) */ -module.exports = (params, user) => new Promise(async (res, rej) => { +module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => { // Get 'name' parameter const [name, nameErr] = $.str.get(params.name); if (nameErr) return rej('invalid name param'); diff --git a/src/server/api/endpoints/drive/files/show.ts b/src/server/api/endpoints/drive/files/show.ts index c7efda7ab0..e7dca486c5 100644 --- a/src/server/api/endpoints/drive/files/show.ts +++ b/src/server/api/endpoints/drive/files/show.ts @@ -1,13 +1,11 @@ -/** - * Module dependencies - */ import $ from 'cafy'; import ID from '../../../../../cafy-id'; import DriveFile, { pack } from '../../../../../models/drive-file'; +import { ILocalUser } from '../../../../../models/user'; /** * Show a file */ -module.exports = async (params, user) => { +module.exports = async (params: any, user: ILocalUser) => { // Get 'fileId' parameter const [fileId, fileIdErr] = $.type(ID).get(params.fileId); if (fileIdErr) throw 'invalid fileId param'; diff --git a/src/server/api/endpoints/drive/files/update.ts b/src/server/api/endpoints/drive/files/update.ts index 12fa8e025d..825683b214 100644 --- a/src/server/api/endpoints/drive/files/update.ts +++ b/src/server/api/endpoints/drive/files/update.ts @@ -1,15 +1,13 @@ -/** - * Module dependencies - */ import $ from 'cafy'; import ID from '../../../../../cafy-id'; import DriveFolder from '../../../../../models/drive-folder'; import DriveFile, { validateFileName, pack } from '../../../../../models/drive-file'; import { publishDriveStream } from '../../../../../publishers/stream'; +import { ILocalUser } from '../../../../../models/user'; /** * Update a file */ -module.exports = (params, user) => new Promise(async (res, rej) => { +module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => { // Get 'fileId' parameter const [fileId, fileIdErr] = $.type(ID).get(params.fileId); if (fileIdErr) return rej('invalid fileId param'); diff --git a/src/server/api/endpoints/drive/files/upload_from_url.ts b/src/server/api/endpoints/drive/files/upload_from_url.ts index c012f0d3c9..cb617d851f 100644 --- a/src/server/api/endpoints/drive/files/upload_from_url.ts +++ b/src/server/api/endpoints/drive/files/upload_from_url.ts @@ -4,11 +4,12 @@ import $ from 'cafy'; import ID from '../../../../../cafy-id'; import { pack } from '../../../../../models/drive-file'; import uploadFromUrl from '../../../../../services/drive/upload-from-url'; +import { ILocalUser } from '../../../../../models/user'; /** * Create a file from a URL */ -module.exports = async (params, user): Promise<any> => { +module.exports = async (params: any, user: ILocalUser): Promise<any> => { // Get 'url' parameter // TODO: Validate this url const [url, urlErr] = $.str.get(params.url); diff --git a/src/server/api/endpoints/drive/folders.ts b/src/server/api/endpoints/drive/folders.ts index bc6c50eb99..3413778950 100644 --- a/src/server/api/endpoints/drive/folders.ts +++ b/src/server/api/endpoints/drive/folders.ts @@ -1,13 +1,11 @@ -/** - * Module dependencies - */ import $ from 'cafy'; import ID from '../../../../cafy-id'; import DriveFolder, { pack } from '../../../../models/drive-folder'; +import { ILocalUser } from '../../../../models/user'; /** * Get drive folders */ -module.exports = (params, user, app) => new Promise(async (res, rej) => { +module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => { // Get 'limit' parameter const [limit = 10, limitErr] = $.num.optional().range(1, 100).get(params.limit); if (limitErr) return rej('invalid limit param'); diff --git a/src/server/api/endpoints/drive/folders/create.ts b/src/server/api/endpoints/drive/folders/create.ts index 62e3b6f6e8..8f06b0f668 100644 --- a/src/server/api/endpoints/drive/folders/create.ts +++ b/src/server/api/endpoints/drive/folders/create.ts @@ -1,14 +1,12 @@ -/** - * Module dependencies - */ import $ from 'cafy'; import ID from '../../../../../cafy-id'; import DriveFolder, { isValidFolderName, pack } from '../../../../../models/drive-folder'; import { publishDriveStream } from '../../../../../publishers/stream'; +import { ILocalUser } from '../../../../../models/user'; /** * Create drive folder */ -module.exports = (params, user) => new Promise(async (res, rej) => { +module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => { // Get 'name' parameter const [name = '無題のフォルダー', nameErr] = $.str.optional().pipe(isValidFolderName).get(params.name); if (nameErr) return rej('invalid name param'); diff --git a/src/server/api/endpoints/drive/folders/find.ts b/src/server/api/endpoints/drive/folders/find.ts index 9703d9e99d..b3238b5c32 100644 --- a/src/server/api/endpoints/drive/folders/find.ts +++ b/src/server/api/endpoints/drive/folders/find.ts @@ -1,13 +1,11 @@ -/** - * Module dependencies - */ import $ from 'cafy'; import ID from '../../../../../cafy-id'; import DriveFolder, { pack } from '../../../../../models/drive-folder'; +import { ILocalUser } from '../../../../../models/user'; /** * Find a folder(s) */ -module.exports = (params, user) => new Promise(async (res, rej) => { +module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => { // Get 'name' parameter const [name, nameErr] = $.str.get(params.name); if (nameErr) return rej('invalid name param'); diff --git a/src/server/api/endpoints/drive/folders/show.ts b/src/server/api/endpoints/drive/folders/show.ts index 44f1889001..c9b4930a76 100644 --- a/src/server/api/endpoints/drive/folders/show.ts +++ b/src/server/api/endpoints/drive/folders/show.ts @@ -1,13 +1,11 @@ -/** - * Module dependencies - */ import $ from 'cafy'; import ID from '../../../../../cafy-id'; import DriveFolder, { pack } from '../../../../../models/drive-folder'; +import { ILocalUser } from '../../../../../models/user'; /** * Show a folder */ -module.exports = (params, user) => new Promise(async (res, rej) => { +module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => { // Get 'folderId' parameter const [folderId, folderIdErr] = $.type(ID).get(params.folderId); if (folderIdErr) return rej('invalid folderId param'); diff --git a/src/server/api/endpoints/drive/folders/update.ts b/src/server/api/endpoints/drive/folders/update.ts index e24d8a14cd..f126c09f5b 100644 --- a/src/server/api/endpoints/drive/folders/update.ts +++ b/src/server/api/endpoints/drive/folders/update.ts @@ -1,14 +1,12 @@ -/** - * Module dependencies - */ import $ from 'cafy'; import ID from '../../../../../cafy-id'; import DriveFolder, { isValidFolderName, pack } from '../../../../../models/drive-folder'; import { publishDriveStream } from '../../../../../publishers/stream'; +import { ILocalUser } from '../../../../../models/user'; /** * Update a folder */ -module.exports = (params, user) => new Promise(async (res, rej) => { +module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => { // Get 'folderId' parameter const [folderId, folderIdErr] = $.type(ID).get(params.folderId); if (folderIdErr) return rej('invalid folderId param'); @@ -48,7 +46,7 @@ module.exports = (params, user) => new Promise(async (res, rej) => { } // Check if the circular reference will occur - async function checkCircle(folderId) { + async function checkCircle(folderId: any): Promise<boolean> { // Fetch folder const folder2 = await DriveFolder.findOne({ _id: folderId diff --git a/src/server/api/endpoints/drive/stream.ts b/src/server/api/endpoints/drive/stream.ts index 8cb3a99b42..515f74645a 100644 --- a/src/server/api/endpoints/drive/stream.ts +++ b/src/server/api/endpoints/drive/stream.ts @@ -1,13 +1,11 @@ -/** - * Module dependencies - */ import $ from 'cafy'; import ID from '../../../../cafy-id'; import DriveFile, { pack } from '../../../../models/drive-file'; +import { ILocalUser } from '../../../../models/user'; /** * Get drive stream */ -module.exports = (params, user) => new Promise(async (res, rej) => { +module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => { // Get 'limit' parameter const [limit = 10, limitErr] = $.num.optional().range(1, 100).get(params.limit); if (limitErr) return rej('invalid limit param'); diff --git a/src/server/api/endpoints/following/create.ts b/src/server/api/endpoints/following/create.ts index 766a8c03d0..3e45b8da53 100644 --- a/src/server/api/endpoints/following/create.ts +++ b/src/server/api/endpoints/following/create.ts @@ -1,15 +1,12 @@ -/** - * Module dependencies - */ import $ from 'cafy'; import ID from '../../../../cafy-id'; -import User from '../../../../models/user'; +import User, { pack, ILocalUser } from '../../../../models/user'; import Following from '../../../../models/following'; import create from '../../../../services/following/create'; /** * Follow a user */ -module.exports = (params, user) => new Promise(async (res, rej) => { +module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => { const follower = user; // Get 'userId' parameter @@ -49,5 +46,5 @@ module.exports = (params, user) => new Promise(async (res, rej) => { create(follower, followee); // Send response - res(); + res(await pack(followee._id, user)); }); diff --git a/src/server/api/endpoints/following/delete.ts b/src/server/api/endpoints/following/delete.ts index 396b19a6f6..0af8813cf9 100644 --- a/src/server/api/endpoints/following/delete.ts +++ b/src/server/api/endpoints/following/delete.ts @@ -1,15 +1,12 @@ -/** - * Module dependencies - */ import $ from 'cafy'; import ID from '../../../../cafy-id'; -import User from '../../../../models/user'; +import User, { pack, ILocalUser } from '../../../../models/user'; import Following from '../../../../models/following'; import deleteFollowing from '../../../../services/following/delete'; /** * Unfollow a user */ -module.exports = (params, user) => new Promise(async (res, rej) => { +module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => { const follower = user; // Get 'userId' parameter @@ -49,5 +46,5 @@ module.exports = (params, user) => new Promise(async (res, rej) => { deleteFollowing(follower, followee); // Send response - res(); + res(await pack(followee._id, user)); }); diff --git a/src/server/api/endpoints/following/requests/accept.ts b/src/server/api/endpoints/following/requests/accept.ts new file mode 100644 index 0000000000..a09e32e4d9 --- /dev/null +++ b/src/server/api/endpoints/following/requests/accept.ts @@ -0,0 +1,26 @@ +import $ from 'cafy'; import ID from '../../../../../cafy-id'; +import acceptFollowRequest from '../../../../../services/following/requests/accept'; +import User, { ILocalUser } from '../../../../../models/user'; + +/** + * Accept a follow request + */ +module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => { + // Get 'userId' parameter + const [followerId, followerIdErr] = $.type(ID).get(params.userId); + if (followerIdErr) return rej('invalid userId param'); + + // Fetch follower + const follower = await User.findOne({ + _id: followerId + }); + + if (follower === null) { + return rej('follower not found'); + } + + await acceptFollowRequest(user, follower); + + // Send response + res(); +}); diff --git a/src/server/api/endpoints/following/requests/cancel.ts b/src/server/api/endpoints/following/requests/cancel.ts new file mode 100644 index 0000000000..f2a40854c2 --- /dev/null +++ b/src/server/api/endpoints/following/requests/cancel.ts @@ -0,0 +1,26 @@ +import $ from 'cafy'; import ID from '../../../../../cafy-id'; +import cancelFollowRequest from '../../../../../services/following/requests/cancel'; +import User, { pack, ILocalUser } from '../../../../../models/user'; + +/** + * Cancel a follow request + */ +module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => { + // Get 'userId' parameter + const [followeeId, followeeIdErr] = $.type(ID).get(params.userId); + if (followeeIdErr) return rej('invalid userId param'); + + // Fetch followee + const followee = await User.findOne({ + _id: followeeId + }); + + if (followee === null) { + return rej('followee not found'); + } + + await cancelFollowRequest(followee, user); + + // Send response + res(await pack(followee._id, user)); +}); diff --git a/src/server/api/endpoints/following/requests/list.ts b/src/server/api/endpoints/following/requests/list.ts new file mode 100644 index 0000000000..287c5a8e46 --- /dev/null +++ b/src/server/api/endpoints/following/requests/list.ts @@ -0,0 +1,15 @@ +//import $ from 'cafy'; import ID from '../../../../../cafy-id'; +import FollowRequest, { pack } from '../../../../../models/follow-request'; +import { ILocalUser } from '../../../../../models/user'; + +/** + * Get all pending received follow requests + */ +module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => { + const reqs = await FollowRequest.find({ + followeeId: user._id + }); + + // Send response + res(await Promise.all(reqs.map(req => pack(req)))); +}); diff --git a/src/server/api/endpoints/following/requests/reject.ts b/src/server/api/endpoints/following/requests/reject.ts new file mode 100644 index 0000000000..69dddf1355 --- /dev/null +++ b/src/server/api/endpoints/following/requests/reject.ts @@ -0,0 +1,26 @@ +import $ from 'cafy'; import ID from '../../../../../cafy-id'; +import rejectFollowRequest from '../../../../../services/following/requests/reject'; +import User, { ILocalUser } from '../../../../../models/user'; + +/** + * Reject a follow request + */ +module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => { + // Get 'userId' parameter + const [followerId, followerIdErr] = $.type(ID).get(params.userId); + if (followerIdErr) return rej('invalid userId param'); + + // Fetch follower + const follower = await User.findOne({ + _id: followerId + }); + + if (follower === null) { + return rej('follower not found'); + } + + await rejectFollowRequest(user, follower); + + // Send response + res(); +}); diff --git a/src/server/api/endpoints/following/stalk.ts b/src/server/api/endpoints/following/stalk.ts index f0bc8cbdfc..b9d19d57b4 100644 --- a/src/server/api/endpoints/following/stalk.ts +++ b/src/server/api/endpoints/following/stalk.ts @@ -1,10 +1,11 @@ import $ from 'cafy'; import ID from '../../../../cafy-id'; import Following from '../../../../models/following'; +import { ILocalUser } from '../../../../models/user'; /** * Stalk a user */ -module.exports = (params, user) => new Promise(async (res, rej) => { +module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => { const follower = user; // Get 'userId' parameter diff --git a/src/server/api/endpoints/following/unstalk.ts b/src/server/api/endpoints/following/unstalk.ts index 0d0a018c34..255f22ca1f 100644 --- a/src/server/api/endpoints/following/unstalk.ts +++ b/src/server/api/endpoints/following/unstalk.ts @@ -1,10 +1,11 @@ import $ from 'cafy'; import ID from '../../../../cafy-id'; import Following from '../../../../models/following'; +import { ILocalUser } from '../../../../models/user'; /** * Unstalk a user */ -module.exports = (params, user) => new Promise(async (res, rej) => { +module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => { const follower = user; // Get 'userId' parameter diff --git a/src/server/api/endpoints/hashtags/trend.ts b/src/server/api/endpoints/hashtags/trend.ts new file mode 100644 index 0000000000..17af9d6a9a --- /dev/null +++ b/src/server/api/endpoints/hashtags/trend.ts @@ -0,0 +1,139 @@ +import Note from '../../../../models/note'; + +/* +トレンドに載るためには「『直近a分間のユニーク投稿数が今からa分前~今からb分前の間のユニーク投稿数のn倍以上』のハッシュタグの上位5位以内に入る」ことが必要 +ユニーク投稿数とはそのハッシュタグと投稿ユーザーのペアのカウントで、例えば同じユーザーが複数回同じハッシュタグを投稿してもそのハッシュタグのユニーク投稿数は1とカウントされる +*/ + +const rangeA = 1000 * 60 * 30; // 30分 +const rangeB = 1000 * 60 * 120; // 2時間 +const coefficient = 1.25; // 「n倍」の部分 +const requiredUsers = 3; // 最低何人がそのタグを投稿している必要があるか + +const max = 5; + +/** + * Get trends of hashtags + */ +module.exports = () => new Promise(async (res, rej) => { + //#region 1. 直近Aの内に投稿されたハッシュタグ(とユーザーのペア)を集計 + const data = await Note.aggregate([{ + $match: { + createdAt: { + $gt: new Date(Date.now() - rangeA) + }, + tagsLower: { + $exists: true, + $ne: [] + } + } + }, { + $unwind: '$tagsLower' + }, { + $group: { + _id: { tag: '$tagsLower', userId: '$userId' } + } + }]) as Array<{ + _id: { + tag: string; + userId: any; + } + }>; + //#endregion + + if (data.length == 0) { + return res([]); + } + + const tags: Array<{ + name: string; + count: number; + }> = []; + + // カウント + data.map(x => x._id).forEach(x => { + const i = tags.findIndex(tag => tag.name == x.tag); + if (i != -1) { + tags[i].count++; + } else { + tags.push({ + name: x.tag, + count: 1 + }); + } + }); + + // 最低要求投稿者数を下回るならカットする + const limitedTags = tags.filter(tag => tag.count >= requiredUsers); + + //#region 2. 1で取得したそれぞれのタグについて、「直近a分間のユニーク投稿数が今からa分前~今からb分前の間のユニーク投稿数のn倍以上」かどうかを判定する + const hotsPromises = limitedTags.map(async tag => { + const passedCount = (await Note.distinct('userId', { + tagsLower: tag.name, + createdAt: { + $lt: new Date(Date.now() - rangeA), + $gt: new Date(Date.now() - rangeB) + } + }) as any).length; + + if (tag.count >= (passedCount * coefficient)) { + return tag; + } else { + return null; + } + }); + //#endregion + + // タグを人気順に並べ替え + let hots = (await Promise.all(hotsPromises)) + .filter(x => x != null) + .sort((a, b) => b.count - a.count) + .map(tag => tag.name) + .slice(0, max); + + //#region 3. もし上記の方法でのトレンド抽出の結果、求められているタグ数に達しなければ「ただ単に現在投稿数が多いハッシュタグ」に切り替える + if (hots.length < max) { + hots = hots.concat(tags + .filter(tag => hots.indexOf(tag.name) == -1) + .sort((a, b) => b.count - a.count) + .map(tag => tag.name) + .slice(0, max - hots.length)); + } + //#endregion + + //#region 2(または3)で話題と判定されたタグそれぞれについて過去の投稿数グラフを取得する + const countPromises: Array<Promise<any[]>> = []; + + const range = 20; + + // 10分 + const interval = 1000 * 60 * 10; + + for (let i = 0; i < range; i++) { + countPromises.push(Promise.all(hots.map(tag => Note.distinct('userId', { + tagsLower: tag, + createdAt: { + $lt: new Date(Date.now() - (interval * i)), + $gt: new Date(Date.now() - (interval * (i + 1))) + } + })))); + } + + const countsLog = await Promise.all(countPromises); + + const totalCounts: any = await Promise.all(hots.map(tag => Note.distinct('userId', { + tagsLower: tag, + createdAt: { + $gt: new Date(Date.now() - (interval * range)) + } + }))); + //#endregion + + const stats = hots.map((tag, i) => ({ + tag, + chart: countsLog.map(counts => counts[i].length), + usersCount: totalCounts[i].length + })); + + res(stats); +}); diff --git a/src/server/api/endpoints/i.ts b/src/server/api/endpoints/i.ts index 379c3c4d88..5c769a02fd 100644 --- a/src/server/api/endpoints/i.ts +++ b/src/server/api/endpoints/i.ts @@ -1,12 +1,10 @@ -/** - * Module dependencies - */ -import User, { pack } from '../../../models/user'; +import User, { pack, ILocalUser } from '../../../models/user'; +import { IApp } from '../../../models/app'; /** * Show myself */ -module.exports = (params, user, app) => new Promise(async (res, rej) => { +module.exports = (params: any, user: ILocalUser, app: IApp) => new Promise(async (res, rej) => { const isSecure = user != null && app == null; // Serialize diff --git a/src/server/api/endpoints/i/2fa/done.ts b/src/server/api/endpoints/i/2fa/done.ts index 1a2706aa84..61f13c4c61 100644 --- a/src/server/api/endpoints/i/2fa/done.ts +++ b/src/server/api/endpoints/i/2fa/done.ts @@ -1,11 +1,8 @@ -/** - * Module dependencies - */ import $ from 'cafy'; import * as speakeasy from 'speakeasy'; -import User from '../../../../../models/user'; +import User, { ILocalUser } from '../../../../../models/user'; -module.exports = async (params, user) => new Promise(async (res, rej) => { +module.exports = async (params: any, user: ILocalUser) => new Promise(async (res, rej) => { // Get 'token' parameter const [token, tokenErr] = $.str.get(params.token); if (tokenErr) return rej('invalid token param'); diff --git a/src/server/api/endpoints/i/2fa/register.ts b/src/server/api/endpoints/i/2fa/register.ts index d314e1a280..d05892c84b 100644 --- a/src/server/api/endpoints/i/2fa/register.ts +++ b/src/server/api/endpoints/i/2fa/register.ts @@ -1,14 +1,11 @@ -/** - * Module dependencies - */ import $ from 'cafy'; import * as bcrypt from 'bcryptjs'; import * as speakeasy from 'speakeasy'; import * as QRCode from 'qrcode'; -import User from '../../../../../models/user'; +import User, { ILocalUser } from '../../../../../models/user'; import config from '../../../../../config'; -module.exports = async (params, user) => new Promise(async (res, rej) => { +module.exports = async (params: any, user: ILocalUser) => new Promise(async (res, rej) => { // Get 'password' parameter const [password, passwordErr] = $.str.get(params.password); if (passwordErr) return rej('invalid password param'); diff --git a/src/server/api/endpoints/i/2fa/unregister.ts b/src/server/api/endpoints/i/2fa/unregister.ts index 336a3564ab..fc197cb1e4 100644 --- a/src/server/api/endpoints/i/2fa/unregister.ts +++ b/src/server/api/endpoints/i/2fa/unregister.ts @@ -1,11 +1,8 @@ -/** - * Module dependencies - */ import $ from 'cafy'; import * as bcrypt from 'bcryptjs'; -import User from '../../../../../models/user'; +import User, { ILocalUser } from '../../../../../models/user'; -module.exports = async (params, user) => new Promise(async (res, rej) => { +module.exports = async (params: any, user: ILocalUser) => new Promise(async (res, rej) => { // Get 'password' parameter const [password, passwordErr] = $.str.get(params.password); if (passwordErr) return rej('invalid password param'); diff --git a/src/server/api/endpoints/i/authorized_apps.ts b/src/server/api/endpoints/i/authorized_apps.ts index d15bd67bf2..cfc93c1518 100644 --- a/src/server/api/endpoints/i/authorized_apps.ts +++ b/src/server/api/endpoints/i/authorized_apps.ts @@ -1,14 +1,12 @@ -/** - * Module dependencies - */ import $ from 'cafy'; import AccessToken from '../../../../models/access-token'; import { pack } from '../../../../models/app'; +import { ILocalUser } from '../../../../models/user'; /** * Get authorized apps of my account */ -module.exports = (params, user) => new Promise(async (res, rej) => { +module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => { // Get 'limit' parameter const [limit = 10, limitErr] = $.num.optional().range(1, 100).get(params.limit); if (limitErr) return rej('invalid limit param'); diff --git a/src/server/api/endpoints/i/change_password.ts b/src/server/api/endpoints/i/change_password.ts index a1a1a43406..9851fa895a 100644 --- a/src/server/api/endpoints/i/change_password.ts +++ b/src/server/api/endpoints/i/change_password.ts @@ -1,14 +1,11 @@ -/** - * Module dependencies - */ import $ from 'cafy'; import * as bcrypt from 'bcryptjs'; -import User from '../../../../models/user'; +import User, { ILocalUser } from '../../../../models/user'; /** * Change password */ -module.exports = async (params, user) => new Promise(async (res, rej) => { +module.exports = async (params: any, user: ILocalUser) => new Promise(async (res, rej) => { // Get 'currentPasword' parameter const [currentPassword, currentPasswordErr] = $.str.get(params.currentPasword); if (currentPasswordErr) return rej('invalid currentPasword param'); diff --git a/src/server/api/endpoints/i/favorites.ts b/src/server/api/endpoints/i/favorites.ts index 23517baaff..dc343afaed 100644 --- a/src/server/api/endpoints/i/favorites.ts +++ b/src/server/api/endpoints/i/favorites.ts @@ -1,13 +1,11 @@ -/** - * Module dependencies - */ import $ from 'cafy'; import ID from '../../../../cafy-id'; import Favorite, { pack } from '../../../../models/favorite'; +import { ILocalUser } from '../../../../models/user'; /** * Get favorited notes */ -module.exports = (params, user) => new Promise(async (res, rej) => { +module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => { // Get 'limit' parameter const [limit = 10, limitErr] = $.num.optional().range(1, 100).get(params.limit); if (limitErr) return rej('invalid limit param'); diff --git a/src/server/api/endpoints/i/notifications.ts b/src/server/api/endpoints/i/notifications.ts index ba9c47508c..ce283fe48f 100644 --- a/src/server/api/endpoints/i/notifications.ts +++ b/src/server/api/endpoints/i/notifications.ts @@ -1,17 +1,15 @@ -/** - * Module dependencies - */ import $ from 'cafy'; import ID from '../../../../cafy-id'; import Notification from '../../../../models/notification'; import Mute from '../../../../models/mute'; import { pack } from '../../../../models/notification'; import { getFriendIds } from '../../common/get-friends'; import read from '../../common/read-notification'; +import { ILocalUser } from '../../../../models/user'; /** * Get notifications */ -module.exports = (params, user) => new Promise(async (res, rej) => { +module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => { // Get 'following' parameter const [following = false, followingError] = $.bool.optional().get(params.following); diff --git a/src/server/api/endpoints/i/pin.ts b/src/server/api/endpoints/i/pin.ts index 423f0ac4ae..7f4a45e1f5 100644 --- a/src/server/api/endpoints/i/pin.ts +++ b/src/server/api/endpoints/i/pin.ts @@ -1,15 +1,12 @@ -/** - * Module dependencies - */ import $ from 'cafy'; import ID from '../../../../cafy-id'; -import User from '../../../../models/user'; +import User, { ILocalUser } from '../../../../models/user'; import Note from '../../../../models/note'; import { pack } from '../../../../models/user'; /** * Pin note */ -module.exports = async (params, user) => new Promise(async (res, rej) => { +module.exports = async (params: any, user: ILocalUser) => new Promise(async (res, rej) => { // Get 'noteId' parameter const [noteId, noteIdErr] = $.type(ID).get(params.noteId); if (noteIdErr) return rej('invalid noteId param'); diff --git a/src/server/api/endpoints/i/regenerate_token.ts b/src/server/api/endpoints/i/regenerate_token.ts index 6e1e571297..3ffab5428e 100644 --- a/src/server/api/endpoints/i/regenerate_token.ts +++ b/src/server/api/endpoints/i/regenerate_token.ts @@ -1,16 +1,13 @@ -/** - * Module dependencies - */ import $ from 'cafy'; import * as bcrypt from 'bcryptjs'; -import User from '../../../../models/user'; +import User, { ILocalUser } from '../../../../models/user'; import event from '../../../../publishers/stream'; import generateUserToken from '../../common/generate-native-user-token'; /** * Regenerate native token */ -module.exports = async (params, user) => new Promise(async (res, rej) => { +module.exports = async (params: any, user: ILocalUser) => new Promise(async (res, rej) => { // Get 'password' parameter const [password, passwordErr] = $.str.get(params.password); if (passwordErr) return rej('invalid password param'); diff --git a/src/server/api/endpoints/i/signin_history.ts b/src/server/api/endpoints/i/signin_history.ts index 63a74b41b1..4ab9881f34 100644 --- a/src/server/api/endpoints/i/signin_history.ts +++ b/src/server/api/endpoints/i/signin_history.ts @@ -1,13 +1,11 @@ -/** - * Module dependencies - */ import $ from 'cafy'; import ID from '../../../../cafy-id'; import Signin, { pack } from '../../../../models/signin'; +import { ILocalUser } from '../../../../models/user'; /** * Get signin history of my account */ -module.exports = (params, user) => new Promise(async (res, rej) => { +module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => { // Get 'limit' parameter const [limit = 10, limitErr] = $.num.optional().range(1, 100).get(params.limit); if (limitErr) return rej('invalid limit param'); diff --git a/src/server/api/endpoints/i/update.ts b/src/server/api/endpoints/i/update.ts index 6e0c5b8515..57b050ebc4 100644 --- a/src/server/api/endpoints/i/update.ts +++ b/src/server/api/endpoints/i/update.ts @@ -1,61 +1,72 @@ -/** - * Module dependencies - */ import $ from 'cafy'; import ID from '../../../../cafy-id'; -import User, { isValidName, isValidDescription, isValidLocation, isValidBirthday, pack } from '../../../../models/user'; +import User, { isValidName, isValidDescription, isValidLocation, isValidBirthday, pack, ILocalUser } from '../../../../models/user'; import event from '../../../../publishers/stream'; import DriveFile from '../../../../models/drive-file'; +import acceptAllFollowRequests from '../../../../services/following/requests/accept-all'; +import { IApp } from '../../../../models/app'; /** * Update myself */ -module.exports = async (params, user, app) => new Promise(async (res, rej) => { +module.exports = async (params: any, user: ILocalUser, app: IApp) => new Promise(async (res, rej) => { const isSecure = user != null && app == null; + const updates = {} as any; + // Get 'name' parameter const [name, nameErr] = $.str.optional().nullable().pipe(isValidName).get(params.name); if (nameErr) return rej('invalid name param'); - if (name) user.name = name; + if (name) updates.name = name; // Get 'description' parameter const [description, descriptionErr] = $.str.optional().nullable().pipe(isValidDescription).get(params.description); if (descriptionErr) return rej('invalid description param'); - if (description !== undefined) user.description = description; + if (description !== undefined) updates.description = description; // Get 'location' parameter const [location, locationErr] = $.str.optional().nullable().pipe(isValidLocation).get(params.location); if (locationErr) return rej('invalid location param'); - if (location !== undefined) user.profile.location = location; + if (location !== undefined) updates['profile.location'] = location; // Get 'birthday' parameter const [birthday, birthdayErr] = $.str.optional().nullable().pipe(isValidBirthday).get(params.birthday); if (birthdayErr) return rej('invalid birthday param'); - if (birthday !== undefined) user.profile.birthday = birthday; + if (birthday !== undefined) updates['profile.birthday'] = birthday; // Get 'avatarId' parameter - const [avatarId, avatarIdErr] = $.type(ID).optional().get(params.avatarId); + const [avatarId, avatarIdErr] = $.type(ID).optional().nullable().get(params.avatarId); if (avatarIdErr) return rej('invalid avatarId param'); - if (avatarId) user.avatarId = avatarId; + if (avatarId !== undefined) updates.avatarId = avatarId; // Get 'bannerId' parameter - const [bannerId, bannerIdErr] = $.type(ID).optional().get(params.bannerId); + const [bannerId, bannerIdErr] = $.type(ID).optional().nullable().get(params.bannerId); if (bannerIdErr) return rej('invalid bannerId param'); - if (bannerId) user.bannerId = bannerId; + if (bannerId !== undefined) updates.bannerId = bannerId; + + // Get 'wallpaperId' parameter + const [wallpaperId, wallpaperIdErr] = $.type(ID).optional().nullable().get(params.wallpaperId); + if (wallpaperIdErr) return rej('invalid wallpaperId param'); + if (wallpaperId !== undefined) updates.wallpaperId = wallpaperId; + + // Get 'isLocked' parameter + const [isLocked, isLockedErr] = $.bool.optional().get(params.isLocked); + if (isLockedErr) return rej('invalid isLocked param'); + if (isLocked != null) updates.isLocked = isLocked; // Get 'isBot' parameter const [isBot, isBotErr] = $.bool.optional().get(params.isBot); if (isBotErr) return rej('invalid isBot param'); - if (isBot != null) user.isBot = isBot; + if (isBot != null) updates.isBot = isBot; // Get 'isCat' parameter const [isCat, isCatErr] = $.bool.optional().get(params.isCat); if (isCatErr) return rej('invalid isCat param'); - if (isCat != null) user.isCat = isCat; + if (isCat != null) updates.isCat = isCat; // Get 'autoWatch' parameter const [autoWatch, autoWatchErr] = $.bool.optional().get(params.autoWatch); if (autoWatchErr) return rej('invalid autoWatch param'); - if (autoWatch != null) user.settings.autoWatch = autoWatch; + if (autoWatch != null) updates['settings.autoWatch'] = autoWatch; if (avatarId) { const avatar = await DriveFile.findOne({ @@ -63,7 +74,7 @@ module.exports = async (params, user, app) => new Promise(async (res, rej) => { }); if (avatar != null && avatar.metadata.properties.avgColor) { - user.avatarColor = avatar.metadata.properties.avgColor; + updates.avatarColor = avatar.metadata.properties.avgColor; } } @@ -73,27 +84,26 @@ module.exports = async (params, user, app) => new Promise(async (res, rej) => { }); if (banner != null && banner.metadata.properties.avgColor) { - user.bannerColor = banner.metadata.properties.avgColor; + updates.bannerColor = banner.metadata.properties.avgColor; } } - await User.update(user._id, { - $set: { - name: user.name, - description: user.description, - avatarId: user.avatarId, - avatarColor: user.avatarColor, - bannerId: user.bannerId, - bannerColor: user.bannerColor, - profile: user.profile, - isBot: user.isBot, - isCat: user.isCat, - settings: user.settings + if (wallpaperId) { + const wallpaper = await DriveFile.findOne({ + _id: wallpaperId + }); + + if (wallpaper != null && wallpaper.metadata.properties.avgColor) { + updates.wallpaperColor = wallpaper.metadata.properties.avgColor; } + } + + await User.update(user._id, { + $set: updates }); // Serialize - const iObj = await pack(user, user, { + const iObj = await pack(user._id, user, { detail: true, includeSecrets: isSecure }); @@ -101,6 +111,11 @@ module.exports = async (params, user, app) => new Promise(async (res, rej) => { // Send response res(iObj); - // Publish i updated event - event(user._id, 'i_updated', iObj); + // Publish meUpdated event + event(user._id, 'meUpdated', iObj); + + // 鍵垢を解除したとき、溜まっていたフォローリクエストがあるならすべて承認 + if (user.isLocked && isLocked === false) { + acceptAllFollowRequests(user); + } }); diff --git a/src/server/api/endpoints/i/update_client_setting.ts b/src/server/api/endpoints/i/update_client_setting.ts index e91d7565fd..6d6e8ed24a 100644 --- a/src/server/api/endpoints/i/update_client_setting.ts +++ b/src/server/api/endpoints/i/update_client_setting.ts @@ -1,14 +1,11 @@ -/** - * Module dependencies - */ import $ from 'cafy'; -import User from '../../../../models/user'; +import User, { ILocalUser } from '../../../../models/user'; import event from '../../../../publishers/stream'; /** * Update myself */ -module.exports = async (params, user) => new Promise(async (res, rej) => { +module.exports = async (params: any, user: ILocalUser) => new Promise(async (res, rej) => { // Get 'name' parameter const [name, nameErr] = $.str.get(params.name); if (nameErr) return rej('invalid name param'); @@ -17,7 +14,7 @@ module.exports = async (params, user) => new Promise(async (res, rej) => { const [value, valueErr] = $.any.nullable().get(params.value); if (valueErr) return rej('invalid value param'); - const x = {}; + const x: any = {}; x[`clientSettings.${name}`] = value; await User.update(user._id, { diff --git a/src/server/api/endpoints/i/update_home.ts b/src/server/api/endpoints/i/update_home.ts index 8ce551957e..511a647d88 100644 --- a/src/server/api/endpoints/i/update_home.ts +++ b/src/server/api/endpoints/i/update_home.ts @@ -1,11 +1,8 @@ -/** - * Module dependencies - */ import $ from 'cafy'; -import User from '../../../../models/user'; +import User, { ILocalUser } from '../../../../models/user'; import event from '../../../../publishers/stream'; -module.exports = async (params, user) => new Promise(async (res, rej) => { +module.exports = async (params: any, user: ILocalUser) => new Promise(async (res, rej) => { // Get 'home' parameter const [home, homeErr] = $.arr( $.obj.strict() @@ -13,50 +10,16 @@ module.exports = async (params, user) => new Promise(async (res, rej) => { .have('id', $.str) .have('place', $.str) .have('data', $.obj)) - .optional() .get(params.home); if (homeErr) return rej('invalid home param'); - // Get 'id' parameter - const [id, idErr] = $.str.optional().get(params.id); - if (idErr) return rej('invalid id param'); + await User.update(user._id, { + $set: { + 'clientSettings.home': home + } + }); - // Get 'data' parameter - const [data, dataErr] = $.obj.optional().get(params.data); - if (dataErr) return rej('invalid data param'); + res(); - if (home) { - await User.update(user._id, { - $set: { - 'clientSettings.home': home - } - }); - - res(); - - event(user._id, 'home_updated', { - home - }); - } else { - if (id == null && data == null) return rej('you need to set id and data params if home param unset'); - - const _home = user.clientSettings.home; - const widget = _home.find(w => w.id == id); - - if (widget == null) return rej('widget not found'); - - widget.data = data; - - await User.update(user._id, { - $set: { - 'clientSettings.home': _home - } - }); - - res(); - - event(user._id, 'home_updated', { - id, data - }); - } + event(user._id, 'home_updated', home); }); diff --git a/src/server/api/endpoints/i/update_mobile_home.ts b/src/server/api/endpoints/i/update_mobile_home.ts index d79a77072b..b1f25624fd 100644 --- a/src/server/api/endpoints/i/update_mobile_home.ts +++ b/src/server/api/endpoints/i/update_mobile_home.ts @@ -1,60 +1,24 @@ -/** - * Module dependencies - */ import $ from 'cafy'; -import User from '../../../../models/user'; +import User, { ILocalUser } from '../../../../models/user'; import event from '../../../../publishers/stream'; -module.exports = async (params, user) => new Promise(async (res, rej) => { +module.exports = async (params: any, user: ILocalUser) => new Promise(async (res, rej) => { // Get 'home' parameter const [home, homeErr] = $.arr( $.obj.strict() .have('name', $.str) .have('id', $.str) .have('data', $.obj)) - .optional().get(params.home); + .get(params.home); if (homeErr) return rej('invalid home param'); - // Get 'id' parameter - const [id, idErr] = $.str.optional().get(params.id); - if (idErr) return rej('invalid id param'); + await User.update(user._id, { + $set: { + 'clientSettings.mobileHome': home + } + }); - // Get 'data' parameter - const [data, dataErr] = $.obj.optional().get(params.data); - if (dataErr) return rej('invalid data param'); + res(); - if (home) { - await User.update(user._id, { - $set: { - 'clientSettings.mobileHome': home - } - }); - - res(); - - event(user._id, 'mobile_home_updated', { - home - }); - } else { - if (id == null && data == null) return rej('you need to set id and data params if home param unset'); - - const _home = user.clientSettings.mobileHome || []; - const widget = _home.find(w => w.id == id); - - if (widget == null) return rej('widget not found'); - - widget.data = data; - - await User.update(user._id, { - $set: { - 'clientSettings.mobileHome': _home - } - }); - - res(); - - event(user._id, 'mobile_home_updated', { - id, data - }); - } + event(user._id, 'mobile_home_updated', home); }); diff --git a/src/server/api/endpoints/i/update_widget.ts b/src/server/api/endpoints/i/update_widget.ts new file mode 100644 index 0000000000..82bb04d1f4 --- /dev/null +++ b/src/server/api/endpoints/i/update_widget.ts @@ -0,0 +1,79 @@ +import $ from 'cafy'; +import User, { ILocalUser } from '../../../../models/user'; +import event from '../../../../publishers/stream'; + +module.exports = async (params: any, user: ILocalUser) => new Promise(async (res, rej) => { + // Get 'id' parameter + const [id, idErr] = $.str.get(params.id); + if (idErr) return rej('invalid id param'); + + // Get 'data' parameter + const [data, dataErr] = $.obj.get(params.data); + if (dataErr) return rej('invalid data param'); + + if (id == null && data == null) return rej('you need to set id and data params if home param unset'); + + let widget; + + //#region Desktop home + if (widget == null && user.clientSettings.home) { + const desktopHome = user.clientSettings.home; + widget = desktopHome.find((w: any) => w.id == id); + if (widget) { + widget.data = data; + + await User.update(user._id, { + $set: { + 'clientSettings.home': desktopHome + } + }); + } + } + //#endregion + + //#region Mobile home + if (widget == null && user.clientSettings.mobileHome) { + const mobileHome = user.clientSettings.mobileHome; + widget = mobileHome.find((w: any) => w.id == id); + if (widget) { + widget.data = data; + + await User.update(user._id, { + $set: { + 'clientSettings.mobileHome': mobileHome + } + }); + } + } + //#endregion + + //#region Deck + if (widget == null && user.clientSettings.deck && user.clientSettings.deck.columns) { + const deck = user.clientSettings.deck; + deck.columns.filter((c: any) => c.type == 'widgets').forEach((c: any) => { + c.widgets.forEach((w: any) => { + if (w.id == id) widget = w; + }); + }); + if (widget) { + widget.data = data; + + await User.update(user._id, { + $set: { + 'clientSettings.deck': deck + } + }); + } + } + //#endregion + + if (widget) { + event(user._id, 'widgetUpdated', { + id, data + }); + + res(); + } else { + rej('widget not found'); + } +}); diff --git a/src/server/api/endpoints/messaging/history.ts b/src/server/api/endpoints/messaging/history.ts index ec97642f17..713ba9dd7f 100644 --- a/src/server/api/endpoints/messaging/history.ts +++ b/src/server/api/endpoints/messaging/history.ts @@ -1,15 +1,13 @@ -/** - * Module dependencies - */ import $ from 'cafy'; import History from '../../../../models/messaging-history'; import Mute from '../../../../models/mute'; import { pack } from '../../../../models/messaging-message'; +import { ILocalUser } from '../../../../models/user'; /** * Show messaging history */ -module.exports = (params, user) => new Promise(async (res, rej) => { +module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => { // Get 'limit' parameter const [limit = 10, limitErr] = $.num.optional().range(1, 100).get(params.limit); if (limitErr) return rej('invalid limit param'); diff --git a/src/server/api/endpoints/messaging/messages.ts b/src/server/api/endpoints/messaging/messages.ts index 0338aba68a..3eb20ec06b 100644 --- a/src/server/api/endpoints/messaging/messages.ts +++ b/src/server/api/endpoints/messaging/messages.ts @@ -1,20 +1,13 @@ -/** - * Module dependencies - */ import $ from 'cafy'; import ID from '../../../../cafy-id'; import Message from '../../../../models/messaging-message'; -import User from '../../../../models/user'; +import User, { ILocalUser } from '../../../../models/user'; import { pack } from '../../../../models/messaging-message'; import read from '../../common/read-messaging-message'; /** * Get messages - * - * @param {any} params - * @param {any} user - * @return {Promise<any>} */ -module.exports = (params, user) => new Promise(async (res, rej) => { +module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => { // Get 'userId' parameter const [recipientId, recipientIdErr] = $.type(ID).get(params.userId); if (recipientIdErr) return rej('invalid userId param'); diff --git a/src/server/api/endpoints/messaging/messages/create.ts b/src/server/api/endpoints/messaging/messages/create.ts index db471839e7..b3e4f6a8cd 100644 --- a/src/server/api/endpoints/messaging/messages/create.ts +++ b/src/server/api/endpoints/messaging/messages/create.ts @@ -1,11 +1,8 @@ -/** - * Module dependencies - */ import $ from 'cafy'; import ID from '../../../../../cafy-id'; import Message from '../../../../../models/messaging-message'; import { isValidText } from '../../../../../models/messaging-message'; import History from '../../../../../models/messaging-history'; -import User from '../../../../../models/user'; +import User, { ILocalUser } from '../../../../../models/user'; import Mute from '../../../../../models/mute'; import DriveFile from '../../../../../models/drive-file'; import { pack } from '../../../../../models/messaging-message'; @@ -17,7 +14,7 @@ import config from '../../../../../config'; /** * Create a message */ -module.exports = (params, user) => new Promise(async (res, rej) => { +module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => { // Get 'userId' parameter const [recipientId, recipientIdErr] = $.type(ID).get(params.userId); if (recipientIdErr) return rej('invalid userId param'); @@ -91,6 +88,13 @@ module.exports = (params, user) => new Promise(async (res, rej) => { publishMessagingIndexStream(message.recipientId, 'message', messageObj); publishUserStream(message.recipientId, 'messaging_message', messageObj); + // Update flag + User.update({ _id: recipient._id }, { + $set: { + hasUnreadMessagingMessage: true + } + }); + // 3秒経っても(今回作成した)メッセージが既読にならなかったら「未読のメッセージがありますよ」イベントを発行する setTimeout(async () => { const freshMessage = await Message.findOne({ _id: message._id }, { isRead: true }); diff --git a/src/server/api/endpoints/messaging/unread.ts b/src/server/api/endpoints/messaging/unread.ts deleted file mode 100644 index 1d83af501d..0000000000 --- a/src/server/api/endpoints/messaging/unread.ts +++ /dev/null @@ -1,29 +0,0 @@ -/** - * Module dependencies - */ -import Message from '../../../../models/messaging-message'; -import Mute from '../../../../models/mute'; - -/** - * Get count of unread messages - */ -module.exports = (params, user) => new Promise(async (res, rej) => { - const mute = await Mute.find({ - muterId: user._id, - deletedAt: { $exists: false } - }); - const mutedUserIds = mute.map(m => m.muteeId); - - const count = await Message - .count({ - userId: { - $nin: mutedUserIds - }, - recipientId: user._id, - isRead: false - }); - - res({ - count: count - }); -}); diff --git a/src/server/api/endpoints/meta.ts b/src/server/api/endpoints/meta.ts index 0e9ecf47df..ce460d0b8b 100644 --- a/src/server/api/endpoints/meta.ts +++ b/src/server/api/endpoints/meta.ts @@ -38,7 +38,7 @@ const client = require('../../../../built/client/meta.json'); /** * Show core info */ -module.exports = (params) => new Promise(async (res, rej) => { +module.exports = (params: any) => new Promise(async (res, rej) => { const meta: any = (await Meta.findOne()) || {}; res({ diff --git a/src/server/api/endpoints/mute/create.ts b/src/server/api/endpoints/mute/create.ts index 534020c671..415745e2c3 100644 --- a/src/server/api/endpoints/mute/create.ts +++ b/src/server/api/endpoints/mute/create.ts @@ -1,14 +1,11 @@ -/** - * Module dependencies - */ import $ from 'cafy'; import ID from '../../../../cafy-id'; -import User from '../../../../models/user'; +import User, { ILocalUser } from '../../../../models/user'; import Mute from '../../../../models/mute'; /** * Mute a user */ -module.exports = (params, user) => new Promise(async (res, rej) => { +module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => { const muter = user; // Get 'userId' parameter diff --git a/src/server/api/endpoints/mute/delete.ts b/src/server/api/endpoints/mute/delete.ts index 949aff64ba..2d1d286585 100644 --- a/src/server/api/endpoints/mute/delete.ts +++ b/src/server/api/endpoints/mute/delete.ts @@ -1,14 +1,11 @@ -/** - * Module dependencies - */ import $ from 'cafy'; import ID from '../../../../cafy-id'; -import User from '../../../../models/user'; +import User, { ILocalUser } from '../../../../models/user'; import Mute from '../../../../models/mute'; /** * Unmute a user */ -module.exports = (params, user) => new Promise(async (res, rej) => { +module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => { const muter = user; // Get 'userId' parameter diff --git a/src/server/api/endpoints/mute/list.ts b/src/server/api/endpoints/mute/list.ts index cf89f7e959..8b0171be33 100644 --- a/src/server/api/endpoints/mute/list.ts +++ b/src/server/api/endpoints/mute/list.ts @@ -1,15 +1,12 @@ -/** - * Module dependencies - */ import $ from 'cafy'; import ID from '../../../../cafy-id'; import Mute from '../../../../models/mute'; -import { pack } from '../../../../models/user'; +import { pack, ILocalUser } from '../../../../models/user'; import { getFriendIds } from '../../common/get-friends'; /** * Get muted users of a user */ -module.exports = (params, me) => new Promise(async (res, rej) => { +module.exports = (params: any, me: ILocalUser) => new Promise(async (res, rej) => { // Get 'iknow' parameter const [iknow = false, iknowErr] = $.bool.optional().get(params.iknow); if (iknowErr) return rej('invalid iknow param'); diff --git a/src/server/api/endpoints/my/apps.ts b/src/server/api/endpoints/my/apps.ts index 086e0b8965..7687afd0c7 100644 --- a/src/server/api/endpoints/my/apps.ts +++ b/src/server/api/endpoints/my/apps.ts @@ -1,13 +1,11 @@ -/** - * Module dependencies - */ import $ from 'cafy'; import App, { pack } from '../../../../models/app'; +import { ILocalUser } from '../../../../models/user'; /** * Get my apps */ -module.exports = (params, user) => new Promise(async (res, rej) => { +module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => { // Get 'limit' parameter const [limit = 10, limitErr] = $.num.optional().range(1, 100).get(params.limit); if (limitErr) return rej('invalid limit param'); diff --git a/src/server/api/endpoints/notes.ts b/src/server/api/endpoints/notes.ts index 21946d1bd3..5554e53aa4 100644 --- a/src/server/api/endpoints/notes.ts +++ b/src/server/api/endpoints/notes.ts @@ -7,7 +7,7 @@ import Note, { pack } from '../../../models/note'; /** * Get all notes */ -module.exports = (params) => new Promise(async (res, rej) => { +module.exports = (params: any) => new Promise(async (res, rej) => { // Get 'local' parameter const [local, localErr] = $.bool.optional().get(params.local); if (localErr) return rej('invalid local param'); @@ -53,7 +53,9 @@ module.exports = (params) => new Promise(async (res, rej) => { const sort = { _id: -1 }; - const query = {} as any; + const query = { + visibility: 'public' + } as any; if (sinceId) { sort._id = 1; query._id = { diff --git a/src/server/api/endpoints/notes/conversation.ts b/src/server/api/endpoints/notes/conversation.ts index 02f7229ccf..b2bc6a2e72 100644 --- a/src/server/api/endpoints/notes/conversation.ts +++ b/src/server/api/endpoints/notes/conversation.ts @@ -1,13 +1,11 @@ -/** - * Module dependencies - */ import $ from 'cafy'; import ID from '../../../../cafy-id'; -import Note, { pack } from '../../../../models/note'; +import Note, { pack, INote } from '../../../../models/note'; +import { ILocalUser } from '../../../../models/user'; /** * Show conversation of a note */ -module.exports = (params, user) => new Promise(async (res, rej) => { +module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => { // Get 'noteId' parameter const [noteId, noteIdErr] = $.type(ID).get(params.noteId); if (noteIdErr) return rej('invalid noteId param'); @@ -29,10 +27,10 @@ module.exports = (params, user) => new Promise(async (res, rej) => { return rej('note not found'); } - const conversation = []; + const conversation: INote[] = []; let i = 0; - async function get(id) { + async function get(id: any) { i++; const p = await Note.findOne({ _id: id }); diff --git a/src/server/api/endpoints/notes/create.ts b/src/server/api/endpoints/notes/create.ts index 182359f637..64f3b5ce26 100644 --- a/src/server/api/endpoints/notes/create.ts +++ b/src/server/api/endpoints/notes/create.ts @@ -1,9 +1,6 @@ -/** - * Module dependencies - */ import $ from 'cafy'; import ID from '../../../../cafy-id'; import Note, { INote, isValidText, isValidCw, pack } from '../../../../models/note'; -import User, { ILocalUser } from '../../../../models/user'; +import User, { ILocalUser, IUser } from '../../../../models/user'; import DriveFile from '../../../../models/drive-file'; import create from '../../../../services/note/create'; import { IApp } from '../../../../models/app'; @@ -11,7 +8,7 @@ import { IApp } from '../../../../models/app'; /** * Create a note */ -module.exports = (params, user: ILocalUser, app: IApp) => new Promise(async (res, rej) => { +module.exports = (params: any, user: ILocalUser, app: IApp) => new Promise(async (res, rej) => { // Get 'visibility' parameter const [visibility = 'public', visibilityErr] = $.str.optional().or(['public', 'home', 'followers', 'specified', 'private']).get(params.visibility); if (visibilityErr) return rej('invalid visibility'); @@ -20,7 +17,7 @@ module.exports = (params, user: ILocalUser, app: IApp) => new Promise(async (res const [visibleUserIds, visibleUserIdsErr] = $.arr($.type(ID)).optional().unique().min(1).get(params.visibleUserIds); if (visibleUserIdsErr) return rej('invalid visibleUserIds'); - let visibleUsers = []; + let visibleUsers: IUser[] = []; if (visibleUserIds !== undefined) { visibleUsers = await Promise.all(visibleUserIds.map(id => User.findOne({ _id: id @@ -132,7 +129,7 @@ module.exports = (params, user: ILocalUser, app: IApp) => new Promise(async (res if (pollErr) return rej('invalid poll'); if (poll) { - (poll as any).choices = (poll as any).choices.map((choice, i) => ({ + (poll as any).choices = (poll as any).choices.map((choice: string, i: number) => ({ id: i, // IDを付与 text: choice.trim(), votes: 0 @@ -140,7 +137,7 @@ module.exports = (params, user: ILocalUser, app: IApp) => new Promise(async (res } // テキストが無いかつ添付ファイルが無いかつRenoteも無いかつ投票も無かったらエラー - if (text === undefined && files === null && renote === null && poll === undefined) { + if ((text === undefined || text === null) && files === null && renote === null && poll === undefined) { return rej('text, mediaIds, renoteId or poll is required'); } diff --git a/src/server/api/endpoints/notes/delete.ts b/src/server/api/endpoints/notes/delete.ts new file mode 100644 index 0000000000..70bcdbaab9 --- /dev/null +++ b/src/server/api/endpoints/notes/delete.ts @@ -0,0 +1,27 @@ +import $ from 'cafy'; import ID from '../../../../cafy-id'; +import Note from '../../../../models/note'; +import deleteNote from '../../../../services/note/delete'; +import { ILocalUser } from '../../../../models/user'; + +/** + * Delete a note + */ +module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => { + // Get 'noteId' parameter + const [noteId, noteIdErr] = $.type(ID).get(params.noteId); + if (noteIdErr) return rej('invalid noteId param'); + + // Fetch note + const note = await Note.findOne({ + _id: noteId, + userId: user._id + }); + + if (note === null) { + return rej('note not found'); + } + + await deleteNote(user, note); + + res(); +}); diff --git a/src/server/api/endpoints/notes/favorites/create.ts b/src/server/api/endpoints/notes/favorites/create.ts index 6832b52f75..23f7ac5f8d 100644 --- a/src/server/api/endpoints/notes/favorites/create.ts +++ b/src/server/api/endpoints/notes/favorites/create.ts @@ -1,14 +1,12 @@ -/** - * Module dependencies - */ import $ from 'cafy'; import ID from '../../../../../cafy-id'; import Favorite from '../../../../../models/favorite'; import Note from '../../../../../models/note'; +import { ILocalUser } from '../../../../../models/user'; /** * Favorite a note */ -module.exports = (params, user) => new Promise(async (res, rej) => { +module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => { // Get 'noteId' parameter const [noteId, noteIdErr] = $.type(ID).get(params.noteId); if (noteIdErr) return rej('invalid noteId param'); diff --git a/src/server/api/endpoints/notes/favorites/delete.ts b/src/server/api/endpoints/notes/favorites/delete.ts index 07112dae15..7d2d2b4cb5 100644 --- a/src/server/api/endpoints/notes/favorites/delete.ts +++ b/src/server/api/endpoints/notes/favorites/delete.ts @@ -1,14 +1,12 @@ -/** - * Module dependencies - */ import $ from 'cafy'; import ID from '../../../../../cafy-id'; import Favorite from '../../../../../models/favorite'; import Note from '../../../../../models/note'; +import { ILocalUser } from '../../../../../models/user'; /** * Unfavorite a note */ -module.exports = (params, user) => new Promise(async (res, rej) => { +module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => { // Get 'noteId' parameter const [noteId, noteIdErr] = $.type(ID).get(params.noteId); if (noteIdErr) return rej('invalid noteId param'); diff --git a/src/server/api/endpoints/notes/global-timeline.ts b/src/server/api/endpoints/notes/global-timeline.ts index d22a1763de..24ffdbcba7 100644 --- a/src/server/api/endpoints/notes/global-timeline.ts +++ b/src/server/api/endpoints/notes/global-timeline.ts @@ -1,15 +1,13 @@ -/** - * Module dependencies - */ import $ from 'cafy'; import ID from '../../../../cafy-id'; import Note from '../../../../models/note'; import Mute from '../../../../models/mute'; import { pack } from '../../../../models/note'; +import { ILocalUser } from '../../../../models/user'; /** * Get timeline of global */ -module.exports = async (params, user, app) => { +module.exports = async (params: any, user: ILocalUser) => { // Get 'limit' parameter const [limit = 10, limitErr] = $.num.optional().range(1, 100).get(params.limit); if (limitErr) throw 'invalid limit param'; @@ -35,10 +33,14 @@ module.exports = async (params, user, app) => { throw 'only one of sinceId, untilId, sinceDate, untilDate can be specified'; } + // Get 'mediaOnly' parameter + const [mediaOnly, mediaOnlyErr] = $.bool.optional().get(params.mediaOnly); + if (mediaOnlyErr) throw 'invalid mediaOnly param'; + // ミュートしているユーザーを取得 - const mutedUserIds = (await Mute.find({ + const mutedUserIds = user ? (await Mute.find({ muterId: user._id - })).map(m => m.muteeId); + })).map(m => m.muteeId) : null; //#region Construct query const sort = { @@ -46,17 +48,27 @@ module.exports = async (params, user, app) => { }; const query = { - // mute - userId: { + // public only + visibility: 'public' + } as any; + + if (mutedUserIds && mutedUserIds.length > 0) { + query.userId = { $nin: mutedUserIds - }, - '_reply.userId': { + }; + + query['_reply.userId'] = { $nin: mutedUserIds - }, - '_renote.userId': { + }; + + query['_renote.userId'] = { $nin: mutedUserIds - } - } as any; + }; + } + + if (mediaOnly) { + query.mediaIds = { $exists: true, $ne: [] }; + } if (sinceId) { sort._id = 1; diff --git a/src/server/api/endpoints/notes/local-timeline.ts b/src/server/api/endpoints/notes/local-timeline.ts index e7ebe5d960..48490638d2 100644 --- a/src/server/api/endpoints/notes/local-timeline.ts +++ b/src/server/api/endpoints/notes/local-timeline.ts @@ -1,15 +1,13 @@ -/** - * Module dependencies - */ import $ from 'cafy'; import ID from '../../../../cafy-id'; import Note from '../../../../models/note'; import Mute from '../../../../models/mute'; import { pack } from '../../../../models/note'; +import { ILocalUser } from '../../../../models/user'; /** * Get timeline of local */ -module.exports = async (params, user, app) => { +module.exports = async (params: any, user: ILocalUser) => { // Get 'limit' parameter const [limit = 10, limitErr] = $.num.optional().range(1, 100).get(params.limit); if (limitErr) throw 'invalid limit param'; @@ -35,10 +33,14 @@ module.exports = async (params, user, app) => { throw 'only one of sinceId, untilId, sinceDate, untilDate can be specified'; } + // Get 'mediaOnly' parameter + const [mediaOnly, mediaOnlyErr] = $.bool.optional().get(params.mediaOnly); + if (mediaOnlyErr) throw 'invalid mediaOnly param'; + // ミュートしているユーザーを取得 - const mutedUserIds = (await Mute.find({ + const mutedUserIds = user ? (await Mute.find({ muterId: user._id - })).map(m => m.muteeId); + })).map(m => m.muteeId) : null; //#region Construct query const sort = { @@ -46,21 +48,31 @@ module.exports = async (params, user, app) => { }; const query = { - // mute - userId: { - $nin: mutedUserIds - }, - '_reply.userId': { - $nin: mutedUserIds - }, - '_renote.userId': { - $nin: mutedUserIds - }, + // public only + visibility: 'public', // local '_user.host': null } as any; + if (mutedUserIds && mutedUserIds.length > 0) { + query.userId = { + $nin: mutedUserIds + }; + + query['_reply.userId'] = { + $nin: mutedUserIds + }; + + query['_renote.userId'] = { + $nin: mutedUserIds + }; + } + + if (mediaOnly) { + query.mediaIds = { $exists: true, $ne: [] }; + } + if (sinceId) { sort._id = 1; query._id = { diff --git a/src/server/api/endpoints/notes/mentions.ts b/src/server/api/endpoints/notes/mentions.ts index 163a6b4866..45511603af 100644 --- a/src/server/api/endpoints/notes/mentions.ts +++ b/src/server/api/endpoints/notes/mentions.ts @@ -1,19 +1,13 @@ -/** - * Module dependencies - */ import $ from 'cafy'; import ID from '../../../../cafy-id'; import Note from '../../../../models/note'; import { getFriendIds } from '../../common/get-friends'; import { pack } from '../../../../models/note'; +import { ILocalUser } from '../../../../models/user'; /** * Get mentions of myself - * - * @param {any} params - * @param {any} user - * @return {Promise<any>} */ -module.exports = (params, user) => new Promise(async (res, rej) => { +module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => { // Get 'following' parameter const [following = false, followingError] = $.bool.optional().get(params.following); diff --git a/src/server/api/endpoints/notes/polls/recommendation.ts b/src/server/api/endpoints/notes/polls/recommendation.ts index a272378d19..640140c3d1 100644 --- a/src/server/api/endpoints/notes/polls/recommendation.ts +++ b/src/server/api/endpoints/notes/polls/recommendation.ts @@ -1,14 +1,12 @@ -/** - * Module dependencies - */ import $ from 'cafy'; import Vote from '../../../../../models/poll-vote'; import Note, { pack } from '../../../../../models/note'; +import { ILocalUser } from '../../../../../models/user'; /** * Get recommended polls */ -module.exports = (params, user) => new Promise(async (res, rej) => { +module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => { // Get 'limit' parameter const [limit = 10, limitErr] = $.num.optional().range(1, 100).get(params.limit); if (limitErr) return rej('invalid limit param'); diff --git a/src/server/api/endpoints/notes/polls/vote.ts b/src/server/api/endpoints/notes/polls/vote.ts index f8f4515308..72ac6bb202 100644 --- a/src/server/api/endpoints/notes/polls/vote.ts +++ b/src/server/api/endpoints/notes/polls/vote.ts @@ -1,6 +1,3 @@ -/** - * Module dependencies - */ import $ from 'cafy'; import ID from '../../../../../cafy-id'; import Vote from '../../../../../models/poll-vote'; import Note from '../../../../../models/note'; @@ -8,11 +5,12 @@ import Watching from '../../../../../models/note-watching'; import watch from '../../../../../services/note/watch'; import { publishNoteStream } from '../../../../../publishers/stream'; import notify from '../../../../../publishers/notify'; +import { ILocalUser } from '../../../../../models/user'; /** * Vote poll of a note */ -module.exports = (params, user) => new Promise(async (res, rej) => { +module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => { // Get 'noteId' parameter const [noteId, noteIdErr] = $.type(ID).get(params.noteId); if (noteIdErr) return rej('invalid noteId param'); @@ -58,8 +56,8 @@ module.exports = (params, user) => new Promise(async (res, rej) => { // Send response res(); - const inc = {}; - inc[`poll.choices.${findWithAttr(note.poll.choices, 'id', choice)}.votes`] = 1; + const inc: any = {}; + inc[`poll.choices.${note.poll.choices.findIndex(c => c.id == choice)}.votes`] = 1; // Increment votes count await Note.update({ _id: note._id }, { @@ -100,12 +98,3 @@ module.exports = (params, user) => new Promise(async (res, rej) => { watch(user._id, note); } }); - -function findWithAttr(array, attr, value) { - for (let i = 0; i < array.length; i += 1) { - if (array[i][attr] === value) { - return i; - } - } - return -1; -} diff --git a/src/server/api/endpoints/notes/reactions.ts b/src/server/api/endpoints/notes/reactions.ts index 4ad952a7a1..d3b2d43432 100644 --- a/src/server/api/endpoints/notes/reactions.ts +++ b/src/server/api/endpoints/notes/reactions.ts @@ -1,18 +1,12 @@ -/** - * Module dependencies - */ import $ from 'cafy'; import ID from '../../../../cafy-id'; import Note from '../../../../models/note'; import Reaction, { pack } from '../../../../models/note-reaction'; +import { ILocalUser } from '../../../../models/user'; /** * Show reactions of a note - * - * @param {any} params - * @param {any} user - * @return {Promise<any>} */ -module.exports = (params, user) => new Promise(async (res, rej) => { +module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => { // Get 'noteId' parameter const [noteId, noteIdErr] = $.type(ID).get(params.noteId); if (noteIdErr) return rej('invalid noteId param'); diff --git a/src/server/api/endpoints/notes/reactions/create.ts b/src/server/api/endpoints/notes/reactions/create.ts index 21757cb427..33e457e308 100644 --- a/src/server/api/endpoints/notes/reactions/create.ts +++ b/src/server/api/endpoints/notes/reactions/create.ts @@ -1,15 +1,13 @@ -/** - * Module dependencies - */ import $ from 'cafy'; import ID from '../../../../../cafy-id'; import Note from '../../../../../models/note'; import create from '../../../../../services/note/reaction/create'; import { validateReaction } from '../../../../../models/note-reaction'; +import { ILocalUser } from '../../../../../models/user'; /** * React to a note */ -module.exports = (params, user) => new Promise(async (res, rej) => { +module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => { // Get 'noteId' parameter const [noteId, noteIdErr] = $.type(ID).get(params.noteId); if (noteIdErr) return rej('invalid noteId param'); diff --git a/src/server/api/endpoints/notes/reactions/delete.ts b/src/server/api/endpoints/notes/reactions/delete.ts index afb8629112..1f2d662511 100644 --- a/src/server/api/endpoints/notes/reactions/delete.ts +++ b/src/server/api/endpoints/notes/reactions/delete.ts @@ -1,14 +1,12 @@ -/** - * Module dependencies - */ import $ from 'cafy'; import ID from '../../../../../cafy-id'; import Reaction from '../../../../../models/note-reaction'; import Note from '../../../../../models/note'; +import { ILocalUser } from '../../../../../models/user'; /** * Unreact to a note */ -module.exports = (params, user) => new Promise(async (res, rej) => { +module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => { // Get 'noteId' parameter const [noteId, noteIdErr] = $.type(ID).get(params.noteId); if (noteIdErr) return rej('invalid noteId param'); @@ -45,7 +43,7 @@ module.exports = (params, user) => new Promise(async (res, rej) => { // Send response res(); - const dec = {}; + const dec: any = {}; dec[`reactionCounts.${exist.reaction}`] = -1; // Decrement reactions count diff --git a/src/server/api/endpoints/notes/replies.ts b/src/server/api/endpoints/notes/replies.ts index 11d221d8f7..4aaf1d322b 100644 --- a/src/server/api/endpoints/notes/replies.ts +++ b/src/server/api/endpoints/notes/replies.ts @@ -1,17 +1,11 @@ -/** - * Module dependencies - */ import $ from 'cafy'; import ID from '../../../../cafy-id'; import Note, { pack } from '../../../../models/note'; +import { ILocalUser } from '../../../../models/user'; /** - * Show a replies of a note - * - * @param {any} params - * @param {any} user - * @return {Promise<any>} + * Get replies of a note */ -module.exports = (params, user) => new Promise(async (res, rej) => { +module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => { // Get 'noteId' parameter const [noteId, noteIdErr] = $.type(ID).get(params.noteId); if (noteIdErr) return rej('invalid noteId param'); @@ -24,10 +18,6 @@ module.exports = (params, user) => new Promise(async (res, rej) => { const [offset = 0, offsetErr] = $.num.optional().min(0).get(params.offset); if (offsetErr) return rej('invalid offset param'); - // Get 'sort' parameter - const [sort = 'desc', sortError] = $.str.optional().or('desc asc').get(params.sort); - if (sortError) return rej('invalid sort param'); - // Lookup note const note = await Note.findOne({ _id: noteId @@ -37,17 +27,8 @@ module.exports = (params, user) => new Promise(async (res, rej) => { return rej('note not found'); } - // Issue query - const replies = await Note - .find({ replyId: note._id }, { - limit: limit, - skip: offset, - sort: { - _id: sort == 'asc' ? 1 : -1 - } - }); + const ids = (note._replyIds || []).slice(offset, offset + limit); // Serialize - res(await Promise.all(replies.map(async note => - await pack(note, user)))); + res(await Promise.all(ids.map(id => pack(id, user)))); }); diff --git a/src/server/api/endpoints/notes/reposts.ts b/src/server/api/endpoints/notes/reposts.ts index 3098211b61..ea3f174e1a 100644 --- a/src/server/api/endpoints/notes/reposts.ts +++ b/src/server/api/endpoints/notes/reposts.ts @@ -1,17 +1,11 @@ -/** - * Module dependencies - */ import $ from 'cafy'; import ID from '../../../../cafy-id'; import Note, { pack } from '../../../../models/note'; +import { ILocalUser } from '../../../../models/user'; /** * Show a renotes of a note - * - * @param {any} params - * @param {any} user - * @return {Promise<any>} */ -module.exports = (params, user) => new Promise(async (res, rej) => { +module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => { // Get 'noteId' parameter const [noteId, noteIdErr] = $.type(ID).get(params.noteId); if (noteIdErr) return rej('invalid noteId param'); diff --git a/src/server/api/endpoints/notes/search.ts b/src/server/api/endpoints/notes/search_by_tag.ts index 9705dcfd6e..9be7cfffb6 100644 --- a/src/server/api/endpoints/notes/search.ts +++ b/src/server/api/endpoints/notes/search_by_tag.ts @@ -1,25 +1,17 @@ -/** - * Module dependencies - */ import $ from 'cafy'; import ID from '../../../../cafy-id'; -const escapeRegexp = require('escape-regexp'); import Note from '../../../../models/note'; -import User from '../../../../models/user'; +import User, { ILocalUser } from '../../../../models/user'; import Mute from '../../../../models/mute'; import { getFriendIds } from '../../common/get-friends'; import { pack } from '../../../../models/note'; /** - * Search a note - * - * @param {any} params - * @param {any} me - * @return {Promise<any>} + * Search notes by tag */ -module.exports = (params, me) => new Promise(async (res, rej) => { - // Get 'text' parameter - const [text, textError] = $.str.optional().get(params.text); - if (textError) return rej('invalid text param'); +module.exports = (params: any, me: ILocalUser) => new Promise(async (res, rej) => { + // Get 'tag' parameter + const [tag, tagError] = $.str.get(params.tag); + if (tagError) return rej('invalid tag param'); // Get 'includeUserIds' parameter const [includeUserIds = [], includeUserIdsErr] = $.arr($.type(ID)).optional().get(params.includeUserIds); @@ -77,7 +69,6 @@ module.exports = (params, me) => new Promise(async (res, rej) => { const [limit = 10, limitErr] = $.num.optional().range(1, 30).get(params.limit); if (limitErr) return rej('invalid limit param'); - let includeUsers = includeUserIds; if (includeUserUsernames != null) { const ids = (await Promise.all(includeUserUsernames.map(async (username) => { const _user = await User.findOne({ @@ -85,10 +76,10 @@ module.exports = (params, me) => new Promise(async (res, rej) => { }); return _user ? _user._id : null; }))).filter(id => id != null); - includeUsers = includeUsers.concat(ids); + + ids.forEach(id => includeUserIds.push(id)); } - let excludeUsers = excludeUserIds; if (excludeUserUsernames != null) { const ids = (await Promise.all(excludeUserUsernames.map(async (username) => { const _user = await User.findOne({ @@ -96,50 +87,17 @@ module.exports = (params, me) => new Promise(async (res, rej) => { }); return _user ? _user._id : null; }))).filter(id => id != null); - excludeUsers = excludeUsers.concat(ids); - } - - search(res, rej, me, text, includeUsers, excludeUsers, following, - mute, reply, renote, media, poll, sinceDate, untilDate, offset, limit); -}); -async function search( - res, rej, me, text, includeUserIds, excludeUserIds, following, - mute, reply, renote, media, poll, sinceDate, untilDate, offset, max) { + ids.forEach(id => excludeUserIds.push(id)); + } let q: any = { - $and: [] + $and: [{ + tagsLower: tag.toLowerCase() + }] }; - const push = x => q.$and.push(x); - - if (text) { - // 完全一致検索 - if (/"""(.+?)"""/.test(text)) { - const x = text.match(/"""(.+?)"""/)[1]; - push({ - text: x - }); - } else { - const tags = text.split(' ').filter(x => x[0] == '#'); - if (tags) { - push({ - $and: tags.map(x => ({ - tags: x - })) - }); - } - - push({ - $and: text.split(' ').map(x => ({ - // キーワードが-で始まる場合そのキーワードを除外する - text: x[0] == '-' ? { - $not: new RegExp(escapeRegexp(x.substr(1))) - } : new RegExp(escapeRegexp(x)) - })) - }); - } - } + const push = (x: any) => q.$and.push(x); if (includeUserIds && includeUserIds.length != 0) { push({ @@ -354,11 +312,10 @@ async function search( sort: { _id: -1 }, - limit: max, + limit: limit, skip: offset }); // Serialize - res(await Promise.all(notes.map(async note => - await pack(note, me)))); -} + res(await Promise.all(notes.map(note => pack(note, me)))); +}); diff --git a/src/server/api/endpoints/notes/show.ts b/src/server/api/endpoints/notes/show.ts index 78dc55a703..1ba7145996 100644 --- a/src/server/api/endpoints/notes/show.ts +++ b/src/server/api/endpoints/notes/show.ts @@ -1,17 +1,11 @@ -/** - * Module dependencies - */ import $ from 'cafy'; import ID from '../../../../cafy-id'; import Note, { pack } from '../../../../models/note'; +import { ILocalUser } from '../../../../models/user'; /** * Show a note - * - * @param {any} params - * @param {any} user - * @return {Promise<any>} */ -module.exports = (params, user) => new Promise(async (res, rej) => { +module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => { // Get 'noteId' parameter const [noteId, noteIdErr] = $.type(ID).get(params.noteId); if (noteIdErr) return rej('invalid noteId param'); diff --git a/src/server/api/endpoints/notes/timeline.ts b/src/server/api/endpoints/notes/timeline.ts index 9f32555649..18c0acd379 100644 --- a/src/server/api/endpoints/notes/timeline.ts +++ b/src/server/api/endpoints/notes/timeline.ts @@ -1,16 +1,14 @@ -/** - * Module dependencies - */ import $ from 'cafy'; import ID from '../../../../cafy-id'; import Note from '../../../../models/note'; import Mute from '../../../../models/mute'; import { getFriends } from '../../common/get-friends'; import { pack } from '../../../../models/note'; +import { ILocalUser } from '../../../../models/user'; /** * Get timeline of myself */ -module.exports = async (params, user, app) => { +module.exports = async (params: any, user: ILocalUser) => { // Get 'limit' parameter const [limit = 10, limitErr] = $.num.optional().range(1, 100).get(params.limit); if (limitErr) throw 'invalid limit param'; @@ -44,6 +42,10 @@ module.exports = async (params, user, app) => { const [includeRenotedMyNotes = true, includeRenotedMyNotesErr] = $.bool.optional().get(params.includeRenotedMyNotes); if (includeRenotedMyNotesErr) throw 'invalid includeRenotedMyNotes param'; + // Get 'mediaOnly' parameter + const [mediaOnly, mediaOnlyErr] = $.bool.optional().get(params.mediaOnly); + if (mediaOnlyErr) throw 'invalid mediaOnly param'; + const [followings, mutedUserIds] = await Promise.all([ // フォローを取得 // Fetch following @@ -137,6 +139,12 @@ module.exports = async (params, user, app) => { }); } + if (mediaOnly) { + query.$and.push({ + mediaIds: { $exists: true, $ne: [] } + }); + } + if (sinceId) { sort._id = 1; query._id = { diff --git a/src/server/api/endpoints/notes/trend.ts b/src/server/api/endpoints/notes/trend.ts index 4735bec51e..9c0a1bb112 100644 --- a/src/server/api/endpoints/notes/trend.ts +++ b/src/server/api/endpoints/notes/trend.ts @@ -1,18 +1,12 @@ -/** - * Module dependencies - */ const ms = require('ms'); import $ from 'cafy'; import Note, { pack } from '../../../../models/note'; +import { ILocalUser } from '../../../../models/user'; /** * Get trend notes - * - * @param {any} params - * @param {any} user - * @return {Promise<any>} */ -module.exports = (params, user) => new Promise(async (res, rej) => { +module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => { // Get 'limit' parameter const [limit = 10, limitErr] = $.num.optional().range(1, 100).get(params.limit); if (limitErr) return rej('invalid limit param'); diff --git a/src/server/api/endpoints/notes/user-list-timeline.ts b/src/server/api/endpoints/notes/user-list-timeline.ts index 9f8397d679..8aa800b712 100644 --- a/src/server/api/endpoints/notes/user-list-timeline.ts +++ b/src/server/api/endpoints/notes/user-list-timeline.ts @@ -1,16 +1,14 @@ -/** - * Module dependencies - */ import $ from 'cafy'; import ID from '../../../../cafy-id'; import Note from '../../../../models/note'; import Mute from '../../../../models/mute'; import { pack } from '../../../../models/note'; import UserList from '../../../../models/user-list'; +import { ILocalUser } from '../../../../models/user'; /** * Get timeline of a user list */ -module.exports = async (params, user, app) => { +module.exports = async (params: any, user: ILocalUser) => { // Get 'limit' parameter const [limit = 10, limitErr] = $.num.optional().range(1, 100).get(params.limit); if (limitErr) throw 'invalid limit param'; @@ -44,6 +42,10 @@ module.exports = async (params, user, app) => { const [includeRenotedMyNotes = true, includeRenotedMyNotesErr] = $.bool.optional().get(params.includeRenotedMyNotes); if (includeRenotedMyNotesErr) throw 'invalid includeRenotedMyNotes param'; + // Get 'mediaOnly' parameter + const [mediaOnly, mediaOnlyErr] = $.bool.optional().get(params.mediaOnly); + if (mediaOnlyErr) throw 'invalid mediaOnly param'; + // Get 'listId' parameter const [listId, listIdErr] = $.type(ID).get(params.listId); if (listIdErr) throw 'invalid listId param'; @@ -146,6 +148,12 @@ module.exports = async (params, user, app) => { }); } + if (mediaOnly) { + query.$and.push({ + mediaIds: { $exists: true, $ne: [] } + }); + } + if (sinceId) { sort._id = 1; query._id = { diff --git a/src/server/api/endpoints/notifications/get_unread_count.ts b/src/server/api/endpoints/notifications/get_unread_count.ts deleted file mode 100644 index 9766366ff1..0000000000 --- a/src/server/api/endpoints/notifications/get_unread_count.ts +++ /dev/null @@ -1,28 +0,0 @@ -/** - * Module dependencies - */ -import Notification from '../../../../models/notification'; -import Mute from '../../../../models/mute'; - -/** - * Get count of unread notifications - */ -module.exports = (params, user) => new Promise(async (res, rej) => { - const mute = await Mute.find({ - muterId: user._id - }); - const mutedUserIds = mute.map(m => m.muteeId); - - const count = await Notification - .count({ - notifieeId: user._id, - notifierId: { - $nin: mutedUserIds - }, - isRead: false - }); - - res({ - count: count - }); -}); diff --git a/src/server/api/endpoints/notifications/mark_as_read_all.ts b/src/server/api/endpoints/notifications/mark_as_read_all.ts index dce3cb4663..faaaf65a2d 100644 --- a/src/server/api/endpoints/notifications/mark_as_read_all.ts +++ b/src/server/api/endpoints/notifications/mark_as_read_all.ts @@ -1,13 +1,11 @@ -/** - * Module dependencies - */ import Notification from '../../../../models/notification'; import event from '../../../../publishers/stream'; +import User, { ILocalUser } from '../../../../models/user'; /** * Mark as read all notifications */ -module.exports = (params, user) => new Promise(async (res, rej) => { +module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => { // Update documents await Notification.update({ notifieeId: user._id, @@ -23,6 +21,13 @@ module.exports = (params, user) => new Promise(async (res, rej) => { // Response res(); + // Update flag + User.update({ _id: user._id }, { + $set: { + hasUnreadNotification: false + } + }); + // 全ての通知を読みましたよというイベントを発行 event(user._id, 'read_all_notifications'); }); diff --git a/src/server/api/endpoints/othello/match/cancel.ts b/src/server/api/endpoints/othello/match/cancel.ts deleted file mode 100644 index 562e691061..0000000000 --- a/src/server/api/endpoints/othello/match/cancel.ts +++ /dev/null @@ -1,9 +0,0 @@ -import Matching from '../../../../../models/othello-matching'; - -module.exports = (params, user) => new Promise(async (res, rej) => { - await Matching.remove({ - parentId: user._id - }); - - res(); -}); diff --git a/src/server/api/endpoints/othello/games.ts b/src/server/api/endpoints/reversi/games.ts index 2320a34b04..1455f191f7 100644 --- a/src/server/api/endpoints/othello/games.ts +++ b/src/server/api/endpoints/reversi/games.ts @@ -1,7 +1,8 @@ import $ from 'cafy'; import ID from '../../../../cafy-id'; -import OthelloGame, { pack } from '../../../../models/othello-game'; +import ReversiGame, { pack } from '../../../../models/reversi-game'; +import { ILocalUser } from '../../../../models/user'; -module.exports = (params, user) => new Promise(async (res, rej) => { +module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => { // Get 'my' parameter const [my = false, myErr] = $.bool.optional().get(params.my); if (myErr) return rej('invalid my param'); @@ -50,7 +51,7 @@ module.exports = (params, user) => new Promise(async (res, rej) => { } // Fetch games - const games = await OthelloGame.find(q, { + const games = await ReversiGame.find(q, { sort, limit }); diff --git a/src/server/api/endpoints/othello/games/show.ts b/src/server/api/endpoints/reversi/games/show.ts index 6b2f5ce137..d70ee547a2 100644 --- a/src/server/api/endpoints/othello/games/show.ts +++ b/src/server/api/endpoints/reversi/games/show.ts @@ -1,19 +1,20 @@ import $ from 'cafy'; import ID from '../../../../../cafy-id'; -import OthelloGame, { pack } from '../../../../../models/othello-game'; -import Othello from '../../../../../othello/core'; +import ReversiGame, { pack } from '../../../../../models/reversi-game'; +import Reversi from '../../../../../reversi/core'; +import { ILocalUser } from '../../../../../models/user'; -module.exports = (params, user) => new Promise(async (res, rej) => { +module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => { // Get 'gameId' parameter const [gameId, gameIdErr] = $.type(ID).get(params.gameId); if (gameIdErr) return rej('invalid gameId param'); - const game = await OthelloGame.findOne({ _id: gameId }); + const game = await ReversiGame.findOne({ _id: gameId }); if (game == null) { return rej('game not found'); } - const o = new Othello(game.settings.map, { + const o = new Reversi(game.settings.map, { isLlotheo: game.settings.isLlotheo, canPutEverywhere: game.settings.canPutEverywhere, loopedBoard: game.settings.loopedBoard diff --git a/src/server/api/endpoints/othello/invitations.ts b/src/server/api/endpoints/reversi/invitations.ts index 4761537614..d7727071ae 100644 --- a/src/server/api/endpoints/othello/invitations.ts +++ b/src/server/api/endpoints/reversi/invitations.ts @@ -1,6 +1,7 @@ -import Matching, { pack as packMatching } from '../../../../models/othello-matching'; +import Matching, { pack as packMatching } from '../../../../models/reversi-matching'; +import { ILocalUser } from '../../../../models/user'; -module.exports = (params, user) => new Promise(async (res, rej) => { +module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => { // Find session const invitations = await Matching.find({ childId: user._id diff --git a/src/server/api/endpoints/othello/match.ts b/src/server/api/endpoints/reversi/match.ts index e70e579755..907df7cf43 100644 --- a/src/server/api/endpoints/othello/match.ts +++ b/src/server/api/endpoints/reversi/match.ts @@ -1,11 +1,11 @@ import $ from 'cafy'; import ID from '../../../../cafy-id'; -import Matching, { pack as packMatching } from '../../../../models/othello-matching'; -import OthelloGame, { pack as packGame } from '../../../../models/othello-game'; -import User from '../../../../models/user'; -import publishUserStream, { publishOthelloStream } from '../../../../publishers/stream'; -import { eighteight } from '../../../../othello/maps'; +import Matching, { pack as packMatching } from '../../../../models/reversi-matching'; +import ReversiGame, { pack as packGame } from '../../../../models/reversi-game'; +import User, { ILocalUser } from '../../../../models/user'; +import publishUserStream, { publishReversiStream } from '../../../../publishers/stream'; +import { eighteight } from '../../../../reversi/maps'; -module.exports = (params, user) => new Promise(async (res, rej) => { +module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => { // Get 'userId' parameter const [childId, childIdErr] = $.type(ID).get(params.userId); if (childIdErr) return rej('invalid userId param'); @@ -28,7 +28,7 @@ module.exports = (params, user) => new Promise(async (res, rej) => { }); // Create game - const game = await OthelloGame.insert({ + const game = await ReversiGame.insert({ createdAt: new Date(), user1Id: exist.parentId, user2Id: user._id, @@ -47,14 +47,14 @@ module.exports = (params, user) => new Promise(async (res, rej) => { // Reponse res(await packGame(game, user)); - publishOthelloStream(exist.parentId, 'matched', await packGame(game, exist.parentId)); + publishReversiStream(exist.parentId, 'matched', await packGame(game, exist.parentId)); const other = await Matching.count({ childId: user._id }); if (other == 0) { - publishUserStream(user._id, 'othello_no_invites'); + publishUserStream(user._id, 'reversi_no_invites'); } } else { // Fetch child @@ -88,8 +88,8 @@ module.exports = (params, user) => new Promise(async (res, rej) => { const packed = await packMatching(matching, child); // 招待 - publishOthelloStream(child._id, 'invited', packed); + publishReversiStream(child._id, 'invited', packed); - publishUserStream(child._id, 'othello_invited', packed); + publishUserStream(child._id, 'reversi_invited', packed); } }); diff --git a/src/server/api/endpoints/reversi/match/cancel.ts b/src/server/api/endpoints/reversi/match/cancel.ts new file mode 100644 index 0000000000..1c9c799dbe --- /dev/null +++ b/src/server/api/endpoints/reversi/match/cancel.ts @@ -0,0 +1,10 @@ +import Matching from '../../../../../models/reversi-matching'; +import { ILocalUser } from '../../../../../models/user'; + +module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => { + await Matching.remove({ + parentId: user._id + }); + + res(); +}); diff --git a/src/server/api/endpoints/stats.ts b/src/server/api/endpoints/stats.ts index d1e17651f2..74ab6ba945 100644 --- a/src/server/api/endpoints/stats.ts +++ b/src/server/api/endpoints/stats.ts @@ -1,26 +1,10 @@ -import Note from '../../../models/note'; -import User from '../../../models/user'; +import Meta from '../../../models/meta'; /** * Get the misskey's statistics */ -module.exports = params => new Promise(async (res, rej) => { - const notesCount = await Note.count(); +module.exports = () => new Promise(async (res, rej) => { + const meta = await Meta.findOne(); - const usersCount = await User.count(); - - const originalNotesCount = await Note.count({ - '_user.host': null - }); - - const originalUsersCount = await User.count({ - host: null - }); - - res({ - notesCount, - usersCount, - originalNotesCount, - originalUsersCount - }); + res(meta.stats); }); diff --git a/src/server/api/endpoints/sw/register.ts b/src/server/api/endpoints/sw/register.ts index b22a8b08ef..f04a77fa4d 100644 --- a/src/server/api/endpoints/sw/register.ts +++ b/src/server/api/endpoints/sw/register.ts @@ -1,13 +1,11 @@ -/** - * Module dependencies - */ import $ from 'cafy'; import Subscription from '../../../../models/sw-subscription'; +import { ILocalUser } from '../../../../models/user'; /** * subscribe service worker */ -module.exports = async (params, user, app) => new Promise(async (res, rej) => { +module.exports = async (params: any, user: ILocalUser) => new Promise(async (res, rej) => { // Get 'endpoint' parameter const [endpoint, endpointErr] = $.str.get(params.endpoint); if (endpointErr) return rej('invalid endpoint param'); diff --git a/src/server/api/endpoints/username/available.ts b/src/server/api/endpoints/username/available.ts index b11bec4e58..aad3adc514 100644 --- a/src/server/api/endpoints/username/available.ts +++ b/src/server/api/endpoints/username/available.ts @@ -1,17 +1,11 @@ -/** - * Module dependencies - */ import $ from 'cafy'; import User from '../../../../models/user'; import { validateUsername } from '../../../../models/user'; /** * Check available username - * - * @param {any} params - * @return {Promise<any>} */ -module.exports = async (params) => new Promise(async (res, rej) => { +module.exports = async (params: any) => new Promise(async (res, rej) => { // Get 'username' parameter const [username, usernameError] = $.str.pipe(validateUsername).get(params.username); if (usernameError) return rej('invalid username param'); diff --git a/src/server/api/endpoints/users.ts b/src/server/api/endpoints/users.ts index eb581cb7e6..b8df6f3ecf 100644 --- a/src/server/api/endpoints/users.ts +++ b/src/server/api/endpoints/users.ts @@ -1,13 +1,10 @@ -/** - * Module dependencies - */ import $ from 'cafy'; -import User, { pack } from '../../../models/user'; +import User, { pack, ILocalUser } from '../../../models/user'; /** * Lists all users */ -module.exports = (params, me) => new Promise(async (res, rej) => { +module.exports = (params: any, me: ILocalUser) => new Promise(async (res, rej) => { // Get 'limit' parameter const [limit = 10, limitErr] = $.num.optional().range(1, 100).get(params.limit); if (limitErr) return rej('invalid limit param'); diff --git a/src/server/api/endpoints/users/followers.ts b/src/server/api/endpoints/users/followers.ts index 810cd7341b..53133ee969 100644 --- a/src/server/api/endpoints/users/followers.ts +++ b/src/server/api/endpoints/users/followers.ts @@ -1,8 +1,5 @@ -/** - * Module dependencies - */ import $ from 'cafy'; import ID from '../../../../cafy-id'; -import User from '../../../../models/user'; +import User, { ILocalUser } from '../../../../models/user'; import Following from '../../../../models/following'; import { pack } from '../../../../models/user'; import { getFriendIds } from '../../common/get-friends'; @@ -10,7 +7,7 @@ import { getFriendIds } from '../../common/get-friends'; /** * Get followers of a user */ -module.exports = (params, me) => new Promise(async (res, rej) => { +module.exports = (params: any, me: ILocalUser) => new Promise(async (res, rej) => { // Get 'userId' parameter const [userId, userIdErr] = $.type(ID).get(params.userId); if (userIdErr) return rej('invalid userId param'); diff --git a/src/server/api/endpoints/users/following.ts b/src/server/api/endpoints/users/following.ts index 3373b9d632..2061200198 100644 --- a/src/server/api/endpoints/users/following.ts +++ b/src/server/api/endpoints/users/following.ts @@ -1,20 +1,13 @@ -/** - * Module dependencies - */ import $ from 'cafy'; import ID from '../../../../cafy-id'; -import User from '../../../../models/user'; +import User, { ILocalUser } from '../../../../models/user'; import Following from '../../../../models/following'; import { pack } from '../../../../models/user'; import { getFriendIds } from '../../common/get-friends'; /** * Get following users of a user - * - * @param {any} params - * @param {any} me - * @return {Promise<any>} */ -module.exports = (params, me) => new Promise(async (res, rej) => { +module.exports = (params: any, me: ILocalUser) => new Promise(async (res, rej) => { // Get 'userId' parameter const [userId, userIdErr] = $.type(ID).get(params.userId); if (userIdErr) return rej('invalid userId param'); 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 64d737a06b..ba8779d334 100644 --- a/src/server/api/endpoints/users/get_frequently_replied_users.ts +++ b/src/server/api/endpoints/users/get_frequently_replied_users.ts @@ -1,11 +1,8 @@ -/** - * Module dependencies - */ import $ from 'cafy'; import ID from '../../../../cafy-id'; import Note from '../../../../models/note'; -import User, { pack } from '../../../../models/user'; +import User, { pack, ILocalUser } from '../../../../models/user'; -module.exports = (params, me) => new Promise(async (res, rej) => { +module.exports = (params: any, me: ILocalUser) => new Promise(async (res, rej) => { // Get 'userId' parameter const [userId, userIdErr] = $.type(ID).get(params.userId); if (userIdErr) return rej('invalid userId param'); @@ -64,7 +61,7 @@ module.exports = (params, me) => new Promise(async (res, rej) => { } }); - const repliedUsers = {}; + const repliedUsers: any = {}; // Extract replies from recent notes replyTargetNotes.forEach(note => { diff --git a/src/server/api/endpoints/users/lists/create.ts b/src/server/api/endpoints/users/lists/create.ts index 100a78b872..cdd1a0d813 100644 --- a/src/server/api/endpoints/users/lists/create.ts +++ b/src/server/api/endpoints/users/lists/create.ts @@ -1,13 +1,11 @@ -/** - * Module dependencies - */ import $ from 'cafy'; import UserList, { pack } from '../../../../../models/user-list'; +import { ILocalUser } from '../../../../../models/user'; /** * Create a user list */ -module.exports = async (params, user) => new Promise(async (res, rej) => { +module.exports = async (params: any, user: ILocalUser) => 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'); diff --git a/src/server/api/endpoints/users/lists/list.ts b/src/server/api/endpoints/users/lists/list.ts index d19339a1f5..bf8391d863 100644 --- a/src/server/api/endpoints/users/lists/list.ts +++ b/src/server/api/endpoints/users/lists/list.ts @@ -1,9 +1,10 @@ import UserList, { pack } from '../../../../../models/user-list'; +import { ILocalUser } from '../../../../../models/user'; /** * Add a user to a user list */ -module.exports = async (params, me) => new Promise(async (res, rej) => { +module.exports = async (params: any, me: ILocalUser) => new Promise(async (res, rej) => { // Fetch lists const userLists = await UserList.find({ userId: me._id, diff --git a/src/server/api/endpoints/users/lists/push.ts b/src/server/api/endpoints/users/lists/push.ts index da5a9a134c..d8a3b3c9aa 100644 --- a/src/server/api/endpoints/users/lists/push.ts +++ b/src/server/api/endpoints/users/lists/push.ts @@ -1,6 +1,6 @@ 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 User, { pack as packUser, isRemoteUser, getGhost, ILocalUser } from '../../../../../models/user'; import { publishUserListStream } from '../../../../../publishers/stream'; import ap from '../../../../../remote/activitypub/renderer'; import renderFollow from '../../../../../remote/activitypub/renderer/follow'; @@ -9,7 +9,7 @@ import { deliver } from '../../../../../queue'; /** * Add a user to a user list */ -module.exports = async (params, me) => new Promise(async (res, rej) => { +module.exports = async (params: any, me: ILocalUser) => new Promise(async (res, rej) => { // Get 'listId' parameter const [listId, listIdErr] = $.type(ID).get(params.listId); if (listIdErr) return rej('invalid listId param'); diff --git a/src/server/api/endpoints/users/lists/show.ts b/src/server/api/endpoints/users/lists/show.ts index 16cb3382fd..e4ae239613 100644 --- a/src/server/api/endpoints/users/lists/show.ts +++ b/src/server/api/endpoints/users/lists/show.ts @@ -1,10 +1,11 @@ import $ from 'cafy'; import ID from '../../../../../cafy-id'; import UserList, { pack } from '../../../../../models/user-list'; +import { ILocalUser } from '../../../../../models/user'; /** * Show a user list */ -module.exports = async (params, me) => new Promise(async (res, rej) => { +module.exports = async (params: any, me: ILocalUser) => new Promise(async (res, rej) => { // Get 'listId' parameter const [listId, listIdErr] = $.type(ID).get(params.listId); if (listIdErr) return rej('invalid listId param'); diff --git a/src/server/api/endpoints/users/notes.ts b/src/server/api/endpoints/users/notes.ts index 061c363d0f..222a8d950a 100644 --- a/src/server/api/endpoints/users/notes.ts +++ b/src/server/api/endpoints/users/notes.ts @@ -1,15 +1,12 @@ -/** - * Module dependencies - */ 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'; +import User, { ILocalUser } from '../../../../models/user'; /** * Get notes of a user */ -module.exports = (params, me) => new Promise(async (res, rej) => { +module.exports = (params: any, me: ILocalUser) => new Promise(async (res, rej) => { // Get 'userId' parameter const [userId, userIdErr] = $.type(ID).optional().get(params.userId); if (userIdErr) return rej('invalid userId param'); diff --git a/src/server/api/endpoints/users/recommendation.ts b/src/server/api/endpoints/users/recommendation.ts index 620ae17ca2..1d0d889f11 100644 --- a/src/server/api/endpoints/users/recommendation.ts +++ b/src/server/api/endpoints/users/recommendation.ts @@ -1,20 +1,13 @@ -/** - * Module dependencies - */ const ms = require('ms'); import $ from 'cafy'; -import User, { pack } from '../../../../models/user'; +import User, { pack, ILocalUser } from '../../../../models/user'; import { getFriendIds } from '../../common/get-friends'; import Mute from '../../../../models/mute'; /** * Get recommended users - * - * @param {any} params - * @param {any} me - * @return {Promise<any>} */ -module.exports = (params, me) => new Promise(async (res, rej) => { +module.exports = (params: any, me: ILocalUser) => new Promise(async (res, rej) => { // Get 'limit' parameter const [limit = 10, limitErr] = $.num.optional().range(1, 100).get(params.limit); if (limitErr) return rej('invalid limit param'); @@ -36,6 +29,7 @@ module.exports = (params, me) => new Promise(async (res, rej) => { _id: { $nin: followingIds.concat(mutedUserIds) }, + isLocked: false, $or: [{ 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 cfbdc337bf..e29c8d32f1 100644 --- a/src/server/api/endpoints/users/search.ts +++ b/src/server/api/endpoints/users/search.ts @@ -1,45 +1,25 @@ -/** - * Module dependencies - */ -import * as mongo from 'mongodb'; import $ from 'cafy'; -import User, { pack } from '../../../../models/user'; -import config from '../../../../config'; +import User, { pack, ILocalUser } from '../../../../models/user'; const escapeRegexp = require('escape-regexp'); /** * Search a user - * - * @param {any} params - * @param {any} me - * @return {Promise<any>} */ -module.exports = (params, me) => new Promise(async (res, rej) => { +module.exports = (params: any, me: ILocalUser) => new Promise(async (res, rej) => { // Get 'query' parameter const [query, queryError] = $.str.pipe(x => x != '').get(params.query); if (queryError) return rej('invalid query param'); - // Get 'offset' parameter - 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] = $.num.optional().range(1, 30).get(params.max); if (maxErr) return rej('invalid max param'); - // If Elasticsearch is available, search by $ - // If not, search by MongoDB - (config.elasticsearch.enable ? byElasticsearch : byNative) - (res, rej, me, query, offset, max); -}); - -// Search by MongoDB -async function byNative(res, rej, me, query, offset, max) { const escapedQuery = escapeRegexp(query); // Search users const users = await User .find({ + host: null, $or: [{ usernameLower: new RegExp(escapedQuery.replace('@', '').toLowerCase()) }, { @@ -50,49 +30,5 @@ async function byNative(res, rej, me, query, offset, max) { }); // Serialize - res(await Promise.all(users.map(async user => - await pack(user, me, { detail: true })))); -} - -// Search by Elasticsearch -async function byElasticsearch(res, rej, me, query, offset, max) { - const es = require('../../db/elasticsearch'); - - es.search({ - index: 'misskey', - type: 'user', - body: { - size: max, - from: offset, - query: { - simple_query_string: { - fields: ['username', 'name', 'bio'], - query: query, - default_operator: 'and' - } - } - } - }, async (error, response) => { - if (error) { - console.error(error); - return res(500); - } - - if (response.hits.total === 0) { - return res([]); - } - - const hits = response.hits.hits.map(hit => new mongo.ObjectID(hit._id)); - - const users = await User - .find({ - _id: { - $in: hits - } - }); - - // Serialize - res(await Promise.all(users.map(async user => - await pack(user, me, { detail: true })))); - }); -} + res(await Promise.all(users.map(user => pack(user, me, { detail: true })))); +}); diff --git a/src/server/api/endpoints/users/search_by_username.ts b/src/server/api/endpoints/users/search_by_username.ts index 5927d00faf..937f9af589 100644 --- a/src/server/api/endpoints/users/search_by_username.ts +++ b/src/server/api/endpoints/users/search_by_username.ts @@ -1,13 +1,10 @@ -/** - * Module dependencies - */ import $ from 'cafy'; -import User, { pack } from '../../../../models/user'; +import User, { pack, ILocalUser } from '../../../../models/user'; /** * Search a user by username */ -module.exports = (params, me) => new Promise(async (res, rej) => { +module.exports = (params: any, me: ILocalUser) => new Promise(async (res, rej) => { // Get 'query' parameter const [query, queryError] = $.str.get(params.query); if (queryError) return rej('invalid query param'); @@ -20,15 +17,27 @@ module.exports = (params, me) => new Promise(async (res, rej) => { const [limit = 10, limitErr] = $.num.optional().range(1, 100).get(params.limit); if (limitErr) return rej('invalid limit param'); - const users = await User + let users = await User .find({ + host: null, usernameLower: new RegExp(query.toLowerCase()) }, { limit: limit, skip: offset }); + if (users.length < limit) { + const remoteUsers = await User + .find({ + host: { $ne: null }, + usernameLower: new RegExp(query.toLowerCase()) + }, { + limit: limit - users.length + }); + + users = users.concat(remoteUsers); + } + // Serialize - res(await Promise.all(users.map(async user => - await pack(user, me, { detail: true })))); + res(await Promise.all(users.map(user => pack(user, me, { detail: true })))); }); diff --git a/src/server/api/endpoints/users/show.ts b/src/server/api/endpoints/users/show.ts index b8c6ff25c4..bf7e2a2312 100644 --- a/src/server/api/endpoints/users/show.ts +++ b/src/server/api/endpoints/users/show.ts @@ -1,8 +1,5 @@ -/** - * Module dependencies - */ import $ from 'cafy'; import ID from '../../../../cafy-id'; -import User, { pack } from '../../../../models/user'; +import User, { pack, ILocalUser } from '../../../../models/user'; import resolveRemoteUser from '../../../../remote/resolve-user'; const cursorOption = { fields: { data: false } }; @@ -10,7 +7,7 @@ const cursorOption = { fields: { data: false } }; /** * Show user(s) */ -module.exports = (params, me) => new Promise(async (res, rej) => { +module.exports = (params: any, me: ILocalUser) => new Promise(async (res, rej) => { let user; // Get 'userId' parameter @@ -49,7 +46,7 @@ module.exports = (params, me) => new Promise(async (res, rej) => { return rej('failed to resolve remote user'); } } else { - const q = userId !== undefined + const q: any = userId !== undefined ? { _id: userId } : { usernameLower: username.toLowerCase(), host: null }; |