@solufy/evolution-sdk
Version:
Unofficial SDK for the Evolution Whatsapp API v2
672 lines (657 loc) • 20 kB
JavaScript
// src/api/routes.ts
var Routes = {
Message: {
SendText: "message/sendText",
SendMedia: "message/sendMedia",
SendVoice: "message/sendWhatsAppAudio",
SendSticker: "message/sendSticker",
SendLocation: "message/sendLocation",
SendContact: "message/sendContact",
SendPoll: "message/sendPoll"
},
Chats: {
Check: "chat/whatsappNumbers",
FindAll: "chat/findChats",
SendPresence: "chat/sendPresence"
},
Groups: {
FindAll: "group/fetchAllGroups",
FindByJid: "group/findGroupInfos",
FindByInviteCode: "group/inviteInfo"
}
};
// src/modules/messages/schemas/audio.ts
import { z as z3 } from "zod";
// src/schemas/common.ts
import { isValidPhoneNumber, parsePhoneNumber } from "libphonenumber-js";
import { z } from "zod";
var PhoneNumberSchema = z.custom((value) => isValidPhoneNumber(value), "Invalid phone number").transform((phoneNumber) => parsePhoneNumber(phoneNumber).number);
var JidSchema = z.string().endsWith(
"@s.whatsapp.net",
"Invalid remote JID, should end with @s.whatsapp.net"
);
var GroupJidSchema = z.string().endsWith(
"@g.us",
"Invalid group JID, should end with @g.us"
);
var GroupInviteCodeSchema = z.string().length(22).regex(
/^[a-zA-Z0-9]{22}$/,
"Invalid group invite code"
);
var ApiNumberSchema = z.union([
PhoneNumberSchema,
JidSchema,
GroupJidSchema
]);
var mediaSchema = z.union([z.string().url(), z.string().base64()]);
// src/types/tags.ts
var Jid = (jid) => jid;
var MessageId = (id) => id;
// src/utils/phone-numer-from-jid.ts
import { parsePhoneNumber as parsePhoneNumber2 } from "libphonenumber-js";
function phoneNumberFromJid(jid) {
return parsePhoneNumber2(`+${jid.split("@")[0]}`).number;
}
// src/modules/messages/schemas/base.ts
import { z as z2 } from "zod";
var BaseMessageOptionsSchema = z2.object({
/**
* Number (with country code) or JID to receive the message
*/
number: ApiNumberSchema,
/**
* Time in milliseconds before sending message
*/
delay: z2.number().optional()
});
// src/modules/messages/schemas/audio.ts
var AudioMessageOptionsSchema = BaseMessageOptionsSchema.extend({
/**
* Audio URL or file in base64
*/
audio: mediaSchema,
/**
* Audio mimetype
*/
mimetype: z3.string().optional()
});
var AudioMessageBodySchema = AudioMessageOptionsSchema.transform(
({ audio, ...data }) => ({ ...data, media: audio, mediatype: "audio" })
);
var AudioMessageResponseSchema = z3.object({
key: z3.object({
remoteJid: z3.string(),
id: z3.string()
}),
message: z3.object({
audioMessage: z3.object({
url: z3.string().url(),
mimetype: z3.string().optional(),
fileSha256: z3.string().base64(),
fileLength: z3.coerce.number(),
seconds: z3.number(),
mediaKey: z3.string().base64(),
fileEncSha256: z3.string().base64(),
directPath: z3.string(),
mediaKeyTimestamp: z3.coerce.number().transform((value) => new Date(value))
})
}),
messageTimestamp: z3.coerce.date()
}).transform((data) => ({
receiver: {
phoneNumber: phoneNumberFromJid(data.key.remoteJid),
jid: Jid(data.key.remoteJid)
},
media: {
url: data.message.audioMessage.url,
mimetype: data.message.audioMessage.mimetype,
length: data.message.audioMessage.fileLength,
durationInSeconds: data.message.audioMessage.seconds,
sha256: data.message.audioMessage.fileSha256,
encryptedSha256: data.message.audioMessage.fileEncSha256,
directPath: data.message.audioMessage.directPath,
key: data.message.audioMessage.mediaKey,
keyTimestamp: data.message.audioMessage.mediaKeyTimestamp
},
id: MessageId(data.key.id),
timestamp: data.messageTimestamp
}));
// src/modules/messages/schemas/contact.ts
import { parsePhoneNumber as parsePhoneNumber3 } from "libphonenumber-js";
import { z as z4 } from "zod";
var ContactMessageOptionsSchema = BaseMessageOptionsSchema.extend({
/**
* Contact list
*/
contacts: z4.array(
z4.object({
/**
* Contact display name
*/
fullName: z4.string(),
/**
* Contact phone number
*/
phoneNumber: PhoneNumberSchema,
/**
* Contact organization
*/
organization: z4.string().optional(),
/**
* Contact email
*/
email: z4.string().email().optional(),
/**
* Contact website url
*/
url: z4.string().url().optional()
})
)
});
var ContactMessageBodySchema = ContactMessageOptionsSchema.transform(
({ contacts, ...data }) => ({
...data,
contact: contacts.map((contact) => ({
...contact,
phoneNumber: parsePhoneNumber3(contact.phoneNumber).formatInternational(),
wuid: contact.phoneNumber.replace(/\D/g, "")
}))
})
);
var ContactMessageResponseSchema = z4.object({
key: z4.object({
remoteJid: z4.string(),
id: z4.string()
}),
message: z4.union([
z4.object({
contactMessage: z4.object({
displayName: z4.string(),
vcard: z4.string()
})
}),
z4.object({
contactsArrayMessage: z4.object({
contacts: z4.array(
z4.object({
displayName: z4.string(),
vcard: z4.string()
})
)
})
})
]),
messageTimestamp: z4.coerce.date()
}).transform((data) => ({
receiver: {
phoneNumber: phoneNumberFromJid(data.key.remoteJid),
jid: Jid(data.key.remoteJid)
},
contacts: "contactMessage" in data.message ? [data.message.contactMessage] : data.message.contactsArrayMessage.contacts,
id: MessageId(data.key.id),
timestamp: data.messageTimestamp
}));
// src/modules/messages/schemas/document.ts
import { z as z5 } from "zod";
var DocumentMessageOptionsSchema = BaseMessageOptionsSchema.extend({
/**
* Document URL or file in base64
*/
document: mediaSchema,
/**
* Caption to send with document
*/
caption: z5.string().optional(),
/**
* Document mimetype
*/
mimetype: z5.string().optional(),
/**
* Name of the file
*/
fileName: z5.string().optional()
}).refine(
(data) => URL.canParse(data.document) ? true : Boolean(data.fileName),
{
message: "fileName must be provided when document is not an URL",
path: ["fileName"]
}
);
var DocumentMessageBodySchema = DocumentMessageOptionsSchema.transform(
({ document, ...data }) => ({
...data,
media: document,
mediatype: "document"
})
);
var DocumentMessageResponseSchema = z5.object({
key: z5.object({
remoteJid: z5.string(),
id: z5.string()
}),
message: z5.object({
documentMessage: z5.object({
url: z5.string().url(),
mimetype: z5.string().optional(),
fileSha256: z5.string().base64(),
fileLength: z5.coerce.number(),
mediaKey: z5.string().base64(),
caption: z5.string().optional(),
fileName: z5.string(),
fileEncSha256: z5.string().base64(),
directPath: z5.string(),
mediaKeyTimestamp: z5.coerce.number().transform((value) => new Date(value))
})
}),
messageTimestamp: z5.coerce.date()
}).transform((data) => ({
receiver: {
phoneNumber: phoneNumberFromJid(data.key.remoteJid),
jid: Jid(data.key.remoteJid)
},
media: {
url: data.message.documentMessage.url,
caption: data.message.documentMessage.caption,
mimetype: data.message.documentMessage.mimetype,
length: data.message.documentMessage.fileLength,
sha256: data.message.documentMessage.fileSha256,
fileName: data.message.documentMessage.fileName,
encryptedSha256: data.message.documentMessage.fileEncSha256,
directPath: data.message.documentMessage.directPath,
key: data.message.documentMessage.mediaKey,
keyTimestamp: data.message.documentMessage.mediaKeyTimestamp
},
id: MessageId(data.key.id),
timestamp: data.messageTimestamp
}));
// src/modules/messages/schemas/image.ts
import { z as z6 } from "zod";
var ImageMessageOptionsSchema = BaseMessageOptionsSchema.extend({
/**
* Image URL or file in base64
*/
image: mediaSchema,
/**
* Caption to send with image
*/
caption: z6.string().optional(),
/**
* Image mimetype
*/
mimetype: z6.string().optional()
});
var ImageMessageBodySchema = ImageMessageOptionsSchema.transform(
({ image, ...data }) => ({ ...data, media: image, mediatype: "image" })
);
var ImageMessageResponseSchema = z6.object({
key: z6.object({
remoteJid: z6.string(),
id: z6.string()
}),
message: z6.object({
imageMessage: z6.object({
url: z6.string().url(),
mimetype: z6.string().optional(),
fileSha256: z6.string().base64(),
fileLength: z6.coerce.number(),
height: z6.number(),
width: z6.number(),
mediaKey: z6.string().base64(),
caption: z6.string().optional(),
fileEncSha256: z6.string().base64(),
directPath: z6.string(),
mediaKeyTimestamp: z6.coerce.number().transform((value) => new Date(value))
})
}),
messageTimestamp: z6.coerce.date()
}).transform((data) => ({
receiver: {
phoneNumber: phoneNumberFromJid(data.key.remoteJid),
jid: Jid(data.key.remoteJid)
},
media: {
url: data.message.imageMessage.url,
caption: data.message.imageMessage.caption,
mimetype: data.message.imageMessage.mimetype,
length: data.message.imageMessage.fileLength,
height: data.message.imageMessage.height,
width: data.message.imageMessage.width,
sha256: data.message.imageMessage.fileSha256,
encryptedSha256: data.message.imageMessage.fileEncSha256,
directPath: data.message.imageMessage.directPath,
key: data.message.imageMessage.mediaKey,
keyTimestamp: data.message.imageMessage.mediaKeyTimestamp
},
id: MessageId(data.key.id),
timestamp: data.messageTimestamp
}));
// src/modules/messages/schemas/location.ts
import { z as z7 } from "zod";
var LocationMessageOptionsSchema = BaseMessageOptionsSchema.extend({
/**
* Location name
*/
name: z7.string(),
/**
* Location address
*/
address: z7.string(),
/**
* Location latitude
*/
latitude: z7.number(),
/**
* Location longitude
*/
longitude: z7.number()
});
var LocationMessageBodySchema = LocationMessageOptionsSchema;
var LocationMessageResponseSchema = z7.object({
key: z7.object({
remoteJid: z7.string(),
id: z7.string()
}),
message: z7.object({
locationMessage: z7.object({
degreesLatitude: z7.number(),
degreesLongitude: z7.number(),
name: z7.string(),
address: z7.string()
})
}),
messageTimestamp: z7.coerce.date()
}).transform((data) => ({
receiver: {
phoneNumber: phoneNumberFromJid(data.key.remoteJid),
jid: Jid(data.key.remoteJid)
},
location: {
latitude: data.message.locationMessage.degreesLatitude,
longitude: data.message.locationMessage.degreesLongitude,
name: data.message.locationMessage.name,
address: data.message.locationMessage.address
},
id: MessageId(data.key.id),
timestamp: data.messageTimestamp
}));
// src/modules/messages/schemas/sticker.ts
import { z as z8 } from "zod";
var StickerMessageOptionsSchema = BaseMessageOptionsSchema.extend({
/**
* Image URL or file in base64
*/
sticker: mediaSchema
});
var StickerMessageBodySchema = StickerMessageOptionsSchema;
var StickerMessageResponseSchema = z8.object({
key: z8.object({
remoteJid: z8.string(),
id: z8.string()
}),
message: z8.object({
stickerMessage: z8.object({
url: z8.string().url(),
fileSha256: z8.string().base64(),
fileEncSha256: z8.string().base64(),
mediaKey: z8.string().base64(),
mimetype: z8.string().optional(),
directPath: z8.string(),
fileLength: z8.coerce.number(),
mediaKeyTimestamp: z8.coerce.number().transform((value) => new Date(value))
})
}),
messageTimestamp: z8.coerce.date()
}).transform((data) => ({
receiver: {
phoneNumber: phoneNumberFromJid(data.key.remoteJid),
jid: Jid(data.key.remoteJid)
},
media: {
url: data.message.stickerMessage.url,
mimetype: data.message.stickerMessage.mimetype,
length: data.message.stickerMessage.fileLength,
sha256: data.message.stickerMessage.fileSha256,
encryptedSha256: data.message.stickerMessage.fileEncSha256,
directPath: data.message.stickerMessage.directPath,
key: data.message.stickerMessage.mediaKey,
keyTimestamp: data.message.stickerMessage.mediaKeyTimestamp
},
id: MessageId(data.key.id),
timestamp: data.messageTimestamp
}));
// src/modules/messages/schemas/text.ts
import { z as z9 } from "zod";
var TextMessageOptionsSchema = BaseMessageOptionsSchema.extend({
/**
* Message text content
*/
text: z9.string(),
/**
* Whether link preview should be shown
*/
linkPreview: z9.boolean().optional()
});
var TextMessageBodySchema = TextMessageOptionsSchema;
var TextMessageResponseSchema = z9.object({
key: z9.object({
remoteJid: z9.string(),
id: z9.string()
}),
messageTimestamp: z9.coerce.date()
}).transform((data) => ({
receiver: {
phoneNumber: phoneNumberFromJid(data.key.remoteJid),
jid: Jid(data.key.remoteJid)
},
messageId: MessageId(data.key.id),
timestamp: data.messageTimestamp
}));
// src/modules/messages/schemas/video.ts
import { z as z10 } from "zod";
var VideoMessageOptionsSchema = BaseMessageOptionsSchema.extend({
/**
* Video URL or file in base64
*/
video: mediaSchema,
/**
* Caption to send with video
*/
caption: z10.string().optional(),
/**
* Video mimetype
*/
mimetype: z10.string().optional()
});
var VideoMessageBodySchema = VideoMessageOptionsSchema.transform(
({ video, ...data }) => ({ ...data, media: video, mediatype: "video" })
);
var VideoMessageResponseSchema = z10.object({
key: z10.object({
remoteJid: z10.string(),
id: z10.string()
}),
message: z10.object({
videoMessage: z10.object({
url: z10.string().url(),
mimetype: z10.string().optional(),
fileSha256: z10.string().base64(),
fileLength: z10.coerce.number(),
mediaKey: z10.string().base64(),
caption: z10.string().optional(),
gifPlayback: z10.boolean(),
fileEncSha256: z10.string().base64(),
directPath: z10.string(),
mediaKeyTimestamp: z10.coerce.number().transform((value) => new Date(value))
})
}),
messageTimestamp: z10.coerce.date()
}).transform((data) => ({
receiver: {
phoneNumber: phoneNumberFromJid(data.key.remoteJid),
jid: Jid(data.key.remoteJid)
},
media: {
url: data.message.videoMessage.url,
caption: data.message.videoMessage.caption,
mimetype: data.message.videoMessage.mimetype,
gifPlayback: data.message.videoMessage.gifPlayback,
length: data.message.videoMessage.fileLength,
sha256: data.message.videoMessage.fileSha256,
encryptedSha256: data.message.videoMessage.fileEncSha256,
directPath: data.message.videoMessage.directPath,
key: data.message.videoMessage.mediaKey,
keyTimestamp: data.message.videoMessage.mediaKeyTimestamp
},
id: MessageId(data.key.id),
timestamp: data.messageTimestamp
}));
// src/modules/messages/schemas/voice.ts
import { z as z11 } from "zod";
var VoiceMessageOptionsSchema = BaseMessageOptionsSchema.extend({
/**
* Audio URL or file in base64
*/
audio: mediaSchema,
/**
* Encode audio into WhatsApp default format (allows audio to be sped up)
* @default true
*/
encoding: z11.boolean().optional().default(true)
});
var VoiceMessageBodySchema = VoiceMessageOptionsSchema;
var VoiceMessageResponseSchema = z11.object({
key: z11.object({
remoteJid: z11.string(),
id: z11.string()
}),
message: z11.object({
audioMessage: z11.object({
url: z11.string().url(),
mimetype: z11.string(),
fileSha256: z11.string().base64(),
fileLength: z11.coerce.number(),
seconds: z11.number(),
ptt: z11.boolean().optional(),
mediaKey: z11.string().base64(),
fileEncSha256: z11.string().base64(),
directPath: z11.string(),
mediaKeyTimestamp: z11.coerce.number().transform((value) => new Date(value)),
waveform: z11.string().base64().nullish()
})
}),
messageTimestamp: z11.coerce.date()
}).transform((data) => ({
receiver: {
phoneNumber: phoneNumberFromJid(data.key.remoteJid),
jid: Jid(data.key.remoteJid)
},
media: {
url: data.message.audioMessage.url,
mimetype: data.message.audioMessage.mimetype,
length: data.message.audioMessage.fileLength,
durationInSeconds: data.message.audioMessage.seconds,
sha256: data.message.audioMessage.fileSha256,
encryptedSha256: data.message.audioMessage.fileEncSha256,
directPath: data.message.audioMessage.directPath,
/**
* Indicates whether the audio message is a push-to-talk (PTT) message
*/
isPtt: data.message.audioMessage.ptt,
key: data.message.audioMessage.mediaKey,
keyTimestamp: data.message.audioMessage.mediaKeyTimestamp,
waveform: data.message.audioMessage.waveform
},
messageId: MessageId(data.key.id),
timestamp: data.messageTimestamp
}));
// src/modules/messages/index.ts
var MessagesModule = class {
constructor(api) {
this.api = api;
}
/**
* Sends a text message
* @param options - Text message options
*/
async sendText(options) {
const body = TextMessageBodySchema.parse(options);
const response = await this.api.post(Routes.Message.SendText, { body });
return TextMessageResponseSchema.parse(response);
}
/**
* Sends an image
* @param options - Image message options
*/
async sendImage(options) {
const body = ImageMessageBodySchema.parse(options);
const response = await this.api.post(Routes.Message.SendMedia, { body });
return ImageMessageResponseSchema.parse(response);
}
/**
* Sends a video
* @param options - Video message options
*/
async sendVideo(options) {
const body = VideoMessageBodySchema.parse(options);
const response = await this.api.post(Routes.Message.SendMedia, { body });
return VideoMessageResponseSchema.parse(response);
}
/**
* Sends a document
* @param options - Document message options
*/
async sendDocument(options) {
const body = DocumentMessageBodySchema.parse(options);
const response = await this.api.post(Routes.Message.SendMedia, { body });
return DocumentMessageResponseSchema.parse(response);
}
/**
* Sends an audio
* @param options - Audio message options
*/
async sendAudio(options) {
const body = AudioMessageBodySchema.parse(options);
const response = await this.api.post(Routes.Message.SendMedia, { body });
return AudioMessageResponseSchema.parse(response);
}
/**
* Sends a voice message
* @param options - Voice message options
*/
async sendVoice(options) {
const body = VoiceMessageBodySchema.parse(options);
const response = await this.api.post(Routes.Message.SendVoice, { body });
return VoiceMessageResponseSchema.parse(response);
}
/**
* Sends a sticker
* @param options - Sticker message options
*/
async sendSticker(options) {
const body = StickerMessageBodySchema.parse(options);
const response = await this.api.post(Routes.Message.SendSticker, { body });
return StickerMessageResponseSchema.parse(response);
}
/**
* Sends a location
* @param options - Location message options
*/
async sendLocation(options) {
const body = LocationMessageBodySchema.parse(options);
const response = await this.api.post(Routes.Message.SendLocation, { body });
return LocationMessageResponseSchema.parse(response);
}
/**
* Sends a contact
* @param options - Contact message options
*/
async sendContact(options) {
const body = ContactMessageBodySchema.parse(options);
const response = await this.api.post(Routes.Message.SendContact, { body });
return ContactMessageResponseSchema.parse(response);
}
};
export {
MessagesModule
};
//# sourceMappingURL=index.mjs.map