diff options
Diffstat (limited to 'src/api/serializers')
| -rw-r--r-- | src/api/serializers/app.ts | 85 | ||||
| -rw-r--r-- | src/api/serializers/auth-session.ts | 42 | ||||
| -rw-r--r-- | src/api/serializers/drive-file.ts | 63 | ||||
| -rw-r--r-- | src/api/serializers/drive-folder.ts | 52 | ||||
| -rw-r--r-- | src/api/serializers/drive-tag.ts | 37 | ||||
| -rw-r--r-- | src/api/serializers/messaging-message.ts | 64 | ||||
| -rw-r--r-- | src/api/serializers/notification.ts | 66 | ||||
| -rw-r--r-- | src/api/serializers/post.ts | 103 | ||||
| -rw-r--r-- | src/api/serializers/signin.ts | 25 | ||||
| -rw-r--r-- | src/api/serializers/user.ts | 138 |
10 files changed, 675 insertions, 0 deletions
diff --git a/src/api/serializers/app.ts b/src/api/serializers/app.ts new file mode 100644 index 0000000000..23a12c977d --- /dev/null +++ b/src/api/serializers/app.ts @@ -0,0 +1,85 @@ +'use strict'; + +/** + * Module dependencies + */ +import * as mongo from 'mongodb'; +const deepcopy = require('deepcopy'); +import App from '../models/app'; +import User from '../models/user'; +import Userkey from '../models/userkey'; + +/** + * Serialize an app + * + * @param {Object} app + * @param {Object} me? + * @param {Object} options? + * @return {Promise<Object>} + */ +export default ( + app: any, + me?: any, + options?: { + includeSecret: boolean, + includeProfileImageIds: boolean + } +) => new Promise<any>(async (resolve, reject) => { + const opts = options || { + includeSecret: false, + includeProfileImageIds: false + }; + + let _app: any; + + // Populate the app if 'app' is ID + if (mongo.ObjectID.prototype.isPrototypeOf(app)) { + _app = await App.findOne({ + _id: app + }); + } else if (typeof app === 'string') { + _app = await User.findOne({ + _id: new mongo.ObjectID(app) + }); + } else { + _app = deepcopy(app); + } + + // Me + if (me && !mongo.ObjectID.prototype.isPrototypeOf(me)) { + if (typeof me === 'string') { + me = new mongo.ObjectID(me); + } else { + me = me._id; + } + } + + // Rename _id to id + _app.id = _app._id; + delete _app._id; + + delete _app.name_id_lower; + + // Visible by only owner + if (!opts.includeSecret) { + delete _app.secret; + } + + _app.icon_url = _app.icon != null + ? `${config.drive_url}/${_app.icon}` + : `${config.drive_url}/app-default.jpg`; + + if (me) { + // 既に連携しているか + const exist = await Userkey.count({ + app_id: _app.id, + user_id: me, + }, { + limit: 1 + }); + + _app.is_authorized = exist === 1; + } + + resolve(_app); +}); diff --git a/src/api/serializers/auth-session.ts b/src/api/serializers/auth-session.ts new file mode 100644 index 0000000000..786684b4e0 --- /dev/null +++ b/src/api/serializers/auth-session.ts @@ -0,0 +1,42 @@ +'use strict'; + +/** + * Module dependencies + */ +import * as mongo from 'mongodb'; +const deepcopy = require('deepcopy'); +import serializeApp from './app'; + +/** + * Serialize an auth session + * + * @param {Object} session + * @param {Object} me? + * @return {Promise<Object>} + */ +export default ( + session: any, + me?: any +) => new Promise<any>(async (resolve, reject) => { + let _session: any; + + // TODO: Populate session if it ID + + _session = deepcopy(session); + + // Me + if (me && !mongo.ObjectID.prototype.isPrototypeOf(me)) { + if (typeof me === 'string') { + me = new mongo.ObjectID(me); + } else { + me = me._id; + } + } + + delete _session._id; + + // Populate app + _session.app = await serializeApp(_session.app_id, me); + + resolve(_session); +}); diff --git a/src/api/serializers/drive-file.ts b/src/api/serializers/drive-file.ts new file mode 100644 index 0000000000..635cf13867 --- /dev/null +++ b/src/api/serializers/drive-file.ts @@ -0,0 +1,63 @@ +'use strict'; + +/** + * Module dependencies + */ +import * as mongo from 'mongodb'; +import DriveFile from '../models/drive-file'; +import serializeDriveTag from './drive-tag'; +const deepcopy = require('deepcopy'); + +/** + * Serialize a drive file + * + * @param {Object} file + * @param {Object} options? + * @return {Promise<Object>} + */ +export default ( + file: any, + options?: { + includeTags: boolean + } +) => new Promise<Object>(async (resolve, reject) => { + const opts = options || { + includeTags: true + }; + + let _file: any; + + // Populate the file if 'file' is ID + if (mongo.ObjectID.prototype.isPrototypeOf(file)) { + _file = await DriveFile.findOne({ + _id: file + }, { + data: false + }); + } else if (typeof file === 'string') { + _file = await DriveFile.findOne({ + _id: new mongo.ObjectID(file) + }, { + data: false + }); + } else { + _file = deepcopy(file); + } + + // Rename _id to id + _file.id = _file._id; + delete _file._id; + + delete _file.data; + + _file.url = `${config.drive_url}/${_file.id}/${encodeURIComponent(_file.name)}`; + + if (opts.includeTags && _file.tags) { + // Populate tags + _file.tags = await _file.tags.map(async (tag: any) => + await serializeDriveTag(tag) + ); + } + + resolve(_file); +}); diff --git a/src/api/serializers/drive-folder.ts b/src/api/serializers/drive-folder.ts new file mode 100644 index 0000000000..ee5a973e14 --- /dev/null +++ b/src/api/serializers/drive-folder.ts @@ -0,0 +1,52 @@ +'use strict'; + +/** + * Module dependencies + */ +import * as mongo from 'mongodb'; +import DriveFolder from '../models/drive-folder'; +const deepcopy = require('deepcopy'); + +/** + * Serialize a drive folder + * + * @param {Object} folder + * @param {Object} options? + * @return {Promise<Object>} + */ +const self = ( + folder: any, + options?: { + includeParent: boolean + } +) => new Promise<Object>(async (resolve, reject) => { + const opts = options || { + includeParent: false + }; + + let _folder: any; + + // Populate the folder if 'folder' is ID + if (mongo.ObjectID.prototype.isPrototypeOf(folder)) { + _folder = await DriveFolder.findOne({_id: folder}); + } else if (typeof folder === 'string') { + _folder = await DriveFolder.findOne({_id: new mongo.ObjectID(folder)}); + } else { + _folder = deepcopy(folder); + } + + // Rename _id to id + _folder.id = _folder._id; + delete _folder._id; + + if (opts.includeParent && _folder.parent_id) { + // Populate parent folder + _folder.parent = await self(_folder.parent_id, { + includeParent: true + }); + } + + resolve(_folder); +}); + +export default self; diff --git a/src/api/serializers/drive-tag.ts b/src/api/serializers/drive-tag.ts new file mode 100644 index 0000000000..182e9a66d4 --- /dev/null +++ b/src/api/serializers/drive-tag.ts @@ -0,0 +1,37 @@ +'use strict'; + +/** + * Module dependencies + */ +import * as mongo from 'mongodb'; +import DriveTag from '../models/drive-tag'; +const deepcopy = require('deepcopy'); + +/** + * Serialize a drive tag + * + * @param {Object} tag + * @return {Promise<Object>} + */ +const self = ( + tag: any +) => new Promise<Object>(async (resolve, reject) => { + let _tag: any; + + // Populate the tag if 'tag' is ID + if (mongo.ObjectID.prototype.isPrototypeOf(tag)) { + _tag = await DriveTag.findOne({_id: tag}); + } else if (typeof tag === 'string') { + _tag = await DriveTag.findOne({_id: new mongo.ObjectID(tag)}); + } else { + _tag = deepcopy(tag); + } + + // Rename _id to id + _tag.id = _tag._id; + delete _tag._id; + + resolve(_tag); +}); + +export default self; diff --git a/src/api/serializers/messaging-message.ts b/src/api/serializers/messaging-message.ts new file mode 100644 index 0000000000..0855b25d16 --- /dev/null +++ b/src/api/serializers/messaging-message.ts @@ -0,0 +1,64 @@ +'use strict'; + +/** + * Module dependencies + */ +import * as mongo from 'mongodb'; +import Message from '../models/messaging-message'; +import serializeUser from './user'; +import serializeDriveFile from './drive-file'; +const deepcopy = require('deepcopy'); + +/** + * Serialize a message + * + * @param {Object} message + * @param {Object} me? + * @param {Object} options? + * @return {Promise<Object>} + */ +export default ( + message: any, + me: any, + options?: { + populateRecipient: boolean + } +) => new Promise<Object>(async (resolve, reject) => { + const opts = options || { + populateRecipient: true + }; + + let _message: any; + + // Populate the message if 'message' is ID + if (mongo.ObjectID.prototype.isPrototypeOf(message)) { + _message = await Message.findOne({ + _id: message + }); + } else if (typeof message === 'string') { + _message = await Message.findOne({ + _id: new mongo.ObjectID(message) + }); + } else { + _message = deepcopy(message); + } + + // Rename _id to id + _message.id = _message._id; + delete _message._id; + + // Populate user + _message.user = await serializeUser(_message.user_id, me); + + if (_message.file) { + // Populate file + _message.file = await serializeDriveFile(_message.file_id); + } + + if (opts.populateRecipient) { + // Populate recipient + _message.recipient = await serializeUser(_message.recipient_id, me); + } + + resolve(_message); +}); diff --git a/src/api/serializers/notification.ts b/src/api/serializers/notification.ts new file mode 100644 index 0000000000..56769f50d0 --- /dev/null +++ b/src/api/serializers/notification.ts @@ -0,0 +1,66 @@ +'use strict'; + +/** + * Module dependencies + */ +import * as mongo from 'mongodb'; +import Notification from '../models/notification'; +import serializeUser from './user'; +import serializePost from './post'; +const deepcopy = require('deepcopy'); + +/** + * Serialize a notification + * + * @param {Object} notification + * @return {Promise<Object>} + */ +export default (notification: any) => new Promise<Object>(async (resolve, reject) => { + let _notification: any; + + // Populate the notification if 'notification' is ID + if (mongo.ObjectID.prototype.isPrototypeOf(notification)) { + _notification = await Notification.findOne({ + _id: notification + }); + } else if (typeof notification === 'string') { + _notification = await Notification.findOne({ + _id: new mongo.ObjectID(notification) + }); + } else { + _notification = deepcopy(notification); + } + + // Rename _id to id + _notification.id = _notification._id; + delete _notification._id; + + // Rename notifier_id to user_id + _notification.user_id = _notification.notifier_id; + delete _notification.notifier_id; + + const me = _notification.notifiee_id; + delete _notification.notifiee_id; + + // Populate notifier + _notification.user = await serializeUser(_notification.user_id, me); + + switch (_notification.type) { + case 'follow': + // nope + break; + case 'mention': + case 'reply': + case 'repost': + case 'quote': + case 'like': + // Populate post + _notification.post = await serializePost(_notification.post_id, me); + break; + default: + console.error(`Unknown type: ${_notification.type}`); + break; + } + + resolve(_notification); +}); diff --git a/src/api/serializers/post.ts b/src/api/serializers/post.ts new file mode 100644 index 0000000000..a17aa9035b --- /dev/null +++ b/src/api/serializers/post.ts @@ -0,0 +1,103 @@ +'use strict'; + +/** + * Module dependencies + */ +import * as mongo from 'mongodb'; +import Post from '../models/post'; +import Like from '../models/like'; +import serializeUser from './user'; +import serializeDriveFile from './drive-file'; +const deepcopy = require('deepcopy'); + +/** + * Serialize a post + * + * @param {Object} post + * @param {Object} me? + * @param {Object} options? + * @return {Promise<Object>} + */ +const self = ( + post: any, + me?: any, + options?: { + serializeReplyTo: boolean, + serializeRepost: boolean, + includeIsLiked: boolean + } +) => new Promise<Object>(async (resolve, reject) => { + const opts = options || { + serializeReplyTo: true, + serializeRepost: true, + includeIsLiked: true + }; + + let _post: any; + + // Populate the post if 'post' is ID + if (mongo.ObjectID.prototype.isPrototypeOf(post)) { + _post = await Post.findOne({ + _id: post + }); + } else if (typeof post === 'string') { + _post = await Post.findOne({ + _id: new mongo.ObjectID(post) + }); + } else { + _post = deepcopy(post); + } + + const id = _post._id; + + // Rename _id to id + _post.id = _post._id; + delete _post._id; + + delete _post.mentions; + + // Populate user + _post.user = await serializeUser(_post.user_id, me); + + if (_post.media_ids) { + // Populate media + _post.media = await Promise.all(_post.media_ids.map(async fileId => + await serializeDriveFile(fileId) + )); + } + + if (_post.reply_to_id && opts.serializeReplyTo) { + // Populate reply to post + _post.reply_to = await self(_post.reply_to_id, me, { + serializeReplyTo: false, + serializeRepost: false, + includeIsLiked: false + }); + } + + if (_post.repost_id && opts.serializeRepost) { + // Populate repost + _post.repost = await self(_post.repost_id, me, { + serializeReplyTo: _post.text == null, + serializeRepost: _post.text == null, + includeIsLiked: _post.text == null + }); + } + + // Check if it is liked + if (me && opts.includeIsLiked) { + const liked = await Like + .count({ + user_id: me._id, + post_id: id + }, { + limit: 1 + }); + + _post.is_liked = liked === 1; + } + + resolve(_post); +}); + +export default self; diff --git a/src/api/serializers/signin.ts b/src/api/serializers/signin.ts new file mode 100644 index 0000000000..d6d7a39471 --- /dev/null +++ b/src/api/serializers/signin.ts @@ -0,0 +1,25 @@ +'use strict'; + +/** + * Module dependencies + */ +const deepcopy = require('deepcopy'); + +/** + * Serialize a signin record + * + * @param {Object} record + * @return {Promise<Object>} + */ +export default ( + record: any +) => new Promise<Object>(async (resolve, reject) => { + + const _record = deepcopy(record); + + // Rename _id to id + _record.id = _record._id; + delete _record._id; + + resolve(_record); +}); diff --git a/src/api/serializers/user.ts b/src/api/serializers/user.ts new file mode 100644 index 0000000000..0585863950 --- /dev/null +++ b/src/api/serializers/user.ts @@ -0,0 +1,138 @@ +'use strict'; + +/** + * Module dependencies + */ +import * as mongo from 'mongodb'; +const deepcopy = require('deepcopy'); +import User from '../models/user'; +import Following from '../models/following'; +import getFriends from '../common/get-friends'; + +/** + * Serialize a user + * + * @param {Object} user + * @param {Object} me? + * @param {Object} options? + * @return {Promise<Object>} + */ +export default ( + user: any, + me?: any, + options?: { + detail: boolean, + includeSecrets: boolean + } +) => new Promise<any>(async (resolve, reject) => { + + const opts = Object.assign({ + detail: false, + includeSecrets: false + }, options); + + let _user: any; + + // Populate the user if 'user' is ID + if (mongo.ObjectID.prototype.isPrototypeOf(user)) { + _user = await User.findOne({ + _id: user + }); + } else if (typeof user === 'string') { + _user = await User.findOne({ + _id: new mongo.ObjectID(user) + }); + } else { + _user = deepcopy(user); + } + + // Me + if (me && !mongo.ObjectID.prototype.isPrototypeOf(me)) { + if (typeof me === 'string') { + me = new mongo.ObjectID(me); + } else { + me = me._id; + } + } + + // Rename _id to id + _user.id = _user._id; + delete _user._id; + + // Remove private properties + delete _user.password; + delete _user.token; + delete _user.username_lower; + + // Visible via only the official client + if (!opts.includeSecrets) { + delete _user.data; + delete _user.email; + } + + _user.avatar_url = _user.avatar_id != null + ? `${config.drive_url}/${_user.avatar_id}` + : `${config.drive_url}/default-avatar.jpg`; + + _user.banner_url = _user.banner_id != null + ? `${config.drive_url}/${_user.banner_id}` + : null; + + if (!me || !me.equals(_user.id) || !opts.detail) { + delete _user.avatar_id; + delete _user.banner_id; + + delete _user.drive_capacity; + } + + if (me && !me.equals(_user.id)) { + // If the user is following + const follow = await Following.findOne({ + follower_id: me, + followee_id: _user.id, + deleted_at: { $exists: false } + }); + _user.is_following = follow !== null; + + // If the user is followed + const follow2 = await Following.findOne({ + follower_id: _user.id, + followee_id: me, + deleted_at: { $exists: false } + }); + _user.is_followed = follow2 !== null; + } + + if (me && !me.equals(_user.id) && opts.detail) { + const myFollowingIds = await getFriends(me); + + // Get following you know count + const followingYouKnowCount = await Following.count({ + followee_id: { $in: myFollowingIds }, + follower_id: _user.id, + deleted_at: { $exists: false } + }); + _user.following_you_know_count = followingYouKnowCount; + + // Get followers you know count + const followersYouKnowCount = await Following.count({ + followee_id: _user.id, + follower_id: { $in: myFollowingIds }, + deleted_at: { $exists: false } + }); + _user.followers_you_know_count = followersYouKnowCount; + } + + resolve(_user); +}); +/* +function img(url) { + return { + thumbnail: { + large: `${url}`, + medium: '', + small: '' + } + }; +} +*/ |