feat: group mentions + improved user mentions (#2602)
* added logic to mention groups + fixed user mentions * usage example updated * docs fixed * window.injectToFunction clarifications * usage example clarifications * fix: typo * docs: added missed docs
This commit is contained in:
parent
8d683a668b
commit
e0d955f130
5 changed files with 164 additions and 25 deletions
54
example.js
54
example.js
|
|
@ -240,12 +240,52 @@ client.on('message', async msg => {
|
||||||
const newStatus = msg.body.split(' ')[1];
|
const newStatus = msg.body.split(' ')[1];
|
||||||
await client.setStatus(newStatus);
|
await client.setStatus(newStatus);
|
||||||
msg.reply(`Status was updated to *${newStatus}*`);
|
msg.reply(`Status was updated to *${newStatus}*`);
|
||||||
} else if (msg.body === '!mention') {
|
} else if (msg.body === '!mentionUsers') {
|
||||||
const contact = await msg.getContact();
|
|
||||||
const chat = await msg.getChat();
|
const chat = await msg.getChat();
|
||||||
chat.sendMessage(`Hi @${contact.number}!`, {
|
const userNumber = 'XXXXXXXXXX';
|
||||||
mentions: [contact]
|
/**
|
||||||
|
* To mention one user you can pass user's ID to 'mentions' property as is,
|
||||||
|
* without wrapping it in Array, and a user's phone number to the message body:
|
||||||
|
*/
|
||||||
|
await chat.sendMessage(`Hi @${userNumber}`, {
|
||||||
|
mentions: userNumber + '@c.us'
|
||||||
});
|
});
|
||||||
|
// To mention a list of users:
|
||||||
|
await chat.sendMessage(`Hi @${userNumber}, @${userNumber}`, {
|
||||||
|
mentions: [userNumber + '@c.us', userNumber + '@c.us']
|
||||||
|
});
|
||||||
|
} else if (msg.body === '!mentionGroups') {
|
||||||
|
const chat = await msg.getChat();
|
||||||
|
const groupId = 'YYYYYYYYYY@g.us';
|
||||||
|
/**
|
||||||
|
* Sends clickable group mentions, the same as user mentions.
|
||||||
|
* When the mentions are clicked, it opens a chat with the mentioned group.
|
||||||
|
* The 'groupMentions.subject' can be custom
|
||||||
|
*
|
||||||
|
* @note The user that does not participate in the mentioned group,
|
||||||
|
* will not be able to click on that mentioned group, the same if the group does not exist
|
||||||
|
*
|
||||||
|
* To mention one group:
|
||||||
|
*/
|
||||||
|
await chat.sendMessage(`Check the last message here: @${groupId}`, {
|
||||||
|
groupMentions: { subject: 'GroupSubject', id: groupId }
|
||||||
|
});
|
||||||
|
// To mention a list of groups:
|
||||||
|
await chat.sendMessage(`Check the last message in these groups: @${groupId}, @${groupId}`, {
|
||||||
|
groupMentions: [
|
||||||
|
{ subject: 'FirstGroup', id: groupId },
|
||||||
|
{ subject: 'SecondGroup', id: groupId }
|
||||||
|
]
|
||||||
|
});
|
||||||
|
} else if (msg.body === '!getGroupMentions') {
|
||||||
|
// To get group mentions from a message:
|
||||||
|
const groupId = 'ZZZZZZZZZZ@g.us';
|
||||||
|
const msg = await client.sendMessage('chatId', `Check the last message here: @${groupId}`, {
|
||||||
|
groupMentions: { subject: 'GroupSubject', id: groupId }
|
||||||
|
});
|
||||||
|
/** {@link groupMentions} is an array of `GroupChat` */
|
||||||
|
const groupMentions = await msg.getGroupMentions();
|
||||||
|
console.log(groupMentions);
|
||||||
} else if (msg.body === '!delete') {
|
} else if (msg.body === '!delete') {
|
||||||
if (msg.hasQuotedMsg) {
|
if (msg.hasQuotedMsg) {
|
||||||
const quotedMsg = await msg.getQuotedMessage();
|
const quotedMsg = await msg.getQuotedMessage();
|
||||||
|
|
@ -288,7 +328,9 @@ client.on('message', async msg => {
|
||||||
let button = new Buttons('Button body', [{ body: 'bt1' }, { body: 'bt2' }, { body: 'bt3' }], 'title', 'footer');
|
let button = new Buttons('Button body', [{ body: 'bt1' }, { body: 'bt2' }, { body: 'bt3' }], 'title', 'footer');
|
||||||
client.sendMessage(msg.from, button);
|
client.sendMessage(msg.from, button);
|
||||||
} else if (msg.body === '!list') {
|
} else if (msg.body === '!list') {
|
||||||
let sections = [{ title: 'sectionTitle', rows: [{ title: 'ListItem1', description: 'desc' }, { title: 'ListItem2' }] }];
|
let sections = [
|
||||||
|
{ title: 'sectionTitle', rows: [{ title: 'ListItem1', description: 'desc' }, { title: 'ListItem2' }] }
|
||||||
|
];
|
||||||
let list = new List('List body', 'btnText', sections, 'Title', 'footer');
|
let list = new List('List body', 'btnText', sections, 'Title', 'footer');
|
||||||
client.sendMessage(msg.from, list);
|
client.sendMessage(msg.from, list);
|
||||||
} else if (msg.body === '!reaction') {
|
} else if (msg.body === '!reaction') {
|
||||||
|
|
@ -323,7 +365,7 @@ client.on('message', async msg => {
|
||||||
await chat.changeLabels([0, 1]);
|
await chat.changeLabels([0, 1]);
|
||||||
} else if (msg.body === '!addlabels') {
|
} else if (msg.body === '!addlabels') {
|
||||||
const chat = await msg.getChat();
|
const chat = await msg.getChat();
|
||||||
let labels = (await chat.getLabels()).map(l => l.id);
|
let labels = (await chat.getLabels()).map((l) => l.id);
|
||||||
labels.push('0');
|
labels.push('0');
|
||||||
labels.push('1');
|
labels.push('1');
|
||||||
await chat.changeLabels(labels);
|
await chat.changeLabels(labels);
|
||||||
|
|
|
||||||
24
index.d.ts
vendored
24
index.d.ts
vendored
|
|
@ -857,7 +857,16 @@ declare namespace WAWebJS {
|
||||||
/** MediaKey that represents the sticker 'ID' */
|
/** MediaKey that represents the sticker 'ID' */
|
||||||
mediaKey?: string,
|
mediaKey?: string,
|
||||||
/** Indicates the mentions in the message body. */
|
/** Indicates the mentions in the message body. */
|
||||||
mentionedIds: [],
|
mentionedIds: ChatId[],
|
||||||
|
/** Indicates whether there are group mentions in the message body */
|
||||||
|
groupMentions: {
|
||||||
|
groupSubject: string;
|
||||||
|
groupJid: {
|
||||||
|
server: string;
|
||||||
|
user: string;
|
||||||
|
_serialized: string;
|
||||||
|
};
|
||||||
|
}[],
|
||||||
/** Unix timestamp for when the message was created */
|
/** Unix timestamp for when the message was created */
|
||||||
timestamp: number,
|
timestamp: number,
|
||||||
/**
|
/**
|
||||||
|
|
@ -917,6 +926,8 @@ declare namespace WAWebJS {
|
||||||
getContact: () => Promise<Contact>,
|
getContact: () => Promise<Contact>,
|
||||||
/** Returns the Contacts mentioned in this message */
|
/** Returns the Contacts mentioned in this message */
|
||||||
getMentions: () => Promise<Contact[]>,
|
getMentions: () => Promise<Contact[]>,
|
||||||
|
/** Returns groups mentioned in this message */
|
||||||
|
getGroupMentions: () => Promise<GroupChat[]|[]>,
|
||||||
/** Returns the quoted message, if any */
|
/** Returns the quoted message, if any */
|
||||||
getQuotedMessage: () => Promise<Message>,
|
getQuotedMessage: () => Promise<Message>,
|
||||||
/**
|
/**
|
||||||
|
|
@ -1039,8 +1050,15 @@ declare namespace WAWebJS {
|
||||||
caption?: string
|
caption?: string
|
||||||
/** Id of the message that is being quoted (or replied to) */
|
/** Id of the message that is being quoted (or replied to) */
|
||||||
quotedMessageId?: string
|
quotedMessageId?: string
|
||||||
/** Contacts that are being mentioned in the message */
|
/** User IDs to mention in the message */
|
||||||
mentions?: Contact[]
|
mentions?: string[]
|
||||||
|
/** An array of object that handle group mentions */
|
||||||
|
groupMentions?: {
|
||||||
|
/** The name of a group to mention (can be custom) */
|
||||||
|
subject: string,
|
||||||
|
/** The group ID, e.g.: 'XXXXXXXXXX@g.us' */
|
||||||
|
id: string
|
||||||
|
}[]
|
||||||
/** Send 'seen' status */
|
/** Send 'seen' status */
|
||||||
sendSeen?: boolean
|
sendSeen?: boolean
|
||||||
/** Media to be sent */
|
/** Media to be sent */
|
||||||
|
|
|
||||||
|
|
@ -810,6 +810,13 @@ class Client extends EventEmitter {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An object representing mentions of groups
|
||||||
|
* @typedef {Object} GroupMention
|
||||||
|
* @property {string} subject - The name of a group to mention (can be custom)
|
||||||
|
* @property {string} id - The group ID, e.g.: 'XXXXXXXXXX@g.us'
|
||||||
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Message options.
|
* Message options.
|
||||||
* @typedef {Object} MessageSendOptions
|
* @typedef {Object} MessageSendOptions
|
||||||
|
|
@ -822,7 +829,8 @@ class Client extends EventEmitter {
|
||||||
* @property {boolean} [parseVCards=true] - Automatically parse vCards and send them as contacts
|
* @property {boolean} [parseVCards=true] - Automatically parse vCards and send them as contacts
|
||||||
* @property {string} [caption] - Image or video caption
|
* @property {string} [caption] - Image or video caption
|
||||||
* @property {string} [quotedMessageId] - Id of the message that is being quoted (or replied to)
|
* @property {string} [quotedMessageId] - Id of the message that is being quoted (or replied to)
|
||||||
* @property {Contact[]} [mentions] - Contacts that are being mentioned in the message
|
* @property {GroupMention[]} [groupMentions] - An array of object that handle group mentions
|
||||||
|
* @property {string[]} [mentions] - User IDs to mention in the message
|
||||||
* @property {boolean} [sendSeen=true] - Mark the conversation as seen after sending the message
|
* @property {boolean} [sendSeen=true] - Mark the conversation as seen after sending the message
|
||||||
* @property {string} [stickerAuthor=undefined] - Sets the author of the sticker, (if sendMediaAsSticker is true).
|
* @property {string} [stickerAuthor=undefined] - Sets the author of the sticker, (if sendMediaAsSticker is true).
|
||||||
* @property {string} [stickerName=undefined] - Sets the name of the sticker, (if sendMediaAsSticker is true).
|
* @property {string} [stickerName=undefined] - Sets the name of the sticker, (if sendMediaAsSticker is true).
|
||||||
|
|
@ -839,10 +847,16 @@ class Client extends EventEmitter {
|
||||||
* @returns {Promise<Message>} Message that was just sent
|
* @returns {Promise<Message>} Message that was just sent
|
||||||
*/
|
*/
|
||||||
async sendMessage(chatId, content, options = {}) {
|
async sendMessage(chatId, content, options = {}) {
|
||||||
if (options.mentions && options.mentions.some(possiblyContact => possiblyContact instanceof Contact)) {
|
if (options.mentions) {
|
||||||
console.warn('Mentions with an array of Contact are now deprecated. See more at https://github.com/pedroslopez/whatsapp-web.js/pull/2166.');
|
!Array.isArray(options.mentions) && (options.mentions = [options.mentions]);
|
||||||
options.mentions = options.mentions.map(a => a.id._serialized);
|
if (options.mentions.some((possiblyContact) => possiblyContact instanceof Contact)) {
|
||||||
|
console.warn('Mentions with an array of Contact are now deprecated. See more at https://github.com/pedroslopez/whatsapp-web.js/pull/2166.');
|
||||||
|
options.mentions = options.mentions.map((a) => a.id._serialized);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
options.groupMentions && !Array.isArray(options.groupMentions) && (options.groupMentions = [options.groupMentions]);
|
||||||
|
|
||||||
let internalOptions = {
|
let internalOptions = {
|
||||||
linkPreview: options.linkPreview === false ? undefined : true,
|
linkPreview: options.linkPreview === false ? undefined : true,
|
||||||
sendAudioAsVoice: options.sendAudioAsVoice,
|
sendAudioAsVoice: options.sendAudioAsVoice,
|
||||||
|
|
@ -852,7 +866,8 @@ class Client extends EventEmitter {
|
||||||
caption: options.caption,
|
caption: options.caption,
|
||||||
quotedMessageId: options.quotedMessageId,
|
quotedMessageId: options.quotedMessageId,
|
||||||
parseVCards: options.parseVCards === false ? false : true,
|
parseVCards: options.parseVCards === false ? false : true,
|
||||||
mentionedJidList: Array.isArray(options.mentions) ? options.mentions : [],
|
mentionedJidList: options.mentions || [],
|
||||||
|
groupMentions: options.groupMentions,
|
||||||
extraOptions: options.extra
|
extraOptions: options.extra
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -187,14 +187,32 @@ class Message extends Base {
|
||||||
} : undefined;
|
} : undefined;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Indicates the mentions in the message body.
|
* @typedef {Object} Mention
|
||||||
* @type {Array<string>}
|
* @property {string} server
|
||||||
|
* @property {string} user
|
||||||
|
* @property {string} _serialized
|
||||||
*/
|
*/
|
||||||
this.mentionedIds = [];
|
|
||||||
|
|
||||||
if (data.mentionedJidList) {
|
/**
|
||||||
this.mentionedIds = data.mentionedJidList;
|
* Indicates the mentions in the message body.
|
||||||
}
|
* @type {Mention[]}
|
||||||
|
*/
|
||||||
|
this.mentionedIds = data.mentionedJidList || [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef {Object} GroupMention
|
||||||
|
* @property {string} groupSubject The name of the group
|
||||||
|
* @property {Object} groupJid The group ID
|
||||||
|
* @property {string} groupJid.server
|
||||||
|
* @property {string} groupJid.user
|
||||||
|
* @property {string} groupJid._serialized
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicates whether there are group mentions in the message body
|
||||||
|
* @type {GroupMention[]}
|
||||||
|
*/
|
||||||
|
this.groupMentions = data.groupMentions || [];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Order ID for message type ORDER
|
* Order ID for message type ORDER
|
||||||
|
|
@ -341,6 +359,14 @@ class Message extends Base {
|
||||||
async getMentions() {
|
async getMentions() {
|
||||||
return await Promise.all(this.mentionedIds.map(async m => await this.client.getContactById(m)));
|
return await Promise.all(this.mentionedIds.map(async m => await this.client.getContactById(m)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns groups mentioned in this message
|
||||||
|
* @returns {Promise<GroupChat[]|[]>}
|
||||||
|
*/
|
||||||
|
async getGroupMentions() {
|
||||||
|
return await Promise.all(this.groupMentions.map(async (m) => await this.client.getChatById(m.groupJid._serialized)));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the quoted message, if any
|
* Returns the quoted message, if any
|
||||||
|
|
@ -649,12 +675,20 @@ class Message extends Base {
|
||||||
* @returns {Promise<?Message>}
|
* @returns {Promise<?Message>}
|
||||||
*/
|
*/
|
||||||
async edit(content, options = {}) {
|
async edit(content, options = {}) {
|
||||||
if (options.mentions && options.mentions.some(possiblyContact => possiblyContact instanceof Contact)) {
|
if (options.mentions) {
|
||||||
options.mentions = options.mentions.map(a => a.id._serialized);
|
!Array.isArray(options.mentions) && (options.mentions = [options.mentions]);
|
||||||
|
if (options.mentions.some((possiblyContact) => possiblyContact instanceof Contact)) {
|
||||||
|
console.warn('Mentions with an array of Contact are now deprecated. See more at https://github.com/pedroslopez/whatsapp-web.js/pull/2166.');
|
||||||
|
options.mentions = options.mentions.map((a) => a.id._serialized);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
options.groupMentions && !Array.isArray(options.groupMentions) && (options.groupMentions = [options.groupMentions]);
|
||||||
|
|
||||||
let internalOptions = {
|
let internalOptions = {
|
||||||
linkPreview: options.linkPreview === false ? undefined : true,
|
linkPreview: options.linkPreview === false ? undefined : true,
|
||||||
mentionedJidList: Array.isArray(options.mentions) ? options.mentions : [],
|
mentionedJidList: options.mentions || [],
|
||||||
|
groupMentions: options.groupMentions,
|
||||||
extraOptions: options.extra
|
extraOptions: options.extra
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -58,12 +58,12 @@ exports.ExposeStore = (moduleRaidStr) => {
|
||||||
window.Store.LidUtils = window.mR.findModule('getCurrentLid')[0];
|
window.Store.LidUtils = window.mR.findModule('getCurrentLid')[0];
|
||||||
window.Store.WidToJid = window.mR.findModule('widToUserJid')[0];
|
window.Store.WidToJid = window.mR.findModule('widToUserJid')[0];
|
||||||
window.Store.JidToWid = window.mR.findModule('userJidToUserWid')[0];
|
window.Store.JidToWid = window.mR.findModule('userJidToUserWid')[0];
|
||||||
|
window.Store.getMsgInfo = (window.mR.findModule('sendQueryMsgInfo')[0] || {}).sendQueryMsgInfo || window.mR.findModule('queryMsgInfo')[0].queryMsgInfo;
|
||||||
window.Store.pinUnpinMsg = window.mR.findModule('sendPinInChatMsg')[0].sendPinInChatMsg;
|
window.Store.pinUnpinMsg = window.mR.findModule('sendPinInChatMsg')[0].sendPinInChatMsg;
|
||||||
|
|
||||||
/* eslint-disable no-undef, no-cond-assign */
|
/* eslint-disable no-undef, no-cond-assign */
|
||||||
window.Store.QueryExist = ((m = window.mR.findModule('queryExists')[0]) ? m.queryExists : window.mR.findModule('queryExist')[0].queryWidExists);
|
window.Store.QueryExist = ((m = window.mR.findModule('queryExists')[0]) ? m.queryExists : window.mR.findModule('queryExist')[0].queryWidExists);
|
||||||
window.Store.ReplyUtils = (m = window.mR.findModule('canReplyMsg')).length > 0 && m[0];
|
window.Store.ReplyUtils = (m = window.mR.findModule('canReplyMsg')).length > 0 && m[0];
|
||||||
window.Store.getMsgInfo = (window.mR.findModule('sendQueryMsgInfo')[0] || {}).sendQueryMsgInfo || window.mR.findModule('queryMsgInfo')[0].queryMsgInfo;
|
|
||||||
/* eslint-enable no-undef, no-cond-assign */
|
/* eslint-enable no-undef, no-cond-assign */
|
||||||
|
|
||||||
window.Store.Settings = {
|
window.Store.Settings = {
|
||||||
|
|
@ -195,7 +195,22 @@ exports.LoadUtils = () => {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options.mentionedJidList) {
|
if (options.mentionedJidList) {
|
||||||
options.mentionedJidList = options.mentionedJidList.map(cId => window.Store.Contact.get(cId).id);
|
options.mentionedJidList = await Promise.all(
|
||||||
|
options.mentionedJidList.map(async (id) => {
|
||||||
|
const wid = window.Store.WidFactory.createWid(id);
|
||||||
|
if (await window.Store.QueryExist(wid)) {
|
||||||
|
return wid;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
);
|
||||||
|
options.mentionedJidList = options.mentionedJidList.filter(Boolean);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (options.groupMentions) {
|
||||||
|
options.groupMentions = options.groupMentions.map((e) => ({
|
||||||
|
groupSubject: e.subject,
|
||||||
|
groupJid: window.Store.WidFactory.createWid(e.id)
|
||||||
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
let locationOptions = {};
|
let locationOptions = {};
|
||||||
|
|
@ -368,7 +383,22 @@ exports.LoadUtils = () => {
|
||||||
delete options.extraOptions;
|
delete options.extraOptions;
|
||||||
|
|
||||||
if (options.mentionedJidList) {
|
if (options.mentionedJidList) {
|
||||||
options.mentionedJidList = options.mentionedJidList.map(cId => window.Store.Contact.get(cId).id);
|
options.mentionedJidList = await Promise.all(
|
||||||
|
options.mentionedJidList.map(async (id) => {
|
||||||
|
const wid = window.Store.WidFactory.createWid(id);
|
||||||
|
if (await window.Store.QueryExist(wid)) {
|
||||||
|
return wid;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
);
|
||||||
|
options.mentionedJidList = options.mentionedJidList.filter(Boolean);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (options.groupMentions) {
|
||||||
|
options.groupMentions = options.groupMentions.map((e) => ({
|
||||||
|
groupSubject: e.subject,
|
||||||
|
groupJid: window.Store.WidFactory.createWid(e.id)
|
||||||
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options.linkPreview) {
|
if (options.linkPreview) {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue