Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enhance: 高度な検索でフォロー中/フォロー外を検索条件にできるように #503

Merged
merged 2 commits into from
Oct 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG_YOJO.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ Cherrypick 4.11.1
- Enhance: ノートにつけられたリアクションを対象にした検索ができるように
- Opensearchのみ対応
- Opensearchの設定で` reactionSearchLocalOnly: true`にすることでリモートのカスタム絵文字リアクションをインデックス対象外にできます
- Enhance: 高度な検索でフォロー中/フォロー外を検索条件にできるように
- Fix: 照会かリモートユーザーの投稿取得で作成されたノートの場合通知を発行しないように
- Enhance(Opensearch): 表記ゆれがヒットしないようにするオプションを追加

Expand Down
18 changes: 18 additions & 0 deletions locales/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11891,6 +11891,24 @@ export interface Locale extends ILocale {
*/
"endDate": string;
};
"_followingFilter": {
/**
* フォローフィルター
*/
"title": string;
/**
* フィルタしない
*/
"combined": string;
/**
* フォロー中
*/
"following": string;
/**
* フォロー外
*/
"notFollowing": string;
};
"_description": {
/**
* その他の設定
Expand Down
5 changes: 5 additions & 0 deletions locales/ja-JP.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3169,6 +3169,11 @@ _advancedSearch:
_specifyDate:
startDate: "から"
endDate: "まで"
_followingFilter:
title: "フォローフィルター"
combined: "フィルタしない"
following: "フォロー中"
notFollowing: "フォロー外"
_description:
other: "その他の設定"
_fileNsfwOption:
Expand Down
18 changes: 14 additions & 4 deletions packages/backend/src/core/AdvancedSearchService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -782,6 +782,7 @@ export class AdvancedSearchService {
excludeReply?: boolean;
excludeQuote?: boolean;
sensitiveFilter?: string | null;
followingFilter?: string | null;
offset?: number | null;
useStrictSearch?: boolean | null;
}, pagination: {
Expand Down Expand Up @@ -920,7 +921,7 @@ export class AdvancedSearchService {
});
}

const Result = await this.search(Option, pagination.untilId ? 1 : 0, me ? me.id : undefined);
const Result = await this.search(Option, pagination.untilId ? 1 : 0, opts.followingFilter ?? 'combined', me ? me.id : undefined);
if (Result.length === 0) {
return [];
}
Expand Down Expand Up @@ -997,7 +998,11 @@ export class AdvancedSearchService {
}
}

this.queryService.generateVisibilityQuery(query, me);
if (opts.followingFilter) {
this.queryService.generateVisibilityQuery(query, me, opts.followingFilter);
} else {
this.queryService.generateVisibilityQuery(query, me);
}
this.queryService.generateSearchableQuery(query, me);
if (me) this.queryService.generateMutedUserQuery(query, me);
if (me) this.queryService.generateBlockedUserQuery(query, me);
Expand All @@ -1010,6 +1015,7 @@ export class AdvancedSearchService {
private async search(
OpenSearchOption: any,
untilAvail: number,
followingFilter: string,
meUserId?: string,
): Promise<any[]> {
if (!this.opensearch) throw new Error();
Expand All @@ -1030,7 +1036,7 @@ export class AdvancedSearchService {
notes = res.body.hits.hits as OpenSearchHit[];
if (notes.length === 0) break;//これ以上探してもない

const resultPromises = notes.map(x => this.filter(x, Filter, Followings, meUserId));
const resultPromises = notes.map(x => this.filter(x, Filter, Followings, followingFilter, meUserId));
const Results = (await Promise.all(resultPromises)).filter( (x) => x !== null);

if (Results.length > 0) {
Expand Down Expand Up @@ -1060,12 +1066,16 @@ export class AdvancedSearchService {
Note: OpenSearchHit,
Filter: string[],
Followings: string[],
meUserId?: string): Promise<OpenSearchHit| null> {
followingFilter: string,
meUserId?: string ): Promise<OpenSearchHit| null> {
if (meUserId) {//ミュートしているか、ブロックされている
if (Filter.includes(Note._source.userId) ) return null;
if (Note._source.referenceUserId) {
if (Filter.includes(Note._source.referenceUserId)) return null;
}
if (followingFilter === 'following' && !Followings.includes(Note._source.userId)) return null;
if (followingFilter === 'notFollowing' && Followings.includes(Note._source.userId)) return null;

if (Note._source.userId === meUserId) {//自分のノート
return Note;
}
Expand Down
7 changes: 6 additions & 1 deletion packages/backend/src/core/QueryService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,7 @@ export class QueryService {
}

@bindThis
public generateVisibilityQuery(q: SelectQueryBuilder<any>, me?: { id: MiUser['id'] } | null): void {
public generateVisibilityQuery(q: SelectQueryBuilder<any>, me?: { id: MiUser['id'] } | null, followingFilter?: string): void {
// This code must always be synchronized with the checks in Notes.isVisibleForMe.
if (me == null) {
q.andWhere(new Brackets(qb => {
Expand All @@ -201,6 +201,11 @@ export class QueryService {
.select('following.followeeId')
.where('following.followerId = :meId');

if (followingFilter) {
if (followingFilter === 'following') q.andWhere(`note.userId IN (${ followingQuery.getQuery() })`);
if (followingFilter === 'notFollowing') q.andWhere(`note.userId NOT IN (${ followingQuery.getQuery() })`);
}

q.andWhere(new Brackets(qb => {
qb
// 公開投稿である
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,12 @@ export const paramDef = {
default: 'combined',
description: '添付ファイルのセンシティブ状態',
},
followingFilter: {
type: 'string',
enum: ['following', 'notFollowing', 'combined'],
default: 'combined',
description: 'ユーザーのフォロー状態',
},
offset: {
type: 'integer',
default: 0,
Expand Down Expand Up @@ -163,6 +169,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
origin: ps.origin,
fileOption: ps.fileOption,
sensitiveFilter: ps.sensitiveFilter,
followingFilter: ps.followingFilter,
excludeCW: ps.excludeCW,
excludeReply: ps.excludeReply,
excludeQuote: ps.excludeQuote,
Expand Down
6 changes: 6 additions & 0 deletions packages/cherrypick-js/src/autogen/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23621,6 +23621,12 @@ export type operations = {
* @enum {string}
*/
sensitiveFilter?: 'includeSensitive' | 'withOutSensitive' | 'sensitiveOnly' | 'combined';
/**
* @description ユーザーのフォロー状態
* @default combined
* @enum {string}
*/
followingFilter?: 'following' | 'notFollowing' | 'combined';
/**
* @description 指定された件数の以降のノートを返します
* @default 0
Expand Down
12 changes: 12 additions & 0 deletions packages/frontend/src/pages/search.anote.vue
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,16 @@ SPDX-License-Identifier: AGPL-3.0-only
</div>
</div>
</FormSection>
<FormSection>
<template #label>{{ i18n.ts._advancedSearch._followingFilter.title }}</template>
<div style="text-align: center;" class="_gaps_m">
<MkRadios v-model="followingFilter" @update:modelValue="search()">
<option value="combined">{{ i18n.ts._advancedSearch._followingFilter.combined }}</option>
<option value="following">{{ i18n.ts._advancedSearch._followingFilter.following }}</option>
<option value="notFollowing">{{ i18n.ts._advancedSearch._followingFilter.notFollowing }}</option>
</MkRadios>
</div>
</FormSection>
<FormSection>
<template #label>{{ i18n.ts.other }}</template>
<template #caption>{{ i18n.ts._advancedSearch._description.other }}</template>
Expand Down Expand Up @@ -125,6 +135,7 @@ const excludeCW = ref(false);
const excludeReply = ref(false);
const excludeQuote = ref(false);
const sensitiveFilter = ref('combined');
const followingFilter = ref('combined');
const hostInput = ref('');
const emojiSearchQuery = ref('');
const emojiExcludeSearchQuery = ref('');
Expand Down Expand Up @@ -228,6 +239,7 @@ async function search() {
excludeReply: excludeReply.value,
excludeQuote: excludeQuote.value,
sensitiveFilter: sensitiveFilter.value,
followingFilter: followingFilter.value,
useStrictSearch: strictSearch.value,
},
};
Expand Down
Loading