This commit is contained in:
syuilo 2021-10-17 18:38:38 +09:00
parent 2c82a89c64
commit ff25b6b65a
3 changed files with 38 additions and 54 deletions

View file

@ -69,7 +69,7 @@
<template #prefix><i class="fas fa-search"></i></template> <template #prefix><i class="fas fa-search"></i></template>
<template #label>{{ $ts.searchUser }}</template> <template #label>{{ $ts.searchUser }}</template>
</MkInput> </MkInput>
<MkRadios v-model="searchScope"> <MkRadios v-model="searchOrigin">
<option value="local">{{ $ts.local }}</option> <option value="local">{{ $ts.local }}</option>
<option value="remote">{{ $ts.remote }}</option> <option value="remote">{{ $ts.remote }}</option>
<option value="both">{{ $ts.both }}</option> <option value="both">{{ $ts.both }}</option>
@ -167,14 +167,14 @@ export default defineComponent({
limit: 10, limit: 10,
params: computed(() => (this.searchQuery && this.searchQuery !== '') ? { params: computed(() => (this.searchQuery && this.searchQuery !== '') ? {
query: this.searchQuery, query: this.searchQuery,
scope: this.searchScope, origin: this.searchOrigin,
} : null) } : null)
}, },
tagsLocal: [], tagsLocal: [],
tagsRemote: [], tagsRemote: [],
stats: null, stats: null,
searchQuery: null, searchQuery: null,
searchScope: 'both', searchOrigin: 'both',
num: number, num: number,
}; };
}, },

View file

@ -46,13 +46,15 @@ export const meta = {
}; };
export default define(meta, async (ps, me) => { export default define(meta, async (ps, me) => {
const activeThreshold = new Date(Date.now() - (1000 * 60 * 60 * 24 * 30)); // 30日
if (ps.host) { if (ps.host) {
const q = Users.createQueryBuilder('user') const q = Users.createQueryBuilder('user')
.where('user.isSuspended = FALSE') .where('user.isSuspended = FALSE')
.andWhere('user.host LIKE :host', { host: ps.host.toLowerCase() + '%' }); .andWhere('user.host LIKE :host', { host: ps.host.toLowerCase() + '%' });
if (ps.username) { if (ps.username) {
q.andWhere('user.usernameLower like :username', { username: ps.username.toLowerCase() + '%' }); q.andWhere('user.usernameLower LIKE :username', { username: ps.username.toLowerCase() + '%' });
} }
q.andWhere('user.updatedAt IS NOT NULL'); q.andWhere('user.updatedAt IS NOT NULL');
@ -65,12 +67,12 @@ export default define(meta, async (ps, me) => {
let users = await Users.createQueryBuilder('user') let users = await Users.createQueryBuilder('user')
.where('user.host IS NULL') .where('user.host IS NULL')
.andWhere('user.isSuspended = FALSE') .andWhere('user.isSuspended = FALSE')
.andWhere('user.usernameLower like :username', { username: ps.username.toLowerCase() + '%' }) .andWhere('user.usernameLower LIKE :username', { username: ps.username.toLowerCase() + '%' })
.andWhere(new Brackets(qb => { qb .andWhere(new Brackets(qb => { qb
.where('user.lastActiveDate IS NULL') .where('user.updatedAt IS NULL')
.orWhere('user.lastActiveDate > :activeThreshold', { activeThreshold: new Date(Date.now() - USER_ACTIVE_THRESHOLD) }); .orWhere('user.updatedAt > :activeThreshold', { activeThreshold: activeThreshold });
})) }))
.orderBy('user.lastActiveDate', 'DESC', 'NULLS LAST') .orderBy('user.updatedAt', 'DESC', 'NULLS LAST')
.take(ps.limit!) .take(ps.limit!)
.skip(ps.offset) .skip(ps.offset)
.getMany(); .getMany();
@ -79,7 +81,7 @@ export default define(meta, async (ps, me) => {
const otherUsers = await Users.createQueryBuilder('user') const otherUsers = await Users.createQueryBuilder('user')
.where('user.host IS NOT NULL') .where('user.host IS NOT NULL')
.andWhere('user.isSuspended = FALSE') .andWhere('user.isSuspended = FALSE')
.andWhere('user.usernameLower like :username', { username: ps.username.toLowerCase() + '%' }) .andWhere('user.usernameLower LIKE :username', { username: ps.username.toLowerCase() + '%' })
.andWhere('user.updatedAt IS NOT NULL') .andWhere('user.updatedAt IS NOT NULL')
.orderBy('user.updatedAt', 'DESC') .orderBy('user.updatedAt', 'DESC')
.take(ps.limit! - users.length) .take(ps.limit! - users.length)

View file

@ -3,7 +3,6 @@ import define from '../../define';
import { UserProfiles, Users } from '@/models/index'; import { UserProfiles, Users } from '@/models/index';
import { User } from '@/models/entities/user'; import { User } from '@/models/entities/user';
import { Brackets } from 'typeorm'; import { Brackets } from 'typeorm';
import { USER_ACTIVE_THRESHOLD } from '@/const';
export const meta = { export const meta = {
tags: ['users'], tags: ['users'],
@ -25,9 +24,9 @@ export const meta = {
default: 10, default: 10,
}, },
scope: { origin: {
validator: $.optional.str.or(['local', 'remote', 'both']), validator: $.optional.str.or(['local', 'remote', 'combined']),
default: 'both', default: 'combined',
}, },
detail: { detail: {
@ -48,59 +47,49 @@ export const meta = {
}; };
export default define(meta, async (ps, me) => { export default define(meta, async (ps, me) => {
const activeThreshold = new Date(Date.now() - (1000 * 60 * 60 * 24 * 30)); // 30日
const isUsername = ps.query.startsWith('@'); const isUsername = ps.query.startsWith('@');
let users: User[] = []; let users: User[] = [];
if (isUsername) { if (isUsername) {
const usernameQuery = Users.createQueryBuilder('user') const usernameQuery = Users.createQueryBuilder('user')
.where('user.usernameLower like :username', { username: ps.query.replace('@', '').toLowerCase() + '%' }) .where('user.usernameLower LIKE :username', { username: ps.query.replace('@', '').toLowerCase() + '%' })
.andWhere(new Brackets(qb => { qb .andWhere(new Brackets(qb => { qb
.where('user.lastActiveDate IS NULL') .where('user.updatedAt IS NULL')
.orWhere('user.lastActiveDate > :activeThreshold', { activeThreshold: new Date(Date.now() - USER_ACTIVE_THRESHOLD) }); .orWhere('user.updatedAt > :activeThreshold', { activeThreshold: activeThreshold });
})) }))
.andWhere('user.isSuspended = FALSE'); .andWhere('user.isSuspended = FALSE');
if (ps.scope === 'local') { if (ps.origin === 'local') {
usernameQuery usernameQuery.andWhere('user.host IS NULL');
.andWhere('user.host IS NULL') } else if (ps.origin === 'remote') {
.orderBy('user.lastActiveDate', 'DESC', 'NULLS LAST'); usernameQuery.andWhere('user.host IS NOT NULL');
} else if (ps.scope === 'remote') {
usernameQuery
.andWhere('user.host IS NOT NULL')
.orderBy('user.updatedAt', 'DESC', 'NULLS LAST');
} else { // both
usernameQuery
.orderBy('user.updatedAt', 'DESC', 'NULLS LAST');
} }
users = await usernameQuery users = await usernameQuery
.orderBy('user.updatedAt', 'DESC', 'NULLS LAST')
.take(ps.limit!) .take(ps.limit!)
.skip(ps.offset) .skip(ps.offset)
.getMany(); .getMany();
} else { } else {
const nameQuery = Users.createQueryBuilder('user') const nameQuery = Users.createQueryBuilder('user')
.where('user.name ilike :query', { query: '%' + ps.query + '%' }) .where('user.name ILIKE :query', { query: '%' + ps.query + '%' })
.andWhere(new Brackets(qb => { qb .andWhere(new Brackets(qb => { qb
.where('user.lastActiveDate IS NULL') .where('user.updatedAt IS NULL')
.orWhere('user.lastActiveDate > :activeThreshold', { activeThreshold: new Date(Date.now() - USER_ACTIVE_THRESHOLD) }); .orWhere('user.updatedAt > :activeThreshold', { activeThreshold: activeThreshold });
})) }))
.andWhere('user.isSuspended = FALSE'); .andWhere('user.isSuspended = FALSE');
if (ps.scope === 'local') { if (ps.origin === 'local') {
nameQuery nameQuery.andWhere('user.host IS NULL');
.andWhere('user.host IS NULL') } else if (ps.origin === 'remote') {
.orderBy('user.lastActiveDate', 'DESC', 'NULLS LAST'); nameQuery.andWhere('user.host IS NOT NULL');
} else if (ps.scope === 'remote') {
nameQuery
.andWhere('user.host IS NOT NULL')
.orderBy('user.updatedAt', 'DESC', 'NULLS LAST');
} else { // both
nameQuery
.orderBy('user.updatedAt', 'DESC', 'NULLS LAST');
} }
users = await nameQuery users = await nameQuery
.orderBy('user.updatedAt', 'DESC', 'NULLS LAST')
.take(ps.limit!) .take(ps.limit!)
.skip(ps.offset) .skip(ps.offset)
.getMany(); .getMany();
@ -108,32 +97,25 @@ export default define(meta, async (ps, me) => {
if (users.length < ps.limit!) { if (users.length < ps.limit!) {
const profQuery = UserProfiles.createQueryBuilder('prof') const profQuery = UserProfiles.createQueryBuilder('prof')
.select('prof.userId') .select('prof.userId')
.where('prof.description ilike :query', { query: '%' + ps.query + '%' }); .where('prof.description ILIKE :query', { query: '%' + ps.query + '%' });
if (ps.scope === 'local') { if (ps.origin === 'local') {
profQuery.andWhere('prof.userHost IS NULL'); profQuery.andWhere('prof.userHost IS NULL');
} else if (ps.scope === 'remote') { } else if (ps.origin === 'remote') {
profQuery.andWhere('prof.userHost IS NOT NULL'); profQuery.andWhere('prof.userHost IS NOT NULL');
} }
const query = Users.createQueryBuilder('user') const query = Users.createQueryBuilder('user')
.where(`user.id IN (${ profQuery.getQuery() })`) .where(`user.id IN (${ profQuery.getQuery() })`)
.andWhere(new Brackets(qb => { qb .andWhere(new Brackets(qb => { qb
.where('user.lastActiveDate IS NULL') .where('user.updatedAt IS NULL')
.orWhere('user.lastActiveDate > :activeThreshold', { activeThreshold: new Date(Date.now() - USER_ACTIVE_THRESHOLD) }); .orWhere('user.updatedAt > :activeThreshold', { activeThreshold: activeThreshold });
})) }))
.andWhere('user.isSuspended = FALSE') .andWhere('user.isSuspended = FALSE')
.setParameters(profQuery.getParameters()); .setParameters(profQuery.getParameters());
if (ps.scope === 'local') {
query.orderBy('user.lastActiveDate', 'DESC', 'NULLS LAST');
} else if (ps.scope === 'remote') {
query.orderBy('user.updatedAt', 'DESC', 'NULLS LAST');
} else { // both
query.orderBy('user.updatedAt', 'DESC', 'NULLS LAST');
}
users = users.concat(await query users = users.concat(await query
.orderBy('user.updatedAt', 'DESC', 'NULLS LAST')
.take(ps.limit!) .take(ps.limit!)
.skip(ps.offset) .skip(ps.offset)
.getMany() .getMany()