From 2a9cba25a89b5cf2394a22696ee0fb67140076a9 Mon Sep 17 00:00:00 2001 From: syuilo Date: Fri, 3 Mar 2017 08:24:48 +0900 Subject: wip --- src/api/endpoints/messaging/history.js | 47 ------- src/api/endpoints/messaging/history.ts | 38 ++++++ src/api/endpoints/messaging/messages.js | 140 -------------------- src/api/endpoints/messaging/messages.ts | 133 +++++++++++++++++++ src/api/endpoints/messaging/messages/create.js | 169 ------------------------ src/api/endpoints/messaging/messages/create.ts | 147 +++++++++++++++++++++ src/api/endpoints/messaging/unread.js | 27 ---- src/api/endpoints/messaging/unread.ts | 27 ++++ src/api/endpoints/my/apps.js | 58 -------- src/api/endpoints/my/apps.ts | 45 +++++++ src/api/endpoints/notifications/mark_as_read.js | 53 -------- src/api/endpoints/notifications/mark_as_read.ts | 50 +++++++ 12 files changed, 440 insertions(+), 494 deletions(-) delete mode 100644 src/api/endpoints/messaging/history.js create mode 100644 src/api/endpoints/messaging/history.ts delete mode 100644 src/api/endpoints/messaging/messages.js create mode 100644 src/api/endpoints/messaging/messages.ts delete mode 100644 src/api/endpoints/messaging/messages/create.js create mode 100644 src/api/endpoints/messaging/messages/create.ts delete mode 100644 src/api/endpoints/messaging/unread.js create mode 100644 src/api/endpoints/messaging/unread.ts delete mode 100644 src/api/endpoints/my/apps.js create mode 100644 src/api/endpoints/my/apps.ts delete mode 100644 src/api/endpoints/notifications/mark_as_read.js create mode 100644 src/api/endpoints/notifications/mark_as_read.ts (limited to 'src/api/endpoints') diff --git a/src/api/endpoints/messaging/history.js b/src/api/endpoints/messaging/history.js deleted file mode 100644 index 60c34a6a41..0000000000 --- a/src/api/endpoints/messaging/history.js +++ /dev/null @@ -1,47 +0,0 @@ -'use strict'; - -/** - * Module dependencies - */ -import * as mongo from 'mongodb'; -import History from '../../models/messaging-history'; -import serialize from '../../serializers/messaging-message'; - -/** - * Show messaging history - * - * @param {any} params - * @param {any} user - * @return {Promise} - */ -module.exports = (params, user) => - new Promise(async (res, rej) => -{ - // Get 'limit' parameter - let limit = params.limit; - if (limit !== undefined && limit !== null) { - limit = parseInt(limit, 10); - - // From 1 to 100 - if (!(1 <= limit && limit <= 100)) { - return rej('invalid limit range'); - } - } else { - limit = 10; - } - - // Get history - const history = await History - .find({ - user_id: user._id - }, { - limit: limit, - sort: { - updated_at: -1 - } - }); - - // Serialize - res(await Promise.all(history.map(async h => - await serialize(h.message, user)))); -}); diff --git a/src/api/endpoints/messaging/history.ts b/src/api/endpoints/messaging/history.ts new file mode 100644 index 0000000000..07ad6e0f22 --- /dev/null +++ b/src/api/endpoints/messaging/history.ts @@ -0,0 +1,38 @@ +'use strict'; + +/** + * Module dependencies + */ +import it from '../../it'; +import History from '../../models/messaging-history'; +import serialize from '../../serializers/messaging-message'; + +/** + * Show messaging history + * + * @param {any} params + * @param {any} user + * @return {Promise} + */ +module.exports = (params, user) => + new Promise(async (res, rej) => +{ + // Get 'limit' parameter + const [limit, limitErr] = it(params.limit).expect.number().range(1, 100).default(10).qed(); + if (limitErr) return rej('invalid limit param'); + + // Get history + const history = await History + .find({ + user_id: user._id + }, { + limit: limit, + sort: { + updated_at: -1 + } + }); + + // Serialize + res(await Promise.all(history.map(async h => + await serialize(h.message, user)))); +}); diff --git a/src/api/endpoints/messaging/messages.js b/src/api/endpoints/messaging/messages.js deleted file mode 100644 index eaaf38c398..0000000000 --- a/src/api/endpoints/messaging/messages.js +++ /dev/null @@ -1,140 +0,0 @@ -'use strict'; - -/** - * Module dependencies - */ -import * as mongo from 'mongodb'; -import Message from '../../models/messaging-message'; -import User from '../../models/user'; -import serialize from '../../serializers/messaging-message'; -import publishUserStream from '../../event'; -import { publishMessagingStream } from '../../event'; - -/** - * Get messages - * - * @param {any} params - * @param {any} user - * @return {Promise} - */ -module.exports = (params, user) => - new Promise(async (res, rej) => -{ - // Get 'user_id' parameter - let recipient = params.user_id; - if (recipient !== undefined && recipient !== null) { - recipient = await User.findOne({ - _id: new mongo.ObjectID(recipient) - }, { - fields: { - _id: true - } - }); - - if (recipient === null) { - return rej('user not found'); - } - } else { - return rej('user_id is required'); - } - - // Get 'mark_as_read' parameter - let markAsRead = params.mark_as_read; - if (markAsRead == null) { - markAsRead = true; - } - - // Get 'limit' parameter - let limit = params.limit; - if (limit !== undefined && limit !== null) { - limit = parseInt(limit, 10); - - // From 1 to 100 - if (!(1 <= limit && limit <= 100)) { - return rej('invalid limit range'); - } - } else { - limit = 10; - } - - const since = params.since_id || null; - const max = params.max_id || null; - - // Check if both of since_id and max_id is specified - if (since !== null && max !== null) { - return rej('cannot set since_id and max_id'); - } - - const query = { - $or: [{ - user_id: user._id, - recipient_id: recipient._id - }, { - user_id: recipient._id, - recipient_id: user._id - }] - }; - - const sort = { - _id: -1 - }; - - if (since !== null) { - sort._id = 1; - query._id = { - $gt: new mongo.ObjectID(since) - }; - } else if (max !== null) { - query._id = { - $lt: new mongo.ObjectID(max) - }; - } - - // Issue query - const messages = await Message - .find(query, { - limit: limit, - sort: sort - }); - - // Serialize - res(await Promise.all(messages.map(async message => - await serialize(message, user, { - populateRecipient: false - })))); - - if (messages.length === 0) { - return; - } - - // Mark as read all - if (markAsRead) { - const ids = messages - .filter(m => m.is_read == false) - .filter(m => m.recipient_id.equals(user._id)) - .map(m => m._id); - - // Update documents - await Message.update({ - _id: { $in: ids } - }, { - $set: { is_read: true } - }, { - multi: true - }); - - // Publish event - publishMessagingStream(recipient._id, user._id, 'read', ids.map(id => id.toString())); - - const count = await Message - .count({ - recipient_id: user._id, - is_read: false - }); - - if (count == 0) { - // 全ての(いままで未読だった)メッセージを(これで)読みましたよというイベントを発行 - publishUserStream(user._id, 'read_all_messaging_messages'); - } - } -}); diff --git a/src/api/endpoints/messaging/messages.ts b/src/api/endpoints/messaging/messages.ts new file mode 100644 index 0000000000..81562efbcc --- /dev/null +++ b/src/api/endpoints/messaging/messages.ts @@ -0,0 +1,133 @@ +'use strict'; + +/** + * Module dependencies + */ +import it from '../../it'; +import Message from '../../models/messaging-message'; +import User from '../../models/user'; +import serialize from '../../serializers/messaging-message'; +import publishUserStream from '../../event'; +import { publishMessagingStream } from '../../event'; + +/** + * Get messages + * + * @param {any} params + * @param {any} user + * @return {Promise} + */ +module.exports = (params, user) => + new Promise(async (res, rej) => +{ + // Get 'user_id' parameter + const [recipientId, recipientIdErr] = it(params.user_id).expect.id().required().qed(); + if (recipientIdErr) return rej('invalid user_id param'); + + // Fetch recipient + const recipient = await User.findOne({ + _id: recipientId + }, { + fields: { + _id: true + } + }); + + if (recipient === null) { + return rej('user not found'); + } + + // Get 'mark_as_read' parameter + const [markAsRead, markAsReadErr] = it(params.mark_as_read).expect.boolean().default(true).qed(); + if (markAsReadErr) return rej('invalid mark_as_read param'); + + // Get 'limit' parameter + const [limit, limitErr] = it(params.limit).expect.number().range(1, 100).default(10).qed(); + if (limitErr) return rej('invalid limit param'); + + // Get 'since_id' parameter + const [sinceId, sinceIdErr] = it(params.since_id).expect.id().qed(); + if (sinceIdErr) return rej('invalid since_id param'); + + // Get 'max_id' parameter + const [maxId, maxIdErr] = it(params.max_id).expect.id().qed(); + if (maxIdErr) return rej('invalid max_id param'); + + // Check if both of since_id and max_id is specified + if (sinceId !== null && maxId !== null) { + return rej('cannot set since_id and max_id'); + } + + const query = { + $or: [{ + user_id: user._id, + recipient_id: recipient._id + }, { + user_id: recipient._id, + recipient_id: user._id + }] + } as any; + + const sort = { + _id: -1 + }; + + if (sinceId) { + sort._id = 1; + query._id = { + $gt: sinceId + }; + } else if (maxId) { + query._id = { + $lt: maxId + }; + } + + // Issue query + const messages = await Message + .find(query, { + limit: limit, + sort: sort + }); + + // Serialize + res(await Promise.all(messages.map(async message => + await serialize(message, user, { + populateRecipient: false + })))); + + if (messages.length === 0) { + return; + } + + // Mark as read all + if (markAsRead) { + const ids = messages + .filter(m => m.is_read == false) + .filter(m => m.recipient_id.equals(user._id)) + .map(m => m._id); + + // Update documents + await Message.update({ + _id: { $in: ids } + }, { + $set: { is_read: true } + }, { + multi: true + }); + + // Publish event + publishMessagingStream(recipient._id, user._id, 'read', ids.map(id => id.toString())); + + const count = await Message + .count({ + recipient_id: user._id, + is_read: false + }); + + if (count == 0) { + // 全ての(いままで未読だった)メッセージを(これで)読みましたよというイベントを発行 + publishUserStream(user._id, 'read_all_messaging_messages'); + } + } +}); diff --git a/src/api/endpoints/messaging/messages/create.js b/src/api/endpoints/messaging/messages/create.js deleted file mode 100644 index a88cc39ee8..0000000000 --- a/src/api/endpoints/messaging/messages/create.js +++ /dev/null @@ -1,169 +0,0 @@ -'use strict'; - -/** - * Module dependencies - */ -import * as mongo from 'mongodb'; -import Message from '../../../models/messaging-message'; -import History from '../../../models/messaging-history'; -import User from '../../../models/user'; -import DriveFile from '../../../models/drive-file'; -import serialize from '../../../serializers/messaging-message'; -import publishUserStream from '../../../event'; -import { publishMessagingStream } from '../../../event'; -import config from '../../../../conf'; - -/** - * 最大文字数 - */ -const maxTextLength = 500; - -/** - * Create a message - * - * @param {any} params - * @param {any} user - * @return {Promise} - */ -module.exports = (params, user) => - new Promise(async (res, rej) => -{ - // Get 'user_id' parameter - let recipient = params.user_id; - if (recipient !== undefined && recipient !== null) { - if (typeof recipient != 'string') { - return rej('user_id must be a string'); - } - - // Validate id - if (!mongo.ObjectID.isValid(recipient)) { - return rej('incorrect user_id'); - } - - // Myself - if (new mongo.ObjectID(recipient).equals(user._id)) { - return rej('cannot send message to myself'); - } - - recipient = await User.findOne({ - _id: new mongo.ObjectID(recipient) - }, { - fields: { - _id: true - } - }); - - if (recipient === null) { - return rej('user not found'); - } - } else { - return rej('user_id is required'); - } - - // Get 'text' parameter - let text = params.text; - if (text !== undefined && text !== null) { - text = text.trim(); - if (text.length === 0) { - text = null; - } else if (text.length > maxTextLength) { - return rej('too long text'); - } - } else { - text = null; - } - - // Get 'file_id' parameter - let file = params.file_id; - if (file !== undefined && file !== null) { - file = await DriveFile.findOne({ - _id: new mongo.ObjectID(file), - user_id: user._id - }, { - data: false - }); - - if (file === null) { - return rej('file not found'); - } - } else { - file = null; - } - - // テキストが無いかつ添付ファイルも無かったらエラー - if (text === null && file === null) { - return rej('text or file is required'); - } - - // メッセージを作成 - const message = await Message.insert({ - created_at: new Date(), - file_id: file ? file._id : undefined, - recipient_id: recipient._id, - text: text ? text : undefined, - user_id: user._id, - is_read: false - }); - - // Serialize - const messageObj = await serialize(message); - - // Reponse - res(messageObj); - - // 自分のストリーム - publishMessagingStream(message.user_id, message.recipient_id, 'message', messageObj); - publishUserStream(message.user_id, 'messaging_message', messageObj); - - // 相手のストリーム - publishMessagingStream(message.recipient_id, message.user_id, 'message', messageObj); - publishUserStream(message.recipient_id, 'messaging_message', messageObj); - - // 5秒経っても(今回作成した)メッセージが既読にならなかったら「未読のメッセージがありますよ」イベントを発行する - setTimeout(async () => { - const freshMessage = await Message.findOne({ _id: message._id }, { is_read: true }); - if (!freshMessage.is_read) { - publishUserStream(message.recipient_id, 'unread_messaging_message', messageObj); - } - }, 5000); - - // Register to search database - if (message.text && config.elasticsearch.enable) { - const es = require('../../../db/elasticsearch'); - - es.index({ - index: 'misskey', - type: 'messaging_message', - id: message._id.toString(), - body: { - text: message.text - } - }); - } - - // 履歴作成(自分) - History.update({ - user_id: user._id, - partner: recipient._id - }, { - updated_at: new Date(), - user_id: user._id, - partner: recipient._id, - message: message._id - }, { - upsert: true - }); - - // 履歴作成(相手) - History.update({ - user_id: recipient._id, - partner: user._id - }, { - updated_at: new Date(), - user_id: recipient._id, - partner: user._id, - message: message._id - }, { - upsert: true - }); -}); diff --git a/src/api/endpoints/messaging/messages/create.ts b/src/api/endpoints/messaging/messages/create.ts new file mode 100644 index 0000000000..dbe7f617fa --- /dev/null +++ b/src/api/endpoints/messaging/messages/create.ts @@ -0,0 +1,147 @@ +'use strict'; + +/** + * Module dependencies + */ +import it from '../../../it'; +import Message from '../../../models/messaging-message'; +import { isValidText } from '../../../models/messaging-message'; +import History from '../../../models/messaging-history'; +import User from '../../../models/user'; +import DriveFile from '../../../models/drive-file'; +import serialize from '../../../serializers/messaging-message'; +import publishUserStream from '../../../event'; +import { publishMessagingStream } from '../../../event'; +import config from '../../../../conf'; + +/** + * Create a message + * + * @param {any} params + * @param {any} user + * @return {Promise} + */ +module.exports = (params, user) => + new Promise(async (res, rej) => +{ + // Get 'user_id' parameter + const [recipientId, recipientIdErr] = it(params.user_id).expect.id().required().qed(); + if (recipientIdErr) return rej('invalid user_id param'); + + // Myself + if (recipientId.equals(user._id)) { + return rej('cannot send message to myself'); + } + + // Fetch recipient + const recipient = await User.findOne({ + _id: recipientId + }, { + fields: { + _id: true + } + }); + + if (recipient === null) { + return rej('user not found'); + } + + // Get 'text' parameter + const [text, textErr] = it(params.text).expect.string().validate(isValidText).qed(); + if (textErr) return rej('invalid text'); + + // Get 'file_id' parameter + const [fileId, fileIdErr] = it(params.file_id).expect.id().qed(); + if (fileIdErr) return rej('invalid file_id param'); + + let file = null; + if (fileId !== null) { + file = await DriveFile.findOne({ + _id: fileId, + user_id: user._id + }, { + data: false + }); + + if (file === null) { + return rej('file not found'); + } + } + + // テキストが無いかつ添付ファイルも無かったらエラー + if (text === null && file === null) { + return rej('text or file is required'); + } + + // メッセージを作成 + const message = await Message.insert({ + created_at: new Date(), + file_id: file ? file._id : undefined, + recipient_id: recipient._id, + text: text ? text : undefined, + user_id: user._id, + is_read: false + }); + + // Serialize + const messageObj = await serialize(message); + + // Reponse + res(messageObj); + + // 自分のストリーム + publishMessagingStream(message.user_id, message.recipient_id, 'message', messageObj); + publishUserStream(message.user_id, 'messaging_message', messageObj); + + // 相手のストリーム + publishMessagingStream(message.recipient_id, message.user_id, 'message', messageObj); + publishUserStream(message.recipient_id, 'messaging_message', messageObj); + + // 5秒経っても(今回作成した)メッセージが既読にならなかったら「未読のメッセージがありますよ」イベントを発行する + setTimeout(async () => { + const freshMessage = await Message.findOne({ _id: message._id }, { is_read: true }); + if (!freshMessage.is_read) { + publishUserStream(message.recipient_id, 'unread_messaging_message', messageObj); + } + }, 5000); + + // Register to search database + if (message.text && config.elasticsearch.enable) { + const es = require('../../../db/elasticsearch'); + + es.index({ + index: 'misskey', + type: 'messaging_message', + id: message._id.toString(), + body: { + text: message.text + } + }); + } + + // 履歴作成(自分) + History.update({ + user_id: user._id, + partner: recipient._id + }, { + updated_at: new Date(), + user_id: user._id, + partner: recipient._id, + message: message._id + }, { + upsert: true + }); + + // 履歴作成(相手) + History.update({ + user_id: recipient._id, + partner: user._id + }, { + updated_at: new Date(), + user_id: recipient._id, + partner: user._id, + message: message._id + }, { + upsert: true + }); +}); diff --git a/src/api/endpoints/messaging/unread.js b/src/api/endpoints/messaging/unread.js deleted file mode 100644 index faba171bdc..0000000000 --- a/src/api/endpoints/messaging/unread.js +++ /dev/null @@ -1,27 +0,0 @@ -'use strict'; - -/** - * Module dependencies - */ -import Message from '../../models/messaging-message'; - -/** - * Get count of unread messages - * - * @param {any} params - * @param {any} user - * @return {Promise} - */ -module.exports = (params, user) => - new Promise(async (res, rej) => -{ - const count = await Message - .count({ - recipient_id: user._id, - is_read: false - }); - - res({ - count: count - }); -}); diff --git a/src/api/endpoints/messaging/unread.ts b/src/api/endpoints/messaging/unread.ts new file mode 100644 index 0000000000..faba171bdc --- /dev/null +++ b/src/api/endpoints/messaging/unread.ts @@ -0,0 +1,27 @@ +'use strict'; + +/** + * Module dependencies + */ +import Message from '../../models/messaging-message'; + +/** + * Get count of unread messages + * + * @param {any} params + * @param {any} user + * @return {Promise} + */ +module.exports = (params, user) => + new Promise(async (res, rej) => +{ + const count = await Message + .count({ + recipient_id: user._id, + is_read: false + }); + + res({ + count: count + }); +}); diff --git a/src/api/endpoints/my/apps.js b/src/api/endpoints/my/apps.js deleted file mode 100644 index 1f45a1a27f..0000000000 --- a/src/api/endpoints/my/apps.js +++ /dev/null @@ -1,58 +0,0 @@ -'use strict'; - -/** - * Module dependencies - */ -import * as mongo from 'mongodb'; -import App from '../../models/app'; -import serialize from '../../serializers/app'; - -/** - * Get my apps - * - * @param {any} params - * @param {any} user - * @return {Promise} - */ -module.exports = (params, user) => - new Promise(async (res, rej) => -{ - // Get 'limit' parameter - let limit = params.limit; - if (limit !== undefined && limit !== null) { - limit = parseInt(limit, 10); - - // From 1 to 100 - if (!(1 <= limit && limit <= 100)) { - return rej('invalid limit range'); - } - } else { - limit = 10; - } - - // Get 'offset' parameter - let offset = params.offset; - if (offset !== undefined && offset !== null) { - offset = parseInt(offset, 10); - } else { - offset = 0; - } - - const query = { - user_id: user._id - }; - - // Execute query - const apps = await App - .find(query, { - limit: limit, - skip: offset, - sort: { - _id: -1 - } - }); - - // Reply - res(await Promise.all(apps.map(async app => - await serialize(app)))); -}); diff --git a/src/api/endpoints/my/apps.ts b/src/api/endpoints/my/apps.ts new file mode 100644 index 0000000000..2466a47ce4 --- /dev/null +++ b/src/api/endpoints/my/apps.ts @@ -0,0 +1,45 @@ +'use strict'; + +/** + * Module dependencies + */ +import it from '../../it'; +import App from '../../models/app'; +import serialize from '../../serializers/app'; + +/** + * Get my apps + * + * @param {any} params + * @param {any} user + * @return {Promise} + */ +module.exports = (params, user) => + new Promise(async (res, rej) => +{ + // Get 'limit' parameter + const [limit, limitErr] = it(params.limit).expect.number().range(1, 100).default(10).qed(); + if (limitErr) return rej('invalid limit param'); + + // Get 'offset' parameter + const [offset, offsetErr] = it(params.offset).expect.number().min(0).default(0).qed(); + if (offsetErr) return rej('invalid offset param'); + + const query = { + user_id: user._id + }; + + // Execute query + const apps = await App + .find(query, { + limit: limit, + skip: offset, + sort: { + _id: -1 + } + }); + + // Reply + res(await Promise.all(apps.map(async app => + await serialize(app)))); +}); diff --git a/src/api/endpoints/notifications/mark_as_read.js b/src/api/endpoints/notifications/mark_as_read.js deleted file mode 100644 index 9c8a5ee64b..0000000000 --- a/src/api/endpoints/notifications/mark_as_read.js +++ /dev/null @@ -1,53 +0,0 @@ -'use strict'; - -/** - * Module dependencies - */ -import * as mongo from 'mongodb'; -import Notification from '../../../models/notification'; -import serialize from '../../../serializers/notification'; -import event from '../../../event'; - -/** - * Mark as read a notification - * - * @param {any} params - * @param {any} user - * @return {Promise} - */ -module.exports = (params, user) => - new Promise(async (res, rej) => { - const notificationId = params.notification; - - if (notificationId === undefined || notificationId === null) { - return rej('notification is required'); - } - - // Get notification - const notification = await Notification - .findOne({ - _id: new mongo.ObjectID(notificationId), - i: user._id - }); - - if (notification === null) { - return rej('notification-not-found'); - } - - // Update - notification.is_read = true; - Notification.update({ _id: notification._id }, { - $set: { - is_read: true - } - }); - - // Response - res(); - - // Serialize - const notificationObj = await serialize(notification); - - // Publish read_notification event - event(user._id, 'read_notification', notificationObj); - }); diff --git a/src/api/endpoints/notifications/mark_as_read.ts b/src/api/endpoints/notifications/mark_as_read.ts new file mode 100644 index 0000000000..6e75927cfa --- /dev/null +++ b/src/api/endpoints/notifications/mark_as_read.ts @@ -0,0 +1,50 @@ +'use strict'; + +/** + * Module dependencies + */ +import it from '../../it'; +import Notification from '../../models/notification'; +import serialize from '../../serializers/notification'; +import event from '../../event'; + +/** + * Mark as read a notification + * + * @param {any} params + * @param {any} user + * @return {Promise} + */ +module.exports = (params, user) => + new Promise(async (res, rej) => { + const [notificationId, notificationIdErr] = it(params.notification_id).expect.id().required().qed(); + if (notificationIdErr) return rej('invalid notification_id param'); + + // Get notification + const notification = await Notification + .findOne({ + _id: notificationId, + i: user._id + }); + + if (notification === null) { + return rej('notification-not-found'); + } + + // Update + notification.is_read = true; + Notification.update({ _id: notification._id }, { + $set: { + is_read: true + } + }); + + // Response + res(); + + // Serialize + const notificationObj = await serialize(notification); + + // Publish read_notification event + event(user._id, 'read_notification', notificationObj); + }); -- cgit v1.2.3-freya