parent
a91bf1c762
commit
8e8d0c9b3e
6 changed files with 138 additions and 3 deletions
|
|
@ -201,6 +201,15 @@ client.on('message', async msg => {
|
|||
client.sendMessage(msg.from, list);
|
||||
} else if (msg.body === '!reaction') {
|
||||
msg.react('👍');
|
||||
} else if (msg.body === '!edit') {
|
||||
if (msg.hasQuotedMsg) {
|
||||
const quotedMsg = await msg.getQuotedMessage();
|
||||
if (quotedMsg.fromMe) {
|
||||
quotedMsg.edit(msg.body.replace('!edit', ''));
|
||||
} else {
|
||||
msg.reply('I can only edit my own messages');
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
|||
27
index.d.ts
vendored
27
index.d.ts
vendored
|
|
@ -242,6 +242,16 @@ declare namespace WAWebJS {
|
|||
ack: MessageAck
|
||||
) => void): this
|
||||
|
||||
/** Emitted when an ack event occurrs on message type */
|
||||
on(event: 'message_edit', listener: (
|
||||
/** The message that was affected */
|
||||
message: Message,
|
||||
/** New text message */
|
||||
newBody: String,
|
||||
/** Prev text message */
|
||||
prevBody: String
|
||||
) => void): this
|
||||
|
||||
/** Emitted when a chat unread count changes */
|
||||
on(event: 'unread_count', listener: (
|
||||
/** The chat that was affected */
|
||||
|
|
@ -567,6 +577,7 @@ declare namespace WAWebJS {
|
|||
MESSAGE_REVOKED_EVERYONE = 'message_revoke_everyone',
|
||||
MESSAGE_REVOKED_ME = 'message_revoke_me',
|
||||
MESSAGE_ACK = 'message_ack',
|
||||
MESSAGE_EDIT = 'message_edit',
|
||||
MEDIA_UPLOADED = 'media_uploaded',
|
||||
CONTACT_CHANGED = 'contact_changed',
|
||||
GROUP_JOIN = 'group_join',
|
||||
|
|
@ -789,6 +800,10 @@ declare namespace WAWebJS {
|
|||
businessOwnerJid?: string,
|
||||
/** Product JID */
|
||||
productId?: string,
|
||||
/** Last edit time */
|
||||
latestEditSenderTimestampMs?: number,
|
||||
/** Last edit message author */
|
||||
latestEditMsgKey?: MessageId,
|
||||
/** Message buttons */
|
||||
dynamicReplyButtons?: object,
|
||||
/** Selected button ID */
|
||||
|
|
@ -846,6 +861,8 @@ declare namespace WAWebJS {
|
|||
* Gets the reactions associated with the given message
|
||||
*/
|
||||
getReactions: () => Promise<ReactionList[]>,
|
||||
/** Edits the current message */
|
||||
edit: (content: MessageContent, options?: MessageEditOptions) => Promise<Message | null>,
|
||||
}
|
||||
|
||||
/** ID that represents a message */
|
||||
|
|
@ -911,6 +928,16 @@ declare namespace WAWebJS {
|
|||
stickerCategories?: string[]
|
||||
}
|
||||
|
||||
/** Options for editing a message */
|
||||
export interface MessageEditOptions {
|
||||
/** Show links preview. Has no effect on multi-device accounts. */
|
||||
linkPreview?: boolean
|
||||
/** Contacts that are being mentioned in the message */
|
||||
mentions?: Contact[]
|
||||
/** Extra options */
|
||||
extra?: any
|
||||
}
|
||||
|
||||
export interface MediaFromURLOptions {
|
||||
client?: Client
|
||||
filename?: string
|
||||
|
|
|
|||
|
|
@ -584,12 +584,28 @@ class Client extends EventEmitter {
|
|||
this.emit(Events.CHAT_ARCHIVED, new Chat(this, chat), currState, prevState);
|
||||
});
|
||||
|
||||
await page.exposeFunction('onEditMessageEvent', (msg, newBody, prevBody) => {
|
||||
|
||||
if(msg.type === 'revoked'){
|
||||
return;
|
||||
}
|
||||
/**
|
||||
* Emitted when messages are edited
|
||||
* @event Client#message_edit
|
||||
* @param {Message} message
|
||||
* @param {string} newBody
|
||||
* @param {string} prevBody
|
||||
*/
|
||||
this.emit(Events.MESSAGE_EDIT, new Message(this, msg), newBody, prevBody);
|
||||
});
|
||||
|
||||
await page.evaluate(() => {
|
||||
window.Store.Msg.on('change', (msg) => { window.onChangeMessageEvent(window.WWebJS.getMessageModel(msg)); });
|
||||
window.Store.Msg.on('change:type', (msg) => { window.onChangeMessageTypeEvent(window.WWebJS.getMessageModel(msg)); });
|
||||
window.Store.Msg.on('change:ack', (msg, ack) => { window.onMessageAckEvent(window.WWebJS.getMessageModel(msg), ack); });
|
||||
window.Store.Msg.on('change:isUnsentMedia', (msg, unsent) => { if (msg.id.fromMe && !unsent) window.onMessageMediaUploadedEvent(window.WWebJS.getMessageModel(msg)); });
|
||||
window.Store.Msg.on('remove', (msg) => { if (msg.isNewMsg) window.onRemoveMessageEvent(window.WWebJS.getMessageModel(msg)); });
|
||||
window.Store.Msg.on('change:body', (msg, newBody, prevBody) => { window.onEditMessageEvent(window.WWebJS.getMessageModel(msg), newBody, prevBody); });
|
||||
window.Store.AppState.on('change:state', (_AppState, state) => { window.onAppStateChangedEvent(state); });
|
||||
window.Store.Conn.on('change:battery', (state) => { window.onBatteryStateChangedEvent(state); });
|
||||
window.Store.Call.on('add', (call) => { window.onIncomingCall(call); });
|
||||
|
|
@ -732,7 +748,7 @@ class Client extends EventEmitter {
|
|||
* @property {string[]} [stickerCategories=undefined] - Sets the categories of the sticker, (if sendMediaAsSticker is true). Provide emoji char array, can be null.
|
||||
* @property {MessageMedia} [media] - Media to be sent
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* Send a message to a specific chatId
|
||||
* @param {string} chatId
|
||||
|
|
@ -785,7 +801,7 @@ class Client extends EventEmitter {
|
|||
internalOptions.list = content;
|
||||
content = '';
|
||||
}
|
||||
|
||||
|
||||
if (internalOptions.sendMediaAsSticker && internalOptions.attachment) {
|
||||
internalOptions.attachment = await Util.formatToWebpSticker(
|
||||
internalOptions.attachment, {
|
||||
|
|
@ -811,7 +827,7 @@ class Client extends EventEmitter {
|
|||
|
||||
return new Message(this, newMessage);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Searches for messages
|
||||
* @param {string} query
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ const Order = require('./Order');
|
|||
const Payment = require('./Payment');
|
||||
const Reaction = require('./Reaction');
|
||||
const {MessageTypes} = require('../util/Constants');
|
||||
const {Contact} = require('./Contact');
|
||||
|
||||
/**
|
||||
* Represents a Message on WhatsApp
|
||||
|
|
@ -224,6 +225,16 @@ class Message extends Base {
|
|||
this.productId = data.productId;
|
||||
}
|
||||
|
||||
/** Last edit time */
|
||||
if (data.latestEditSenderTimestampMs) {
|
||||
this.latestEditSenderTimestampMs = data.latestEditSenderTimestampMs;
|
||||
}
|
||||
|
||||
/** Last edit message author */
|
||||
if (data.latestEditMsgKey) {
|
||||
this.latestEditMsgKey = data.latestEditMsgKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* Links included in the message.
|
||||
* @type {Array<{link: string, isSuspicious: boolean}>}
|
||||
|
|
@ -576,6 +587,42 @@ class Message extends Base {
|
|||
return reaction;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Edits the current message.
|
||||
* @param {string} content
|
||||
* @param {MessageEditOptions} [options] - Options used when editing the message
|
||||
* @returns {Promise<?Message>}
|
||||
*/
|
||||
async edit(content, options = {}) {
|
||||
if (options.mentions && options.mentions.some(possiblyContact => possiblyContact instanceof Contact)) {
|
||||
options.mentions = options.mentions.map(a => a.id._serialized);
|
||||
}
|
||||
let internalOptions = {
|
||||
linkPreview: options.linkPreview === false ? undefined : true,
|
||||
mentionedJidList: Array.isArray(options.mentions) ? options.mentions : [],
|
||||
extraOptions: options.extra
|
||||
};
|
||||
|
||||
if (!this.fromMe) {
|
||||
return null;
|
||||
}
|
||||
const messageEdit = await this.client.pupPage.evaluate(async (msgId, message, options) => {
|
||||
let msg = window.Store.Msg.get(msgId);
|
||||
if (!msg) return null;
|
||||
|
||||
let catEdit = (msg.type === 'chat' && window.Store.MsgActionChecks.canEditText(msg));
|
||||
if (catEdit) {
|
||||
const msgEdit = await window.WWebJS.editMessage(msg, message, options);
|
||||
return msgEdit.serialize();
|
||||
}
|
||||
return null;
|
||||
}, this.id._serialized, content, internalOptions);
|
||||
if (messageEdit) {
|
||||
return new Message(this.client, messageEdit);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Message;
|
||||
|
|
|
|||
|
|
@ -48,6 +48,7 @@ exports.Events = {
|
|||
MESSAGE_REVOKED_EVERYONE: 'message_revoke_everyone',
|
||||
MESSAGE_REVOKED_ME: 'message_revoke_me',
|
||||
MESSAGE_ACK: 'message_ack',
|
||||
MESSAGE_EDIT: 'message_edit',
|
||||
UNREAD_COUNT: 'unread_count',
|
||||
MESSAGE_REACTION: 'message_reaction',
|
||||
MEDIA_UPLOADED: 'media_uploaded',
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ exports.ExposeStore = (moduleRaidStr) => {
|
|||
window.Store.SendClear = window.mR.findModule('sendClear')[0];
|
||||
window.Store.SendDelete = window.mR.findModule('sendDelete')[0];
|
||||
window.Store.SendMessage = window.mR.findModule('addAndSendMsgToChat')[0];
|
||||
window.Store.EditMessage = window.mR.findModule('addAndSendMessageEdit')[0];
|
||||
window.Store.SendSeen = window.mR.findModule('sendSeen')[0];
|
||||
window.Store.User = window.mR.findModule('getMaybeMeUser')[0];
|
||||
window.Store.UploadUtils = window.mR.findModule((module) => (module.default && module.default.encryptAndUpload) ? module.default : null)[0].default;
|
||||
|
|
@ -289,6 +290,40 @@ exports.LoadUtils = () => {
|
|||
await window.Store.SendMessage.addAndSendMsgToChat(chat, message);
|
||||
return window.Store.Msg.get(newMsgId._serialized);
|
||||
};
|
||||
|
||||
window.WWebJS.editMessage = async (msg, content, options = {}) => {
|
||||
|
||||
const extraOptions = options.extraOptions || {};
|
||||
delete options.extraOptions;
|
||||
|
||||
if (options.mentionedJidList) {
|
||||
options.mentionedJidList = options.mentionedJidList.map(cId => window.Store.Contact.get(cId).id);
|
||||
}
|
||||
|
||||
if (options.linkPreview) {
|
||||
options.linkPreview = null;
|
||||
|
||||
// Not supported yet by WhatsApp Web on MD
|
||||
if(!window.Store.MDBackend) {
|
||||
const link = window.Store.Validators.findLink(content);
|
||||
if (link) {
|
||||
const preview = await window.Store.Wap.queryLinkPreview(link.url);
|
||||
preview.preview = true;
|
||||
preview.subtype = 'url';
|
||||
options = { ...options, ...preview };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const internalOptions = {
|
||||
...options,
|
||||
...extraOptions
|
||||
};
|
||||
|
||||
await window.Store.EditMessage.sendMessageEdit(msg, content, internalOptions);
|
||||
return window.Store.Msg.get(msg.id._serialized);
|
||||
};
|
||||
|
||||
window.WWebJS.toStickerData = async (mediaInfo) => {
|
||||
if (mediaInfo.mimetype == 'image/webp') return mediaInfo;
|
||||
|
|
|
|||
Loading…
Reference in a new issue