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

Fix messages search #339

Merged
merged 19 commits into from
Aug 28, 2024
6 changes: 6 additions & 0 deletions packages/backend/src/core/CoreModule.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ import { ImageProcessingService } from './ImageProcessingService.js';
import { InstanceActorService } from './InstanceActorService.js';
import { InternalStorageService } from './InternalStorageService.js';
import { MessagingService } from './MessagingService.js';
import { DirectMessageSearchService } from './DirectMessageSearchService.js';
import { MetaService } from './MetaService.js';
import { MfmService } from './MfmService.js';
import { ModerationLogService } from './ModerationLogService.js';
Expand Down Expand Up @@ -189,6 +190,7 @@ const $ImageProcessingService: Provider = { provide: 'ImageProcessingService', u
const $InstanceActorService: Provider = { provide: 'InstanceActorService', useExisting: InstanceActorService };
const $InternalStorageService: Provider = { provide: 'InternalStorageService', useExisting: InternalStorageService };
const $MessagingService: Provider = { provide: 'MessagingService', useExisting: MessagingService };
const $DirectMessageSearchService: Provider = { provide: 'DirectMessageSearchService', useExisting: DirectMessageSearchService };
const $MetaService: Provider = { provide: 'MetaService', useExisting: MetaService };
const $MfmService: Provider = { provide: 'MfmService', useExisting: MfmService };
const $ModerationLogService: Provider = { provide: 'ModerationLogService', useExisting: ModerationLogService };
Expand Down Expand Up @@ -346,6 +348,7 @@ const $ApGameService: Provider = { provide: 'ApGameService', useExisting: ApGame
InstanceActorService,
InternalStorageService,
MessagingService,
DirectMessageSearchService,
MetaService,
MfmService,
ModerationLogService,
Expand Down Expand Up @@ -499,6 +502,7 @@ const $ApGameService: Provider = { provide: 'ApGameService', useExisting: ApGame
$InstanceActorService,
$InternalStorageService,
$MessagingService,
$DirectMessageSearchService,
$MetaService,
$MfmService,
$ModerationLogService,
Expand Down Expand Up @@ -653,6 +657,7 @@ const $ApGameService: Provider = { provide: 'ApGameService', useExisting: ApGame
InstanceActorService,
InternalStorageService,
MessagingService,
DirectMessageSearchService,
MetaService,
MfmService,
ModerationLogService,
Expand Down Expand Up @@ -805,6 +810,7 @@ const $ApGameService: Provider = { provide: 'ApGameService', useExisting: ApGame
$InstanceActorService,
$InternalStorageService,
$MessagingService,
$DirectMessageSearchService,
$MetaService,
$MfmService,
$ModerationLogService,
Expand Down
28 changes: 23 additions & 5 deletions packages/backend/src/core/DirectMessageSearchService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@
*/

import { Inject, Injectable } from '@nestjs/common';
import { Brackets } from 'typeorm';
import { DI } from '@/di-symbols.js';
import type { MessagingMessagesRepository, UserGroupJoiningsRepository } from '@/models/_.js';
import type { BlockingsRepository, MessagingMessagesRepository, MutingsRepository, UserGroupJoiningsRepository } from '@/models/_.js';
import type { MiMessagingMessage } from '@/models/MessagingMessage.js';
import type { MiUser } from '@/models/User.js';
import type { Config } from '@/config.js';
Expand Down Expand Up @@ -42,6 +43,12 @@ export class DirectMessageSearchService {
@Inject(DI.userGroupJoiningsRepository)
private userGroupJoiningsRepository: UserGroupJoiningsRepository,

@Inject(DI.mutingsRepository)
private mutingsRepository: MutingsRepository,

@Inject(DI.blockingsRepository)
private blockingsRepository: BlockingsRepository,

private cacheService: CacheService,
private queryService: QueryService,
private userEntityService: UserEntityService,
Expand All @@ -58,16 +65,27 @@ export class DirectMessageSearchService {
sinceId?: MiMessagingMessage['id'];
limit?: number;
}): Promise<MiMessagingMessage[]> {
if (me === null) return [];
const query = this.queryService.makePaginationQuery(this.messagingMessagesRepository.createQueryBuilder('message'), pagination.sinceId, pagination.untilId);

query
.andWhere('message.text ILIKE :q', { q: `%${ sqlLikeEscape(q)}%` })
.innerJoinAndSelect('message.user', 'user')
.leftJoinAndSelect('message.group', 'group');

this.queryService.generateVisibilityQuery(query, me);
if (me) this.queryService.generateMutedUserQuery(query, me);
if (me) this.queryService.generateBlockedUserQuery(query, me);
if (opts.groupId) {
query.andWhere(new Brackets(qb => {
qb
.where('message.groupId IN (:...groups)', { groups: [opts.groupId] })
.orWhere(':userId = ANY(message.reads)', { userId: me.id });
}));
} else {
query.andWhere(new Brackets(qb => {
qb
.where('message.userId = :userId', { userId: me.id })
.orWhere('message.recipientId = :userId', { userId: me.id });
}));
query.andWhere('message.groupId IS NULL');
}

return await query.limit(pagination.limit).getMany();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,5 +60,18 @@ export class MessagingMessageEntityService {
reads: message.reads,
};
}
@bindThis
public async packMany(
messages: MiMessagingMessage[],
me: MiUser | null,
options?: {
populateRecipient?: boolean,
populateGroup?: boolean,
},
) : Promise<Packed<'MessagingMessage'>[]> {
return (await Promise.allSettled(messages.map(x => this.pack(x, me, options))))
.filter(result => result.status === 'fulfilled')
.map(result => (result as PromiseFulfilledResult<Packed<'MessagingMessage'>>).value);
}
}

4 changes: 4 additions & 0 deletions packages/backend/src/server/api/EndpointsModule.ts
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,7 @@ import * as ep___messaging_messages from './endpoints/messaging/messages.js';
import * as ep___messaging_messages_create from './endpoints/messaging/messages/create.js';
import * as ep___messaging_messages_delete from './endpoints/messaging/messages/delete.js';
import * as ep___messaging_messages_read from './endpoints/messaging/messages/read.js';
import * as ep___messaging_messages_search from './endpoints/messaging/messages/search.js';
import * as ep___meta from './endpoints/meta.js';
import * as ep___emojis from './endpoints/emojis.js';
import * as ep___emoji from './endpoints/emoji.js';
Expand Down Expand Up @@ -677,6 +678,7 @@ const $messaging_messages: Provider = { provide: 'ep:messaging/messages', useCla
const $messaging_messages_create: Provider = { provide: 'ep:messaging/messages/create', useClass: ep___messaging_messages_create.default };
const $messaging_messages_delete: Provider = { provide: 'ep:messaging/messages/delete', useClass: ep___messaging_messages_delete.default };
const $messaging_messages_read: Provider = { provide: 'ep:messaging/messages/read', useClass: ep___messaging_messages_read.default };
const $messaging_messages_search: Provider = { provide: 'ep:messaging/messages/search', useClass: ep___messaging_messages_search.default };
const $meta: Provider = { provide: 'ep:meta', useClass: ep___meta.default };
const $emojis: Provider = { provide: 'ep:emojis', useClass: ep___emojis.default };
const $emoji: Provider = { provide: 'ep:emoji', useClass: ep___emoji.default };
Expand Down Expand Up @@ -1091,6 +1093,7 @@ const $reversi_verify: Provider = { provide: 'ep:reversi/verify', useClass: ep__
$messaging_messages_create,
$messaging_messages_delete,
$messaging_messages_read,
$messaging_messages_search,
$meta,
$emojis,
$emoji,
Expand Down Expand Up @@ -1497,6 +1500,7 @@ const $reversi_verify: Provider = { provide: 'ep:reversi/verify', useClass: ep__
$messaging_messages_create,
$messaging_messages_delete,
$messaging_messages_read,
$messaging_messages_search,
$meta,
$emojis,
$emoji,
Expand Down
2 changes: 2 additions & 0 deletions packages/backend/src/server/api/endpoints.ts
Original file line number Diff line number Diff line change
Expand Up @@ -273,6 +273,7 @@ import * as ep___messaging_messages from './endpoints/messaging/messages.js';
import * as ep___messaging_messages_create from './endpoints/messaging/messages/create.js';
import * as ep___messaging_messages_delete from './endpoints/messaging/messages/delete.js';
import * as ep___messaging_messages_read from './endpoints/messaging/messages/read.js';
import * as ep___messaging_messages_search from './endpoints/messaging/messages/search.js';
import * as ep___meta from './endpoints/meta.js';
import * as ep___emojis from './endpoints/emojis.js';
import * as ep___emoji from './endpoints/emoji.js';
Expand Down Expand Up @@ -680,6 +681,7 @@ const eps = [
['messaging/messages/create', ep___messaging_messages_create],
['messaging/messages/delete', ep___messaging_messages_delete],
['messaging/messages/read', ep___messaging_messages_read],
['messaging/messages/search', ep___messaging_messages_search],
['meta', ep___meta],
['emojis', ep___emojis],
['emoji', ep___emoji],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,16 @@
*/

import { Injectable } from '@nestjs/common';
import { id } from 'date-fns/locale';
import { Endpoint } from '@/server/api/endpoint-base.js';
import { MessagingMessageEntityService } from '@/core/entities/MessagingMessageEntityService.js';
import { DirectMessageSearchService } from '@/core/DirectMessageSearchService.js';
import { ApiError } from '@/server/api/error.js';
import { GetterService } from '@/server/api/GetterService.js';

export const meta = {
tags: ['messaging'],
requireCredentail: false,

requireCredential: true,
kind: 'read:messaging',

res: {
type: 'array',
optional: false, nullable: false,
Expand Down Expand Up @@ -47,11 +47,10 @@ export const paramDef = {
} as const;

@Injectable()
export default class extends Endpoint<typeof meta, typeof paramDef> {
export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-disable-line import/no-default-export
constructor(
private messagingMessageEntityService: MessagingMessageEntityService,
private directMessageSearchService: DirectMessageSearchService,
private getterService: GetterService,
) {
super(meta, paramDef, async (ps, me) => {
const message = await this.directMessageSearchService.searchMessages(ps.query, me, {
Expand Down
8 changes: 8 additions & 0 deletions packages/cherrypick-js/etc/cherrypick-js.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -1575,6 +1575,8 @@ declare namespace entities {
MessagingMessagesCreateResponse,
MessagingMessagesDeleteRequest,
MessagingMessagesReadRequest,
MessagingMessagesSearchRequest,
MessagingMessagesSearchResponse,
MetaRequest,
MetaResponse,
EmojisResponse,
Expand Down Expand Up @@ -2397,6 +2399,12 @@ type MessagingMessagesRequest = operations['messaging___messages']['requestBody'
// @public (undocumented)
type MessagingMessagesResponse = operations['messaging___messages']['responses']['200']['content']['application/json'];

// @public (undocumented)
type MessagingMessagesSearchRequest = operations['messaging___messages___search']['requestBody']['content']['application/json'];

// @public (undocumented)
type MessagingMessagesSearchResponse = operations['messaging___messages___search']['responses']['200']['content']['application/json'];

// @public (undocumented)
type MetaDetailed = components['schemas']['MetaDetailed'];

Expand Down
11 changes: 11 additions & 0 deletions packages/cherrypick-js/src/autogen/apiClientJSDoc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2923,6 +2923,17 @@ declare module '../api.js' {
credential?: string | null,
): Promise<SwitchCaseResponseType<E, P>>;

/**
* No description provided.
*
* **Credential required**: *Yes* / **Permission**: *read:messaging*
*/
request<E extends 'messaging/messages/search', P extends Endpoints[E]['req']>(
endpoint: E,
params: P,
credential?: string | null,
): Promise<SwitchCaseResponseType<E, P>>;

/**
* No description provided.
*
Expand Down
4 changes: 4 additions & 0 deletions packages/cherrypick-js/src/autogen/endpoint.ts
Original file line number Diff line number Diff line change
Expand Up @@ -383,6 +383,8 @@ import type {
MessagingMessagesCreateResponse,
MessagingMessagesDeleteRequest,
MessagingMessagesReadRequest,
MessagingMessagesSearchRequest,
MessagingMessagesSearchResponse,
MetaRequest,
MetaResponse,
EmojisResponse,
Expand Down Expand Up @@ -867,6 +869,7 @@ export type Endpoints = {
'messaging/messages/create': { req: MessagingMessagesCreateRequest; res: MessagingMessagesCreateResponse };
'messaging/messages/delete': { req: MessagingMessagesDeleteRequest; res: EmptyResponse };
'messaging/messages/read': { req: MessagingMessagesReadRequest; res: EmptyResponse };
'messaging/messages/search': { req: MessagingMessagesSearchRequest; res: MessagingMessagesSearchResponse };
'meta': { req: MetaRequest; res: MetaResponse };
'emojis': { req: EmptyRequest; res: EmojisResponse };
'emoji': { req: EmojiRequest; res: EmojiResponse };
Expand Down Expand Up @@ -1275,6 +1278,7 @@ export const endpointReqTypes: Record<keyof Endpoints, 'application/json' | 'mul
'messaging/messages/create': 'application/json',
'messaging/messages/delete': 'application/json',
'messaging/messages/read': 'application/json',
'messaging/messages/search': 'application/json',
'meta': 'application/json',
'emojis': 'application/json',
'emoji': 'application/json',
Expand Down
2 changes: 2 additions & 0 deletions packages/cherrypick-js/src/autogen/entities.ts
Original file line number Diff line number Diff line change
Expand Up @@ -386,6 +386,8 @@ export type MessagingMessagesCreateRequest = operations['messaging___messages___
export type MessagingMessagesCreateResponse = operations['messaging___messages___create']['responses']['200']['content']['application/json'];
export type MessagingMessagesDeleteRequest = operations['messaging___messages___delete']['requestBody']['content']['application/json'];
export type MessagingMessagesReadRequest = operations['messaging___messages___read']['requestBody']['content']['application/json'];
export type MessagingMessagesSearchRequest = operations['messaging___messages___search']['requestBody']['content']['application/json'];
export type MessagingMessagesSearchResponse = operations['messaging___messages___search']['responses']['200']['content']['application/json'];
export type MetaRequest = operations['meta']['requestBody']['content']['application/json'];
export type MetaResponse = operations['meta']['responses']['200']['content']['application/json'];
export type EmojisResponse = operations['emojis']['responses']['200']['content']['application/json'];
Expand Down
78 changes: 78 additions & 0 deletions packages/cherrypick-js/src/autogen/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2522,6 +2522,15 @@ export type paths = {
*/
post: operations['messaging___messages___read'];
};
'/messaging/messages/search': {
/**
* messaging/messages/search
* @description No description provided.
*
* **Credential required**: *Yes* / **Permission**: *read:messaging*
*/
post: operations['messaging___messages___search'];
};
'/meta': {
/**
* meta
Expand Down Expand Up @@ -21047,6 +21056,75 @@ export type operations = {
};
};
};
/**
* messaging/messages/search
* @description No description provided.
*
* **Credential required**: *Yes* / **Permission**: *read:messaging*
*/
messaging___messages___search: {
requestBody: {
content: {
'application/json': {
query: string;
/** Format: misskey:id */
sinceId?: string;
/** Format: misskey:id */
untilId?: string;
/** @default 10 */
limit?: number;
/**
* Format: misskey:id
* @default null
*/
recipientId?: string | null;
/**
* Format: misskey:id
* @default null
*/
groupId?: string | null;
};
};
};
responses: {
/** @description OK (with results) */
200: {
content: {
'application/json': components['schemas']['MessagingMessage'][];
};
};
/** @description Client error */
400: {
content: {
'application/json': components['schemas']['Error'];
};
};
/** @description Authentication error */
401: {
content: {
'application/json': components['schemas']['Error'];
};
};
/** @description Forbidden error */
403: {
content: {
'application/json': components['schemas']['Error'];
};
};
/** @description I'm Ai */
418: {
content: {
'application/json': components['schemas']['Error'];
};
};
/** @description Internal server error */
500: {
content: {
'application/json': components['schemas']['Error'];
};
};
};
};
/**
* meta
* @description No description provided.
Expand Down
Loading