/* * This file is part of WPPConnect. * * WPPConnect is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * WPPConnect is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with WPPConnect. If not, see . */ import type { AllMessageOptions, FileMessageOptions, ForwardMessagesOptions, ListMessageOptions, LocationMessageOptions, PoolMessageOptions, SendMessageOptions, TextMessageOptions, } from '@wppconnect/wa-js/dist/chat'; import { OrderItems, OrderMessageOptions, } from '@wppconnect/wa-js/dist/chat/functions/sendChargeMessage'; import * as path from 'path'; import { Page } from 'puppeteer'; import { CreateConfig } from '../../config/create-config'; import { PixParams } from '../../types/WAPI'; import { convertToMP4GIF } from '../../utils/ffmpeg'; import { base64MimeType, downloadFileToBase64, evaluateAndReturn, fileToBase64, stickerSelect, } from '../helpers'; import { filenameFromMimeType } from '../helpers/filename-from-mimetype'; import { Message, Wid } from '../model'; import { ChatState } from '../model/enum'; import { ListenerLayer } from './listener.layer'; export class SenderLayer extends ListenerLayer { constructor(public page: Page, session?: string, options?: CreateConfig) { super(page, session, options); } /** * Automatically sends a link with the auto generated link preview. You can also add a custom message to be added. * * Deprecated: please use {@link sendText} * * @category Chat * @deprecated * @param chatId * @param url string A link, for example for youtube. e.g https://www.youtube.com/watch?v=Zi_XLOBDo_Y&list=RDEMe12_MlgO8mGFdeeftZ2nOQ&start_radio=1 * @param text custom text as the message body, this includes the link or will be attached after the link */ public async sendLinkPreview(chatId: string, url: string, text: string = '') { const message = text.includes(url) ? text : `${url}\n${text}`; const result = await evaluateAndReturn( this.page, ({ chatId, message }) => { return WPP.chat.sendTextMessage(chatId, message, { linkPreview: true }); }, { chatId, message } ); return result; } /** * Sends a text message to given chat * @category Chat * @param to chat id: xxxxx@us.c * @param content text message * * @example * ```javascript * // Simple message * client.sendText('@c.us', 'A simple message'); * * // A message with reply * client.sendText('@c.us', 'A simple message', { * quotedMsg: 'true_...@c.us_3EB01DE65ACC6_out' * }); * * // With buttons * client.sendText('@c.us', 'WPPConnect message with buttons', { * useTemplateButtons: true, // False for legacy * buttons: [ * { * url: 'https://wppconnect.io/', * text: 'WPPConnect Site' * }, * { * phoneNumber: '+55 11 22334455', * text: 'Call me' * }, * { * id: 'your custom id 1', * text: 'Some text' * }, * { * id: 'another id 2', * text: 'Another text' * } * ], * title: 'Title text' // Optional * footer: 'Footer text' // Optional * }); * ``` */ public async sendText( to: string, content: string, options?: TextMessageOptions ): Promise { const sendResult = await evaluateAndReturn( this.page, ({ to, content, options }) => WPP.chat.sendTextMessage(to, content, { ...options, waitForAck: true, }), { to, content, options: options as any } ); // I don't know why the evaluate is returning undefined for direct call // To solve that, I added `JSON.parse(JSON.stringify())` to solve that const result = (await evaluateAndReturn( this.page, async ({ messageId }) => { return JSON.parse(JSON.stringify(await WAPI.getMessageById(messageId))); }, { messageId: sendResult.id } )) as Message; if (result['erro'] == true) { throw result; } return result; } /** * Sends a pix message to given chat * @category Chat * @param to chat id: xxxxx@us.c * @param content pix message * * @example * ```javascript * // Simple message * client.sendPix('@c.us', { keyType: 'PHONE', name: 'WPPCONNECT-TEAM', key: '+5567123456789', instructions: 'teste', }); * ``` */ public async sendPixKey( to: string, params: PixParams, options?: SendMessageOptions ): Promise { const sendResult = await evaluateAndReturn( this.page, ({ to, params, options }) => WPP.chat.sendPixKeyMessage(to, params, { ...options, waitForAck: true, }), { to, params, options: options as any } ); // I don't know why the evaluate is returning undefined for direct call // To solve that, I added `JSON.parse(JSON.stringify())` to solve that const result = (await evaluateAndReturn( this.page, async ({ messageId }) => { return JSON.parse(JSON.stringify(await WAPI.getMessageById(messageId))); }, { messageId: sendResult.id } )) as Message; if (result['erro'] == true) { throw result; } return result; } /** * * @category Chat * @param chat * @param content * @param options * @returns */ public async sendMessageOptions( chat: any, content: any, options?: any ): Promise { const messageId = await evaluateAndReturn( this.page, ({ chat, content, options }) => { return WAPI.sendMessageOptions(chat, content, options); }, { chat, content, options } ); const result = (await evaluateAndReturn( this.page, (messageId: any) => WAPI.getMessageById(messageId), messageId )) as Message; return result; } /** * Sends image message * @category Chat * @param to Chat id * @param filePath File path or http link * @param filename * @param caption * @param quotedMessageId Quoted message id * @param isViewOnce Enable single view */ public async sendImage( to: string, filePath: string, filename?: string, caption?: string, quotedMessageId?: string, isViewOnce?: boolean, options?: { msgId?: string; mentionedList?: string[]; } ) { let base64 = await downloadFileToBase64(filePath, [ 'image/gif', 'image/png', 'image/jpg', 'image/jpeg', 'image/webp', ]); if (!base64) { base64 = await fileToBase64(filePath); } if (!base64) { const obj = { erro: true, to: to, text: 'No such file or directory, open "' + filePath + '"', }; throw obj; } if (!filename) { filename = path.basename(filePath); } return await this.sendImageFromBase64( to, base64, filename, caption, quotedMessageId, isViewOnce, options?.mentionedList, options || {} ); } /** * Sends image message * @category Chat * @param to ID of the chat to send the image to * @param base64 A base64-encoded data URI (with mime type) * @param filename * @param caption * @param quotedMessageId Quoted message id * @param isViewOnce Enable single view * @param mentionedList * @example * ```javascript * const base64picture = "/9j/4AA[...]VZoCn9Lp//Z" * await client.sendImageFromBase64("120[...]381@g.us'", "data:image/png;base64," + base64picture, "picture.png") * ``` */ public async sendImageFromBase64( to: string, base64: string, filename: string, caption?: string, quotedMessageId?: string, isViewOnce?: boolean, mentionedList?: any, options?: { msgId?: string; } ) { let mimeType = base64MimeType(base64); if (!mimeType) { const obj = { erro: true, to: to, text: 'Invalid base64!', }; throw obj; } if (!mimeType.includes('image')) { const obj = { erro: true, to: to, text: 'Not an image, allowed formats png, jpeg and webp', }; throw obj; } filename = filenameFromMimeType(filename, mimeType); const result = await evaluateAndReturn( this.page, async ({ to, base64, filename, caption, quotedMessageId, isViewOnce, mentionedList, options, }) => { const result = await WPP.chat.sendFileMessage(to, base64, { type: 'image', isViewOnce, messageId: options?.msgId, filename, caption, quotedMsg: quotedMessageId, waitForAck: true, detectMentioned: true, mentionedList: mentionedList, }); return { ack: result.ack, id: result.id, sendMsgResult: await result.sendMsgResult, }; }, { to, base64, filename, caption, quotedMessageId, isViewOnce, mentionedList, options, } ); return result; } /** * Sends message with thumbnail * * @deprecated: please use {@link sendText} with options * * @deprecated * @category Chat * @param pathOrBase64 * @param url * @param title * @param description * @param chatId */ public async sendMessageWithThumb( pathOrBase64: string, url: string, title: string, description: string, chatId: string ) { let base64: string = ''; if (pathOrBase64.startsWith('data:')) { base64 = pathOrBase64; } else { let fileContent = await downloadFileToBase64(pathOrBase64, [ 'image/gif', 'image/png', 'image/jpg', 'image/jpeg', 'image/webp', ]); if (!fileContent) { fileContent = await fileToBase64(pathOrBase64); } if (fileContent) { base64 = fileContent; } } if (!base64) { const error = new Error('Empty or invalid file or base64'); Object.assign(error, { code: 'empty_file', }); throw error; } const mimeInfo = base64MimeType(base64); if (!mimeInfo || !mimeInfo.includes('image')) { const error = new Error( 'Not an image, allowed formats png, jpeg, webp and gif' ); Object.assign(error, { code: 'invalid_image', }); throw error; } const thumbnail = base64.replace( /^data:image\/(png|jpe?g|webp|gif);base64,/, '' ); return evaluateAndReturn( this.page, ({ thumbnail, url, title, description, chatId }) => WPP.chat.sendTextMessage(chatId, url, { linkPreview: { thumbnail: thumbnail, canonicalUrl: url, description: description, matchedText: url, title: title, richPreviewType: 0, doNotPlayInline: true, }, }), { thumbnail, url, title, description, chatId, } ); } /** * Replies to given mesage id of given chat id * * Deprecated: Please, use sendText with quotedMsg option * * @deprecated * * @category Chat * @param to Chat id * @param content Message body * @param quotedMsg Message id to reply to. */ public async reply( to: string, content: string, quotedMsg: string ): Promise { const result = await evaluateAndReturn( this.page, ({ to, content, quotedMsg }) => { return WPP.chat.sendTextMessage(to, content, { quotedMsg }); }, { to, content, quotedMsg } ); const message = (await evaluateAndReturn( this.page, (messageId: any) => WAPI.getMessageById(messageId), result.id )) as Message; if (message['erro'] == true) { throw message; } return message; } /** * Sends ptt audio * base64 parameter should have mime type already defined * @category Chat * @param to Chat id * @param base64 base64 data * @param filename * @param caption * @param quotedMessageId Quoted message id * @param messageId Set the id for this message * @param isPtt Set as ptt audio */ public async sendPttFromBase64( to: string, base64: string, filename: string, caption?: string, quotedMessageId?: string, messageId?: string, isPtt: boolean = true ) { const result = await evaluateAndReturn( this.page, async ({ to, base64, filename, caption, quotedMessageId, messageId, isPtt, }) => { const result = await WPP.chat.sendFileMessage(to, base64, { type: 'audio', isPtt: isPtt, filename, caption, quotedMsg: quotedMessageId, waitForAck: true, messageId: messageId, }); return { ack: result.ack, id: result.id, sendMsgResult: await result.sendMsgResult, }; }, { to, base64, filename, caption, quotedMessageId, messageId, isPtt } ); return result; } /** * Sends ptt audio from path * @category Chat * @param to Chat id * @param filePath File path * @param filename * @param caption * @param quotedMessageId Quoted message id * @param messageId Set the id for this message * @param isPtt Set as ptt audio */ public async sendPtt( to: string, filePath: string, filename?: string, caption?: string, quotedMessageId?: string, messageId?: string, isPtt: boolean = true ) { return new Promise(async (resolve, reject) => { let base64 = await downloadFileToBase64(filePath, [/^audio/]), obj: { erro: boolean; to: string; text: string }; if (!base64) { base64 = await fileToBase64(filePath); } if (!base64) { obj = { erro: true, to: to, text: 'No such file or directory, open "' + filePath + '"', }; return reject(obj); } if (!filename) { filename = path.basename(filePath); } return this.sendPttFromBase64( to, base64, filename, caption, quotedMessageId, messageId, isPtt ) .then(resolve) .catch(reject); }); } /** * Sends file * base64 parameter should have mime type already defined * * Deprecated: please use sendFile with options: sendFile(to, content, options) * * @deprecated * * @category Chat * @param chatId Chat id * @param base64 base64 data * @param filename * @param caption */ public async sendFileFromBase64( chatId: string, base64: string, filename: string, caption?: string ) { return this.sendFile(chatId, base64, filename, caption); } /** * Sends file from path or base64 * * @example * ```javascript * // File message from a path * client.sendFile('@c.us', './someFile.txt'); * // Simple message from base64 * * client.sendFile('@c.us', 'data:text/plain;base64,V1BQQ29ubmVjdA=='); * * // With buttons * client.sendFile('@c.us', 'data:text/plain;base64,V1BQQ29ubmVjdA==', { * useTemplateButtons: true, // False for legacy * buttons: [ * { * url: 'https://wppconnect.io/', * text: 'WPPConnect Site' * }, * { * phoneNumber: '+55 11 22334455', * text: 'Call me' * }, * { * id: 'your custom id 1', * text: 'Some text' * }, * { * id: 'another id 2', * text: 'Another text' * } * ], * title: 'Title text' // Optional * footer: 'Footer text' // Optional * }); * ``` * * @category Chat * @param to Chat id * @param pathOrBase64 File path * @param options */ public async sendFile( to: string | Wid, pathOrBase64: string, options?: FileMessageOptions ); /** * Sends file from path or base64 * * Deprecated: please use sendFile with options: sendFile(to, content, options) * * @deprecated * * @category Chat * @param to Chat id * @param pathOrBase64 File path or base64 * @param filename The file name * @param caption Caption for the filename */ public async sendFile( to: string, pathOrBase64: string, filename?: string, caption?: string ); public async sendFile( to: string, pathOrBase64: string, nameOrOptions?: string | FileMessageOptions, caption?: string ) { let options: FileMessageOptions = { type: 'auto-detect' }; if (typeof nameOrOptions === 'string') { options.filename = nameOrOptions; options.caption = caption; } else if (typeof nameOrOptions === 'object') { options = nameOrOptions; } let base64 = ''; if (pathOrBase64.startsWith('data:')) { base64 = pathOrBase64; } else { let fileContent = await downloadFileToBase64(pathOrBase64); if (!fileContent) { fileContent = await fileToBase64(pathOrBase64); } if (fileContent) { base64 = fileContent; } if (!options.filename) { options.filename = path.basename(pathOrBase64); } } if (!base64) { const error = new Error('Empty or invalid file or base64'); Object.assign(error, { code: 'empty_file', }); throw error; } return evaluateAndReturn( this.page, async ({ to, base64, options }) => { const result = await WPP.chat.sendFileMessage(to, base64, options); return { ack: result.ack, id: result.id, sendMsgResult: await result.sendMsgResult, }; }, { to, base64, options: options as any } ); } /** * Sends a video to given chat as a gif, with caption or not * @category Chat * @param to Chat id * @param filePath File path * @param filename * @param caption */ public async sendVideoAsGif( to: string, filePath: string, filename?: string, caption?: string ) { let base64 = await downloadFileToBase64(filePath), obj: { erro: boolean; to: string; text: string }; if (!base64) { base64 = await fileToBase64(filePath); } if (!base64) { obj = { erro: true, to: to, text: 'No such file or directory, open "' + filePath + '"', }; throw obj; } if (!filename) { filename = path.basename(filePath); } return this.sendVideoAsGifFromBase64(to, base64, filename, caption); } /** * Sends a video to given chat as a gif, with caption or not, using base64 * @category Chat * @param to chat id xxxxx@us.c * @param base64 base64 data:video/xxx;base64,xxx * @param filename string xxxxx * @param caption string xxxxx */ public async sendVideoAsGifFromBase64( to: string, base64: string, filename: string, caption?: string, quotedMessageId?: string ) { const result = await evaluateAndReturn( this.page, async ({ to, base64, filename, caption, quotedMessageId }) => { const result = await WPP.chat.sendFileMessage(to, base64, { type: 'video', isGif: true, filename, caption, quotedMsg: quotedMessageId, waitForAck: true, }); return { ack: result.ack, id: result.id, sendMsgResult: await result.sendMsgResult, }; }, { to, base64, filename, caption, quotedMessageId } ); return result; } /** * Sends a video to given chat as a gif, with caption or not, using base64 * @category Chat * @param to Chat id * @param filePath File path * @param filename * @param caption */ public async sendGif( to: string, filePath: string, filename?: string, caption?: string ) { let base64 = await downloadFileToBase64(filePath), obj: { erro: boolean; to: string; text: string }; if (!base64) { base64 = await fileToBase64(filePath); } if (!base64) { obj = { erro: true, to: to, text: 'No such file or directory, open "' + filePath + '"', }; throw obj; } if (!filename) { filename = path.basename(filePath); } return this.sendGifFromBase64(to, base64, filename, caption); } /** * Sends a video to given chat as a gif, with caption or not, using base64 * @category Chat * @param to chat id xxxxx@us.c * @param base64 base64 data:video/xxx;base64,xxx * @param filename string xxxxx * @param caption string xxxxx */ public async sendGifFromBase64( to: string, base64: string, filename: string, caption?: string ) { base64 = await convertToMP4GIF(base64); return await this.sendVideoAsGifFromBase64(to, base64, filename, caption); } /** * Sends contact card to iven chat id * @category Chat * @param to Chat id * @param contactsId Example: 0000@c.us | [000@c.us, 1111@c.us] */ public async sendContactVcard(to: string, contactsId: string, name?: string) { const result = await evaluateAndReturn( this.page, ({ to, contactsId, name }) => { return WPP.chat.sendVCardContactMessage(to, { id: contactsId, name: name, }); }, { to, contactsId, name } ); return result; } /** * Send a list of contact cards * @category Chat * @param to Chat id * @param contacts Example: | ['000@c.us', '1111@c.us', {id: '2222@c.us', name: 'Test'}] */ public async sendContactVcardList( to: string, contacts: (string | { id: string; name: string })[] ) { const result = await evaluateAndReturn( this.page, ({ to, contacts }) => { return WPP.chat.sendVCardContactMessage(to, contacts); }, { to, contacts } ); return result; } /** * Forwards array of messages (could be ids or message objects) * @deprecated please use {@link forwardMessagesV2} * @category Chat * @param to Chat id * @param messages Array of messages ids to be forwarded * @param skipMyMessages * @returns array of messages ID */ public async forwardMessage( toChatId: string, msgId: string | string[], options?: ForwardMessagesOptions ): Promise { return evaluateAndReturn( this.page, ({ toChatId, msgId, options }) => WPP.chat.forwardMessage(toChatId, msgId, options), { toChatId, msgId, options } ); } /** * Forwards array of messages (could be ids or message objects) * What is the difference between forwardMessage and forwardMessagesV2? * forwardMessage was used to forward a single message * forwardMessagesV2 is used to forward multiple messages * Also, it fixes how we pass the arguments to the whatsapp original function * From positional args to named args (object) * @category Chat * @param to Chat id * @param messages Array of messages ids to be forwarded * @param options * @returns array of messages ID */ public async forwardMessagesV2( toChatId: string, messages: string | string[], options?: ForwardMessagesOptions ): Promise> { return evaluateAndReturn( this.page, ({ toChatId, messages, options }) => WPP.chat.forwardMessages(toChatId, messages, options), { toChatId, messages, options } ); } /** * Generates sticker from the provided animated gif image and sends it (Send image as animated sticker) * * @example * ```javascript * client.sendImageAsStickerGif('000000000000@c.us', 'base64....'); * ``` * * @example * Send Sticker with reply * ```javascript * client.sendImageAsStickerGif('000000000000@c.us', 'base64....', { * quotedMsg: 'msgId', * }); * ``` * @category Chat * @param pathOrBase64 image path imageBase64 A valid gif image is required. You can also send via http/https (http://www.website.com/img.gif) * @param to chatId '000000000000@c.us' */ public async sendImageAsStickerGif( to: string, pathOrBase64: string, options?: AllMessageOptions ) { let base64: string = ''; if (pathOrBase64.startsWith('data:')) { base64 = pathOrBase64; } else { let fileContent = await downloadFileToBase64(pathOrBase64, [ 'image/gif', 'image/webp', ]); if (!fileContent) { fileContent = await fileToBase64(pathOrBase64); } if (fileContent) { base64 = fileContent; } } if (!base64) { const error = new Error('Empty or invalid file or base64'); Object.assign(error, { code: 'empty_file', }); throw error; } const mimeInfo = base64MimeType(base64); if (!mimeInfo || !mimeInfo.includes('image')) { const error = new Error('Not an image, allowed formats gig and webp'); Object.assign(error, { code: 'invalid_image', }); throw error; } const buff = Buffer.from( base64.replace(/^data:image\/(gif|webp);base64,/, ''), 'base64' ); let obj = await stickerSelect(buff, 1); if (!obj) { const error = new Error( 'Error with sharp library, check the console log' ); Object.assign(error, { code: 'sharp_error', }); throw error; } const { webpBase64 } = obj; return await evaluateAndReturn( this.page, ({ to, webpBase64, options }) => { return WPP.chat.sendFileMessage(to, webpBase64, { type: 'sticker', ...options, }); }, { to, webpBase64, options } ); } /** * Generates sticker from given image and sends it (Send Image As Sticker) * * @example * ```javascript * client.sendImageAsSticker('000000000000@c.us', 'base64....'); * ``` * * @example * Send Sticker with reply * ```javascript * client.sendImageAsSticker('000000000000@c.us', 'base64....', { * quotedMsg: 'msgId', * }); * ``` * * @category Chat * @param pathOrBase64 image path imageBase64 A valid png, jpg and webp image is required. You can also send via http/https (http://www.website.com/img.gif) * @param to chatId '000000000000@c.us' */ public async sendImageAsSticker( to: string, pathOrBase64: string, options?: AllMessageOptions ) { let base64: string = ''; if (pathOrBase64.startsWith('data:')) { base64 = pathOrBase64; } else { let fileContent = await downloadFileToBase64(pathOrBase64, [ 'image/gif', 'image/png', 'image/jpg', 'image/jpeg', 'image/webp', ]); if (!fileContent) { fileContent = await fileToBase64(pathOrBase64); } if (fileContent) { base64 = fileContent; } } if (!base64) { const error = new Error('Empty or invalid file or base64'); Object.assign(error, { code: 'empty_file', }); throw error; } const mimeInfo = base64MimeType(base64); if (!mimeInfo || !mimeInfo.includes('image')) { const error = new Error( 'Not an image, allowed formats png, jpeg, webp and gif' ); Object.assign(error, { code: 'invalid_image', }); throw error; } const buff = Buffer.from( base64.replace(/^data:image\/(png|jpe?g|webp|gif);base64,/, ''), 'base64' ); let obj = await stickerSelect(buff, 0); if (!obj) { const error = new Error( 'Error with sharp library, check the console log' ); Object.assign(error, { code: 'sharp_error', }); throw error; } const { webpBase64 } = obj; return await evaluateAndReturn( this.page, ({ to, webpBase64, options }) => { return WPP.chat.sendFileMessage(to, webpBase64, { type: 'sticker', ...options, }); }, { to, webpBase64, options } ); } /** * Sends location to given chat id * @category Chat * @param to Chat id * @param options location options */ public async sendLocation(to: string, options: LocationMessageOptions); /** * Sends location to given chat id * @category Chat * @param to Chat id * @param latitude Latitude * @param longitude Longitude * @param title Text caption */ public async sendLocation( to: string, latitude: string, longitude: string, title: string ); public async sendLocation( to: string, latitudeOrOptions: string | LocationMessageOptions, longitude?: string, title?: string ) { const options: LocationMessageOptions = typeof latitudeOrOptions === 'string' ? { lat: latitudeOrOptions, lng: longitude, title: title, } : latitudeOrOptions; return await evaluateAndReturn( this.page, async ({ to, options }) => { const result = await WPP.chat.sendLocationMessage(to, options); return { ack: result.ack, id: result.id, sendMsgResult: await result.sendMsgResult, }; }, { to, options: options as any } ); } /** * Sets a chat status to seen. Marks all messages as ack: 3 * @category Chat * @param chatId chat id: xxxxx@us.c */ public async sendSeen(chatId: string) { return evaluateAndReturn( this.page, (chatId) => WPP.chat.markIsRead(chatId), chatId ); } /** * Sets an audio or image view once. Marks message as played * @category Chat * @param msgId Message id: xxxxx@us.c */ public async markPlayed(msgId: string) { return evaluateAndReturn( this.page, (msgId) => WPP.chat.markPlayed(msgId), msgId ); } /** * Starts typing ('Typing...' state) * * @example * ```javascript * // Keep sending typing state, use stopTyping to finish * await client.startTyping('[number]@c.us'); * * // Keep sending typing state for 5 seconds * await client.startTyping('[number]@c.us', 5000); * ``` * @category Chat * @param to Chat Id * @param duration Duration in milliseconds */ public async startTyping(to: string, duration?: number) { return evaluateAndReturn( this.page, ({ to, duration }) => WPP.chat.markIsComposing(to, duration), { to, duration, } ); } /** * Stops typing ('Typing...' state) * @category Chat * @param to Chat Id */ public async stopTyping(to: string) { return evaluateAndReturn(this.page, ({ to }) => WPP.chat.markIsPaused(to), { to, }); } /** * Starts recording ('Recording...' state) * @example * ```javascript * // Keep sending recording state, use `stopRecording` to finish * await client.startRecording('[number]@c.us'); * * // Keep sending typing state for 5 seconds * await client.startRecording('[number]@c.us', 5000); * ``` * @category Chat * @param to Chat Id * @param duration Duration in milliseconds */ public async startRecording(to: string, duration?: number) { return evaluateAndReturn( this.page, ({ to, duration }) => WPP.chat.markIsRecording(to, duration), { to, duration, } ); } /** * Stops recording ('Recording...' state) * @deprecated please use {@link stopRecording} this function will be removed in future releases * @category Chat * @param to Chat Id */ public async stopRecoring(to: string) { return evaluateAndReturn(this.page, ({ to }) => WPP.chat.markIsPaused(to), { to, }); } /** * Stops recording ('Recording...' state) * @category Chat * @param to Chat Id */ public async stopRecording(to: string) { return evaluateAndReturn(this.page, ({ to }) => WPP.chat.markIsPaused(to), { to, }); } /** * Update your online presence * @category Chat * @param online true for available presence and false for unavailable */ public async setOnlinePresence(online: boolean = true) { return evaluateAndReturn( this.page, ({ online }) => WPP.conn.markAvailable(online), { online, } ); } /** * Sends text with tags * @category Chat */ public async sendMentioned(to: string, message: string, mentioned: string[]) { return await evaluateAndReturn( this.page, ({ to, message, mentioned }) => WPP.chat.sendTextMessage(to, message, { detectMentioned: true, mentionedList: mentioned, }), { to, message, mentioned } ); } /** * Sends a list message * * ```typescript * // Example * client.sendListMessage('@c.us', { * buttonText: 'Click here', * description: 'Choose one option', * sections: [ * { * title: 'Section 1', * rows: [ * { * rowId: 'my_custom_id', * title: 'Test 1', * description: 'Description 1', * }, * { * rowId: '2', * title: 'Test 2', * description: 'Description 2', * }, * ], * }, * ], * }); * ``` * * @category Chat */ public async sendListMessage(to: string, options: ListMessageOptions) { const sendResult = await evaluateAndReturn( this.page, ({ to, options }) => WPP.chat.sendListMessage(to, options), { to, options: options, } ); // I don't know why the evaluate is returning undefined for direct call // To solve that, I added `JSON.parse(JSON.stringify())` to solve that const result = (await evaluateAndReturn( this.page, async ({ messageId }) => { return JSON.parse(JSON.stringify(await WAPI.getMessageById(messageId))); }, { messageId: sendResult.id } )) as Message; if (result['erro'] == true) { throw result; } return result; } /** * Send a create poll message * * @example * ```javascript * // Single pool * client.sendPollMessage( * '[number]@g.us', * 'A poll name', * ['Option 1', 'Option 2', 'Option 3'] * ); * ``` * // Selectable Count * ```javascript * // Single pool * client.sendPollMessage( * '[number]@g.us', * 'A poll name', * ['Option 1', 'Option 2', 'Option 3'], * { * selectableCount: 1, * } * ); * ``` * * @category Chat */ public async sendPollMessage( chatId: string, name: string, choices: string[], options?: PoolMessageOptions ) { const sendResult = await evaluateAndReturn( this.page, ({ chatId, name, choices, options }) => WPP.chat.sendCreatePollMessage(chatId, name, choices, options), { chatId, name, choices, options: options, } ); // I don't know why the evaluate is returning undefined for direct call // To solve that, I added `JSON.parse(JSON.stringify())` to solve that const result = (await evaluateAndReturn( this.page, async ({ messageId }) => { return JSON.parse(JSON.stringify(await WAPI.getMessageById(messageId))); }, { messageId: sendResult.id } )) as Message; if (result['erro'] == true) { throw result; } return result; } /** * Sets the chat state * Deprecated in favor of Use startTyping or startRecording functions * @category Chat * @param chatState * @param chatId * @deprecated Deprecated in favor of Use startTyping or startRecording functions */ public async setChatState(chatId: string, chatState: ChatState) { return await evaluateAndReturn( this.page, ({ chatState, chatId }) => { WAPI.sendChatstate(chatState, chatId); }, { chatState, chatId } ); } /** * Send reaction to message * @example * ```javascript * // For send Reaction, just to send emoji * await client.sendReactionToMessage('[number]@c.us', '🤯'); * * // to remove reacition * await client.startRecording('[number]@c.us', false); * ``` * @category Chat * @param to Chat Id * @param duration Duration in milliseconds */ public async sendReactionToMessage(msgId: string, reaction: string | false) { return evaluateAndReturn( this.page, ({ msgId, reaction }) => WPP.chat.sendReactionToMessage(msgId, reaction), { msgId, reaction, } ); } /** * Send an order message * To send (prices, tax, shipping or discount), for example: USD 12.90, send them without dots or commas, like: 12900 * * @example * ```javascript * // Send an order with a product * client.sendOrderMessage('[number]@c.us', [ * { type: 'product', id: '67689897878', qnt: 2 }, * { type: 'product', id: '37878774457', qnt: 1 }, * ] * * // Send Order with a custom item * client.sendOrderMessage('[number]@c.us', [ * { type: 'custom', name: 'Item de cost test', price: 120000, qnt: 2 }, * ] * * // Send Order with custom options * client.sendOrderMessage('[number]@c.us', [ * { type: 'product', id: '37878774457', qnt: 1 }, * { type: 'custom', name: 'Item de cost test', price: 120000, qnt: 2 }, * ], * { tax: 10000, shipping: 4000, discount: 10000 } * ``` * * @category Chat */ public async sendOrderMessage( to: string, items: OrderItems[], options?: OrderMessageOptions ) { const sendResult = await evaluateAndReturn( this.page, ({ to, items, options }) => WPP.chat.sendChargeMessage(to, items, options), { to, items, options, } ); // I don't know why the evaluate is returning undefined for direct call // To solve that, I added `JSON.parse(JSON.stringify())` to solve that const result = (await evaluateAndReturn( this.page, async ({ messageId }) => { return JSON.parse(JSON.stringify(await WAPI.getMessageById(messageId))); }, { messageId: sendResult.id } )) as Message; if (result['erro'] == true) { throw result; } return result; } }