mirror of
https://github.com/cheveguerra/whatsapp-web.js.git
synced 2026-04-17 19:26:20 +00:00
497 lines
16 KiB
HTML
497 lines
16 KiB
HTML
<!doctype html>
|
|
<html>
|
|
|
|
<head>
|
|
<meta name="generator" content="JSDoc 3.6.7">
|
|
<meta charset="utf-8">
|
|
<title>whatsapp-web.js 1.14.0 » Source: structures/Message.js</title>
|
|
<link rel="stylesheet" href="https://brick.a.ssl.fastly.net/Karla:400,400i,700,700i" type="text/css">
|
|
<link rel="stylesheet" href="https://brick.a.ssl.fastly.net/Noto+Serif:400,400i,700,700i" type="text/css">
|
|
<link rel="stylesheet" href="https://brick.a.ssl.fastly.net/Inconsolata:500" type="text/css">
|
|
<link href="css/baseline.css" rel="stylesheet">
|
|
</head>
|
|
|
|
<body onload="prettyPrint()">
|
|
<nav id="jsdoc-navbar" role="navigation" class="jsdoc-navbar">
|
|
<div id="jsdoc-navbar-container">
|
|
<div id="jsdoc-navbar-content">
|
|
<a href="index.html" class="jsdoc-navbar-package-name">whatsapp-web.<wbr>js 1.<wbr>14.<wbr>0</a>
|
|
</div>
|
|
</div>
|
|
</nav>
|
|
<div id="jsdoc-body-container">
|
|
<div id="jsdoc-content">
|
|
<div id="jsdoc-content-container">
|
|
<div id="jsdoc-banner" role="banner">
|
|
</div>
|
|
<div id="jsdoc-main" role="main">
|
|
<header class="page-header">
|
|
<h1>Source: structures/Message.js</h1>
|
|
</header>
|
|
<article>
|
|
<pre class="prettyprint linenums"><code>'use strict';
|
|
|
|
const Base = require('./Base');
|
|
const MessageMedia = require('./MessageMedia');
|
|
const Location = require('./Location');
|
|
const Order = require('./Order');
|
|
const { MessageTypes } = require('../util/Constants');
|
|
|
|
/**
|
|
* Represents a Message on WhatsApp
|
|
* @extends {Base}
|
|
*/
|
|
class Message extends Base {
|
|
constructor(client, data) {
|
|
super(client);
|
|
|
|
if (data) this._patch(data);
|
|
}
|
|
|
|
_patch(data) {
|
|
/**
|
|
* MediaKey that represents the sticker 'ID'
|
|
* @type {string}
|
|
*/
|
|
this.mediaKey = data.mediaKey;
|
|
|
|
|
|
/**
|
|
* ID that represents the message
|
|
* @type {object}
|
|
*/
|
|
this.id = data.id;
|
|
|
|
/**
|
|
* ACK status for the message
|
|
* @type {MessageAck}
|
|
*/
|
|
this.ack = data.ack;
|
|
|
|
/**
|
|
* Indicates if the message has media available for download
|
|
* @type {boolean}
|
|
*/
|
|
this.hasMedia = Boolean(data.mediaKey &amp;&amp; data.directPath);
|
|
|
|
/**
|
|
* Message content
|
|
* @type {string}
|
|
*/
|
|
this.body = this.hasMedia ? data.caption || '' : data.body || '';
|
|
|
|
/**
|
|
* Message type
|
|
* @type {MessageTypes}
|
|
*/
|
|
this.type = data.type;
|
|
|
|
/**
|
|
* Unix timestamp for when the message was created
|
|
* @type {number}
|
|
*/
|
|
this.timestamp = data.t;
|
|
|
|
/**
|
|
* ID for the Chat that this message was sent to, except if the message was sent by the current user.
|
|
* @type {string}
|
|
*/
|
|
this.from = (typeof (data.from) === 'object' &amp;&amp; data.from !== null) ? data.from._serialized : data.from;
|
|
|
|
/**
|
|
* ID for who this message is for.
|
|
*
|
|
* If the message is sent by the current user, it will be the Chat to which the message is being sent.
|
|
* If the message is sent by another user, it will be the ID for the current user.
|
|
* @type {string}
|
|
*/
|
|
this.to = (typeof (data.to) === 'object' &amp;&amp; data.to !== null) ? data.to._serialized : data.to;
|
|
|
|
/**
|
|
* If the message was sent to a group, this field will contain the user that sent the message.
|
|
* @type {string}
|
|
*/
|
|
this.author = (typeof (data.author) === 'object' &amp;&amp; data.author !== null) ? data.author._serialized : data.author;
|
|
|
|
/**
|
|
* String that represents from which device type the message was sent
|
|
* @type {string}
|
|
*/
|
|
this.deviceType = data.id.id.length > 21 ? 'android' : data.id.id.substring(0,2) =='3A' ? 'ios' : 'web';
|
|
|
|
/**
|
|
* Indicates if the message was forwarded
|
|
* @type {boolean}
|
|
*/
|
|
this.isForwarded = data.isForwarded;
|
|
|
|
/**
|
|
* Indicates how many times the message was forwarded.
|
|
*
|
|
* The maximum value is 127.
|
|
* @type {number}
|
|
*/
|
|
this.forwardingScore = data.forwardingScore || 0;
|
|
|
|
/**
|
|
* Indicates if the message is a status update
|
|
* @type {boolean}
|
|
*/
|
|
this.isStatus = data.isStatusV3;
|
|
|
|
/**
|
|
* Indicates if the message was starred
|
|
* @type {boolean}
|
|
*/
|
|
this.isStarred = data.star;
|
|
|
|
/**
|
|
* Indicates if the message was a broadcast
|
|
* @type {boolean}
|
|
*/
|
|
this.broadcast = data.broadcast;
|
|
|
|
/**
|
|
* Indicates if the message was sent by the current user
|
|
* @type {boolean}
|
|
*/
|
|
this.fromMe = data.id.fromMe;
|
|
|
|
/**
|
|
* Indicates if the message was sent as a reply to another message.
|
|
* @type {boolean}
|
|
*/
|
|
this.hasQuotedMsg = data.quotedMsg ? true : false;
|
|
|
|
/**
|
|
* Location information contained in the message, if the message is type "location"
|
|
* @type {Location}
|
|
*/
|
|
this.location = data.type === MessageTypes.LOCATION ? new Location(data.lat, data.lng, data.loc) : undefined;
|
|
|
|
/**
|
|
* List of vCards contained in the message.
|
|
* @type {Array&lt;string>}
|
|
*/
|
|
this.vCards = data.type === MessageTypes.CONTACT_CARD_MULTI ? data.vcardList.map((c) => c.vcard) : data.type === MessageTypes.CONTACT_CARD ? [data.body] : [];
|
|
|
|
/**
|
|
* Group Invite Data
|
|
* @type {object}
|
|
*/
|
|
this.inviteV4 = data.type === MessageTypes.GROUP_INVITE ? {
|
|
inviteCode: data.inviteCode,
|
|
inviteCodeExp: data.inviteCodeExp,
|
|
groupId: data.inviteGrp,
|
|
groupName: data.inviteGrpName,
|
|
fromId: data.from._serialized,
|
|
toId: data.to._serialized
|
|
} : undefined;
|
|
|
|
/**
|
|
* Indicates the mentions in the message body.
|
|
* @type {Array&lt;string>}
|
|
*/
|
|
this.mentionedIds = [];
|
|
|
|
if (data.mentionedJidList) {
|
|
this.mentionedIds = data.mentionedJidList;
|
|
}
|
|
|
|
/**
|
|
* Order ID for message type ORDER
|
|
* @type {string}
|
|
*/
|
|
this.orderId = data.orderId ? data.orderId : undefined;
|
|
/**
|
|
* Order Token for message type ORDER
|
|
* @type {string}
|
|
*/
|
|
this.token = data.token ? data.token : undefined;
|
|
|
|
/** Title */
|
|
if (data.title) {
|
|
this.title = data.title;
|
|
}
|
|
|
|
/** Description */
|
|
if (data.description) {
|
|
this.description = data.description;
|
|
}
|
|
|
|
/** Business Owner JID */
|
|
if (data.businessOwnerJid) {
|
|
this.businessOwnerJid = data.businessOwnerJid;
|
|
}
|
|
|
|
/** Product ID */
|
|
if (data.productId) {
|
|
this.productId = data.productId;
|
|
}
|
|
|
|
/**
|
|
* Links included in the message.
|
|
* @type {Array&lt;{link: string, isSuspicious: boolean}>}
|
|
*
|
|
*/
|
|
this.links = data.links;
|
|
|
|
return super._patch(data);
|
|
}
|
|
|
|
_getChatId() {
|
|
return this.fromMe ? this.to : this.from;
|
|
}
|
|
|
|
/**
|
|
* Returns the Chat this message was sent in
|
|
* @returns {Promise&lt;Chat>}
|
|
*/
|
|
getChat() {
|
|
return this.client.getChatById(this._getChatId());
|
|
}
|
|
|
|
/**
|
|
* Returns the Contact this message was sent from
|
|
* @returns {Promise&lt;Contact>}
|
|
*/
|
|
getContact() {
|
|
return this.client.getContactById(this.author || this.from);
|
|
}
|
|
|
|
/**
|
|
* Returns the Contacts mentioned in this message
|
|
* @returns {Promise&lt;Array&lt;Contact>>}
|
|
*/
|
|
async getMentions() {
|
|
return await Promise.all(this.mentionedIds.map(async m => await this.client.getContactById(m)));
|
|
}
|
|
|
|
/**
|
|
* Returns the quoted message, if any
|
|
* @returns {Promise&lt;Message>}
|
|
*/
|
|
async getQuotedMessage() {
|
|
if (!this.hasQuotedMsg) return undefined;
|
|
|
|
const quotedMsg = await this.client.pupPage.evaluate((msgId) => {
|
|
let msg = window.Store.Msg.get(msgId);
|
|
return msg.quotedMsgObj().serialize();
|
|
}, this.id._serialized);
|
|
|
|
return new Message(this.client, quotedMsg);
|
|
}
|
|
|
|
/**
|
|
* Sends a message as a reply to this message. If chatId is specified, it will be sent
|
|
* through the specified Chat. If not, it will send the message
|
|
* in the same Chat as the original message was sent.
|
|
*
|
|
* @param {string|MessageMedia|Location} content
|
|
* @param {string} [chatId]
|
|
* @param {MessageSendOptions} [options]
|
|
* @returns {Promise&lt;Message>}
|
|
*/
|
|
async reply(content, chatId, options = {}) {
|
|
if (!chatId) {
|
|
chatId = this._getChatId();
|
|
}
|
|
|
|
options = {
|
|
...options,
|
|
quotedMessageId: this.id._serialized
|
|
};
|
|
|
|
return this.client.sendMessage(chatId, content, options);
|
|
}
|
|
|
|
/**
|
|
* Accept Group V4 Invite
|
|
* @returns {Promise&lt;Object>}
|
|
*/
|
|
async acceptGroupV4Invite() {
|
|
return await this.client.acceptGroupV4Invite(this.inviteV4);
|
|
}
|
|
|
|
/**
|
|
* Forwards this message to another chat
|
|
*
|
|
* @param {string|Chat} chat Chat model or chat ID to which the message will be forwarded
|
|
* @returns {Promise}
|
|
*/
|
|
async forward(chat) {
|
|
const chatId = typeof chat === 'string' ? chat : chat.id._serialized;
|
|
|
|
await this.client.pupPage.evaluate(async (msgId, chatId) => {
|
|
let msg = window.Store.Msg.get(msgId);
|
|
let chat = window.Store.Chat.get(chatId);
|
|
|
|
return await chat.forwardMessages([msg]);
|
|
}, this.id._serialized, chatId);
|
|
}
|
|
|
|
/**
|
|
* Downloads and returns the attatched message media
|
|
* @returns {Promise&lt;MessageMedia>}
|
|
*/
|
|
async downloadMedia() {
|
|
if (!this.hasMedia) {
|
|
return undefined;
|
|
}
|
|
|
|
const result = await this.client.pupPage.evaluate(async (msgId) => {
|
|
const msg = window.Store.Msg.get(msgId);
|
|
|
|
if (msg.mediaData.mediaStage != 'RESOLVED') {
|
|
// try to resolve media
|
|
await msg.downloadMedia({
|
|
downloadEvenIfExpensive: true,
|
|
rmrReason: 1
|
|
});
|
|
}
|
|
|
|
if (msg.mediaData.mediaStage.includes('ERROR') || msg.mediaData.mediaStage === 'FETCHING') {
|
|
// media could not be downloaded
|
|
return undefined;
|
|
}
|
|
|
|
try {
|
|
const decryptedMedia = await window.Store.DownloadManager.downloadAndDecrypt({
|
|
directPath: msg.directPath,
|
|
encFilehash: msg.encFilehash,
|
|
filehash: msg.filehash,
|
|
mediaKey: msg.mediaKey,
|
|
mediaKeyTimestamp: msg.mediaKeyTimestamp,
|
|
type: msg.type,
|
|
signal: (new AbortController).signal
|
|
});
|
|
|
|
const data = window.WWebJS.arrayBufferToBase64(decryptedMedia);
|
|
|
|
return {
|
|
data,
|
|
mimetype: msg.mimetype,
|
|
filename: msg.filename
|
|
};
|
|
} catch (e) {
|
|
if(e.status &amp;&amp; e.status === 404) return undefined;
|
|
throw e;
|
|
}
|
|
}, this.id._serialized);
|
|
|
|
if (!result) return undefined;
|
|
return new MessageMedia(result.mimetype, result.data, result.filename);
|
|
}
|
|
|
|
/**
|
|
* Deletes a message from the chat
|
|
* @param {?boolean} everyone If true and the message is sent by the current user, will delete it for everyone in the chat.
|
|
*/
|
|
async delete(everyone) {
|
|
await this.client.pupPage.evaluate((msgId, everyone) => {
|
|
let msg = window.Store.Msg.get(msgId);
|
|
|
|
if (everyone &amp;&amp; msg.id.fromMe &amp;&amp; msg.canRevoke()) {
|
|
return window.Store.Cmd.sendRevokeMsgs(msg.chat, [msg], true);
|
|
}
|
|
|
|
return window.Store.Cmd.sendDeleteMsgs(msg.chat, [msg], true);
|
|
}, this.id._serialized, everyone);
|
|
}
|
|
|
|
/**
|
|
* Stars this message
|
|
*/
|
|
async star() {
|
|
await this.client.pupPage.evaluate((msgId) => {
|
|
let msg = window.Store.Msg.get(msgId);
|
|
|
|
if (msg.canStar()) {
|
|
return msg.chat.sendStarMsgs([msg], true);
|
|
}
|
|
}, this.id._serialized);
|
|
}
|
|
|
|
/**
|
|
* Unstars this message
|
|
*/
|
|
async unstar() {
|
|
await this.client.pupPage.evaluate((msgId) => {
|
|
let msg = window.Store.Msg.get(msgId);
|
|
|
|
if (msg.canStar()) {
|
|
return msg.chat.sendStarMsgs([msg], false);
|
|
}
|
|
}, this.id._serialized);
|
|
}
|
|
|
|
/**
|
|
* Message Info
|
|
* @typedef {Object} MessageInfo
|
|
* @property {Array&lt;{id: ContactId, t: number}>} delivery Contacts to which the message has been delivered to
|
|
* @property {number} deliveryRemaining Amount of people to whom the message has not been delivered to
|
|
* @property {Array&lt;{id: ContactId, t: number}>} played Contacts who have listened to the voice message
|
|
* @property {number} playedRemaining Amount of people who have not listened to the message
|
|
* @property {Array&lt;{id: ContactId, t: number}>} read Contacts who have read the message
|
|
* @property {number} readRemaining Amount of people who have not read the message
|
|
*/
|
|
|
|
/**
|
|
* Get information about message delivery status. May return null if the message does not exist or is not sent by you.
|
|
* @returns {Promise&lt;?MessageInfo>}
|
|
*/
|
|
async getInfo() {
|
|
const info = await this.client.pupPage.evaluate(async (msgId) => {
|
|
const msg = window.Store.Msg.get(msgId);
|
|
if(!msg) return null;
|
|
|
|
return await window.Store.Wap.queryMsgInfo(msg.id);
|
|
}, this.id._serialized);
|
|
|
|
if(info.status) {
|
|
return null;
|
|
}
|
|
|
|
return info;
|
|
}
|
|
|
|
/**
|
|
* Gets the order associated with a given message
|
|
* @return {Promise&lt;Order>}
|
|
*/
|
|
async getOrder() {
|
|
if (this.type === MessageTypes.ORDER) {
|
|
const result = await this.client.pupPage.evaluate((orderId, token) => {
|
|
return window.WWebJS.getOrderDetail(orderId, token);
|
|
}, this.orderId, this.token);
|
|
if (!result) return undefined;
|
|
return new Order(this.client, result);
|
|
}
|
|
return undefined;
|
|
}
|
|
}
|
|
|
|
module.exports = Message;
|
|
</code></pre>
|
|
</article>
|
|
</div>
|
|
</div>
|
|
<nav id="jsdoc-toc-nav" role="navigation"></nav>
|
|
</div>
|
|
</div>
|
|
<footer id="jsdoc-footer" class="jsdoc-footer">
|
|
<div id="jsdoc-footer-container">
|
|
<p>
|
|
Generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc</a> 3.6.7 on August 1, 2021.
|
|
</p>
|
|
</div>
|
|
</footer>
|
|
<script src="scripts/jquery.min.js"></script>
|
|
<script src="scripts/tree.jquery.js"></script>
|
|
<script src="scripts/prettify.js"></script>
|
|
<script src="scripts/jsdoc-toc.js"></script>
|
|
<script src="scripts/linenumber.js"></script>
|
|
<script src="scripts/scrollanchor.js"></script>
|
|
</body>
|
|
|
|
</html> |