diff --git a/src/api/chats.controller.ts b/src/api/chats.controller.ts index 943a6b43..a6bc13f8 100644 --- a/src/api/chats.controller.ts +++ b/src/api/chats.controller.ts @@ -29,6 +29,7 @@ import { GetChatMessageQuery, GetChatMessagesFilter, GetChatMessagesQuery, + MessageSortField, OverviewBodyRequest, OverviewFilter, OverviewPaginationParams, @@ -38,6 +39,7 @@ import { transformAck, } from '../structures/chats.dto'; import { EditMessageRequest } from '../structures/chatting.dto'; +import { SortOrder } from '@waha/structures/pagination.dto'; @ApiSecurity('api_key') @Controller('api/:session/chats') @@ -120,6 +122,8 @@ class ChatsController { @WorkingSessionParam session: WhatsappSession, @Param('chatId') chatId: string, ) { + query.sortBy = query.sortBy || MessageSortField.TIMESTAMP; + query.sortOrder = query.sortOrder || SortOrder.DESC; filter = transformAck(filter); return session.getChatMessages(chatId, query, filter); } diff --git a/src/core/engines/gows/grpc/gows.ts b/src/core/engines/gows/grpc/gows.ts index 14a0ce40..f76a7050 100644 --- a/src/core/engines/gows/grpc/gows.ts +++ b/src/core/engines/gows/grpc/gows.ts @@ -8718,6 +8718,7 @@ export namespace messages { session?: Session; filters?: MessageFilters; pagination?: Pagination; + sortBy?: SortBy; }) { super(); pb_1.Message.initialize(this, Array.isArray(data) ? data : [], 0, -1, [], this.#one_of_decls); @@ -8731,6 +8732,9 @@ export namespace messages { if ("pagination" in data && data.pagination != undefined) { this.pagination = data.pagination; } + if ("sortBy" in data && data.sortBy != undefined) { + this.sortBy = data.sortBy; + } } } get session() { @@ -8760,10 +8764,20 @@ export namespace messages { get has_pagination() { return pb_1.Message.getField(this, 3) != null; } + get sortBy() { + return pb_1.Message.getWrapperField(this, SortBy, 4) as SortBy; + } + set sortBy(value: SortBy) { + pb_1.Message.setWrapperField(this, 4, value); + } + get has_sortBy() { + return pb_1.Message.getField(this, 4) != null; + } static fromObject(data: { session?: ReturnType; filters?: ReturnType; pagination?: ReturnType; + sortBy?: ReturnType; }): GetMessagesRequest { const message = new GetMessagesRequest({}); if (data.session != null) { @@ -8775,6 +8789,9 @@ export namespace messages { if (data.pagination != null) { message.pagination = Pagination.fromObject(data.pagination); } + if (data.sortBy != null) { + message.sortBy = SortBy.fromObject(data.sortBy); + } return message; } toObject() { @@ -8782,6 +8799,7 @@ export namespace messages { session?: ReturnType; filters?: ReturnType; pagination?: ReturnType; + sortBy?: ReturnType; } = {}; if (this.session != null) { data.session = this.session.toObject(); @@ -8792,6 +8810,9 @@ export namespace messages { if (this.pagination != null) { data.pagination = this.pagination.toObject(); } + if (this.sortBy != null) { + data.sortBy = this.sortBy.toObject(); + } return data; } serialize(): Uint8Array; @@ -8804,6 +8825,8 @@ export namespace messages { writer.writeMessage(2, this.filters, () => this.filters.serialize(writer)); if (this.has_pagination) writer.writeMessage(3, this.pagination, () => this.pagination.serialize(writer)); + if (this.has_sortBy) + writer.writeMessage(4, this.sortBy, () => this.sortBy.serialize(writer)); if (!w) return writer.getResultBuffer(); } @@ -8822,6 +8845,9 @@ export namespace messages { case 3: reader.readMessage(message.pagination, () => message.pagination = Pagination.deserialize(reader)); break; + case 4: + reader.readMessage(message.sortBy, () => message.sortBy = SortBy.deserialize(reader)); + break; default: reader.skipField(); } } diff --git a/src/core/engines/gows/grpc/gows_pb.js b/src/core/engines/gows/grpc/gows_pb.js index 941bb3e7..ccc025ac 100644 --- a/src/core/engines/gows/grpc/gows_pb.js +++ b/src/core/engines/gows/grpc/gows_pb.js @@ -18172,7 +18172,8 @@ proto.messages.GetMessagesRequest.toObject = function(includeInstance, msg) { var f, obj = { session: (f = msg.getSession()) && proto.messages.Session.toObject(includeInstance, f), filters: (f = msg.getFilters()) && proto.messages.MessageFilters.toObject(includeInstance, f), - pagination: (f = msg.getPagination()) && proto.messages.Pagination.toObject(includeInstance, f) + pagination: (f = msg.getPagination()) && proto.messages.Pagination.toObject(includeInstance, f), + sortby: (f = msg.getSortby()) && proto.messages.SortBy.toObject(includeInstance, f) }; if (includeInstance) { @@ -18224,6 +18225,11 @@ proto.messages.GetMessagesRequest.deserializeBinaryFromReader = function(msg, re reader.readMessage(value,proto.messages.Pagination.deserializeBinaryFromReader); msg.setPagination(value); break; + case 4: + var value = new proto.messages.SortBy; + reader.readMessage(value,proto.messages.SortBy.deserializeBinaryFromReader); + msg.setSortby(value); + break; default: reader.skipField(); break; @@ -18277,6 +18283,14 @@ proto.messages.GetMessagesRequest.serializeBinaryToWriter = function(message, wr proto.messages.Pagination.serializeBinaryToWriter ); } + f = message.getSortby(); + if (f != null) { + writer.writeMessage( + 4, + f, + proto.messages.SortBy.serializeBinaryToWriter + ); + } }; @@ -18391,6 +18405,43 @@ proto.messages.GetMessagesRequest.prototype.hasPagination = function() { }; +/** + * optional SortBy sortBy = 4; + * @return {?proto.messages.SortBy} + */ +proto.messages.GetMessagesRequest.prototype.getSortby = function() { + return /** @type{?proto.messages.SortBy} */ ( + jspb.Message.getWrapperField(this, proto.messages.SortBy, 4)); +}; + + +/** + * @param {?proto.messages.SortBy|undefined} value + * @return {!proto.messages.GetMessagesRequest} returns this +*/ +proto.messages.GetMessagesRequest.prototype.setSortby = function(value) { + return jspb.Message.setWrapperField(this, 4, value); +}; + + +/** + * Clears the message field making it undefined. + * @return {!proto.messages.GetMessagesRequest} returns this + */ +proto.messages.GetMessagesRequest.prototype.clearSortby = function() { + return this.setSortby(undefined); +}; + + +/** + * Returns whether this field is set. + * @return {boolean} + */ +proto.messages.GetMessagesRequest.prototype.hasSortby = function() { + return jspb.Message.getField(this, 4) != null; +}; + + diff --git a/src/core/engines/gows/session.gows.core.ts b/src/core/engines/gows/session.gows.core.ts index 0d6ecbc8..45b35b81 100644 --- a/src/core/engines/gows/session.gows.core.ts +++ b/src/core/engines/gows/session.gows.core.ts @@ -1,5 +1,8 @@ -import { normalizeMessageContent, WAMessageKey } from '@adiwajshing/baileys'; -import { proto } from '@adiwajshing/baileys'; +import { + normalizeMessageContent, + proto, + WAMessageKey, +} from '@adiwajshing/baileys'; import * as grpc from '@grpc/grpc-js'; import { connectivityState } from '@grpc/grpc-js'; import { UnprocessableEntityException } from '@nestjs/common'; @@ -61,6 +64,7 @@ import { GetChatMessageQuery, GetChatMessagesFilter, GetChatMessagesQuery, + MessageSortField, OverviewFilter, ReadChatMessagesQuery, ReadChatMessagesResponse, @@ -142,14 +146,13 @@ import { partition, retry, share, + Subject, } from 'rxjs'; -import { Subject } from 'rxjs'; import { map } from 'rxjs/operators'; import { promisify } from 'util'; import * as gows from './types'; import { MessageStatus } from './types'; -import MessageServiceClient = messages.MessageServiceClient; import { isFromFullSync } from '@waha/core/engines/gows/appstate'; import { toVcardV3 } from '@waha/core/vcard'; import { AckToStatus } from '@waha/core/utils/acks'; @@ -168,6 +171,7 @@ import { } from './labels.gows'; import esm from '@waha/vendor/esm'; import { IsEditedMessage } from '@waha/core/utils/pwa'; +import MessageServiceClient = messages.MessageServiceClient; enum WhatsMeowEvent { CONNECTED = 'gows.ConnectedEventData', @@ -1776,6 +1780,13 @@ export class WhatsappSessionGoWSCore extends WhatsappSession { fromMe: optional(filter['filter.fromMe'], messages.OptionalBool), status: optional(status, messages.OptionalUInt32), }), + sortBy: new messages.SortBy({ + field: query.sortBy || MessageSortField.TIMESTAMP, + order: + query.sortOrder === SortOrder.ASC + ? messages.SortBy.Order.ASC + : messages.SortBy.Order.DESC, + }), pagination: new messages.Pagination({ limit: query.limit, offset: query.offset, diff --git a/src/core/engines/noweb/store/NowebPersistentStore.ts b/src/core/engines/noweb/store/NowebPersistentStore.ts index 7a49b235..69c83375 100644 --- a/src/core/engines/noweb/store/NowebPersistentStore.ts +++ b/src/core/engines/noweb/store/NowebPersistentStore.ts @@ -601,7 +601,7 @@ export class NowebPersistentStore implements INowebStore { pagination: PaginationParams, ): Promise { pagination.sortBy = 'messageTimestamp'; - pagination.sortOrder = SortOrder.DESC; + pagination.sortOrder = pagination.sortOrder || SortOrder.DESC; return this.messagesRepo.getAllByJid(chatId, filter, pagination); } diff --git a/src/structures/chats.dto.ts b/src/structures/chats.dto.ts index 71610c15..e7cea909 100644 --- a/src/structures/chats.dto.ts +++ b/src/structures/chats.dto.ts @@ -7,7 +7,6 @@ import { PaginationParams, } from '@waha/structures/pagination.dto'; import { ChatIdProperty } from '@waha/structures/properties.dto'; -import { SessionConfig } from '@waha/structures/sessions.dto'; import { Transform, Type } from 'class-transformer'; import { IsArray, @@ -93,16 +92,23 @@ export class ChatPictureResponse { url: string; } -export class GetChatMessagesQuery { +export enum MessageSortField { + TIMESTAMP = 'timestamp', +} + +export class GetChatMessagesQuery extends PaginationParams { @IsNumber() @IsOptional() @Type(() => Number) limit: number = 10; - @IsNumber() + @ApiProperty({ + description: 'Sort by field', + enum: MessageSortField, + }) @IsOptional() - @Type(() => Number) - offset?: number; + @IsEnum(MessageSortField) + sortBy?: string = MessageSortField.TIMESTAMP; @ApiProperty({ example: false,