whatsapp-web.js 1.13.2 → 1.15.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/.env.example ADDED
@@ -0,0 +1,2 @@
1
+ WWEBJS_TEST_SESSION_PATH=test_session.json
2
+ WWEBJS_TEST_REMOTE_ID=XXXXXXXXXX@c.us
package/README.md CHANGED
@@ -1,4 +1,4 @@
1
- [![npm](https://img.shields.io/npm/v/whatsapp-web.js.svg)](https://www.npmjs.com/package/whatsapp-web.js) [![Depfu](https://badges.depfu.com/badges/4a65a0de96ece65fdf39e294e0c8dcba/overview.svg)](https://depfu.com/github/pedroslopez/whatsapp-web.js?project_id=9765) ![WhatsApp_Web 2.2126.10](https://img.shields.io/badge/WhatsApp_Web-2.2126.10-brightgreen.svg) [![Discord Chat](https://img.shields.io/discord/698610475432411196.svg?logo=discord)](https://discord.gg/H7DqQs4)
1
+ [![npm](https://img.shields.io/npm/v/whatsapp-web.js.svg)](https://www.npmjs.com/package/whatsapp-web.js) [![Depfu](https://badges.depfu.com/badges/4a65a0de96ece65fdf39e294e0c8dcba/overview.svg)](https://depfu.com/github/pedroslopez/whatsapp-web.js?project_id=9765) ![WhatsApp_Web 2.2142.12](https://img.shields.io/badge/WhatsApp_Web-2.2142.12-brightgreen.svg) [![Discord Chat](https://img.shields.io/discord/698610475432411196.svg?logo=discord)](https://discord.gg/H7DqQs4)
2
2
 
3
3
  # whatsapp-web.js
4
4
  A WhatsApp API client that connects through the WhatsApp Web browser app
@@ -11,12 +11,13 @@ It uses Puppeteer to run a real instance of Whatsapp Web to avoid getting blocke
11
11
 
12
12
  The module is now available on npm! `npm i whatsapp-web.js`
13
13
 
14
- Please note that Node v14+ is required.
14
+ Please note that Node v12+ is required.
15
15
 
16
16
  ## Example usage
17
17
 
18
18
  ```js
19
19
  const { Client } = require('whatsapp-web.js');
20
+
20
21
  const client = new Client();
21
22
 
22
23
  client.on('qr', (qr) => {
@@ -39,6 +40,39 @@ client.initialize();
39
40
 
40
41
  Take a look at [example.js](https://github.com/pedroslopez/whatsapp-web.js/blob/master/example.js) for another example with more use cases.
41
42
 
43
+ ## Remote Access
44
+
45
+ You could also connect to any previously existing browser instance:
46
+
47
+ ```js
48
+ const client = new Client({
49
+ puppeteer: {
50
+ browserWSEndpoint: `ws://localhost:3000`
51
+ }
52
+ });
53
+ ```
54
+
55
+ ### Docker
56
+
57
+ 1) Installing a browser using browserless:
58
+
59
+ ```
60
+ docker run \
61
+ --rm \
62
+ -p 3000:3000 \
63
+ -e "MAX_CONCURRENT_SESSIONS=1" \
64
+ browserless/chrome:latest
65
+ ```
66
+
67
+ Reference: https://docs.browserless.io/docs/docker-quickstart.html
68
+
69
+ ### Remote Debugging
70
+
71
+ 2) Running a browser with websocket remote debugging enabled:
72
+ > chrome.exe --remote-debugging-port=9222
73
+
74
+ After that check the following webpage and check http://127.0.0.1:9220/json and get the **webSocketDebuggerUrl**
75
+
42
76
  ## Supported features
43
77
 
44
78
  | Feature | Status |
@@ -46,11 +80,13 @@ Take a look at [example.js](https://github.com/pedroslopez/whatsapp-web.js/blob/
46
80
  | Send messages | ✅ |
47
81
  | Receive messages | ✅ |
48
82
  | Send media (images/audio/documents) | ✅ |
49
- | Send media (video) | ✅ [(requires google chrome)](https://waguide.pedroslopez.me/features/handling-attachments#caveat-for-sending-videos-and-gifs) |
83
+ | Send media (video) | ✅ [(requires google chrome)](https://guide.wwebjs.dev/features/handling-attachments#caveat-for-sending-videos-and-gifs) |
50
84
  | Send stickers | ✅ |
51
85
  | Receive media (images/audio/video/documents) | ✅ |
52
86
  | Send contact cards | ✅ |
53
87
  | Send location | ✅ |
88
+ | Send buttons | ✅ |
89
+ | Send lists | ✅ (business accounts not supported) |
54
90
  | Receive location | ✅ |
55
91
  | Message replies | ✅ |
56
92
  | Join groups by invite | ✅ |
@@ -71,9 +107,10 @@ Something missing? Make an issue and let us know!
71
107
 
72
108
  ## Links
73
109
 
74
- * [Reference](https://pedroslopez.me/whatsapp-web.js)
75
- * [Guide](https://waguide.pedroslopez.me/) _(work in progress)_
110
+ * [Reference](https://docs.wwebjs.dev/)
111
+ * [Guide](https://guide.wwebjs.dev/) _(work in progress)_
76
112
  * [GitHub](https://github.com/pedroslopez/whatsapp-web.js)
113
+ * [npm](https://npmjs.org/package/whatsapp-web.js)
77
114
 
78
115
  ## Contributing
79
116
 
package/example.js CHANGED
@@ -1,5 +1,5 @@
1
1
  const fs = require('fs');
2
- const { Client, Location } = require('./index');
2
+ const { Client, Location, List, Buttons } = require('./index');
3
3
 
4
4
  const SESSION_FILE_PATH = './session.json';
5
5
  let sessionCfg;
@@ -11,6 +11,13 @@ const client = new Client({ puppeteer: { headless: false }, session: sessionCfg
11
11
  // You can use an existing session and avoid scanning a QR code by adding a "session" object to the client options.
12
12
  // This object must include WABrowserId, WASecretBundle, WAToken1 and WAToken2.
13
13
 
14
+ // You also could connect to an existing instance of a browser
15
+ // {
16
+ // puppeteer: {
17
+ // browserWSEndpoint: `ws://localhost:3000`
18
+ // }
19
+ // }
20
+
14
21
  client.initialize();
15
22
 
16
23
  client.on('qr', (qr) => {
@@ -197,6 +204,13 @@ client.on('message', async msg => {
197
204
  const quotedMsg = await msg.getQuotedMessage();
198
205
  client.interface.openChatWindowAt(quotedMsg.id._serialized);
199
206
  }
207
+ } else if (msg.body === '!buttons') {
208
+ let button = new Buttons('Button body',[{body:'bt1'},{body:'bt2'},{body:'bt3'}],'title','footer');
209
+ client.sendMessage(msg.from, button);
210
+ } else if (msg.body === '!list') {
211
+ let sections = [{title:'sectionTitle',rows:[{title:'ListItem1', description: 'desc'},{title:'ListItem2'}]}];
212
+ let list = new List('List body','btnText',sections,'Title','footer');
213
+ client.sendMessage(msg.from, list);
200
214
  }
201
215
  });
202
216
 
package/index.d.ts CHANGED
@@ -1,5 +1,6 @@
1
1
 
2
2
  import { EventEmitter } from 'events'
3
+ import { RequestInit } from 'node-fetch'
3
4
  import puppeteer = require('puppeteer')
4
5
 
5
6
  declare namespace WAWebJS {
@@ -47,6 +48,9 @@ declare namespace WAWebJS {
47
48
  /** Logs out the client, closing the current session */
48
49
  logout(): Promise<void>
49
50
 
51
+ /** Get all blocked contacts by host account */
52
+ getBlockedContacts(): Promise<Contact[]>
53
+
50
54
  /** Get chat instance by ID */
51
55
  getChatById(chatId: string): Promise<Chat>
52
56
 
@@ -58,6 +62,12 @@ declare namespace WAWebJS {
58
62
 
59
63
  /** Get all current contact instances */
60
64
  getContacts(): Promise<Contact[]>
65
+
66
+ /** Get the country code of a WhatsApp ID. (154185968@c.us) => (1) */
67
+ getCountryCode(number: string): Promise<string>
68
+
69
+ /** Get the formatted number of a WhatsApp ID. (12345678901@c.us) => (+1 (234) 5678-901) */
70
+ getFormattedNumber(number: string): Promise<string>
61
71
 
62
72
  /** Get all current Labels */
63
73
  getLabels(): Promise<Label[]>
@@ -90,11 +100,11 @@ declare namespace WAWebJS {
90
100
  getNumberId(number: string): Promise<ContactId | null>
91
101
 
92
102
  /**
93
- * Mutes the Chat until a specified date
103
+ * Mutes this chat forever, unless a date is specified
94
104
  * @param chatId ID of the chat that will be muted
95
- * @param unmuteDate Date when the chat will be unmuted
105
+ * @param unmuteDate Date when the chat will be unmuted, leave as is to mute forever
96
106
  */
97
- muteChat(chatId: string, unmuteDate: Date): Promise<void>
107
+ muteChat(chatId: string, unmuteDate?: Date): Promise<void>
98
108
 
99
109
  /** Force reset of connection state for the client */
100
110
  resetState(): Promise<void>
@@ -227,6 +237,12 @@ declare namespace WAWebJS {
227
237
  qr: string
228
238
  ) => void): this
229
239
 
240
+ /** Emitted when a call is received */
241
+ on(event: 'call', listener: (
242
+ /** The call that started */
243
+ call: Call
244
+ ) => void): this
245
+
230
246
  /** Emitted when the client has initialized and is ready to receive messages */
231
247
  on(event: 'ready', listener: () => void): this
232
248
  }
@@ -271,13 +287,16 @@ declare namespace WAWebJS {
271
287
  * @default 45000 */
272
288
  authTimeoutMs?: number,
273
289
  /** Puppeteer launch options. View docs here: https://github.com/puppeteer/puppeteer/ */
274
- puppeteer?: puppeteer.LaunchOptions
290
+ puppeteer?: puppeteer.LaunchOptions & puppeteer.BrowserLaunchArgumentOptions & puppeteer.BrowserConnectOptions
275
291
  /** Refresh interval for qr code (how much time to wait before checking if the qr code has changed)
276
292
  * @default 20000 */
277
293
  qrRefreshIntervalMs?: number
278
294
  /** Timeout for qr code selector in puppeteer
279
295
  * @default 45000 */
280
296
  qrTimeoutMs?: number,
297
+ /** How many times should the qrcode be refreshed before giving up
298
+ * @default 0 (disabled) */
299
+ qrMaxRetries?: number,
281
300
  /** Restart client with a new session (i.e. use null 'session' var) if authentication fails
282
301
  * @default false */
283
302
  restartOnAuthFail?: boolean
@@ -349,7 +368,7 @@ declare namespace WAWebJS {
349
368
  reply: (content: MessageContent, options?: MessageSendOptions) => Promise<Message>,
350
369
 
351
370
  }
352
-
371
+
353
372
  /** whatsapp web url */
354
373
  export const WhatsWebURL: string
355
374
 
@@ -421,6 +440,7 @@ declare namespace WAWebJS {
421
440
  REVOKED = 'revoked',
422
441
  ORDER = 'order',
423
442
  PRODUCT = 'product',
443
+ PAYMENT = 'payment',
424
444
  UNKNOWN = 'unknown',
425
445
  GROUP_INVITE = 'groups_v4_invite',
426
446
  }
@@ -517,6 +537,11 @@ declare namespace WAWebJS {
517
537
  id: MessageId,
518
538
  /** Indicates if the message was forwarded */
519
539
  isForwarded: boolean,
540
+ /**
541
+ * Indicates how many times the message was forwarded.
542
+ * The maximum value is 127.
543
+ */
544
+ forwardingScore: number,
520
545
  /** Indicates if the message was starred */
521
546
  isStarred: boolean,
522
547
  /** Location information contained in the message, if the message is type "location" */
@@ -540,7 +565,10 @@ declare namespace WAWebJS {
540
565
  /** Message type */
541
566
  type: MessageTypes,
542
567
  /** Links included in the message. */
543
- links: string[],
568
+ links: Array<{
569
+ link: string,
570
+ isSuspicious: boolean
571
+ }>,
544
572
  /** Order ID */
545
573
  orderId: string,
546
574
  /** title */
@@ -551,6 +579,12 @@ declare namespace WAWebJS {
551
579
  businessOwnerJid?: string,
552
580
  /** Product JID */
553
581
  productId?: string,
582
+ /** Message buttons */
583
+ dynamicReplyButtons?: object,
584
+ /** Selected button ID */
585
+ selectedButtonId?: string,
586
+ /** Selected list row ID */
587
+ selectedRowId?: string,
554
588
  /** Accept the Group V4 Invite in message */
555
589
  acceptGroupV4Invite: () => Promise<{status: number}>,
556
590
  /** Deletes the message from the chat */
@@ -585,6 +619,10 @@ declare namespace WAWebJS {
585
619
  * Gets the order associated with a given message
586
620
  */
587
621
  getOrder: () => Order,
622
+ /**
623
+ * Gets the payment details associated with a given message
624
+ */
625
+ getPayment: () => Payment,
588
626
  }
589
627
 
590
628
  /** ID that represents a message */
@@ -595,10 +633,13 @@ declare namespace WAWebJS {
595
633
  _serialized: string,
596
634
  }
597
635
 
598
- export interface Location {
599
- description?: string | null,
600
- latitude: string,
601
- longitude: string,
636
+ /** Location information */
637
+ export class Location {
638
+ description?: string | null
639
+ latitude: string
640
+ longitude: string
641
+
642
+ constructor(latitude: number, longitude: number, description?: string)
602
643
  }
603
644
 
604
645
  export interface Label {
@@ -647,6 +688,12 @@ declare namespace WAWebJS {
647
688
  stickerCategories?: string[]
648
689
  }
649
690
 
691
+ export interface MediaFromURLOptions {
692
+ client?: Client
693
+ unsafeMime?: boolean
694
+ reqOptions?: RequestInit
695
+ }
696
+
650
697
  /** Media attached to a message */
651
698
  export class MessageMedia {
652
699
  /** MIME type of the attachment */
@@ -665,9 +712,12 @@ declare namespace WAWebJS {
665
712
 
666
713
  /** Creates a MessageMedia instance from a local file path */
667
714
  static fromFilePath: (filePath: string) => MessageMedia
715
+
716
+ /** Creates a MessageMedia instance from a URL */
717
+ static fromUrl: (url: string, options?: MediaFromURLOptions) => Promise<MessageMedia>
668
718
  }
669
719
 
670
- export type MessageContent = string | MessageMedia | Location | Contact | Contact[]
720
+ export type MessageContent = string | MessageMedia | Location | Contact | Contact[] | List | Buttons
671
721
 
672
722
  /**
673
723
  * Represents a Contact on WhatsApp
@@ -745,9 +795,16 @@ declare namespace WAWebJS {
745
795
  * Will return null when getting chat for currently logged in user.
746
796
  */
747
797
  getChat: () => Promise<Chat>,
748
-
798
+
799
+ /** Returns the contact's countrycode, (1541859685@c.us) => (1) */
800
+ getCountryCode(): Promise<string>,
801
+
802
+ /** Returns the contact's formatted phone number, (12345678901@c.us) => (+1 (234) 5678-901) */
803
+ getFormattedNumber(): Promise<string>,
804
+
749
805
  /** Blocks this contact from WhatsApp */
750
806
  block: () => Promise<boolean>,
807
+
751
808
  /** Unlocks this contact from WhatsApp */
752
809
  unblock: () => Promise<boolean>,
753
810
 
@@ -826,8 +883,8 @@ declare namespace WAWebJS {
826
883
  delete: () => Promise<boolean>,
827
884
  /** Loads chat messages, sorted from earliest to latest. */
828
885
  fetchMessages: (searchOptions: MessageSearchOptions) => Promise<Message[]>,
829
- /** Mutes this chat until a specified date */
830
- mute: (unmuteDate: Date) => Promise<void>,
886
+ /** Mutes this chat forever, unless a date is specified */
887
+ mute: (unmuteDate?: Date) => Promise<void>,
831
888
  /** Send a message to this chat */
832
889
  sendMessage: (content: MessageContent, options?: MessageSendOptions) => Promise<Message>,
833
890
  /** Set the message as seen */
@@ -1033,6 +1090,111 @@ declare namespace WAWebJS {
1033
1090
  /** Order Created At*/
1034
1091
  createdAt: number;
1035
1092
  }
1093
+
1094
+ /**
1095
+ * Represents a Payment on WhatsApp
1096
+ *
1097
+ * @example
1098
+ * {
1099
+ * id: {
1100
+ * fromMe: true,
1101
+ * remote: {
1102
+ * server: 'c.us',
1103
+ * user: '5511999999999',
1104
+ * _serialized: '5511999999999@c.us'
1105
+ * },
1106
+ * id: 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA',
1107
+ * _serialized: 'true_5511999999999@c.us_AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'
1108
+ * },
1109
+ * paymentCurrency: 'BRL',
1110
+ * paymentAmount1000: 1000,
1111
+ * paymentMessageReceiverJid: {
1112
+ * server: 'c.us',
1113
+ * user: '5511999999999',
1114
+ * _serialized: '5511999999999@c.us'
1115
+ * },
1116
+ * paymentTransactionTimestamp: 1623463058,
1117
+ * paymentStatus: 4,
1118
+ * paymentTxnStatus: 4,
1119
+ * paymentNote: 'note'
1120
+ * }
1121
+ */
1122
+ export interface Payment {
1123
+ /** Payment Id*/
1124
+ id: object,
1125
+ /** Payment currency */
1126
+ paymentCurrency: string,
1127
+ /** Payment ammount */
1128
+ paymentAmount1000 : number,
1129
+ /** Payment receiver */
1130
+ paymentMessageReceiverJid : object,
1131
+ /** Payment transaction timestamp */
1132
+ paymentTransactionTimestamp : number,
1133
+ /** Payment paymentStatus */
1134
+ paymentStatus : number,
1135
+ /** Integer that represents the payment Text */
1136
+ paymentTxnStatus : number,
1137
+ /** The note sent with the payment */
1138
+ paymentNote : string;
1139
+ }
1140
+
1141
+ /**
1142
+ * Represents a Call on WhatsApp
1143
+ *
1144
+ * @example
1145
+ * Call {
1146
+ * id: 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA',
1147
+ * from: '5511999999@c.us',
1148
+ * timestamp: 1625003709,
1149
+ * isVideo: false,
1150
+ * isGroup: false,
1151
+ * fromMe: false,
1152
+ * canHandleLocally: false,
1153
+ * webClientShouldHandle: false,
1154
+ * participants: []
1155
+ * }
1156
+ */
1157
+ export interface Call {
1158
+ /** Call Id */
1159
+ id: string,
1160
+ /** from */
1161
+ from?: string,
1162
+ /** Unix timestamp for when the call was created*/
1163
+ timestamp: number,
1164
+ /** Is video */
1165
+ isVideo: boolean,
1166
+ /** Is Group */
1167
+ isGroup: boolean,
1168
+ /** Indicates if the call was sent by the current user */
1169
+ fromMe: boolean,
1170
+ /** indicates if the call can be handled in waweb */
1171
+ canHandleLocally: boolean,
1172
+ /** indicates if the call should be handled in waweb */
1173
+ webClientShouldHandle: boolean,
1174
+ /** Object with participants */
1175
+ participants: object
1176
+ }
1177
+
1178
+ /** Message type List */
1179
+ export class List {
1180
+ body: string
1181
+ buttonText: string
1182
+ sections: Array<any>
1183
+ title?: string | null
1184
+ footer?: string | null
1185
+
1186
+ constructor(body: string, buttonText: string, sections: Array<any>, title?: string | null, footer?: string | null)
1187
+ }
1188
+
1189
+ /** Message type buttons */
1190
+ export class Buttons {
1191
+ body: string | MessageMedia
1192
+ buttons: Array<Array<string>>
1193
+ title?: string | null
1194
+ footer?: string | null
1195
+
1196
+ constructor(body: string, buttons: Array<Array<string>>, title?: string | null, footer?: string | null)
1197
+ }
1036
1198
  }
1037
1199
 
1038
1200
  export = WAWebJS
package/index.js CHANGED
@@ -19,5 +19,7 @@ module.exports = {
19
19
  ClientInfo: require('./src/structures/ClientInfo'),
20
20
  Location: require('./src/structures/Location'),
21
21
  ProductMetadata: require('./src/structures/ProductMetadata'),
22
+ List: require('./src/structures/List'),
23
+ Buttons: require('./src/structures/Buttons'),
22
24
  ...Constants
23
25
  };
package/package.json CHANGED
@@ -1,11 +1,11 @@
1
1
  {
2
2
  "name": "whatsapp-web.js",
3
- "version": "1.13.2",
3
+ "version": "1.15.1",
4
4
  "description": "Library for interacting with the WhatsApp Web API ",
5
5
  "main": "./index.js",
6
6
  "typings": "./index.d.ts",
7
7
  "scripts": {
8
- "test": "echo \"Error: no test specified\" && exit 1",
8
+ "test": "mocha tests",
9
9
  "shell": "node --experimental-repl-await ./shell.js",
10
10
  "generate-docs": "node_modules/.bin/jsdoc --configure .jsdoc.json --verbose"
11
11
  },
@@ -26,19 +26,28 @@
26
26
  "bugs": {
27
27
  "url": "https://github.com/pedroslopez/whatsapp-web.js/issues"
28
28
  },
29
- "homepage": "https://waguide.pedroslopez.me/",
29
+ "homepage": "https://guide.wwebjs.dev/",
30
30
  "dependencies": {
31
- "@pedroslopez/moduleraid": "^5.0.1",
31
+ "@pedroslopez/moduleraid": "^5.0.2",
32
32
  "fluent-ffmpeg": "^2.1.2",
33
33
  "jsqr": "^1.3.1",
34
34
  "mime": "^2.4.5",
35
- "node-webpmux": "^2.0.0",
36
- "puppeteer": "^5.2.1",
37
- "sharp": "^0.26.3"
35
+ "node-webpmux": "^3.1.0",
36
+ "puppeteer": "^10.1.0",
37
+ "sharp": "^0.28.3"
38
38
  },
39
39
  "devDependencies": {
40
+ "@types/node-fetch": "^2.5.11",
41
+ "chai": "^4.3.4",
42
+ "dotenv": "^10.0.0",
40
43
  "eslint": "^7.27.0",
44
+ "eslint-plugin-mocha": "^9.0.0",
41
45
  "jsdoc": "^3.6.4",
42
- "jsdoc-baseline": "^0.1.5"
46
+ "jsdoc-baseline": "^0.1.5",
47
+ "mocha": "^9.0.2",
48
+ "sinon": "^11.1.1"
49
+ },
50
+ "engines": {
51
+ "node": ">=12.0.0"
43
52
  }
44
53
  }