diff options
| author | syuilo <syuilotan@yahoo.co.jp> | 2018-02-02 08:06:01 +0900 |
|---|---|---|
| committer | syuilo <syuilotan@yahoo.co.jp> | 2018-02-02 08:06:01 +0900 |
| commit | 9a282e37be5ba847718d198d30eb97f31d11f2a0 (patch) | |
| tree | 9e1f6bda799ca3f6cc6b489a96751cb5b48f170b /src/api/models/user.ts | |
| parent | Update dependencies :rocket: (diff) | |
| download | sharkey-9a282e37be5ba847718d198d30eb97f31d11f2a0.tar.gz sharkey-9a282e37be5ba847718d198d30eb97f31d11f2a0.tar.bz2 sharkey-9a282e37be5ba847718d198d30eb97f31d11f2a0.zip | |
wip
Diffstat (limited to 'src/api/models/user.ts')
| -rw-r--r-- | src/api/models/user.ts | 196 |
1 files changed, 190 insertions, 6 deletions
diff --git a/src/api/models/user.ts b/src/api/models/user.ts index 018979158f..48a45ac2f7 100644 --- a/src/api/models/user.ts +++ b/src/api/models/user.ts @@ -1,14 +1,19 @@ import * as mongo from 'mongodb'; - +import deepcopy = require('deepcopy'); +import rap from '@prezzemolo/rap'; import db from '../../db/mongodb'; -import { IPost } from './post'; +import { IPost, pack as packPost } from './post'; +import Following from './following'; +import Mute from './mute'; +import getFriends from '../common/get-friends'; +import config from '../../conf'; -const collection = db.get('users'); +const User = db.get<IUser>('users'); -(collection as any).createIndex('username'); // fuck type definition -(collection as any).createIndex('token'); // fuck type definition +User.createIndex('username'); +User.createIndex('token'); -export default collection as any; // fuck type definition +export default User; export function validateUsername(username: string): boolean { return typeof username == 'string' && /^[a-zA-Z0-9\-]{3,20}$/.test(username); @@ -83,3 +88,182 @@ export function init(user): IUser { user.pinned_post_id = new mongo.ObjectID(user.pinned_post_id); return user; } + +/** + * Pack a user for API response + * + * @param user target + * @param me? serializee + * @param options? serialize options + * @return Packed user + */ +export const pack = ( + user: string | mongo.ObjectID | IUser, + me?: string | mongo.ObjectID | IUser, + options?: { + detail?: boolean, + includeSecrets?: boolean + } +) => new Promise<any>(async (resolve, reject) => { + + const opts = Object.assign({ + detail: false, + includeSecrets: false + }, options); + + let _user: any; + + const fields = opts.detail ? { + settings: false + } : { + settings: false, + client_settings: false, + profile: false, + keywords: false, + domains: false + }; + + // Populate the user if 'user' is ID + if (mongo.ObjectID.prototype.isPrototypeOf(user)) { + _user = await User.findOne({ + _id: user + }, { fields }); + } else if (typeof user === 'string') { + _user = await User.findOne({ + _id: new mongo.ObjectID(user) + }, { fields }); + } else { + _user = deepcopy(user); + } + + if (!_user) return reject('invalid user arg.'); + + // Me + const meId: mongo.ObjectID = me + ? mongo.ObjectID.prototype.isPrototypeOf(me) + ? me as mongo.ObjectID + : typeof me === 'string' + ? new mongo.ObjectID(me) + : (me as IUser)._id + : null; + + // Rename _id to id + _user.id = _user._id; + delete _user._id; + + // Remove needless properties + delete _user.latest_post; + + // Remove private properties + delete _user.password; + delete _user.token; + delete _user.two_factor_temp_secret; + delete _user.two_factor_secret; + delete _user.username_lower; + if (_user.twitter) { + delete _user.twitter.access_token; + delete _user.twitter.access_token_secret; + } + delete _user.line; + + // Visible via only the official client + if (!opts.includeSecrets) { + delete _user.email; + delete _user.client_settings; + } + + if (!opts.detail) { + delete _user.two_factor_enabled; + } + + _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 (!meId || !meId.equals(_user.id) || !opts.detail) { + delete _user.avatar_id; + delete _user.banner_id; + + delete _user.drive_capacity; + } + + if (meId && !meId.equals(_user.id)) { + // Whether the user is following + _user.is_following = (async () => { + const follow = await Following.findOne({ + follower_id: meId, + followee_id: _user.id, + deleted_at: { $exists: false } + }); + return follow !== null; + })(); + + // Whether the user is followed + _user.is_followed = (async () => { + const follow2 = await Following.findOne({ + follower_id: _user.id, + followee_id: meId, + deleted_at: { $exists: false } + }); + return follow2 !== null; + })(); + + // Whether the user is muted + _user.is_muted = (async () => { + const mute = await Mute.findOne({ + muter_id: meId, + mutee_id: _user.id, + deleted_at: { $exists: false } + }); + return mute !== null; + })(); + } + + if (opts.detail) { + if (_user.pinned_post_id) { + // Populate pinned post + _user.pinned_post = packPost(_user.pinned_post_id, meId, { + detail: true + }); + } + + if (meId && !meId.equals(_user.id)) { + const myFollowingIds = await getFriends(meId); + + // Get following you know count + _user.following_you_know_count = Following.count({ + followee_id: { $in: myFollowingIds }, + follower_id: _user.id, + deleted_at: { $exists: false } + }); + + // Get followers you know count + _user.followers_you_know_count = Following.count({ + followee_id: _user.id, + follower_id: { $in: myFollowingIds }, + deleted_at: { $exists: false } + }); + } + } + + // resolve promises in _user object + _user = await rap(_user); + + resolve(_user); +}); + +/* +function img(url) { + return { + thumbnail: { + large: `${url}`, + medium: '', + small: '' + } + }; +} +*/ |