diff options
| author | Sayamame-beans <61457993+Sayamame-beans@users.noreply.github.com> | 2024-07-30 19:18:43 +0900 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-07-30 19:18:43 +0900 |
| commit | d0b7c74fd15673604a682726c817c57475cfa5d4 (patch) | |
| tree | 6b27b20d66cadcd3a14f2275319da2b698dc0bec /packages/backend/src/server/api/endpoints | |
| parent | fix(misskey-js): misskey-js.api.mdのコミット漏れ修正 (#14329) (diff) | |
| download | sharkey-d0b7c74fd15673604a682726c817c57475cfa5d4.tar.gz sharkey-d0b7c74fd15673604a682726c817c57475cfa5d4.tar.bz2 sharkey-d0b7c74fd15673604a682726c817c57475cfa5d4.zip | |
検索からハッシュタグのページが開けるように、users/searchに`@`から始まる文字列が与えられた際の処理を修正 等 (#13858)
* enhance(frontend): 検索からハッシュタグのページを開けるように
* fix(frontend): 照会で入力が`#`のみの場合は`/tags/`に遷移しないように
* docs(changelog): update changelog
* enhance(frontend): ユーザー検索からもハッシュタグのページを開けるように
* docs(changelog): update changelog
* enhance(frontend): 検索範囲等が指定されている時は照会/ハッシュタグページを開かないように
* enhance(frontend): 検索内容に空白が含まれている場合は照会/ハッシュタグページを開かないように
* docs(changelog): update changelog
* Revert "enhance(frontend): 検索範囲等が指定されている時は照会/ハッシュタグページを開かないように"
This reverts commit f84eecea964b90e9b115eac19ed6f19a603a6bbc.
* enhance(frontend): 検索から照会/ハッシュタグページを開くかどうか確認するように
* docs(changelog): update changelog
* chore: fix lint
* docs(changelog): update changelog insertion position
* enhance(frontend): 検索から`@user@host`の形式で照会出来るように
* fix(frontend): 照会で入力が`@`のみの場合に`/@`に遷移しないように
* fix(backend): `users/search`において`@`から始まるqueryに対する処理が正しくなかった問題を修正
* docs(changelog): update changelog
* chore(backend): fix lint error
* fix(backend): more improvements for users/search when query startswith `@`
* chore: unify common conditions
* docs(changelog): refine changelog
* chore(backend): fix lint error
* MkInputをpreventに対応させ、enterの意図せぬ伝搬を防ぐ
* chore(frontend/search.user): use .prevent to prevent the propagation of enter instead of setTimeout
---------
Co-authored-by: samunohito <46447427+samunohito@users.noreply.github.com>
Co-authored-by: syuilo <4439005+syuilo@users.noreply.github.com>
Co-authored-by: taichanne30 <dev@taichan.site>
Diffstat (limited to 'packages/backend/src/server/api/endpoints')
| -rw-r--r-- | packages/backend/src/server/api/endpoints/users/search.ts | 108 |
1 files changed, 43 insertions, 65 deletions
diff --git a/packages/backend/src/server/api/endpoints/users/search.ts b/packages/backend/src/server/api/endpoints/users/search.ts index df9d9f6312..0b0136066d 100644 --- a/packages/backend/src/server/api/endpoints/users/search.ts +++ b/packages/backend/src/server/api/endpoints/users/search.ts @@ -57,88 +57,66 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint- const activeThreshold = new Date(Date.now() - (1000 * 60 * 60 * 24 * 30)); // 30日 ps.query = ps.query.trim(); - const isUsername = ps.query.startsWith('@'); + const isUsername = ps.query.startsWith('@') && !ps.query.includes(' ') && ps.query.indexOf('@', 1) === -1; let users: MiUser[] = []; - if (isUsername) { - const usernameQuery = this.usersRepository.createQueryBuilder('user') - .where('user.usernameLower LIKE :username', { username: sqlLikeEscape(ps.query.replace('@', '').toLowerCase()) + '%' }) - .andWhere(new Brackets(qb => { - qb - .where('user.updatedAt IS NULL') - .orWhere('user.updatedAt > :activeThreshold', { activeThreshold: activeThreshold }); - })) - .andWhere('user.isSuspended = FALSE'); + const nameQuery = this.usersRepository.createQueryBuilder('user') + .where(new Brackets(qb => { + qb.where('user.name ILIKE :query', { query: '%' + sqlLikeEscape(ps.query) + '%' }); + + if (isUsername) { + qb.orWhere('user.usernameLower LIKE :username', { username: sqlLikeEscape(ps.query.replace('@', '').toLowerCase()) + '%' }); + } else if (this.userEntityService.validateLocalUsername(ps.query)) { // Also search username if it qualifies as username + qb.orWhere('user.usernameLower LIKE :username', { username: '%' + sqlLikeEscape(ps.query.toLowerCase()) + '%' }); + } + })) + .andWhere(new Brackets(qb => { + qb + .where('user.updatedAt IS NULL') + .orWhere('user.updatedAt > :activeThreshold', { activeThreshold: activeThreshold }); + })) + .andWhere('user.isSuspended = FALSE'); + + if (ps.origin === 'local') { + nameQuery.andWhere('user.host IS NULL'); + } else if (ps.origin === 'remote') { + nameQuery.andWhere('user.host IS NOT NULL'); + } + + users = await nameQuery + .orderBy('user.updatedAt', 'DESC', 'NULLS LAST') + .limit(ps.limit) + .offset(ps.offset) + .getMany(); + + if (users.length < ps.limit) { + const profQuery = this.userProfilesRepository.createQueryBuilder('prof') + .select('prof.userId') + .where('prof.description ILIKE :query', { query: '%' + sqlLikeEscape(ps.query) + '%' }); if (ps.origin === 'local') { - usernameQuery.andWhere('user.host IS NULL'); + profQuery.andWhere('prof.userHost IS NULL'); } else if (ps.origin === 'remote') { - usernameQuery.andWhere('user.host IS NOT NULL'); + profQuery.andWhere('prof.userHost IS NOT NULL'); } - users = await usernameQuery - .orderBy('user.updatedAt', 'DESC', 'NULLS LAST') - .limit(ps.limit) - .offset(ps.offset) - .getMany(); - } else { - const nameQuery = this.usersRepository.createQueryBuilder('user') - .where(new Brackets(qb => { - qb.where('user.name ILIKE :query', { query: '%' + sqlLikeEscape(ps.query) + '%' }); - - // Also search username if it qualifies as username - if (this.userEntityService.validateLocalUsername(ps.query)) { - qb.orWhere('user.usernameLower LIKE :username', { username: '%' + sqlLikeEscape(ps.query.toLowerCase()) + '%' }); - } - })) + const query = this.usersRepository.createQueryBuilder('user') + .where(`user.id IN (${ profQuery.getQuery() })`) .andWhere(new Brackets(qb => { qb .where('user.updatedAt IS NULL') .orWhere('user.updatedAt > :activeThreshold', { activeThreshold: activeThreshold }); })) - .andWhere('user.isSuspended = FALSE'); - - if (ps.origin === 'local') { - nameQuery.andWhere('user.host IS NULL'); - } else if (ps.origin === 'remote') { - nameQuery.andWhere('user.host IS NOT NULL'); - } + .andWhere('user.isSuspended = FALSE') + .setParameters(profQuery.getParameters()); - users = await nameQuery + users = users.concat(await query .orderBy('user.updatedAt', 'DESC', 'NULLS LAST') .limit(ps.limit) .offset(ps.offset) - .getMany(); - - if (users.length < ps.limit) { - const profQuery = this.userProfilesRepository.createQueryBuilder('prof') - .select('prof.userId') - .where('prof.description ILIKE :query', { query: '%' + sqlLikeEscape(ps.query) + '%' }); - - if (ps.origin === 'local') { - profQuery.andWhere('prof.userHost IS NULL'); - } else if (ps.origin === 'remote') { - profQuery.andWhere('prof.userHost IS NOT NULL'); - } - - const query = this.usersRepository.createQueryBuilder('user') - .where(`user.id IN (${ profQuery.getQuery() })`) - .andWhere(new Brackets(qb => { - qb - .where('user.updatedAt IS NULL') - .orWhere('user.updatedAt > :activeThreshold', { activeThreshold: activeThreshold }); - })) - .andWhere('user.isSuspended = FALSE') - .setParameters(profQuery.getParameters()); - - users = users.concat(await query - .orderBy('user.updatedAt', 'DESC', 'NULLS LAST') - .limit(ps.limit) - .offset(ps.offset) - .getMany(), - ); - } + .getMany(), + ); } return await this.userEntityService.packMany(users, me, { schema: ps.detail ? 'UserDetailed' : 'UserLite' }); |