[core] - Add 'filter.ack' to /messages
This commit is contained in:
1 parent
0b044c67bb
commit
640c0d305c
12 files changed
+224
-12
No files matched your search
@@ -31,6 +31,7 @@ import {
|
||||
GetChatMessagesQuery,
|
||||
OverviewPaginationParams,
|
||||
PinMessageRequest,
|
||||
transformAck,
|
||||
} from '../structures/chats.dto';
|
||||
import { EditMessageRequest } from '../structures/chatting.dto';
|
||||
|
||||
@@ -100,6 +101,7 @@ class ChatsController {
|
||||
@WorkingSessionParam session: WhatsappSession,
|
||||
@Param('chatId') chatId: string,
|
||||
) {
|
||||
filter = transformAck(filter);
|
||||
return session.getChatMessages(chatId, query, filter);
|
||||
}
|
||||
|
||||
|
||||
@@ -10,7 +10,10 @@ import {
|
||||
} from '@nestjs/common';
|
||||
import { ApiOperation, ApiSecurity, ApiTags } from '@nestjs/swagger';
|
||||
import { WAHAValidationPipe } from '@waha/nestjs/pipes/WAHAValidationPipe';
|
||||
import { GetChatMessagesFilter } from '@waha/structures/chats.dto';
|
||||
import {
|
||||
GetChatMessagesFilter,
|
||||
transformAck,
|
||||
} from '@waha/structures/chats.dto';
|
||||
import { SendButtonsRequest } from '@waha/structures/chatting.buttons.dto';
|
||||
|
||||
import { SessionManager } from '../core/abc/manager.abc';
|
||||
@@ -223,6 +226,7 @@ export class ChattingController {
|
||||
@Query() query: GetMessageQuery,
|
||||
@Query() filter: GetChatMessagesFilter,
|
||||
) {
|
||||
filter = transformAck(filter);
|
||||
const whatsapp = await this.manager.getWorkingSession(query.session);
|
||||
return whatsapp.getChatMessages(query.chatId, query, filter);
|
||||
}
|
||||
|
||||
@@ -3983,9 +3983,10 @@ export namespace messages {
|
||||
sender?: string;
|
||||
messageId?: string;
|
||||
type?: ReceiptType;
|
||||
messageIds?: string[];
|
||||
}) {
|
||||
super();
|
||||
pb_1.Message.initialize(this, Array.isArray(data) ? data : [], 0, -1, [], this.#one_of_decls);
|
||||
pb_1.Message.initialize(this, Array.isArray(data) ? data : [], 0, -1, [6], this.#one_of_decls);
|
||||
if (!Array.isArray(data) && typeof data == "object") {
|
||||
if ("session" in data && data.session != undefined) {
|
||||
this.session = data.session;
|
||||
@@ -4002,6 +4003,9 @@ export namespace messages {
|
||||
if ("type" in data && data.type != undefined) {
|
||||
this.type = data.type;
|
||||
}
|
||||
if ("messageIds" in data && data.messageIds != undefined) {
|
||||
this.messageIds = data.messageIds;
|
||||
}
|
||||
}
|
||||
}
|
||||
get session() {
|
||||
@@ -4037,12 +4041,19 @@ export namespace messages {
|
||||
set type(value: ReceiptType) {
|
||||
pb_1.Message.setField(this, 5, value);
|
||||
}
|
||||
get messageIds() {
|
||||
return pb_1.Message.getFieldWithDefault(this, 6, []) as string[];
|
||||
}
|
||||
set messageIds(value: string[]) {
|
||||
pb_1.Message.setField(this, 6, value);
|
||||
}
|
||||
static fromObject(data: {
|
||||
session?: ReturnType<typeof Session.prototype.toObject>;
|
||||
jid?: string;
|
||||
sender?: string;
|
||||
messageId?: string;
|
||||
type?: ReceiptType;
|
||||
messageIds?: string[];
|
||||
}): MarkReadRequest {
|
||||
const message = new MarkReadRequest({});
|
||||
if (data.session != null) {
|
||||
@@ -4060,6 +4071,9 @@ export namespace messages {
|
||||
if (data.type != null) {
|
||||
message.type = data.type;
|
||||
}
|
||||
if (data.messageIds != null) {
|
||||
message.messageIds = data.messageIds;
|
||||
}
|
||||
return message;
|
||||
}
|
||||
toObject() {
|
||||
@@ -4069,6 +4083,7 @@ export namespace messages {
|
||||
sender?: string;
|
||||
messageId?: string;
|
||||
type?: ReceiptType;
|
||||
messageIds?: string[];
|
||||
} = {};
|
||||
if (this.session != null) {
|
||||
data.session = this.session.toObject();
|
||||
@@ -4085,6 +4100,9 @@ export namespace messages {
|
||||
if (this.type != null) {
|
||||
data.type = this.type;
|
||||
}
|
||||
if (this.messageIds != null) {
|
||||
data.messageIds = this.messageIds;
|
||||
}
|
||||
return data;
|
||||
}
|
||||
serialize(): Uint8Array;
|
||||
@@ -4101,6 +4119,8 @@ export namespace messages {
|
||||
writer.writeString(4, this.messageId);
|
||||
if (this.type != ReceiptType.READ)
|
||||
writer.writeEnum(5, this.type);
|
||||
if (this.messageIds.length)
|
||||
writer.writeRepeatedString(6, this.messageIds);
|
||||
if (!w)
|
||||
return writer.getResultBuffer();
|
||||
}
|
||||
@@ -4125,6 +4145,9 @@ export namespace messages {
|
||||
case 5:
|
||||
message.type = reader.readEnum();
|
||||
break;
|
||||
case 6:
|
||||
pb_1.Message.addToRepeatedField(message, 6, reader.readString());
|
||||
break;
|
||||
default: reader.skipField();
|
||||
}
|
||||
}
|
||||
@@ -6934,6 +6957,7 @@ export namespace messages {
|
||||
timestampGte?: OptionalUInt64;
|
||||
timestampLte?: OptionalUInt64;
|
||||
fromMe?: OptionalBool;
|
||||
status?: OptionalUInt32;
|
||||
}) {
|
||||
super();
|
||||
pb_1.Message.initialize(this, Array.isArray(data) ? data : [], 0, -1, [], this.#one_of_decls);
|
||||
@@ -6950,6 +6974,9 @@ export namespace messages {
|
||||
if ("fromMe" in data && data.fromMe != undefined) {
|
||||
this.fromMe = data.fromMe;
|
||||
}
|
||||
if ("status" in data && data.status != undefined) {
|
||||
this.status = data.status;
|
||||
}
|
||||
}
|
||||
}
|
||||
get jid() {
|
||||
@@ -6988,11 +7015,21 @@ export namespace messages {
|
||||
get has_fromMe() {
|
||||
return pb_1.Message.getField(this, 4) != null;
|
||||
}
|
||||
get status() {
|
||||
return pb_1.Message.getWrapperField(this, OptionalUInt32, 5) as OptionalUInt32;
|
||||
}
|
||||
set status(value: OptionalUInt32) {
|
||||
pb_1.Message.setWrapperField(this, 5, value);
|
||||
}
|
||||
get has_status() {
|
||||
return pb_1.Message.getField(this, 5) != null;
|
||||
}
|
||||
static fromObject(data: {
|
||||
jid?: ReturnType<typeof OptionalString.prototype.toObject>;
|
||||
timestampGte?: ReturnType<typeof OptionalUInt64.prototype.toObject>;
|
||||
timestampLte?: ReturnType<typeof OptionalUInt64.prototype.toObject>;
|
||||
fromMe?: ReturnType<typeof OptionalBool.prototype.toObject>;
|
||||
status?: ReturnType<typeof OptionalUInt32.prototype.toObject>;
|
||||
}): MessageFilters {
|
||||
const message = new MessageFilters({});
|
||||
if (data.jid != null) {
|
||||
@@ -7007,6 +7044,9 @@ export namespace messages {
|
||||
if (data.fromMe != null) {
|
||||
message.fromMe = OptionalBool.fromObject(data.fromMe);
|
||||
}
|
||||
if (data.status != null) {
|
||||
message.status = OptionalUInt32.fromObject(data.status);
|
||||
}
|
||||
return message;
|
||||
}
|
||||
toObject() {
|
||||
@@ -7015,6 +7055,7 @@ export namespace messages {
|
||||
timestampGte?: ReturnType<typeof OptionalUInt64.prototype.toObject>;
|
||||
timestampLte?: ReturnType<typeof OptionalUInt64.prototype.toObject>;
|
||||
fromMe?: ReturnType<typeof OptionalBool.prototype.toObject>;
|
||||
status?: ReturnType<typeof OptionalUInt32.prototype.toObject>;
|
||||
} = {};
|
||||
if (this.jid != null) {
|
||||
data.jid = this.jid.toObject();
|
||||
@@ -7028,6 +7069,9 @@ export namespace messages {
|
||||
if (this.fromMe != null) {
|
||||
data.fromMe = this.fromMe.toObject();
|
||||
}
|
||||
if (this.status != null) {
|
||||
data.status = this.status.toObject();
|
||||
}
|
||||
return data;
|
||||
}
|
||||
serialize(): Uint8Array;
|
||||
@@ -7042,6 +7086,8 @@ export namespace messages {
|
||||
writer.writeMessage(3, this.timestampLte, () => this.timestampLte.serialize(writer));
|
||||
if (this.has_fromMe)
|
||||
writer.writeMessage(4, this.fromMe, () => this.fromMe.serialize(writer));
|
||||
if (this.has_status)
|
||||
writer.writeMessage(5, this.status, () => this.status.serialize(writer));
|
||||
if (!w)
|
||||
return writer.getResultBuffer();
|
||||
}
|
||||
@@ -7063,6 +7109,9 @@ export namespace messages {
|
||||
case 4:
|
||||
reader.readMessage(message.fromMe, () => message.fromMe = OptionalBool.deserialize(reader));
|
||||
break;
|
||||
case 5:
|
||||
reader.readMessage(message.status, () => message.status = OptionalUInt32.deserialize(reader));
|
||||
break;
|
||||
default: reader.skipField();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -905,7 +905,7 @@ if (goog.DEBUG && !COMPILED) {
|
||||
* @constructor
|
||||
*/
|
||||
proto.messages.MarkReadRequest = function(opt_data) {
|
||||
jspb.Message.initialize(this, opt_data, 0, -1, null, null);
|
||||
jspb.Message.initialize(this, opt_data, 0, -1, proto.messages.MarkReadRequest.repeatedFields_, null);
|
||||
};
|
||||
goog.inherits(proto.messages.MarkReadRequest, jspb.Message);
|
||||
if (goog.DEBUG && !COMPILED) {
|
||||
@@ -8962,6 +8962,13 @@ proto.messages.SubscribePresenceRequest.prototype.setJid = function(value) {
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* List of repeated fields within this message type.
|
||||
* @private {!Array<number>}
|
||||
* @const
|
||||
*/
|
||||
proto.messages.MarkReadRequest.repeatedFields_ = [6];
|
||||
|
||||
|
||||
|
||||
if (jspb.Message.GENERATE_TO_OBJECT) {
|
||||
@@ -8997,7 +9004,8 @@ proto.messages.MarkReadRequest.toObject = function(includeInstance, msg) {
|
||||
jid: jspb.Message.getFieldWithDefault(msg, 2, ""),
|
||||
sender: jspb.Message.getFieldWithDefault(msg, 3, ""),
|
||||
messageid: jspb.Message.getFieldWithDefault(msg, 4, ""),
|
||||
type: jspb.Message.getFieldWithDefault(msg, 5, 0)
|
||||
type: jspb.Message.getFieldWithDefault(msg, 5, 0),
|
||||
messageidsList: (f = jspb.Message.getRepeatedField(msg, 6)) == null ? undefined : f
|
||||
};
|
||||
|
||||
if (includeInstance) {
|
||||
@@ -9055,6 +9063,10 @@ proto.messages.MarkReadRequest.deserializeBinaryFromReader = function(msg, reade
|
||||
var value = /** @type {!proto.messages.ReceiptType} */ (reader.readEnum());
|
||||
msg.setType(value);
|
||||
break;
|
||||
case 6:
|
||||
var value = /** @type {string} */ (reader.readString());
|
||||
msg.addMessageids(value);
|
||||
break;
|
||||
default:
|
||||
reader.skipField();
|
||||
break;
|
||||
@@ -9120,6 +9132,13 @@ proto.messages.MarkReadRequest.serializeBinaryToWriter = function(message, write
|
||||
f
|
||||
);
|
||||
}
|
||||
f = message.getMessageidsList();
|
||||
if (f.length > 0) {
|
||||
writer.writeRepeatedString(
|
||||
6,
|
||||
f
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -9232,6 +9251,43 @@ proto.messages.MarkReadRequest.prototype.setType = function(value) {
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* repeated string messageIds = 6;
|
||||
* @return {!Array<string>}
|
||||
*/
|
||||
proto.messages.MarkReadRequest.prototype.getMessageidsList = function() {
|
||||
return /** @type {!Array<string>} */ (jspb.Message.getRepeatedField(this, 6));
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {!Array<string>} value
|
||||
* @return {!proto.messages.MarkReadRequest} returns this
|
||||
*/
|
||||
proto.messages.MarkReadRequest.prototype.setMessageidsList = function(value) {
|
||||
return jspb.Message.setField(this, 6, value || []);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {string} value
|
||||
* @param {number=} opt_index
|
||||
* @return {!proto.messages.MarkReadRequest} returns this
|
||||
*/
|
||||
proto.messages.MarkReadRequest.prototype.addMessageids = function(value, opt_index) {
|
||||
return jspb.Message.addToRepeatedField(this, 6, value, opt_index);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Clears the list making it empty but non-null.
|
||||
* @return {!proto.messages.MarkReadRequest} returns this
|
||||
*/
|
||||
proto.messages.MarkReadRequest.prototype.clearMessageidsList = function() {
|
||||
return this.setMessageidsList([]);
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* List of repeated fields within this message type.
|
||||
@@ -14523,7 +14579,8 @@ proto.messages.MessageFilters.toObject = function(includeInstance, msg) {
|
||||
jid: (f = msg.getJid()) && proto.messages.OptionalString.toObject(includeInstance, f),
|
||||
timestampgte: (f = msg.getTimestampgte()) && proto.messages.OptionalUInt64.toObject(includeInstance, f),
|
||||
timestamplte: (f = msg.getTimestamplte()) && proto.messages.OptionalUInt64.toObject(includeInstance, f),
|
||||
fromme: (f = msg.getFromme()) && proto.messages.OptionalBool.toObject(includeInstance, f)
|
||||
fromme: (f = msg.getFromme()) && proto.messages.OptionalBool.toObject(includeInstance, f),
|
||||
status: (f = msg.getStatus()) && proto.messages.OptionalUInt32.toObject(includeInstance, f)
|
||||
};
|
||||
|
||||
if (includeInstance) {
|
||||
@@ -14580,6 +14637,11 @@ proto.messages.MessageFilters.deserializeBinaryFromReader = function(msg, reader
|
||||
reader.readMessage(value,proto.messages.OptionalBool.deserializeBinaryFromReader);
|
||||
msg.setFromme(value);
|
||||
break;
|
||||
case 5:
|
||||
var value = new proto.messages.OptionalUInt32;
|
||||
reader.readMessage(value,proto.messages.OptionalUInt32.deserializeBinaryFromReader);
|
||||
msg.setStatus(value);
|
||||
break;
|
||||
default:
|
||||
reader.skipField();
|
||||
break;
|
||||
@@ -14641,6 +14703,14 @@ proto.messages.MessageFilters.serializeBinaryToWriter = function(message, writer
|
||||
proto.messages.OptionalBool.serializeBinaryToWriter
|
||||
);
|
||||
}
|
||||
f = message.getStatus();
|
||||
if (f != null) {
|
||||
writer.writeMessage(
|
||||
5,
|
||||
f,
|
||||
proto.messages.OptionalUInt32.serializeBinaryToWriter
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -14792,6 +14862,43 @@ proto.messages.MessageFilters.prototype.hasFromme = function() {
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* optional OptionalUInt32 status = 5;
|
||||
* @return {?proto.messages.OptionalUInt32}
|
||||
*/
|
||||
proto.messages.MessageFilters.prototype.getStatus = function() {
|
||||
return /** @type{?proto.messages.OptionalUInt32} */ (
|
||||
jspb.Message.getWrapperField(this, proto.messages.OptionalUInt32, 5));
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {?proto.messages.OptionalUInt32|undefined} value
|
||||
* @return {!proto.messages.MessageFilters} returns this
|
||||
*/
|
||||
proto.messages.MessageFilters.prototype.setStatus = function(value) {
|
||||
return jspb.Message.setWrapperField(this, 5, value);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Clears the message field making it undefined.
|
||||
* @return {!proto.messages.MessageFilters} returns this
|
||||
*/
|
||||
proto.messages.MessageFilters.prototype.clearStatus = function() {
|
||||
return this.setStatus(undefined);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns whether this field is set.
|
||||
* @return {boolean}
|
||||
*/
|
||||
proto.messages.MessageFilters.prototype.hasStatus = function() {
|
||||
return jspb.Message.getField(this, 5) != null;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1322,6 +1322,8 @@ export class WhatsappSessionGoWSCore extends WhatsappSession {
|
||||
});
|
||||
}
|
||||
|
||||
const status =
|
||||
filter['filter.ack'] != null ? filter['filter.ack'] + 1 : null;
|
||||
const request = new messages.GetMessagesRequest({
|
||||
session: this.session,
|
||||
filters: new messages.MessageFilters({
|
||||
@@ -1335,6 +1337,7 @@ export class WhatsappSessionGoWSCore extends WhatsappSession {
|
||||
messages.OptionalUInt64,
|
||||
),
|
||||
fromMe: optional(filter['filter.fromMe'], messages.OptionalBool),
|
||||
status: optional(status, messages.OptionalUInt32),
|
||||
}),
|
||||
pagination: new messages.Pagination({
|
||||
limit: query.limit,
|
||||
|
||||
@@ -35,8 +35,17 @@ export class SqlMessagesMethods {
|
||||
}
|
||||
if (filter['filter.fromMe'] != null) {
|
||||
// filter by data json inside
|
||||
const sql = this.repository.filterJson('data', 'key.fromMe');
|
||||
query = query.whereRaw(sql, [filter['filter.fromMe'] ? 'true' : 'false']);
|
||||
const [sql, value] = this.repository.filterJson(
|
||||
'data',
|
||||
'key.fromMe',
|
||||
filter['filter.fromMe'],
|
||||
);
|
||||
query = query.whereRaw(sql, [value]);
|
||||
}
|
||||
if (filter['filter.ack'] != null) {
|
||||
const status = filter['filter.ack'] + 1;
|
||||
const [sql, value] = this.repository.filterJson('data', 'status', status);
|
||||
query = query.whereRaw(sql, [value]);
|
||||
}
|
||||
query = this.repository.pagination(query, pagination);
|
||||
return this.repository.all(query);
|
||||
|
||||
@@ -199,6 +199,9 @@ export class WebjsClientCore extends Client {
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
if (filter['filter.ack'] != null && m.ack !== filter['filter.ack']) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
export interface IJsonQuery {
|
||||
filter(field: string, key: string): string;
|
||||
filter(field: string, key: string, value: any): [string, string];
|
||||
sortBy(field: string, sortBy: string, direction: string): string;
|
||||
}
|
||||
@@ -187,8 +187,8 @@ export class SqlKVRepository<Entity> {
|
||||
/**
|
||||
* JSON helpers
|
||||
*/
|
||||
public filterJson(field: string, key: string): string {
|
||||
return this.jsonQuery.filter(field, key);
|
||||
public filterJson(field: string, key: string, value: any): [string, string] {
|
||||
return this.jsonQuery.filter(field, key, value);
|
||||
}
|
||||
|
||||
protected stringify(data: any): string {
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { IJsonQuery } from '@waha/core/storage/sql/IJsonQuery';
|
||||
|
||||
export class Sqlite3JsonQuery implements IJsonQuery {
|
||||
filter(field: string, key: string): string {
|
||||
filter(field: string, key: string, value: any): [string, string] {
|
||||
const jsonPath = `$.${key}`;
|
||||
return `${field}->'${jsonPath}' = ?`;
|
||||
return [`${field}->'${jsonPath}' = ?`, `${value}`];
|
||||
}
|
||||
|
||||
sortBy(field: string, sortBy: string, direction: string): string {
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import { BadRequestException } from '@nestjs/common';
|
||||
import { ApiProperty } from '@nestjs/swagger';
|
||||
import { BooleanString } from '@waha/nestjs/validation/BooleanString';
|
||||
import { WAMessageAck, WAMessageAckName } from '@waha/structures/enums.dto';
|
||||
import {
|
||||
LimitOffsetParams,
|
||||
PaginationParams,
|
||||
@@ -39,6 +41,30 @@ export class GetChatMessagesFilter {
|
||||
@IsBoolean()
|
||||
@IsOptional()
|
||||
'filter.fromMe'?: boolean;
|
||||
|
||||
@ApiProperty({
|
||||
required: false,
|
||||
description: 'Filter messages by acknowledgment status',
|
||||
enum: WAMessageAckName,
|
||||
})
|
||||
@IsEnum(WAMessageAckName)
|
||||
@IsOptional()
|
||||
'filter.ack'?: WAMessageAck;
|
||||
}
|
||||
|
||||
export function transformAck(
|
||||
filter: GetChatMessagesFilter,
|
||||
): GetChatMessagesFilter {
|
||||
if (!filter) return filter;
|
||||
if (!filter['filter.ack']) return filter;
|
||||
const ackName = filter['filter.ack'];
|
||||
// @ts-ignore
|
||||
const ack: WAMessageAck = WAMessageAck[ackName];
|
||||
if (ack == null) {
|
||||
throw new BadRequestException(`Invalid ack: '${ackName}'`);
|
||||
}
|
||||
filter['filter.ack'] = ack;
|
||||
return filter;
|
||||
}
|
||||
|
||||
export class ChatPictureQuery {
|
||||
|
||||
@@ -68,4 +68,13 @@ export enum WAMessageAck {
|
||||
PLAYED = 4,
|
||||
}
|
||||
|
||||
export enum WAMessageAckName {
|
||||
ERROR = 'ERROR',
|
||||
PENDING = 'PENDING',
|
||||
SERVER = 'SERVER',
|
||||
DEVICE = 'DEVICE',
|
||||
READ = 'READ',
|
||||
PLAYED = 'PLAYED',
|
||||
}
|
||||
|
||||
export const ACK_UNKNOWN = 'UNKNOWN';
|
||||
Reference in new issue
Block a user