1 parent
31885e41af
commit
72d69eeab5
20 files changed
+976
-21
No files matched your search
@@ -0,0 +1,101 @@
|
||||
import { isLidUser } from '@adiwajshing/baileys/lib/WABinary/jid-utils';
|
||||
import {
|
||||
Body,
|
||||
Controller,
|
||||
Get,
|
||||
Param,
|
||||
Post,
|
||||
Query,
|
||||
UnprocessableEntityException,
|
||||
UsePipes,
|
||||
ValidationPipe,
|
||||
} from '@nestjs/common';
|
||||
import { ApiOperation, ApiSecurity, ApiTags } from '@nestjs/swagger';
|
||||
import { WhatsappSession } from '@waha/core/abc/session.abc';
|
||||
import {
|
||||
SessionApiParam,
|
||||
WorkingSessionParam,
|
||||
} from '@waha/nestjs/params/SessionApiParam';
|
||||
import { CountResponse } from '@waha/structures/base.dto';
|
||||
import {
|
||||
LidsListQueryParams,
|
||||
LidToPhoneNumber,
|
||||
} from '@waha/structures/lids.dto';
|
||||
import { PaginationParams, SortOrder } from '@waha/structures/pagination.dto';
|
||||
import { assignWith } from 'lodash';
|
||||
|
||||
import { SessionManager } from '../core/abc/manager.abc';
|
||||
|
||||
@ApiSecurity('api_key')
|
||||
@Controller('api/:session/lids')
|
||||
@ApiTags('👤 Contacts')
|
||||
export class LidsController {
|
||||
constructor(private manager: SessionManager) {}
|
||||
|
||||
@Get('/')
|
||||
@SessionApiParam
|
||||
@ApiOperation({ summary: 'Get all known lids to phone number mapping' })
|
||||
@UsePipes(new ValidationPipe({ transform: true, whitelist: true }))
|
||||
async getAll(
|
||||
@WorkingSessionParam session: WhatsappSession,
|
||||
@Query() params: LidsListQueryParams,
|
||||
): Promise<Array<LidToPhoneNumber>> {
|
||||
// Always lid
|
||||
const pagination: PaginationParams = params;
|
||||
pagination.sortBy = 'lid';
|
||||
pagination.sortOrder = SortOrder.ASC;
|
||||
const lids = await session.getAllLids(pagination);
|
||||
return lids;
|
||||
}
|
||||
|
||||
@Get('/count')
|
||||
@SessionApiParam
|
||||
@ApiOperation({ summary: 'Get the number of known lids' })
|
||||
@UsePipes(new ValidationPipe({ transform: true, whitelist: true }))
|
||||
async getLidsCount(
|
||||
@WorkingSessionParam session: WhatsappSession,
|
||||
): Promise<CountResponse> {
|
||||
const count = await session.getLidsCount();
|
||||
return {
|
||||
count: count,
|
||||
};
|
||||
}
|
||||
|
||||
@Get('/:lid')
|
||||
@SessionApiParam
|
||||
@ApiOperation({ summary: 'Get phone number by lid' })
|
||||
@UsePipes(new ValidationPipe({ transform: true, whitelist: true }))
|
||||
async findPNByLid(
|
||||
@WorkingSessionParam session: WhatsappSession,
|
||||
@Param('lid') lid: string,
|
||||
): Promise<LidToPhoneNumber> {
|
||||
if (!isLidUser(lid)) {
|
||||
throw new UnprocessableEntityException(
|
||||
'Invalid LID - it must end with @lid',
|
||||
);
|
||||
}
|
||||
const result = await session.findPNByLid(lid);
|
||||
result.pn = result.pn || null;
|
||||
return result;
|
||||
}
|
||||
|
||||
@Get('/pn/:phoneNumber')
|
||||
@SessionApiParam
|
||||
@ApiOperation({ summary: 'Get lid by phone number (chat id)' })
|
||||
@UsePipes(new ValidationPipe({ transform: true, whitelist: true }))
|
||||
async findLIDByPhoneNumber(
|
||||
@WorkingSessionParam session: WhatsappSession,
|
||||
@Param('phoneNumber') phoneNumber: string,
|
||||
): Promise<LidToPhoneNumber> {
|
||||
if (isLidUser(phoneNumber)) {
|
||||
return {
|
||||
lid: phoneNumber,
|
||||
pn: null,
|
||||
};
|
||||
}
|
||||
|
||||
const result = await session.findLIDByPhoneNumber(phoneNumber);
|
||||
result.lid = result.lid || null;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -22,7 +22,11 @@ import {
|
||||
import { SendButtonsRequest } from '@waha/structures/chatting.buttons.dto';
|
||||
import { BinaryFile, RemoteFile } from '@waha/structures/files.dto';
|
||||
import { Label, LabelDTO, LabelID } from '@waha/structures/labels.dto';
|
||||
import { PaginationParams } from '@waha/structures/pagination.dto';
|
||||
import { LidToPhoneNumber } from '@waha/structures/lids.dto';
|
||||
import {
|
||||
LimitOffsetParams,
|
||||
PaginationParams,
|
||||
} from '@waha/structures/pagination.dto';
|
||||
import { MessageSource, WAMessage } from '@waha/structures/responses.dto';
|
||||
import { DefaultMap } from '@waha/utils/DefaultMap';
|
||||
import { generatePrefixedId } from '@waha/utils/ids';
|
||||
@@ -627,6 +631,29 @@ export abstract class WhatsappSession {
|
||||
throw new NotImplementedByEngineError();
|
||||
}
|
||||
|
||||
/**
|
||||
* Lid to Phone Number methods
|
||||
*/
|
||||
public async getAllLids(
|
||||
pagination: PaginationParams,
|
||||
): Promise<Array<LidToPhoneNumber>> {
|
||||
throw new NotImplementedByEngineError();
|
||||
}
|
||||
|
||||
public async getLidsCount(): Promise<number> {
|
||||
throw new NotImplementedByEngineError();
|
||||
}
|
||||
|
||||
public async findPNByLid(lid: string): Promise<LidToPhoneNumber> {
|
||||
throw new NotImplementedByEngineError();
|
||||
}
|
||||
|
||||
public async findLIDByPhoneNumber(
|
||||
phoneNumber: string,
|
||||
): Promise<LidToPhoneNumber> {
|
||||
throw new NotImplementedByEngineError();
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch the latest profile picture of the contact (group, newsletter, etc.)
|
||||
* @param id
|
||||
|
||||
@@ -5,6 +5,7 @@ import { PassportModule } from '@nestjs/passport';
|
||||
import { ServeStaticModule } from '@nestjs/serve-static';
|
||||
import { TerminusModule } from '@nestjs/terminus';
|
||||
import { ChannelsController } from '@waha/api/channels.controller';
|
||||
import { LidsController } from '@waha/api/lids.controller';
|
||||
import { ProfileController } from '@waha/api/profile.controller';
|
||||
import {
|
||||
ServerController,
|
||||
@@ -130,6 +131,7 @@ export const CONTROLLERS = [
|
||||
StatusController,
|
||||
LabelsController,
|
||||
ContactsController,
|
||||
LidsController,
|
||||
GroupsController,
|
||||
PresenceController,
|
||||
ScreenshotController,
|
||||
|
||||
@@ -8720,6 +8720,76 @@ export namespace messages {
|
||||
return CancelEventMessageRequest.deserialize(bytes);
|
||||
}
|
||||
}
|
||||
export class GetLidsRequest extends pb_1.Message {
|
||||
#one_of_decls: number[][] = [];
|
||||
constructor(data?: any[] | {
|
||||
session?: Session;
|
||||
}) {
|
||||
super();
|
||||
pb_1.Message.initialize(this, Array.isArray(data) ? data : [], 0, -1, [], this.#one_of_decls);
|
||||
if (!Array.isArray(data) && typeof data == "object") {
|
||||
if ("session" in data && data.session != undefined) {
|
||||
this.session = data.session;
|
||||
}
|
||||
}
|
||||
}
|
||||
get session() {
|
||||
return pb_1.Message.getWrapperField(this, Session, 1) as Session;
|
||||
}
|
||||
set session(value: Session) {
|
||||
pb_1.Message.setWrapperField(this, 1, value);
|
||||
}
|
||||
get has_session() {
|
||||
return pb_1.Message.getField(this, 1) != null;
|
||||
}
|
||||
static fromObject(data: {
|
||||
session?: ReturnType<typeof Session.prototype.toObject>;
|
||||
}): GetLidsRequest {
|
||||
const message = new GetLidsRequest({});
|
||||
if (data.session != null) {
|
||||
message.session = Session.fromObject(data.session);
|
||||
}
|
||||
return message;
|
||||
}
|
||||
toObject() {
|
||||
const data: {
|
||||
session?: ReturnType<typeof Session.prototype.toObject>;
|
||||
} = {};
|
||||
if (this.session != null) {
|
||||
data.session = this.session.toObject();
|
||||
}
|
||||
return data;
|
||||
}
|
||||
serialize(): Uint8Array;
|
||||
serialize(w: pb_1.BinaryWriter): void;
|
||||
serialize(w?: pb_1.BinaryWriter): Uint8Array | void {
|
||||
const writer = w || new pb_1.BinaryWriter();
|
||||
if (this.has_session)
|
||||
writer.writeMessage(1, this.session, () => this.session.serialize(writer));
|
||||
if (!w)
|
||||
return writer.getResultBuffer();
|
||||
}
|
||||
static deserialize(bytes: Uint8Array | pb_1.BinaryReader): GetLidsRequest {
|
||||
const reader = bytes instanceof pb_1.BinaryReader ? bytes : new pb_1.BinaryReader(bytes), message = new GetLidsRequest();
|
||||
while (reader.nextField()) {
|
||||
if (reader.isEndGroup())
|
||||
break;
|
||||
switch (reader.getFieldNumber()) {
|
||||
case 1:
|
||||
reader.readMessage(message.session, () => message.session = Session.deserialize(reader));
|
||||
break;
|
||||
default: reader.skipField();
|
||||
}
|
||||
}
|
||||
return message;
|
||||
}
|
||||
serializeBinary(): Uint8Array {
|
||||
return this.serialize();
|
||||
}
|
||||
static deserializeBinary(bytes: Uint8Array): GetLidsRequest {
|
||||
return GetLidsRequest.deserialize(bytes);
|
||||
}
|
||||
}
|
||||
interface GrpcUnaryServiceInterface<P, R> {
|
||||
(message: P, metadata: grpc_1.Metadata, options: grpc_1.CallOptions, callback: grpc_1.requestCallback<R>): grpc_1.ClientUnaryCall;
|
||||
(message: P, metadata: grpc_1.Metadata, callback: grpc_1.requestCallback<R>): grpc_1.ClientUnaryCall;
|
||||
@@ -8841,6 +8911,42 @@ export namespace messages {
|
||||
responseSerialize: (message: Empty) => Buffer.from(message.serialize()),
|
||||
responseDeserialize: (bytes: Buffer) => Empty.deserialize(new Uint8Array(bytes))
|
||||
},
|
||||
GetAllLids: {
|
||||
path: "/messages.MessageService/GetAllLids",
|
||||
requestStream: false,
|
||||
responseStream: false,
|
||||
requestSerialize: (message: GetLidsRequest) => Buffer.from(message.serialize()),
|
||||
requestDeserialize: (bytes: Buffer) => GetLidsRequest.deserialize(new Uint8Array(bytes)),
|
||||
responseSerialize: (message: JsonList) => Buffer.from(message.serialize()),
|
||||
responseDeserialize: (bytes: Buffer) => JsonList.deserialize(new Uint8Array(bytes))
|
||||
},
|
||||
GetLidsCount: {
|
||||
path: "/messages.MessageService/GetLidsCount",
|
||||
requestStream: false,
|
||||
responseStream: false,
|
||||
requestSerialize: (message: Session) => Buffer.from(message.serialize()),
|
||||
requestDeserialize: (bytes: Buffer) => Session.deserialize(new Uint8Array(bytes)),
|
||||
responseSerialize: (message: OptionalUInt64) => Buffer.from(message.serialize()),
|
||||
responseDeserialize: (bytes: Buffer) => OptionalUInt64.deserialize(new Uint8Array(bytes))
|
||||
},
|
||||
FindPNByLid: {
|
||||
path: "/messages.MessageService/FindPNByLid",
|
||||
requestStream: false,
|
||||
responseStream: false,
|
||||
requestSerialize: (message: EntityByIdRequest) => Buffer.from(message.serialize()),
|
||||
requestDeserialize: (bytes: Buffer) => EntityByIdRequest.deserialize(new Uint8Array(bytes)),
|
||||
responseSerialize: (message: OptionalString) => Buffer.from(message.serialize()),
|
||||
responseDeserialize: (bytes: Buffer) => OptionalString.deserialize(new Uint8Array(bytes))
|
||||
},
|
||||
FindLIDByPhoneNumber: {
|
||||
path: "/messages.MessageService/FindLIDByPhoneNumber",
|
||||
requestStream: false,
|
||||
responseStream: false,
|
||||
requestSerialize: (message: EntityByIdRequest) => Buffer.from(message.serialize()),
|
||||
requestDeserialize: (bytes: Buffer) => EntityByIdRequest.deserialize(new Uint8Array(bytes)),
|
||||
responseSerialize: (message: OptionalString) => Buffer.from(message.serialize()),
|
||||
responseDeserialize: (bytes: Buffer) => OptionalString.deserialize(new Uint8Array(bytes))
|
||||
},
|
||||
FetchGroups: {
|
||||
path: "/messages.MessageService/FetchGroups",
|
||||
requestStream: false,
|
||||
@@ -9292,6 +9398,10 @@ export namespace messages {
|
||||
abstract SetProfileName(call: grpc_1.ServerUnaryCall<ProfileNameRequest, Empty>, callback: grpc_1.sendUnaryData<Empty>): void;
|
||||
abstract SetProfileStatus(call: grpc_1.ServerUnaryCall<ProfileStatusRequest, Empty>, callback: grpc_1.sendUnaryData<Empty>): void;
|
||||
abstract SetProfilePicture(call: grpc_1.ServerUnaryCall<SetProfilePictureRequest, Empty>, callback: grpc_1.sendUnaryData<Empty>): void;
|
||||
abstract GetAllLids(call: grpc_1.ServerUnaryCall<GetLidsRequest, JsonList>, callback: grpc_1.sendUnaryData<JsonList>): void;
|
||||
abstract GetLidsCount(call: grpc_1.ServerUnaryCall<Session, OptionalUInt64>, callback: grpc_1.sendUnaryData<OptionalUInt64>): void;
|
||||
abstract FindPNByLid(call: grpc_1.ServerUnaryCall<EntityByIdRequest, OptionalString>, callback: grpc_1.sendUnaryData<OptionalString>): void;
|
||||
abstract FindLIDByPhoneNumber(call: grpc_1.ServerUnaryCall<EntityByIdRequest, OptionalString>, callback: grpc_1.sendUnaryData<OptionalString>): void;
|
||||
abstract FetchGroups(call: grpc_1.ServerUnaryCall<Session, Empty>, callback: grpc_1.sendUnaryData<Empty>): void;
|
||||
abstract GetGroups(call: grpc_1.ServerUnaryCall<Session, JsonList>, callback: grpc_1.sendUnaryData<JsonList>): void;
|
||||
abstract GetGroupInfo(call: grpc_1.ServerUnaryCall<JidRequest, Json>, callback: grpc_1.sendUnaryData<Json>): void;
|
||||
@@ -9370,6 +9480,18 @@ export namespace messages {
|
||||
SetProfilePicture: GrpcUnaryServiceInterface<SetProfilePictureRequest, Empty> = (message: SetProfilePictureRequest, metadata: grpc_1.Metadata | grpc_1.CallOptions | grpc_1.requestCallback<Empty>, options?: grpc_1.CallOptions | grpc_1.requestCallback<Empty>, callback?: grpc_1.requestCallback<Empty>): grpc_1.ClientUnaryCall => {
|
||||
return super.SetProfilePicture(message, metadata, options, callback);
|
||||
};
|
||||
GetAllLids: GrpcUnaryServiceInterface<GetLidsRequest, JsonList> = (message: GetLidsRequest, metadata: grpc_1.Metadata | grpc_1.CallOptions | grpc_1.requestCallback<JsonList>, options?: grpc_1.CallOptions | grpc_1.requestCallback<JsonList>, callback?: grpc_1.requestCallback<JsonList>): grpc_1.ClientUnaryCall => {
|
||||
return super.GetAllLids(message, metadata, options, callback);
|
||||
};
|
||||
GetLidsCount: GrpcUnaryServiceInterface<Session, OptionalUInt64> = (message: Session, metadata: grpc_1.Metadata | grpc_1.CallOptions | grpc_1.requestCallback<OptionalUInt64>, options?: grpc_1.CallOptions | grpc_1.requestCallback<OptionalUInt64>, callback?: grpc_1.requestCallback<OptionalUInt64>): grpc_1.ClientUnaryCall => {
|
||||
return super.GetLidsCount(message, metadata, options, callback);
|
||||
};
|
||||
FindPNByLid: GrpcUnaryServiceInterface<EntityByIdRequest, OptionalString> = (message: EntityByIdRequest, metadata: grpc_1.Metadata | grpc_1.CallOptions | grpc_1.requestCallback<OptionalString>, options?: grpc_1.CallOptions | grpc_1.requestCallback<OptionalString>, callback?: grpc_1.requestCallback<OptionalString>): grpc_1.ClientUnaryCall => {
|
||||
return super.FindPNByLid(message, metadata, options, callback);
|
||||
};
|
||||
FindLIDByPhoneNumber: GrpcUnaryServiceInterface<EntityByIdRequest, OptionalString> = (message: EntityByIdRequest, metadata: grpc_1.Metadata | grpc_1.CallOptions | grpc_1.requestCallback<OptionalString>, options?: grpc_1.CallOptions | grpc_1.requestCallback<OptionalString>, callback?: grpc_1.requestCallback<OptionalString>): grpc_1.ClientUnaryCall => {
|
||||
return super.FindLIDByPhoneNumber(message, metadata, options, callback);
|
||||
};
|
||||
FetchGroups: GrpcUnaryServiceInterface<Session, Empty> = (message: Session, metadata: grpc_1.Metadata | grpc_1.CallOptions | grpc_1.requestCallback<Empty>, options?: grpc_1.CallOptions | grpc_1.requestCallback<Empty>, callback?: grpc_1.requestCallback<Empty>): grpc_1.ClientUnaryCall => {
|
||||
return super.FetchGroups(message, metadata, options, callback);
|
||||
};
|
||||
|
||||
@@ -202,6 +202,17 @@ function deserialize_messages_GetLabelsRequest(buffer_arg) {
|
||||
return gows_pb.GetLabelsRequest.deserializeBinary(new Uint8Array(buffer_arg));
|
||||
}
|
||||
|
||||
function serialize_messages_GetLidsRequest(arg) {
|
||||
if (!(arg instanceof gows_pb.GetLidsRequest)) {
|
||||
throw new Error('Expected argument of type messages.GetLidsRequest');
|
||||
}
|
||||
return Buffer.from(arg.serializeBinary());
|
||||
}
|
||||
|
||||
function deserialize_messages_GetLidsRequest(buffer_arg) {
|
||||
return gows_pb.GetLidsRequest.deserializeBinary(new Uint8Array(buffer_arg));
|
||||
}
|
||||
|
||||
function serialize_messages_GetMessagesRequest(arg) {
|
||||
if (!(arg instanceof gows_pb.GetMessagesRequest)) {
|
||||
throw new Error('Expected argument of type messages.GetMessagesRequest');
|
||||
@@ -433,6 +444,17 @@ function deserialize_messages_OptionalString(buffer_arg) {
|
||||
return gows_pb.OptionalString.deserializeBinary(new Uint8Array(buffer_arg));
|
||||
}
|
||||
|
||||
function serialize_messages_OptionalUInt64(arg) {
|
||||
if (!(arg instanceof gows_pb.OptionalUInt64)) {
|
||||
throw new Error('Expected argument of type messages.OptionalUInt64');
|
||||
}
|
||||
return Buffer.from(arg.serializeBinary());
|
||||
}
|
||||
|
||||
function deserialize_messages_OptionalUInt64(buffer_arg) {
|
||||
return gows_pb.OptionalUInt64.deserializeBinary(new Uint8Array(buffer_arg));
|
||||
}
|
||||
|
||||
function serialize_messages_PairCodeRequest(arg) {
|
||||
if (!(arg instanceof gows_pb.PairCodeRequest)) {
|
||||
throw new Error('Expected argument of type messages.PairCodeRequest');
|
||||
@@ -746,6 +768,53 @@ setProfileName: {
|
||||
responseDeserialize: deserialize_messages_Empty,
|
||||
},
|
||||
//
|
||||
// Lids
|
||||
//
|
||||
getAllLids: {
|
||||
path: '/messages.MessageService/GetAllLids',
|
||||
requestStream: false,
|
||||
responseStream: false,
|
||||
requestType: gows_pb.GetLidsRequest,
|
||||
responseType: gows_pb.JsonList,
|
||||
requestSerialize: serialize_messages_GetLidsRequest,
|
||||
requestDeserialize: deserialize_messages_GetLidsRequest,
|
||||
responseSerialize: serialize_messages_JsonList,
|
||||
responseDeserialize: deserialize_messages_JsonList,
|
||||
},
|
||||
getLidsCount: {
|
||||
path: '/messages.MessageService/GetLidsCount',
|
||||
requestStream: false,
|
||||
responseStream: false,
|
||||
requestType: gows_pb.Session,
|
||||
responseType: gows_pb.OptionalUInt64,
|
||||
requestSerialize: serialize_messages_Session,
|
||||
requestDeserialize: deserialize_messages_Session,
|
||||
responseSerialize: serialize_messages_OptionalUInt64,
|
||||
responseDeserialize: deserialize_messages_OptionalUInt64,
|
||||
},
|
||||
findPNByLid: {
|
||||
path: '/messages.MessageService/FindPNByLid',
|
||||
requestStream: false,
|
||||
responseStream: false,
|
||||
requestType: gows_pb.EntityByIdRequest,
|
||||
responseType: gows_pb.OptionalString,
|
||||
requestSerialize: serialize_messages_EntityByIdRequest,
|
||||
requestDeserialize: deserialize_messages_EntityByIdRequest,
|
||||
responseSerialize: serialize_messages_OptionalString,
|
||||
responseDeserialize: deserialize_messages_OptionalString,
|
||||
},
|
||||
findLIDByPhoneNumber: {
|
||||
path: '/messages.MessageService/FindLIDByPhoneNumber',
|
||||
requestStream: false,
|
||||
responseStream: false,
|
||||
requestType: gows_pb.EntityByIdRequest,
|
||||
responseType: gows_pb.OptionalString,
|
||||
requestSerialize: serialize_messages_EntityByIdRequest,
|
||||
requestDeserialize: deserialize_messages_EntityByIdRequest,
|
||||
responseSerialize: serialize_messages_OptionalString,
|
||||
responseDeserialize: deserialize_messages_OptionalString,
|
||||
},
|
||||
//
|
||||
// Groups
|
||||
//
|
||||
fetchGroups: {
|
||||
|
||||
@@ -43,6 +43,7 @@ goog.exportSymbol('proto.messages.EventMessage', null, global);
|
||||
goog.exportSymbol('proto.messages.GetChatsRequest', null, global);
|
||||
goog.exportSymbol('proto.messages.GetContactsRequest', null, global);
|
||||
goog.exportSymbol('proto.messages.GetLabelsRequest', null, global);
|
||||
goog.exportSymbol('proto.messages.GetLidsRequest', null, global);
|
||||
goog.exportSymbol('proto.messages.GetMessagesRequest', null, global);
|
||||
goog.exportSymbol('proto.messages.GetNewsletterMessagesByInviteRequest', null, global);
|
||||
goog.exportSymbol('proto.messages.GroupCodeRequest', null, global);
|
||||
@@ -1766,6 +1767,27 @@ if (goog.DEBUG && !COMPILED) {
|
||||
*/
|
||||
proto.messages.CancelEventMessageRequest.displayName = 'proto.messages.CancelEventMessageRequest';
|
||||
}
|
||||
/**
|
||||
* Generated by JsPbCodeGenerator.
|
||||
* @param {Array=} opt_data Optional initial data array, typically from a
|
||||
* server response, or constructed directly in Javascript. The array is used
|
||||
* in place and becomes part of the constructed object. It is not cloned.
|
||||
* If no data is provided, the constructed object will be empty, but still
|
||||
* valid.
|
||||
* @extends {jspb.Message}
|
||||
* @constructor
|
||||
*/
|
||||
proto.messages.GetLidsRequest = function(opt_data) {
|
||||
jspb.Message.initialize(this, opt_data, 0, -1, null, null);
|
||||
};
|
||||
goog.inherits(proto.messages.GetLidsRequest, jspb.Message);
|
||||
if (goog.DEBUG && !COMPILED) {
|
||||
/**
|
||||
* @public
|
||||
* @override
|
||||
*/
|
||||
proto.messages.GetLidsRequest.displayName = 'proto.messages.GetLidsRequest';
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -18154,6 +18176,157 @@ proto.messages.CancelEventMessageRequest.prototype.setMessageid = function(value
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
if (jspb.Message.GENERATE_TO_OBJECT) {
|
||||
/**
|
||||
* Creates an object representation of this proto.
|
||||
* Field names that are reserved in JavaScript and will be renamed to pb_name.
|
||||
* Optional fields that are not set will be set to undefined.
|
||||
* To access a reserved field use, foo.pb_<name>, eg, foo.pb_default.
|
||||
* For the list of reserved names please see:
|
||||
* net/proto2/compiler/js/internal/generator.cc#kKeyword.
|
||||
* @param {boolean=} opt_includeInstance Deprecated. whether to include the
|
||||
* JSPB instance for transitional soy proto support:
|
||||
* http://goto/soy-param-migration
|
||||
* @return {!Object}
|
||||
*/
|
||||
proto.messages.GetLidsRequest.prototype.toObject = function(opt_includeInstance) {
|
||||
return proto.messages.GetLidsRequest.toObject(opt_includeInstance, this);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Static version of the {@see toObject} method.
|
||||
* @param {boolean|undefined} includeInstance Deprecated. Whether to include
|
||||
* the JSPB instance for transitional soy proto support:
|
||||
* http://goto/soy-param-migration
|
||||
* @param {!proto.messages.GetLidsRequest} msg The msg instance to transform.
|
||||
* @return {!Object}
|
||||
* @suppress {unusedLocalVariables} f is only used for nested messages
|
||||
*/
|
||||
proto.messages.GetLidsRequest.toObject = function(includeInstance, msg) {
|
||||
var f, obj = {
|
||||
session: (f = msg.getSession()) && proto.messages.Session.toObject(includeInstance, f)
|
||||
};
|
||||
|
||||
if (includeInstance) {
|
||||
obj.$jspbMessageInstance = msg;
|
||||
}
|
||||
return obj;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Deserializes binary data (in protobuf wire format).
|
||||
* @param {jspb.ByteSource} bytes The bytes to deserialize.
|
||||
* @return {!proto.messages.GetLidsRequest}
|
||||
*/
|
||||
proto.messages.GetLidsRequest.deserializeBinary = function(bytes) {
|
||||
var reader = new jspb.BinaryReader(bytes);
|
||||
var msg = new proto.messages.GetLidsRequest;
|
||||
return proto.messages.GetLidsRequest.deserializeBinaryFromReader(msg, reader);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Deserializes binary data (in protobuf wire format) from the
|
||||
* given reader into the given message object.
|
||||
* @param {!proto.messages.GetLidsRequest} msg The message object to deserialize into.
|
||||
* @param {!jspb.BinaryReader} reader The BinaryReader to use.
|
||||
* @return {!proto.messages.GetLidsRequest}
|
||||
*/
|
||||
proto.messages.GetLidsRequest.deserializeBinaryFromReader = function(msg, reader) {
|
||||
while (reader.nextField()) {
|
||||
if (reader.isEndGroup()) {
|
||||
break;
|
||||
}
|
||||
var field = reader.getFieldNumber();
|
||||
switch (field) {
|
||||
case 1:
|
||||
var value = new proto.messages.Session;
|
||||
reader.readMessage(value,proto.messages.Session.deserializeBinaryFromReader);
|
||||
msg.setSession(value);
|
||||
break;
|
||||
default:
|
||||
reader.skipField();
|
||||
break;
|
||||
}
|
||||
}
|
||||
return msg;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Serializes the message to binary data (in protobuf wire format).
|
||||
* @return {!Uint8Array}
|
||||
*/
|
||||
proto.messages.GetLidsRequest.prototype.serializeBinary = function() {
|
||||
var writer = new jspb.BinaryWriter();
|
||||
proto.messages.GetLidsRequest.serializeBinaryToWriter(this, writer);
|
||||
return writer.getResultBuffer();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Serializes the given message to binary data (in protobuf wire
|
||||
* format), writing to the given BinaryWriter.
|
||||
* @param {!proto.messages.GetLidsRequest} message
|
||||
* @param {!jspb.BinaryWriter} writer
|
||||
* @suppress {unusedLocalVariables} f is only used for nested messages
|
||||
*/
|
||||
proto.messages.GetLidsRequest.serializeBinaryToWriter = function(message, writer) {
|
||||
var f = undefined;
|
||||
f = message.getSession();
|
||||
if (f != null) {
|
||||
writer.writeMessage(
|
||||
1,
|
||||
f,
|
||||
proto.messages.Session.serializeBinaryToWriter
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* optional Session session = 1;
|
||||
* @return {?proto.messages.Session}
|
||||
*/
|
||||
proto.messages.GetLidsRequest.prototype.getSession = function() {
|
||||
return /** @type{?proto.messages.Session} */ (
|
||||
jspb.Message.getWrapperField(this, proto.messages.Session, 1));
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {?proto.messages.Session|undefined} value
|
||||
* @return {!proto.messages.GetLidsRequest} returns this
|
||||
*/
|
||||
proto.messages.GetLidsRequest.prototype.setSession = function(value) {
|
||||
return jspb.Message.setWrapperField(this, 1, value);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Clears the message field making it undefined.
|
||||
* @return {!proto.messages.GetLidsRequest} returns this
|
||||
*/
|
||||
proto.messages.GetLidsRequest.prototype.clearSession = function() {
|
||||
return this.setSession(undefined);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns whether this field is set.
|
||||
* @return {boolean}
|
||||
*/
|
||||
proto.messages.GetLidsRequest.prototype.hasSession = function() {
|
||||
return jspb.Message.getField(this, 1) != null;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @enum {number}
|
||||
*/
|
||||
|
||||
@@ -150,6 +150,7 @@ import { AckToStatus } from '@waha/core/utils/acks';
|
||||
import { ParseEventResponseType } from '@waha/core/utils/events';
|
||||
import { DistinctAck } from '@waha/core/utils/reactive';
|
||||
import { Label, LabelDTO, LabelID } from '@waha/structures/labels.dto';
|
||||
import { LidToPhoneNumber } from '@waha/structures/lids.dto';
|
||||
import { exclude } from '@waha/utils/reactive/ops/exclude';
|
||||
import * as lodash from 'lodash';
|
||||
|
||||
@@ -1406,6 +1407,62 @@ export class WhatsappSessionGoWSCore extends WhatsappSession {
|
||||
return data.map(this.toWAContact.bind(this));
|
||||
}
|
||||
|
||||
/**
|
||||
* Lid to Phone Number methods
|
||||
*/
|
||||
public async getAllLids(
|
||||
pagination: PaginationParams,
|
||||
): Promise<Array<LidToPhoneNumber>> {
|
||||
const request = new messages.GetLidsRequest({
|
||||
session: this.session,
|
||||
});
|
||||
const response = await promisify(this.client.GetAllLids)(request);
|
||||
const data = parseJsonList(response);
|
||||
|
||||
const lids = data.map((item) => ({
|
||||
lid: item.lid,
|
||||
pn: toCusFormat(item.pn),
|
||||
}));
|
||||
|
||||
// Use in-memory pagination
|
||||
const paginator = new PaginatorInMemory(pagination);
|
||||
return paginator.apply(lids);
|
||||
}
|
||||
|
||||
public async getLidsCount(): Promise<number> {
|
||||
const response = await promisify(this.client.GetLidsCount)(this.session);
|
||||
return response?.value;
|
||||
}
|
||||
|
||||
public async findPNByLid(lid: string): Promise<LidToPhoneNumber> {
|
||||
const request = new messages.EntityByIdRequest({
|
||||
session: this.session,
|
||||
id: lid,
|
||||
});
|
||||
const response = await promisify(this.client.FindPNByLid)(request);
|
||||
const phoneNumber = response?.value;
|
||||
return {
|
||||
lid: lid,
|
||||
pn: phoneNumber ? toCusFormat(phoneNumber) : null,
|
||||
};
|
||||
}
|
||||
|
||||
public async findLIDByPhoneNumber(
|
||||
phoneNumber: string,
|
||||
): Promise<LidToPhoneNumber> {
|
||||
const pn = toJID(phoneNumber);
|
||||
const request = new messages.EntityByIdRequest({
|
||||
session: this.session,
|
||||
id: pn,
|
||||
});
|
||||
const response = await promisify(this.client.FindLIDByPhoneNumber)(request);
|
||||
const lid = response.value;
|
||||
return {
|
||||
lid: lid || null,
|
||||
pn: toCusFormat(pn),
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Chats methods
|
||||
*/
|
||||
|
||||
@@ -138,6 +138,7 @@ import {
|
||||
LabelDTO,
|
||||
LabelID,
|
||||
} from '@waha/structures/labels.dto';
|
||||
import { LidToPhoneNumber } from '@waha/structures/lids.dto';
|
||||
import { ReplyToMessage } from '@waha/structures/message.dto';
|
||||
import { PaginationParams } from '@waha/structures/pagination.dto';
|
||||
import {
|
||||
@@ -1339,6 +1340,44 @@ export class WhatsappSessionNoWebCore extends WhatsappSession {
|
||||
throw new NotImplementedByEngineError();
|
||||
}
|
||||
|
||||
/**
|
||||
* Lid to Phone Number methods
|
||||
*/
|
||||
public async getAllLids(
|
||||
pagination: PaginationParams,
|
||||
): Promise<Array<LidToPhoneNumber>> {
|
||||
const lids = await this.store.getAllLids(pagination);
|
||||
return lids.map((value) => {
|
||||
return {
|
||||
lid: value.lid,
|
||||
pn: toCusFormat(value.pn),
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
public async getLidsCount(): Promise<number> {
|
||||
return this.store.getLidsCount();
|
||||
}
|
||||
|
||||
public async findPNByLid(lid: string): Promise<LidToPhoneNumber> {
|
||||
const pn = await this.store.findPNByLid(lid);
|
||||
return {
|
||||
lid: lid,
|
||||
pn: pn ? toCusFormat(pn) : null,
|
||||
};
|
||||
}
|
||||
|
||||
public async findLIDByPhoneNumber(
|
||||
phoneNumber: string,
|
||||
): Promise<LidToPhoneNumber> {
|
||||
const pn = toJID(phoneNumber);
|
||||
const lid = await this.store.findLidByPN(pn);
|
||||
return {
|
||||
lid: lid || null,
|
||||
pn: toCusFormat(pn),
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Group methods
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
import { LimitOffsetParams } from '@waha/structures/pagination.dto';
|
||||
|
||||
export class LidToPN {
|
||||
id: string;
|
||||
pn: string;
|
||||
}
|
||||
|
||||
export interface INowebLidPNRepository {
|
||||
/**
|
||||
* Save lid to phone number mapping
|
||||
*/
|
||||
saveLids(lids: LidToPN[]): Promise<void>;
|
||||
|
||||
/**
|
||||
* Get all lids with pagination
|
||||
*/
|
||||
getAllLids(pagination?: LimitOffsetParams): Promise<LidToPN[]>;
|
||||
|
||||
/**
|
||||
* Get a total count of lids
|
||||
*/
|
||||
getLidsCount(): Promise<number>;
|
||||
|
||||
/**
|
||||
* Find a phone number by lid
|
||||
*/
|
||||
findPNByLid(lid: string): Promise<string | null>;
|
||||
|
||||
/**
|
||||
* Find lid by phone number
|
||||
*/
|
||||
findLidByPN(pn: string): Promise<string | null>;
|
||||
}
|
||||
@@ -5,6 +5,7 @@ import { ILabelsRepository } from '@waha/core/engines/noweb/store/ILabelsReposit
|
||||
import { IChatRepository } from './IChatRepository';
|
||||
import { IContactRepository } from './IContactRepository';
|
||||
import { IMessagesRepository } from './IMessagesRepository';
|
||||
import { INowebLidPNRepository } from './INowebLidPNRepository';
|
||||
|
||||
export abstract class INowebStorage {
|
||||
abstract init(): Promise<void>;
|
||||
@@ -22,4 +23,6 @@ export abstract class INowebStorage {
|
||||
abstract getLabelsRepository(): ILabelsRepository;
|
||||
|
||||
abstract getLabelAssociationRepository(): ILabelAssociationRepository;
|
||||
|
||||
abstract getLidPNRepository(): INowebLidPNRepository;
|
||||
}
|
||||
@@ -7,7 +7,11 @@ import {
|
||||
import { GroupMetadata } from '@adiwajshing/baileys/lib/Types/GroupMetadata';
|
||||
import { Label } from '@adiwajshing/baileys/lib/Types/Label';
|
||||
import { GetChatMessagesFilter } from '@waha/structures/chats.dto';
|
||||
import { PaginationParams } from '@waha/structures/pagination.dto';
|
||||
import { LidToPhoneNumber } from '@waha/structures/lids.dto';
|
||||
import {
|
||||
LimitOffsetParams,
|
||||
PaginationParams,
|
||||
} from '@waha/structures/pagination.dto';
|
||||
|
||||
export interface INowebStore {
|
||||
presences: any;
|
||||
@@ -47,4 +51,13 @@ export interface INowebStore {
|
||||
getGroups(pagination: PaginationParams): Promise<GroupMetadata[]>;
|
||||
|
||||
resetGroupsCache(): void;
|
||||
|
||||
// Lid Repository methods
|
||||
getAllLids(pagination?: LimitOffsetParams): Promise<LidToPhoneNumber[]>;
|
||||
|
||||
getLidsCount(): Promise<number>;
|
||||
|
||||
findPNByLid(lid: string): Promise<string | null>;
|
||||
|
||||
findLidByPN(pn: string): Promise<string | null>;
|
||||
}
|
||||
@@ -7,7 +7,11 @@ import makeWASocket, {
|
||||
import { Label } from '@adiwajshing/baileys/lib/Types/Label';
|
||||
import { BadRequestException } from '@nestjs/common';
|
||||
import { GetChatMessagesFilter } from '@waha/structures/chats.dto';
|
||||
import { PaginationParams } from '@waha/structures/pagination.dto';
|
||||
import { LidToPhoneNumber } from '@waha/structures/lids.dto';
|
||||
import {
|
||||
LimitOffsetParams,
|
||||
PaginationParams,
|
||||
} from '@waha/structures/pagination.dto';
|
||||
import { PaginatorInMemory } from '@waha/utils/Paginator';
|
||||
|
||||
import { INowebStore } from './INowebStore';
|
||||
@@ -107,4 +111,23 @@ export class NowebInMemoryStore implements INowebStore {
|
||||
resetGroupsCache() {
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// Lids methods
|
||||
//
|
||||
getAllLids(pagination?: LimitOffsetParams): Promise<LidToPhoneNumber[]> {
|
||||
throw new BadRequestException(this.errorMessage);
|
||||
}
|
||||
|
||||
findLidByPN(pn: string): Promise<string | null> {
|
||||
throw new BadRequestException(this.errorMessage);
|
||||
}
|
||||
|
||||
findPNByLid(lid: string): Promise<string | null> {
|
||||
throw new BadRequestException(this.errorMessage);
|
||||
}
|
||||
|
||||
getLidsCount(): Promise<number> {
|
||||
throw new BadRequestException(this.errorMessage);
|
||||
}
|
||||
}
|
||||
@@ -5,6 +5,7 @@ import makeWASocket, {
|
||||
ChatUpdate,
|
||||
Contact,
|
||||
GroupParticipant,
|
||||
isJidUser,
|
||||
isRealMessage,
|
||||
jidNormalizedUser,
|
||||
ParticipantAction,
|
||||
@@ -18,13 +19,19 @@ import {
|
||||
LabelAssociation,
|
||||
LabelAssociationType,
|
||||
} from '@adiwajshing/baileys/lib/Types/LabelAssociation';
|
||||
import { isLidUser } from '@adiwajshing/baileys/lib/WABinary/jid-utils';
|
||||
import { IGroupRepository } from '@waha/core/engines/noweb/store/IGroupRepository';
|
||||
import { ILabelAssociationRepository } from '@waha/core/engines/noweb/store/ILabelAssociationsRepository';
|
||||
import { ILabelsRepository } from '@waha/core/engines/noweb/store/ILabelsRepository';
|
||||
import { GetChatMessagesFilter } from '@waha/structures/chats.dto';
|
||||
import { PaginationParams, SortOrder } from '@waha/structures/pagination.dto';
|
||||
import { LidToPhoneNumber } from '@waha/structures/lids.dto';
|
||||
import {
|
||||
LimitOffsetParams,
|
||||
PaginationParams,
|
||||
SortOrder,
|
||||
} from '@waha/structures/pagination.dto';
|
||||
import { DefaultMap } from '@waha/utils/DefaultMap';
|
||||
import { sleep, waitUntil } from '@waha/utils/promiseTimeout';
|
||||
import { waitUntil } from '@waha/utils/promiseTimeout';
|
||||
import * as lodash from 'lodash';
|
||||
import { toNumber } from 'lodash';
|
||||
import { Logger } from 'pino';
|
||||
@@ -32,6 +39,7 @@ import { Logger } from 'pino';
|
||||
import { IChatRepository } from './IChatRepository';
|
||||
import { IContactRepository } from './IContactRepository';
|
||||
import { IMessagesRepository } from './IMessagesRepository';
|
||||
import { INowebLidPNRepository, LidToPN } from './INowebLidPNRepository';
|
||||
import { INowebStorage } from './INowebStorage';
|
||||
import { INowebStore } from './INowebStore';
|
||||
|
||||
@@ -49,6 +57,7 @@ export class NowebPersistentStore implements INowebStore {
|
||||
private messagesRepo: IMessagesRepository;
|
||||
private labelsRepo: ILabelsRepository;
|
||||
private labelAssociationsRepo: ILabelAssociationRepository;
|
||||
private lidRepo: INowebLidPNRepository;
|
||||
public presences: any;
|
||||
|
||||
private lock: any = new AsyncLock({
|
||||
@@ -76,6 +85,7 @@ export class NowebPersistentStore implements INowebStore {
|
||||
this.messagesRepo = storage.getMessagesRepository();
|
||||
this.labelsRepo = storage.getLabelsRepository();
|
||||
this.labelAssociationsRepo = storage.getLabelAssociationRepository();
|
||||
this.lidRepo = storage.getLidPNRepository();
|
||||
this.presences = {};
|
||||
}
|
||||
|
||||
@@ -116,9 +126,16 @@ export class NowebPersistentStore implements INowebStore {
|
||||
ev.on('groups.upsert', (data) =>
|
||||
this.withLock('groups', () => this.onGroupUpsert(data)),
|
||||
);
|
||||
ev.on('groups.update', (data) =>
|
||||
this.withLock('groups', () => this.onGroupUpdate(data)),
|
||||
);
|
||||
ev.on('groups.update', (data) => {
|
||||
this.withLock('groups', () => this.onGroupUpdate(data));
|
||||
this.withLock('lids', async () => {
|
||||
const participants = lodash.flatMap(data, (g) => g?.participants || []);
|
||||
const lids = await this.handleLidPNUpdates(participants);
|
||||
this.logger.debug(
|
||||
`groups.update - '${lids.length}' synced lid to pn mapping`,
|
||||
);
|
||||
});
|
||||
});
|
||||
ev.on('group-participants.update', (data) =>
|
||||
this.withLock(`group-${data.id}`, () =>
|
||||
this.onGroupParticipantsUpdate(data),
|
||||
@@ -126,12 +143,24 @@ export class NowebPersistentStore implements INowebStore {
|
||||
);
|
||||
|
||||
// Contacts
|
||||
ev.on('contacts.upsert', (data) =>
|
||||
this.withLock('contacts', () => this.onContactsUpsert(data)),
|
||||
);
|
||||
ev.on('contacts.update', (data) =>
|
||||
this.withLock('contacts', () => this.onContactUpdate(data)),
|
||||
);
|
||||
ev.on('contacts.upsert', (data) => {
|
||||
this.withLock('contacts', () => this.onContactsUpsert(data));
|
||||
this.withLock('lids', async () => {
|
||||
const lids = await this.handleLidPNUpdates(data);
|
||||
this.logger.debug(
|
||||
`contacts.upsert - '${lids.length}' synced lid to pn mapping`,
|
||||
);
|
||||
});
|
||||
});
|
||||
ev.on('contacts.update', (data) => {
|
||||
this.withLock('contacts', () => this.onContactUpdate(data));
|
||||
this.withLock('lids', async () => {
|
||||
const lids = await this.handleLidPNUpdates(data);
|
||||
this.logger.debug(
|
||||
`contacts.update - '${lids.length}' synced lid to pn mapping`,
|
||||
);
|
||||
});
|
||||
});
|
||||
ev.on('labels.edit', (data) => this.onLabelsEdit(data));
|
||||
ev.on('labels.association', ({ association, type }) =>
|
||||
this.onLabelsAssociation(association, type),
|
||||
@@ -166,6 +195,12 @@ export class NowebPersistentStore implements INowebStore {
|
||||
await this.onContactsUpsert(contacts);
|
||||
this.logger.info(`history sync - '${contacts.length}' synced contacts`);
|
||||
}),
|
||||
this.withLock('lids', async () => {
|
||||
const lids = await this.handleLidPNUpdates(contacts);
|
||||
this.logger.info(
|
||||
`history sync - '${lids.length}' synced lid to pn mapping`,
|
||||
);
|
||||
}),
|
||||
this.withLock('chats', () => this.onChatUpsert(chats)),
|
||||
this.withLock('messages', () => this.syncMessagesHistory(messages)),
|
||||
]);
|
||||
@@ -563,4 +598,64 @@ export class NowebPersistentStore implements INowebStore {
|
||||
const ids = associations.map((association) => association.labelId);
|
||||
return await this.labelsRepo.getAllByIds(ids);
|
||||
}
|
||||
|
||||
//
|
||||
// Lid methods
|
||||
//
|
||||
private async handleLidPNUpdates(contacts: Array<Partial<Contact>>) {
|
||||
let lids: LidToPN[] = [];
|
||||
for (const contact of contacts) {
|
||||
// contact.id = pn, contact.lid = lid
|
||||
if (isJidUser(contact.id) && isLidUser(contact.lid)) {
|
||||
lids.push({
|
||||
pn: contact.id,
|
||||
id: contact.lid,
|
||||
});
|
||||
}
|
||||
// contact.pn = pn, contact.lid = lid
|
||||
else if (isJidUser(contact.pn) && isLidUser(contact.lid)) {
|
||||
lids.push({
|
||||
pn: contact.pn,
|
||||
id: contact.lid,
|
||||
});
|
||||
}
|
||||
// contact.pn = pn, contact.id = lid
|
||||
else if (isJidUser(contact.pn) && isLidUser(contact.id)) {
|
||||
lids.push({
|
||||
pn: contact.pn,
|
||||
id: contact.id,
|
||||
});
|
||||
}
|
||||
}
|
||||
// make lids unique by id
|
||||
lids = lodash.uniqBy(lids, 'id');
|
||||
if (lids.length > 0) {
|
||||
await this.lidRepo.saveLids(lids);
|
||||
}
|
||||
return lids;
|
||||
}
|
||||
|
||||
async getAllLids(
|
||||
pagination?: LimitOffsetParams,
|
||||
): Promise<LidToPhoneNumber[]> {
|
||||
const lids = await this.lidRepo.getAllLids(pagination);
|
||||
return lids.map((value) => {
|
||||
return {
|
||||
lid: value.id,
|
||||
pn: value.pn,
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
getLidsCount(): Promise<number> {
|
||||
return this.lidRepo.getLidsCount();
|
||||
}
|
||||
|
||||
findPNByLid(lid: string): Promise<string | null> {
|
||||
return this.lidRepo.findPNByLid(lid);
|
||||
}
|
||||
|
||||
findLidByPN(pn: string): Promise<string | null> {
|
||||
return this.lidRepo.findLidByPN(pn);
|
||||
}
|
||||
}
|
||||
@@ -65,6 +65,15 @@ export const NowebLabelAssociationsSchema = new Schema(
|
||||
],
|
||||
);
|
||||
|
||||
export const NowebLidMapSchema = new Schema(
|
||||
'lid_map',
|
||||
[new Field('id', 'TEXT'), new Field('pn', 'TEXT'), new Field('data', 'TEXT')],
|
||||
[
|
||||
new Index('lid_map_id_index', ['id']),
|
||||
new Index('lid_map_pn_index', ['pn']),
|
||||
],
|
||||
);
|
||||
|
||||
export const NOWEB_STORE_SCHEMA = [
|
||||
NowebContactSchema,
|
||||
NowebChatSchema,
|
||||
@@ -72,6 +81,7 @@ export const NOWEB_STORE_SCHEMA = [
|
||||
NowebMessagesSchema,
|
||||
NowebLabelsSchema,
|
||||
NowebLabelAssociationsSchema,
|
||||
NowebLidMapSchema,
|
||||
];
|
||||
|
||||
export const Migrations: string[] = [
|
||||
@@ -100,4 +110,8 @@ export const Migrations: string[] = [
|
||||
'CREATE INDEX IF NOT EXISTS label_assoc_type_label_index ON "labelAssociations" (type, "labelId")',
|
||||
'CREATE INDEX IF NOT EXISTS label_assoc_type_chat_index ON "labelAssociations" (type, "chatId")',
|
||||
'CREATE INDEX IF NOT EXISTS label_assoc_type_message_index ON "labelAssociations" (type, "messageId")',
|
||||
// Lid Map
|
||||
'CREATE TABLE IF NOT EXISTS lid_map (id TEXT PRIMARY KEY, pn TEXT, data TEXT)',
|
||||
'CREATE UNIQUE INDEX IF NOT EXISTS lid_map_id_index ON lid_map (id)',
|
||||
'CREATE INDEX IF NOT EXISTS lid_map_pn_index ON lid_map (pn)',
|
||||
];
|
||||
@@ -0,0 +1,41 @@
|
||||
import { NowebLidMapSchema } from '@waha/core/engines/noweb/store/schemas';
|
||||
import { LimitOffsetParams } from '@waha/structures/pagination.dto';
|
||||
import { KnexPaginator } from '@waha/utils/Paginator';
|
||||
|
||||
import { INowebLidPNRepository, LidToPN } from '../INowebLidPNRepository';
|
||||
import { NOWEBSqlite3KVRepository } from './NOWEBSqlite3KVRepository';
|
||||
|
||||
export class LidPaginator extends KnexPaginator {
|
||||
indexes = ['id', 'pn'];
|
||||
}
|
||||
|
||||
export class Sqlite3LidPNRepository
|
||||
extends NOWEBSqlite3KVRepository<LidToPN>
|
||||
implements INowebLidPNRepository
|
||||
{
|
||||
get schema() {
|
||||
return NowebLidMapSchema;
|
||||
}
|
||||
|
||||
saveLids(lids: LidToPN[]): Promise<void> {
|
||||
return this.upsertMany(lids);
|
||||
}
|
||||
|
||||
getAllLids(pagination?: LimitOffsetParams): Promise<LidToPN[]> {
|
||||
return this.getAll(pagination);
|
||||
}
|
||||
|
||||
getLidsCount(): Promise<number> {
|
||||
return this.getCount();
|
||||
}
|
||||
|
||||
async findLidByPN(pn: string): Promise<string | null> {
|
||||
const value = await this.getBy({ pn: pn });
|
||||
return value?.id || null;
|
||||
}
|
||||
|
||||
async findPNByLid(lid: string): Promise<string | null> {
|
||||
const value = await this.getBy({ id: lid });
|
||||
return value?.pn || null;
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,10 @@
|
||||
import { ILabelAssociationRepository } from '@waha/core/engines/noweb/store/ILabelAssociationsRepository';
|
||||
import { ILabelsRepository } from '@waha/core/engines/noweb/store/ILabelsRepository';
|
||||
import { INowebLidPNRepository } from '@waha/core/engines/noweb/store/INowebLidPNRepository';
|
||||
import { Sqlite3GroupRepository } from '@waha/core/engines/noweb/store/sqlite3/Sqlite3GroupRepository';
|
||||
import { Sqlite3LabelAssociationsRepository } from '@waha/core/engines/noweb/store/sqlite3/Sqlite3LabelAssociationsRepository';
|
||||
import { Sqlite3LabelsRepository } from '@waha/core/engines/noweb/store/sqlite3/Sqlite3LabelsRepository';
|
||||
import { Sqlite3LidPNRepository } from '@waha/core/engines/noweb/store/sqlite3/Sqlite3LidPNRepository';
|
||||
import { Schema } from '@waha/core/storage/Schema';
|
||||
|
||||
import { INowebStorage } from '../INowebStorage';
|
||||
@@ -74,4 +76,8 @@ export class Sqlite3Storage extends INowebStorage {
|
||||
getMessagesRepository() {
|
||||
return new Sqlite3MessagesRepository(this.db);
|
||||
}
|
||||
|
||||
getLidPNRepository(): INowebLidPNRepository {
|
||||
return new Sqlite3LidPNRepository(this.db);
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
import { GetChatMessagesFilter } from '@waha/structures/chats.dto';
|
||||
import { Label } from '@waha/structures/labels.dto';
|
||||
import { LidToPhoneNumber } from '@waha/structures/lids.dto';
|
||||
import { PaginationParams } from '@waha/structures/pagination.dto';
|
||||
import { TextStatus } from '@waha/structures/status.dto';
|
||||
import { EventEmitter } from 'events';
|
||||
@@ -99,7 +100,7 @@ export class WebjsClientCore extends Client {
|
||||
}
|
||||
|
||||
async createLabel(name: string, color: number): Promise<number> {
|
||||
const labelId: number = await this.pupPage.evaluate(
|
||||
const labelId: number = (await this.pupPage.evaluate(
|
||||
async (name, color) => {
|
||||
// @ts-ignore
|
||||
return await window.WAHA.WAWebBizLabelEditingAction.labelAddAction(
|
||||
@@ -109,7 +110,7 @@ export class WebjsClientCore extends Client {
|
||||
},
|
||||
name,
|
||||
color,
|
||||
);
|
||||
)) as any;
|
||||
return labelId;
|
||||
}
|
||||
|
||||
@@ -262,4 +263,77 @@ export class WebjsClientCore extends Client {
|
||||
|
||||
return messages.map((m) => new Message(this, m));
|
||||
}
|
||||
|
||||
public async getAllLids(
|
||||
pagination: PaginationParams,
|
||||
): Promise<Array<LidToPhoneNumber>> {
|
||||
const lids: Array<LidToPhoneNumber> = (await this.pupPage.evaluate(
|
||||
async (pagination) => {
|
||||
pagination.limit ||= Infinity;
|
||||
pagination.offset ||= 0;
|
||||
pagination.sortBy ||= 'lid';
|
||||
|
||||
// @ts-ignore
|
||||
const WAWebApiContact = window.Store.LidUtils;
|
||||
|
||||
await WAWebApiContact.warmUpAllLidPnMappings();
|
||||
const lidMap = WAWebApiContact.lidPnCache['$1'];
|
||||
const values = Array.from(lidMap.values());
|
||||
const result = values.map((map) => {
|
||||
return {
|
||||
// @ts-ignore
|
||||
lid: map.lid._serialized,
|
||||
// @ts-ignore
|
||||
pn: map.phoneNumber._serialized,
|
||||
};
|
||||
});
|
||||
// @ts-ignore
|
||||
const paginator = new window.Paginator(pagination);
|
||||
const page = paginator.apply(result);
|
||||
return page;
|
||||
},
|
||||
pagination,
|
||||
)) as any;
|
||||
return lids;
|
||||
}
|
||||
|
||||
public async getLidsCount(): Promise<number> {
|
||||
const count: number = (await this.pupPage.evaluate(async () => {
|
||||
// @ts-ignore
|
||||
const WAWebApiContact = window.Store.LidUtils;
|
||||
|
||||
await WAWebApiContact.warmUpAllLidPnMappings();
|
||||
const lidMap = WAWebApiContact.lidPnCache['$1'];
|
||||
return lidMap.size;
|
||||
})) as any;
|
||||
return count;
|
||||
}
|
||||
|
||||
public async findPNByLid(lid: string): Promise<string> {
|
||||
const pn = await this.pupPage.evaluate(async (lid) => {
|
||||
// @ts-ignore
|
||||
const WAWebApiContact = window.Store.LidUtils;
|
||||
// @ts-ignore
|
||||
const WAWebWidFactory = window.Store.WidFactory;
|
||||
|
||||
const wid = WAWebWidFactory.createWid(lid);
|
||||
const result = WAWebApiContact.getPhoneNumber(wid);
|
||||
return result ? result._serialized : null;
|
||||
}, lid);
|
||||
return pn;
|
||||
}
|
||||
|
||||
public async findLIDByPhoneNumber(phoneNumber: string): Promise<string> {
|
||||
const lid: string = (await this.pupPage.evaluate(async (pn) => {
|
||||
// @ts-ignore
|
||||
const WAWebApiContact = window.Store.LidUtils;
|
||||
// @ts-ignore
|
||||
const WAWebWidFactory = window.Store.WidFactory;
|
||||
|
||||
const wid = WAWebWidFactory.createWid(pn);
|
||||
const result = WAWebApiContact.getCurrentLid(wid);
|
||||
return result ? result._serialized : null;
|
||||
}, phoneNumber)) as any;
|
||||
return lid;
|
||||
}
|
||||
}
|
||||
@@ -93,6 +93,7 @@ import {
|
||||
SettingsSecurityChangeInfo,
|
||||
} from '@waha/structures/groups.dto';
|
||||
import { Label, LabelDTO, LabelID } from '@waha/structures/labels.dto';
|
||||
import { LidToPhoneNumber } from '@waha/structures/lids.dto';
|
||||
import { ReplyToMessage } from '@waha/structures/message.dto';
|
||||
import { PaginationParams, SortOrder } from '@waha/structures/pagination.dto';
|
||||
import {
|
||||
@@ -926,6 +927,38 @@ export class WhatsappSessionWebJSCore extends WhatsappSession {
|
||||
await contact.unblock();
|
||||
}
|
||||
|
||||
/**
|
||||
* Lid to Phone Number methods
|
||||
*/
|
||||
public async getAllLids(
|
||||
pagination: PaginationParams,
|
||||
): Promise<Array<LidToPhoneNumber>> {
|
||||
return this.whatsapp.getAllLids(pagination);
|
||||
}
|
||||
|
||||
public async getLidsCount(): Promise<number> {
|
||||
return this.whatsapp.getLidsCount();
|
||||
}
|
||||
|
||||
public async findPNByLid(lid: string): Promise<LidToPhoneNumber> {
|
||||
const phoneNumber = await this.whatsapp.findPNByLid(lid);
|
||||
return {
|
||||
lid: lid,
|
||||
pn: phoneNumber,
|
||||
};
|
||||
}
|
||||
|
||||
public async findLIDByPhoneNumber(
|
||||
phoneNumber: string,
|
||||
): Promise<LidToPhoneNumber> {
|
||||
const pn = toCusFormat(phoneNumber);
|
||||
const lid = await this.whatsapp.findLIDByPhoneNumber(pn);
|
||||
return {
|
||||
lid: lid,
|
||||
pn: pn,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Group methods
|
||||
*/
|
||||
|
||||
@@ -95,11 +95,11 @@ export class SqlKVRepository<Entity> {
|
||||
const sql = `INSERT INTO "${this.table}" (${columns.join(', ')})
|
||||
VALUES ${data
|
||||
.map(() => `(${columns.map(() => '?').join(', ')})`)
|
||||
.join(', ')}
|
||||
ON CONFLICT(id) DO UPDATE
|
||||
SET ${columns
|
||||
.map((column) => `${column} = excluded.${column}`)
|
||||
.join(', ')}`;
|
||||
.join(', ')} ON CONFLICT(id) DO
|
||||
UPDATE
|
||||
SET ${columns
|
||||
.map((column) => `${column} = excluded.${column}`)
|
||||
.join(', ')}`;
|
||||
try {
|
||||
await this.raw(sql, values);
|
||||
} catch (err) {
|
||||
@@ -119,6 +119,15 @@ export class SqlKVRepository<Entity> {
|
||||
return this.all(query);
|
||||
}
|
||||
|
||||
async getCount(): Promise<number> {
|
||||
const query = this.select().count({ count: 'id' });
|
||||
const row = await this.engine.get(query);
|
||||
if (!row) {
|
||||
return 0;
|
||||
}
|
||||
return parseInt(row.count, 10);
|
||||
}
|
||||
|
||||
async getAllByIds(ids: string[]) {
|
||||
const entitiesMap = await this.getEntitiesByIds(ids);
|
||||
return Array.from(entitiesMap.values()).filter(
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
import { ApiProperty } from '@nestjs/swagger';
|
||||
import { LimitOffsetParams } from '@waha/structures/pagination.dto';
|
||||
|
||||
export class LidToPhoneNumber {
|
||||
@ApiProperty({
|
||||
description: 'Linked ID for the user',
|
||||
example: '1111111@lid',
|
||||
})
|
||||
lid?: string;
|
||||
|
||||
@ApiProperty({
|
||||
description: 'Phone number (chat id) for the user',
|
||||
example: '3333333@c.us',
|
||||
})
|
||||
pn?: string;
|
||||
}
|
||||
|
||||
export class LidsListQueryParams extends LimitOffsetParams {
|
||||
limit?: number = 100;
|
||||
offset?: number = 0;
|
||||
}
|
||||
Reference in new issue
Block a user