summaryrefslogtreecommitdiff
path: root/src/api/serializers
diff options
context:
space:
mode:
Diffstat (limited to 'src/api/serializers')
-rw-r--r--src/api/serializers/app.ts85
-rw-r--r--src/api/serializers/auth-session.ts42
-rw-r--r--src/api/serializers/drive-file.ts63
-rw-r--r--src/api/serializers/drive-folder.ts52
-rw-r--r--src/api/serializers/drive-tag.ts37
-rw-r--r--src/api/serializers/messaging-message.ts64
-rw-r--r--src/api/serializers/notification.ts66
-rw-r--r--src/api/serializers/post.ts103
-rw-r--r--src/api/serializers/signin.ts25
-rw-r--r--src/api/serializers/user.ts138
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: ''
+ }
+ };
+}
+*/