Skip to content

Commit

Permalink
Merge branch 'master' of github.com:harish2704/whatsapp-web.js
Browse files Browse the repository at this point in the history
# By Pedro S. Lopez (3) and others
# Via GitHub
* 'master' of github.com:harish2704/whatsapp-web.js:
  Update lint.yml
  feat: acceptGroupV4Invite (pedroslopez#677)
  chore: update eslint and ecmaVersion (pedroslopez#680)
  chore: update lint action (pedroslopez#679)
  feat(dev): add argument bypassCSP to use in pupperter (pedroslopez#635)
  add searchMessages method (pedroslopez#586)
  feat: Add from which device the message was sent (pedroslopez#648)
  feat: disable / enable WA Web features (pedroslopez#543)
  feat: Get Orders and Products (pedroslopez#612)
  add extra option to MessageSendOptions (pedroslopez#600)
  feat: openChatWindow can open new chats (pedroslopez#592)
  Add sendVideoAsGif option (pedroslopez#578)
  Add support for sticker Name and author (pedroslopez#527)

# Conflicts:
#	package.json
  • Loading branch information
harish2704 committed Jun 9, 2021
2 parents 6b8db9f + ebba1b9 commit cfd7771
Show file tree
Hide file tree
Showing 16 changed files with 541 additions and 34 deletions.
3 changes: 2 additions & 1 deletion .eslintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,9 @@
"SharedArrayBuffer": "readonly"
},
"parserOptions": {
"ecmaVersion": 2018
"ecmaVersion": 2020
},
"ignorePatterns": ["docs"],
"rules": {
"indent": [
"error",
Expand Down
20 changes: 8 additions & 12 deletions .github/workflows/lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,15 @@ on:

jobs:
eslint:
name: eslint
name: ESLint
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- name: install node v12
uses: actions/setup-node@v1
- uses: actions/checkout@v2
- name: Install node v14
uses: actions/setup-node@v2
with:
node-version: 12
- name: npm install
node-version: '14'
- name: Install dependencies
run: npm install
- name: eslint
uses: icrawl/action-eslint@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
job-name: eslint
- name: Run ESLint
run: ./node_modules/.bin/eslint .
2 changes: 1 addition & 1 deletion example.js
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,7 @@ client.on('message', async msg => {
const chat = await msg.getChat();
// stops typing or recording in the chat
chat.clearState();
} else if (msg.body === 'jumpto') {
} else if (msg.body === '!jumpto') {
if (msg.hasQuotedMsg) {
const quotedMsg = await msg.getQuotedMessage();
client.interface.openChatWindowAt(quotedMsg.id._serialized);
Expand Down
130 changes: 128 additions & 2 deletions index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ declare namespace WAWebJS {
/**Accepts an invitation to join a group */
acceptInvite(inviteCode: string): Promise<string>

/** Accepts a private invitation to join a group (v4 invite) */
acceptGroupV4Invite: (inviteV4: InviteV4Data) => Promise<{status: number}>

/**Returns an object with information about the invite code's group */
getInviteInfo(inviteCode: string): Promise<object>

Expand Down Expand Up @@ -99,6 +102,9 @@ declare namespace WAWebJS {
/** Send a message to a specific chatId */
sendMessage(chatId: string, content: MessageContent, options?: MessageSendOptions): Promise<Message>

/** Searches for messages */
searchMessages(query: string, options?: { chatId?: string, page?: number, limit?: number }): Promise<Message[]>

/** Marks the client as online */
sendPresenceAvailable(): Promise<void>

Expand Down Expand Up @@ -413,7 +419,10 @@ declare namespace WAWebJS {
CONTACT_CARD = 'vcard',
CONTACT_CARD_MULTI = 'multi_vcard',
REVOKED = 'revoked',
ORDER = 'order',
PRODUCT = 'product',
UNKNOWN = 'unknown',
GROUP_INVITE = 'groups_v4_invite',
}

/** Client status */
Expand Down Expand Up @@ -448,6 +457,15 @@ declare namespace WAWebJS {
readRemaining: number
}

export type InviteV4Data = {
inviteCode: string,
inviteCodeExp: number,
groupId: string,
groupName?: string,
fromId: string,
toId: string
}

/**
* Represents a Message on WhatsApp
*
Expand Down Expand Up @@ -505,6 +523,8 @@ declare namespace WAWebJS {
location: Location,
/** List of vCards contained in the message */
vCards: string[],
/** Invite v4 info */
inviteV4?: InviteV4Data,
/** MediaKey that represents the sticker 'ID' */
mediaKey?: string,
/** Indicates the mentions in the message body. */
Expand All @@ -521,7 +541,18 @@ declare namespace WAWebJS {
type: MessageTypes,
/** Links included in the message. */
links: string[],

/** Order ID */
orderId: string,
/** title */
title?: string,
/** description*/
description?: string,
/** Business Owner JID */
businessOwnerJid?: string,
/** Product JID */
productId?: string,
/** Accept the Group V4 Invite in message */
acceptGroupV4Invite: () => Promise<{status: number}>,
/** Deletes the message from the chat */
delete: (everyone?: boolean) => Promise<void>,
/** Downloads and returns the attatched message media */
Expand Down Expand Up @@ -549,7 +580,11 @@ declare namespace WAWebJS {
/** Unstar this message */
unstar: () => Promise<void>,
/** Get information about message delivery statuso */
getInfo: () => Promise<MessageInfo | null>
getInfo: () => Promise<MessageInfo | null>,
/**
* Gets the order associated with a given message
*/
getOrder: () => Order,
}

/** ID that represents a message */
Expand Down Expand Up @@ -584,6 +619,8 @@ declare namespace WAWebJS {
linkPreview?: boolean
/** Send audio as voice message */
sendAudioAsVoice?: boolean
/** Send video as gif */
sendVideoAsGif?: boolean
/** Send media as sticker */
sendMediaAsSticker?: boolean
/** Send media as document */
Expand All @@ -600,6 +637,14 @@ declare namespace WAWebJS {
sendSeen?: boolean
/** Media to be sent */
media?: MessageMedia
/** Extra options */
extra?: any
/** Sticker name, if sendMediaAsSticker is true */
stickerName?: string
/** Sticker author, if sendMediaAsSticker is true */
stickerAuthor?: string
/** Sticker categories, if sendMediaAsSticker is true */
stickerCategories?: string[]
}

/** Media attached to a message */
Expand Down Expand Up @@ -907,6 +952,87 @@ declare namespace WAWebJS {
/** Makes the bot leave the group */
leave: () => Promise<void>;
}

/**
* Represents the metadata associated with a given product
*
*/
export interface ProductMetadata {
/** Product Id */
id: string,
/** Product Name */
name: string,
/** Product Description */
description: string,
/** Retailer ID */
retailer_id?: string
}

/**
* Represents a Product on Whatsapp
* @example
* {
* "id": "123456789",
* "price": "150000",
* "thumbnailId": "123456789",
* "thumbnailUrl": "https://mmg.whatsapp.net",
* "currency": "GTQ",
* "name": "Store Name",
* "quantity": 1
* }
*/
export interface Product {
/** Product Id */
id: string,
/** Price */
price?: string,
/** Product Thumbnail*/
thumbnailUrl: string,
/** Currency */
currency: string,
/** Product Name */
name: string,
/** Product Quantity*/
quantity: number,
/** Gets the Product metadata */
getData: () => Promise<ProductMetadata>
}

/**
* Represents a Order on WhatsApp
*
* @example
* {
* "products": [
* {
* "id": "123456789",
* "price": "150000",
* "thumbnailId": "123456789",
* "thumbnailUrl": "https://mmg.whatsapp.net",
* "currency": "GTQ",
* "name": "Store Name",
* "quantity": 1
* }
* ],
* "subtotal": "150000",
* "total": "150000",
* "currency": "GTQ",
* "createdAt": 1610136796,
* "sellerJid": "55555555@s.whatsapp.net"
* }
*/
export interface Order {
/** List of products*/
products: Array<Product>,
/** Order Subtotal */
subtotal: string,
/** Order Total */
total: string,
/** Order Currency */
currency: string,
/** Order Created At*/
createdAt: number;
}
}

export = WAWebJS
2 changes: 1 addition & 1 deletion index.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,6 @@ module.exports = {
BusinessContact: require('./src/structures/BusinessContact'),
ClientInfo: require('./src/structures/ClientInfo'),
Location: require('./src/structures/Location'),

ProductMetadata: require('./src/structures/ProductMetadata'),
...Constants
};
6 changes: 4 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,12 @@
"fluent-ffmpeg": "^2.1.2",
"jsqr": "^1.3.1",
"mime": "^2.4.5",
"puppeteer": "*"
"node-webpmux": "^2.0.0",
"puppeteer": "*",
"sharp": "^0.26.3"
},
"devDependencies": {
"eslint": "^6.8.0",
"eslint": "^7.27.0",
"jsdoc": "^3.6.4",
"jsdoc-baseline": "^0.1.5"
}
Expand Down
52 changes: 50 additions & 2 deletions src/Client.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ const { ClientInfo, Message, MessageMedia, Contact, Location, GroupNotification
* @param {number} options.takeoverTimeoutMs - How much time to wait before taking over the session
* @param {string} options.userAgent - User agent to use in puppeteer
* @param {string} options.ffmpegPath - Ffmpeg path to use when formating videos to webp while sending stickers
* @param {boolean} options.bypassCSP - Sets bypassing of page's Content-Security-Policy.
*
* @fires Client#qr
* @fires Client#authenticated
Expand Down Expand Up @@ -82,6 +83,10 @@ class Client extends EventEmitter {
}, this.options.session);
}

if(this.options.bypassCSP) {
await page.setBypassCSP(true);
}

await page.goto(WhatsWebURL, {
waitUntil: 'load',
timeout: 0,
Expand Down Expand Up @@ -430,13 +435,17 @@ class Client extends EventEmitter {
* @typedef {Object} MessageSendOptions
* @property {boolean} [linkPreview=true] - Show links preview
* @property {boolean} [sendAudioAsVoice=false] - Send audio as voice message
* @property {boolean} [sendVideoAsGif=false] - Send video as gif
* @property {boolean} [sendMediaAsSticker=false] - Send media as a sticker
* @property {boolean} [sendMediaAsDocument=false] - Send media as a document
* @property {boolean} [parseVCards=true] - Automatically parse vCards and send them as contacts
* @property {string} [caption] - Image or video caption
* @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 {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} [stickerName=undefined] - Sets the name of the sticker, (if sendMediaAsSticker is true).
* @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
*/

Expand All @@ -452,12 +461,14 @@ class Client extends EventEmitter {
let internalOptions = {
linkPreview: options.linkPreview === false ? undefined : true,
sendAudioAsVoice: options.sendAudioAsVoice,
sendVideoAsGif: options.sendVideoAsGif,
sendMediaAsSticker: options.sendMediaAsSticker,
sendMediaAsDocument: options.sendMediaAsDocument,
caption: options.caption,
quotedMessageId: options.quotedMessageId,
parseVCards: options.parseVCards === false ? false : true,
mentionedJidList: Array.isArray(options.mentions) ? options.mentions.map(contact => contact.id._serialized) : []
mentionedJidList: Array.isArray(options.mentions) ? options.mentions.map(contact => contact.id._serialized) : [],
...options.extra
};

const sendSeen = typeof options.sendSeen === 'undefined' ? true : options.sendSeen;
Expand All @@ -481,7 +492,12 @@ class Client extends EventEmitter {
}

if (internalOptions.sendMediaAsSticker && internalOptions.attachment) {
internalOptions.attachment = await Util.formatToWebpSticker(internalOptions.attachment);
internalOptions.attachment =
await Util.formatToWebpSticker(internalOptions.attachment, {
name: options.stickerName,
author: options.stickerAuthor,
categories: options.stickerCategories
});
}

const newMessage = await this.pupPage.evaluate(async (chatId, message, options, sendSeen) => {
Expand All @@ -499,6 +515,24 @@ class Client extends EventEmitter {
return new Message(this, newMessage);
}

/**
* Searches for messages
* @param {string} query
* @param {Object} [options]
* @param {number} [options.page]
* @param {number} [options.limit]
* @param {string} [options.chatId]
* @returns {Promise<Message[]>}
*/
async searchMessages(query, options = {}) {
const messages = await this.pupPage.evaluate(async (query, page, count, remote) => {
const { messages } = await window.Store.Msg.search(query, page, count, remote);
return messages.map(msg => window.WWebJS.getMessageModel(msg));
}, query, options.page, options.limit, options.chatId);

return messages.map(msg => new Message(this, msg));
}

/**
* Get all current chat instances
* @returns {Promise<Array<Chat>>}
Expand Down Expand Up @@ -573,6 +607,20 @@ class Client extends EventEmitter {
return chatId._serialized;
}

/**
* Accepts a private invitation to join a group
* @param {object} inviteV4 Invite V4 Info
* @returns {Promise<Object>}
*/
async acceptGroupV4Invite(inviteInfo) {
if(!inviteInfo.inviteCode) throw 'Invalid invite code, try passing the message.inviteV4 object';
if (inviteInfo.inviteCodeExp == 0) throw 'Expired invite code';
return await this.pupPage.evaluate(async inviteInfo => {
let { groupId, fromId, inviteCode, inviteCodeExp, toId } = inviteInfo;
return await window.Store.Wap.acceptGroupV4Invite(groupId, fromId, inviteCode, String(inviteCodeExp), toId);
}, inviteInfo);
}

/**
* Sets the current user's status message
* @param {string} status New status message
Expand Down
Loading

0 comments on commit cfd7771

Please sign in to comment.