ユーザー検索APIを統合

This commit is contained in:
syuilo 2018-08-06 18:28:27 +09:00
parent 10f9549a04
commit 5f208a7d99
3 changed files with 143 additions and 90 deletions

View file

@ -132,7 +132,7 @@ export default Vue.extend({
this.users = users;
this.fetching = false;
} else {
(this as any).api('users/search_by_username', {
(this as any).api('users/search', {
query: this.q,
limit: 30
}).then(users => {

View file

@ -1,34 +1,157 @@
import $ from 'cafy';
import User, { pack, ILocalUser } from '../../../../models/user';
const escapeRegexp = require('escape-regexp');
import User, { pack, ILocalUser, validateUsername, IUser } from '../../../../models/user';
import getParams from '../../get-params';
export const meta = {
desc: {
ja: 'ユーザーを検索します。'
},
requireCredential: false,
params: {
query: $.str.note({
desc: {
ja: 'クエリ'
}
}),
offset: $.num.optional.min(0).note({
default: 0,
desc: {
ja: 'オフセット'
}
}),
limit: $.num.optional.range(1, 100).note({
default: 10,
desc: {
ja: '取得する数'
}
}),
localOnly: $.bool.optional.note({
default: false,
desc: {
ja: 'ローカルユーザーのみ検索対象にするか否か'
}
}),
},
};
/**
* Search a user
*/
export default (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');
const [ps, psErr] = getParams(meta, params);
if (psErr) return rej(psErr);
// Get 'max' parameter
const [max = 10, maxErr] = $.num.optional.range(1, 30).get(params.max);
if (maxErr) return rej('invalid max param');
const isUsername = validateUsername(ps.query.replace('@', ''));
const escapedQuery = escapeRegexp(query);
let users: IUser[] = [];
// Search users
const users = await User
if (isUsername) {
users = await User
.find({
host: null,
$or: [{
usernameLower: new RegExp(escapedQuery.replace('@', '').toLowerCase())
usernameLower: new RegExp('^' + escapeRegexp(ps.query.replace('@', '').toLowerCase()))
}, {
name: new RegExp(escapedQuery)
}]
}, {
limit: max
limit: ps.limit,
skip: ps.offset
});
if (users.length < ps.limit && !ps.localOnly) {
const otherUsers = await User
.find({
host: { $ne: null },
usernameLower: new RegExp('^' + escapeRegexp(ps.query.replace('@', '').toLowerCase()))
}, {
limit: ps.limit - users.length
});
users = users.concat(otherUsers);
}
if (users.length < ps.limit) {
const otherUsers = await User
.find({
_id: { $nin: users.map(u => u._id) },
host: null,
usernameLower: new RegExp(escapeRegexp(ps.query.replace('@', '').toLowerCase()))
}, {
limit: ps.limit - users.length
});
users = users.concat(otherUsers);
}
if (users.length < ps.limit && !ps.localOnly) {
const otherUsers = await User
.find({
_id: { $nin: users.map(u => u._id) },
host: { $ne: null },
usernameLower: new RegExp(escapeRegexp(ps.query.replace('@', '').toLowerCase()))
}, {
limit: ps.limit - users.length
});
users = users.concat(otherUsers);
}
}
if (users.length < ps.limit) {
const otherUsers = await User
.find({
_id: { $nin: users.map(u => u._id) },
host: null,
name: new RegExp('^' + escapeRegexp(ps.query.toLowerCase()))
}, {
limit: ps.limit - users.length
});
users = users.concat(otherUsers);
}
if (users.length < ps.limit && !ps.localOnly) {
const otherUsers = await User
.find({
_id: { $nin: users.map(u => u._id) },
host: { $ne: null },
name: new RegExp('^' + escapeRegexp(ps.query.toLowerCase()))
}, {
limit: ps.limit - users.length
});
users = users.concat(otherUsers);
}
if (users.length < ps.limit) {
const otherUsers = await User
.find({
_id: { $nin: users.map(u => u._id) },
host: null,
name: new RegExp(escapeRegexp(ps.query.toLowerCase()))
}, {
limit: ps.limit - users.length
});
users = users.concat(otherUsers);
}
if (users.length < ps.limit && !ps.localOnly) {
const otherUsers = await User
.find({
_id: { $nin: users.map(u => u._id) },
host: { $ne: null },
name: new RegExp(escapeRegexp(ps.query.toLowerCase()))
}, {
limit: ps.limit - users.length
});
users = users.concat(otherUsers);
}
// Serialize
res(await Promise.all(users.map(user => pack(user, me, { detail: true }))));
});

View file

@ -1,70 +0,0 @@
import $ from 'cafy';
import User, { pack, ILocalUser } from '../../../../models/user';
const escapeRegexp = require('escape-regexp');
/**
* Search a user by username
*/
export default (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');
// Get 'offset' parameter
const [offset = 0, offsetErr] = $.num.optional.min(0).get(params.offset);
if (offsetErr) return rej('invalid offset param');
// Get 'limit' parameter
const [limit = 10, limitErr] = $.num.optional.range(1, 100).get(params.limit);
if (limitErr) return rej('invalid limit param');
let users = await User
.find({
host: null,
usernameLower: new RegExp('^' + escapeRegexp(query.toLowerCase()))
}, {
limit: limit,
skip: offset
});
if (users.length < limit) {
const otherUsers = await User
.find({
host: { $ne: null },
usernameLower: new RegExp('^' + escapeRegexp(query.toLowerCase()))
}, {
limit: limit - users.length
});
users = users.concat(otherUsers);
}
if (users.length < limit) {
const otherUsers = await User
.find({
_id: { $nin: users.map(u => u._id) },
host: null,
usernameLower: new RegExp(escapeRegexp(query.toLowerCase()))
}, {
limit: limit - users.length
});
users = users.concat(otherUsers);
}
if (users.length < limit) {
const otherUsers = await User
.find({
_id: { $nin: users.map(u => u._id) },
host: { $ne: null },
usernameLower: new RegExp(escapeRegexp(query.toLowerCase()))
}, {
limit: limit - users.length
});
users = users.concat(otherUsers);
}
// Serialize
res(await Promise.all(users.map(user => pack(user, me, { detail: true }))));
});