Compare commits

..

365 Commits

Author SHA1 Message Date
Pedro Lopez
7beeff4901 chore: mark version 1.14.1 2021-09-01 09:19:28 -04:00
Pedro Lopez
022c87f3c7 optionally patch _find function if it's not found 2021-09-01 09:18:34 -04:00
Pedro Lopez
e527fe74fd fix: patch find function to get chats 2021-09-01 09:16:12 -04:00
Pedro S. Lopez
7597608f9d Update README.md 2021-08-02 00:49:03 -04:00
Pedro Lopez
be018e651d update .npmignore 2021-08-02 00:07:52 -04:00
Pedro Lopez
64189d2d67 chore: mark version v1.14.0 2021-08-01 23:59:56 -04:00
Pedro Lopez
38e31a07cf Update package.json and readme for node 12 support 2021-08-01 23:57:21 -04:00
Pedro Lopez
40cec51956 fix: node v12 support 2021-08-01 23:56:27 -04:00
Pedro S. Lopez
d9ccb6f276 fix: correctly resolve media that hasn't been downloaded (#763)
* fix: correctly abort if media does not exist

* catch 404s

* dont throw for media that cant be fetched
2021-08-01 23:29:06 -04:00
github-actions[bot]
628b6e4d49 Update supported WhatsApp Web version to v2.2126.14 (#806)
Co-authored-by: pedroslopez <pedroslopez@users.noreply.github.com>
2021-08-01 23:13:07 -04:00
Pedro S. Lopez
8e56aef3ce fix: more stable latest version check (#805) 2021-08-01 23:04:02 -04:00
Wictor Nogueira
cd774bef17 feat: Add MessageMedia.fromUrl method (#769) 2021-07-31 16:36:11 +03:00
Pedro S. Lopez
9c2592e164 chore: temporarily stop update action from auto running 2021-07-20 14:51:58 -04:00
Pedro S. Lopez
ae6d61bda9 fix: correctly serialize messages with replyButtons 2021-07-19 22:23:06 -04:00
Pedro S. Lopez
98acd2312d delete gh branch automatically when closing update PR 2021-07-19 19:46:24 -04:00
Pedro Lopez
62c7c15f44 chore: update links 2021-07-19 00:19:40 -04:00
Pedro Lopez
e12c53f6ce chore: specify minimum required node version 2021-07-19 00:11:57 -04:00
Pedro S. Lopez
811008da4b Delete CNAME 2021-07-18 23:37:45 -04:00
Pedro S. Lopez
863284c9d1 Create CNAME 2021-07-18 23:37:21 -04:00
Pedro S. Lopez
ec95483518 Create CNAME 2021-07-18 23:36:02 -04:00
Pedro S. Lopez
ff2eb95751 Change WA Web update PR branch name 2021-07-18 22:57:18 -04:00
dependabot[bot]
1b5e9d2392 chore(deps-dev): bump mocha from 8.4.0 to 9.0.2 (#776)
Bumps [mocha](https://github.com/mochajs/mocha) from 8.4.0 to 9.0.2.
- [Release notes](https://github.com/mochajs/mocha/releases)
- [Changelog](https://github.com/mochajs/mocha/blob/master/CHANGELOG.md)
- [Commits](https://github.com/mochajs/mocha/compare/v8.4.0...v9.0.2)

---
updated-dependencies:
- dependency-name: mocha
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-07-18 22:55:06 -04:00
Pedro Lopez
340e9764fe Publish gh-pages site (branch name change) 2021-07-18 22:43:07 -04:00
Rajeh Taher
084525ddfa Add Operating System information for bug reports. (#725)
* 📄 Add Operating System information for bug reports.

* 🐛 Forgot Line Break
2021-07-17 22:04:44 -04:00
github-actions[bot]
3398501ee6 Update supported WhatsApp Web version to v2.2126.11 (#766)
Co-authored-by: pedroslopez <pedroslopez@users.noreply.github.com>
Co-authored-by: Pedro S. Lopez <pslamoros@hotmail.com>
2021-07-17 00:07:38 -04:00
tuyuribr
cdede835af Include Calls (#720)
* Get Call module

* The call event

* Update onCall index.d.ts
2021-07-17 00:05:53 -04:00
Pedro S. Lopez
449d0f01d8 Trim current version string 2021-07-16 03:19:58 -04:00
Pedro S. Lopez
4ed9312eb7 Update update.yml 2021-07-16 03:09:54 -04:00
Pedro S. Lopez
76deaad2fd Update update.yml 2021-07-16 03:05:18 -04:00
Pedro S. Lopez
284903dce4 Update README.md 2021-07-16 02:53:39 -04:00
Pedro S. Lopez
a03cc41d22 Add tests and detect WhatsApp Web updates (#686)
* test setup, add initializer tests

* test sending messages

* add script to check latest version

* add github action

* use env vars

* configure environment with .env file

* add test for sticker name and author

* add DownloadManager model

* test chats and contacts

* test for number utility functions

* throw error if no remote id has been set

* Update .version
2021-07-16 02:50:05 -04:00
ApeironTsuka
04d2308bbc Update node-webpmux 2.x syntax to 3.x (support upstream breaking change) (#762)
Co-authored-by: Apeiron <apeiron@none>
2021-07-15 22:50:54 -04:00
Pedro S. Lopez
dc9b7e5f3d Update minimum moduleRaid version to 5.0.2
close #741
2021-07-14 22:42:21 -04:00
dependabot[bot]
cc7a729223 chore(deps): bump puppeteer from 5.5.0 to 10.1.0 (#750)
Bumps [puppeteer](https://github.com/puppeteer/puppeteer) from 5.5.0 to 10.1.0.
- [Release notes](https://github.com/puppeteer/puppeteer/releases)
- [Changelog](https://github.com/puppeteer/puppeteer/blob/main/CHANGELOG.md)
- [Commits](https://github.com/puppeteer/puppeteer/compare/v5.5.0...v10.1.0)

---
updated-dependencies:
- dependency-name: puppeteer
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-07-14 18:39:24 -04:00
dependabot[bot]
2ec46f674a chore(deps): bump sharp from 0.26.3 to 0.28.3 (#751)
Bumps [sharp](https://github.com/lovell/sharp) from 0.26.3 to 0.28.3.
- [Release notes](https://github.com/lovell/sharp/releases)
- [Changelog](https://github.com/lovell/sharp/blob/master/docs/changelog.md)
- [Commits](https://github.com/lovell/sharp/compare/v0.26.3...v0.28.3)

---
updated-dependencies:
- dependency-name: sharp
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-07-14 18:35:59 -04:00
dependabot[bot]
22993fc23d chore(deps): bump node-webpmux from 2.0.3 to 3.0.0 (#749)
Bumps [node-webpmux](https://github.com/ApeironTsuka/node-webpmux) from 2.0.3 to 3.0.0.
- [Release notes](https://github.com/ApeironTsuka/node-webpmux/releases)
- [Commits](https://github.com/ApeironTsuka/node-webpmux/commits)

---
updated-dependencies:
- dependency-name: node-webpmux
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-07-14 18:33:36 -04:00
Edson Tégila
cd52075447 Add the option to use "browserWSEndpoint" (#727)
* Update Client.js

* Update package.json

* Update package.json

* 🚨🔥 Fixed ESLint and removed old code.

* Update README.md

* Update README.md

* Update Client.js

* chore(deps): bump sharp from 0.26.3 to 0.28.3

Bumps [sharp](https://github.com/lovell/sharp) from 0.26.3 to 0.28.3.
- [Release notes](https://github.com/lovell/sharp/releases)
- [Changelog](https://github.com/lovell/sharp/blob/master/docs/changelog.md)
- [Commits](https://github.com/lovell/sharp/compare/v0.26.3...v0.28.3)

---
updated-dependencies:
- dependency-name: sharp
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

* Update package.json

* Update README.md

* Update example.js

* Update README.md

Co-authored-by: Rajeh Taher <52720753+PurpShell@users.noreply.github.com>
Co-authored-by: Rajeh Taher <rajeh@reforward.tk>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Aliyss Snow <33941859+Aliyss@users.noreply.github.com>
2021-07-13 10:27:00 -07:00
Rajeh Taher
54a07fa22f feat: Add support to suspicious links (#642) 2021-07-12 11:03:11 -07:00
Pedro S. Lopez
1d49f74ab4 Update dependabot.yml 2021-07-11 21:29:58 -04:00
Pedro S. Lopez
ea4dfb17f3 Create dependabot.yml 2021-07-11 21:28:39 -04:00
stefanfuchs
efa6cf98d2 fix: location class type (#718) 2021-07-12 00:54:32 +00:00
Giancarlo Rocha
9d715735ed feat: message forwarding score (#716) 2021-07-11 20:52:54 -04:00
Pedro Lopez
4afff38713 Fix download media (v1.13.2) 2021-07-09 03:08:52 -04:00
Pedro Lopez
b13dea0339 chore: mark version v1.13.1 2021-07-09 02:39:13 -04:00
Pedro S. Lopez
0ef6061d7e Fix downloading media for WhatsApp Web v2.2126.10 (#735)
* fix downloadMedia

* return a boolean for hasMedia
2021-07-09 02:38:31 -04:00
Pedro Lopez
0465507009 chore: mark version v1.13.0 2021-07-09 01:22:08 -04:00
Pedro Lopez
2fd96e76b9 update readme to indicate node 14 is required 2021-07-09 01:18:09 -04:00
Pedro Lopez
caab11cfe4 bump minimum required moduleraid version 2021-07-09 01:14:07 -04:00
Pedro S. Lopez
ebba1b9ab9 Update lint.yml 2021-06-05 19:02:08 -04:00
JoseHM8A
cdc00e934d feat: acceptGroupV4Invite (#677)
* Added option client.acceptGroupV4Invite()

* Update Client.js

* Update index.d.ts

Added a description to the inviteV4 object

Renamed "invite" by "inviteV4"

* Update Client.js

* Update Message.js

renamed "invite" to "inviteV4"

* Update Client.js

* Added message.acceptGroupV4Invite method

* Update index.d.ts

acceptGroupV4Invite

* better typings, refactor some names

Co-authored-by: Pedro Lopez <pedroslopez@me.com>
2021-06-05 17:10:47 -04:00
Pedro S. Lopez
795570a697 chore: update eslint and ecmaVersion (#680) 2021-06-02 23:39:01 -04:00
Pedro S. Lopez
0465742ffb chore: update lint action (#679)
* update lint action

* fix script path

* ignore docs

* update names
2021-06-02 23:17:28 -04:00
Ricardo Araújo Paes
38976558f5 feat(dev): add argument bypassCSP to use in pupperter (#635) 2021-06-01 22:05:44 -04:00
Wictor Nogueira
b895437458 add searchMessages method (#586)
* add searchMessages method

* fix typing

* fix typing

* remove unused statement

Co-authored-by: Pedro S. Lopez <pslamoros@hotmail.com>
2021-06-01 21:54:27 -04:00
tuyuribr
0a061f982c feat: Add from which device the message was sent (#648)
* Add from which device the message was sent.

Use the message Id for fingerprint the device that was being use when the message was sent

* To single quotes

Co-authored-by: Pedro S. Lopez <pslamoros@hotmail.com>
2021-05-31 21:03:23 -04:00
Aliyss Snow
63d11d3f84 feat: disable / enable WA Web features (#543)
* Added Features and Enabling/Disabling of Features within WhatsappWeb

* remove feature commands from example

Co-authored-by: Pedro S. Lopez <pslamoros@hotmail.com>
Co-authored-by: Pedro Lopez <pedroslopez@me.com>
2021-05-31 20:58:55 -04:00
renjop
5177a257cf feat: Get Orders and Products (#612)
* - Get products and orders

* - Get products and orders

* - Eslint fixes

* - Eslint fixes

* allow downloading media for products

* products and orders work on normal accounts

Co-authored-by: Renato Jop <renato.jop@consystec-corp.com>
Co-authored-by: Pedro Lopez <pedroslopez@me.com>
Co-authored-by: Pedro S. Lopez <pslamoros@hotmail.com>
2021-05-31 20:46:43 -04:00
Wictor Nogueira
f506c171c1 add extra option to MessageSendOptions (#600)
Co-authored-by: Pedro S. Lopez <pslamoros@hotmail.com>
2021-05-31 19:24:30 -04:00
tuyuribr
64e2cc48fc feat: openChatWindow can open new chats (#592)
Open the chat window even if you never chatted with the chatId

Co-authored-by: Pedro S. Lopez <pslamoros@hotmail.com>
2021-05-31 19:21:57 -04:00
Wictor Nogueira
6c66ab2bef Add sendVideoAsGif option (#578)
* Add sendVideoAsGif option

* fix typo

Co-authored-by: Pedro S. Lopez <pslamoros@hotmail.com>
2021-05-31 19:18:10 -04:00
Rajeh Taher
efc7018f9a Add support for sticker Name and author (#527)
* Added Sticker author and sticker name support

This patch of Client.js includes support for sticker metadata

* Docs: stickerName and stickerAuthor in MessageOpts

* Hotfix_Sticker_Feature

fixes a bug

* Update global.html

* updated

* fixed comma

* Fixed duplicate code

* Fixing eslint

* Fixing eslint again

* eslint....

* fixing problem with eslint.

* move sticker exif data filling to Utils.formatToWebpSticker() function

* Update Client.js

* Added temporary stuff

* eslint

* Update Util.js

* eslint bad :D

* eslint

* polish work with files

* fix error and TODOs

* clean up code to match with repo code style

* update typescript params

* Update src/util/Util.js

camel Case

Co-authored-by: Pedro S. Lopez <pedroslopez@me.com>

* Update Util.js

*  webp-converter  node-webpmux

* Update Util.js

*  Use node-webpmux

*  node-webpmux  node-webpmux-commonjs

* ✏️ Fixed require mode

* :heavy_plus_sign:node-webpmux  node-webpmux-commonjs

* ⬆️ Node-webpmux update changes

* 🚨 removing try/catch

* 🚨 complier warnings

* 🧐 stupid mistakes

* ⬆️ Upgrade required version

* 🐛 creating a buffer the right way

* 🐛 linting and simplification

* 🐛 unsimplification

* 🚨 eslint loves singlequotes

*  Added emojis / categories in metadata

* 🏷️ TypeScript Declarations

*  Sticker Categories in sendMessage

* 🏷️ Improved TS declarations

* fix stickerCategories type

* fix: don't set name/author if not defined

Co-authored-by: Marcelo Carvalho <mpirescarvalho17@gmail.com>
Co-authored-by: Pedro S. Lopez <pslamoros@hotmail.com>
Co-authored-by: Pedro S. Lopez <pedroslopez@me.com>
2021-05-31 19:13:30 -04:00
Pedro Lopez
5991b28b88 update supported whatsapp web ver to v2.2114.8 2021-04-20 23:02:33 -04:00
Pedro Lopez
2894832b00 chore: mark version v1.12.6 2021-04-20 22:59:35 -04:00
Pedro Lopez
6cece4a006 fix: emit disconnected event on page navigation
This also addresses an issue due to a change in behavior from WhatsApp Web when the session is logged out from the device.
2021-04-20 20:02:22 -04:00
Pedro Lopez
f1e2f32988 fix: click correct element on manual qr code refresh 2021-04-20 19:39:13 -04:00
Pedro S. Lopez
f564e41781 chore: bump version to v1.12.5 2021-02-25 00:31:39 -04:00
Jacob Galam
e6015162c5 fix(types): media type in MessageSendOptions (#554)
Co-authored-by: Pedro S. Lopez <pslamoros@hotmail.com>
2021-02-25 00:27:23 -04:00
Pedro S. Lopez
bc90ffcb19 fix: WhatsApp Web v2.2106.5 compatibility 2021-02-25 00:23:49 -04:00
Antoine Schaller
2702757dce fix: star() & unstar() functions (#547) 2021-02-15 22:24:07 -04:00
Pedro S. Lopez
56171f957e chore: don't auto set bug label on issues
This should be manually added when it's confirmed a bug
2021-02-13 11:29:16 -04:00
Pedro S. Lopez
204a1c79af chore: mark version v1.12.4 2021-02-11 18:44:15 -04:00
Pedro S. Lopez
168c84250e fix sending stickers on WhatsApp Web v2.2104.6 2021-02-11 18:40:35 -04:00
Pedro S. Lopez
d96e8e5eb5 chore: mark version v1.12.3 2021-02-09 15:40:57 -04:00
Pedro S. Lopez
0cbb0373ad fix(ts): getNumberId typings caused error on build 2021-02-09 15:35:57 -04:00
Pedro S. Lopez
1f756142e4 ignore logs on npm publish 2021-02-09 00:48:58 -04:00
Pedro S. Lopez
4047afe332 chore: mark version v1.12.2 2021-02-09 00:47:28 -04:00
Pedro S. Lopez
89029ac916 add docs 2021-02-09 00:43:45 -04:00
Artem Sinelnikov
fa4923db98 fixed acceptInvite typings 2021-02-09 00:43:45 -04:00
Pedro S. Lopez
559133c3c4 fix: upload media on WhatsApp Web v2.2104.6 2021-02-09 00:35:25 -04:00
Pedro S. Lopez
e2acd03efc fix: download media on WhatsApp Web v2.2104.6 2021-02-09 00:24:48 -04:00
Pedro S. Lopez
c6974295a6 chore: mark version v1.12.1 2021-01-30 20:38:10 -04:00
Pedro S. Lopez
6590c75c8a fix (ts): include pupPage and pupBrowser properties on Client typedef 2021-01-30 20:36:46 -04:00
Pedro S. Lopez
1bdc7335d8 chore: mark version v1.12.0 2020-12-29 00:38:44 -04:00
Pedro S. Lopez
bb9d160f72 docs: switch links to point to the guide 2020-12-29 00:37:25 -04:00
Pedro S. Lopez
cea1830dde docs: fix error generating Label docs 2020-12-29 00:33:49 -04:00
Pedro S. Lopez
f639c53f0a feat: Get message delivery information (close #418) 2020-12-29 00:33:49 -04:00
Raphael R
3e32fe27ea feat: mark chat as unread (#475)
Co-authored-by: Pedro S. Lopez <pedroslopez@me.com>
2020-12-29 00:33:49 -04:00
Marcelo Carvalho
5c6195738f feat: add GroupChat types (#485)
Co-authored-by: Pedro S. Lopez <pedroslopez@me.com>
2020-12-29 00:33:49 -04:00
Pedro S. Lopez
32575490da docs: fix typo 2020-12-29 00:33:49 -04:00
Antoine Schaller
5a0ccc8b17 feat: added starred indicator to messages (#501)
Co-authored-by: Pedro S. Lopez <pedroslopez@me.com>
2020-12-29 00:33:49 -04:00
Marcelo Carvalho
1b946940f4 feat: star/unstar messages (#494) 2020-12-29 00:33:49 -04:00
Pedro S. Lopez
71dbe99023 feat: get Contact's "About" text (close #491) 2020-12-29 00:33:49 -04:00
Pedro S. Lopez
8b101d1f3d feat: get links included in message (#457) 2020-12-29 00:33:49 -04:00
Marcelo Carvalho
e2a642a81b feat: send media as stickers (#479)
Adds the option `sendMediaAsSticker` that will take care of converting media to appropriate formats and send it as a sticker. Note that ffmpeg is required to properly convert animated stickers that are not in webp format.

Co-authored-by: Pedro S. Lopez <pedroslopez@me.com>
2020-12-29 00:33:49 -04:00
Pedro Lopez
0c0a5a752b docs: fix slight typo 2020-12-29 00:33:49 -04:00
Marcelo Carvalho
e141a5df97 feat: send media as document (#490)
Co-authored-by: Pedro S. Lopez <pslamoros@hotmail.com>
2020-12-29 00:33:49 -04:00
Lucas Rosa
576768e390 feat: Get registered ID for a given phone number (#483)
Exposes internal getNumberById function for easy usage.
This can help with dealing with brazilian numbers with the extra digit, always returning the correct ID.

This will probably eventually replace the current isRegisteredUser function.

Co-authored-by: Pedro Lopez <pedroslopez@me.com>
2020-12-29 00:33:49 -04:00
Aliyss Snow
87cb5a0519 feat(interface): Open chat search, open chat at message position (#447) 2020-12-29 00:33:49 -04:00
dyegoaurelio
274d24002b feat: WA Business Labels support (#407)
* Get all labels
* Get chats by label
* Get labels assigned to chats

Co-authored-by: Pedro S. Lopez <pslamoros@hotmail.com>
Co-authored-by: Pedro Lopez <pedroslopez@me.com>
2020-12-29 00:33:49 -04:00
Pedro Lopez
563f73d290 chore: mark version v1.11.2 2020-12-21 22:13:14 -04:00
Pedro Lopez
4b3079d2c1 chore: bump supported WhatsApp Web version to v2.2049.10 2020-12-21 22:08:13 -04:00
Pedro Lopez
7b0e356fcc chore: ignore all session files on npm 2020-12-21 22:04:02 -04:00
Pedro Lopez
467f2af7d8 fix: properly serialize chats with pending button replies
close #489
2020-12-21 21:55:38 -04:00
Pedro Lopez
19b1b9fdef chore: mark version v1.11.1 2020-11-19 15:07:29 -04:00
victormga
a1d09e0e21 fix: fetchMessages when msgs length is smaller than limit (#438) 2020-11-19 15:03:39 -04:00
victormga
d86ccec5d1 fix: Expose store on WhatsApp Web v2.2047.10 (#437)
Fixed whatsapp updates

close #436
2020-11-19 14:55:41 -04:00
Pedro Lopez
f359ad40ee chore: bump supported WhatsApp Web version to v2.2045.15 2020-11-05 02:27:39 -04:00
Pedro Lopez
db7a8bcd3b chore: bump version to v1.11.0-post 2020-11-05 02:26:20 -04:00
Pedro Lopez
edbf4139e7 chore: mark version v1.11.0 (again)
PR had to be merged and added to the release
2020-11-05 02:09:32 -04:00
Pedro S. Lopez
709c43cc9f feat: add received vcards to the message (#400)
close #398 

Co-authored-by: Pedro S. Lopez <pedroslopez@me.com>
2020-11-05 02:07:40 -04:00
Pedro Lopez
054ef4a84f add typings 2020-11-05 02:06:13 -04:00
Pedro S. Lopez
c9bc0a1c8b Merge branch 'master' into bugfix-multi_vcard 2020-11-05 01:55:03 -04:00
Pedro Lopez
6b3c8465e9 chore: mark version v1.11.0 2020-11-05 01:51:39 -04:00
Pedro Lopez
43aa6b3716 chore: add blocking functionality to readme 2020-11-05 01:43:45 -04:00
Pedro Lopez
7738f7910b fix linting issues 2020-11-05 01:40:12 -04:00
Pedro Lopez
fc7a1a9974 fix: address removal of Conn.me
This change on WhatsApp Web v2.2045.15 caused errors when sending messages and getting the current user id
2020-11-05 01:37:51 -04:00
Pedro Lopez
b0465ceeff fix: expose GroupMetadata
WhatsApp Web v2.2045.15+ no longer has this in the store by default
2020-11-05 01:20:52 -04:00
Lucas Rosa
2abe4a157d Merge branch 'master' into bugfix-multi_vcard 2020-11-02 13:20:25 -03:00
yuvalfis
e520a96b20 fix: serialize msgs.buttons and delete msgs from chat model (#402)
Co-authored-by: yuvalFishler <yuvalf@realfriend.ai>

close #386
2020-11-01 18:32:46 -04:00
Lucas Rosa
75296b652b feat: add received vcards to the message. 2020-10-26 19:49:06 -03:00
Lucas Rosa
b15ec768d3 fix: show multiple vcard as array in body 2020-10-26 16:23:26 -03:00
Pedro S. Lopez
42dd866a53 feat: boolean for indicating Status update messages (#396) 2020-10-26 00:45:09 -04:00
Pedro S. Lopez
20e07c43d7 feat: block/unblock contacts (#397) 2020-10-26 00:44:03 -04:00
Pedro S. Lopez
9b096db784 feat: Send contacts (#395)
Introduces the ability to send contact cards. You can send Contacts directly or send a vCard string and it will be automatically parsed. If you'd like to disable this autoparse functionality, you can set `parseVCards: false` as an option while sending a message.

close #293
2020-10-25 22:44:37 -04:00
Pedro S. Lopez
668106be2d chore: add group settings functionality to readme 2020-10-25 19:23:28 -04:00
Pedro Lopez
cc5d85b2b1 chore: bump version to v1.10.0-post 2020-10-25 19:15:40 -04:00
Pedro Lopez
3d06babed9 chore: mark version v1.10.0 2020-10-21 15:22:05 -04:00
Pedro Lopez
0ca909233d Merge branch 'master' of https://github.com/pedroslopez/whatsapp-web.js 2020-10-21 15:21:08 -04:00
Pedro Lopez
f4a2c44ed7 chore: bump supported WhatsApp Web version to v2.2043.8 2020-10-21 15:21:02 -04:00
Pedro S. Lopez
604656cf73 fix: change OpaqueData module lookup function (#391)
A change introduced in WhatsApp Web v2.2043.8 caused this to break, leading to issues while sending media

fix #390
2020-10-21 15:18:51 -04:00
Aliyss Snow
aedf41b762 feat: Pin and unpin Chats (#166)
* Added Pinning
- chat.pin() to pin
- chat.unpin() to unpin

Co-authored-by: Pedro S. Lopez <pedroslopez@me.com>
2020-10-11 15:50:12 -04:00
Pedro S. Lopez
bf2775d1f0 feat: update group settings (messages and set info admins only) (#374)
close #187
2020-10-11 15:14:06 -04:00
Pedro Lopez
0b112004d5 chore: mark version v1.9.0 2020-10-09 02:34:02 -04:00
Pedro Lopez
336fb9b551 chore: update supported WhatsApp Web version to v2.2041.6 2020-10-09 02:32:42 -04:00
Pedro Lopez
ba6ec7feab fix: apply message serialization fix everywhere
Moving this to a serializer function like done with a couple other models guarantees getting messages with pending acks won't fail elsewhere. It also sets it up so the we can add/remove properties on the Message model as needed in the future.

related: 51a1028588
2020-10-09 02:29:07 -04:00
Pedro Lopez
51a1028588 fix: remove pendingAckUpdate from serialization on changed message ack
As of WhatsApp Web v2.2041.6, a "pendingAckUpdate" property was added to the Message model that persists on serialization but is a non-serializable type. This fix removes it from the change:ack so it can be properly sent through puppeteer.

fix #371
2020-10-09 01:40:07 -04:00
Pedro Lopez
1c31139434 fix(types): add missing type defs for chat.muteExpiration 2020-09-27 19:18:07 -04:00
Pedro Lopez
ee21e14547 feat: indicate if chat is currently muted 2020-09-27 19:15:34 -04:00
Leonardo Almeida
cbf8fb7cf5 feat: chat mute expiration timestamp (#351)
add chat.muteExpiration to indicate when the mute expires

Co-authored-by: Pedro S. Lopez <pedroslopez@me.com>
2020-09-27 19:11:08 -04:00
Pedro Lopez
c7d5eb67ee chore: bump version to v1.8.2-post 2020-09-01 15:27:36 -04:00
Pedro Lopez
7fcd43f100 chore: mark version v1.8.2 2020-09-01 15:23:46 -04:00
Pedro Lopez
a60f0ce139 chore: update supported WhatsApp Web version to v2.2035.14 2020-09-01 15:00:45 -04:00
Pedro Lopez
ab0db80063 fix: reliably get group metadata
GroupMetadata was only loaded for the first couple chats, so you could not access it on older group chats without performing an action that would update its state

close #264
2020-09-01 12:48:22 -04:00
Hendra827
e7c76fe069 chore: update puppeteer to v5.2.1 2020-08-31 14:11:31 -04:00
Pedro Lopez
233382ce7a chore: ignore test session files when pushing to git 2020-08-28 23:15:15 -04:00
Pedro Lopez
e08dd7d835 chore: add .npmignore for smaller package size 2020-08-28 23:12:45 -04:00
Pedro Lopez
a1e8e8cf51 chore: bump version to v1.8.1-post 2020-08-28 23:08:25 -04:00
Pedro Lopez
a1e0970e1e chore: mark version v1.8.1 2020-08-28 23:04:31 -04:00
Caio Henrique Agiani
c827b32328 fix(types): correct response type for message.forward() (#324) 2020-08-28 22:00:13 -04:00
Pedro Lopez
2345b5c4ee chore: bump version to v1.8.0-post 2020-08-25 23:26:55 -04:00
Pedro Lopez
8627fc3d71 chore: mark version v1.8.0 2020-08-25 23:06:36 -04:00
Pedro Lopez
502b22f6d7 feat: forward messages
close #316
2020-08-25 23:00:35 -04:00
Pedro Lopez
590ecc2351 chore: update supported WhatsApp Web version to 2.2035.12 2020-08-25 22:34:10 -04:00
Pedro Lopez
7da8345722 fix: upload media
As of WhatsApp Web v2.2035.12, the structure of the return value for  `uploadMedia()` now returns an object that contains the previously returned data in its `mediaEntry` property.

fix #318
2020-08-25 22:30:04 -04:00
Pedro Lopez
4344df6152 fix: properly detect successful authentication on dark mode 2020-08-25 21:40:57 -04:00
Pedro Lopez
382259488b feat(dev): Interactive shell for quick testing/exploration 2020-08-17 23:43:50 -04:00
Pedro Lopez
7180beda2e feat: Get corresponding Chat from Contact object and vice versa
close #269
2020-08-17 23:31:19 -04:00
Pedro Lopez
34aa136bf9 fix(docs): Correctly document Chat timestamp property
close #287
2020-08-17 22:36:32 -04:00
Pedro Lopez
2a58cfe8e2 fix(types): properly set optional arguments when sending / replying to messages
close #309
2020-08-17 22:28:27 -04:00
Pedro Lopez
9da553ecb9 feat: Set client's display name (pushname) 2020-08-17 22:19:29 -04:00
stefanfuchs
97705b1865 fix: MessageMedia interface to class (index.d.ts) (#301)
* fix: change MessageMedia to class

* fix: remove all references to MessageMediaInterface

* add MessageMedia constructor params docs
2020-08-08 15:03:09 -04:00
stefanfuchs
fbdfd2c4dd fix: Constants export in index.js (#285)
* fix: add Constants export in index.js
* fix: add missing constants export in index.d.ts


Co-authored-by: Pedro S. Lopez <pedroslopez@me.com>
2020-08-03 02:58:15 -04:00
stefanfuchs
5c84a1651d chore: add missing types in JSDoc/TSDoc (ClientOptions, ClientInfo, MessageSendOptions, Session) (#286)
* chore: add ClientOptions and ClientInfo in JSDoc

* chore: add MessageSendOptions type

* chore: add ClientSession type in JSDoc

* chore: remove @todo from createGroup (was already solved)

Co-authored-by: Pedro Lopez <pedroslopez@me.com>
2020-08-03 02:52:37 -04:00
stefanfuchs
bfea74f567 fix: add missing type definitions (#278)
* fix: @todo docs improvements

* fix: add ClientInfo to Client typings

* add ClientInfoPhone

* fix: set getBatteryStatus as async

* add ClientInfo comment

Co-authored-by: Pedro S. Lopez <pedroslopez@me.com>
2020-07-11 02:58:57 -04:00
YY
a10b458cd5 feat: custom user Agent in Client (#271)
* Added Option to Custom User Agent in Client

* Update Typescript Index

* Delete Variable UserAgent From Client

* Update Variable UserAgent to userAgent
2020-07-03 02:05:23 -04:00
Pedro Lopez
de2c441870 chore: update supported whatsapp web version 2.2025.6 2020-06-18 01:48:10 -04:00
Pedro Lopez
bff60bc9f6 chore: bump version v1.7.0-post 2020-06-18 01:47:46 -04:00
Pedro Lopez
9cc668e4d9 chore: mark version v1.7.0 2020-06-18 01:41:36 -04:00
Pedro Lopez
753b6772ab feat: get current battery status 2020-06-18 01:28:25 -04:00
Pedro Lopez
300b367fa0 feat: logout client
close #255
2020-06-17 23:58:02 -04:00
Pedro Lopez
b0baeaa8da Merge branch 'master' of https://github.com/pedroslopez/whatsapp-web.js 2020-06-17 23:30:01 -04:00
Pedro Lopez
ad9ae1f703 fix: move invite info to client
Since static methods do not have access to `this.client`, it was giving an error when trying to call these functions. The client itself is a better place for them.

close #258
2020-06-17 23:29:34 -04:00
Pedro Lopez
b89f0e146f fix: move invite info to client
Since static methods do not have access to `this.client`, it was giving an error when trying to call these functions. The client itself is a better place for them.
2020-06-17 23:28:54 -04:00
Maximilian Walterskirchen
6c7a3f9899 fix: Added check for null in Message constructor (#253)
Co-authored-by: Walterskirchen <walterskirchen@walter-group.com>
Co-authored-by: Pedro S. Lopez <pedroslopez@me.com>
2020-06-16 18:15:19 -04:00
stefanfuchs
d7459eac23 feat: add typescript definition file (#252)
Co-authored-by: Pedro S. Lopez <pedroslopez@me.com>
2020-06-16 18:12:14 -04:00
Javier Portillo
2abd3729d8 fix: clear qr refresh interval on client.destroy() (#249)
* fix: client.destroy() keeps trying to get QR code when client is not authorized yet

Co-authored-by: Javier Portillo <javier.marquez@dada-dada.com>
2020-06-08 22:31:22 -04:00
Pedro S. Lopez
810ff4603b chore: add discord link to issue creation 2020-06-07 18:10:49 -04:00
Pedro S. Lopez
4d5619019c chore: Add issue templates
close #246
2020-06-07 18:06:02 -04:00
Pedro Lopez
84213cc781 chore: bump version v1.6.1-post 2020-06-04 20:25:04 -04:00
Pedro Lopez
bf94d20db3 Merge branch 'hotfix/v1.6.1' 2020-06-04 20:23:55 -04:00
Pedro Lopez
2e3b2f2a43 chore: mark version v1.6.1 2020-06-04 20:20:43 -04:00
Caio Henrique Agiani
9c9b3c4441 fix: WhatsApp Autentication by oguzhan51 (#237)
The selector used to detect successful authentication was changed in WhatsApp Web v2.2023.2

Co-authored-by: oguzhan51
2020-06-04 20:15:40 -04:00
Caio Henrique Agiani
832e402671 fix: WhatsApp Autentication by oguzhan51 (#237)
The selector used to detect successful authentication was changed in WhatsApp Web v2.2023.2

Co-authored-by: oguzhan51
2020-06-04 20:03:44 -04:00
Aliyss Snow
47011a32a5 feat: Interface controls (#220)
- Open chat drawer
- Open chat window
- Open message info drawer
- Close drawer
2020-05-31 18:14:21 -04:00
Pedro S. Lopez
a7ca628775 chore: update required node version (#222)
Puppeteer v3 now requires 10.18.1+
2020-05-26 13:52:52 -04:00
Aliyss Snow
aa60e89911 docs: add mute/unmute feature to readme (#214)
Co-authored-by: Pedro S. Lopez <pedroslopez@me.com>
2020-05-24 19:27:41 -04:00
Pedro Lopez
d922e4df2f chore: bump version to v1.6.0-post 2020-05-24 01:11:07 -04:00
Pedro Lopez
c032ea4387 chore: mark version v1.6.0 2020-05-24 00:57:54 -04:00
Pedro Lopez
a80fcfa740 update supported whatsapp web version to v2.2021.3 2020-05-24 00:55:12 -04:00
Pedro Lopez
44f837c42a fix: remove unreliable return values for new mute state 2020-05-24 00:19:23 -04:00
Aliyss Snow
4beeab9b2c feat: mute/unmute chats (#168)
Co-authored-by: Pedro S. Lopez <pedroslopez@me.com>
2020-05-24 00:10:26 -04:00
Pedro Lopez
cca74ec8b9 docs: indicate return type for MessageMedia.fromFilePath 2020-05-23 23:28:19 -04:00
Pedro Lopez
8b656c2caf fix: set thumbnail for media messages
close #55
2020-05-23 23:21:13 -04:00
Pedro Lopez
4d09a4b60c fix: media would stay stuck uploading when using the media option 2020-05-23 22:55:18 -04:00
Pedro Lopez
7d2c89cf84 docs: fix wrong parameter name 2020-05-23 22:37:31 -04:00
Pedro Lopez
0928f48762 Merge branch 'master' of https://github.com/pedroslopez/whatsapp-web.js 2020-05-23 22:36:04 -04:00
Pedro Lopez
eb82e80343 feat: Helper function to create MessageMedia from a local file path 2020-05-23 22:35:59 -04:00
Caio Henrique Agiani
f5a0de7def fix: Wait for WhatsApp page load (#209)
* Fix bug on Puppeteer timeout 30000 ms exceeded
2020-05-23 21:52:46 -04:00
Pedro Lopez
d6637d662a fix: visual glitch when sending message to new chat; no longer require at least one chat to have been created 2020-05-16 02:08:13 -04:00
Pedro Lopez
4188734839 Ignore lock files 2020-05-16 01:22:05 -04:00
Pedro Lopez
207ea200b4 Merge branch 'master' of https://github.com/pedroslopez/whatsapp-web.js 2020-05-16 01:12:20 -04:00
Pedro Lopez
b062f9f82f Update puppeteer to version 3.0.4 2020-05-16 01:12:14 -04:00
Pedro S. Lopez
4d7a6ee4c2 Update supported whatsapp web version 2020-05-16 00:50:16 -04:00
depfu[bot]
e528e8c50e Update jsqr to version 1.3.1 (#185)
Co-authored-by: depfu[bot] <23717796+depfu[bot]@users.noreply.github.com>
2020-05-02 17:56:43 -04:00
Aliyss Snow
bcd02aa5e4 set defaultViewPort option for puppeteer (#167)
- Mainly for those who like to keep the GUI open.
- Expands to fit and looks like it usually would.
2020-04-20 22:57:59 -04:00
Pedro Lopez
686c99f0c7 feat: send audio as voice note
This adds the 'sendAudioAsVoice' option for messages

close #160
2020-04-14 23:18:08 -04:00
Pedro Lopez
59ee68b227 chore: bump version to v1.5.1-post 2020-04-14 22:49:57 -04:00
Pedro Lopez
f40c8d4ffe chore: mark version v1.5.1 2020-04-14 22:47:07 -04:00
Pedro Lopez
bab54aea8b fix: set url subtype for messages with link previews
Co-authored-by: João Vitor Miranda <joao.miranda@aluno.ufabc.edu.br>
Co-authored-by: Top <shmuliktop@users.noreply.github.com>
2020-04-14 22:42:05 -04:00
Pedro Lopez
f0a1e05600 chore: bump version v1.5.0-post 2020-04-11 20:00:28 -04:00
Pedro Lopez
303d814376 chore: mark version v1.5.0 2020-04-11 19:49:45 -04:00
Pedro Lopez
044f62216b feat: link previews
After this commit, previews for links will be enabled by default. To disable it, use linkPreview: false as an option when sending the message.

close #98
2020-04-11 19:45:06 -04:00
Pedro Lopez
2b3c3e971a docs: add new param to jsdoc for getProfilePicUrl 2020-04-11 19:04:15 -04:00
Pedro Lopez
8528d9b0b6 feat: get profile pic url by user ID
This moves the function from Contact to Client to enable getting profile picture without requiring a conversation before. The old function is still available on Contact for convenience and backwards-compatibility.
2020-04-11 19:03:47 -04:00
Pedro Lopez
7eb7fa8e28 feat: send online status
close #69
2020-04-11 18:56:23 -04:00
Pedro Lopez
8714e90df9 revert: included this by mistake on last commit 2020-04-11 18:52:01 -04:00
Pedro Lopez
478f7136d9 feat: takeover on conflict
This adds funcitonality to takeover after a certain timeout if WhatsApp Web has been opened in another browser

close #119
2020-04-11 18:48:50 -04:00
Pedro S. Lopez
20bbe3d0c4 readme: add discord logo to shield 2020-04-11 16:32:53 -04:00
Pedro S. Lopez
33db17e67d add discord link 2020-04-11 16:31:17 -04:00
Pedro Lopez
1c2b4592b5 chore: bump version to v1.4.1-post 2020-04-11 15:04:00 -04:00
Pedro Lopez
ce0a80383c chore: mark version v1.4.1 2020-04-11 15:01:44 -04:00
Pedro Lopez
97e488b10a chore: update supported WhatsApp Web version to 2.2013.7 2020-04-11 15:00:42 -04:00
Pedro Lopez
ef507fcb95 Merge branch 'master' of https://github.com/pedroslopez/whatsapp-web.js 2020-04-11 14:59:39 -04:00
Pedro Lopez
8e011e0233 feat: get current whatsapp web version 2020-04-11 14:59:32 -04:00
InstantlyMoist
470c7aea04 feat: added MediaKey in order to see which sticker has been sent (#146) 2020-04-11 14:54:19 -04:00
Antoine Schaller
f92f1ec6bf Fix uploadMedia arguments after origin code change (#153) 2020-04-11 14:53:22 -04:00
depfu[bot]
702a0ab103 Update jsdoc to version 3.6.4 (#144)
Co-authored-by: depfu[bot] <23717796+depfu[bot]@users.noreply.github.com>
2020-04-07 23:38:56 -04:00
Pedro Lopez
d9fb5693d1 chore: bump version v1.4.0-post 2020-04-05 23:45:18 -04:00
Pedro Lopez
3cbf1e9c2f chore: mark version v1.4.0 2020-04-05 23:39:22 -04:00
Aliyss Snow
93a617336a feat: battery percentage changed event (#126)
New "change_battery" event is triggered when the battery percentage changes. Has current battery percentage and charging state as object param.

Co-authored-by: Pedro S. Lopez <pedroslopez@me.com>
2020-04-05 23:36:03 -04:00
kurob1993
1780436b93 fix: make pupBrowser and pupPage available sooner (#137)
* move this.pupBrowser variable to line 51 to resolve not being able to close the browser when it is not connected to the internet

* move pupPage along with pupBrowser

Co-authored-by: Pedro S. Lopez <pedroslopez@me.com>
2020-04-05 23:04:03 -04:00
Pedro Lopez
7acbd3d800 fix: properly set chatId
This was causing errors when using the .reply() function
2020-04-05 22:57:59 -04:00
Pedro Lopez
67435b2244 fix: group events were not being triggered 2020-04-05 22:57:36 -04:00
Pedro Lopez
743ac93f6e feat: allow setting timeouts via options 2020-04-03 01:49:16 -04:00
Pedro Lopez
0a7412cf17 feat: create groups
close #131
2020-04-03 01:45:06 -04:00
Pedro Lopez
d1e357d23b chore: bump version v1.3.1-post 2020-04-02 02:35:36 -04:00
Pedro Lopez
3610cef926 chore(docs): mark v1.3.1 2020-04-02 02:33:44 -04:00
Pedro Lopez
4e5eeace2f chore: mark v1.3.1 2020-04-02 02:33:17 -04:00
Pedro Lopez
6c43a2d2ed fix: increase timeouts
close #130
2020-04-02 02:30:50 -04:00
Pedro Lopez
001c045c08 fix: only return undefined for ERROR_* media states
This was causing a regression as of 1.2.5 that caused media files sent by the client to not be properly downloaded
cc #111 @stevefold
2020-04-02 02:24:12 -04:00
Pedro S. Lopez
c3ba79464b Update README.md 2020-03-31 12:43:03 -04:00
Pedro Lopez
237331b656 chore: bump version to v1.3.0-post 2020-03-29 23:59:05 -04:00
Pedro Lopez
9d0b58a847 chore: mark version v1.3.0 2020-03-29 23:51:49 -04:00
Pedro Lopez
842c4f0e06 feat: check if ID is a valid whatsapp user
close #120
2020-03-29 22:58:08 -04:00
Pedro Lopez
2dddc781c5 fix: initialize takes no params 2020-03-29 21:47:47 -04:00
Pedro S. Lopez
d8cd2d1d83 chore: updated whatsapp web version 2020-03-23 18:59:53 -04:00
Pedro Lopez
80d5783f22 feat: new event for when media is uploaded
Messages created by the current client don't have attatched media on message_create because it is still being uploaded and sent. This event allows you to detect when the media has been properly sent so it can be downloaded.

close #111
2020-03-22 20:38:26 -04:00
Pedro Lopez
cb54487197 feat: add ack to message model
close #108
2020-03-22 20:00:53 -04:00
Steven L
d08b343815 Added "restartOnAuthFail" as an option (#112)
- When true, the sessions passed is discarded when reinitialized.
2020-03-22 19:52:46 -04:00
Pedro Lopez
ec1a80dfb4 chore: bump version to v1.2.5-post 2020-03-15 15:36:57 -04:00
Pedro Lopez
56ed020d65 chore: mark version v1.2.5 2020-03-15 15:32:37 -04:00
Pedro Lopez
25b96378c7 fix: properly handle unresolved media 2020-03-15 15:29:56 -04:00
Pedro S. Lopez
5934ec531f fix: return undefined when attempting to download nonexistent media
This could occur when the user has deleted the media and it can no longer be downloaded.
2020-03-15 15:20:50 -04:00
Pedro Lopez
65542f6025 chore/fix: update requires for new moduleraid package
For got to do this on the previous release
2020-03-15 02:05:20 -04:00
Pedro Lopez
00c603e623 chore: use published moduleraid
Pulling this from github was causing confusion and issues on installation for users that did not have git installed. I have published the library myself for now, but should be changed back to the official library when an official release is made.
2020-03-15 02:03:11 -04:00
Pedro Lopez
bcd18428eb chore: bump version to v1.2.4-post 2020-03-14 17:46:33 -04:00
Pedro Lopez
995abbf4a6 chore: mark version v1.2.4 2020-03-14 17:43:31 -04:00
Pedro Lopez
8599a6d918 fix: properly download media if it has not been loaded
This issue occurred when attempting to download media from old messages.
2020-03-14 17:37:59 -04:00
Pedro Lopez
5e9deff8a9 chore: bump version v1.2.3-post 2020-03-13 17:54:22 -04:00
Pedro Lopez
539849732c chore: mark version v1.2.1 2020-03-13 17:46:39 -04:00
Pedro Lopez
4fe7fa93b9 fix: delegate all event handlers
Attaching these events directly to puppeteer functions apparently blocks and causes CPU usage to go up, slowing everything down.

related #88, 8bdecad
2020-03-13 17:44:20 -04:00
Pedro Lopez
2820d3e72a chore: bump version to v1.2.2-post 2020-03-13 00:18:30 -04:00
Pedro Lopez
cde5719bb6 chrore: mark version v1.2.2 2020-03-13 00:13:46 -04:00
Pedro Lopez
8bdecadba4 fix: don't call event handler for new messages directly to puppeteer
This was creating performance issues, specially on startup when the initial set of messages were being loaded for a client with many chats.
2020-03-13 00:09:43 -04:00
Pedro Lopez
b41414cfbf chore: bump version to 1.2.1-post 2020-03-05 21:23:48 -04:00
Pedro Lopez
c61f447a93 chore: mark version v1.2.1 2020-03-05 21:20:53 -04:00
Pedro Lopez
49aacec4a7 fix: correctly splice and merge fetched messages
This was eliminating messages in the middle of the array instead of eliminating older messages to reach the specified limit.

close #97
2020-03-05 21:18:10 -04:00
Pedro S. Lopez
d7a3e1a9a3 chore: update supported whatsapp web version 2020-03-02 23:57:24 -04:00
Pedro Lopez
e14b49c5df chore: bump version to v1.2.0-post 2020-03-01 15:14:06 -04:00
Pedro Lopez
f34902dfdd chore: mark version v1.2.0 2020-03-01 15:00:15 -04:00
Pedro Lopez
6e76fece91 docs: add jsdoc strings for group events 2020-03-01 14:58:06 -04:00
sahalMoidu
98458f760e feat : send conversation seen (#66)
After this commit, chats will be automatically marked as seen when a message is sent to it. If this is not the intended behavior, `sendSeen: false` can be set as part of the options object. 

You can also manually mark a conversation as seen by calling the sendSeen() function on the Chat.

Co-authored-by: Pedro S. Lopez <pedroslopez@me.com>
2020-03-01 14:42:35 -04:00
Aliyss Snow
48b9ae1e81 feat: listen to group events (#90)
This allows you to listen for user joins or leaves, description updates, subject updates, picture updates, and group settings updates.

Co-authored-by: Pedro S. Lopez <pedroslopez@me.com>
2020-03-01 14:32:58 -04:00
Aliyss Snow
588dc93c17 chore: added index.js for structures (#91)
- Allows for a cleaner integration (imo) in Client.js
2020-03-01 13:59:09 -04:00
Pedro Lopez
16fe865a9c feat: fetch chat messages
This will automatically fetch messages until it reaches the specified limit or there are no more messages. In the future, this should be extended to fetch messages before, after or around a specific message/date by adding props to the searchOptions object.

close #51
2020-02-29 16:01:13 -04:00
Pedro Lopez
b07b38bbe8 feat: Simulate recording audio in chat, clear recording/typing state, standardize chatstate change function names 2020-02-29 14:07:47 -04:00
Anderson de Oliveira Machado
d35f101fac feat: send typing in chat (#87)
Co-authored-by: Pedro S. Lopez <pedroslopez@me.com>
2020-02-29 13:55:27 -04:00
Gabriel
72441beb37 feat(example): better sesion data save (#79)
For more consistency whenever I have a successful authentication I write
to the json file the session data
2020-02-28 17:02:10 -04:00
Jan Vlach
794c9e16fc feat: force state update (#77)
Whatsapp web will not update state until some action, this will force update client state.
First will set state to TIMEOUT, then to current state
2020-02-28 17:00:24 -04:00
Pedro Lopez
05f57d2f39 chore: bump version to v1.1.0-post 2020-02-26 23:50:55 -04:00
Pedro Lopez
130da046f5 chore: mark version v1.1.0 2020-02-26 23:34:01 -04:00
Pedro Lopez
bb40218c66 docs: use MessageAck type 2020-02-26 23:33:11 -04:00
Pedro S. Lopez
ad3834e575 Update MessageAck constant for consistancy 2020-02-26 23:31:10 -04:00
Pedro Lopez
e6ef5929fc added ack constants and brief example 2020-02-26 23:18:09 -04:00
João Vitor Miranda
bb4ad11bfa feat: added ACK events (#73)
Implements ack change detection, making it possible to know when messages have been delivered, read, etc.

Co-authored-by: Pedro S. Lopez <pedroslopez@me.com>
2020-02-26 22:59:46 -04:00
Pedro Lopez
1ebaf56617 Merge branch 'master' of https://github.com/pedroslopez/whatsapp-web.js 2020-02-26 00:40:51 -04:00
Pedro Lopez
60ee2ca522 feat: delete chat, clear chat 2020-02-26 00:39:33 -04:00
Aliyss Snow
132424ea08 feat: archive chats (#63) 2020-02-25 20:06:46 -04:00
sahalMoidu
5c9e76e23f feat: refresh qr code (#68)
close #60
2020-02-23 12:20:11 -04:00
Pedro S. Lopez
37932d9a69 Update README.md 2020-02-22 17:43:57 -04:00
Pedro Lopez
3c500a6474 Merge branch 'master' of https://github.com/pedroslopez/whatsapp-web.js 2020-02-22 17:28:15 -04:00
Pedro Lopez
1c60c83e80 feat: Delete messages 2020-02-22 17:28:03 -04:00
Pedro S. Lopez
69d7b3e50b update supported whatsapp web version 2020-02-22 16:12:13 -04:00
Pedro S. Lopez
0b1f06a932 update supported whatsapp web version 2020-02-22 16:11:51 -04:00
sahalMoidu
1840826e2b feat : Check if the given number is a whatsapp number (#54)
* feat : Check if the given number is a whatsapp number

- Avoids sending message to non whatsapp number
- Gets the id of the user from whatsapp server rather than generating on client
2020-02-17 09:10:07 -04:00
sahalMoidu
6ade08e814 Implemented changes mentioned in SimiPrambos PR#28 (#52)
* Implemented changes mentioned in SimiPrambos PR#28
To reflect new code structure
2020-02-14 17:53:28 -04:00
Pedro S. Lopez
9891d85b35 Update README.md 2020-02-13 20:10:51 -04:00
Pedro Lopez
67784bc797 feat: get current connection state
Note: This only partly works, since the state may not be updated on WhatsApp's end. In the case of not being able to reach the phone, the state is only updated when the user performs an action, such as sending a message. This means that the state may be CONNECTED when we check, but the phone's really not connected.

ref #43
2020-02-11 22:26:33 -04:00
Fernando Cardoso
e385563883 Initialize the Script with the first browser tab (#47)
Suggestion for the script to start under the first tab of the browser, in order to reduce memory consumption.
2020-02-11 13:53:18 -04:00
Pedro Lopez
d5a26add20 chore: bump version v1.0.2-post 2020-02-10 21:56:21 -04:00
Pedro Lopez
4bc67b0f99 chore: mark version v1.0.2 2020-02-10 21:53:33 -04:00
Pedro Lopez
d44fd5d76a new event on connection state changed 2020-02-10 21:51:58 -04:00
Pedro Lopez
a293146ed8 fix: added timeout to accepted states
This makes the client more reliable since it doesn't quit as soon as it looses conection from the phone for a second. Messages should be queued by WhatsApp Web.
2020-02-10 21:44:56 -04:00
Pedro Lopez
3c774d6553 chore: bump version to v1.0.1-post 2020-02-09 21:35:47 -04:00
Pedro Lopez
dd0a4c6cc3 chore: mark version v1.0.1 2020-02-09 21:33:27 -04:00
Pedro Lopez
ffe803306e fix: send message media
In some cases, the mediaBlob was not resolved correctly

ref: #38
2020-02-09 21:30:28 -04:00
Pedro Lopez
74cfc69367 fix location example 2020-02-09 20:10:56 -04:00
Pedro Lopez
2607e6df3a fix: send message media in options object
An inconsistency in variable names was preventing media sent through the options object from being processed
2020-02-09 02:49:21 -04:00
Pedro Lopez
5fbd8ddf68 feat(example): auto restore session
This is as suggested in #29. Mainly implemeted to ease work while developing, but also serves as an example.
2020-02-09 01:52:38 -04:00
Pedro Lopez
6f44fc586b chore: mark post release 2020-02-09 01:16:28 -04:00
Pedro Lopez
7deef27800 chore: mark version v1.0.0 2020-02-09 00:58:10 -04:00
Pedro Lopez
f947f75725 docs: add location to supported content types 2020-02-09 00:53:43 -04:00
Pedro Lopez
d1dba0f4c0 add disconnect reason 2020-02-09 00:53:00 -04:00
Pedro Lopez
64ed2c125b more message types 2020-02-09 00:46:00 -04:00
Pedro Lopez
5616613807 feat: Mention users, get user number from Contact model 2020-02-08 03:19:51 -04:00
Pedro Lopez
ef80f966ea fix: correctly get message contact in group chats 2020-02-08 03:18:32 -04:00
Pedro Lopez
edc2c7022d feat: change status message 2020-02-08 01:32:15 -04:00
Pedro Lopez
f2b286a319 feat: get contact's profile picture 2020-02-08 01:23:29 -04:00
Pedro Lopez
004312a99f expose some more fields on contacts 2020-02-08 01:17:06 -04:00
Pedro Lopez
2896aeb382 fix some doc related stuff 2020-02-08 01:01:33 -04:00
Pedro Lopez
065a9212ba add another location example 2020-02-08 00:54:21 -04:00
Pedro Lopez
7b229a39a4 feat: Send and receive location 2020-02-08 00:46:55 -04:00
Aliyss Snow
4b1768450f Get Mentions (#35) 2020-02-06 15:47:46 -04:00
depfu[bot]
0cbc24fc6c Update puppeteer to version 2.1.1 (#36) 2020-02-06 11:51:11 -04:00
Pedro Lopez
a247b39f81 docs(readme): add whatsapp web version tested 2020-02-05 02:22:02 -04:00
Pedro Lopez
bf70eb1b87 docs: regenerate docs 2020-02-05 02:17:19 -04:00
Pedro Lopez
1ad9cac682 docs: better readme 2020-02-05 02:16:49 -04:00
Pedro Lopez
4c05e47027 mark post release 2020-02-05 01:43:11 -04:00
Pedro Lopez
62e264231d docs: add generated docs 2020-02-05 01:07:56 -04:00
Pedro Lopez
2f0480c80e docs: add more documentation 2020-02-04 23:04:51 -04:00
Pedro Lopez
a098d61b03 feat: send messages with attachments
close #3
2020-02-04 21:11:20 -04:00
Pedro Lopez
e717915f94 fix: don't get chat after accepting invite
This will now only return the chatId, since getting the chat at this point is unreliable.
2020-02-02 20:37:51 -04:00
Aliyss Snow
e2351db722 Added Contact Model (#34) 2020-02-02 19:08:36 -04:00
Aliyss Snow
b597e4a504 Added delete event message(#33)
* A hacky way of doing things but seems to work. Also after client restart.
2020-02-02 19:00:23 -04:00
Pedro S. Lopez
b99744afa2 Create lint.yml 2020-02-02 14:52:49 -04:00
Pedro Lopez
cc477f9545 Add eslint config and fix linting issues 2020-02-02 14:50:04 -04:00
Pedro Lopez
8eb461ed32 Update puppeteer to v2.1.0
This fixes the library not working on the latest versions of macOS
2020-02-02 13:53:33 -04:00
Pedro Lopez
7243240568 fix !quoteinfo example 2020-02-02 13:52:25 -04:00
Pedro Lopez
5b9413de5c [FIX] Expose Wap module
Setting group description and title did not work due to whatsapp no longer exposing it as it was previously.
2020-02-02 13:44:54 -04:00
Pedro Lopez
8ddf4c29be Add .editorconfig (close #25) 2020-02-02 13:33:08 -04:00
Pedro Lopez
caa8598ec1 [+] Join groups by invite code 2020-02-02 00:52:51 -04:00
Pedro Lopez
a6cc5e5bf2 [+] Get quoted message
[FIX] Properly reply to messages sent by the current user
2020-02-01 22:41:53 -04:00
Pedro S. Lopez
ba8edc8d40 [+] Expose information about the logged in client (#19) 2020-02-01 21:16:03 -04:00
Pedro Lopez
88c56b1371 Return new message after sending 2020-02-01 19:34:28 -04:00
Pedro S. Lopez
2a3f404244 Merge pull request #32 from gabriel-tandil/master
Improvement in KEEP_PHONE_CONNECTED_IMG_SELECTOR
2020-01-31 19:54:46 -04:00
Gabriel Alvarez
d2889a8f03 Improvement in KEEP_PHONE_CONNECTED_IMG_SELECTOR
I change the selector from 'class' to 'attribute = value' to try to get
more permanent results
2020-01-31 16:17:58 -03:00
Pedro Lopez
3c55fbf2ca 0.3.2 2020-01-17 22:06:19 -04:00
Pedro Lopez
6b1b51eacd Increase successful connection timeout 2020-01-17 22:06:04 -04:00
Pedro Lopez
2dc53e0820 [FIX] Connection success detection selector changed
close #31
2020-01-17 22:05:05 -04:00
Pedro Lopez
9043e61c40 0.3.1 2019-12-04 03:00:04 -04:00
Pedro Lopez
bea1ebf480 [FIX] Get QR code directly from canvas element (fix #26) 2019-12-04 02:58:55 -04:00
Pedro Lopez
021a213de3 0.3.0 2019-11-24 04:25:35 -04:00
Pedro S. Lopez
d0bef55b8a Merge pull request #24 from pedroslopez/development
Download message attachments (images, documents, etc)
2019-11-24 04:25:14 -04:00
Pedro Lopez
64912dccfd Download message attachments (images, documents, etc) 2019-11-24 04:23:08 -04:00
Pedro Lopez
dfcf76c139 0.2.0 2019-10-10 22:06:24 -04:00
Pedro Lopez
512b21e522 [FIX] Use STREAM module for getting connection state instead of removed Conn model 2019-10-10 22:05:24 -04:00
Pedro S. Lopez
8babc97788 Merge pull request #18 from renato-macedo/issue17
workaround for module raid not finding 'Conn' module
2019-10-10 21:48:32 -04:00
Pedro S. Lopez
bf177ca1d4 Create stale.yml 2019-10-10 14:13:55 -04:00
Renato
46a7d025fe searches for Chat module instead 2019-10-10 01:46:17 -03:00
Pedro Lopez
517e22381a [-] Remove method to add extra serialized props. This does not work, and the prop being added was already included. 2019-09-08 03:54:44 -04:00
Pedro Lopez
18199d8120 [+] New message_create event that is fired on all message creations.
A new property "fromMe" has also been added to messages.

Close #8
2019-09-08 03:48:19 -04:00
Pedro Lopez
cde0034d93 [+] Implement function to get all open chats.
Close #14
2019-09-08 03:18:40 -04:00
Pedro Lopez
cdfa1760eb [FIX] Implement setDescription and setSubject for groups (close #6) 2019-09-08 03:09:07 -04:00
Pedro Lopez
cf8c54879e Load moduleRaid from GitHub 2019-09-08 00:53:38 -04:00
Pedro Lopez
b2a1e9368a 0.1.2 2019-05-29 23:47:43 -04:00
99 changed files with 22138 additions and 719 deletions

8
.editorconfig Normal file
View File

@@ -0,0 +1,8 @@
root = true
[*]
indent_style = space
indent_size = 4
charset = utf-8
trim_trailing_whitespace = false
insert_final_newline = false

2
.env.example Normal file
View File

@@ -0,0 +1,2 @@
WWEBJS_TEST_SESSION_PATH=test_session.json
WWEBJS_TEST_REMOTE_ID=XXXXXXXXXX@c.us

36
.eslintrc.json Normal file
View File

@@ -0,0 +1,36 @@
{
"env": {
"browser": true,
"commonjs": true,
"es6": true,
"node": true
},
"extends": ["eslint:recommended", "plugin:mocha/recommended"],
"globals": {
"Atomics": "readonly",
"SharedArrayBuffer": "readonly"
},
"parserOptions": {
"ecmaVersion": 2020
},
"plugins": ["mocha"],
"ignorePatterns": ["docs"],
"rules": {
"indent": [
"error",
4
],
"linebreak-style": [
"error",
"unix"
],
"quotes": [
"error",
"single"
],
"semi": [
"error",
"always"
]
}
}

41
.github/ISSUE_TEMPLATE/bug_report.md vendored Normal file
View File

@@ -0,0 +1,41 @@
---
name: Bug report
about: Is something not working as intended? Report it here.
title: ''
assignees: ''
---
### Bug description
A clear and concise description of what the bug is.
### Reproduction steps
Steps to reproduce the behavior:
1.
2.
3.
...
### Expected behavior
A clear and concise description of what you expected to happen.
### Relevant code
If applicable, add code snippets to help explain your problem.
### Environment (please complete the following information):
**WhatsApp**
- Account type [Standard / Business]:
- Device OS [iOS / Android]:
- WhatsApp Web version [run `await client.getWWebVersion()`]:
**Library**
- Browser [Chrome / Chromium]:
- NodeJS version (`node -v`):
- npm or yarn version (`npm -v`):
- whatsapp-web.js version:
**Other**
- Operating system (the one running node) [Linux / MacOS / Windows]:
- Operating system version (ex. Windows 10):
### Additional context
Add any other context about the problem here.

5
.github/ISSUE_TEMPLATE/config.yml vendored Normal file
View File

@@ -0,0 +1,5 @@
blank_issues_enabled: false
contact_links:
- name: Official WWebJS Discord Server
url: https://discord.gg/H7DqQs4
about: Please ask and answer questions here.

View File

@@ -0,0 +1,20 @@
---
name: Feature request
about: Suggest an idea for this project
title: ''
labels: enhancement
assignees: ''
---
**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
**Describe the solution you'd like**
A clear and concise description of what you want to happen.
**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.
**Additional context**
Add any other context or screenshots about the feature request here.

7
.github/dependabot.yml vendored Normal file
View File

@@ -0,0 +1,7 @@
version: 2
updates:
- package-ecosystem: "npm"
directory: "/"
open-pull-requests-limit: 10
schedule:
interval: "monthly"

20
.github/stale.yml vendored Normal file
View File

@@ -0,0 +1,20 @@
# Number of days of inactivity before an issue becomes stale
daysUntilStale: 30
# Number of days of inactivity before a stale issue is closed
daysUntilClose: 7
# Issues with these labels will never be considered stale
exemptLabels:
- pinned
- security
- enhancement
- bug
- WhatsApp Change
# Label to use when marking an issue as stale
staleLabel: stale
# Comment to post when marking an issue as stale. Set to `false` to disable
markComment: >
This issue has been automatically marked as stale because it has not had
recent activity. It will be closed if no further activity occurs. Thank you
for your contributions.
# Comment to post when closing a stale issue. Set to `false` to disable
closeComment: false

20
.github/workflows/lint.yml vendored Normal file
View File

@@ -0,0 +1,20 @@
name: Lint
on:
push:
pull_request:
jobs:
eslint:
name: ESLint
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Install node v14
uses: actions/setup-node@v2
with:
node-version: '14'
- name: Install dependencies
run: npm install
- name: Run ESLint
run: ./node_modules/.bin/eslint .

39
.github/workflows/update.yml vendored Normal file
View File

@@ -0,0 +1,39 @@
name: Update
on:
schedule:
- cron: "0/15 * * * *"
workflow_dispatch:
jobs:
update:
runs-on: ubuntu-latest
defaults:
run:
working-directory: ./tools/version-checker
steps:
- uses: actions/checkout@v2
- name: Install node v16
uses: actions/setup-node@v2
with:
node-version: '16'
- name: Install dependencies
run: npm install
- name: Run Updater
run: ./update-version
- name: Store WA Version
run: echo WA_VERSION=`cat ./.version` >> $GITHUB_ENV
- name: Create Pull Request
uses: peter-evans/create-pull-request@v3
with:
branch: auto-wa-web-update/patch
delete-branch: true
commit-message: Update supported WhatsApp Web version to v${{ env.WA_VERSION }}
title: Update WhatsApp Web Version (${{ env.WA_VERSION }})
body: |
A new version of WhatsApp Web has been detected!
Tests should be run against this new version before merging.
labels: WhatsApp Change
reviewers: pedroslopez

10
.gitignore vendored
View File

@@ -36,6 +36,10 @@ build/Release
node_modules/
jspm_packages/
# Lock files
package-lock.json
yarn.lock
# TypeScript v1 declaration files
typings/
@@ -59,3 +63,9 @@ typings/
# next.js build output
.next
# macOS Thumbnails
._*
# Test sessions
*session.json

26
.jsdoc.json Normal file
View File

@@ -0,0 +1,26 @@
{
"tags": {
"allowUnknownTags": true,
"dictionaries": ["jsdoc"]
},
"source": {
"include": ["src", "package.json", "README.md"],
"includePattern": ".js$",
"excludePattern": "(node_modules/|docs)"
},
"plugins": [
"plugins/markdown"
],
"templates": {
"cleverLinks": false,
"monospaceLinks": true,
"useLongnameInNav": false,
"showInheritedInNav": true
},
"opts": {
"destination": "./docs/",
"encoding": "utf8",
"recurse": true,
"template": "./node_modules/jsdoc-baseline"
}
}

17
.npmignore Normal file
View File

@@ -0,0 +1,17 @@
docs/*
.github/*
.eslintrc.json
.jsdoc.json
.editorconfig
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
*session.json
.env
tools/
tests/

132
README.md
View File

@@ -1,4 +1,5 @@
[![npm](https://img.shields.io/npm/v/whatsapp-web.js.svg)](https://www.npmjs.com/package/whatsapp-web.js)
[![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.14](https://img.shields.io/badge/WhatsApp_Web-2.2126.14-brightgreen.svg) [![Discord Chat](https://img.shields.io/discord/698610475432411196.svg?logo=discord)](https://discord.gg/H7DqQs4)
# whatsapp-web.js
A WhatsApp API client that connects through the WhatsApp Web browser app
@@ -6,8 +7,133 @@ It uses Puppeteer to run a real instance of Whatsapp Web to avoid getting blocke
**NOTE:** I can't guarantee you will not be blocked by using this method, although it has worked for me. WhatsApp does not allow bots or unofficial clients on their platform, so this shouldn't be considered totally safe.
This is still very much a work in progress, but you can check out [example.js](./example.js) to see how to read and send messages.
## Installation
The module is now available on npm! `npm i whatsapp-web.js`
Please note that Node v12+ is required.
## Example usage
```js
const { Client } = require('whatsapp-web.js');
const client = new Client();
client.on('qr', (qr) => {
// Generate and scan this code with your phone
console.log('QR RECEIVED', qr);
});
client.on('ready', () => {
console.log('Client is ready!');
});
client.on('message', msg => {
if (msg.body == '!ping') {
msg.reply('pong');
}
});
client.initialize();
```
Take a look at [example.js](https://github.com/pedroslopez/whatsapp-web.js/blob/master/example.js) for another example with more use cases.
## Remote Access
You could also connect to any previously existing browser instance:
```js
const client = new Client({
puppeteer: {
browserWSEndpoint: `ws://localhost:3000`
}
});
```
### Docker
1) Installing a browser using browserless:
```
docker run \
--rm \
-p 3000:3000 \
-e "MAX_CONCURRENT_SESSIONS=1" \
browserless/chrome:latest
```
Reference: https://docs.browserless.io/docs/docker-quickstart.html
### Remote Debugging
2) Running a browser with websocket remote debugging enabled:
> chrome.exe --remote-debugging-port=9222
After that check the following webpage and check http://127.0.0.1:9220/json and get the **webSocketDebuggerUrl**
## Supported features
| Feature | Status |
| ------------- | ------------- |
| Send messages | ✅ |
| Receive messages | ✅ |
| Send media (images/audio/documents) | ✅ |
| Send media (video) | ✅ [(requires google chrome)](https://guide.wwebjs.dev/features/handling-attachments#caveat-for-sending-videos-and-gifs) |
| Send stickers | ✅ |
| Receive media (images/audio/video/documents) | ✅ |
| Send contact cards | ✅ |
| Send location | ✅ |
| Receive location | ✅ |
| Message replies | ✅ |
| Join groups by invite | ✅ |
| Get invite for group | ✅ |
| Modify group info (subject, description) | ✅ |
| Modify group settings (send messages, edit info) | ✅ |
| Add group participants | ✅ |
| Kick group participants | ✅ |
| Promote/demote group participants | ✅ |
| Mention users | ✅ |
| Mute/unmute chats | ✅ |
| Block/unblock contacts | ✅ |
| Get contact info | ✅ |
| Get profile pictures | ✅ |
| Set user status message | ✅ |
Something missing? Make an issue and let us know!
## Links
* [Reference](https://docs.wwebjs.dev/)
* [Guide](https://guide.wwebjs.dev/) _(work in progress)_
* [GitHub](https://github.com/pedroslopez/whatsapp-web.js)
* [npm](https://npmjs.org/package/whatsapp-web.js)
## Contributing
Pull requests are welcome! If you see something you'd like to add, please do. For drastic changes, please open an issue first.
## Donating
You can support the maintainer of this project through the link below
[![Support via PayPal](https://cdn.rawgit.com/twolfson/paypal-github-button/1.0.0/dist/button.svg)](https://www.paypal.me/psla/)
## Disclaimer
This project is not affiliated, associated, authorized, endorsed by, or in any way officially connected with WhatsApp or any of its subsidiaries or its affiliates. The official WhatsApp website can be found at https://whatsapp.com. "WhatsApp" as well as related names, marks, emblems and images are registered trademarks of their respective owners.
## License
Copyright 2019 Pedro S Lopez
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this project except in compliance with the License.
You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0.
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

65
docs/Base.html Normal file
View File

@@ -0,0 +1,65 @@
<!doctype html>
<html>
<head>
<meta name="generator" content="JSDoc 3.6.7">
<meta charset="utf-8">
<title>whatsapp-web.js 1.14.1 &raquo; Class: Base</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>1</a>
</div>
</div>
</nav>
<div id="jsdoc-body-container">
<div id="jsdoc-content">
<div id="jsdoc-content-container">
<div id="jsdoc-main" role="main">
<header class="page-header">
<div class="symbol-detail-labels"><span class="label label-kind">class</span></div>
<h1><small></small><span class="symbol-name">Base</span></h1>
<p class="source-link">Source: <a href="structures_Base.js.html#source-line-6">structures/<wbr>Base.<wbr>js:6</a></p>
<div class="symbol-classdesc">
<p>Represents a WhatsApp data structure</p>
</div>
<dl class="dl-compact">
</dl>
</header>
<section id="summary">
</section>
<section>
<h2 id="Base">new&nbsp;<span class="symbol-name">Base</span><span class="signature"><span class="signature-params">()</span></span></h2>
<dl class="dl-compact">
</dl>
</section>
<section>
</section>
</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 September 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>

305
docs/BusinessContact.html Normal file
View File

@@ -0,0 +1,305 @@
<!doctype html>
<html>
<head>
<meta name="generator" content="JSDoc 3.6.7">
<meta charset="utf-8">
<title>whatsapp-web.js 1.14.1 &raquo; Class: BusinessContact</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>1</a>
</div>
</div>
</nav>
<div id="jsdoc-body-container">
<div id="jsdoc-content">
<div id="jsdoc-content-container">
<div id="jsdoc-main" role="main">
<header class="page-header">
<div class="symbol-detail-labels"><span class="label label-kind">class</span></div>
<h1><small></small><span class="symbol-name">BusinessContact</span></h1>
<p class="source-link">Source: <a href="structures_BusinessContact.js.html#source-line-9">structures/<wbr>BusinessContact.<wbr>js:9</a></p>
<div class="symbol-classdesc">
<p>Represents a Business Contact on WhatsApp</p>
</div>
<dl class="dl-compact">
</dl>
</header>
<section id="summary">
<div class="summary-callout">
<h2 class="summary-callout-heading">Properties</h2>
<div class="summary-content">
<div class="summary-column">
<dl class="dl-summary-callout">
<dt><a href="BusinessContact.html#businessProfile">businessProfile</a></dt>
<dd>
</dd>
<dt><a href="BusinessContact.html#id">id</a></dt>
<dd>
</dd>
<dt><a href="BusinessContact.html#isBlocked">isBlocked</a></dt>
<dd>
</dd>
<dt><a href="BusinessContact.html#isBusiness">isBusiness</a></dt>
<dd>
</dd>
<dt><a href="BusinessContact.html#isEnterprise">isEnterprise</a></dt>
<dd>
</dd>
</dl>
</div>
<div class="summary-column">
<dl class="dl-summary-callout">
<dt><a href="BusinessContact.html#isGroup">isGroup</a></dt>
<dd>
</dd>
<dt><a href="BusinessContact.html#isMe">isMe</a></dt>
<dd>
</dd>
<dt><a href="BusinessContact.html#isMyContact">isMyContact</a></dt>
<dd>
</dd>
<dt><a href="BusinessContact.html#isUser">isUser</a></dt>
<dd>
</dd>
<dt><a href="BusinessContact.html#isWAContact">isWAContact</a></dt>
<dd>
</dd>
</dl>
</div>
<div class="summary-column">
<dl class="dl-summary-callout">
<dt><a href="BusinessContact.html#name">name</a></dt>
<dd>
</dd>
<dt><a href="BusinessContact.html#number">number</a></dt>
<dd>
</dd>
<dt><a href="BusinessContact.html#pushname">pushname</a></dt>
<dd>
</dd>
<dt><a href="BusinessContact.html#shortName">shortName</a></dt>
<dd>
</dd>
</dl>
</div>
</div>
</div>
<div class="summary-callout">
<h2 class="summary-callout-heading">Methods</h2>
<div class="summary-content">
<div class="summary-column">
<dl class="dl-summary-callout">
<dt><a href="BusinessContact.html#block">block()</a></dt>
<dd>
</dd>
<dt><a href="BusinessContact.html#getAbout">getAbout()</a></dt>
<dd>
</dd>
</dl>
</div>
<div class="summary-column">
<dl class="dl-summary-callout">
<dt><a href="BusinessContact.html#getChat">getChat()</a></dt>
<dd>
</dd>
<dt><a href="BusinessContact.html#getProfilePicUrl">getProfilePicUrl()</a></dt>
<dd>
</dd>
</dl>
</div>
<div class="summary-column">
<dl class="dl-summary-callout">
<dt><a href="BusinessContact.html#unblock">unblock()</a></dt>
<dd>
</dd>
</dl>
</div>
</div>
</div>
</section>
<section>
<h2 id="BusinessContact">new&nbsp;<span class="symbol-name">BusinessContact</span><span class="signature"><span class="signature-params">()</span></span></h2>
<dl class="dl-compact">
<dt>Extends</dt>
<dd><a href="Contact.html">Contact</a></dd>
</dl>
</section>
<section>
<h2>Properties</h2>
<section>
<h3 id="businessProfile"><span class="symbol-name">businessProfile</span></h3>
<p>The contact's business profile</p>
<dl class="dl-compact">
</dl>
<h3 id="id"><span class="symbol-name">id</span><small class="property-type">
&nbsp;unknown</small></h3>
<p>ID that represents the contact</p>
<dl class="dl-compact">
<dt>Inherited from</dt>
<dd><a href="Contact.html#id">Contact#id</a></dd>
</dl>
<h3 id="isBlocked"><span class="symbol-name">isBlocked</span><small class="property-type">
&nbsp;unknown</small></h3>
<p>Indicates if you have blocked this contact</p>
<dl class="dl-compact">
<dt>Inherited from</dt>
<dd><a href="Contact.html#isBlocked">Contact#isBlocked</a></dd>
</dl>
<h3 id="isBusiness"><span class="symbol-name">isBusiness</span><small class="property-type">
&nbsp;unknown</small></h3>
<p>Indicates if the contact is a business contact</p>
<dl class="dl-compact">
<dt>Inherited from</dt>
<dd><a href="Contact.html#isBusiness">Contact#isBusiness</a></dd>
</dl>
<h3 id="isEnterprise"><span class="symbol-name">isEnterprise</span><small class="property-type">
&nbsp;unknown</small></h3>
<p>Indicates if the contact is an enterprise contact</p>
<dl class="dl-compact">
<dt>Inherited from</dt>
<dd><a href="Contact.html#isEnterprise">Contact#isEnterprise</a></dd>
</dl>
<h3 id="isGroup"><span class="symbol-name">isGroup</span><small class="property-type">
&nbsp;unknown</small></h3>
<p>Indicates if the contact is a group contact</p>
<dl class="dl-compact">
<dt>Inherited from</dt>
<dd><a href="Contact.html#isGroup">Contact#isGroup</a></dd>
</dl>
<h3 id="isMe"><span class="symbol-name">isMe</span><small class="property-type">
&nbsp;unknown</small></h3>
<p>Indicates if the contact is the current user's contact</p>
<dl class="dl-compact">
<dt>Inherited from</dt>
<dd><a href="Contact.html#isMe">Contact#isMe</a></dd>
</dl>
<h3 id="isMyContact"><span class="symbol-name">isMyContact</span><small class="property-type">
&nbsp;unknown</small></h3>
<p>Indicates if the number is saved in the current phone's contacts</p>
<dl class="dl-compact">
<dt>Inherited from</dt>
<dd><a href="Contact.html#isMyContact">Contact#isMyContact</a></dd>
</dl>
<h3 id="isUser"><span class="symbol-name">isUser</span><small class="property-type">
&nbsp;unknown</small></h3>
<p>Indicates if the contact is a user contact</p>
<dl class="dl-compact">
<dt>Inherited from</dt>
<dd><a href="Contact.html#isUser">Contact#isUser</a></dd>
</dl>
<h3 id="isWAContact"><span class="symbol-name">isWAContact</span><small class="property-type">
&nbsp;unknown</small></h3>
<p>Indicates if the number is registered on WhatsApp</p>
<dl class="dl-compact">
<dt>Inherited from</dt>
<dd><a href="Contact.html#isWAContact">Contact#isWAContact</a></dd>
</dl>
<h3 id="name"><span class="symbol-name">name</span><small class="property-type">
&nbsp;unknown</small></h3>
<p>The contact's name, as saved by the current user</p>
<dl class="dl-compact">
<dt>Inherited from</dt>
<dd><a href="Contact.html#name">Contact#name</a></dd>
</dl>
<h3 id="number"><span class="symbol-name">number</span><small class="property-type">
&nbsp;unknown</small></h3>
<p>Contact's phone number</p>
<dl class="dl-compact">
<dt>Inherited from</dt>
<dd><a href="Contact.html#number">Contact#number</a></dd>
</dl>
<h3 id="pushname"><span class="symbol-name">pushname</span><small class="property-type">
&nbsp;unknown</small></h3>
<p>The name that the contact has configured to be shown publically</p>
<dl class="dl-compact">
<dt>Inherited from</dt>
<dd><a href="Contact.html#pushname">Contact#pushname</a></dd>
</dl>
<h3 id="shortName"><span class="symbol-name">shortName</span><small class="property-type">
&nbsp;unknown</small></h3>
<p>A shortened version of name</p>
<dl class="dl-compact">
<dt>Inherited from</dt>
<dd><a href="Contact.html#shortName">Contact#shortName</a></dd>
</dl>
</section>
<h2>Methods</h2>
<section>
<div class="symbol-detail-labels"><span class="label label-async">async</span></div>
<h3 id="block"><span class="symbol-name">block</span><span class="signature"><span class="signature-params">()</span>&nbsp;&rarr; <span class="signature-returns"> Promise containing boolean</span></span></h3>
<p>Blocks this contact from WhatsApp</p>
<dl class="dl-compact">
<dt>Inherited from</dt>
<dd><a href="Contact.html#block">Contact#block</a></dd>
<dt>Returns</dt>
<dd></dd>
</dl>
<div class="symbol-detail-labels"><span class="label label-async">async</span></div>
<h3 id="getAbout"><span class="symbol-name">getAbout</span><span class="signature"><span class="signature-params">()</span>&nbsp;&rarr; <span class="signature-returns"> Promise containing nullable string</span></span></h3>
<p>Gets the Contact's current &quot;about&quot; info. Returns null if you don't have permission to read their status.</p>
<dl class="dl-compact">
<dt>Inherited from</dt>
<dd><a href="Contact.html#getAbout">Contact#getAbout</a></dd>
<dt>Returns</dt>
<dd></dd>
</dl>
<div class="symbol-detail-labels"><span class="label label-async">async</span></div>
<h3 id="getChat"><span class="symbol-name">getChat</span><span class="signature"><span class="signature-params">()</span>&nbsp;&rarr; <span class="signature-returns"> Promise containing <a href="Chat.html">Chat</a></span></span></h3>
<p>Returns the Chat that corresponds to this Contact.
Will return null when getting chat for currently logged in user.</p>
<dl class="dl-compact">
<dt>Inherited from</dt>
<dd><a href="Contact.html#getChat">Contact#getChat</a></dd>
<dt>Returns</dt>
<dd></dd>
</dl>
<div class="symbol-detail-labels"><span class="label label-async">async</span></div>
<h3 id="getProfilePicUrl"><span class="symbol-name">getProfilePicUrl</span><span class="signature"><span class="signature-params">()</span>&nbsp;&rarr; <span class="signature-returns"> Promise containing string</span></span></h3>
<p>Returns the contact's profile picture URL, if privacy settings allow it</p>
<dl class="dl-compact">
<dt>Inherited from</dt>
<dd><a href="Contact.html#getProfilePicUrl">Contact#getProfilePicUrl</a></dd>
<dt>Returns</dt>
<dd></dd>
</dl>
<div class="symbol-detail-labels"><span class="label label-async">async</span></div>
<h3 id="unblock"><span class="symbol-name">unblock</span><span class="signature"><span class="signature-params">()</span>&nbsp;&rarr; <span class="signature-returns"> Promise containing boolean</span></span></h3>
<p>Unblocks this contact from WhatsApp</p>
<dl class="dl-compact">
<dt>Inherited from</dt>
<dd><a href="Contact.html#unblock">Contact#unblock</a></dd>
<dt>Returns</dt>
<dd></dd>
</dl>
</section>
</section>
</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 September 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>

1
docs/CNAME Normal file
View File

@@ -0,0 +1 @@
docs.wwebjs.dev

159
docs/Call.html Normal file
View File

@@ -0,0 +1,159 @@
<!doctype html>
<html>
<head>
<meta name="generator" content="JSDoc 3.6.7">
<meta charset="utf-8">
<title>whatsapp-web.js 1.14.1 &raquo; Class: Call</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>1</a>
</div>
</div>
</nav>
<div id="jsdoc-body-container">
<div id="jsdoc-content">
<div id="jsdoc-content-container">
<div id="jsdoc-main" role="main">
<header class="page-header">
<div class="symbol-detail-labels"><span class="label label-kind">class</span></div>
<h1><small></small><span class="symbol-name">Call</span></h1>
<p class="source-link">Source: <a href="structures_Call.js.html#source-line-9">structures/<wbr>Call.<wbr>js:9</a></p>
<div class="symbol-classdesc">
<p>Represents a Call on WhatsApp</p>
</div>
<dl class="dl-compact">
</dl>
</header>
<section id="summary">
<div class="summary-callout">
<h2 class="summary-callout-heading">Properties</h2>
<div class="summary-content">
<div class="summary-column">
<dl class="dl-summary-callout">
<dt><a href="Call.html#canHandleLocally">canHandleLocally</a></dt>
<dd>
</dd>
<dt><a href="Call.html#from">from</a></dt>
<dd>
</dd>
<dt><a href="Call.html#fromMe">fromMe</a></dt>
<dd>
</dd>
</dl>
</div>
<div class="summary-column">
<dl class="dl-summary-callout">
<dt><a href="Call.html#id">id</a></dt>
<dd>
</dd>
<dt><a href="Call.html#isGroup">isGroup</a></dt>
<dd>
</dd>
<dt><a href="Call.html#isVideo">isVideo</a></dt>
<dd>
</dd>
</dl>
</div>
<div class="summary-column">
<dl class="dl-summary-callout">
<dt><a href="Call.html#participants">participants</a></dt>
<dd>
</dd>
<dt><a href="Call.html#timestamp">timestamp</a></dt>
<dd>
</dd>
<dt><a href="Call.html#webClientShouldHandle">webClientShouldHandle</a></dt>
<dd>
</dd>
</dl>
</div>
</div>
</div>
</section>
<section>
<h2 id="Call">new&nbsp;<span class="symbol-name">Call</span><span class="signature"><span class="signature-params">()</span></span></h2>
<dl class="dl-compact">
<dt>Extends</dt>
<dd><a href="Base.html">Base</a></dd>
</dl>
</section>
<section>
<h2>Properties</h2>
<section>
<h3 id="canHandleLocally"><span class="symbol-name">canHandleLocally</span><small class="property-type">
&nbsp;boolean</small></h3>
<p>Indicates if the call can be handled in waweb</p>
<dl class="dl-compact">
</dl>
<h3 id="from"><span class="symbol-name">from</span><small class="property-type">
&nbsp;string</small></h3>
<p>From</p>
<dl class="dl-compact">
</dl>
<h3 id="fromMe"><span class="symbol-name">fromMe</span><small class="property-type">
&nbsp;boolean</small></h3>
<p>Indicates if the call was sent by the current user</p>
<dl class="dl-compact">
</dl>
<h3 id="id"><span class="symbol-name">id</span><small class="property-type">
&nbsp;string</small></h3>
<p>Call ID</p>
<dl class="dl-compact">
</dl>
<h3 id="isGroup"><span class="symbol-name">isGroup</span><small class="property-type">
&nbsp;boolean</small></h3>
<p>Is Group</p>
<dl class="dl-compact">
</dl>
<h3 id="isVideo"><span class="symbol-name">isVideo</span><small class="property-type">
&nbsp;boolean</small></h3>
<p>Is video</p>
<dl class="dl-compact">
</dl>
<h3 id="participants"><span class="symbol-name">participants</span><small class="property-type">
&nbsp;object</small></h3>
<p>Object with participants</p>
<dl class="dl-compact">
</dl>
<h3 id="timestamp"><span class="symbol-name">timestamp</span><small class="property-type">
&nbsp;number</small></h3>
<p>Unix timestamp for when the call was created</p>
<dl class="dl-compact">
</dl>
<h3 id="webClientShouldHandle"><span class="symbol-name">webClientShouldHandle</span><small class="property-type">
&nbsp;boolean</small></h3>
<p>Indicates if the call Should be handled in waweb</p>
<dl class="dl-compact">
</dl>
</section>
</section>
</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 September 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>

492
docs/Chat.html Normal file
View File

@@ -0,0 +1,492 @@
<!doctype html>
<html>
<head>
<meta name="generator" content="JSDoc 3.6.7">
<meta charset="utf-8">
<title>whatsapp-web.js 1.14.1 &raquo; Class: Chat</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>1</a>
</div>
</div>
</nav>
<div id="jsdoc-body-container">
<div id="jsdoc-content">
<div id="jsdoc-content-container">
<div id="jsdoc-main" role="main">
<header class="page-header">
<div class="symbol-detail-labels"><span class="label label-kind">class</span></div>
<h1><small></small><span class="symbol-name">Chat</span></h1>
<p class="source-link">Source: <a href="structures_Chat.js.html#source-line-10">structures/<wbr>Chat.<wbr>js:10</a></p>
<div class="symbol-classdesc">
<p>Represents a Chat on WhatsApp</p>
</div>
<dl class="dl-compact">
</dl>
</header>
<section id="summary">
<div class="summary-callout">
<h2 class="summary-callout-heading">Properties</h2>
<div class="summary-content">
<div class="summary-column">
<dl class="dl-summary-callout">
<dt><a href="Chat.html#archived">archived</a></dt>
<dd>
</dd>
<dt><a href="Chat.html#id">id</a></dt>
<dd>
</dd>
<dt><a href="Chat.html#isGroup">isGroup</a></dt>
<dd>
</dd>
<dt><a href="Chat.html#isMuted">isMuted</a></dt>
<dd>
</dd>
</dl>
</div>
<div class="summary-column">
<dl class="dl-summary-callout">
<dt><a href="Chat.html#isReadOnly">isReadOnly</a></dt>
<dd>
</dd>
<dt><a href="Chat.html#muteExpiration">muteExpiration</a></dt>
<dd>
</dd>
<dt><a href="Chat.html#name">name</a></dt>
<dd>
</dd>
<dt><a href="Chat.html#pinned">pinned</a></dt>
<dd>
</dd>
</dl>
</div>
<div class="summary-column">
<dl class="dl-summary-callout">
<dt><a href="Chat.html#timestamp">timestamp</a></dt>
<dd>
</dd>
<dt><a href="Chat.html#unreadCount">unreadCount</a></dt>
<dd>
</dd>
</dl>
</div>
</div>
</div>
<div class="summary-callout">
<h2 class="summary-callout-heading">Methods</h2>
<div class="summary-content">
<div class="summary-column">
<dl class="dl-summary-callout">
<dt><a href="Chat.html#archive">archive()</a></dt>
<dd>
</dd>
<dt><a href="Chat.html#clearMessages">clearMessages()</a></dt>
<dd>
</dd>
<dt><a href="Chat.html#clearState">clearState()</a></dt>
<dd>
</dd>
<dt><a href="Chat.html#delete">delete()</a></dt>
<dd>
</dd>
<dt><a href="Chat.html#fetchMessages">fetchMessages(searchOptions)</a></dt>
<dd>
</dd>
<dt><a href="Chat.html#getContact">getContact()</a></dt>
<dd>
</dd>
</dl>
</div>
<div class="summary-column">
<dl class="dl-summary-callout">
<dt><a href="Chat.html#getLabels">getLabels()</a></dt>
<dd>
</dd>
<dt><a href="Chat.html#markUnread">markUnread()</a></dt>
<dd>
</dd>
<dt><a href="Chat.html#mute">mute(unmuteDate)</a></dt>
<dd>
</dd>
<dt><a href="Chat.html#pin">pin()</a></dt>
<dd>
</dd>
<dt><a href="Chat.html#sendMessage">sendMessage(content[, options])</a></dt>
<dd>
</dd>
<dt><a href="Chat.html#sendSeen">sendSeen()</a></dt>
<dd>
</dd>
</dl>
</div>
<div class="summary-column">
<dl class="dl-summary-callout">
<dt><a href="Chat.html#sendStateRecording">sendStateRecording()</a></dt>
<dd>
</dd>
<dt><a href="Chat.html#sendStateTyping">sendStateTyping()</a></dt>
<dd>
</dd>
<dt><a href="Chat.html#unarchive">unarchive()</a></dt>
<dd>
</dd>
<dt><a href="Chat.html#unmute">unmute()</a></dt>
<dd>
</dd>
<dt><a href="Chat.html#unpin">unpin()</a></dt>
<dd>
</dd>
</dl>
</div>
</div>
</div>
</section>
<section>
<h2 id="Chat">new&nbsp;<span class="symbol-name">Chat</span><span class="signature"><span class="signature-params">()</span></span></h2>
<dl class="dl-compact">
<dt>Extends</dt>
<dd><a href="Base.html">Base</a></dd>
</dl>
</section>
<section>
<h2>Properties</h2>
<section>
<h3 id="archived"><span class="symbol-name">archived</span><small class="property-type">
&nbsp;boolean</small></h3>
<p>Indicates if the Chat is archived</p>
<dl class="dl-compact">
</dl>
<h3 id="id"><span class="symbol-name">id</span><small class="property-type">
&nbsp;object</small></h3>
<p>ID that represents the chat</p>
<dl class="dl-compact">
</dl>
<h3 id="isGroup"><span class="symbol-name">isGroup</span><small class="property-type">
&nbsp;boolean</small></h3>
<p>Indicates if the Chat is a Group Chat</p>
<dl class="dl-compact">
</dl>
<h3 id="isMuted"><span class="symbol-name">isMuted</span><small class="property-type">
&nbsp;number</small></h3>
<p>Indicates if the chat is muted or not</p>
<dl class="dl-compact">
</dl>
<h3 id="isReadOnly"><span class="symbol-name">isReadOnly</span><small class="property-type">
&nbsp;boolean</small></h3>
<p>Indicates if the Chat is readonly</p>
<dl class="dl-compact">
</dl>
<h3 id="muteExpiration"><span class="symbol-name">muteExpiration</span><small class="property-type">
&nbsp;number</small></h3>
<p>Unix timestamp for when the mute expires</p>
<dl class="dl-compact">
</dl>
<h3 id="name"><span class="symbol-name">name</span><small class="property-type">
&nbsp;string</small></h3>
<p>Title of the chat</p>
<dl class="dl-compact">
</dl>
<h3 id="pinned"><span class="symbol-name">pinned</span><small class="property-type">
&nbsp;boolean</small></h3>
<p>Indicates if the Chat is pinned</p>
<dl class="dl-compact">
</dl>
<h3 id="timestamp"><span class="symbol-name">timestamp</span><small class="property-type">
&nbsp;number</small></h3>
<p>Unix timestamp for when the last activity occurred</p>
<dl class="dl-compact">
</dl>
<h3 id="unreadCount"><span class="symbol-name">unreadCount</span><small class="property-type">
&nbsp;number</small></h3>
<p>Amount of messages unread</p>
<dl class="dl-compact">
</dl>
</section>
<h2>Methods</h2>
<section>
<div class="symbol-detail-labels"><span class="label label-async">async</span></div>
<h3 id="archive"><span class="symbol-name">archive</span><span class="signature"><span class="signature-params">()</span></span></h3>
<p>Archives this chat</p>
<dl class="dl-compact">
</dl>
<div class="symbol-detail-labels"><span class="label label-async">async</span></div>
<h3 id="clearMessages"><span class="symbol-name">clearMessages</span><span class="signature"><span class="signature-params">()</span>&nbsp;&rarr; <span class="signature-returns"> Promise containing Boolean</span></span></h3>
<p>Clears all messages from the chat</p>
<dl class="dl-compact">
<dt>Returns</dt>
<dd>
<p><code>Promise containing Boolean</code> <p>result</p>
</p>
</dd>
</dl>
<div class="symbol-detail-labels"><span class="label label-async">async</span></div>
<h3 id="clearState"><span class="symbol-name">clearState</span><span class="signature"><span class="signature-params">()</span></span></h3>
<p>Stops typing or recording in chat immediately.</p>
<dl class="dl-compact">
</dl>
<div class="symbol-detail-labels"><span class="label label-async">async</span></div>
<h3 id="delete"><span class="symbol-name">delete</span><span class="signature"><span class="signature-params">()</span>&nbsp;&rarr; <span class="signature-returns"> Promise containing Boolean</span></span></h3>
<p>Deletes the chat</p>
<dl class="dl-compact">
<dt>Returns</dt>
<dd>
<p><code>Promise containing Boolean</code> <p>result</p>
</p>
</dd>
</dl>
<div class="symbol-detail-labels"><span class="label label-async">async</span></div>
<h3 id="fetchMessages"><span class="symbol-name">fetchMessages</span><span class="signature"><span class="signature-params">(searchOptions)</span>&nbsp;&rarr; <span class="signature-returns"> Promise containing Array of <a href="Message.html">Message</a></span></span></h3>
<p>Loads chat messages, sorted from earliest to latest.</p>
<section>
<h4>Parameters</h4>
<table class="jsdoc-details-table">
<thead>
<tr>
<th>Name</th>
<th>Type</th>
<th>Optional</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<p>searchOptions</p>
</td>
<td>
<p>Object</p>
</td>
<td>
<p>&nbsp;</p>
</td>
<td>
<p>Options for searching messages. Right now only limit is supported.</p>
<p>Values in <code>searchOptions</code> have the following properties:</p>
<table class="jsdoc-details-table">
<thead>
<tr>
<th>Name</th>
<th>Type</th>
<th>Optional</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<p>limit</p>
</td>
<td>
<p>Number</p>
</td>
<td>
<p>Yes</p>
</td>
<td>
<p>The amount of messages to return. Note that the actual number of returned messages may be smaller if there aren't enough messages in the conversation. Set this to Infinity to load all messages.</p>
<p>Defaults to <code>50</code>.</p>
</td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
</section>
<dl class="dl-compact">
<dt>Returns</dt>
<dd>
<p><code>Promise containing Array of <a href="Message.html">Message</a></code> </p>
</dd>
</dl>
<div class="symbol-detail-labels"><span class="label label-async">async</span></div>
<h3 id="getContact"><span class="symbol-name">getContact</span><span class="signature"><span class="signature-params">()</span>&nbsp;&rarr; <span class="signature-returns"> Promise containing <a href="Contact.html">Contact</a></span></span></h3>
<p>Returns the Contact that corresponds to this Chat.</p>
<dl class="dl-compact">
<dt>Returns</dt>
<dd>
<p><code>Promise containing <a href="Contact.html">Contact</a></code> </p>
</dd>
</dl>
<div class="symbol-detail-labels"><span class="label label-async">async</span></div>
<h3 id="getLabels"><span class="symbol-name">getLabels</span><span class="signature"><span class="signature-params">()</span>&nbsp;&rarr; <span class="signature-returns"> Promise containing Array of <a href="Label.html">Label</a></span></span></h3>
<p>Returns array of all Labels assigned to this Chat</p>
<dl class="dl-compact">
<dt>Returns</dt>
<dd>
<p><code>Promise containing Array of <a href="Label.html">Label</a></code> </p>
</dd>
</dl>
<div class="symbol-detail-labels"><span class="label label-async">async</span></div>
<h3 id="markUnread"><span class="symbol-name">markUnread</span><span class="signature"><span class="signature-params">()</span></span></h3>
<p>Mark this chat as unread</p>
<dl class="dl-compact">
</dl>
<div class="symbol-detail-labels"><span class="label label-async">async</span></div>
<h3 id="mute"><span class="symbol-name">mute</span><span class="signature"><span class="signature-params">(unmuteDate)</span></span></h3>
<p>Mutes this chat until a specified date</p>
<section>
<h4>Parameter</h4>
<table class="jsdoc-details-table">
<thead>
<tr>
<th>Name</th>
<th>Type</th>
<th>Optional</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<p>unmuteDate</p>
</td>
<td>
<p>Date</p>
</td>
<td>
<p>&nbsp;</p>
</td>
<td>
<p>Date at which the Chat will be unmuted</p>
</td>
</tr>
</tbody>
</table>
</section>
<dl class="dl-compact">
</dl>
<div class="symbol-detail-labels"><span class="label label-async">async</span></div>
<h3 id="pin"><span class="symbol-name">pin</span><span class="signature"><span class="signature-params">()</span>&nbsp;&rarr; <span class="signature-returns"> Promise containing boolean</span></span></h3>
<p>Pins this chat</p>
<dl class="dl-compact">
<dt>Returns</dt>
<dd>
<p><code>Promise containing boolean</code> <p>New pin state. Could be false if the max number of pinned chats was reached.</p>
</p>
</dd>
</dl>
<div class="symbol-detail-labels"><span class="label label-async">async</span></div>
<h3 id="sendMessage"><span class="symbol-name">sendMessage</span><span class="signature"><span class="signature-params">(content[, options])</span>&nbsp;&rarr; <span class="signature-returns"> Promise containing <a href="Message.html">Message</a></span></span></h3>
<p>Send a message to this chat</p>
<section>
<h4>Parameters</h4>
<table class="jsdoc-details-table">
<thead>
<tr>
<th>Name</th>
<th>Type</th>
<th>Optional</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<p>content</p>
</td>
<td>
<p>(string, <a href="MessageMedia.html">MessageMedia</a>, or <a href="Location.html">Location</a>)</p>
</td>
<td>
<p>&nbsp;</p>
</td>
<td>
</td>
</tr>
<tr>
<td>
<p>options</p>
</td>
<td>
<p><a href="global.html#MessageSendOptions">MessageSendOptions</a></p>
</td>
<td>
<p>Yes</p>
</td>
<td>
</td>
</tr>
</tbody>
</table>
</section>
<dl class="dl-compact">
<dt>Returns</dt>
<dd>
<p><code>Promise containing <a href="Message.html">Message</a></code> <p>Message that was just sent</p>
</p>
</dd>
</dl>
<div class="symbol-detail-labels"><span class="label label-async">async</span></div>
<h3 id="sendSeen"><span class="symbol-name">sendSeen</span><span class="signature"><span class="signature-params">()</span>&nbsp;&rarr; <span class="signature-returns"> Promise containing Boolean</span></span></h3>
<p>Set the message as seen</p>
<dl class="dl-compact">
<dt>Returns</dt>
<dd>
<p><code>Promise containing Boolean</code> <p>result</p>
</p>
</dd>
</dl>
<div class="symbol-detail-labels"><span class="label label-async">async</span></div>
<h3 id="sendStateRecording"><span class="symbol-name">sendStateRecording</span><span class="signature"><span class="signature-params">()</span></span></h3>
<p>Simulate recording audio in chat. This will last for 25 seconds.</p>
<dl class="dl-compact">
</dl>
<div class="symbol-detail-labels"><span class="label label-async">async</span></div>
<h3 id="sendStateTyping"><span class="symbol-name">sendStateTyping</span><span class="signature"><span class="signature-params">()</span></span></h3>
<p>Simulate typing in chat. This will last for 25 seconds.</p>
<dl class="dl-compact">
</dl>
<div class="symbol-detail-labels"><span class="label label-async">async</span></div>
<h3 id="unarchive"><span class="symbol-name">unarchive</span><span class="signature"><span class="signature-params">()</span></span></h3>
<p>un-archives this chat</p>
<dl class="dl-compact">
</dl>
<div class="symbol-detail-labels"><span class="label label-async">async</span></div>
<h3 id="unmute"><span class="symbol-name">unmute</span><span class="signature"><span class="signature-params">()</span></span></h3>
<p>Unmutes this chat</p>
<dl class="dl-compact">
</dl>
<div class="symbol-detail-labels"><span class="label label-async">async</span></div>
<h3 id="unpin"><span class="symbol-name">unpin</span><span class="signature"><span class="signature-params">()</span>&nbsp;&rarr; <span class="signature-returns"> Promise containing boolean</span></span></h3>
<p>Unpins this chat</p>
<dl class="dl-compact">
<dt>Returns</dt>
<dd>
<p><code>Promise containing boolean</code> <p>New pin state</p>
</p>
</dd>
</dl>
</section>
</section>
</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 September 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>

2313
docs/Client.html Normal file

File diff suppressed because it is too large Load Diff

990
docs/Client.js.html Normal file
View File

@@ -0,0 +1,990 @@
<!doctype html>
<html>
<head>
<meta name="generator" content="JSDoc 3.6.7">
<meta charset="utf-8">
<title>whatsapp-web.js 1.14.1 &raquo; Source: Client.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>1</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: Client.js</h1>
</header>
<article>
<pre class="prettyprint linenums"><code>&#x27;use strict&#x27;;
const EventEmitter &#x3D; require(&#x27;events&#x27;);
const puppeteer &#x3D; require(&#x27;puppeteer&#x27;);
const moduleRaid &#x3D; require(&#x27;@pedroslopez/moduleraid/moduleraid&#x27;);
const jsQR &#x3D; require(&#x27;jsqr&#x27;);
const Util &#x3D; require(&#x27;./util/Util&#x27;);
const InterfaceController &#x3D; require(&#x27;./util/InterfaceController&#x27;);
const { WhatsWebURL, DefaultOptions, Events, WAState } &#x3D; require(&#x27;./util/Constants&#x27;);
const { ExposeStore, LoadUtils } &#x3D; require(&#x27;./util/Injected&#x27;);
const ChatFactory &#x3D; require(&#x27;./factories/ChatFactory&#x27;);
const ContactFactory &#x3D; require(&#x27;./factories/ContactFactory&#x27;);
const { ClientInfo, Message, MessageMedia, Contact, Location, GroupNotification , Label, Call } &#x3D; require(&#x27;./structures&#x27;);
/**
* Starting point for interacting with the WhatsApp Web API
* @extends {EventEmitter}
* @param {object} options - Client options
* @param {number} options.authTimeoutMs - Timeout for authentication selector in puppeteer
* @param {object} options.puppeteer - Puppeteer launch options. View docs here: https://github.com/puppeteer/puppeteer/
* @param {number} options.qrRefreshIntervalMs - Refresh interval for qr code (how much time to wait before checking if the qr code has changed)
* @param {number} options.qrTimeoutMs - Timeout for qr code selector in puppeteer
* @param {string} options.restartOnAuthFail - Restart client with a new session (i.e. use null &#x27;session&#x27; var) if authentication fails
* @param {object} options.session - Whatsapp session to restore. If not set, will start a new session
* @param {string} options.session.WABrowserId
* @param {string} options.session.WASecretBundle
* @param {string} options.session.WAToken1
* @param {string} options.session.WAToken2
* @param {number} options.takeoverOnConflict - If another whatsapp web session is detected (another browser), take over the session in the current browser
* @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&#x27;s Content-Security-Policy.
*
* @fires Client#qr
* @fires Client#authenticated
* @fires Client#auth_failure
* @fires Client#ready
* @fires Client#message
* @fires Client#message_ack
* @fires Client#message_create
* @fires Client#message_revoke_me
* @fires Client#message_revoke_everyone
* @fires Client#media_uploaded
* @fires Client#group_join
* @fires Client#group_leave
* @fires Client#group_update
* @fires Client#disconnected
* @fires Client#change_state
* @fires Client#change_battery
*/
class Client extends EventEmitter {
constructor(options &#x3D; {}) {
super();
this.options &#x3D; Util.mergeDefault(DefaultOptions, options);
this.pupBrowser &#x3D; null;
this.pupPage &#x3D; null;
Util.setFfmpegPath(this.options.ffmpegPath);
}
/**
* Sets up events and requirements, kicks off authentication request
*/
async initialize() {
let [browser, page] &#x3D; [null, null];
if(this.options.puppeteer &amp;amp;&amp;amp; this.options.puppeteer.browserWSEndpoint) {
browser &#x3D; await puppeteer.connect(this.options.puppeteer);
page &#x3D; await browser.newPage();
} else {
browser &#x3D; await puppeteer.launch(this.options.puppeteer);
page &#x3D; (await browser.pages())[0];
}
page.setUserAgent(this.options.userAgent);
this.pupBrowser &#x3D; browser;
this.pupPage &#x3D; page;
if (this.options.session) {
await page.evaluateOnNewDocument(
session &#x3D;&gt; {
localStorage.clear();
localStorage.setItem(&#x27;WABrowserId&#x27;, session.WABrowserId);
localStorage.setItem(&#x27;WASecretBundle&#x27;, session.WASecretBundle);
localStorage.setItem(&#x27;WAToken1&#x27;, session.WAToken1);
localStorage.setItem(&#x27;WAToken2&#x27;, session.WAToken2);
}, this.options.session);
}
if(this.options.bypassCSP) {
await page.setBypassCSP(true);
}
await page.goto(WhatsWebURL, {
waitUntil: &#x27;load&#x27;,
timeout: 0,
});
const KEEP_PHONE_CONNECTED_IMG_SELECTOR &#x3D; &#x27;[data-asset-intro-image-light&#x3D;&quot;true&quot;], [data-asset-intro-image-dark&#x3D;&quot;true&quot;]&#x27;;
if (this.options.session) {
// Check if session restore was successfull
try {
await page.waitForSelector(KEEP_PHONE_CONNECTED_IMG_SELECTOR, { timeout: this.options.authTimeoutMs });
} catch (err) {
if (err.name &#x3D;&#x3D;&#x3D; &#x27;TimeoutError&#x27;) {
/**
* Emitted when there has been an error while trying to restore an existing session
* @event Client#auth_failure
* @param {string} message
*/
this.emit(Events.AUTHENTICATION_FAILURE, &#x27;Unable to log in. Are the session details valid?&#x27;);
browser.close();
if (this.options.restartOnAuthFail) {
// session restore failed so try again but without session to force new authentication
this.options.session &#x3D; null;
this.initialize();
}
return;
}
throw err;
}
} else {
const getQrCode &#x3D; async () &#x3D;&gt; {
// Check if retry button is present
var QR_RETRY_SELECTOR &#x3D; &#x27;div[data-ref] &gt; span &gt; button&#x27;;
var qrRetry &#x3D; await page.$(QR_RETRY_SELECTOR);
if (qrRetry) {
await qrRetry.click();
}
// Wait for QR Code
const QR_CANVAS_SELECTOR &#x3D; &#x27;canvas&#x27;;
await page.waitForSelector(QR_CANVAS_SELECTOR, { timeout: this.options.qrTimeoutMs });
const qrImgData &#x3D; await page.$eval(QR_CANVAS_SELECTOR, canvas &#x3D;&gt; [].slice.call(canvas.getContext(&#x27;2d&#x27;).getImageData(0, 0, 264, 264).data));
const qr &#x3D; jsQR(qrImgData, 264, 264).data;
/**
* Emitted when the QR code is received
* @event Client#qr
* @param {string} qr QR Code
*/
this.emit(Events.QR_RECEIVED, qr);
};
getQrCode();
this._qrRefreshInterval &#x3D; setInterval(getQrCode, this.options.qrRefreshIntervalMs);
// Wait for code scan
await page.waitForSelector(KEEP_PHONE_CONNECTED_IMG_SELECTOR, { timeout: 0 });
clearInterval(this._qrRefreshInterval);
this._qrRefreshInterval &#x3D; undefined;
}
await page.evaluate(ExposeStore, moduleRaid.toString());
// Get session tokens
const localStorage &#x3D; JSON.parse(await page.evaluate(() &#x3D;&gt; {
return JSON.stringify(window.localStorage);
}));
const session &#x3D; {
WABrowserId: localStorage.WABrowserId,
WASecretBundle: localStorage.WASecretBundle,
WAToken1: localStorage.WAToken1,
WAToken2: localStorage.WAToken2
};
/**
* Emitted when authentication is successful
* @event Client#authenticated
* @param {object} session Object containing session information. Can be used to restore the session.
* @param {string} session.WABrowserId
* @param {string} session.WASecretBundle
* @param {string} session.WAToken1
* @param {string} session.WAToken2
*/
this.emit(Events.AUTHENTICATED, session);
// Check window.Store Injection
await page.waitForFunction(&#x27;window.Store !&#x3D; undefined&#x27;);
//Load util functions (serializers, helper functions)
await page.evaluate(LoadUtils);
// Expose client info
/**
* Current connection information
* @type {ClientInfo}
*/
this.info &#x3D; new ClientInfo(this, await page.evaluate(() &#x3D;&gt; {
return window.Store.Conn.serialize();
}));
// Add InterfaceController
this.interface &#x3D; new InterfaceController(this);
// Register events
await page.exposeFunction(&#x27;onAddMessageEvent&#x27;, msg &#x3D;&gt; {
if (!msg.isNewMsg) return;
if (msg.type &#x3D;&#x3D;&#x3D; &#x27;gp2&#x27;) {
const notification &#x3D; new GroupNotification(this, msg);
if (msg.subtype &#x3D;&#x3D;&#x3D; &#x27;add&#x27; || msg.subtype &#x3D;&#x3D;&#x3D; &#x27;invite&#x27;) {
/**
* Emitted when a user joins the chat via invite link or is added by an admin.
* @event Client#group_join
* @param {GroupNotification} notification GroupNotification with more information about the action
*/
this.emit(Events.GROUP_JOIN, notification);
} else if (msg.subtype &#x3D;&#x3D;&#x3D; &#x27;remove&#x27; || msg.subtype &#x3D;&#x3D;&#x3D; &#x27;leave&#x27;) {
/**
* Emitted when a user leaves the chat or is removed by an admin.
* @event Client#group_leave
* @param {GroupNotification} notification GroupNotification with more information about the action
*/
this.emit(Events.GROUP_LEAVE, notification);
} else {
/**
* Emitted when group settings are updated, such as subject, description or picture.
* @event Client#group_update
* @param {GroupNotification} notification GroupNotification with more information about the action
*/
this.emit(Events.GROUP_UPDATE, notification);
}
return;
}
const message &#x3D; new Message(this, msg);
/**
* Emitted when a new message is created, which may include the current user&#x27;s own messages.
* @event Client#message_create
* @param {Message} message The message that was created
*/
this.emit(Events.MESSAGE_CREATE, message);
if (msg.id.fromMe) return;
/**
* Emitted when a new message is received.
* @event Client#message
* @param {Message} message The message that was received
*/
this.emit(Events.MESSAGE_RECEIVED, message);
});
let last_message;
await page.exposeFunction(&#x27;onChangeMessageTypeEvent&#x27;, (msg) &#x3D;&gt; {
if (msg.type &#x3D;&#x3D;&#x3D; &#x27;revoked&#x27;) {
const message &#x3D; new Message(this, msg);
let revoked_msg;
if (last_message &amp;amp;&amp;amp; msg.id.id &#x3D;&#x3D;&#x3D; last_message.id.id) {
revoked_msg &#x3D; new Message(this, last_message);
}
/**
* Emitted when a message is deleted for everyone in the chat.
* @event Client#message_revoke_everyone
* @param {Message} message The message that was revoked, in its current state. It will not contain the original message&#x27;s data.
* @param {?Message} revoked_msg The message that was revoked, before it was revoked. It will contain the message&#x27;s original data.
* Note that due to the way this data is captured, it may be possible that this param will be undefined.
*/
this.emit(Events.MESSAGE_REVOKED_EVERYONE, message, revoked_msg);
}
});
await page.exposeFunction(&#x27;onChangeMessageEvent&#x27;, (msg) &#x3D;&gt; {
if (msg.type !&#x3D;&#x3D; &#x27;revoked&#x27;) {
last_message &#x3D; msg;
}
});
await page.exposeFunction(&#x27;onRemoveMessageEvent&#x27;, (msg) &#x3D;&gt; {
if (!msg.isNewMsg) return;
const message &#x3D; new Message(this, msg);
/**
* Emitted when a message is deleted by the current user.
* @event Client#message_revoke_me
* @param {Message} message The message that was revoked
*/
this.emit(Events.MESSAGE_REVOKED_ME, message);
});
await page.exposeFunction(&#x27;onMessageAckEvent&#x27;, (msg, ack) &#x3D;&gt; {
const message &#x3D; new Message(this, msg);
/**
* Emitted when an ack event occurrs on message type.
* @event Client#message_ack
* @param {Message} message The message that was affected
* @param {MessageAck} ack The new ACK value
*/
this.emit(Events.MESSAGE_ACK, message, ack);
});
await page.exposeFunction(&#x27;onMessageMediaUploadedEvent&#x27;, (msg) &#x3D;&gt; {
const message &#x3D; new Message(this, msg);
/**
* Emitted when media has been uploaded for a message sent by the client.
* @event Client#media_uploaded
* @param {Message} message The message with media that was uploaded
*/
this.emit(Events.MEDIA_UPLOADED, message);
});
await page.exposeFunction(&#x27;onAppStateChangedEvent&#x27;, (state) &#x3D;&gt; {
/**
* Emitted when the connection state changes
* @event Client#change_state
* @param {WAState} state the new connection state
*/
this.emit(Events.STATE_CHANGED, state);
const ACCEPTED_STATES &#x3D; [WAState.CONNECTED, WAState.OPENING, WAState.PAIRING, WAState.TIMEOUT];
if (this.options.takeoverOnConflict) {
ACCEPTED_STATES.push(WAState.CONFLICT);
if (state &#x3D;&#x3D;&#x3D; WAState.CONFLICT) {
setTimeout(() &#x3D;&gt; {
this.pupPage.evaluate(() &#x3D;&gt; window.Store.AppState.takeover());
}, this.options.takeoverTimeoutMs);
}
}
if (!ACCEPTED_STATES.includes(state)) {
/**
* Emitted when the client has been disconnected
* @event Client#disconnected
* @param {WAState|&quot;NAVIGATION&quot;} reason reason that caused the disconnect
*/
this.emit(Events.DISCONNECTED, state);
this.destroy();
}
});
await page.exposeFunction(&#x27;onBatteryStateChangedEvent&#x27;, (state) &#x3D;&gt; {
const { battery, plugged } &#x3D; state;
if (battery &#x3D;&#x3D;&#x3D; undefined) return;
/**
* Emitted when the battery percentage for the attached device changes
* @event Client#change_battery
* @param {object} batteryInfo
* @param {number} batteryInfo.battery - The current battery percentage
* @param {boolean} batteryInfo.plugged - Indicates if the phone is plugged in (true) or not (false)
*/
this.emit(Events.BATTERY_CHANGED, { battery, plugged });
});
await page.exposeFunction(&#x27;onIncomingCall&#x27;, (call) &#x3D;&gt; {
/**
* Emitted when a call is received
* @event Client#incoming_call
* @param {object} call
* @param {number} call.id - Call id
* @param {string} call.peerJid - Who called
* @param {boolean} call.isVideo - if is video
* @param {boolean} call.isGroup - if is group
* @param {boolean} call.canHandleLocally - if we can handle in waweb
* @param {boolean} call.outgoing - if is outgoing
* @param {boolean} call.webClientShouldHandle - If Waweb should handle
* @param {object} call.participants - Participants
*/
const cll &#x3D; new Call(this,call);
this.emit(Events.INCOMING_CALL, cll);
});
await page.evaluate(() &#x3D;&gt; {
window.Store.Msg.on(&#x27;add&#x27;, (msg) &#x3D;&gt; { if (msg.isNewMsg) window.onAddMessageEvent(window.WWebJS.getMessageModel(msg)); });
window.Store.Msg.on(&#x27;change&#x27;, (msg) &#x3D;&gt; { window.onChangeMessageEvent(window.WWebJS.getMessageModel(msg)); });
window.Store.Msg.on(&#x27;change:type&#x27;, (msg) &#x3D;&gt; { window.onChangeMessageTypeEvent(window.WWebJS.getMessageModel(msg)); });
window.Store.Msg.on(&#x27;change:ack&#x27;, (msg,ack) &#x3D;&gt; { window.onMessageAckEvent(window.WWebJS.getMessageModel(msg), ack); });
window.Store.Msg.on(&#x27;change:isUnsentMedia&#x27;, (msg, unsent) &#x3D;&gt; { if (msg.id.fromMe &amp;amp;&amp;amp; !unsent) window.onMessageMediaUploadedEvent(window.WWebJS.getMessageModel(msg)); });
window.Store.Msg.on(&#x27;remove&#x27;, (msg) &#x3D;&gt; { if (msg.isNewMsg) window.onRemoveMessageEvent(window.WWebJS.getMessageModel(msg)); });
window.Store.AppState.on(&#x27;change:state&#x27;, (_AppState, state) &#x3D;&gt; { window.onAppStateChangedEvent(state); });
window.Store.Conn.on(&#x27;change:battery&#x27;, (state) &#x3D;&gt; { window.onBatteryStateChangedEvent(state); });
window.Store.Call.on(&#x27;add&#x27;, (call) &#x3D;&gt; { window.onIncomingCall(call); });
});
/**
* Emitted when the client has initialized and is ready to receive messages.
* @event Client#ready
*/
this.emit(Events.READY);
// Disconnect when navigating away
// Because WhatsApp Web now reloads when logging out from the device, this also covers that case
this.pupPage.on(&#x27;framenavigated&#x27;, async () &#x3D;&gt; {
this.emit(Events.DISCONNECTED, &#x27;NAVIGATION&#x27;);
await this.destroy();
});
}
/**
* Closes the client
*/
async destroy() {
if (this._qrRefreshInterval) {
clearInterval(this._qrRefreshInterval);
}
await this.pupBrowser.close();
}
/**
* Logs out the client, closing the current session
*/
async logout() {
return await this.pupPage.evaluate(() &#x3D;&gt; {
return window.Store.AppState.logout();
});
}
/**
* Returns the version of WhatsApp Web currently being run
* @returns {Promise&amp;lt;string&gt;}
*/
async getWWebVersion() {
return await this.pupPage.evaluate(() &#x3D;&gt; {
return window.Debug.VERSION;
});
}
/**
* Mark as seen for the Chat
* @param {string} chatId
* @returns {Promise&amp;lt;boolean&gt;} result
*
*/
async sendSeen(chatId) {
const result &#x3D; await this.pupPage.evaluate(async (chatId) &#x3D;&gt; {
return window.WWebJS.sendSeen(chatId);
}, chatId);
return result;
}
/**
* Message options.
* @typedef {Object} MessageSendOptions
* @property {boolean} [linkPreview&#x3D;true] - Show links preview
* @property {boolean} [sendAudioAsVoice&#x3D;false] - Send audio as voice message
* @property {boolean} [sendVideoAsGif&#x3D;false] - Send video as gif
* @property {boolean} [sendMediaAsSticker&#x3D;false] - Send media as a sticker
* @property {boolean} [sendMediaAsDocument&#x3D;false] - Send media as a document
* @property {boolean} [parseVCards&#x3D;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&#x3D;true] - Mark the conversation as seen after sending the message
* @property {string} [stickerAuthor&#x3D;undefined] - Sets the author of the sticker, (if sendMediaAsSticker is true).
* @property {string} [stickerName&#x3D;undefined] - Sets the name of the sticker, (if sendMediaAsSticker is true).
* @property {string[]} [stickerCategories&#x3D;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
* @param {string|MessageMedia|Location|Contact|Array&amp;lt;Contact&gt;} content
* @param {MessageSendOptions} [options] - Options used when sending the message
*
* @returns {Promise&amp;lt;Message&gt;} Message that was just sent
*/
async sendMessage(chatId, content, options &#x3D; {}) {
let internalOptions &#x3D; {
linkPreview: options.linkPreview &#x3D;&#x3D;&#x3D; false ? undefined : true,
sendAudioAsVoice: options.sendAudioAsVoice,
sendVideoAsGif: options.sendVideoAsGif,
sendMediaAsSticker: options.sendMediaAsSticker,
sendMediaAsDocument: options.sendMediaAsDocument,
caption: options.caption,
quotedMessageId: options.quotedMessageId,
parseVCards: options.parseVCards &#x3D;&#x3D;&#x3D; false ? false : true,
mentionedJidList: Array.isArray(options.mentions) ? options.mentions.map(contact &#x3D;&gt; contact.id._serialized) : [],
...options.extra
};
const sendSeen &#x3D; typeof options.sendSeen &#x3D;&#x3D;&#x3D; &#x27;undefined&#x27; ? true : options.sendSeen;
if (content instanceof MessageMedia) {
internalOptions.attachment &#x3D; content;
content &#x3D; &#x27;&#x27;;
} else if (options.media instanceof MessageMedia) {
internalOptions.attachment &#x3D; options.media;
internalOptions.caption &#x3D; content;
content &#x3D; &#x27;&#x27;;
} else if (content instanceof Location) {
internalOptions.location &#x3D; content;
content &#x3D; &#x27;&#x27;;
} else if(content instanceof Contact) {
internalOptions.contactCard &#x3D; content.id._serialized;
content &#x3D; &#x27;&#x27;;
} else if(Array.isArray(content) &amp;amp;&amp;amp; content.length &gt; 0 &amp;amp;&amp;amp; content[0] instanceof Contact) {
internalOptions.contactCardList &#x3D; content.map(contact &#x3D;&gt; contact.id._serialized);
content &#x3D; &#x27;&#x27;;
}
if (internalOptions.sendMediaAsSticker &amp;amp;&amp;amp; internalOptions.attachment) {
internalOptions.attachment &#x3D;
await Util.formatToWebpSticker(internalOptions.attachment, {
name: options.stickerName,
author: options.stickerAuthor,
categories: options.stickerCategories
});
}
const newMessage &#x3D; await this.pupPage.evaluate(async (chatId, message, options, sendSeen) &#x3D;&gt; {
const chatWid &#x3D; window.Store.WidFactory.createWid(chatId);
const chat &#x3D; await window.Store.Chat.find(chatWid);
if (sendSeen) {
window.WWebJS.sendSeen(chatId);
}
const msg &#x3D; await window.WWebJS.sendMessage(chat, message, options, sendSeen);
return msg.serialize();
}, chatId, content, internalOptions, sendSeen);
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&amp;lt;Message[]&gt;}
*/
async searchMessages(query, options &#x3D; {}) {
const messages &#x3D; await this.pupPage.evaluate(async (query, page, count, remote) &#x3D;&gt; {
const { messages } &#x3D; await window.Store.Msg.search(query, page, count, remote);
return messages.map(msg &#x3D;&gt; window.WWebJS.getMessageModel(msg));
}, query, options.page, options.limit, options.chatId);
return messages.map(msg &#x3D;&gt; new Message(this, msg));
}
/**
* Get all current chat instances
* @returns {Promise&amp;lt;Array&amp;lt;Chat&gt;&gt;}
*/
async getChats() {
let chats &#x3D; await this.pupPage.evaluate(async () &#x3D;&gt; {
return await window.WWebJS.getChats();
});
return chats.map(chat &#x3D;&gt; ChatFactory.create(this, chat));
}
/**
* Get chat instance by ID
* @param {string} chatId
* @returns {Promise&amp;lt;Chat&gt;}
*/
async getChatById(chatId) {
let chat &#x3D; await this.pupPage.evaluate(async chatId &#x3D;&gt; {
return await window.WWebJS.getChat(chatId);
}, chatId);
return ChatFactory.create(this, chat);
}
/**
* Get all current contact instances
* @returns {Promise&amp;lt;Array&amp;lt;Contact&gt;&gt;}
*/
async getContacts() {
let contacts &#x3D; await this.pupPage.evaluate(() &#x3D;&gt; {
return window.WWebJS.getContacts();
});
return contacts.map(contact &#x3D;&gt; ContactFactory.create(this, contact));
}
/**
* Get contact instance by ID
* @param {string} contactId
* @returns {Promise&amp;lt;Contact&gt;}
*/
async getContactById(contactId) {
let contact &#x3D; await this.pupPage.evaluate(contactId &#x3D;&gt; {
return window.WWebJS.getContact(contactId);
}, contactId);
return ContactFactory.create(this, contact);
}
/**
* Returns an object with information about the invite code&#x27;s group
* @param {string} inviteCode
* @returns {Promise&amp;lt;object&gt;} Invite information
*/
async getInviteInfo(inviteCode) {
return await this.pupPage.evaluate(inviteCode &#x3D;&gt; {
return window.Store.Wap.groupInviteInfo(inviteCode);
}, inviteCode);
}
/**
* Accepts an invitation to join a group
* @param {string} inviteCode Invitation code
* @returns {Promise&amp;lt;string&gt;} Id of the joined Chat
*/
async acceptInvite(inviteCode) {
const chatId &#x3D; await this.pupPage.evaluate(async inviteCode &#x3D;&gt; {
return await window.Store.Invite.sendJoinGroupViaInvite(inviteCode);
}, inviteCode);
return chatId._serialized;
}
/**
* Accepts a private invitation to join a group
* @param {object} inviteV4 Invite V4 Info
* @returns {Promise&amp;lt;Object&gt;}
*/
async acceptGroupV4Invite(inviteInfo) {
if(!inviteInfo.inviteCode) throw &#x27;Invalid invite code, try passing the message.inviteV4 object&#x27;;
if (inviteInfo.inviteCodeExp &#x3D;&#x3D; 0) throw &#x27;Expired invite code&#x27;;
return await this.pupPage.evaluate(async inviteInfo &#x3D;&gt; {
let { groupId, fromId, inviteCode, inviteCodeExp, toId } &#x3D; inviteInfo;
return await window.Store.Wap.acceptGroupV4Invite(groupId, fromId, inviteCode, String(inviteCodeExp), toId);
}, inviteInfo);
}
/**
* Sets the current user&#x27;s status message
* @param {string} status New status message
*/
async setStatus(status) {
await this.pupPage.evaluate(async status &#x3D;&gt; {
return await window.Store.Wap.sendSetStatus(status);
}, status);
}
/**
* Sets the current user&#x27;s display name.
* This is the name shown to WhatsApp users that have not added you as a contact beside your number in groups and in your profile.
* @param {string} displayName New display name
*/
async setDisplayName(displayName) {
await this.pupPage.evaluate(async displayName &#x3D;&gt; {
return await window.Store.Wap.setPushname(displayName);
}, displayName);
}
/**
* Gets the current connection state for the client
* @returns {WAState}
*/
async getState() {
return await this.pupPage.evaluate(() &#x3D;&gt; {
return window.Store.AppState.state;
});
}
/**
* Marks the client as online
*/
async sendPresenceAvailable() {
return await this.pupPage.evaluate(() &#x3D;&gt; {
return window.Store.Wap.sendPresenceAvailable();
});
}
/**
* Enables and returns the archive state of the Chat
* @returns {boolean}
*/
async archiveChat(chatId) {
return await this.pupPage.evaluate(async chatId &#x3D;&gt; {
let chat &#x3D; await window.Store.Chat.get(chatId);
await window.Store.Cmd.archiveChat(chat, true);
return chat.archive;
}, chatId);
}
/**
* Changes and returns the archive state of the Chat
* @returns {boolean}
*/
async unarchiveChat(chatId) {
return await this.pupPage.evaluate(async chatId &#x3D;&gt; {
let chat &#x3D; await window.Store.Chat.get(chatId);
await window.Store.Cmd.archiveChat(chat, false);
return chat.archive;
}, chatId);
}
/**
* Pins the Chat
* @returns {Promise&amp;lt;boolean&gt;} New pin state. Could be false if the max number of pinned chats was reached.
*/
async pinChat(chatId) {
return this.pupPage.evaluate(async chatId &#x3D;&gt; {
let chat &#x3D; window.Store.Chat.get(chatId);
if (chat.pin) {
return true;
}
const MAX_PIN_COUNT &#x3D; 3;
if (window.Store.Chat.models.length &gt; MAX_PIN_COUNT) {
let maxPinned &#x3D; window.Store.Chat.models[MAX_PIN_COUNT - 1].pin;
if (maxPinned) {
return false;
}
}
await window.Store.Cmd.pinChat(chat, true);
return true;
}, chatId);
}
/**
* Unpins the Chat
* @returns {Promise&amp;lt;boolean&gt;} New pin state
*/
async unpinChat(chatId) {
return this.pupPage.evaluate(async chatId &#x3D;&gt; {
let chat &#x3D; window.Store.Chat.get(chatId);
if (!chat.pin) {
return false;
}
await window.Store.Cmd.pinChat(chat, false);
return false;
}, chatId);
}
/**
* Mutes the Chat until a specified date
* @param {string} chatId ID of the chat that will be muted
* @param {Date} unmuteDate Date when the chat will be unmuted
*/
async muteChat(chatId, unmuteDate) {
await this.pupPage.evaluate(async (chatId, timestamp) &#x3D;&gt; {
let chat &#x3D; await window.Store.Chat.get(chatId);
await chat.mute.mute(timestamp, !0);
}, chatId, unmuteDate.getTime() / 1000);
}
/**
* Unmutes the Chat
* @param {string} chatId ID of the chat that will be unmuted
*/
async unmuteChat(chatId) {
await this.pupPage.evaluate(async chatId &#x3D;&gt; {
let chat &#x3D; await window.Store.Chat.get(chatId);
await window.Store.Cmd.muteChat(chat, false);
}, chatId);
}
/**
* Mark the Chat as unread
* @param {string} chatId ID of the chat that will be marked as unread
*/
async markChatUnread(chatId) {
await this.pupPage.evaluate(async chatId &#x3D;&gt; {
let chat &#x3D; await window.Store.Chat.get(chatId);
await window.Store.Cmd.markChatUnread(chat, true);
}, chatId);
}
/**
* Returns the contact ID&#x27;s profile picture URL, if privacy settings allow it
* @param {string} contactId the whatsapp user&#x27;s ID
* @returns {Promise&amp;lt;string&gt;}
*/
async getProfilePicUrl(contactId) {
const profilePic &#x3D; await this.pupPage.evaluate((contactId) &#x3D;&gt; {
return window.Store.Wap.profilePicFind(contactId);
}, contactId);
return profilePic ? profilePic.eurl : undefined;
}
/**
* Force reset of connection state for the client
*/
async resetState() {
await this.pupPage.evaluate(() &#x3D;&gt; {
window.Store.AppState.phoneWatchdog.shiftTimer.forceRunNow();
});
}
/**
* Check if a given ID is registered in whatsapp
* @param {string} id the whatsapp user&#x27;s ID
* @returns {Promise&amp;lt;Boolean&gt;}
*/
async isRegisteredUser(id) {
return await this.pupPage.evaluate(async (id) &#x3D;&gt; {
let result &#x3D; await window.Store.Wap.queryExist(id);
return result.jid !&#x3D;&#x3D; undefined;
}, id);
}
/**
* Get the registered WhatsApp ID for a number.
* Will return null if the number is not registered on WhatsApp.
* @param {string} number Number or ID (&quot;@c.us&quot; will be automatically appended if not specified)
* @returns {Promise&amp;lt;Object|null&gt;}
*/
async getNumberId(number) {
if(!number.endsWith(&#x27;@c.us&#x27;)) {
number +&#x3D; &#x27;@c.us&#x27;;
}
try {
return await this.pupPage.evaluate(async numberId &#x3D;&gt; {
return window.WWebJS.getNumberId(numberId);
}, number);
} catch(_) {
return null;
}
}
/**
* Create a new group
* @param {string} name group title
* @param {Array&amp;lt;Contact|string&gt;} participants an array of Contacts or contact IDs to add to the group
* @returns {Object} createRes
* @returns {string} createRes.gid - ID for the group that was just created
* @returns {Object.&amp;lt;string,string&gt;} createRes.missingParticipants - participants that were not added to the group. Keys represent the ID for participant that was not added and its value is a status code that represents the reason why participant could not be added. This is usually 403 if the user&#x27;s privacy settings don&#x27;t allow you to add them to groups.
*/
async createGroup(name, participants) {
if (!Array.isArray(participants) || participants.length &#x3D;&#x3D; 0) {
throw &#x27;You need to add at least one other participant to the group&#x27;;
}
if (participants.every(c &#x3D;&gt; c instanceof Contact)) {
participants &#x3D; participants.map(c &#x3D;&gt; c.id._serialized);
}
const createRes &#x3D; await this.pupPage.evaluate(async (name, participantIds) &#x3D;&gt; {
const res &#x3D; await window.Store.Wap.createGroup(name, participantIds);
console.log(res);
if (!res.status &#x3D;&#x3D;&#x3D; 200) {
throw &#x27;An error occurred while creating the group!&#x27;;
}
return res;
}, name, participants);
const missingParticipants &#x3D; createRes.participants.reduce(((missing, c) &#x3D;&gt; {
const id &#x3D; Object.keys(c)[0];
const statusCode &#x3D; c[id].code;
if (statusCode !&#x3D; 200) return Object.assign(missing, { [id]: statusCode });
return missing;
}), {});
return { gid: createRes.gid, missingParticipants };
}
/**
* Get all current Labels
* @returns {Promise&amp;lt;Array&amp;lt;Label&gt;&gt;}
*/
async getLabels() {
const labels &#x3D; await this.pupPage.evaluate(async () &#x3D;&gt; {
return window.WWebJS.getLabels();
});
return labels.map(data &#x3D;&gt; new Label(this , data));
}
/**
* Get Label instance by ID
* @param {string} labelId
* @returns {Promise&amp;lt;Label&gt;}
*/
async getLabelById(labelId) {
const label &#x3D; await this.pupPage.evaluate(async (labelId) &#x3D;&gt; {
return window.WWebJS.getLabel(labelId);
}, labelId);
return new Label(this, label);
}
/**
* Get all Labels assigned to a chat
* @param {string} chatId
* @returns {Promise&amp;lt;Array&amp;lt;Label&gt;&gt;}
*/
async getChatLabels(chatId){
const labels &#x3D; await this.pupPage.evaluate(async (chatId) &#x3D;&gt; {
return window.WWebJS.getChatLabels(chatId);
}, chatId);
return labels.map(data &#x3D;&gt; new Label(this, data));
}
/**
* Get all Chats for a specific Label
* @param {string} labelId
* @returns {Promise&amp;lt;Array&amp;lt;Chat&gt;&gt;}
*/
async getChatsByLabelId(labelId){
const chatIds &#x3D; await this.pupPage.evaluate(async (labelId) &#x3D;&gt; {
const label &#x3D; window.Store.Label.get(labelId);
const labelItems &#x3D; label.labelItemCollection.models;
return labelItems.reduce((result, item) &#x3D;&gt; {
if(item.parentType &#x3D;&#x3D;&#x3D; &#x27;Chat&#x27;){
result.push(item.parentId);
}
return result;
},[]);
}, labelId);
return Promise.all(chatIds.map(id &#x3D;&gt; this.getChatById(id)));
}
}
module.exports &#x3D; Client;
</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 September 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>

250
docs/ClientInfo.html Normal file
View File

@@ -0,0 +1,250 @@
<!doctype html>
<html>
<head>
<meta name="generator" content="JSDoc 3.6.7">
<meta charset="utf-8">
<title>whatsapp-web.js 1.14.1 &raquo; Class: ClientInfo</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>1</a>
</div>
</div>
</nav>
<div id="jsdoc-body-container">
<div id="jsdoc-content">
<div id="jsdoc-content-container">
<div id="jsdoc-main" role="main">
<header class="page-header">
<div class="symbol-detail-labels"><span class="label label-kind">class</span></div>
<h1><small></small><span class="symbol-name">ClientInfo</span></h1>
<p class="source-link">Source: <a href="structures_ClientInfo.js.html#source-line-9">structures/<wbr>ClientInfo.<wbr>js:9</a></p>
<div class="symbol-classdesc">
<p>Current connection information</p>
</div>
<dl class="dl-compact">
</dl>
</header>
<section id="summary">
<div class="summary-callout">
<h2 class="summary-callout-heading">Properties</h2>
<div class="summary-content">
<div class="summary-column">
<dl class="dl-summary-callout">
<dt><a href="ClientInfo.html#me">me</a></dt>
<dd>
</dd>
<dt><a href="ClientInfo.html#phone">phone</a></dt>
<dd>
</dd>
</dl>
</div>
<div class="summary-column">
<dl class="dl-summary-callout">
<dt><a href="ClientInfo.html#platform">platform</a></dt>
<dd>
</dd>
<dt><a href="ClientInfo.html#pushname">pushname</a></dt>
<dd>
</dd>
</dl>
</div>
<div class="summary-column">
<dl class="dl-summary-callout">
<dt><a href="ClientInfo.html#wid">wid</a></dt>
<dd>
</dd>
</dl>
</div>
</div>
</div>
<div class="summary-callout">
<h2 class="summary-callout-heading">Method</h2>
<div class="summary-content">
<div class="summary-column">
<dl class="dl-summary-callout">
<dt><a href="ClientInfo.html#getBatteryStatus">getBatteryStatus()</a></dt>
<dd>
</dd>
</dl>
</div>
<div class="summary-column">
</div>
<div class="summary-column">
</div>
</div>
</div>
</section>
<section>
<h2 id="ClientInfo">new&nbsp;<span class="symbol-name">ClientInfo</span><span class="signature"><span class="signature-params">()</span></span></h2>
<dl class="dl-compact">
<dt>Extends</dt>
<dd><a href="Base.html">Base</a></dd>
</dl>
</section>
<section>
<h2>Properties</h2>
<section>
<h3 id="me"><span class="symbol-name">me</span><small class="property-type">
&nbsp;object</small></h3>
<dl class="dl-compact">
<dt>Deprecated</dt>
<dd>Use .wid instead</dd>
</dl>
<h3 id="phone"><span class="symbol-name">phone</span><small class="property-type">
&nbsp;object</small></h3>
<p>Information about the phone this client is connected to</p>
<section>
<h4>Properties</h4>
<table class="jsdoc-details-table">
<thead>
<tr>
<th>Name</th>
<th>Type</th>
<th>Optional</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<p>wa_version</p>
</td>
<td>
<p>string</p>
</td>
<td>
<p>&nbsp;</p>
</td>
<td>
<p>WhatsApp Version running on the phone</p>
</td>
</tr>
<tr>
<td>
<p>os_version</p>
</td>
<td>
<p>string</p>
</td>
<td>
<p>&nbsp;</p>
</td>
<td>
<p>OS Version running on the phone (iOS or Android version)</p>
</td>
</tr>
<tr>
<td>
<p>device_manufacturer</p>
</td>
<td>
<p>string</p>
</td>
<td>
<p>&nbsp;</p>
</td>
<td>
<p>Device manufacturer</p>
</td>
</tr>
<tr>
<td>
<p>device_model</p>
</td>
<td>
<p>string</p>
</td>
<td>
<p>&nbsp;</p>
</td>
<td>
<p>Device model</p>
</td>
</tr>
<tr>
<td>
<p>os_build_number</p>
</td>
<td>
<p>string</p>
</td>
<td>
<p>&nbsp;</p>
</td>
<td>
<p>OS build number</p>
</td>
</tr>
</tbody>
</table>
</section>
<dl class="dl-compact">
</dl>
<h3 id="platform"><span class="symbol-name">platform</span><small class="property-type">
&nbsp;string</small></h3>
<p>Platform the phone is running on</p>
<dl class="dl-compact">
</dl>
<h3 id="pushname"><span class="symbol-name">pushname</span><small class="property-type">
&nbsp;string</small></h3>
<p>Name configured to be shown in push notifications</p>
<dl class="dl-compact">
</dl>
<h3 id="wid"><span class="symbol-name">wid</span><small class="property-type">
&nbsp;object</small></h3>
<p>Current user ID</p>
<dl class="dl-compact">
</dl>
</section>
<h2>Method</h2>
<section>
<div class="symbol-detail-labels"><span class="label label-async">async</span></div>
<h3 id="getBatteryStatus"><span class="symbol-name">getBatteryStatus</span><span class="signature"><span class="signature-params">()</span>&nbsp;&rarr; <span class="signature-returns"> (object, number, or boolean)</span></span></h3>
<p>Get current battery percentage and charging status for the attached device</p>
<dl class="dl-compact">
<dt>Returns</dt>
<dd>
<p><code>object</code> <p>batteryStatus</p>
</p>
</dd>
<dd>
<p><code>number</code> <p>batteryStatus.battery - The current battery percentage</p>
</p>
</dd>
<dd>
<p><code>boolean</code> <p>batteryStatus.plugged - Indicates if the phone is plugged in (true) or not (false)</p>
</p>
</dd>
</dl>
</section>
</section>
</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 September 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>

272
docs/Contact.html Normal file
View File

@@ -0,0 +1,272 @@
<!doctype html>
<html>
<head>
<meta name="generator" content="JSDoc 3.6.7">
<meta charset="utf-8">
<title>whatsapp-web.js 1.14.1 &raquo; Class: Contact</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>1</a>
</div>
</div>
</nav>
<div id="jsdoc-body-container">
<div id="jsdoc-content">
<div id="jsdoc-content-container">
<div id="jsdoc-main" role="main">
<header class="page-header">
<div class="symbol-detail-labels"><span class="label label-kind">class</span></div>
<h1><small></small><span class="symbol-name">Contact</span></h1>
<p class="source-link">Source: <a href="structures_Contact.js.html#source-line-17">structures/<wbr>Contact.<wbr>js:17</a></p>
<div class="symbol-classdesc">
<p>Represents a Contact on WhatsApp</p>
</div>
<dl class="dl-compact">
</dl>
</header>
<section id="summary">
<div class="summary-callout">
<h2 class="summary-callout-heading">Properties</h2>
<div class="summary-content">
<div class="summary-column">
<dl class="dl-summary-callout">
<dt><a href="Contact.html#id">id</a></dt>
<dd>
</dd>
<dt><a href="Contact.html#isBlocked">isBlocked</a></dt>
<dd>
</dd>
<dt><a href="Contact.html#isBusiness">isBusiness</a></dt>
<dd>
</dd>
<dt><a href="Contact.html#isEnterprise">isEnterprise</a></dt>
<dd>
</dd>
<dt><a href="Contact.html#isGroup">isGroup</a></dt>
<dd>
</dd>
</dl>
</div>
<div class="summary-column">
<dl class="dl-summary-callout">
<dt><a href="Contact.html#isMe">isMe</a></dt>
<dd>
</dd>
<dt><a href="Contact.html#isMyContact">isMyContact</a></dt>
<dd>
</dd>
<dt><a href="Contact.html#isUser">isUser</a></dt>
<dd>
</dd>
<dt><a href="Contact.html#isWAContact">isWAContact</a></dt>
<dd>
</dd>
<dt><a href="Contact.html#name">name</a></dt>
<dd>
</dd>
</dl>
</div>
<div class="summary-column">
<dl class="dl-summary-callout">
<dt><a href="Contact.html#number">number</a></dt>
<dd>
</dd>
<dt><a href="Contact.html#pushname">pushname</a></dt>
<dd>
</dd>
<dt><a href="Contact.html#shortName">shortName</a></dt>
<dd>
</dd>
</dl>
</div>
</div>
</div>
<div class="summary-callout">
<h2 class="summary-callout-heading">Methods</h2>
<div class="summary-content">
<div class="summary-column">
<dl class="dl-summary-callout">
<dt><a href="Contact.html#block">block()</a></dt>
<dd>
</dd>
<dt><a href="Contact.html#getAbout">getAbout()</a></dt>
<dd>
</dd>
</dl>
</div>
<div class="summary-column">
<dl class="dl-summary-callout">
<dt><a href="Contact.html#getChat">getChat()</a></dt>
<dd>
</dd>
<dt><a href="Contact.html#getProfilePicUrl">getProfilePicUrl()</a></dt>
<dd>
</dd>
</dl>
</div>
<div class="summary-column">
<dl class="dl-summary-callout">
<dt><a href="Contact.html#unblock">unblock()</a></dt>
<dd>
</dd>
</dl>
</div>
</div>
</div>
</section>
<section>
<h2 id="Contact">new&nbsp;<span class="symbol-name">Contact</span><span class="signature"><span class="signature-params">()</span></span></h2>
<dl class="dl-compact">
<dt>Extends</dt>
<dd><a href="Base.html">Base</a></dd>
</dl>
</section>
<section>
<h2>Properties</h2>
<section>
<h3 id="id"><span class="symbol-name">id</span><small class="property-type">
&nbsp;<a href="global.html#ContactId">ContactId</a></small></h3>
<p>ID that represents the contact</p>
<dl class="dl-compact">
</dl>
<h3 id="isBlocked"><span class="symbol-name">isBlocked</span><small class="property-type">
&nbsp;boolean</small></h3>
<p>Indicates if you have blocked this contact</p>
<dl class="dl-compact">
</dl>
<h3 id="isBusiness"><span class="symbol-name">isBusiness</span><small class="property-type">
&nbsp;boolean</small></h3>
<p>Indicates if the contact is a business contact</p>
<dl class="dl-compact">
</dl>
<h3 id="isEnterprise"><span class="symbol-name">isEnterprise</span><small class="property-type">
&nbsp;boolean</small></h3>
<p>Indicates if the contact is an enterprise contact</p>
<dl class="dl-compact">
</dl>
<h3 id="isGroup"><span class="symbol-name">isGroup</span><small class="property-type">
&nbsp;boolean</small></h3>
<p>Indicates if the contact is a group contact</p>
<dl class="dl-compact">
</dl>
<h3 id="isMe"><span class="symbol-name">isMe</span><small class="property-type">
&nbsp;boolean</small></h3>
<p>Indicates if the contact is the current user's contact</p>
<dl class="dl-compact">
</dl>
<h3 id="isMyContact"><span class="symbol-name">isMyContact</span><small class="property-type">
&nbsp;boolean</small></h3>
<p>Indicates if the number is saved in the current phone's contacts</p>
<dl class="dl-compact">
</dl>
<h3 id="isUser"><span class="symbol-name">isUser</span><small class="property-type">
&nbsp;boolean</small></h3>
<p>Indicates if the contact is a user contact</p>
<dl class="dl-compact">
</dl>
<h3 id="isWAContact"><span class="symbol-name">isWAContact</span><small class="property-type">
&nbsp;boolean</small></h3>
<p>Indicates if the number is registered on WhatsApp</p>
<dl class="dl-compact">
</dl>
<h3 id="name"><span class="symbol-name">name</span><small class="property-type">
&nbsp;nullable string</small></h3>
<p>The contact's name, as saved by the current user</p>
<dl class="dl-compact">
</dl>
<h3 id="number"><span class="symbol-name">number</span><small class="property-type">
&nbsp;string</small></h3>
<p>Contact's phone number</p>
<dl class="dl-compact">
</dl>
<h3 id="pushname"><span class="symbol-name">pushname</span><small class="property-type">
&nbsp;string</small></h3>
<p>The name that the contact has configured to be shown publically</p>
<dl class="dl-compact">
</dl>
<h3 id="shortName"><span class="symbol-name">shortName</span><small class="property-type">
&nbsp;nullable string</small></h3>
<p>A shortened version of name</p>
<dl class="dl-compact">
</dl>
</section>
<h2>Methods</h2>
<section>
<div class="symbol-detail-labels"><span class="label label-async">async</span></div>
<h3 id="block"><span class="symbol-name">block</span><span class="signature"><span class="signature-params">()</span>&nbsp;&rarr; <span class="signature-returns"> Promise containing boolean</span></span></h3>
<p>Blocks this contact from WhatsApp</p>
<dl class="dl-compact">
<dt>Returns</dt>
<dd>
<p><code>Promise containing boolean</code> </p>
</dd>
</dl>
<div class="symbol-detail-labels"><span class="label label-async">async</span></div>
<h3 id="getAbout"><span class="symbol-name">getAbout</span><span class="signature"><span class="signature-params">()</span>&nbsp;&rarr; <span class="signature-returns"> Promise containing nullable string</span></span></h3>
<p>Gets the Contact's current &quot;about&quot; info. Returns null if you don't have permission to read their status.</p>
<dl class="dl-compact">
<dt>Returns</dt>
<dd>
<p><code>Promise containing nullable string</code> </p>
</dd>
</dl>
<div class="symbol-detail-labels"><span class="label label-async">async</span></div>
<h3 id="getChat"><span class="symbol-name">getChat</span><span class="signature"><span class="signature-params">()</span>&nbsp;&rarr; <span class="signature-returns"> Promise containing <a href="Chat.html">Chat</a></span></span></h3>
<p>Returns the Chat that corresponds to this Contact.
Will return null when getting chat for currently logged in user.</p>
<dl class="dl-compact">
<dt>Returns</dt>
<dd>
<p><code>Promise containing <a href="Chat.html">Chat</a></code> </p>
</dd>
</dl>
<div class="symbol-detail-labels"><span class="label label-async">async</span></div>
<h3 id="getProfilePicUrl"><span class="symbol-name">getProfilePicUrl</span><span class="signature"><span class="signature-params">()</span>&nbsp;&rarr; <span class="signature-returns"> Promise containing string</span></span></h3>
<p>Returns the contact's profile picture URL, if privacy settings allow it</p>
<dl class="dl-compact">
<dt>Returns</dt>
<dd>
<p><code>Promise containing string</code> </p>
</dd>
</dl>
<div class="symbol-detail-labels"><span class="label label-async">async</span></div>
<h3 id="unblock"><span class="symbol-name">unblock</span><span class="signature"><span class="signature-params">()</span>&nbsp;&rarr; <span class="signature-returns"> Promise containing boolean</span></span></h3>
<p>Unblocks this contact from WhatsApp</p>
<dl class="dl-compact">
<dt>Returns</dt>
<dd>
<p><code>Promise containing boolean</code> </p>
</dd>
</dl>
</section>
</section>
</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 September 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>

931
docs/GroupChat.html Normal file
View File

@@ -0,0 +1,931 @@
<!doctype html>
<html>
<head>
<meta name="generator" content="JSDoc 3.6.7">
<meta charset="utf-8">
<title>whatsapp-web.js 1.14.1 &raquo; Class: GroupChat</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>1</a>
</div>
</div>
</nav>
<div id="jsdoc-body-container">
<div id="jsdoc-content">
<div id="jsdoc-content-container">
<div id="jsdoc-main" role="main">
<header class="page-header">
<div class="symbol-detail-labels"><span class="label label-kind">class</span></div>
<h1><small></small><span class="symbol-name">GroupChat</span></h1>
<p class="source-link">Source: <a href="structures_GroupChat.js.html#source-line-17">structures/<wbr>GroupChat.<wbr>js:17</a></p>
<div class="symbol-classdesc">
<p>Represents a Group Chat on WhatsApp</p>
</div>
<dl class="dl-compact">
</dl>
</header>
<section id="summary">
<div class="summary-callout">
<h2 class="summary-callout-heading">Properties</h2>
<div class="summary-content">
<div class="summary-column">
<dl class="dl-summary-callout">
<dt><a href="GroupChat.html#archived">archived</a></dt>
<dd>
</dd>
<dt><a href="GroupChat.html#createdAt">createdAt</a></dt>
<dd>
</dd>
<dt><a href="GroupChat.html#description">description</a></dt>
<dd>
</dd>
<dt><a href="GroupChat.html#id">id</a></dt>
<dd>
</dd>
<dt><a href="GroupChat.html#isGroup">isGroup</a></dt>
<dd>
</dd>
</dl>
</div>
<div class="summary-column">
<dl class="dl-summary-callout">
<dt><a href="GroupChat.html#isMuted">isMuted</a></dt>
<dd>
</dd>
<dt><a href="GroupChat.html#isReadOnly">isReadOnly</a></dt>
<dd>
</dd>
<dt><a href="GroupChat.html#muteExpiration">muteExpiration</a></dt>
<dd>
</dd>
<dt><a href="GroupChat.html#name">name</a></dt>
<dd>
</dd>
<dt><a href="GroupChat.html#owner">owner</a></dt>
<dd>
</dd>
</dl>
</div>
<div class="summary-column">
<dl class="dl-summary-callout">
<dt><a href="GroupChat.html#participants">participants</a></dt>
<dd>
</dd>
<dt><a href="GroupChat.html#pinned">pinned</a></dt>
<dd>
</dd>
<dt><a href="GroupChat.html#timestamp">timestamp</a></dt>
<dd>
</dd>
<dt><a href="GroupChat.html#unreadCount">unreadCount</a></dt>
<dd>
</dd>
</dl>
</div>
</div>
</div>
<div class="summary-callout">
<h2 class="summary-callout-heading">Methods</h2>
<div class="summary-content">
<div class="summary-column">
<dl class="dl-summary-callout">
<dt><a href="GroupChat.html#addParticipants">addParticipants(participantIds)</a></dt>
<dd>
</dd>
<dt><a href="GroupChat.html#archive">archive()</a></dt>
<dd>
</dd>
<dt><a href="GroupChat.html#clearMessages">clearMessages()</a></dt>
<dd>
</dd>
<dt><a href="GroupChat.html#clearState">clearState()</a></dt>
<dd>
</dd>
<dt><a href="GroupChat.html#delete">delete()</a></dt>
<dd>
</dd>
<dt><a href="GroupChat.html#demoteParticipants">demoteParticipants(participantIds)</a></dt>
<dd>
</dd>
<dt><a href="GroupChat.html#fetchMessages">fetchMessages(searchOptions)</a></dt>
<dd>
</dd>
<dt><a href="GroupChat.html#getContact">getContact()</a></dt>
<dd>
</dd>
<dt><a href="GroupChat.html#getInviteCode">getInviteCode()</a></dt>
<dd>
</dd>
<dt><a href="GroupChat.html#getLabels">getLabels()</a></dt>
<dd>
</dd>
</dl>
</div>
<div class="summary-column">
<dl class="dl-summary-callout">
<dt><a href="GroupChat.html#leave">leave()</a></dt>
<dd>
</dd>
<dt><a href="GroupChat.html#markUnread">markUnread()</a></dt>
<dd>
</dd>
<dt><a href="GroupChat.html#mute">mute(unmuteDate)</a></dt>
<dd>
</dd>
<dt><a href="GroupChat.html#pin">pin()</a></dt>
<dd>
</dd>
<dt><a href="GroupChat.html#promoteParticipants">promoteParticipants(participantIds)</a></dt>
<dd>
</dd>
<dt><a href="GroupChat.html#removeParticipants">removeParticipants(participantIds)</a></dt>
<dd>
</dd>
<dt><a href="GroupChat.html#revokeInvite">revokeInvite()</a></dt>
<dd>
</dd>
<dt><a href="GroupChat.html#sendMessage">sendMessage(content[, options])</a></dt>
<dd>
</dd>
<dt><a href="GroupChat.html#sendSeen">sendSeen()</a></dt>
<dd>
</dd>
<dt><a href="GroupChat.html#sendStateRecording">sendStateRecording()</a></dt>
<dd>
</dd>
</dl>
</div>
<div class="summary-column">
<dl class="dl-summary-callout">
<dt><a href="GroupChat.html#sendStateTyping">sendStateTyping()</a></dt>
<dd>
</dd>
<dt><a href="GroupChat.html#setDescription">setDescription(description)</a></dt>
<dd>
</dd>
<dt><a href="GroupChat.html#setInfoAdminsOnly">setInfoAdminsOnly([adminsOnly])</a></dt>
<dd>
</dd>
<dt><a href="GroupChat.html#setMessagesAdminsOnly">setMessagesAdminsOnly([adminsOnly])</a></dt>
<dd>
</dd>
<dt><a href="GroupChat.html#setSubject">setSubject(subject)</a></dt>
<dd>
</dd>
<dt><a href="GroupChat.html#unarchive">unarchive()</a></dt>
<dd>
</dd>
<dt><a href="GroupChat.html#unmute">unmute()</a></dt>
<dd>
</dd>
<dt><a href="GroupChat.html#unpin">unpin()</a></dt>
<dd>
</dd>
</dl>
</div>
</div>
</div>
</section>
<section>
<h2 id="GroupChat">new&nbsp;<span class="symbol-name">GroupChat</span><span class="signature"><span class="signature-params">()</span></span></h2>
<dl class="dl-compact">
<dt>Extends</dt>
<dd><a href="Chat.html">Chat</a></dd>
</dl>
</section>
<section>
<h2>Properties</h2>
<section>
<h3 id="archived"><span class="symbol-name">archived</span><small class="property-type">
&nbsp;unknown</small></h3>
<p>Indicates if the Chat is archived</p>
<dl class="dl-compact">
<dt>Inherited from</dt>
<dd><a href="Chat.html#archived">Chat#archived</a></dd>
</dl>
<h3 id="createdAt"><span class="symbol-name">createdAt</span><small class="property-type">
&nbsp;date</small></h3>
<p>Gets the date at which the group was created</p>
<dl class="dl-compact">
</dl>
<h3 id="description"><span class="symbol-name">description</span><small class="property-type">
&nbsp;string</small></h3>
<p>Gets the group description</p>
<dl class="dl-compact">
</dl>
<h3 id="id"><span class="symbol-name">id</span><small class="property-type">
&nbsp;unknown</small></h3>
<p>ID that represents the chat</p>
<dl class="dl-compact">
<dt>Inherited from</dt>
<dd><a href="Chat.html#id">Chat#id</a></dd>
</dl>
<h3 id="isGroup"><span class="symbol-name">isGroup</span><small class="property-type">
&nbsp;unknown</small></h3>
<p>Indicates if the Chat is a Group Chat</p>
<dl class="dl-compact">
<dt>Inherited from</dt>
<dd><a href="Chat.html#isGroup">Chat#isGroup</a></dd>
</dl>
<h3 id="isMuted"><span class="symbol-name">isMuted</span><small class="property-type">
&nbsp;unknown</small></h3>
<p>Indicates if the chat is muted or not</p>
<dl class="dl-compact">
<dt>Inherited from</dt>
<dd><a href="Chat.html#isMuted">Chat#isMuted</a></dd>
</dl>
<h3 id="isReadOnly"><span class="symbol-name">isReadOnly</span><small class="property-type">
&nbsp;unknown</small></h3>
<p>Indicates if the Chat is readonly</p>
<dl class="dl-compact">
<dt>Inherited from</dt>
<dd><a href="Chat.html#isReadOnly">Chat#isReadOnly</a></dd>
</dl>
<h3 id="muteExpiration"><span class="symbol-name">muteExpiration</span><small class="property-type">
&nbsp;unknown</small></h3>
<p>Unix timestamp for when the mute expires</p>
<dl class="dl-compact">
<dt>Inherited from</dt>
<dd><a href="Chat.html#muteExpiration">Chat#muteExpiration</a></dd>
</dl>
<h3 id="name"><span class="symbol-name">name</span><small class="property-type">
&nbsp;unknown</small></h3>
<p>Title of the chat</p>
<dl class="dl-compact">
<dt>Inherited from</dt>
<dd><a href="Chat.html#name">Chat#name</a></dd>
</dl>
<h3 id="owner"><span class="symbol-name">owner</span><small class="property-type">
&nbsp;<a href="global.html#ContactId">ContactId</a></small></h3>
<p>Gets the group owner</p>
<dl class="dl-compact">
</dl>
<h3 id="participants"><span class="symbol-name">participants</span><small class="property-type">
&nbsp;Array of <a href="global.html#GroupParticipant">GroupParticipant</a></small></h3>
<p>Gets the group participants</p>
<dl class="dl-compact">
</dl>
<h3 id="pinned"><span class="symbol-name">pinned</span><small class="property-type">
&nbsp;unknown</small></h3>
<p>Indicates if the Chat is pinned</p>
<dl class="dl-compact">
<dt>Inherited from</dt>
<dd><a href="Chat.html#pinned">Chat#pinned</a></dd>
</dl>
<h3 id="timestamp"><span class="symbol-name">timestamp</span><small class="property-type">
&nbsp;unknown</small></h3>
<p>Unix timestamp for when the last activity occurred</p>
<dl class="dl-compact">
<dt>Inherited from</dt>
<dd><a href="Chat.html#timestamp">Chat#timestamp</a></dd>
</dl>
<h3 id="unreadCount"><span class="symbol-name">unreadCount</span><small class="property-type">
&nbsp;unknown</small></h3>
<p>Amount of messages unread</p>
<dl class="dl-compact">
<dt>Inherited from</dt>
<dd><a href="Chat.html#unreadCount">Chat#unreadCount</a></dd>
</dl>
</section>
<h2>Methods</h2>
<section>
<div class="symbol-detail-labels"><span class="label label-async">async</span></div>
<h3 id="addParticipants"><span class="symbol-name">addParticipants</span><span class="signature"><span class="signature-params">(participantIds)</span>&nbsp;&rarr; <span class="signature-returns"> Promise containing Object</span></span></h3>
<p>Adds a list of participants by ID to the group</p>
<section>
<h4>Parameter</h4>
<table class="jsdoc-details-table">
<thead>
<tr>
<th>Name</th>
<th>Type</th>
<th>Optional</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<p>participantIds</p>
</td>
<td>
<p>Array of string</p>
</td>
<td>
<p>&nbsp;</p>
</td>
<td>
</td>
</tr>
</tbody>
</table>
</section>
<dl class="dl-compact">
<dt>Returns</dt>
<dd>
<p><code>Promise containing Object</code> </p>
</dd>
</dl>
<div class="symbol-detail-labels"><span class="label label-async">async</span></div>
<h3 id="archive"><span class="symbol-name">archive</span><span class="signature"><span class="signature-params">()</span></span></h3>
<p>Archives this chat</p>
<dl class="dl-compact">
<dt>Inherited from</dt>
<dd><a href="Chat.html#archive">Chat#archive</a></dd>
</dl>
<div class="symbol-detail-labels"><span class="label label-async">async</span></div>
<h3 id="clearMessages"><span class="symbol-name">clearMessages</span><span class="signature"><span class="signature-params">()</span>&nbsp;&rarr; <span class="signature-returns"> Promise containing Boolean</span></span></h3>
<p>Clears all messages from the chat</p>
<dl class="dl-compact">
<dt>Inherited from</dt>
<dd><a href="Chat.html#clearMessages">Chat#clearMessages</a></dd>
<dt>Returns</dt>
<dd>
<p>result</p>
</dd>
</dl>
<div class="symbol-detail-labels"><span class="label label-async">async</span></div>
<h3 id="clearState"><span class="symbol-name">clearState</span><span class="signature"><span class="signature-params">()</span></span></h3>
<p>Stops typing or recording in chat immediately.</p>
<dl class="dl-compact">
<dt>Inherited from</dt>
<dd><a href="Chat.html#clearState">Chat#clearState</a></dd>
</dl>
<div class="symbol-detail-labels"><span class="label label-async">async</span></div>
<h3 id="delete"><span class="symbol-name">delete</span><span class="signature"><span class="signature-params">()</span>&nbsp;&rarr; <span class="signature-returns"> Promise containing Boolean</span></span></h3>
<p>Deletes the chat</p>
<dl class="dl-compact">
<dt>Inherited from</dt>
<dd><a href="Chat.html#delete">Chat#delete</a></dd>
<dt>Returns</dt>
<dd>
<p>result</p>
</dd>
</dl>
<div class="symbol-detail-labels"><span class="label label-async">async</span></div>
<h3 id="demoteParticipants"><span class="symbol-name">demoteParticipants</span><span class="signature"><span class="signature-params">(participantIds)</span>&nbsp;&rarr; <span class="signature-returns"> Promise containing {status: number}</span></span></h3>
<p>Demotes participants by IDs to regular users</p>
<section>
<h4>Parameter</h4>
<table class="jsdoc-details-table">
<thead>
<tr>
<th>Name</th>
<th>Type</th>
<th>Optional</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<p>participantIds</p>
</td>
<td>
<p>Array of string</p>
</td>
<td>
<p>&nbsp;</p>
</td>
<td>
</td>
</tr>
</tbody>
</table>
</section>
<dl class="dl-compact">
<dt>Returns</dt>
<dd>
<p><code>Promise containing {status: number}</code> <p>Object with status code indicating if the operation was successful</p>
</p>
</dd>
</dl>
<div class="symbol-detail-labels"><span class="label label-async">async</span></div>
<h3 id="fetchMessages"><span class="symbol-name">fetchMessages</span><span class="signature"><span class="signature-params">(searchOptions)</span>&nbsp;&rarr; <span class="signature-returns"> Promise containing Array of <a href="Message.html">Message</a></span></span></h3>
<p>Loads chat messages, sorted from earliest to latest.</p>
<section>
<h4>Parameters</h4>
<table class="jsdoc-details-table">
<thead>
<tr>
<th>Name</th>
<th>Type</th>
<th>Optional</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<p>searchOptions</p>
</td>
<td>
<p>&nbsp;</p>
</td>
<td>
<p>&nbsp;</p>
</td>
<td>
<p>Options for searching messages. Right now only limit is supported.</p>
<p>Values in <code>searchOptions</code> have the following properties:</p>
<table class="jsdoc-details-table">
<thead>
<tr>
<th>Name</th>
<th>Type</th>
<th>Optional</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<p>limit</p>
</td>
<td>
<p>&nbsp;</p>
</td>
<td>
<p>Yes</p>
</td>
<td>
<p>The amount of messages to return. Note that the actual number of returned messages may be smaller if there aren't enough messages in the conversation. Set this to Infinity to load all messages.</p>
<p>Defaults to <code>50</code>.</p>
</td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
</section>
<dl class="dl-compact">
<dt>Inherited from</dt>
<dd><a href="Chat.html#fetchMessages">Chat#fetchMessages</a></dd>
<dt>Returns</dt>
<dd></dd>
</dl>
<div class="symbol-detail-labels"><span class="label label-async">async</span></div>
<h3 id="getContact"><span class="symbol-name">getContact</span><span class="signature"><span class="signature-params">()</span>&nbsp;&rarr; <span class="signature-returns"> Promise containing <a href="Contact.html">Contact</a></span></span></h3>
<p>Returns the Contact that corresponds to this Chat.</p>
<dl class="dl-compact">
<dt>Inherited from</dt>
<dd><a href="Chat.html#getContact">Chat#getContact</a></dd>
<dt>Returns</dt>
<dd></dd>
</dl>
<div class="symbol-detail-labels"><span class="label label-async">async</span></div>
<h3 id="getInviteCode"><span class="symbol-name">getInviteCode</span><span class="signature"><span class="signature-params">()</span>&nbsp;&rarr; <span class="signature-returns"> Promise containing string</span></span></h3>
<p>Gets the invite code for a specific group</p>
<dl class="dl-compact">
<dt>Returns</dt>
<dd>
<p><code>Promise containing string</code> <p>Group's invite code</p>
</p>
</dd>
</dl>
<div class="symbol-detail-labels"><span class="label label-async">async</span></div>
<h3 id="getLabels"><span class="symbol-name">getLabels</span><span class="signature"><span class="signature-params">()</span>&nbsp;&rarr; <span class="signature-returns"> Promise containing Array of <a href="Label.html">Label</a></span></span></h3>
<p>Returns array of all Labels assigned to this Chat</p>
<dl class="dl-compact">
<dt>Inherited from</dt>
<dd><a href="Chat.html#getLabels">Chat#getLabels</a></dd>
<dt>Returns</dt>
<dd></dd>
</dl>
<div class="symbol-detail-labels"><span class="label label-async">async</span></div>
<h3 id="leave"><span class="symbol-name">leave</span><span class="signature"><span class="signature-params">()</span>&nbsp;&rarr; <span class="signature-returns"> Promise</span></span></h3>
<p>Makes the bot leave the group</p>
<dl class="dl-compact">
<dt>Returns</dt>
<dd>
<p><code>Promise</code> </p>
</dd>
</dl>
<div class="symbol-detail-labels"><span class="label label-async">async</span></div>
<h3 id="markUnread"><span class="symbol-name">markUnread</span><span class="signature"><span class="signature-params">()</span></span></h3>
<p>Mark this chat as unread</p>
<dl class="dl-compact">
<dt>Inherited from</dt>
<dd><a href="Chat.html#markUnread">Chat#markUnread</a></dd>
</dl>
<div class="symbol-detail-labels"><span class="label label-async">async</span></div>
<h3 id="mute"><span class="symbol-name">mute</span><span class="signature"><span class="signature-params">(unmuteDate)</span></span></h3>
<p>Mutes this chat until a specified date</p>
<section>
<h4>Parameter</h4>
<table class="jsdoc-details-table">
<thead>
<tr>
<th>Name</th>
<th>Type</th>
<th>Optional</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<p>unmuteDate</p>
</td>
<td>
<p>&nbsp;</p>
</td>
<td>
<p>&nbsp;</p>
</td>
<td>
<p>Date at which the Chat will be unmuted</p>
</td>
</tr>
</tbody>
</table>
</section>
<dl class="dl-compact">
<dt>Inherited from</dt>
<dd><a href="Chat.html#mute">Chat#mute</a></dd>
</dl>
<div class="symbol-detail-labels"><span class="label label-async">async</span></div>
<h3 id="pin"><span class="symbol-name">pin</span><span class="signature"><span class="signature-params">()</span>&nbsp;&rarr; <span class="signature-returns"> Promise containing boolean</span></span></h3>
<p>Pins this chat</p>
<dl class="dl-compact">
<dt>Inherited from</dt>
<dd><a href="Chat.html#pin">Chat#pin</a></dd>
<dt>Returns</dt>
<dd>
<p>New pin state. Could be false if the max number of pinned chats was reached.</p>
</dd>
</dl>
<div class="symbol-detail-labels"><span class="label label-async">async</span></div>
<h3 id="promoteParticipants"><span class="symbol-name">promoteParticipants</span><span class="signature"><span class="signature-params">(participantIds)</span>&nbsp;&rarr; <span class="signature-returns"> Promise containing {status: number}</span></span></h3>
<p>Promotes participants by IDs to admins</p>
<section>
<h4>Parameter</h4>
<table class="jsdoc-details-table">
<thead>
<tr>
<th>Name</th>
<th>Type</th>
<th>Optional</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<p>participantIds</p>
</td>
<td>
<p>Array of string</p>
</td>
<td>
<p>&nbsp;</p>
</td>
<td>
</td>
</tr>
</tbody>
</table>
</section>
<dl class="dl-compact">
<dt>Returns</dt>
<dd>
<p><code>Promise containing {status: number}</code> <p>Object with status code indicating if the operation was successful</p>
</p>
</dd>
</dl>
<div class="symbol-detail-labels"><span class="label label-async">async</span></div>
<h3 id="removeParticipants"><span class="symbol-name">removeParticipants</span><span class="signature"><span class="signature-params">(participantIds)</span>&nbsp;&rarr; <span class="signature-returns"> Promise containing Object</span></span></h3>
<p>Removes a list of participants by ID to the group</p>
<section>
<h4>Parameter</h4>
<table class="jsdoc-details-table">
<thead>
<tr>
<th>Name</th>
<th>Type</th>
<th>Optional</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<p>participantIds</p>
</td>
<td>
<p>Array of string</p>
</td>
<td>
<p>&nbsp;</p>
</td>
<td>
</td>
</tr>
</tbody>
</table>
</section>
<dl class="dl-compact">
<dt>Returns</dt>
<dd>
<p><code>Promise containing Object</code> </p>
</dd>
</dl>
<div class="symbol-detail-labels"><span class="label label-async">async</span></div>
<h3 id="revokeInvite"><span class="symbol-name">revokeInvite</span><span class="signature"><span class="signature-params">()</span>&nbsp;&rarr; <span class="signature-returns"> Promise</span></span></h3>
<p>Invalidates the current group invite code and generates a new one</p>
<dl class="dl-compact">
<dt>Returns</dt>
<dd>
<p><code>Promise</code> </p>
</dd>
</dl>
<div class="symbol-detail-labels"><span class="label label-async">async</span></div>
<h3 id="sendMessage"><span class="symbol-name">sendMessage</span><span class="signature"><span class="signature-params">(content[, options])</span>&nbsp;&rarr; <span class="signature-returns"> Promise containing <a href="Message.html">Message</a></span></span></h3>
<p>Send a message to this chat</p>
<section>
<h4>Parameters</h4>
<table class="jsdoc-details-table">
<thead>
<tr>
<th>Name</th>
<th>Type</th>
<th>Optional</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<p>content</p>
</td>
<td>
<p>&nbsp;</p>
</td>
<td>
<p>&nbsp;</p>
</td>
<td>
</td>
</tr>
<tr>
<td>
<p>options</p>
</td>
<td>
<p>&nbsp;</p>
</td>
<td>
<p>Yes</p>
</td>
<td>
</td>
</tr>
</tbody>
</table>
</section>
<dl class="dl-compact">
<dt>Inherited from</dt>
<dd><a href="Chat.html#sendMessage">Chat#sendMessage</a></dd>
<dt>Returns</dt>
<dd>
<p>Message that was just sent</p>
</dd>
</dl>
<div class="symbol-detail-labels"><span class="label label-async">async</span></div>
<h3 id="sendSeen"><span class="symbol-name">sendSeen</span><span class="signature"><span class="signature-params">()</span>&nbsp;&rarr; <span class="signature-returns"> Promise containing Boolean</span></span></h3>
<p>Set the message as seen</p>
<dl class="dl-compact">
<dt>Inherited from</dt>
<dd><a href="Chat.html#sendSeen">Chat#sendSeen</a></dd>
<dt>Returns</dt>
<dd>
<p>result</p>
</dd>
</dl>
<div class="symbol-detail-labels"><span class="label label-async">async</span></div>
<h3 id="sendStateRecording"><span class="symbol-name">sendStateRecording</span><span class="signature"><span class="signature-params">()</span></span></h3>
<p>Simulate recording audio in chat. This will last for 25 seconds.</p>
<dl class="dl-compact">
<dt>Inherited from</dt>
<dd><a href="Chat.html#sendStateRecording">Chat#sendStateRecording</a></dd>
</dl>
<div class="symbol-detail-labels"><span class="label label-async">async</span></div>
<h3 id="sendStateTyping"><span class="symbol-name">sendStateTyping</span><span class="signature"><span class="signature-params">()</span></span></h3>
<p>Simulate typing in chat. This will last for 25 seconds.</p>
<dl class="dl-compact">
<dt>Inherited from</dt>
<dd><a href="Chat.html#sendStateTyping">Chat#sendStateTyping</a></dd>
</dl>
<div class="symbol-detail-labels"><span class="label label-async">async</span></div>
<h3 id="setDescription"><span class="symbol-name">setDescription</span><span class="signature"><span class="signature-params">(description)</span>&nbsp;&rarr; <span class="signature-returns"> Promise</span></span></h3>
<p>Updates the group description</p>
<section>
<h4>Parameter</h4>
<table class="jsdoc-details-table">
<thead>
<tr>
<th>Name</th>
<th>Type</th>
<th>Optional</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<p>description</p>
</td>
<td>
<p>string</p>
</td>
<td>
<p>&nbsp;</p>
</td>
<td>
</td>
</tr>
</tbody>
</table>
</section>
<dl class="dl-compact">
<dt>Returns</dt>
<dd>
<p><code>Promise</code> </p>
</dd>
</dl>
<div class="symbol-detail-labels"><span class="label label-async">async</span></div>
<h3 id="setInfoAdminsOnly"><span class="symbol-name">setInfoAdminsOnly</span><span class="signature"><span class="signature-params">([adminsOnly])</span>&nbsp;&rarr; <span class="signature-returns"> Promise containing boolean</span></span></h3>
<p>Updates the group settings to only allow admins to edit group info (title, description, photo).</p>
<section>
<h4>Parameter</h4>
<table class="jsdoc-details-table">
<thead>
<tr>
<th>Name</th>
<th>Type</th>
<th>Optional</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<p>adminsOnly</p>
</td>
<td>
<p>boolean</p>
</td>
<td>
<p>Yes</p>
</td>
<td>
<p>Enable or disable this option</p>
<p>Defaults to <code>true</code>.</p>
</td>
</tr>
</tbody>
</table>
</section>
<dl class="dl-compact">
<dt>Returns</dt>
<dd>
<p><code>Promise containing boolean</code> <p>Returns true if the setting was properly updated. This can return false if the user does not have the necessary permissions.</p>
</p>
</dd>
</dl>
<div class="symbol-detail-labels"><span class="label label-async">async</span></div>
<h3 id="setMessagesAdminsOnly"><span class="symbol-name">setMessagesAdminsOnly</span><span class="signature"><span class="signature-params">([adminsOnly])</span>&nbsp;&rarr; <span class="signature-returns"> Promise containing boolean</span></span></h3>
<p>Updates the group settings to only allow admins to send messages.</p>
<section>
<h4>Parameter</h4>
<table class="jsdoc-details-table">
<thead>
<tr>
<th>Name</th>
<th>Type</th>
<th>Optional</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<p>adminsOnly</p>
</td>
<td>
<p>boolean</p>
</td>
<td>
<p>Yes</p>
</td>
<td>
<p>Enable or disable this option</p>
<p>Defaults to <code>true</code>.</p>
</td>
</tr>
</tbody>
</table>
</section>
<dl class="dl-compact">
<dt>Returns</dt>
<dd>
<p><code>Promise containing boolean</code> <p>Returns true if the setting was properly updated. This can return false if the user does not have the necessary permissions.</p>
</p>
</dd>
</dl>
<div class="symbol-detail-labels"><span class="label label-async">async</span></div>
<h3 id="setSubject"><span class="symbol-name">setSubject</span><span class="signature"><span class="signature-params">(subject)</span>&nbsp;&rarr; <span class="signature-returns"> Promise</span></span></h3>
<p>Updates the group subject</p>
<section>
<h4>Parameter</h4>
<table class="jsdoc-details-table">
<thead>
<tr>
<th>Name</th>
<th>Type</th>
<th>Optional</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<p>subject</p>
</td>
<td>
<p>string</p>
</td>
<td>
<p>&nbsp;</p>
</td>
<td>
</td>
</tr>
</tbody>
</table>
</section>
<dl class="dl-compact">
<dt>Returns</dt>
<dd>
<p><code>Promise</code> </p>
</dd>
</dl>
<div class="symbol-detail-labels"><span class="label label-async">async</span></div>
<h3 id="unarchive"><span class="symbol-name">unarchive</span><span class="signature"><span class="signature-params">()</span></span></h3>
<p>un-archives this chat</p>
<dl class="dl-compact">
<dt>Inherited from</dt>
<dd><a href="Chat.html#unarchive">Chat#unarchive</a></dd>
</dl>
<div class="symbol-detail-labels"><span class="label label-async">async</span></div>
<h3 id="unmute"><span class="symbol-name">unmute</span><span class="signature"><span class="signature-params">()</span></span></h3>
<p>Unmutes this chat</p>
<dl class="dl-compact">
<dt>Inherited from</dt>
<dd><a href="Chat.html#unmute">Chat#unmute</a></dd>
</dl>
<div class="symbol-detail-labels"><span class="label label-async">async</span></div>
<h3 id="unpin"><span class="symbol-name">unpin</span><span class="signature"><span class="signature-params">()</span>&nbsp;&rarr; <span class="signature-returns"> Promise containing boolean</span></span></h3>
<p>Unpins this chat</p>
<dl class="dl-compact">
<dt>Inherited from</dt>
<dd><a href="Chat.html#unpin">Chat#unpin</a></dd>
<dt>Returns</dt>
<dd>
<p>New pin state</p>
</dd>
</dl>
</section>
</section>
</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 September 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>

248
docs/GroupNotification.html Normal file
View File

@@ -0,0 +1,248 @@
<!doctype html>
<html>
<head>
<meta name="generator" content="JSDoc 3.6.7">
<meta charset="utf-8">
<title>whatsapp-web.js 1.14.1 &raquo; Class: GroupNotification</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>1</a>
</div>
</div>
</nav>
<div id="jsdoc-body-container">
<div id="jsdoc-content">
<div id="jsdoc-content-container">
<div id="jsdoc-main" role="main">
<header class="page-header">
<div class="symbol-detail-labels"><span class="label label-kind">class</span></div>
<h1><small></small><span class="symbol-name">GroupNotification</span></h1>
<p class="source-link">Source: <a href="structures_GroupNotification.js.html#source-line-9">structures/<wbr>GroupNotification.<wbr>js:9</a></p>
<div class="symbol-classdesc">
<p>Represents a GroupNotification on WhatsApp</p>
</div>
<dl class="dl-compact">
</dl>
</header>
<section id="summary">
<div class="summary-callout">
<h2 class="summary-callout-heading">Properties</h2>
<div class="summary-content">
<div class="summary-column">
<dl class="dl-summary-callout">
<dt><a href="GroupNotification.html#author">author</a></dt>
<dd>
</dd>
<dt><a href="GroupNotification.html#body">body</a></dt>
<dd>
</dd>
<dt><a href="GroupNotification.html#chatId">chatId</a></dt>
<dd>
</dd>
</dl>
</div>
<div class="summary-column">
<dl class="dl-summary-callout">
<dt><a href="GroupNotification.html#id">id</a></dt>
<dd>
</dd>
<dt><a href="GroupNotification.html#recipientIds">recipientIds</a></dt>
<dd>
</dd>
<dt><a href="GroupNotification.html#timestamp">timestamp</a></dt>
<dd>
</dd>
</dl>
</div>
<div class="summary-column">
<dl class="dl-summary-callout">
<dt><a href="GroupNotification.html#type">type</a></dt>
<dd>
</dd>
</dl>
</div>
</div>
</div>
<div class="summary-callout">
<h2 class="summary-callout-heading">Methods</h2>
<div class="summary-content">
<div class="summary-column">
<dl class="dl-summary-callout">
<dt><a href="GroupNotification.html#getChat">getChat()</a></dt>
<dd>
</dd>
<dt><a href="GroupNotification.html#getContact">getContact()</a></dt>
<dd>
</dd>
</dl>
</div>
<div class="summary-column">
<dl class="dl-summary-callout">
<dt><a href="GroupNotification.html#getRecipients">getRecipients()</a></dt>
<dd>
</dd>
<dt><a href="GroupNotification.html#reply">reply(content, options)</a></dt>
<dd>
</dd>
</dl>
</div>
<div class="summary-column">
</div>
</div>
</div>
</section>
<section>
<h2 id="GroupNotification">new&nbsp;<span class="symbol-name">GroupNotification</span><span class="signature"><span class="signature-params">()</span></span></h2>
<dl class="dl-compact">
<dt>Extends</dt>
<dd><a href="Base.html">Base</a></dd>
</dl>
</section>
<section>
<h2>Properties</h2>
<section>
<h3 id="author"><span class="symbol-name">author</span><small class="property-type">
&nbsp;string</small></h3>
<p>ContactId for the user that produced the GroupNotification.</p>
<dl class="dl-compact">
</dl>
<h3 id="body"><span class="symbol-name">body</span><small class="property-type">
&nbsp;string</small></h3>
<p>Extra content</p>
<dl class="dl-compact">
</dl>
<h3 id="chatId"><span class="symbol-name">chatId</span><small class="property-type">
&nbsp;string</small></h3>
<p>ID for the Chat that this groupNotification was sent for.</p>
<dl class="dl-compact">
</dl>
<h3 id="id"><span class="symbol-name">id</span><small class="property-type">
&nbsp;object</small></h3>
<p>ID that represents the groupNotification</p>
<dl class="dl-compact">
</dl>
<h3 id="recipientIds"><span class="symbol-name">recipientIds</span><small class="property-type">
&nbsp;Array of string</small></h3>
<p>Contact IDs for the users that were affected by this GroupNotification.</p>
<dl class="dl-compact">
</dl>
<h3 id="timestamp"><span class="symbol-name">timestamp</span><small class="property-type">
&nbsp;number</small></h3>
<p>Unix timestamp for when the groupNotification was created</p>
<dl class="dl-compact">
</dl>
<h3 id="type"><span class="symbol-name">type</span><small class="property-type">
&nbsp;<a href="global.html#GroupNotificationTypes">GroupNotificationTypes</a></small></h3>
<p>GroupNotification type</p>
<dl class="dl-compact">
</dl>
</section>
<h2>Methods</h2>
<section>
<h3 id="getChat"><span class="symbol-name">getChat</span><span class="signature"><span class="signature-params">()</span>&nbsp;&rarr; <span class="signature-returns"> Promise containing <a href="Chat.html">Chat</a></span></span></h3>
<p>Returns the Chat this groupNotification was sent in</p>
<dl class="dl-compact">
<dt>Returns</dt>
<dd>
<p><code>Promise containing <a href="Chat.html">Chat</a></code> </p>
</dd>
</dl>
<h3 id="getContact"><span class="symbol-name">getContact</span><span class="signature"><span class="signature-params">()</span>&nbsp;&rarr; <span class="signature-returns"> Promise containing <a href="Contact.html">Contact</a></span></span></h3>
<p>Returns the Contact this GroupNotification was produced by</p>
<dl class="dl-compact">
<dt>Returns</dt>
<dd>
<p><code>Promise containing <a href="Contact.html">Contact</a></code> </p>
</dd>
</dl>
<div class="symbol-detail-labels"><span class="label label-async">async</span></div>
<h3 id="getRecipients"><span class="symbol-name">getRecipients</span><span class="signature"><span class="signature-params">()</span>&nbsp;&rarr; <span class="signature-returns"> Promise containing Array of <a href="Contact.html">Contact</a></span></span></h3>
<p>Returns the Contacts affected by this GroupNotification.</p>
<dl class="dl-compact">
<dt>Returns</dt>
<dd>
<p><code>Promise containing Array of <a href="Contact.html">Contact</a></code> </p>
</dd>
</dl>
<div class="symbol-detail-labels"><span class="label label-async">async</span></div>
<h3 id="reply"><span class="symbol-name">reply</span><span class="signature"><span class="signature-params">(content, options)</span>&nbsp;&rarr; <span class="signature-returns"> Promise containing <a href="Message.html">Message</a></span></span></h3>
<p>Sends a message to the same chat this GroupNotification was produced in.</p>
<section>
<h4>Parameters</h4>
<table class="jsdoc-details-table">
<thead>
<tr>
<th>Name</th>
<th>Type</th>
<th>Optional</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<p>content</p>
</td>
<td>
<p>(string, <a href="MessageMedia.html">MessageMedia</a>, or <a href="Location.html">Location</a>)</p>
</td>
<td>
<p>&nbsp;</p>
</td>
<td>
</td>
</tr>
<tr>
<td>
<p>options</p>
</td>
<td>
<p>object</p>
</td>
<td>
<p>&nbsp;</p>
</td>
<td>
</td>
</tr>
</tbody>
</table>
</section>
<dl class="dl-compact">
<dt>Returns</dt>
<dd>
<p><code>Promise containing <a href="Message.html">Message</a></code> </p>
</dd>
</dl>
</section>
</section>
</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 September 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>

View File

@@ -0,0 +1,397 @@
<!doctype html>
<html>
<head>
<meta name="generator" content="JSDoc 3.6.7">
<meta charset="utf-8">
<title>whatsapp-web.js 1.14.1 &raquo; Class: InterfaceController</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>1</a>
</div>
</div>
</nav>
<div id="jsdoc-body-container">
<div id="jsdoc-content">
<div id="jsdoc-content-container">
<div id="jsdoc-main" role="main">
<header class="page-header">
<div class="symbol-detail-labels"><span class="label label-kind">class</span></div>
<h1><small></small><span class="symbol-name">InterfaceController</span></h1>
<p class="source-link">Source: <a href="util_InterfaceController.js.html#source-line-6">util/<wbr>InterfaceController.<wbr>js:6</a></p>
<div class="symbol-classdesc">
<p>Interface Controller</p>
</div>
<dl class="dl-compact">
</dl>
</header>
<section id="summary">
<div class="summary-callout">
<h2 class="summary-callout-heading">Methods</h2>
<div class="summary-content">
<div class="summary-column">
<dl class="dl-summary-callout">
<dt><a href="InterfaceController.html#checkFeatureStatus">checkFeatureStatus(feature)</a></dt>
<dd>
</dd>
<dt><a href="InterfaceController.html#closeRightDrawer">closeRightDrawer()</a></dt>
<dd>
</dd>
<dt><a href="InterfaceController.html#disableFeatures">disableFeatures(features)</a></dt>
<dd>
</dd>
<dt><a href="InterfaceController.html#enableFeatures">enableFeatures(features)</a></dt>
<dd>
</dd>
</dl>
</div>
<div class="summary-column">
<dl class="dl-summary-callout">
<dt><a href="InterfaceController.html#getFeatures">getFeatures()</a></dt>
<dd>
</dd>
<dt><a href="InterfaceController.html#openChatDrawer">openChatDrawer(chatId)</a></dt>
<dd>
</dd>
<dt><a href="InterfaceController.html#openChatSearch">openChatSearch(chatId)</a></dt>
<dd>
</dd>
<dt><a href="InterfaceController.html#openChatWindow">openChatWindow(chatId)</a></dt>
<dd>
</dd>
</dl>
</div>
<div class="summary-column">
<dl class="dl-summary-callout">
<dt><a href="InterfaceController.html#openChatWindowAt">openChatWindowAt(msgId)</a></dt>
<dd>
</dd>
<dt><a href="InterfaceController.html#openMessageDrawer">openMessageDrawer(msgId)</a></dt>
<dd>
</dd>
</dl>
</div>
</div>
</div>
</section>
<section>
<h2 id="InterfaceController">new&nbsp;<span class="symbol-name">InterfaceController</span><span class="signature"><span class="signature-params">()</span></span></h2>
<dl class="dl-compact">
</dl>
</section>
<section>
<h2>Methods</h2>
<section>
<div class="symbol-detail-labels"><span class="label label-async">async</span></div>
<h3 id="checkFeatureStatus"><span class="symbol-name">checkFeatureStatus</span><span class="signature"><span class="signature-params">(feature)</span></span></h3>
<p>Check if Feature is enabled</p>
<section>
<h4>Parameter</h4>
<table class="jsdoc-details-table">
<thead>
<tr>
<th>Name</th>
<th>Type</th>
<th>Optional</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<p>feature</p>
</td>
<td>
<p>string</p>
</td>
<td>
<p>&nbsp;</p>
</td>
<td>
<p>status to check</p>
</td>
</tr>
</tbody>
</table>
</section>
<dl class="dl-compact">
</dl>
<div class="symbol-detail-labels"><span class="label label-async">async</span></div>
<h3 id="closeRightDrawer"><span class="symbol-name">closeRightDrawer</span><span class="signature"><span class="signature-params">()</span></span></h3>
<p>Closes the Right Drawer</p>
<dl class="dl-compact">
</dl>
<div class="symbol-detail-labels"><span class="label label-async">async</span></div>
<h3 id="disableFeatures"><span class="symbol-name">disableFeatures</span><span class="signature"><span class="signature-params">(features)</span></span></h3>
<p>Disable Features</p>
<section>
<h4>Parameter</h4>
<table class="jsdoc-details-table">
<thead>
<tr>
<th>Name</th>
<th>Type</th>
<th>Optional</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<p>features</p>
</td>
<td>
<p>Array of string</p>
</td>
<td>
<p>&nbsp;</p>
</td>
<td>
<p>to be disabled</p>
</td>
</tr>
</tbody>
</table>
</section>
<dl class="dl-compact">
</dl>
<div class="symbol-detail-labels"><span class="label label-async">async</span></div>
<h3 id="enableFeatures"><span class="symbol-name">enableFeatures</span><span class="signature"><span class="signature-params">(features)</span></span></h3>
<p>Enable Features</p>
<section>
<h4>Parameter</h4>
<table class="jsdoc-details-table">
<thead>
<tr>
<th>Name</th>
<th>Type</th>
<th>Optional</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<p>features</p>
</td>
<td>
<p>Array of string</p>
</td>
<td>
<p>&nbsp;</p>
</td>
<td>
<p>to be enabled</p>
</td>
</tr>
</tbody>
</table>
</section>
<dl class="dl-compact">
</dl>
<div class="symbol-detail-labels"><span class="label label-async">async</span></div>
<h3 id="getFeatures"><span class="symbol-name">getFeatures</span><span class="signature"><span class="signature-params">()</span></span></h3>
<p>Get all Features</p>
<dl class="dl-compact">
</dl>
<div class="symbol-detail-labels"><span class="label label-async">async</span></div>
<h3 id="openChatDrawer"><span class="symbol-name">openChatDrawer</span><span class="signature"><span class="signature-params">(chatId)</span></span></h3>
<p>Opens the Chat Drawer</p>
<section>
<h4>Parameter</h4>
<table class="jsdoc-details-table">
<thead>
<tr>
<th>Name</th>
<th>Type</th>
<th>Optional</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<p>chatId</p>
</td>
<td>
<p>string</p>
</td>
<td>
<p>&nbsp;</p>
</td>
<td>
<p>ID of the chat drawer that will be opened</p>
</td>
</tr>
</tbody>
</table>
</section>
<dl class="dl-compact">
</dl>
<div class="symbol-detail-labels"><span class="label label-async">async</span></div>
<h3 id="openChatSearch"><span class="symbol-name">openChatSearch</span><span class="signature"><span class="signature-params">(chatId)</span></span></h3>
<p>Opens the Chat Search</p>
<section>
<h4>Parameter</h4>
<table class="jsdoc-details-table">
<thead>
<tr>
<th>Name</th>
<th>Type</th>
<th>Optional</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<p>chatId</p>
</td>
<td>
<p>string</p>
</td>
<td>
<p>&nbsp;</p>
</td>
<td>
<p>ID of the chat search that will be opened</p>
</td>
</tr>
</tbody>
</table>
</section>
<dl class="dl-compact">
</dl>
<div class="symbol-detail-labels"><span class="label label-async">async</span></div>
<h3 id="openChatWindow"><span class="symbol-name">openChatWindow</span><span class="signature"><span class="signature-params">(chatId)</span></span></h3>
<p>Opens the Chat Window</p>
<section>
<h4>Parameter</h4>
<table class="jsdoc-details-table">
<thead>
<tr>
<th>Name</th>
<th>Type</th>
<th>Optional</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<p>chatId</p>
</td>
<td>
<p>string</p>
</td>
<td>
<p>&nbsp;</p>
</td>
<td>
<p>ID of the chat window that will be opened</p>
</td>
</tr>
</tbody>
</table>
</section>
<dl class="dl-compact">
</dl>
<div class="symbol-detail-labels"><span class="label label-async">async</span></div>
<h3 id="openChatWindowAt"><span class="symbol-name">openChatWindowAt</span><span class="signature"><span class="signature-params">(msgId)</span></span></h3>
<p>Opens or Scrolls the Chat Window to the position of the message</p>
<section>
<h4>Parameter</h4>
<table class="jsdoc-details-table">
<thead>
<tr>
<th>Name</th>
<th>Type</th>
<th>Optional</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<p>msgId</p>
</td>
<td>
<p>string</p>
</td>
<td>
<p>&nbsp;</p>
</td>
<td>
<p>ID of the message that will be scrolled to</p>
</td>
</tr>
</tbody>
</table>
</section>
<dl class="dl-compact">
</dl>
<div class="symbol-detail-labels"><span class="label label-async">async</span></div>
<h3 id="openMessageDrawer"><span class="symbol-name">openMessageDrawer</span><span class="signature"><span class="signature-params">(msgId)</span></span></h3>
<p>Opens the Message Drawer</p>
<section>
<h4>Parameter</h4>
<table class="jsdoc-details-table">
<thead>
<tr>
<th>Name</th>
<th>Type</th>
<th>Optional</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<p>msgId</p>
</td>
<td>
<p>string</p>
</td>
<td>
<p>&nbsp;</p>
</td>
<td>
<p>ID of the message drawer that will be opened</p>
</td>
</tr>
</tbody>
</table>
</section>
<dl class="dl-compact">
</dl>
</section>
</section>
</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 September 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>

178
docs/Label.html Normal file
View File

@@ -0,0 +1,178 @@
<!doctype html>
<html>
<head>
<meta name="generator" content="JSDoc 3.6.7">
<meta charset="utf-8">
<title>whatsapp-web.js 1.14.1 &raquo; Class: Label</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>1</a>
</div>
</div>
</nav>
<div id="jsdoc-body-container">
<div id="jsdoc-content">
<div id="jsdoc-content-container">
<div id="jsdoc-main" role="main">
<header class="page-header">
<div class="symbol-detail-labels"><span class="label label-kind">class</span></div>
<h1><small></small><span class="symbol-name">Label</span></h1>
<p class="source-link">Source: <a href="structures_Label.js.html#source-line-10">structures/<wbr>Label.<wbr>js:10</a></p>
<div class="symbol-classdesc">
<p>WhatsApp Business Label information</p>
</div>
<dl class="dl-compact">
</dl>
</header>
<section id="summary">
<div class="summary-callout">
<h2 class="summary-callout-heading">Properties</h2>
<div class="summary-content">
<div class="summary-column">
<dl class="dl-summary-callout">
<dt><a href="Label.html#hexColor">hexColor</a></dt>
<dd>
</dd>
</dl>
</div>
<div class="summary-column">
<dl class="dl-summary-callout">
<dt><a href="Label.html#id">id</a></dt>
<dd>
</dd>
</dl>
</div>
<div class="summary-column">
<dl class="dl-summary-callout">
<dt><a href="Label.html#name">name</a></dt>
<dd>
</dd>
</dl>
</div>
</div>
</div>
<div class="summary-callout">
<h2 class="summary-callout-heading">Method</h2>
<div class="summary-content">
<div class="summary-column">
<dl class="dl-summary-callout">
<dt><a href="Label.html#getChats">getChats()</a></dt>
<dd>
</dd>
</dl>
</div>
<div class="summary-column">
</div>
<div class="summary-column">
</div>
</div>
</div>
</section>
<section>
<h2 id="Label">new&nbsp;<span class="symbol-name">Label</span><span class="signature"><span class="signature-params">(client, labelData)</span></span></h2>
<section>
<h3>Parameters</h3>
<table class="jsdoc-details-table">
<thead>
<tr>
<th>Name</th>
<th>Type</th>
<th>Optional</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<p>client</p>
</td>
<td>
<p>&nbsp;</p>
</td>
<td>
<p>&nbsp;</p>
</td>
<td>
</td>
</tr>
<tr>
<td>
<p>labelData</p>
</td>
<td>
<p>&nbsp;</p>
</td>
<td>
<p>&nbsp;</p>
</td>
<td>
</td>
</tr>
</tbody>
</table>
</section>
<dl class="dl-compact">
</dl>
</section>
<section>
<h2>Properties</h2>
<section>
<h3 id="hexColor"><span class="symbol-name">hexColor</span><small class="property-type">
&nbsp;string</small></h3>
<p>Label hex color</p>
<dl class="dl-compact">
</dl>
<h3 id="id"><span class="symbol-name">id</span><small class="property-type">
&nbsp;string</small></h3>
<p>Label ID</p>
<dl class="dl-compact">
</dl>
<h3 id="name"><span class="symbol-name">name</span><small class="property-type">
&nbsp;string</small></h3>
<p>Label name</p>
<dl class="dl-compact">
</dl>
</section>
<h2>Method</h2>
<section>
<div class="symbol-detail-labels"><span class="label label-async">async</span></div>
<h3 id="getChats"><span class="symbol-name">getChats</span><span class="signature"><span class="signature-params">()</span>&nbsp;&rarr; <span class="signature-returns"> Promise containing Array of <a href="Chat.html">Chat</a></span></span></h3>
<p>Get all chats that have been assigned this Label</p>
<dl class="dl-compact">
<dt>Returns</dt>
<dd>
<p><code>Promise containing Array of <a href="Chat.html">Chat</a></code> </p>
</dd>
</dl>
</section>
</section>
</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 September 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>

164
docs/Location.html Normal file
View File

@@ -0,0 +1,164 @@
<!doctype html>
<html>
<head>
<meta name="generator" content="JSDoc 3.6.7">
<meta charset="utf-8">
<title>whatsapp-web.js 1.14.1 &raquo; Class: Location</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>1</a>
</div>
</div>
</nav>
<div id="jsdoc-body-container">
<div id="jsdoc-content">
<div id="jsdoc-content-container">
<div id="jsdoc-main" role="main">
<header class="page-header">
<div class="symbol-detail-labels"><span class="label label-kind">class</span></div>
<h1><small></small><span class="symbol-name">Location</span></h1>
<p class="source-link">Source: <a href="structures_Location.js.html#source-line-6">structures/<wbr>Location.<wbr>js:6</a></p>
<div class="symbol-classdesc">
<p>Location information</p>
</div>
<dl class="dl-compact">
</dl>
</header>
<section id="summary">
<div class="summary-callout">
<h2 class="summary-callout-heading">Properties</h2>
<div class="summary-content">
<div class="summary-column">
<dl class="dl-summary-callout">
<dt><a href="Location.html#description">description</a></dt>
<dd>
</dd>
</dl>
</div>
<div class="summary-column">
<dl class="dl-summary-callout">
<dt><a href="Location.html#latitude">latitude</a></dt>
<dd>
</dd>
</dl>
</div>
<div class="summary-column">
<dl class="dl-summary-callout">
<dt><a href="Location.html#longitude">longitude</a></dt>
<dd>
</dd>
</dl>
</div>
</div>
</div>
</section>
<section>
<h2 id="Location">new&nbsp;<span class="symbol-name">Location</span><span class="signature"><span class="signature-params">(latitude, longitude, description)</span></span></h2>
<section>
<h3>Parameters</h3>
<table class="jsdoc-details-table">
<thead>
<tr>
<th>Name</th>
<th>Type</th>
<th>Optional</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<p>latitude</p>
</td>
<td>
<p>&nbsp;</p>
</td>
<td>
<p>&nbsp;</p>
</td>
<td>
</td>
</tr>
<tr>
<td>
<p>longitude</p>
</td>
<td>
<p>&nbsp;</p>
</td>
<td>
<p>&nbsp;</p>
</td>
<td>
</td>
</tr>
<tr>
<td>
<p>description</p>
</td>
<td>
<p>&nbsp;</p>
</td>
<td>
<p>&nbsp;</p>
</td>
<td>
<p>Value can be null.</p>
</td>
</tr>
</tbody>
</table>
</section>
<dl class="dl-compact">
</dl>
</section>
<section>
<h2>Properties</h2>
<section>
<h3 id="description"><span class="symbol-name">description</span><small class="property-type">
&nbsp;nullable string</small></h3>
<p>Name for the location</p>
<dl class="dl-compact">
</dl>
<h3 id="latitude"><span class="symbol-name">latitude</span><small class="property-type">
&nbsp;number</small></h3>
<p>Location latitude</p>
<dl class="dl-compact">
</dl>
<h3 id="longitude"><span class="symbol-name">longitude</span><small class="property-type">
&nbsp;number</small></h3>
<p>Location longitude</p>
<dl class="dl-compact">
</dl>
</section>
</section>
</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 September 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>

567
docs/Message.html Normal file
View File

@@ -0,0 +1,567 @@
<!doctype html>
<html>
<head>
<meta name="generator" content="JSDoc 3.6.7">
<meta charset="utf-8">
<title>whatsapp-web.js 1.14.1 &raquo; Class: Message</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>1</a>
</div>
</div>
</nav>
<div id="jsdoc-body-container">
<div id="jsdoc-content">
<div id="jsdoc-content-container">
<div id="jsdoc-main" role="main">
<header class="page-header">
<div class="symbol-detail-labels"><span class="label label-kind">class</span></div>
<h1><small></small><span class="symbol-name">Message</span></h1>
<p class="source-link">Source: <a href="structures_Message.js.html#source-line-13">structures/<wbr>Message.<wbr>js:13</a></p>
<div class="symbol-classdesc">
<p>Represents a Message on WhatsApp</p>
</div>
<dl class="dl-compact">
</dl>
</header>
<section id="summary">
<div class="summary-callout">
<h2 class="summary-callout-heading">Properties</h2>
<div class="summary-content">
<div class="summary-column">
<dl class="dl-summary-callout">
<dt><a href="Message.html#ack">ack</a></dt>
<dd>
</dd>
<dt><a href="Message.html#author">author</a></dt>
<dd>
</dd>
<dt><a href="Message.html#body">body</a></dt>
<dd>
</dd>
<dt><a href="Message.html#broadcast">broadcast</a></dt>
<dd>
</dd>
<dt><a href="Message.html#deviceType">deviceType</a></dt>
<dd>
</dd>
<dt><a href="Message.html#forwardingScore">forwardingScore</a></dt>
<dd>
</dd>
<dt><a href="Message.html#from">from</a></dt>
<dd>
</dd>
<dt><a href="Message.html#fromMe">fromMe</a></dt>
<dd>
</dd>
<dt><a href="Message.html#hasMedia">hasMedia</a></dt>
<dd>
</dd>
</dl>
</div>
<div class="summary-column">
<dl class="dl-summary-callout">
<dt><a href="Message.html#hasQuotedMsg">hasQuotedMsg</a></dt>
<dd>
</dd>
<dt><a href="Message.html#id">id</a></dt>
<dd>
</dd>
<dt><a href="Message.html#inviteV4">inviteV4</a></dt>
<dd>
</dd>
<dt><a href="Message.html#isForwarded">isForwarded</a></dt>
<dd>
</dd>
<dt><a href="Message.html#isStarred">isStarred</a></dt>
<dd>
</dd>
<dt><a href="Message.html#isStatus">isStatus</a></dt>
<dd>
</dd>
<dt><a href="Message.html#links">links</a></dt>
<dd>
</dd>
<dt><a href="Message.html#location">location</a></dt>
<dd>
</dd>
<dt><a href="Message.html#mediaKey">mediaKey</a></dt>
<dd>
</dd>
</dl>
</div>
<div class="summary-column">
<dl class="dl-summary-callout">
<dt><a href="Message.html#mentionedIds">mentionedIds</a></dt>
<dd>
</dd>
<dt><a href="Message.html#orderId">orderId</a></dt>
<dd>
</dd>
<dt><a href="Message.html#timestamp">timestamp</a></dt>
<dd>
</dd>
<dt><a href="Message.html#to">to</a></dt>
<dd>
</dd>
<dt><a href="Message.html#token">token</a></dt>
<dd>
</dd>
<dt><a href="Message.html#type">type</a></dt>
<dd>
</dd>
<dt><a href="Message.html#vCards">vCards</a></dt>
<dd>
</dd>
</dl>
</div>
</div>
</div>
<div class="summary-callout">
<h2 class="summary-callout-heading">Methods</h2>
<div class="summary-content">
<div class="summary-column">
<dl class="dl-summary-callout">
<dt><a href="Message.html#acceptGroupV4Invite">acceptGroupV4Invite()</a></dt>
<dd>
</dd>
<dt><a href="Message.html#delete">delete(everyone)</a></dt>
<dd>
</dd>
<dt><a href="Message.html#downloadMedia">downloadMedia()</a></dt>
<dd>
</dd>
<dt><a href="Message.html#forward">forward(chat)</a></dt>
<dd>
</dd>
<dt><a href="Message.html#getChat">getChat()</a></dt>
<dd>
</dd>
</dl>
</div>
<div class="summary-column">
<dl class="dl-summary-callout">
<dt><a href="Message.html#getContact">getContact()</a></dt>
<dd>
</dd>
<dt><a href="Message.html#getInfo">getInfo()</a></dt>
<dd>
</dd>
<dt><a href="Message.html#getMentions">getMentions()</a></dt>
<dd>
</dd>
<dt><a href="Message.html#getOrder">getOrder()</a></dt>
<dd>
</dd>
<dt><a href="Message.html#getQuotedMessage">getQuotedMessage()</a></dt>
<dd>
</dd>
</dl>
</div>
<div class="summary-column">
<dl class="dl-summary-callout">
<dt><a href="Message.html#reply">reply(content[, chatId][, options])</a></dt>
<dd>
</dd>
<dt><a href="Message.html#star">star()</a></dt>
<dd>
</dd>
<dt><a href="Message.html#unstar">unstar()</a></dt>
<dd>
</dd>
</dl>
</div>
</div>
</div>
</section>
<section>
<h2 id="Message">new&nbsp;<span class="symbol-name">Message</span><span class="signature"><span class="signature-params">()</span></span></h2>
<dl class="dl-compact">
<dt>Extends</dt>
<dd><a href="Base.html">Base</a></dd>
</dl>
</section>
<section>
<h2>Properties</h2>
<section>
<h3 id="ack"><span class="symbol-name">ack</span><small class="property-type">
&nbsp;<a href="global.html#MessageAck">MessageAck</a></small></h3>
<p>ACK status for the message</p>
<dl class="dl-compact">
</dl>
<h3 id="author"><span class="symbol-name">author</span><small class="property-type">
&nbsp;string</small></h3>
<p>If the message was sent to a group, this field will contain the user that sent the message.</p>
<dl class="dl-compact">
</dl>
<h3 id="body"><span class="symbol-name">body</span><small class="property-type">
&nbsp;string</small></h3>
<p>Message content</p>
<dl class="dl-compact">
</dl>
<h3 id="broadcast"><span class="symbol-name">broadcast</span><small class="property-type">
&nbsp;boolean</small></h3>
<p>Indicates if the message was a broadcast</p>
<dl class="dl-compact">
</dl>
<h3 id="deviceType"><span class="symbol-name">deviceType</span><small class="property-type">
&nbsp;string</small></h3>
<p>String that represents from which device type the message was sent</p>
<dl class="dl-compact">
</dl>
<h3 id="forwardingScore"><span class="symbol-name">forwardingScore</span><small class="property-type">
&nbsp;number</small></h3>
<p>Indicates how many times the message was forwarded.</p>
<p>The maximum value is 127.</p>
<dl class="dl-compact">
</dl>
<h3 id="from"><span class="symbol-name">from</span><small class="property-type">
&nbsp;string</small></h3>
<p>ID for the Chat that this message was sent to, except if the message was sent by the current user.</p>
<dl class="dl-compact">
</dl>
<h3 id="fromMe"><span class="symbol-name">fromMe</span><small class="property-type">
&nbsp;boolean</small></h3>
<p>Indicates if the message was sent by the current user</p>
<dl class="dl-compact">
</dl>
<h3 id="hasMedia"><span class="symbol-name">hasMedia</span><small class="property-type">
&nbsp;boolean</small></h3>
<p>Indicates if the message has media available for download</p>
<dl class="dl-compact">
</dl>
<h3 id="hasQuotedMsg"><span class="symbol-name">hasQuotedMsg</span><small class="property-type">
&nbsp;boolean</small></h3>
<p>Indicates if the message was sent as a reply to another message.</p>
<dl class="dl-compact">
</dl>
<h3 id="id"><span class="symbol-name">id</span><small class="property-type">
&nbsp;object</small></h3>
<p>ID that represents the message</p>
<dl class="dl-compact">
</dl>
<h3 id="inviteV4"><span class="symbol-name">inviteV4</span><small class="property-type">
&nbsp;object</small></h3>
<p>Group Invite Data</p>
<dl class="dl-compact">
</dl>
<h3 id="isForwarded"><span class="symbol-name">isForwarded</span><small class="property-type">
&nbsp;boolean</small></h3>
<p>Indicates if the message was forwarded</p>
<dl class="dl-compact">
</dl>
<h3 id="isStarred"><span class="symbol-name">isStarred</span><small class="property-type">
&nbsp;boolean</small></h3>
<p>Indicates if the message was starred</p>
<dl class="dl-compact">
</dl>
<h3 id="isStatus"><span class="symbol-name">isStatus</span><small class="property-type">
&nbsp;boolean</small></h3>
<p>Indicates if the message is a status update</p>
<dl class="dl-compact">
</dl>
<h3 id="links"><span class="symbol-name">links</span><small class="property-type">
&nbsp;Array of {link: string, isSuspicious: boolean}</small></h3>
<p>Links included in the message.</p>
<dl class="dl-compact">
</dl>
<h3 id="location"><span class="symbol-name">location</span><small class="property-type">
&nbsp;<a href="Location.html">Location</a></small></h3>
<p>Location information contained in the message, if the message is type &quot;location&quot;</p>
<dl class="dl-compact">
</dl>
<h3 id="mediaKey"><span class="symbol-name">mediaKey</span><small class="property-type">
&nbsp;string</small></h3>
<p>MediaKey that represents the sticker 'ID'</p>
<dl class="dl-compact">
</dl>
<h3 id="mentionedIds"><span class="symbol-name">mentionedIds</span><small class="property-type">
&nbsp;Array of string</small></h3>
<p>Indicates the mentions in the message body.</p>
<dl class="dl-compact">
</dl>
<h3 id="orderId"><span class="symbol-name">orderId</span><small class="property-type">
&nbsp;string</small></h3>
<p>Order ID for message type ORDER</p>
<dl class="dl-compact">
</dl>
<h3 id="timestamp"><span class="symbol-name">timestamp</span><small class="property-type">
&nbsp;number</small></h3>
<p>Unix timestamp for when the message was created</p>
<dl class="dl-compact">
</dl>
<h3 id="to"><span class="symbol-name">to</span><small class="property-type">
&nbsp;string</small></h3>
<p>ID for who this message is for.</p>
<p>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.</p>
<dl class="dl-compact">
</dl>
<h3 id="token"><span class="symbol-name">token</span><small class="property-type">
&nbsp;string</small></h3>
<p>Order Token for message type ORDER</p>
<dl class="dl-compact">
</dl>
<h3 id="type"><span class="symbol-name">type</span><small class="property-type">
&nbsp;<a href="global.html#MessageTypes">MessageTypes</a></small></h3>
<p>Message type</p>
<dl class="dl-compact">
</dl>
<h3 id="vCards"><span class="symbol-name">vCards</span><small class="property-type">
&nbsp;Array of string</small></h3>
<p>List of vCards contained in the message.</p>
<dl class="dl-compact">
</dl>
</section>
<h2>Methods</h2>
<section>
<div class="symbol-detail-labels"><span class="label label-async">async</span></div>
<h3 id="acceptGroupV4Invite"><span class="symbol-name">acceptGroupV4Invite</span><span class="signature"><span class="signature-params">()</span>&nbsp;&rarr; <span class="signature-returns"> Promise containing Object</span></span></h3>
<p>Accept Group V4 Invite</p>
<dl class="dl-compact">
<dt>Returns</dt>
<dd>
<p><code>Promise containing Object</code> </p>
</dd>
</dl>
<div class="symbol-detail-labels"><span class="label label-async">async</span></div>
<h3 id="delete"><span class="symbol-name">delete</span><span class="signature"><span class="signature-params">(everyone)</span></span></h3>
<p>Deletes a message from the chat</p>
<section>
<h4>Parameter</h4>
<table class="jsdoc-details-table">
<thead>
<tr>
<th>Name</th>
<th>Type</th>
<th>Optional</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<p>everyone</p>
</td>
<td>
<p>boolean</p>
</td>
<td>
<p>&nbsp;</p>
</td>
<td>
<p>If true and the message is sent by the current user, will delete it for everyone in the chat.</p>
<p>Value can be null.</p>
</td>
</tr>
</tbody>
</table>
</section>
<dl class="dl-compact">
</dl>
<div class="symbol-detail-labels"><span class="label label-async">async</span></div>
<h3 id="downloadMedia"><span class="symbol-name">downloadMedia</span><span class="signature"><span class="signature-params">()</span>&nbsp;&rarr; <span class="signature-returns"> Promise containing <a href="MessageMedia.html">MessageMedia</a></span></span></h3>
<p>Downloads and returns the attatched message media</p>
<dl class="dl-compact">
<dt>Returns</dt>
<dd>
<p><code>Promise containing <a href="MessageMedia.html">MessageMedia</a></code> </p>
</dd>
</dl>
<div class="symbol-detail-labels"><span class="label label-async">async</span></div>
<h3 id="forward"><span class="symbol-name">forward</span><span class="signature"><span class="signature-params">(chat)</span>&nbsp;&rarr; <span class="signature-returns"> Promise</span></span></h3>
<p>Forwards this message to another chat</p>
<section>
<h4>Parameter</h4>
<table class="jsdoc-details-table">
<thead>
<tr>
<th>Name</th>
<th>Type</th>
<th>Optional</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<p>chat</p>
</td>
<td>
<p>(string or <a href="Chat.html">Chat</a>)</p>
</td>
<td>
<p>&nbsp;</p>
</td>
<td>
<p>Chat model or chat ID to which the message will be forwarded</p>
</td>
</tr>
</tbody>
</table>
</section>
<dl class="dl-compact">
<dt>Returns</dt>
<dd>
<p><code>Promise</code> </p>
</dd>
</dl>
<h3 id="getChat"><span class="symbol-name">getChat</span><span class="signature"><span class="signature-params">()</span>&nbsp;&rarr; <span class="signature-returns"> Promise containing <a href="Chat.html">Chat</a></span></span></h3>
<p>Returns the Chat this message was sent in</p>
<dl class="dl-compact">
<dt>Returns</dt>
<dd>
<p><code>Promise containing <a href="Chat.html">Chat</a></code> </p>
</dd>
</dl>
<h3 id="getContact"><span class="symbol-name">getContact</span><span class="signature"><span class="signature-params">()</span>&nbsp;&rarr; <span class="signature-returns"> Promise containing <a href="Contact.html">Contact</a></span></span></h3>
<p>Returns the Contact this message was sent from</p>
<dl class="dl-compact">
<dt>Returns</dt>
<dd>
<p><code>Promise containing <a href="Contact.html">Contact</a></code> </p>
</dd>
</dl>
<div class="symbol-detail-labels"><span class="label label-async">async</span></div>
<h3 id="getInfo"><span class="symbol-name">getInfo</span><span class="signature"><span class="signature-params">()</span>&nbsp;&rarr; <span class="signature-returns"> Promise containing nullable <a href="global.html#MessageInfo">MessageInfo</a></span></span></h3>
<p>Get information about message delivery status. May return null if the message does not exist or is not sent by you.</p>
<dl class="dl-compact">
<dt>Returns</dt>
<dd>
<p><code>Promise containing nullable <a href="global.html#MessageInfo">MessageInfo</a></code> </p>
</dd>
</dl>
<div class="symbol-detail-labels"><span class="label label-async">async</span></div>
<h3 id="getMentions"><span class="symbol-name">getMentions</span><span class="signature"><span class="signature-params">()</span>&nbsp;&rarr; <span class="signature-returns"> Promise containing Array of <a href="Contact.html">Contact</a></span></span></h3>
<p>Returns the Contacts mentioned in this message</p>
<dl class="dl-compact">
<dt>Returns</dt>
<dd>
<p><code>Promise containing Array of <a href="Contact.html">Contact</a></code> </p>
</dd>
</dl>
<div class="symbol-detail-labels"><span class="label label-async">async</span></div>
<h3 id="getOrder"><span class="symbol-name">getOrder</span><span class="signature"><span class="signature-params">()</span>&nbsp;&rarr; <span class="signature-returns"> Promise containing <a href="Order.html">Order</a></span></span></h3>
<p>Gets the order associated with a given message</p>
<dl class="dl-compact">
<dt>Returns</dt>
<dd>
<p><code>Promise containing <a href="Order.html">Order</a></code> </p>
</dd>
</dl>
<div class="symbol-detail-labels"><span class="label label-async">async</span></div>
<h3 id="getQuotedMessage"><span class="symbol-name">getQuotedMessage</span><span class="signature"><span class="signature-params">()</span>&nbsp;&rarr; <span class="signature-returns"> Promise containing <a href="Message.html">Message</a></span></span></h3>
<p>Returns the quoted message, if any</p>
<dl class="dl-compact">
<dt>Returns</dt>
<dd>
<p><code>Promise containing <a href="Message.html">Message</a></code> </p>
</dd>
</dl>
<div class="symbol-detail-labels"><span class="label label-async">async</span></div>
<h3 id="reply"><span class="symbol-name">reply</span><span class="signature"><span class="signature-params">(content[, chatId][, options])</span>&nbsp;&rarr; <span class="signature-returns"> Promise containing <a href="Message.html">Message</a></span></span></h3>
<p>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.</p>
<section>
<h4>Parameters</h4>
<table class="jsdoc-details-table">
<thead>
<tr>
<th>Name</th>
<th>Type</th>
<th>Optional</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<p>content</p>
</td>
<td>
<p>(string, <a href="MessageMedia.html">MessageMedia</a>, or <a href="Location.html">Location</a>)</p>
</td>
<td>
<p>&nbsp;</p>
</td>
<td>
</td>
</tr>
<tr>
<td>
<p>chatId</p>
</td>
<td>
<p>string</p>
</td>
<td>
<p>Yes</p>
</td>
<td>
</td>
</tr>
<tr>
<td>
<p>options</p>
</td>
<td>
<p><a href="global.html#MessageSendOptions">MessageSendOptions</a></p>
</td>
<td>
<p>Yes</p>
</td>
<td>
</td>
</tr>
</tbody>
</table>
</section>
<dl class="dl-compact">
<dt>Returns</dt>
<dd>
<p><code>Promise containing <a href="Message.html">Message</a></code> </p>
</dd>
</dl>
<div class="symbol-detail-labels"><span class="label label-async">async</span></div>
<h3 id="star"><span class="symbol-name">star</span><span class="signature"><span class="signature-params">()</span></span></h3>
<p>Stars this message</p>
<dl class="dl-compact">
</dl>
<div class="symbol-detail-labels"><span class="label label-async">async</span></div>
<h3 id="unstar"><span class="symbol-name">unstar</span><span class="signature"><span class="signature-params">()</span></span></h3>
<p>Unstars this message</p>
<dl class="dl-compact">
</dl>
</section>
</section>
</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 September 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>

345
docs/MessageMedia.html Normal file
View File

@@ -0,0 +1,345 @@
<!doctype html>
<html>
<head>
<meta name="generator" content="JSDoc 3.6.7">
<meta charset="utf-8">
<title>whatsapp-web.js 1.14.1 &raquo; Class: MessageMedia</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>1</a>
</div>
</div>
</nav>
<div id="jsdoc-body-container">
<div id="jsdoc-content">
<div id="jsdoc-content-container">
<div id="jsdoc-main" role="main">
<header class="page-header">
<div class="symbol-detail-labels"><span class="label label-kind">class</span></div>
<h1><small></small><span class="symbol-name">MessageMedia</span></h1>
<p class="source-link">Source: <a href="structures_MessageMedia.js.html#source-line-15">structures/<wbr>MessageMedia.<wbr>js:15</a></p>
<div class="symbol-classdesc">
<p>Media attached to a message</p>
</div>
<dl class="dl-compact">
</dl>
</header>
<section id="summary">
<div class="summary-callout">
<h2 class="summary-callout-heading">Properties</h2>
<div class="summary-content">
<div class="summary-column">
<dl class="dl-summary-callout">
<dt><a href="MessageMedia.html#data">data</a></dt>
<dd>
</dd>
</dl>
</div>
<div class="summary-column">
<dl class="dl-summary-callout">
<dt><a href="MessageMedia.html#filename">filename</a></dt>
<dd>
</dd>
</dl>
</div>
<div class="summary-column">
<dl class="dl-summary-callout">
<dt><a href="MessageMedia.html#mimetype">mimetype</a></dt>
<dd>
</dd>
</dl>
</div>
</div>
</div>
<div class="summary-callout">
<h2 class="summary-callout-heading">Methods</h2>
<div class="summary-content">
<div class="summary-column">
<dl class="dl-summary-callout">
<dt><a href="MessageMedia.html#.fromFilePath">fromFilePath(filePath)</a></dt>
<dd>
</dd>
</dl>
</div>
<div class="summary-column">
<dl class="dl-summary-callout">
<dt><a href="MessageMedia.html#.fromUrl">fromUrl(url[, options])</a></dt>
<dd>
</dd>
</dl>
</div>
<div class="summary-column">
</div>
</div>
</div>
</section>
<section>
<h2 id="MessageMedia">new&nbsp;<span class="symbol-name">MessageMedia</span><span class="signature"><span class="signature-params">(mimetype, data, filename)</span></span></h2>
<section>
<h3>Parameters</h3>
<table class="jsdoc-details-table">
<thead>
<tr>
<th>Name</th>
<th>Type</th>
<th>Optional</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<p>mimetype</p>
</td>
<td>
<p>&nbsp;</p>
</td>
<td>
<p>&nbsp;</p>
</td>
<td>
<p>MIME type of the attachment</p>
</td>
</tr>
<tr>
<td>
<p>data</p>
</td>
<td>
<p>&nbsp;</p>
</td>
<td>
<p>&nbsp;</p>
</td>
<td>
<p>Base64-encoded data of the file</p>
</td>
</tr>
<tr>
<td>
<p>filename</p>
</td>
<td>
<p>&nbsp;</p>
</td>
<td>
<p>&nbsp;</p>
</td>
<td>
<p>Document file name</p>
<p>Value can be null.</p>
</td>
</tr>
</tbody>
</table>
</section>
<dl class="dl-compact">
</dl>
</section>
<section>
<h2>Properties</h2>
<section>
<h3 id="data"><span class="symbol-name">data</span><small class="property-type">
&nbsp;string</small></h3>
<p>Base64 encoded data that represents the file</p>
<dl class="dl-compact">
</dl>
<h3 id="filename"><span class="symbol-name">filename</span><small class="property-type">
&nbsp;nullable string</small></h3>
<p>Name of the file (for documents)</p>
<dl class="dl-compact">
</dl>
<h3 id="mimetype"><span class="symbol-name">mimetype</span><small class="property-type">
&nbsp;string</small></h3>
<p>MIME type of the attachment</p>
<dl class="dl-compact">
</dl>
</section>
<h2>Methods</h2>
<section>
<div class="symbol-detail-labels"><span class="label label-static">static</span></div>
<h3 id=".fromFilePath"><span class="symbol-name">fromFilePath</span><span class="signature"><span class="signature-params">(filePath)</span>&nbsp;&rarr; <span class="signature-returns"> <a href="MessageMedia.html">MessageMedia</a></span></span></h3>
<p>Creates a MessageMedia instance from a local file path</p>
<section>
<h4>Parameter</h4>
<table class="jsdoc-details-table">
<thead>
<tr>
<th>Name</th>
<th>Type</th>
<th>Optional</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<p>filePath</p>
</td>
<td>
<p>string</p>
</td>
<td>
<p>&nbsp;</p>
</td>
<td>
</td>
</tr>
</tbody>
</table>
</section>
<dl class="dl-compact">
<dt>Returns</dt>
<dd>
<p><code><a href="MessageMedia.html">MessageMedia</a></code> </p>
</dd>
</dl>
<div class="symbol-detail-labels"><span class="label label-async">async</span>&nbsp;<span class="label label-static">static</span></div>
<h3 id=".fromUrl"><span class="symbol-name">fromUrl</span><span class="signature"><span class="signature-params">(url[, options])</span>&nbsp;&rarr; <span class="signature-returns"> Promise containing <a href="MessageMedia.html">MessageMedia</a></span></span></h3>
<p>Creates a MessageMedia instance from a URL</p>
<section>
<h4>Parameters</h4>
<table class="jsdoc-details-table">
<thead>
<tr>
<th>Name</th>
<th>Type</th>
<th>Optional</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<p>url</p>
</td>
<td>
<p>string</p>
</td>
<td>
<p>&nbsp;</p>
</td>
<td>
</td>
</tr>
<tr>
<td>
<p>options</p>
</td>
<td>
<p>Object</p>
</td>
<td>
<p>Yes</p>
</td>
<td>
<p>Values in <code>options</code> have the following properties:</p>
<table class="jsdoc-details-table">
<thead>
<tr>
<th>Name</th>
<th>Type</th>
<th>Optional</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<p>unsafeMime</p>
</td>
<td>
<p>number</p>
</td>
<td>
<p>Yes</p>
</td>
<td>
<p>Defaults to <code>false</code>.</p>
</td>
</tr>
<tr>
<td>
<p>client</p>
</td>
<td>
<p>object</p>
</td>
<td>
<p>Yes</p>
</td>
<td>
</td>
</tr>
<tr>
<td>
<p>reqOptions</p>
</td>
<td>
<p>object</p>
</td>
<td>
<p>Yes</p>
</td>
<td>
</td>
</tr>
<tr>
<td>
<p>reqOptions.size</p>
</td>
<td>
<p>number</p>
</td>
<td>
<p>Yes</p>
</td>
<td>
<p>Defaults to <code>0</code>.</p>
</td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
</section>
<dl class="dl-compact">
<dt>Returns</dt>
<dd>
<p><code>Promise containing <a href="MessageMedia.html">MessageMedia</a></code> </p>
</dd>
</dl>
</section>
</section>
</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 September 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>

117
docs/Order.html Normal file
View File

@@ -0,0 +1,117 @@
<!doctype html>
<html>
<head>
<meta name="generator" content="JSDoc 3.6.7">
<meta charset="utf-8">
<title>whatsapp-web.js 1.14.1 &raquo; Class: Order</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>1</a>
</div>
</div>
</nav>
<div id="jsdoc-body-container">
<div id="jsdoc-content">
<div id="jsdoc-content-container">
<div id="jsdoc-main" role="main">
<header class="page-header">
<div class="symbol-detail-labels"><span class="label label-kind">class</span></div>
<h1><small></small><span class="symbol-name">Order</span></h1>
<p class="source-link">Source: <a href="structures_Order.js.html#source-line-10">structures/<wbr>Order.<wbr>js:10</a></p>
<div class="symbol-classdesc">
<p>Represents a Order on WhatsApp</p>
</div>
<dl class="dl-compact">
</dl>
</header>
<section id="summary">
<div class="summary-callout">
<h2 class="summary-callout-heading">Properties</h2>
<div class="summary-content">
<div class="summary-column">
<dl class="dl-summary-callout">
<dt><a href="Order.html#createdAt">createdAt</a></dt>
<dd>
</dd>
<dt><a href="Order.html#currency">currency</a></dt>
<dd>
</dd>
</dl>
</div>
<div class="summary-column">
<dl class="dl-summary-callout">
<dt><a href="Order.html#subtotal">subtotal</a></dt>
<dd>
</dd>
<dt><a href="Order.html#total">total</a></dt>
<dd>
</dd>
</dl>
</div>
<div class="summary-column">
</div>
</div>
</div>
</section>
<section>
<h2 id="Order">new&nbsp;<span class="symbol-name">Order</span><span class="signature"><span class="signature-params">()</span></span></h2>
<dl class="dl-compact">
<dt>Extends</dt>
<dd><a href="Base.html">Base</a></dd>
</dl>
</section>
<section>
<h2>Properties</h2>
<section>
<h3 id="createdAt"><span class="symbol-name">createdAt</span><small class="property-type">
&nbsp;number</small></h3>
<p>Order Created At</p>
<dl class="dl-compact">
</dl>
<h3 id="currency"><span class="symbol-name">currency</span><small class="property-type">
&nbsp;string</small></h3>
<p>Order Currency</p>
<dl class="dl-compact">
</dl>
<h3 id="subtotal"><span class="symbol-name">subtotal</span><small class="property-type">
&nbsp;string</small></h3>
<p>Order Subtotal</p>
<dl class="dl-compact">
</dl>
<h3 id="total"><span class="symbol-name">total</span><small class="property-type">
&nbsp;string</small></h3>
<p>Order Total</p>
<dl class="dl-compact">
</dl>
</section>
</section>
</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 September 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>

534
docs/PrivateChat.html Normal file
View File

@@ -0,0 +1,534 @@
<!doctype html>
<html>
<head>
<meta name="generator" content="JSDoc 3.6.7">
<meta charset="utf-8">
<title>whatsapp-web.js 1.14.1 &raquo; Class: PrivateChat</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>1</a>
</div>
</div>
</nav>
<div id="jsdoc-body-container">
<div id="jsdoc-content">
<div id="jsdoc-content-container">
<div id="jsdoc-main" role="main">
<header class="page-header">
<div class="symbol-detail-labels"><span class="label label-kind">class</span></div>
<h1><small></small><span class="symbol-name">PrivateChat</span></h1>
<p class="source-link">Source: <a href="structures_PrivateChat.js.html#source-line-9">structures/<wbr>PrivateChat.<wbr>js:9</a></p>
<div class="symbol-classdesc">
<p>Represents a Private Chat on WhatsApp</p>
</div>
<dl class="dl-compact">
</dl>
</header>
<section id="summary">
<div class="summary-callout">
<h2 class="summary-callout-heading">Properties</h2>
<div class="summary-content">
<div class="summary-column">
<dl class="dl-summary-callout">
<dt><a href="PrivateChat.html#archived">archived</a></dt>
<dd>
</dd>
<dt><a href="PrivateChat.html#id">id</a></dt>
<dd>
</dd>
<dt><a href="PrivateChat.html#isGroup">isGroup</a></dt>
<dd>
</dd>
<dt><a href="PrivateChat.html#isMuted">isMuted</a></dt>
<dd>
</dd>
</dl>
</div>
<div class="summary-column">
<dl class="dl-summary-callout">
<dt><a href="PrivateChat.html#isReadOnly">isReadOnly</a></dt>
<dd>
</dd>
<dt><a href="PrivateChat.html#muteExpiration">muteExpiration</a></dt>
<dd>
</dd>
<dt><a href="PrivateChat.html#name">name</a></dt>
<dd>
</dd>
<dt><a href="PrivateChat.html#pinned">pinned</a></dt>
<dd>
</dd>
</dl>
</div>
<div class="summary-column">
<dl class="dl-summary-callout">
<dt><a href="PrivateChat.html#timestamp">timestamp</a></dt>
<dd>
</dd>
<dt><a href="PrivateChat.html#unreadCount">unreadCount</a></dt>
<dd>
</dd>
</dl>
</div>
</div>
</div>
<div class="summary-callout">
<h2 class="summary-callout-heading">Methods</h2>
<div class="summary-content">
<div class="summary-column">
<dl class="dl-summary-callout">
<dt><a href="PrivateChat.html#archive">archive()</a></dt>
<dd>
</dd>
<dt><a href="PrivateChat.html#clearMessages">clearMessages()</a></dt>
<dd>
</dd>
<dt><a href="PrivateChat.html#clearState">clearState()</a></dt>
<dd>
</dd>
<dt><a href="PrivateChat.html#delete">delete()</a></dt>
<dd>
</dd>
<dt><a href="PrivateChat.html#fetchMessages">fetchMessages(searchOptions)</a></dt>
<dd>
</dd>
<dt><a href="PrivateChat.html#getContact">getContact()</a></dt>
<dd>
</dd>
</dl>
</div>
<div class="summary-column">
<dl class="dl-summary-callout">
<dt><a href="PrivateChat.html#getLabels">getLabels()</a></dt>
<dd>
</dd>
<dt><a href="PrivateChat.html#markUnread">markUnread()</a></dt>
<dd>
</dd>
<dt><a href="PrivateChat.html#mute">mute(unmuteDate)</a></dt>
<dd>
</dd>
<dt><a href="PrivateChat.html#pin">pin()</a></dt>
<dd>
</dd>
<dt><a href="PrivateChat.html#sendMessage">sendMessage(content[, options])</a></dt>
<dd>
</dd>
<dt><a href="PrivateChat.html#sendSeen">sendSeen()</a></dt>
<dd>
</dd>
</dl>
</div>
<div class="summary-column">
<dl class="dl-summary-callout">
<dt><a href="PrivateChat.html#sendStateRecording">sendStateRecording()</a></dt>
<dd>
</dd>
<dt><a href="PrivateChat.html#sendStateTyping">sendStateTyping()</a></dt>
<dd>
</dd>
<dt><a href="PrivateChat.html#unarchive">unarchive()</a></dt>
<dd>
</dd>
<dt><a href="PrivateChat.html#unmute">unmute()</a></dt>
<dd>
</dd>
<dt><a href="PrivateChat.html#unpin">unpin()</a></dt>
<dd>
</dd>
</dl>
</div>
</div>
</div>
</section>
<section>
<h2 id="PrivateChat">new&nbsp;<span class="symbol-name">PrivateChat</span><span class="signature"><span class="signature-params">()</span></span></h2>
<dl class="dl-compact">
<dt>Extends</dt>
<dd><a href="Chat.html">Chat</a></dd>
</dl>
</section>
<section>
<h2>Properties</h2>
<section>
<h3 id="archived"><span class="symbol-name">archived</span><small class="property-type">
&nbsp;unknown</small></h3>
<p>Indicates if the Chat is archived</p>
<dl class="dl-compact">
<dt>Inherited from</dt>
<dd><a href="Chat.html#archived">Chat#archived</a></dd>
</dl>
<h3 id="id"><span class="symbol-name">id</span><small class="property-type">
&nbsp;unknown</small></h3>
<p>ID that represents the chat</p>
<dl class="dl-compact">
<dt>Inherited from</dt>
<dd><a href="Chat.html#id">Chat#id</a></dd>
</dl>
<h3 id="isGroup"><span class="symbol-name">isGroup</span><small class="property-type">
&nbsp;unknown</small></h3>
<p>Indicates if the Chat is a Group Chat</p>
<dl class="dl-compact">
<dt>Inherited from</dt>
<dd><a href="Chat.html#isGroup">Chat#isGroup</a></dd>
</dl>
<h3 id="isMuted"><span class="symbol-name">isMuted</span><small class="property-type">
&nbsp;unknown</small></h3>
<p>Indicates if the chat is muted or not</p>
<dl class="dl-compact">
<dt>Inherited from</dt>
<dd><a href="Chat.html#isMuted">Chat#isMuted</a></dd>
</dl>
<h3 id="isReadOnly"><span class="symbol-name">isReadOnly</span><small class="property-type">
&nbsp;unknown</small></h3>
<p>Indicates if the Chat is readonly</p>
<dl class="dl-compact">
<dt>Inherited from</dt>
<dd><a href="Chat.html#isReadOnly">Chat#isReadOnly</a></dd>
</dl>
<h3 id="muteExpiration"><span class="symbol-name">muteExpiration</span><small class="property-type">
&nbsp;unknown</small></h3>
<p>Unix timestamp for when the mute expires</p>
<dl class="dl-compact">
<dt>Inherited from</dt>
<dd><a href="Chat.html#muteExpiration">Chat#muteExpiration</a></dd>
</dl>
<h3 id="name"><span class="symbol-name">name</span><small class="property-type">
&nbsp;unknown</small></h3>
<p>Title of the chat</p>
<dl class="dl-compact">
<dt>Inherited from</dt>
<dd><a href="Chat.html#name">Chat#name</a></dd>
</dl>
<h3 id="pinned"><span class="symbol-name">pinned</span><small class="property-type">
&nbsp;unknown</small></h3>
<p>Indicates if the Chat is pinned</p>
<dl class="dl-compact">
<dt>Inherited from</dt>
<dd><a href="Chat.html#pinned">Chat#pinned</a></dd>
</dl>
<h3 id="timestamp"><span class="symbol-name">timestamp</span><small class="property-type">
&nbsp;unknown</small></h3>
<p>Unix timestamp for when the last activity occurred</p>
<dl class="dl-compact">
<dt>Inherited from</dt>
<dd><a href="Chat.html#timestamp">Chat#timestamp</a></dd>
</dl>
<h3 id="unreadCount"><span class="symbol-name">unreadCount</span><small class="property-type">
&nbsp;unknown</small></h3>
<p>Amount of messages unread</p>
<dl class="dl-compact">
<dt>Inherited from</dt>
<dd><a href="Chat.html#unreadCount">Chat#unreadCount</a></dd>
</dl>
</section>
<h2>Methods</h2>
<section>
<div class="symbol-detail-labels"><span class="label label-async">async</span></div>
<h3 id="archive"><span class="symbol-name">archive</span><span class="signature"><span class="signature-params">()</span></span></h3>
<p>Archives this chat</p>
<dl class="dl-compact">
<dt>Inherited from</dt>
<dd><a href="Chat.html#archive">Chat#archive</a></dd>
</dl>
<div class="symbol-detail-labels"><span class="label label-async">async</span></div>
<h3 id="clearMessages"><span class="symbol-name">clearMessages</span><span class="signature"><span class="signature-params">()</span>&nbsp;&rarr; <span class="signature-returns"> Promise containing Boolean</span></span></h3>
<p>Clears all messages from the chat</p>
<dl class="dl-compact">
<dt>Inherited from</dt>
<dd><a href="Chat.html#clearMessages">Chat#clearMessages</a></dd>
<dt>Returns</dt>
<dd>
<p>result</p>
</dd>
</dl>
<div class="symbol-detail-labels"><span class="label label-async">async</span></div>
<h3 id="clearState"><span class="symbol-name">clearState</span><span class="signature"><span class="signature-params">()</span></span></h3>
<p>Stops typing or recording in chat immediately.</p>
<dl class="dl-compact">
<dt>Inherited from</dt>
<dd><a href="Chat.html#clearState">Chat#clearState</a></dd>
</dl>
<div class="symbol-detail-labels"><span class="label label-async">async</span></div>
<h3 id="delete"><span class="symbol-name">delete</span><span class="signature"><span class="signature-params">()</span>&nbsp;&rarr; <span class="signature-returns"> Promise containing Boolean</span></span></h3>
<p>Deletes the chat</p>
<dl class="dl-compact">
<dt>Inherited from</dt>
<dd><a href="Chat.html#delete">Chat#delete</a></dd>
<dt>Returns</dt>
<dd>
<p>result</p>
</dd>
</dl>
<div class="symbol-detail-labels"><span class="label label-async">async</span></div>
<h3 id="fetchMessages"><span class="symbol-name">fetchMessages</span><span class="signature"><span class="signature-params">(searchOptions)</span>&nbsp;&rarr; <span class="signature-returns"> Promise containing Array of <a href="Message.html">Message</a></span></span></h3>
<p>Loads chat messages, sorted from earliest to latest.</p>
<section>
<h4>Parameters</h4>
<table class="jsdoc-details-table">
<thead>
<tr>
<th>Name</th>
<th>Type</th>
<th>Optional</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<p>searchOptions</p>
</td>
<td>
<p>&nbsp;</p>
</td>
<td>
<p>&nbsp;</p>
</td>
<td>
<p>Options for searching messages. Right now only limit is supported.</p>
<p>Values in <code>searchOptions</code> have the following properties:</p>
<table class="jsdoc-details-table">
<thead>
<tr>
<th>Name</th>
<th>Type</th>
<th>Optional</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<p>limit</p>
</td>
<td>
<p>&nbsp;</p>
</td>
<td>
<p>Yes</p>
</td>
<td>
<p>The amount of messages to return. Note that the actual number of returned messages may be smaller if there aren't enough messages in the conversation. Set this to Infinity to load all messages.</p>
<p>Defaults to <code>50</code>.</p>
</td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
</section>
<dl class="dl-compact">
<dt>Inherited from</dt>
<dd><a href="Chat.html#fetchMessages">Chat#fetchMessages</a></dd>
<dt>Returns</dt>
<dd></dd>
</dl>
<div class="symbol-detail-labels"><span class="label label-async">async</span></div>
<h3 id="getContact"><span class="symbol-name">getContact</span><span class="signature"><span class="signature-params">()</span>&nbsp;&rarr; <span class="signature-returns"> Promise containing <a href="Contact.html">Contact</a></span></span></h3>
<p>Returns the Contact that corresponds to this Chat.</p>
<dl class="dl-compact">
<dt>Inherited from</dt>
<dd><a href="Chat.html#getContact">Chat#getContact</a></dd>
<dt>Returns</dt>
<dd></dd>
</dl>
<div class="symbol-detail-labels"><span class="label label-async">async</span></div>
<h3 id="getLabels"><span class="symbol-name">getLabels</span><span class="signature"><span class="signature-params">()</span>&nbsp;&rarr; <span class="signature-returns"> Promise containing Array of <a href="Label.html">Label</a></span></span></h3>
<p>Returns array of all Labels assigned to this Chat</p>
<dl class="dl-compact">
<dt>Inherited from</dt>
<dd><a href="Chat.html#getLabels">Chat#getLabels</a></dd>
<dt>Returns</dt>
<dd></dd>
</dl>
<div class="symbol-detail-labels"><span class="label label-async">async</span></div>
<h3 id="markUnread"><span class="symbol-name">markUnread</span><span class="signature"><span class="signature-params">()</span></span></h3>
<p>Mark this chat as unread</p>
<dl class="dl-compact">
<dt>Inherited from</dt>
<dd><a href="Chat.html#markUnread">Chat#markUnread</a></dd>
</dl>
<div class="symbol-detail-labels"><span class="label label-async">async</span></div>
<h3 id="mute"><span class="symbol-name">mute</span><span class="signature"><span class="signature-params">(unmuteDate)</span></span></h3>
<p>Mutes this chat until a specified date</p>
<section>
<h4>Parameter</h4>
<table class="jsdoc-details-table">
<thead>
<tr>
<th>Name</th>
<th>Type</th>
<th>Optional</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<p>unmuteDate</p>
</td>
<td>
<p>&nbsp;</p>
</td>
<td>
<p>&nbsp;</p>
</td>
<td>
<p>Date at which the Chat will be unmuted</p>
</td>
</tr>
</tbody>
</table>
</section>
<dl class="dl-compact">
<dt>Inherited from</dt>
<dd><a href="Chat.html#mute">Chat#mute</a></dd>
</dl>
<div class="symbol-detail-labels"><span class="label label-async">async</span></div>
<h3 id="pin"><span class="symbol-name">pin</span><span class="signature"><span class="signature-params">()</span>&nbsp;&rarr; <span class="signature-returns"> Promise containing boolean</span></span></h3>
<p>Pins this chat</p>
<dl class="dl-compact">
<dt>Inherited from</dt>
<dd><a href="Chat.html#pin">Chat#pin</a></dd>
<dt>Returns</dt>
<dd>
<p>New pin state. Could be false if the max number of pinned chats was reached.</p>
</dd>
</dl>
<div class="symbol-detail-labels"><span class="label label-async">async</span></div>
<h3 id="sendMessage"><span class="symbol-name">sendMessage</span><span class="signature"><span class="signature-params">(content[, options])</span>&nbsp;&rarr; <span class="signature-returns"> Promise containing <a href="Message.html">Message</a></span></span></h3>
<p>Send a message to this chat</p>
<section>
<h4>Parameters</h4>
<table class="jsdoc-details-table">
<thead>
<tr>
<th>Name</th>
<th>Type</th>
<th>Optional</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<p>content</p>
</td>
<td>
<p>&nbsp;</p>
</td>
<td>
<p>&nbsp;</p>
</td>
<td>
</td>
</tr>
<tr>
<td>
<p>options</p>
</td>
<td>
<p>&nbsp;</p>
</td>
<td>
<p>Yes</p>
</td>
<td>
</td>
</tr>
</tbody>
</table>
</section>
<dl class="dl-compact">
<dt>Inherited from</dt>
<dd><a href="Chat.html#sendMessage">Chat#sendMessage</a></dd>
<dt>Returns</dt>
<dd>
<p>Message that was just sent</p>
</dd>
</dl>
<div class="symbol-detail-labels"><span class="label label-async">async</span></div>
<h3 id="sendSeen"><span class="symbol-name">sendSeen</span><span class="signature"><span class="signature-params">()</span>&nbsp;&rarr; <span class="signature-returns"> Promise containing Boolean</span></span></h3>
<p>Set the message as seen</p>
<dl class="dl-compact">
<dt>Inherited from</dt>
<dd><a href="Chat.html#sendSeen">Chat#sendSeen</a></dd>
<dt>Returns</dt>
<dd>
<p>result</p>
</dd>
</dl>
<div class="symbol-detail-labels"><span class="label label-async">async</span></div>
<h3 id="sendStateRecording"><span class="symbol-name">sendStateRecording</span><span class="signature"><span class="signature-params">()</span></span></h3>
<p>Simulate recording audio in chat. This will last for 25 seconds.</p>
<dl class="dl-compact">
<dt>Inherited from</dt>
<dd><a href="Chat.html#sendStateRecording">Chat#sendStateRecording</a></dd>
</dl>
<div class="symbol-detail-labels"><span class="label label-async">async</span></div>
<h3 id="sendStateTyping"><span class="symbol-name">sendStateTyping</span><span class="signature"><span class="signature-params">()</span></span></h3>
<p>Simulate typing in chat. This will last for 25 seconds.</p>
<dl class="dl-compact">
<dt>Inherited from</dt>
<dd><a href="Chat.html#sendStateTyping">Chat#sendStateTyping</a></dd>
</dl>
<div class="symbol-detail-labels"><span class="label label-async">async</span></div>
<h3 id="unarchive"><span class="symbol-name">unarchive</span><span class="signature"><span class="signature-params">()</span></span></h3>
<p>un-archives this chat</p>
<dl class="dl-compact">
<dt>Inherited from</dt>
<dd><a href="Chat.html#unarchive">Chat#unarchive</a></dd>
</dl>
<div class="symbol-detail-labels"><span class="label label-async">async</span></div>
<h3 id="unmute"><span class="symbol-name">unmute</span><span class="signature"><span class="signature-params">()</span></span></h3>
<p>Unmutes this chat</p>
<dl class="dl-compact">
<dt>Inherited from</dt>
<dd><a href="Chat.html#unmute">Chat#unmute</a></dd>
</dl>
<div class="symbol-detail-labels"><span class="label label-async">async</span></div>
<h3 id="unpin"><span class="symbol-name">unpin</span><span class="signature"><span class="signature-params">()</span>&nbsp;&rarr; <span class="signature-returns"> Promise containing boolean</span></span></h3>
<p>Unpins this chat</p>
<dl class="dl-compact">
<dt>Inherited from</dt>
<dd><a href="Chat.html#unpin">Chat#unpin</a></dd>
<dt>Returns</dt>
<dd>
<p>New pin state</p>
</dd>
</dl>
</section>
</section>
</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 September 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>

298
docs/PrivateContact.html Normal file
View File

@@ -0,0 +1,298 @@
<!doctype html>
<html>
<head>
<meta name="generator" content="JSDoc 3.6.7">
<meta charset="utf-8">
<title>whatsapp-web.js 1.14.1 &raquo; Class: PrivateContact</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>1</a>
</div>
</div>
</nav>
<div id="jsdoc-body-container">
<div id="jsdoc-content">
<div id="jsdoc-content-container">
<div id="jsdoc-main" role="main">
<header class="page-header">
<div class="symbol-detail-labels"><span class="label label-kind">class</span></div>
<h1><small></small><span class="symbol-name">PrivateContact</span></h1>
<p class="source-link">Source: <a href="structures_PrivateContact.js.html#source-line-9">structures/<wbr>PrivateContact.<wbr>js:9</a></p>
<div class="symbol-classdesc">
<p>Represents a Private Contact on WhatsApp</p>
</div>
<dl class="dl-compact">
</dl>
</header>
<section id="summary">
<div class="summary-callout">
<h2 class="summary-callout-heading">Properties</h2>
<div class="summary-content">
<div class="summary-column">
<dl class="dl-summary-callout">
<dt><a href="PrivateContact.html#id">id</a></dt>
<dd>
</dd>
<dt><a href="PrivateContact.html#isBlocked">isBlocked</a></dt>
<dd>
</dd>
<dt><a href="PrivateContact.html#isBusiness">isBusiness</a></dt>
<dd>
</dd>
<dt><a href="PrivateContact.html#isEnterprise">isEnterprise</a></dt>
<dd>
</dd>
<dt><a href="PrivateContact.html#isGroup">isGroup</a></dt>
<dd>
</dd>
</dl>
</div>
<div class="summary-column">
<dl class="dl-summary-callout">
<dt><a href="PrivateContact.html#isMe">isMe</a></dt>
<dd>
</dd>
<dt><a href="PrivateContact.html#isMyContact">isMyContact</a></dt>
<dd>
</dd>
<dt><a href="PrivateContact.html#isUser">isUser</a></dt>
<dd>
</dd>
<dt><a href="PrivateContact.html#isWAContact">isWAContact</a></dt>
<dd>
</dd>
<dt><a href="PrivateContact.html#name">name</a></dt>
<dd>
</dd>
</dl>
</div>
<div class="summary-column">
<dl class="dl-summary-callout">
<dt><a href="PrivateContact.html#number">number</a></dt>
<dd>
</dd>
<dt><a href="PrivateContact.html#pushname">pushname</a></dt>
<dd>
</dd>
<dt><a href="PrivateContact.html#shortName">shortName</a></dt>
<dd>
</dd>
</dl>
</div>
</div>
</div>
<div class="summary-callout">
<h2 class="summary-callout-heading">Methods</h2>
<div class="summary-content">
<div class="summary-column">
<dl class="dl-summary-callout">
<dt><a href="PrivateContact.html#block">block()</a></dt>
<dd>
</dd>
<dt><a href="PrivateContact.html#getAbout">getAbout()</a></dt>
<dd>
</dd>
</dl>
</div>
<div class="summary-column">
<dl class="dl-summary-callout">
<dt><a href="PrivateContact.html#getChat">getChat()</a></dt>
<dd>
</dd>
<dt><a href="PrivateContact.html#getProfilePicUrl">getProfilePicUrl()</a></dt>
<dd>
</dd>
</dl>
</div>
<div class="summary-column">
<dl class="dl-summary-callout">
<dt><a href="PrivateContact.html#unblock">unblock()</a></dt>
<dd>
</dd>
</dl>
</div>
</div>
</div>
</section>
<section>
<h2 id="PrivateContact">new&nbsp;<span class="symbol-name">PrivateContact</span><span class="signature"><span class="signature-params">()</span></span></h2>
<dl class="dl-compact">
<dt>Extends</dt>
<dd><a href="Contact.html">Contact</a></dd>
</dl>
</section>
<section>
<h2>Properties</h2>
<section>
<h3 id="id"><span class="symbol-name">id</span><small class="property-type">
&nbsp;unknown</small></h3>
<p>ID that represents the contact</p>
<dl class="dl-compact">
<dt>Inherited from</dt>
<dd><a href="Contact.html#id">Contact#id</a></dd>
</dl>
<h3 id="isBlocked"><span class="symbol-name">isBlocked</span><small class="property-type">
&nbsp;unknown</small></h3>
<p>Indicates if you have blocked this contact</p>
<dl class="dl-compact">
<dt>Inherited from</dt>
<dd><a href="Contact.html#isBlocked">Contact#isBlocked</a></dd>
</dl>
<h3 id="isBusiness"><span class="symbol-name">isBusiness</span><small class="property-type">
&nbsp;unknown</small></h3>
<p>Indicates if the contact is a business contact</p>
<dl class="dl-compact">
<dt>Inherited from</dt>
<dd><a href="Contact.html#isBusiness">Contact#isBusiness</a></dd>
</dl>
<h3 id="isEnterprise"><span class="symbol-name">isEnterprise</span><small class="property-type">
&nbsp;unknown</small></h3>
<p>Indicates if the contact is an enterprise contact</p>
<dl class="dl-compact">
<dt>Inherited from</dt>
<dd><a href="Contact.html#isEnterprise">Contact#isEnterprise</a></dd>
</dl>
<h3 id="isGroup"><span class="symbol-name">isGroup</span><small class="property-type">
&nbsp;unknown</small></h3>
<p>Indicates if the contact is a group contact</p>
<dl class="dl-compact">
<dt>Inherited from</dt>
<dd><a href="Contact.html#isGroup">Contact#isGroup</a></dd>
</dl>
<h3 id="isMe"><span class="symbol-name">isMe</span><small class="property-type">
&nbsp;unknown</small></h3>
<p>Indicates if the contact is the current user's contact</p>
<dl class="dl-compact">
<dt>Inherited from</dt>
<dd><a href="Contact.html#isMe">Contact#isMe</a></dd>
</dl>
<h3 id="isMyContact"><span class="symbol-name">isMyContact</span><small class="property-type">
&nbsp;unknown</small></h3>
<p>Indicates if the number is saved in the current phone's contacts</p>
<dl class="dl-compact">
<dt>Inherited from</dt>
<dd><a href="Contact.html#isMyContact">Contact#isMyContact</a></dd>
</dl>
<h3 id="isUser"><span class="symbol-name">isUser</span><small class="property-type">
&nbsp;unknown</small></h3>
<p>Indicates if the contact is a user contact</p>
<dl class="dl-compact">
<dt>Inherited from</dt>
<dd><a href="Contact.html#isUser">Contact#isUser</a></dd>
</dl>
<h3 id="isWAContact"><span class="symbol-name">isWAContact</span><small class="property-type">
&nbsp;unknown</small></h3>
<p>Indicates if the number is registered on WhatsApp</p>
<dl class="dl-compact">
<dt>Inherited from</dt>
<dd><a href="Contact.html#isWAContact">Contact#isWAContact</a></dd>
</dl>
<h3 id="name"><span class="symbol-name">name</span><small class="property-type">
&nbsp;unknown</small></h3>
<p>The contact's name, as saved by the current user</p>
<dl class="dl-compact">
<dt>Inherited from</dt>
<dd><a href="Contact.html#name">Contact#name</a></dd>
</dl>
<h3 id="number"><span class="symbol-name">number</span><small class="property-type">
&nbsp;unknown</small></h3>
<p>Contact's phone number</p>
<dl class="dl-compact">
<dt>Inherited from</dt>
<dd><a href="Contact.html#number">Contact#number</a></dd>
</dl>
<h3 id="pushname"><span class="symbol-name">pushname</span><small class="property-type">
&nbsp;unknown</small></h3>
<p>The name that the contact has configured to be shown publically</p>
<dl class="dl-compact">
<dt>Inherited from</dt>
<dd><a href="Contact.html#pushname">Contact#pushname</a></dd>
</dl>
<h3 id="shortName"><span class="symbol-name">shortName</span><small class="property-type">
&nbsp;unknown</small></h3>
<p>A shortened version of name</p>
<dl class="dl-compact">
<dt>Inherited from</dt>
<dd><a href="Contact.html#shortName">Contact#shortName</a></dd>
</dl>
</section>
<h2>Methods</h2>
<section>
<div class="symbol-detail-labels"><span class="label label-async">async</span></div>
<h3 id="block"><span class="symbol-name">block</span><span class="signature"><span class="signature-params">()</span>&nbsp;&rarr; <span class="signature-returns"> Promise containing boolean</span></span></h3>
<p>Blocks this contact from WhatsApp</p>
<dl class="dl-compact">
<dt>Inherited from</dt>
<dd><a href="Contact.html#block">Contact#block</a></dd>
<dt>Returns</dt>
<dd></dd>
</dl>
<div class="symbol-detail-labels"><span class="label label-async">async</span></div>
<h3 id="getAbout"><span class="symbol-name">getAbout</span><span class="signature"><span class="signature-params">()</span>&nbsp;&rarr; <span class="signature-returns"> Promise containing nullable string</span></span></h3>
<p>Gets the Contact's current &quot;about&quot; info. Returns null if you don't have permission to read their status.</p>
<dl class="dl-compact">
<dt>Inherited from</dt>
<dd><a href="Contact.html#getAbout">Contact#getAbout</a></dd>
<dt>Returns</dt>
<dd></dd>
</dl>
<div class="symbol-detail-labels"><span class="label label-async">async</span></div>
<h3 id="getChat"><span class="symbol-name">getChat</span><span class="signature"><span class="signature-params">()</span>&nbsp;&rarr; <span class="signature-returns"> Promise containing <a href="Chat.html">Chat</a></span></span></h3>
<p>Returns the Chat that corresponds to this Contact.
Will return null when getting chat for currently logged in user.</p>
<dl class="dl-compact">
<dt>Inherited from</dt>
<dd><a href="Contact.html#getChat">Contact#getChat</a></dd>
<dt>Returns</dt>
<dd></dd>
</dl>
<div class="symbol-detail-labels"><span class="label label-async">async</span></div>
<h3 id="getProfilePicUrl"><span class="symbol-name">getProfilePicUrl</span><span class="signature"><span class="signature-params">()</span>&nbsp;&rarr; <span class="signature-returns"> Promise containing string</span></span></h3>
<p>Returns the contact's profile picture URL, if privacy settings allow it</p>
<dl class="dl-compact">
<dt>Inherited from</dt>
<dd><a href="Contact.html#getProfilePicUrl">Contact#getProfilePicUrl</a></dd>
<dt>Returns</dt>
<dd></dd>
</dl>
<div class="symbol-detail-labels"><span class="label label-async">async</span></div>
<h3 id="unblock"><span class="symbol-name">unblock</span><span class="signature"><span class="signature-params">()</span>&nbsp;&rarr; <span class="signature-returns"> Promise containing boolean</span></span></h3>
<p>Unblocks this contact from WhatsApp</p>
<dl class="dl-compact">
<dt>Inherited from</dt>
<dd><a href="Contact.html#unblock">Contact#unblock</a></dd>
<dt>Returns</dt>
<dd></dd>
</dl>
</section>
</section>
</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 September 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>

142
docs/Product.html Normal file
View File

@@ -0,0 +1,142 @@
<!doctype html>
<html>
<head>
<meta name="generator" content="JSDoc 3.6.7">
<meta charset="utf-8">
<title>whatsapp-web.js 1.14.1 &raquo; Class: Product</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>1</a>
</div>
</div>
</nav>
<div id="jsdoc-body-container">
<div id="jsdoc-content">
<div id="jsdoc-content-container">
<div id="jsdoc-main" role="main">
<header class="page-header">
<div class="symbol-detail-labels"><span class="label label-kind">class</span></div>
<h1><small></small><span class="symbol-name">Product</span></h1>
<p class="source-link">Source: <a href="structures_Product.js.html#source-line-10">structures/<wbr>Product.<wbr>js:10</a></p>
<div class="symbol-classdesc">
<p>Represents a Product on WhatsAppBusiness</p>
</div>
<dl class="dl-compact">
</dl>
</header>
<section id="summary">
<div class="summary-callout">
<h2 class="summary-callout-heading">Properties</h2>
<div class="summary-content">
<div class="summary-column">
<dl class="dl-summary-callout">
<dt><a href="Product.html#currency">currency</a></dt>
<dd>
</dd>
<dt><a href="Product.html#data">data</a></dt>
<dd>
</dd>
<dt><a href="Product.html#id">id</a></dt>
<dd>
</dd>
</dl>
</div>
<div class="summary-column">
<dl class="dl-summary-callout">
<dt><a href="Product.html#name">name</a></dt>
<dd>
</dd>
<dt><a href="Product.html#price">price</a></dt>
<dd>
</dd>
<dt><a href="Product.html#quantity">quantity</a></dt>
<dd>
</dd>
</dl>
</div>
<div class="summary-column">
<dl class="dl-summary-callout">
<dt><a href="Product.html#thumbnailUrl">thumbnailUrl</a></dt>
<dd>
</dd>
</dl>
</div>
</div>
</div>
</section>
<section>
<h2 id="Product">new&nbsp;<span class="symbol-name">Product</span><span class="signature"><span class="signature-params">()</span></span></h2>
<dl class="dl-compact">
<dt>Extends</dt>
<dd><a href="Base.html">Base</a></dd>
</dl>
</section>
<section>
<h2>Properties</h2>
<section>
<h3 id="currency"><span class="symbol-name">currency</span><small class="property-type">
&nbsp;string</small></h3>
<p>Currency</p>
<dl class="dl-compact">
</dl>
<h3 id="data"><span class="symbol-name">data</span></h3>
<p>Product metadata</p>
<dl class="dl-compact">
</dl>
<h3 id="id"><span class="symbol-name">id</span><small class="property-type">
&nbsp;string</small></h3>
<p>Product ID</p>
<dl class="dl-compact">
</dl>
<h3 id="name"><span class="symbol-name">name</span><small class="property-type">
&nbsp;string</small></h3>
<p>Product Name</p>
<dl class="dl-compact">
</dl>
<h3 id="price"><span class="symbol-name">price</span><small class="property-type">
&nbsp;string</small></h3>
<p>Price</p>
<dl class="dl-compact">
</dl>
<h3 id="quantity"><span class="symbol-name">quantity</span><small class="property-type">
&nbsp;number</small></h3>
<p>Product Quantity</p>
<dl class="dl-compact">
</dl>
<h3 id="thumbnailUrl"><span class="symbol-name">thumbnailUrl</span><small class="property-type">
&nbsp;string</small></h3>
<p>Product Thumbnail</p>
<dl class="dl-compact">
</dl>
</section>
</section>
</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 September 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>

255
docs/Util.html Normal file
View File

@@ -0,0 +1,255 @@
<!doctype html>
<html>
<head>
<meta name="generator" content="JSDoc 3.6.7">
<meta charset="utf-8">
<title>whatsapp-web.js 1.14.1 &raquo; Class: Util</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>1</a>
</div>
</div>
</nav>
<div id="jsdoc-body-container">
<div id="jsdoc-content">
<div id="jsdoc-content-container">
<div id="jsdoc-main" role="main">
<header class="page-header">
<div class="symbol-detail-labels"><span class="label label-kind">class</span></div>
<h1><small></small><span class="symbol-name">Util</span></h1>
<p class="source-link">Source: <a href="util_Util.js.html#source-line-16">util/<wbr>Util.<wbr>js:16</a></p>
<div class="symbol-classdesc">
<p>Utility methods</p>
</div>
<dl class="dl-compact">
</dl>
</header>
<section id="summary">
<div class="summary-callout">
<h2 class="summary-callout-heading">Methods</h2>
<div class="summary-content">
<div class="summary-column">
<dl class="dl-summary-callout">
<dt><a href="Util.html#.formatImageToWebpSticker">formatImageToWebpSticker(media)</a></dt>
<dd>
</dd>
<dt><a href="Util.html#.formatToWebpSticker">formatToWebpSticker(media, metadata)</a></dt>
<dd>
</dd>
</dl>
</div>
<div class="summary-column">
<dl class="dl-summary-callout">
<dt><a href="Util.html#.formatVideoToWebpSticker">formatVideoToWebpSticker(media)</a></dt>
<dd>
</dd>
<dt><a href="Util.html#.setFfmpegPath">setFfmpegPath(path)</a></dt>
<dd>
</dd>
</dl>
</div>
<div class="summary-column">
</div>
</div>
</div>
</section>
<section>
<h2 id="Util">new&nbsp;<span class="symbol-name">Util</span><span class="signature"><span class="signature-params">()</span></span></h2>
<dl class="dl-compact">
</dl>
</section>
<section>
<h2>Methods</h2>
<section>
<div class="symbol-detail-labels"><span class="label label-async">async</span>&nbsp;<span class="label label-static">static</span></div>
<h3 id=".formatImageToWebpSticker"><span class="symbol-name">formatImageToWebpSticker</span><span class="signature"><span class="signature-params">(media)</span>&nbsp;&rarr; <span class="signature-returns"> Promise containing <a href="MessageMedia.html">MessageMedia</a></span></span></h3>
<p>Formats a image to webp</p>
<section>
<h4>Parameter</h4>
<table class="jsdoc-details-table">
<thead>
<tr>
<th>Name</th>
<th>Type</th>
<th>Optional</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<p>media</p>
</td>
<td>
<p><a href="MessageMedia.html">MessageMedia</a></p>
</td>
<td>
<p>&nbsp;</p>
</td>
<td>
</td>
</tr>
</tbody>
</table>
</section>
<dl class="dl-compact">
<dt>Returns</dt>
<dd>
<p><code>Promise containing <a href="MessageMedia.html">MessageMedia</a></code> <p>media in webp format</p>
</p>
</dd>
</dl>
<div class="symbol-detail-labels"><span class="label label-async">async</span>&nbsp;<span class="label label-static">static</span></div>
<h3 id=".formatToWebpSticker"><span class="symbol-name">formatToWebpSticker</span><span class="signature"><span class="signature-params">(media, metadata)</span>&nbsp;&rarr; <span class="signature-returns"> Promise containing <a href="MessageMedia.html">MessageMedia</a></span></span></h3>
<p>Formats a media to webp</p>
<section>
<h4>Parameters</h4>
<table class="jsdoc-details-table">
<thead>
<tr>
<th>Name</th>
<th>Type</th>
<th>Optional</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<p>media</p>
</td>
<td>
<p><a href="MessageMedia.html">MessageMedia</a></p>
</td>
<td>
<p>&nbsp;</p>
</td>
<td>
</td>
</tr>
<tr>
<td>
<p>metadata</p>
</td>
<td>
<p><a href="global.html#StickerMetadata">StickerMetadata</a></p>
</td>
<td>
<p>&nbsp;</p>
</td>
<td>
</td>
</tr>
</tbody>
</table>
</section>
<dl class="dl-compact">
<dt>Returns</dt>
<dd>
<p><code>Promise containing <a href="MessageMedia.html">MessageMedia</a></code> <p>media in webp format</p>
</p>
</dd>
</dl>
<div class="symbol-detail-labels"><span class="label label-async">async</span>&nbsp;<span class="label label-static">static</span></div>
<h3 id=".formatVideoToWebpSticker"><span class="symbol-name">formatVideoToWebpSticker</span><span class="signature"><span class="signature-params">(media)</span>&nbsp;&rarr; <span class="signature-returns"> Promise containing <a href="MessageMedia.html">MessageMedia</a></span></span></h3>
<p>Formats a video to webp</p>
<section>
<h4>Parameter</h4>
<table class="jsdoc-details-table">
<thead>
<tr>
<th>Name</th>
<th>Type</th>
<th>Optional</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<p>media</p>
</td>
<td>
<p><a href="MessageMedia.html">MessageMedia</a></p>
</td>
<td>
<p>&nbsp;</p>
</td>
<td>
</td>
</tr>
</tbody>
</table>
</section>
<dl class="dl-compact">
<dt>Returns</dt>
<dd>
<p><code>Promise containing <a href="MessageMedia.html">MessageMedia</a></code> <p>media in webp format</p>
</p>
</dd>
</dl>
<div class="symbol-detail-labels"><span class="label label-static">static</span></div>
<h3 id=".setFfmpegPath"><span class="symbol-name">setFfmpegPath</span><span class="signature"><span class="signature-params">(path)</span></span></h3>
<p>Configure ffmpeg path</p>
<section>
<h4>Parameter</h4>
<table class="jsdoc-details-table">
<thead>
<tr>
<th>Name</th>
<th>Type</th>
<th>Optional</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<p>path</p>
</td>
<td>
<p>string</p>
</td>
<td>
<p>&nbsp;</p>
</td>
<td>
</td>
</tr>
</tbody>
</table>
</section>
<dl class="dl-compact">
</dl>
</section>
</section>
</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 September 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>

4
docs/css/baseline.css Normal file

File diff suppressed because one or more lines are too long

1623
docs/global.html Normal file

File diff suppressed because it is too large Load Diff

2716
docs/index.html Normal file

File diff suppressed because it is too large Load Diff

2
docs/scripts/jquery.min.js vendored Normal file

File diff suppressed because one or more lines are too long

17
docs/scripts/jsdoc-toc.js Normal file
View File

@@ -0,0 +1,17 @@
(function($) {
// TODO: make the node ID configurable
var treeNode = $('#jsdoc-toc-nav');
// initialize the tree
treeNode.tree({
autoEscape: false,
closedIcon: '&#x21e2;',
data: [{"label":"<a href=\"global.html\">Globals</a>","id":"global","children":[]},{"label":"<a href=\"Base.html\">Base</a>","id":"Base","children":[]},{"label":"<a href=\"BusinessContact.html\">BusinessContact</a>","id":"BusinessContact","children":[]},{"label":"<a href=\"Call.html\">Call</a>","id":"Call","children":[]},{"label":"<a href=\"Chat.html\">Chat</a>","id":"Chat","children":[]},{"label":"<a href=\"Client.html\">Client</a>","id":"Client","children":[]},{"label":"<a href=\"ClientInfo.html\">ClientInfo</a>","id":"ClientInfo","children":[]},{"label":"<a href=\"Contact.html\">Contact</a>","id":"Contact","children":[]},{"label":"<a href=\"GroupChat.html\">GroupChat</a>","id":"GroupChat","children":[]},{"label":"<a href=\"GroupNotification.html\">GroupNotification</a>","id":"GroupNotification","children":[]},{"label":"<a href=\"InterfaceController.html\">InterfaceController</a>","id":"InterfaceController","children":[]},{"label":"<a href=\"Label.html\">Label</a>","id":"Label","children":[]},{"label":"<a href=\"Location.html\">Location</a>","id":"Location","children":[]},{"label":"<a href=\"Message.html\">Message</a>","id":"Message","children":[]},{"label":"<a href=\"MessageMedia.html\">MessageMedia</a>","id":"MessageMedia","children":[]},{"label":"<a href=\"Order.html\">Order</a>","id":"Order","children":[]},{"label":"<a href=\"PrivateChat.html\">PrivateChat</a>","id":"PrivateChat","children":[]},{"label":"<a href=\"PrivateContact.html\">PrivateContact</a>","id":"PrivateContact","children":[]},{"label":"<a href=\"Product.html\">Product</a>","id":"Product","children":[]},{"label":"<a href=\"Util.html\">Util</a>","id":"Util","children":[]}],
openedIcon: ' &#x21e3;',
saveState: false,
useContextMenu: false
});
// add event handlers
// TODO
})(jQuery);

1
docs/scripts/lang-css.js Normal file
View File

@@ -0,0 +1 @@
PR.registerLangHandler(PR.createSimpleLexer([[PR.PR_PLAIN,/^[ \t\r\n\f]+/,null," \t\r\n\f"]],[[PR.PR_STRING,/^\"(?:[^\n\r\f\\\"]|\\(?:\r\n?|\n|\f)|\\[\s\S])*\"/,null],[PR.PR_STRING,/^\'(?:[^\n\r\f\\\']|\\(?:\r\n?|\n|\f)|\\[\s\S])*\'/,null],["lang-css-str",/^url\(([^\)\"\']+)\)/i],[PR.PR_KEYWORD,/^(?:url|rgb|\!important|@import|@page|@media|@charset|inherit)(?=[^\-\w]|$)/i,null],["lang-css-kw",/^(-?(?:[_a-z]|(?:\\[0-9a-f]+ ?))(?:[_a-z0-9\-]|\\(?:\\[0-9a-f]+ ?))*)\s*:/i],[PR.PR_COMMENT,/^\/\*[^*]*\*+(?:[^\/*][^*]*\*+)*\//],[PR.PR_COMMENT,/^(?:<!--|-->)/],[PR.PR_LITERAL,/^(?:\d+|\d*\.\d+)(?:%|[a-z]+)?/i],[PR.PR_LITERAL,/^#(?:[0-9a-f]{3}){1,2}\b/i],[PR.PR_PLAIN,/^-?(?:[_a-z]|(?:\\[\da-f]+ ?))(?:[_a-z\d\-]|\\(?:\\[\da-f]+ ?))*/i],[PR.PR_PUNCTUATION,/^[^\s\w\'\"]+/]]),["css"]),PR.registerLangHandler(PR.createSimpleLexer([],[[PR.PR_KEYWORD,/^-?(?:[_a-z]|(?:\\[\da-f]+ ?))(?:[_a-z\d\-]|\\(?:\\[\da-f]+ ?))*/i]]),["css-kw"]),PR.registerLangHandler(PR.createSimpleLexer([],[[PR.PR_STRING,/^[^\)\"\']+/]]),["css-str"]);

View File

@@ -0,0 +1 @@
!function(){var n,e=0,t=document.getElementsByClassName("prettyprint");t&&t[0]&&(n=(n=(t=t[0].getElementsByTagName("code")[0]).innerHTML.split("\n")).map(function(n){return'<span id="source-line-'+ ++e+'" class="line"></span>'+n}),t.innerHTML=n.join("\n"))}();

1
docs/scripts/prettify.js Normal file

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1 @@
!function(){function o(n){var o,t,e=document.getElementById(n.replace(/^#/,""));e&&(t=e.getBoundingClientRect(),o=t.top+window.pageYOffset,setTimeout(function(){window.scrollTo(0,o-50)},5))}window.addEventListener("load",function(){var n=window.location.hash;n&&"#"!==n&&o(n),window.addEventListener("hashchange",function(){o(window.location.hash)})})}();

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,75 @@
<!doctype html>
<html>
<head>
<meta name="generator" content="JSDoc 3.6.7">
<meta charset="utf-8">
<title>whatsapp-web.js 1.14.1 &raquo; Source: structures/Base.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>1</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/Base.js</h1>
</header>
<article>
<pre class="prettyprint linenums"><code>&#x27;use strict&#x27;;
/**
* Represents a WhatsApp data structure
*/
class Base {
constructor(client) {
/**
* The client that instantiated this
* @readonly
*/
Object.defineProperty(this, &#x27;client&#x27;, { value: client });
}
_clone() {
return Object.assign(Object.create(this), this);
}
_patch(data) { return data; }
}
module.exports &#x3D; Base;</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 September 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>

View File

@@ -0,0 +1,74 @@
<!doctype html>
<html>
<head>
<meta name="generator" content="JSDoc 3.6.7">
<meta charset="utf-8">
<title>whatsapp-web.js 1.14.1 &raquo; Source: structures/BusinessContact.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>1</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/BusinessContact.js</h1>
</header>
<article>
<pre class="prettyprint linenums"><code>&#x27;use strict&#x27;;
const Contact &#x3D; require(&#x27;./Contact&#x27;);
/**
* Represents a Business Contact on WhatsApp
* @extends {Contact}
*/
class BusinessContact extends Contact {
_patch(data) {
/**
* The contact&#x27;s business profile
*/
this.businessProfile &#x3D; data.businessProfile;
return super._patch(data);
}
}
module.exports &#x3D; BusinessContact;</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 September 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>

View File

@@ -0,0 +1,121 @@
<!doctype html>
<html>
<head>
<meta name="generator" content="JSDoc 3.6.7">
<meta charset="utf-8">
<title>whatsapp-web.js 1.14.1 &raquo; Source: structures/Call.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>1</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/Call.js</h1>
</header>
<article>
<pre class="prettyprint linenums"><code>&#x27;use strict&#x27;;
const Base &#x3D; require(&#x27;./Base&#x27;);
/**
* Represents a Call on WhatsApp
* @extends {Base}
*/
class Call extends Base {
constructor(client, data) {
super(client);
if (data) this._patch(data);
}
_patch(data) {
/**
* Call ID
* @type {string}
*/
this.id &#x3D; data.id;
/**
* From
* @type {string}
*/
this.from &#x3D; data.peerJid;
/**
* Unix timestamp for when the call was created
* @type {number}
*/
this.timestamp &#x3D; data.offerTime;
/**
* Is video
* @type {boolean}
*/
this.isVideo &#x3D; data.isVideo;
/**
* Is Group
* @type {boolean}
*/
this.isGroup &#x3D; data.isGroup;
/**
* Indicates if the call was sent by the current user
* @type {boolean}
*/
this.fromMe &#x3D; data.outgoing;
/**
* Indicates if the call can be handled in waweb
* @type {boolean}
*/
this.canHandleLocally &#x3D; data.canHandleLocally;
/**
* Indicates if the call Should be handled in waweb
* @type {boolean}
*/
this.webClientShouldHandle &#x3D; data.webClientShouldHandle;
/**
* Object with participants
* @type {object}
*/
this.participants &#x3D; data.participants;
return super._patch(data);
}
}
module.exports &#x3D; Call;</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 September 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>

View File

@@ -0,0 +1,303 @@
<!doctype html>
<html>
<head>
<meta name="generator" content="JSDoc 3.6.7">
<meta charset="utf-8">
<title>whatsapp-web.js 1.14.1 &raquo; Source: structures/Chat.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>1</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/Chat.js</h1>
</header>
<article>
<pre class="prettyprint linenums"><code>&#x27;use strict&#x27;;
const Base &#x3D; require(&#x27;./Base&#x27;);
const Message &#x3D; require(&#x27;./Message&#x27;);
/**
* Represents a Chat on WhatsApp
* @extends {Base}
*/
class Chat extends Base {
constructor(client, data) {
super(client);
if (data) this._patch(data);
}
_patch(data) {
/**
* ID that represents the chat
* @type {object}
*/
this.id &#x3D; data.id;
/**
* Title of the chat
* @type {string}
*/
this.name &#x3D; data.formattedTitle;
/**
* Indicates if the Chat is a Group Chat
* @type {boolean}
*/
this.isGroup &#x3D; data.isGroup;
/**
* Indicates if the Chat is readonly
* @type {boolean}
*/
this.isReadOnly &#x3D; data.isReadOnly;
/**
* Amount of messages unread
* @type {number}
*/
this.unreadCount &#x3D; data.unreadCount;
/**
* Unix timestamp for when the last activity occurred
* @type {number}
*/
this.timestamp &#x3D; data.t;
/**
* Indicates if the Chat is archived
* @type {boolean}
*/
this.archived &#x3D; data.archive;
/**
* Indicates if the Chat is pinned
* @type {boolean}
*/
this.pinned &#x3D; !!data.pin;
/**
* Indicates if the chat is muted or not
* @type {number}
*/
this.isMuted &#x3D; data.isMuted;
/**
* Unix timestamp for when the mute expires
* @type {number}
*/
this.muteExpiration &#x3D; data.muteExpiration;
return super._patch(data);
}
/**
* Send a message to this chat
* @param {string|MessageMedia|Location} content
* @param {MessageSendOptions} [options]
* @returns {Promise&amp;lt;Message&gt;} Message that was just sent
*/
async sendMessage(content, options) {
return this.client.sendMessage(this.id._serialized, content, options);
}
/**
* Set the message as seen
* @returns {Promise&amp;lt;Boolean&gt;} result
*/
async sendSeen() {
return this.client.sendSeen(this.id._serialized);
}
/**
* Clears all messages from the chat
* @returns {Promise&amp;lt;Boolean&gt;} result
*/
async clearMessages() {
return this.client.pupPage.evaluate(chatId &#x3D;&gt; {
return window.WWebJS.sendClearChat(chatId);
}, this.id._serialized);
}
/**
* Deletes the chat
* @returns {Promise&amp;lt;Boolean&gt;} result
*/
async delete() {
return this.client.pupPage.evaluate(chatId &#x3D;&gt; {
return window.WWebJS.sendDeleteChat(chatId);
}, this.id._serialized);
}
/**
* Archives this chat
*/
async archive() {
return this.client.archiveChat(this.id._serialized);
}
/**
* un-archives this chat
*/
async unarchive() {
return this.client.unarchiveChat(this.id._serialized);
}
/**
* Pins this chat
* @returns {Promise&amp;lt;boolean&gt;} New pin state. Could be false if the max number of pinned chats was reached.
*/
async pin() {
return this.client.pinChat(this.id._serialized);
}
/**
* Unpins this chat
* @returns {Promise&amp;lt;boolean&gt;} New pin state
*/
async unpin() {
return this.client.unpinChat(this.id._serialized);
}
/**
* Mutes this chat until a specified date
* @param {Date} unmuteDate Date at which the Chat will be unmuted
*/
async mute(unmuteDate) {
return this.client.muteChat(this.id._serialized, unmuteDate);
}
/**
* Unmutes this chat
*/
async unmute() {
return this.client.unmuteChat(this.id._serialized);
}
/**
* Mark this chat as unread
*/
async markUnread(){
return this.client.markChatUnread(this.id._serialized);
}
/**
* Loads chat messages, sorted from earliest to latest.
* @param {Object} searchOptions Options for searching messages. Right now only limit is supported.
* @param {Number} [searchOptions.limit&#x3D;50] The amount of messages to return. Note that the actual number of returned messages may be smaller if there aren&#x27;t enough messages in the conversation. Set this to Infinity to load all messages.
* @returns {Promise&amp;lt;Array&amp;lt;Message&gt;&gt;}
*/
async fetchMessages(searchOptions) {
if (!searchOptions || !searchOptions.limit) {
searchOptions &#x3D; { limit: 50 };
}
let messages &#x3D; await this.client.pupPage.evaluate(async (chatId, limit) &#x3D;&gt; {
const msgFilter &#x3D; m &#x3D;&gt; !m.isNotification; // dont include notification messages
const chat &#x3D; window.Store.Chat.get(chatId);
let msgs &#x3D; chat.msgs.models.filter(msgFilter);
while (msgs.length &amp;lt; limit) {
const loadedMessages &#x3D; await chat.loadEarlierMsgs();
if (!loadedMessages) break;
msgs &#x3D; [...loadedMessages.filter(msgFilter), ...msgs];
}
msgs.sort((a, b) &#x3D;&gt; (a.t &gt; b.t) ? 1 : -1);
if (msgs.length &gt; limit) msgs &#x3D; msgs.splice(msgs.length - limit);
return msgs.map(m &#x3D;&gt; window.WWebJS.getMessageModel(m));
}, this.id._serialized, searchOptions.limit);
return messages.map(m &#x3D;&gt; new Message(this.client, m));
}
/**
* Simulate typing in chat. This will last for 25 seconds.
*/
async sendStateTyping() {
return this.client.pupPage.evaluate(chatId &#x3D;&gt; {
window.WWebJS.sendChatstate(&#x27;typing&#x27;, chatId);
return true;
}, this.id._serialized);
}
/**
* Simulate recording audio in chat. This will last for 25 seconds.
*/
async sendStateRecording() {
return this.client.pupPage.evaluate(chatId &#x3D;&gt; {
window.WWebJS.sendChatstate(&#x27;recording&#x27;, chatId);
return true;
}, this.id._serialized);
}
/**
* Stops typing or recording in chat immediately.
*/
async clearState() {
return this.client.pupPage.evaluate(chatId &#x3D;&gt; {
window.WWebJS.sendChatstate(&#x27;stop&#x27;, chatId);
return true;
}, this.id._serialized);
}
/**
* Returns the Contact that corresponds to this Chat.
* @returns {Promise&amp;lt;Contact&gt;}
*/
async getContact() {
return await this.client.getContactById(this.id._serialized);
}
/**
* Returns array of all Labels assigned to this Chat
* @returns {Promise&amp;lt;Array&amp;lt;Label&gt;&gt;}
*/
async getLabels() {
return this.client.getChatLabels(this.id._serialized);
}
}
module.exports &#x3D; Chat;
</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 September 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>

View File

@@ -0,0 +1,123 @@
<!doctype html>
<html>
<head>
<meta name="generator" content="JSDoc 3.6.7">
<meta charset="utf-8">
<title>whatsapp-web.js 1.14.1 &raquo; Source: structures/ClientInfo.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>1</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/ClientInfo.js</h1>
</header>
<article>
<pre class="prettyprint linenums"><code>&#x27;use strict&#x27;;
const Base &#x3D; require(&#x27;./Base&#x27;);
/**
* Current connection information
* @extends {Base}
*/
class ClientInfo extends Base {
constructor(client, data) {
super(client);
if (data) this._patch(data);
}
_patch(data) {
/**
* Name configured to be shown in push notifications
* @type {string}
*/
this.pushname &#x3D; data.pushname;
/**
* @type {object}
* @deprecated Use .wid instead
*/
this.me &#x3D; data.wid;
/**
* Current user ID
* @type {object}
*/
this.wid &#x3D; data.wid;
/**
* Information about the phone this client is connected to
* @type {object}
* @property {string} wa_version WhatsApp Version running on the phone
* @property {string} os_version OS Version running on the phone (iOS or Android version)
* @property {string} device_manufacturer Device manufacturer
* @property {string} device_model Device model
* @property {string} os_build_number OS build number
*/
this.phone &#x3D; data.phone;
/**
* Platform the phone is running on
* @type {string}
*/
this.platform &#x3D; data.platform;
return super._patch(data);
}
/**
* Get current battery percentage and charging status for the attached device
* @returns {object} batteryStatus
* @returns {number} batteryStatus.battery - The current battery percentage
* @returns {boolean} batteryStatus.plugged - Indicates if the phone is plugged in (true) or not (false)
*/
async getBatteryStatus() {
return await this.client.pupPage.evaluate(() &#x3D;&gt; {
const { battery, plugged } &#x3D; window.Store.Conn;
return { battery, plugged };
});
}
}
module.exports &#x3D; ClientInfo;</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 September 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>

View File

@@ -0,0 +1,234 @@
<!doctype html>
<html>
<head>
<meta name="generator" content="JSDoc 3.6.7">
<meta charset="utf-8">
<title>whatsapp-web.js 1.14.1 &raquo; Source: structures/Contact.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>1</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/Contact.js</h1>
</header>
<article>
<pre class="prettyprint linenums"><code>&#x27;use strict&#x27;;
const Base &#x3D; require(&#x27;./Base&#x27;);
/**
* ID that represents a contact
* @typedef {Object} ContactId
* @property {string} server
* @property {string} user
* @property {string} _serialized
*/
/**
* Represents a Contact on WhatsApp
* @extends {Base}
*/
class Contact extends Base {
constructor(client, data) {
super(client);
if(data) this._patch(data);
}
_patch(data) {
/**
* ID that represents the contact
* @type {ContactId}
*/
this.id &#x3D; data.id;
/**
* Contact&#x27;s phone number
* @type {string}
*/
this.number &#x3D; data.userid;
/**
* Indicates if the contact is a business contact
* @type {boolean}
*/
this.isBusiness &#x3D; data.isBusiness;
/**
* Indicates if the contact is an enterprise contact
* @type {boolean}
*/
this.isEnterprise &#x3D; data.isEnterprise;
this.labels &#x3D; data.labels;
/**
* The contact&#x27;s name, as saved by the current user
* @type {?string}
*/
this.name &#x3D; data.name;
/**
* The name that the contact has configured to be shown publically
* @type {string}
*/
this.pushname &#x3D; data.pushname;
this.sectionHeader &#x3D; data.sectionHeader;
/**
* A shortened version of name
* @type {?string}
*/
this.shortName &#x3D; data.shortName;
this.statusMute &#x3D; data.statusMute;
this.type &#x3D; data.type;
this.verifiedLevel &#x3D; data.verifiedLevel;
this.verifiedName &#x3D; data.verifiedName;
/**
* Indicates if the contact is the current user&#x27;s contact
* @type {boolean}
*/
this.isMe &#x3D; data.isMe;
/**
* Indicates if the contact is a user contact
* @type {boolean}
*/
this.isUser &#x3D; data.isUser;
/**
* Indicates if the contact is a group contact
* @type {boolean}
*/
this.isGroup &#x3D; data.isGroup;
/**
* Indicates if the number is registered on WhatsApp
* @type {boolean}
*/
this.isWAContact &#x3D; data.isWAContact;
/**
* Indicates if the number is saved in the current phone&#x27;s contacts
* @type {boolean}
*/
this.isMyContact &#x3D; data.isMyContact;
/**
* Indicates if you have blocked this contact
* @type {boolean}
*/
this.isBlocked &#x3D; data.isBlocked;
return super._patch(data);
}
/**
* Returns the contact&#x27;s profile picture URL, if privacy settings allow it
* @returns {Promise&amp;lt;string&gt;}
*/
async getProfilePicUrl() {
return await this.client.getProfilePicUrl(this.id._serialized);
}
/**
* Returns the Chat that corresponds to this Contact.
* Will return null when getting chat for currently logged in user.
* @returns {Promise&amp;lt;Chat&gt;}
*/
async getChat() {
if(this.isMe) return null;
return await this.client.getChatById(this.id._serialized);
}
/**
* Blocks this contact from WhatsApp
* @returns {Promise&amp;lt;boolean&gt;}
*/
async block() {
if(this.isGroup) return false;
await this.client.pupPage.evaluate(async (contactId) &#x3D;&gt; {
const contact &#x3D; window.Store.Contact.get(contactId);
await window.Store.BlockContact.blockContact(contact);
}, this.id._serialized);
return true;
}
/**
* Unblocks this contact from WhatsApp
* @returns {Promise&amp;lt;boolean&gt;}
*/
async unblock() {
if(this.isGroup) return false;
await this.client.pupPage.evaluate(async (contactId) &#x3D;&gt; {
const contact &#x3D; window.Store.Contact.get(contactId);
await window.Store.BlockContact.unblockContact(contact);
}, this.id._serialized);
return true;
}
/**
* Gets the Contact&#x27;s current &quot;about&quot; info. Returns null if you don&#x27;t have permission to read their status.
* @returns {Promise&amp;lt;?string&gt;}
*/
async getAbout() {
const about &#x3D; await this.client.pupPage.evaluate(async (contactId) &#x3D;&gt; {
return window.Store.Wap.statusFind(contactId);
}, this.id._serialized);
if (typeof about.status !&#x3D;&#x3D; &#x27;string&#x27;)
return null;
return about.status;
}
}
module.exports &#x3D; Contact;</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 September 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>

View File

@@ -0,0 +1,254 @@
<!doctype html>
<html>
<head>
<meta name="generator" content="JSDoc 3.6.7">
<meta charset="utf-8">
<title>whatsapp-web.js 1.14.1 &raquo; Source: structures/GroupChat.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>1</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/GroupChat.js</h1>
</header>
<article>
<pre class="prettyprint linenums"><code>&#x27;use strict&#x27;;
const Chat &#x3D; require(&#x27;./Chat&#x27;);
/**
* Group participant information
* @typedef {Object} GroupParticipant
* @property {ContactId} id
* @property {boolean} isAdmin
* @property {boolean} isSuperAdmin
*/
/**
* Represents a Group Chat on WhatsApp
* @extends {Chat}
*/
class GroupChat extends Chat {
_patch(data) {
this.groupMetadata &#x3D; data.groupMetadata;
return super._patch(data);
}
/**
* Gets the group owner
* @type {ContactId}
*/
get owner() {
return this.groupMetadata.owner;
}
/**
* Gets the date at which the group was created
* @type {date}
*/
get createdAt() {
return new Date(this.groupMetadata.creation * 1000);
}
/**
* Gets the group description
* @type {string}
*/
get description() {
return this.groupMetadata.desc;
}
/**
* Gets the group participants
* @type {Array&amp;lt;GroupParticipant&gt;}
*/
get participants() {
return this.groupMetadata.participants;
}
/**
* Adds a list of participants by ID to the group
* @param {Array&amp;lt;string&gt;} participantIds
* @returns {Promise&amp;lt;Object&gt;}
*/
async addParticipants(participantIds) {
return await this.client.pupPage.evaluate((chatId, participantIds) &#x3D;&gt; {
return window.Store.Wap.addParticipants(chatId, participantIds);
}, this.id._serialized, participantIds);
}
/**
* Removes a list of participants by ID to the group
* @param {Array&amp;lt;string&gt;} participantIds
* @returns {Promise&amp;lt;Object&gt;}
*/
async removeParticipants(participantIds) {
return await this.client.pupPage.evaluate((chatId, participantIds) &#x3D;&gt; {
return window.Store.Wap.removeParticipants(chatId, participantIds);
}, this.id._serialized, participantIds);
}
/**
* Promotes participants by IDs to admins
* @param {Array&amp;lt;string&gt;} participantIds
* @returns {Promise&amp;lt;{ status: number }&gt;} Object with status code indicating if the operation was successful
*/
async promoteParticipants(participantIds) {
return await this.client.pupPage.evaluate((chatId, participantIds) &#x3D;&gt; {
return window.Store.Wap.promoteParticipants(chatId, participantIds);
}, this.id._serialized, participantIds);
}
/**
* Demotes participants by IDs to regular users
* @param {Array&amp;lt;string&gt;} participantIds
* @returns {Promise&amp;lt;{ status: number }&gt;} Object with status code indicating if the operation was successful
*/
async demoteParticipants(participantIds) {
return await this.client.pupPage.evaluate((chatId, participantIds) &#x3D;&gt; {
return window.Store.Wap.demoteParticipants(chatId, participantIds);
}, this.id._serialized, participantIds);
}
/**
* Updates the group subject
* @param {string} subject
* @returns {Promise}
*/
async setSubject(subject) {
let res &#x3D; await this.client.pupPage.evaluate((chatId, subject) &#x3D;&gt; {
return window.Store.Wap.changeSubject(chatId, subject);
}, this.id._serialized, subject);
if(res.status &#x3D;&#x3D; 200) {
this.name &#x3D; subject;
}
}
/**
* Updates the group description
* @param {string} description
* @returns {Promise}
*/
async setDescription(description) {
let res &#x3D; await this.client.pupPage.evaluate((chatId, description) &#x3D;&gt; {
let descId &#x3D; window.Store.GroupMetadata.get(chatId).descId;
return window.Store.Wap.setGroupDescription(chatId, description, window.Store.genId(), descId);
}, this.id._serialized, description);
if (res.status &#x3D;&#x3D; 200) {
this.groupMetadata.desc &#x3D; description;
}
}
/**
* Updates the group settings to only allow admins to send messages.
* @param {boolean} [adminsOnly&#x3D;true] Enable or disable this option
* @returns {Promise&amp;lt;boolean&gt;} Returns true if the setting was properly updated. This can return false if the user does not have the necessary permissions.
*/
async setMessagesAdminsOnly(adminsOnly&#x3D;true) {
let res &#x3D; await this.client.pupPage.evaluate((chatId, value) &#x3D;&gt; {
return window.Store.Wap.setGroupProperty(chatId, &#x27;announcement&#x27;, value);
}, this.id._serialized, adminsOnly);
if (res.status !&#x3D;&#x3D; 200) return false;
this.groupMetadata.announce &#x3D; adminsOnly;
return true;
}
/**
* Updates the group settings to only allow admins to edit group info (title, description, photo).
* @param {boolean} [adminsOnly&#x3D;true] Enable or disable this option
* @returns {Promise&amp;lt;boolean&gt;} Returns true if the setting was properly updated. This can return false if the user does not have the necessary permissions.
*/
async setInfoAdminsOnly(adminsOnly&#x3D;true) {
let res &#x3D; await this.client.pupPage.evaluate((chatId, value) &#x3D;&gt; {
return window.Store.Wap.setGroupProperty(chatId, &#x27;restrict&#x27;, value);
}, this.id._serialized, adminsOnly);
if (res.status !&#x3D;&#x3D; 200) return false;
this.groupMetadata.restrict &#x3D; adminsOnly;
return true;
}
/**
* Gets the invite code for a specific group
* @returns {Promise&amp;lt;string&gt;} Group&#x27;s invite code
*/
async getInviteCode() {
let res &#x3D; await this.client.pupPage.evaluate(chatId &#x3D;&gt; {
return window.Store.Wap.groupInviteCode(chatId);
}, this.id._serialized);
if (res.status &#x3D;&#x3D; 200) {
return res.code;
}
throw new Error(&#x27;Not authorized&#x27;);
}
/**
* Invalidates the current group invite code and generates a new one
* @returns {Promise}
*/
async revokeInvite() {
return await this.client.pupPage.evaluate(chatId &#x3D;&gt; {
return window.Store.Wap.revokeGroupInvite(chatId);
}, this.id._serialized);
}
/**
* Makes the bot leave the group
* @returns {Promise}
*/
async leave() {
return await this.client.pupPage.evaluate(chatId &#x3D;&gt; {
return window.Store.Wap.leaveGroup(chatId);
}, this.id._serialized);
}
}
module.exports &#x3D; GroupChat;</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 September 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>

View File

@@ -0,0 +1,158 @@
<!doctype html>
<html>
<head>
<meta name="generator" content="JSDoc 3.6.7">
<meta charset="utf-8">
<title>whatsapp-web.js 1.14.1 &raquo; Source: structures/GroupNotification.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>1</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/GroupNotification.js</h1>
</header>
<article>
<pre class="prettyprint linenums"><code>&#x27;use strict&#x27;;
const Base &#x3D; require(&#x27;./Base&#x27;);
/**
* Represents a GroupNotification on WhatsApp
* @extends {Base}
*/
class GroupNotification extends Base {
constructor(client, data) {
super(client);
if(data) this._patch(data);
}
_patch(data) {
/**
* ID that represents the groupNotification
* @type {object}
*/
this.id &#x3D; data.id;
/**
* Extra content
* @type {string}
*/
this.body &#x3D; data.body || &#x27;&#x27;;
/**
* GroupNotification type
* @type {GroupNotificationTypes}
*/
this.type &#x3D; data.subtype;
/**
* Unix timestamp for when the groupNotification was created
* @type {number}
*/
this.timestamp &#x3D; data.t;
/**
* ID for the Chat that this groupNotification was sent for.
*
* @type {string}
*/
this.chatId &#x3D; typeof (data.from) &#x3D;&#x3D;&#x3D; &#x27;object&#x27; ? data.from._serialized : data.from;
/**
* ContactId for the user that produced the GroupNotification.
* @type {string}
*/
this.author &#x3D; typeof (data.author) &#x3D;&#x3D;&#x3D; &#x27;object&#x27; ? data.author._serialized : data.author;
/**
* Contact IDs for the users that were affected by this GroupNotification.
* @type {Array&amp;lt;string&gt;}
*/
this.recipientIds &#x3D; [];
if (data.recipients) {
this.recipientIds &#x3D; data.recipients;
}
return super._patch(data);
}
/**
* Returns the Chat this groupNotification was sent in
* @returns {Promise&amp;lt;Chat&gt;}
*/
getChat() {
return this.client.getChatById(this.chatId);
}
/**
* Returns the Contact this GroupNotification was produced by
* @returns {Promise&amp;lt;Contact&gt;}
*/
getContact() {
return this.client.getContactById(this.author);
}
/**
* Returns the Contacts affected by this GroupNotification.
* @returns {Promise&amp;lt;Array&amp;lt;Contact&gt;&gt;}
*/
async getRecipients() {
return await Promise.all(this.recipientIds.map(async m &#x3D;&gt; await this.client.getContactById(m)));
}
/**
* Sends a message to the same chat this GroupNotification was produced in.
*
* @param {string|MessageMedia|Location} content
* @param {object} options
* @returns {Promise&amp;lt;Message&gt;}
*/
async reply(content, options&#x3D;{}) {
return this.client.sendMessage(this.chatId, content, options);
}
}
module.exports &#x3D; GroupNotification;
</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 September 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>

View File

@@ -0,0 +1,103 @@
<!doctype html>
<html>
<head>
<meta name="generator" content="JSDoc 3.6.7">
<meta charset="utf-8">
<title>whatsapp-web.js 1.14.1 &raquo; Source: structures/Label.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>1</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/Label.js</h1>
</header>
<article>
<pre class="prettyprint linenums"><code>&#x27;use strict&#x27;;
const Base &#x3D; require(&#x27;./Base&#x27;);
// eslint-disable-next-line no-unused-vars
const Chat &#x3D; require(&#x27;./Chat&#x27;);
/**
* WhatsApp Business Label information
*/
class Label extends Base {
/**
* @param {Base} client
* @param {object} labelData
*/
constructor(client, labelData){
super(client);
if(labelData) this._patch(labelData);
}
_patch(labelData){
/**
* Label ID
* @type {string}
*/
this.id &#x3D; labelData.id;
/**
* Label name
* @type {string}
*/
this.name &#x3D; labelData.name;
/**
* Label hex color
* @type {string}
*/
this.hexColor &#x3D; labelData.hexColor;
}
/**
* Get all chats that have been assigned this Label
* @returns {Promise&amp;lt;Array&amp;lt;Chat&gt;&gt;}
*/
async getChats(){
return this.client.getChatsByLabelId(this.id);
}
}
module.exports &#x3D; Label;</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 September 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>

View File

@@ -0,0 +1,86 @@
<!doctype html>
<html>
<head>
<meta name="generator" content="JSDoc 3.6.7">
<meta charset="utf-8">
<title>whatsapp-web.js 1.14.1 &raquo; Source: structures/Location.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>1</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/Location.js</h1>
</header>
<article>
<pre class="prettyprint linenums"><code>&#x27;use strict&#x27;;
/**
* Location information
*/
class Location {
/**
* @param {number} latitude
* @param {number} longitude
* @param {?string} description
*/
constructor(latitude, longitude, description) {
/**
* Location latitude
* @type {number}
*/
this.latitude &#x3D; latitude;
/**
* Location longitude
* @type {number}
*/
this.longitude &#x3D; longitude;
/**
* Name for the location
* @type {?string}
*/
this.description &#x3D; description;
}
}
module.exports &#x3D; Location;</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 September 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>

View File

@@ -0,0 +1,497 @@
<!doctype html>
<html>
<head>
<meta name="generator" content="JSDoc 3.6.7">
<meta charset="utf-8">
<title>whatsapp-web.js 1.14.1 &raquo; 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>1</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>&#x27;use strict&#x27;;
const Base &#x3D; require(&#x27;./Base&#x27;);
const MessageMedia &#x3D; require(&#x27;./MessageMedia&#x27;);
const Location &#x3D; require(&#x27;./Location&#x27;);
const Order &#x3D; require(&#x27;./Order&#x27;);
const { MessageTypes } &#x3D; require(&#x27;../util/Constants&#x27;);
/**
* 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 &#x27;ID&#x27;
* @type {string}
*/
this.mediaKey &#x3D; data.mediaKey;
/**
* ID that represents the message
* @type {object}
*/
this.id &#x3D; data.id;
/**
* ACK status for the message
* @type {MessageAck}
*/
this.ack &#x3D; data.ack;
/**
* Indicates if the message has media available for download
* @type {boolean}
*/
this.hasMedia &#x3D; Boolean(data.mediaKey &amp;amp;&amp;amp; data.directPath);
/**
* Message content
* @type {string}
*/
this.body &#x3D; this.hasMedia ? data.caption || &#x27;&#x27; : data.body || &#x27;&#x27;;
/**
* Message type
* @type {MessageTypes}
*/
this.type &#x3D; data.type;
/**
* Unix timestamp for when the message was created
* @type {number}
*/
this.timestamp &#x3D; 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 &#x3D; (typeof (data.from) &#x3D;&#x3D;&#x3D; &#x27;object&#x27; &amp;amp;&amp;amp; data.from !&#x3D;&#x3D; 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 &#x3D; (typeof (data.to) &#x3D;&#x3D;&#x3D; &#x27;object&#x27; &amp;amp;&amp;amp; data.to !&#x3D;&#x3D; 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 &#x3D; (typeof (data.author) &#x3D;&#x3D;&#x3D; &#x27;object&#x27; &amp;amp;&amp;amp; data.author !&#x3D;&#x3D; null) ? data.author._serialized : data.author;
/**
* String that represents from which device type the message was sent
* @type {string}
*/
this.deviceType &#x3D; data.id.id.length &gt; 21 ? &#x27;android&#x27; : data.id.id.substring(0,2) &#x3D;&#x3D;&#x27;3A&#x27; ? &#x27;ios&#x27; : &#x27;web&#x27;;
/**
* Indicates if the message was forwarded
* @type {boolean}
*/
this.isForwarded &#x3D; data.isForwarded;
/**
* Indicates how many times the message was forwarded.
*
* The maximum value is 127.
* @type {number}
*/
this.forwardingScore &#x3D; data.forwardingScore || 0;
/**
* Indicates if the message is a status update
* @type {boolean}
*/
this.isStatus &#x3D; data.isStatusV3;
/**
* Indicates if the message was starred
* @type {boolean}
*/
this.isStarred &#x3D; data.star;
/**
* Indicates if the message was a broadcast
* @type {boolean}
*/
this.broadcast &#x3D; data.broadcast;
/**
* Indicates if the message was sent by the current user
* @type {boolean}
*/
this.fromMe &#x3D; data.id.fromMe;
/**
* Indicates if the message was sent as a reply to another message.
* @type {boolean}
*/
this.hasQuotedMsg &#x3D; data.quotedMsg ? true : false;
/**
* Location information contained in the message, if the message is type &quot;location&quot;
* @type {Location}
*/
this.location &#x3D; data.type &#x3D;&#x3D;&#x3D; MessageTypes.LOCATION ? new Location(data.lat, data.lng, data.loc) : undefined;
/**
* List of vCards contained in the message.
* @type {Array&amp;lt;string&gt;}
*/
this.vCards &#x3D; data.type &#x3D;&#x3D;&#x3D; MessageTypes.CONTACT_CARD_MULTI ? data.vcardList.map((c) &#x3D;&gt; c.vcard) : data.type &#x3D;&#x3D;&#x3D; MessageTypes.CONTACT_CARD ? [data.body] : [];
/**
* Group Invite Data
* @type {object}
*/
this.inviteV4 &#x3D; data.type &#x3D;&#x3D;&#x3D; 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&amp;lt;string&gt;}
*/
this.mentionedIds &#x3D; [];
if (data.mentionedJidList) {
this.mentionedIds &#x3D; data.mentionedJidList;
}
/**
* Order ID for message type ORDER
* @type {string}
*/
this.orderId &#x3D; data.orderId ? data.orderId : undefined;
/**
* Order Token for message type ORDER
* @type {string}
*/
this.token &#x3D; data.token ? data.token : undefined;
/** Title */
if (data.title) {
this.title &#x3D; data.title;
}
/** Description */
if (data.description) {
this.description &#x3D; data.description;
}
/** Business Owner JID */
if (data.businessOwnerJid) {
this.businessOwnerJid &#x3D; data.businessOwnerJid;
}
/** Product ID */
if (data.productId) {
this.productId &#x3D; data.productId;
}
/**
* Links included in the message.
* @type {Array&amp;lt;{link: string, isSuspicious: boolean}&gt;}
*
*/
this.links &#x3D; data.links;
return super._patch(data);
}
_getChatId() {
return this.fromMe ? this.to : this.from;
}
/**
* Returns the Chat this message was sent in
* @returns {Promise&amp;lt;Chat&gt;}
*/
getChat() {
return this.client.getChatById(this._getChatId());
}
/**
* Returns the Contact this message was sent from
* @returns {Promise&amp;lt;Contact&gt;}
*/
getContact() {
return this.client.getContactById(this.author || this.from);
}
/**
* Returns the Contacts mentioned in this message
* @returns {Promise&amp;lt;Array&amp;lt;Contact&gt;&gt;}
*/
async getMentions() {
return await Promise.all(this.mentionedIds.map(async m &#x3D;&gt; await this.client.getContactById(m)));
}
/**
* Returns the quoted message, if any
* @returns {Promise&amp;lt;Message&gt;}
*/
async getQuotedMessage() {
if (!this.hasQuotedMsg) return undefined;
const quotedMsg &#x3D; await this.client.pupPage.evaluate((msgId) &#x3D;&gt; {
let msg &#x3D; 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&amp;lt;Message&gt;}
*/
async reply(content, chatId, options &#x3D; {}) {
if (!chatId) {
chatId &#x3D; this._getChatId();
}
options &#x3D; {
...options,
quotedMessageId: this.id._serialized
};
return this.client.sendMessage(chatId, content, options);
}
/**
* Accept Group V4 Invite
* @returns {Promise&amp;lt;Object&gt;}
*/
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 &#x3D; typeof chat &#x3D;&#x3D;&#x3D; &#x27;string&#x27; ? chat : chat.id._serialized;
await this.client.pupPage.evaluate(async (msgId, chatId) &#x3D;&gt; {
let msg &#x3D; window.Store.Msg.get(msgId);
let chat &#x3D; window.Store.Chat.get(chatId);
return await chat.forwardMessages([msg]);
}, this.id._serialized, chatId);
}
/**
* Downloads and returns the attatched message media
* @returns {Promise&amp;lt;MessageMedia&gt;}
*/
async downloadMedia() {
if (!this.hasMedia) {
return undefined;
}
const result &#x3D; await this.client.pupPage.evaluate(async (msgId) &#x3D;&gt; {
const msg &#x3D; window.Store.Msg.get(msgId);
if (msg.mediaData.mediaStage !&#x3D; &#x27;RESOLVED&#x27;) {
// try to resolve media
await msg.downloadMedia({
downloadEvenIfExpensive: true,
rmrReason: 1
});
}
if (msg.mediaData.mediaStage.includes(&#x27;ERROR&#x27;) || msg.mediaData.mediaStage &#x3D;&#x3D;&#x3D; &#x27;FETCHING&#x27;) {
// media could not be downloaded
return undefined;
}
try {
const decryptedMedia &#x3D; 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 &#x3D; window.WWebJS.arrayBufferToBase64(decryptedMedia);
return {
data,
mimetype: msg.mimetype,
filename: msg.filename
};
} catch (e) {
if(e.status &amp;amp;&amp;amp; e.status &#x3D;&#x3D;&#x3D; 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) &#x3D;&gt; {
let msg &#x3D; window.Store.Msg.get(msgId);
if (everyone &amp;amp;&amp;amp; msg.id.fromMe &amp;amp;&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) &#x3D;&gt; {
let msg &#x3D; 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) &#x3D;&gt; {
let msg &#x3D; window.Store.Msg.get(msgId);
if (msg.canStar()) {
return msg.chat.sendStarMsgs([msg], false);
}
}, this.id._serialized);
}
/**
* Message Info
* @typedef {Object} MessageInfo
* @property {Array&amp;lt;{id: ContactId, t: number}&gt;} 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&amp;lt;{id: ContactId, t: number}&gt;} played Contacts who have listened to the voice message
* @property {number} playedRemaining Amount of people who have not listened to the message
* @property {Array&amp;lt;{id: ContactId, t: number}&gt;} 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&amp;lt;?MessageInfo&gt;}
*/
async getInfo() {
const info &#x3D; await this.client.pupPage.evaluate(async (msgId) &#x3D;&gt; {
const msg &#x3D; 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&amp;lt;Order&gt;}
*/
async getOrder() {
if (this.type &#x3D;&#x3D;&#x3D; MessageTypes.ORDER) {
const result &#x3D; await this.client.pupPage.evaluate((orderId, token) &#x3D;&gt; {
return window.WWebJS.getOrderDetail(orderId, token);
}, this.orderId, this.token);
if (!result) return undefined;
return new Order(this.client, result);
}
return undefined;
}
}
module.exports &#x3D; 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 September 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>

View File

@@ -0,0 +1,153 @@
<!doctype html>
<html>
<head>
<meta name="generator" content="JSDoc 3.6.7">
<meta charset="utf-8">
<title>whatsapp-web.js 1.14.1 &raquo; Source: structures/MessageMedia.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>1</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/MessageMedia.js</h1>
</header>
<article>
<pre class="prettyprint linenums"><code>&#x27;use strict&#x27;;
const fs &#x3D; require(&#x27;fs&#x27;);
const path &#x3D; require(&#x27;path&#x27;);
const mime &#x3D; require(&#x27;mime&#x27;);
const fetch &#x3D; require(&#x27;node-fetch&#x27;);
const { URL } &#x3D; require(&#x27;url&#x27;);
/**
* Media attached to a message
* @param {string} mimetype MIME type of the attachment
* @param {string} data Base64-encoded data of the file
* @param {?string} filename Document file name
*/
class MessageMedia {
constructor(mimetype, data, filename) {
/**
* MIME type of the attachment
* @type {string}
*/
this.mimetype &#x3D; mimetype;
/**
* Base64 encoded data that represents the file
* @type {string}
*/
this.data &#x3D; data;
/**
* Name of the file (for documents)
* @type {?string}
*/
this.filename &#x3D; filename;
}
/**
* Creates a MessageMedia instance from a local file path
* @param {string} filePath
* @returns {MessageMedia}
*/
static fromFilePath(filePath) {
const b64data &#x3D; fs.readFileSync(filePath, {encoding: &#x27;base64&#x27;});
const mimetype &#x3D; mime.getType(filePath);
const filename &#x3D; path.basename(filePath);
return new MessageMedia(mimetype, b64data, filename);
}
/**
* Creates a MessageMedia instance from a URL
* @param {string} url
* @param {Object} [options]
* @param {number} [options.unsafeMime&#x3D;false]
* @param {object} [options.client]
* @param {object} [options.reqOptions]
* @param {number} [options.reqOptions.size&#x3D;0]
* @returns {Promise&amp;lt;MessageMedia&gt;}
*/
static async fromUrl(url, options &#x3D; {}) {
let mimetype;
if (!options.unsafeMime) {
const pUrl &#x3D; new URL(url);
mimetype &#x3D; mime.getType(pUrl.pathname);
if (!mimetype)
throw new Error(&#x27;Unable to determine MIME type&#x27;);
}
async function fetchData (url, options) {
const reqOptions &#x3D; Object.assign({ headers: { accept: &#x27;image/* video/* text/* audio/*&#x27; } }, options);
const response &#x3D; await fetch(url, reqOptions);
const mime &#x3D; response.headers.get(&#x27;Content-Type&#x27;);
let data &#x3D; &#x27;&#x27;;
if (response.buffer) {
data &#x3D; (await response.buffer()).toString(&#x27;base64&#x27;);
} else {
const bArray &#x3D; new Uint8Array(await response.arrayBuffer());
bArray.forEach((b) &#x3D;&gt; {
data +&#x3D; String.fromCharCode(b);
});
data &#x3D; btoa(data);
}
return { data, mime };
}
const res &#x3D; options.client
? (await options.client.pupPage.evaluate(fetchData, url, options.reqOptions))
: (await fetchData(url, options.reqOptions));
if (!mimetype)
mimetype &#x3D; res.mime;
return new MessageMedia(mimetype, res.data, null);
}
}
module.exports &#x3D; MessageMedia;</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 September 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>

View File

@@ -0,0 +1,105 @@
<!doctype html>
<html>
<head>
<meta name="generator" content="JSDoc 3.6.7">
<meta charset="utf-8">
<title>whatsapp-web.js 1.14.1 &raquo; Source: structures/Order.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>1</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/Order.js</h1>
</header>
<article>
<pre class="prettyprint linenums"><code>&#x27;use strict&#x27;;
const Base &#x3D; require(&#x27;./Base&#x27;);
const Product &#x3D; require(&#x27;./Product&#x27;);
/**
* Represents a Order on WhatsApp
* @extends {Base}
*/
class Order extends Base {
constructor(client, data) {
super(client);
if (data) this._patch(data);
}
_patch(data) {
/**
* List of products
* @type {Array&amp;lt;Product&gt;}
*/
if (data.products) {
this.products &#x3D; data.products.map(product &#x3D;&gt; new Product(this.client, product));
}
/**
* Order Subtotal
* @type {string}
*/
this.subtotal &#x3D; data.subtotal;
/**
* Order Total
* @type {string}
*/
this.total &#x3D; data.total;
/**
* Order Currency
* @type {string}
*/
this.currency &#x3D; data.currency;
/**
* Order Created At
* @type {number}
*/
this.createdAt &#x3D; data.createdAt;
return super._patch(data);
}
}
module.exports &#x3D; Order;</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 September 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>

View File

@@ -0,0 +1,66 @@
<!doctype html>
<html>
<head>
<meta name="generator" content="JSDoc 3.6.7">
<meta charset="utf-8">
<title>whatsapp-web.js 1.14.1 &raquo; Source: structures/PrivateChat.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>1</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/PrivateChat.js</h1>
</header>
<article>
<pre class="prettyprint linenums"><code>&#x27;use strict&#x27;;
const Chat &#x3D; require(&#x27;./Chat&#x27;);
/**
* Represents a Private Chat on WhatsApp
* @extends {Chat}
*/
class PrivateChat extends Chat {
}
module.exports &#x3D; PrivateChat;</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 September 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>

View File

@@ -0,0 +1,66 @@
<!doctype html>
<html>
<head>
<meta name="generator" content="JSDoc 3.6.7">
<meta charset="utf-8">
<title>whatsapp-web.js 1.14.1 &raquo; Source: structures/PrivateContact.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>1</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/PrivateContact.js</h1>
</header>
<article>
<pre class="prettyprint linenums"><code>&#x27;use strict&#x27;;
const Contact &#x3D; require(&#x27;./Contact&#x27;);
/**
* Represents a Private Contact on WhatsApp
* @extends {Contact}
*/
class PrivateContact extends Contact {
}
module.exports &#x3D; PrivateContact;</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 September 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>

View File

@@ -0,0 +1,121 @@
<!doctype html>
<html>
<head>
<meta name="generator" content="JSDoc 3.6.7">
<meta charset="utf-8">
<title>whatsapp-web.js 1.14.1 &raquo; Source: structures/Product.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>1</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/Product.js</h1>
</header>
<article>
<pre class="prettyprint linenums"><code>&#x27;use strict&#x27;;
const Base &#x3D; require(&#x27;./Base&#x27;);
const ProductMetadata &#x3D; require(&#x27;./ProductMetadata&#x27;);
/**
* Represents a Product on WhatsAppBusiness
* @extends {Base}
*/
class Product extends Base {
constructor(client, data) {
super(client);
if (data) this._patch(data);
}
_patch(data) {
/**
* Product ID
* @type {string}
*/
this.id &#x3D; data.id;
/**
* Price
* @type {string}
*/
this.price &#x3D; data.price ? data.price : &#x27;&#x27;;
/**
* Product Thumbnail
* @type {string}
*/
this.thumbnailUrl &#x3D; data.thumbnailUrl;
/**
* Currency
* @type {string}
*/
this.currency &#x3D; data.currency;
/**
* Product Name
* @type {string}
*/
this.name &#x3D; data.name;
/**
* Product Quantity
* @type {number}
*/
this.quantity &#x3D; data.quantity;
/** Product metadata */
this.data &#x3D; null;
return super._patch(data);
}
async getData() {
if (this.data &#x3D;&#x3D;&#x3D; null) {
let result &#x3D; await this.client.pupPage.evaluate((productId) &#x3D;&gt; {
return window.WWebJS.getProductMetadata(productId);
}, this.id);
if (!result) {
this.data &#x3D; undefined;
} else {
this.data &#x3D; new ProductMetadata(this.client, result);
}
}
return this.data;
}
}
module.exports &#x3D; Product;</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 September 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>

View File

@@ -0,0 +1,78 @@
<!doctype html>
<html>
<head>
<meta name="generator" content="JSDoc 3.6.7">
<meta charset="utf-8">
<title>whatsapp-web.js 1.14.1 &raquo; Source: structures/ProductMetadata.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>1</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/ProductMetadata.js</h1>
</header>
<article>
<pre class="prettyprint linenums"><code>const Base &#x3D; require(&#x27;./Base&#x27;);
class ProductMetadata extends Base {
constructor(client, data) {
super(client);
if (data) this._patch(data);
}
_patch(data) {
/** Product ID */
this.id &#x3D; data.id;
/** Retailer ID */
this.retailer_id &#x3D; data.retailer_id;
/** Product Name */
this.name &#x3D; data.name;
/** Product Description */
this.description &#x3D; data.description;
return super._patch(data);
}
}
module.exports &#x3D; ProductMetadata;</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 September 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>

194
docs/util_Constants.js.html Normal file
View File

@@ -0,0 +1,194 @@
<!doctype html>
<html>
<head>
<meta name="generator" content="JSDoc 3.6.7">
<meta charset="utf-8">
<title>whatsapp-web.js 1.14.1 &raquo; Source: util/Constants.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>1</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: util/Constants.js</h1>
</header>
<article>
<pre class="prettyprint linenums"><code>&#x27;use strict&#x27;;
exports.WhatsWebURL &#x3D; &#x27;https://web.whatsapp.com/&#x27;;
exports.DefaultOptions &#x3D; {
puppeteer: {
headless: true,
defaultViewport: null
},
session: false,
qrTimeoutMs: 45000,
qrRefreshIntervalMs: 20000,
authTimeoutMs: 45000,
takeoverOnConflict: false,
takeoverTimeoutMs: 0,
userAgent: &#x27;Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.109 Safari/537.36&#x27;,
ffmpegPath: &#x27;ffmpeg&#x27;,
bypassCSP: false
};
/**
* Client status
* @readonly
* @enum {number}
*/
exports.Status &#x3D; {
INITIALIZING: 0,
AUTHENTICATING: 1,
READY: 3
};
/**
* Events that can be emitted by the client
* @readonly
* @enum {string}
*/
exports.Events &#x3D; {
AUTHENTICATED: &#x27;authenticated&#x27;,
AUTHENTICATION_FAILURE: &#x27;auth_failure&#x27;,
READY: &#x27;ready&#x27;,
MESSAGE_RECEIVED: &#x27;message&#x27;,
MESSAGE_CREATE: &#x27;message_create&#x27;,
MESSAGE_REVOKED_EVERYONE: &#x27;message_revoke_everyone&#x27;,
MESSAGE_REVOKED_ME: &#x27;message_revoke_me&#x27;,
MESSAGE_ACK: &#x27;message_ack&#x27;,
MEDIA_UPLOADED: &#x27;media_uploaded&#x27;,
GROUP_JOIN: &#x27;group_join&#x27;,
GROUP_LEAVE: &#x27;group_leave&#x27;,
GROUP_UPDATE: &#x27;group_update&#x27;,
QR_RECEIVED: &#x27;qr&#x27;,
DISCONNECTED: &#x27;disconnected&#x27;,
STATE_CHANGED: &#x27;change_state&#x27;,
BATTERY_CHANGED: &#x27;change_battery&#x27;,
INCOMING_CALL: &#x27;incoming_call&#x27;
};
/**
* Message types
* @readonly
* @enum {string}
*/
exports.MessageTypes &#x3D; {
TEXT: &#x27;chat&#x27;,
AUDIO: &#x27;audio&#x27;,
VOICE: &#x27;ptt&#x27;,
IMAGE: &#x27;image&#x27;,
VIDEO: &#x27;video&#x27;,
DOCUMENT: &#x27;document&#x27;,
STICKER: &#x27;sticker&#x27;,
LOCATION: &#x27;location&#x27;,
CONTACT_CARD: &#x27;vcard&#x27;,
CONTACT_CARD_MULTI: &#x27;multi_vcard&#x27;,
ORDER: &#x27;order&#x27;,
REVOKED: &#x27;revoked&#x27;,
PRODUCT: &#x27;product&#x27;,
UNKNOWN: &#x27;unknown&#x27;,
GROUP_INVITE: &#x27;groups_v4_invite&#x27;
};
/**
* Group notification types
* @readonly
* @enum {string}
*/
exports.GroupNotificationTypes &#x3D; {
ADD: &#x27;add&#x27;,
INVITE: &#x27;invite&#x27;,
REMOVE: &#x27;remove&#x27;,
LEAVE: &#x27;leave&#x27;,
SUBJECT: &#x27;subject&#x27;,
DESCRIPTION: &#x27;description&#x27;,
PICTURE: &#x27;picture&#x27;,
ANNOUNCE: &#x27;announce&#x27;,
RESTRICT: &#x27;restrict&#x27;,
};
/**
* Chat types
* @readonly
* @enum {string}
*/
exports.ChatTypes &#x3D; {
SOLO: &#x27;solo&#x27;,
GROUP: &#x27;group&#x27;,
UNKNOWN: &#x27;unknown&#x27;
};
/**
* WhatsApp state
* @readonly
* @enum {string}
*/
exports.WAState &#x3D; {
CONFLICT: &#x27;CONFLICT&#x27;,
CONNECTED: &#x27;CONNECTED&#x27;,
DEPRECATED_VERSION: &#x27;DEPRECATED_VERSION&#x27;,
OPENING: &#x27;OPENING&#x27;,
PAIRING: &#x27;PAIRING&#x27;,
PROXYBLOCK: &#x27;PROXYBLOCK&#x27;,
SMB_TOS_BLOCK: &#x27;SMB_TOS_BLOCK&#x27;,
TIMEOUT: &#x27;TIMEOUT&#x27;,
TOS_BLOCK: &#x27;TOS_BLOCK&#x27;,
UNLAUNCHED: &#x27;UNLAUNCHED&#x27;,
UNPAIRED: &#x27;UNPAIRED&#x27;,
UNPAIRED_IDLE: &#x27;UNPAIRED_IDLE&#x27;
};
/**
* Message ACK
* @readonly
* @enum {number}
*/
exports.MessageAck &#x3D; {
ACK_ERROR: -1,
ACK_PENDING: 0,
ACK_SERVER: 1,
ACK_DEVICE: 2,
ACK_READ: 3,
ACK_PLAYED: 4,
};
</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 September 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>

View File

@@ -0,0 +1,175 @@
<!doctype html>
<html>
<head>
<meta name="generator" content="JSDoc 3.6.7">
<meta charset="utf-8">
<title>whatsapp-web.js 1.14.1 &raquo; Source: util/InterfaceController.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>1</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: util/InterfaceController.js</h1>
</header>
<article>
<pre class="prettyprint linenums"><code>&#x27;use strict&#x27;;
/**
* Interface Controller
*/
class InterfaceController {
constructor(props) {
this.pupPage &#x3D; props.pupPage;
}
/**
* Opens the Chat Window
* @param {string} chatId ID of the chat window that will be opened
*/
async openChatWindow(chatId) {
await this.pupPage.evaluate(async chatId &#x3D;&gt; {
let chatWid &#x3D; window.Store.WidFactory.createWid(chatId);
let chat &#x3D; await window.Store.Chat.find(chatWid);
await window.Store.Cmd.openChatAt(chat);
}, chatId);
}
/**
* Opens the Chat Drawer
* @param {string} chatId ID of the chat drawer that will be opened
*/
async openChatDrawer(chatId) {
await this.pupPage.evaluate(async chatId &#x3D;&gt; {
let chat &#x3D; await window.Store.Chat.get(chatId);
await window.Store.Cmd.chatInfoDrawer(chat);
}, chatId);
}
/**
* Opens the Chat Search
* @param {string} chatId ID of the chat search that will be opened
*/
async openChatSearch(chatId) {
await this.pupPage.evaluate(async chatId &#x3D;&gt; {
let chat &#x3D; await window.Store.Chat.get(chatId);
await window.Store.Cmd.chatSearch(chat);
}, chatId);
}
/**
* Opens or Scrolls the Chat Window to the position of the message
* @param {string} msgId ID of the message that will be scrolled to
*/
async openChatWindowAt(msgId) {
await this.pupPage.evaluate(async msgId &#x3D;&gt; {
let msg &#x3D; await window.Store.Msg.get(msgId);
await window.Store.Cmd.openChatAt(msg.chat, msg.chat.getSearchContext(msg));
}, msgId);
}
/**
* Opens the Message Drawer
* @param {string} msgId ID of the message drawer that will be opened
*/
async openMessageDrawer(msgId) {
await this.pupPage.evaluate(async msgId &#x3D;&gt; {
let msg &#x3D; await window.Store.Msg.get(msgId);
await window.Store.Cmd.msgInfoDrawer(msg);
}, msgId);
}
/**
* Closes the Right Drawer
*/
async closeRightDrawer() {
await this.pupPage.evaluate(async () &#x3D;&gt; {
await window.Store.Cmd.closeDrawerRight();
});
}
/**
* Get all Features
*/
async getFeatures() {
return await this.pupPage.evaluate(() &#x3D;&gt; {
return window.Store.Features.F;
});
}
/**
* Check if Feature is enabled
* @param {string} feature status to check
*/
async checkFeatureStatus(feature) {
return await this.pupPage.evaluate((feature) &#x3D;&gt; {
return window.Store.Features.supportsFeature(feature);
}, feature);
}
/**
* Enable Features
* @param {string[]} features to be enabled
*/
async enableFeatures(features) {
await this.pupPage.evaluate((features) &#x3D;&gt; {
for (const feature in features) {
window.Store.Features.setFeature(features[feature], true);
}
}, features);
}
/**
* Disable Features
* @param {string[]} features to be disabled
*/
async disableFeatures(features) {
await this.pupPage.evaluate((features) &#x3D;&gt; {
for (const feature in features) {
window.Store.Features.setFeature(features[feature], false);
}
}, features);
}
}
module.exports &#x3D; InterfaceController;
</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 September 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>

257
docs/util_Util.js.html Normal file
View File

@@ -0,0 +1,257 @@
<!doctype html>
<html>
<head>
<meta name="generator" content="JSDoc 3.6.7">
<meta charset="utf-8">
<title>whatsapp-web.js 1.14.1 &raquo; Source: util/Util.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>1</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: util/Util.js</h1>
</header>
<article>
<pre class="prettyprint linenums"><code>&#x27;use strict&#x27;;
const sharp &#x3D; require(&#x27;sharp&#x27;);
const path &#x3D; require(&#x27;path&#x27;);
const Crypto &#x3D; require(&#x27;crypto&#x27;);
const { tmpdir } &#x3D; require(&#x27;os&#x27;);
const ffmpeg &#x3D; require(&#x27;fluent-ffmpeg&#x27;);
const webp &#x3D; require(&#x27;node-webpmux&#x27;);
const fs &#x3D; require(&#x27;fs&#x27;).promises;
const has &#x3D; (o, k) &#x3D;&gt; Object.prototype.hasOwnProperty.call(o, k);
/**
* Utility methods
*/
class Util {
constructor() {
throw new Error(&#x60;The ${this.constructor.name} class may not be instantiated.&#x60;);
}
static generateHash(length) {
var result &#x3D; &#x27;&#x27;;
var characters &#x3D; &#x27;ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789&#x27;;
var charactersLength &#x3D; characters.length;
for ( var i &#x3D; 0; i &amp;lt; length; i++ ) {
result +&#x3D; characters.charAt(Math.floor(Math.random() * charactersLength));
}
return result;
}
/**
* Sets default properties on an object that aren&#x27;t already specified.
* @param {Object} def Default properties
* @param {Object} given Object to assign defaults to
* @returns {Object}
* @private
*/
static mergeDefault(def, given) {
if (!given) return def;
for (const key in def) {
if (!has(given, key) || given[key] &#x3D;&#x3D;&#x3D; undefined) {
given[key] &#x3D; def[key];
} else if (given[key] &#x3D;&#x3D;&#x3D; Object(given[key])) {
given[key] &#x3D; Util.mergeDefault(def[key], given[key]);
}
}
return given;
}
/**
* Formats a image to webp
* @param {MessageMedia} media
*
* @returns {Promise&amp;lt;MessageMedia&gt;} media in webp format
*/
static async formatImageToWebpSticker(media) {
if (!media.mimetype.includes(&#x27;image&#x27;))
throw new Error(&#x27;media is not a image&#x27;);
if (media.mimetype.includes(&#x27;webp&#x27;)) {
return media;
}
const buff &#x3D; Buffer.from(media.data, &#x27;base64&#x27;);
let sharpImg &#x3D; sharp(buff);
sharpImg &#x3D; sharpImg.webp();
sharpImg &#x3D; sharpImg.resize(512, 512, {
fit: &#x27;contain&#x27;,
background: { r: 0, g: 0, b: 0, alpha: 0 },
});
let webpBase64 &#x3D; (await sharpImg.toBuffer()).toString(&#x27;base64&#x27;);
return {
mimetype: &#x27;image/webp&#x27;,
data: webpBase64,
filename: media.filename,
};
}
/**
* Formats a video to webp
* @param {MessageMedia} media
*
* @returns {Promise&amp;lt;MessageMedia&gt;} media in webp format
*/
static async formatVideoToWebpSticker(media) {
if (!media.mimetype.includes(&#x27;video&#x27;))
throw new Error(&#x27;media is not a video&#x27;);
const videoType &#x3D; media.mimetype.split(&#x27;/&#x27;)[1];
const tempFile &#x3D; path.join(
tmpdir(),
&#x60;${Crypto.randomBytes(6).readUIntLE(0, 6).toString(36)}.webp&#x60;
);
const stream &#x3D; new (require(&#x27;stream&#x27;).Readable)();
const buffer &#x3D; Buffer.from(
media.data.replace(&#x60;data:${media.mimetype};base64,&#x60;, &#x27;&#x27;),
&#x27;base64&#x27;
);
stream.push(buffer);
stream.push(null);
await new Promise((resolve, reject) &#x3D;&gt; {
ffmpeg(stream)
.inputFormat(videoType)
.on(&#x27;error&#x27;, reject)
.on(&#x27;end&#x27;, () &#x3D;&gt; resolve(true))
.addOutputOptions([
&#x27;-vcodec&#x27;,
&#x27;libwebp&#x27;,
&#x27;-vf&#x27;,
// eslint-disable-next-line no-useless-escape
&#x27;scale&#x3D;\&#x27;iw*min(300/iw\,300/ih)\&#x27;:\&#x27;ih*min(300/iw\,300/ih)\&#x27;,format&#x3D;rgba,pad&#x3D;300:300:\&#x27;(300-iw)/2\&#x27;:\&#x27;(300-ih)/2\&#x27;:\&#x27;#00000000\&#x27;,setsar&#x3D;1,fps&#x3D;10&#x27;,
&#x27;-loop&#x27;,
&#x27;0&#x27;,
&#x27;-ss&#x27;,
&#x27;00:00:00.0&#x27;,
&#x27;-t&#x27;,
&#x27;00:00:05.0&#x27;,
&#x27;-preset&#x27;,
&#x27;default&#x27;,
&#x27;-an&#x27;,
&#x27;-vsync&#x27;,
&#x27;0&#x27;,
&#x27;-s&#x27;,
&#x27;512:512&#x27;,
])
.toFormat(&#x27;webp&#x27;)
.save(tempFile);
});
const data &#x3D; await fs.readFile(tempFile, &#x27;base64&#x27;);
await fs.unlink(tempFile);
return {
mimetype: &#x27;image/webp&#x27;,
data: data,
filename: media.filename,
};
}
/**
* Sticker metadata.
* @typedef {Object} StickerMetadata
* @property {string} [name]
* @property {string} [author]
* @property {string[]} [categories]
*/
/**
* Formats a media to webp
* @param {MessageMedia} media
* @param {StickerMetadata} metadata
*
* @returns {Promise&amp;lt;MessageMedia&gt;} media in webp format
*/
static async formatToWebpSticker(media, metadata) {
let webpMedia;
if (media.mimetype.includes(&#x27;image&#x27;))
webpMedia &#x3D; await this.formatImageToWebpSticker(media);
else if (media.mimetype.includes(&#x27;video&#x27;))
webpMedia &#x3D; await this.formatVideoToWebpSticker(media);
else
throw new Error(&#x27;Invalid media format&#x27;);
if (metadata.name || metadata.author) {
const img &#x3D; new webp.Image();
const hash &#x3D; this.generateHash(32);
const stickerPackId &#x3D; hash;
const packname &#x3D; metadata.name;
const author &#x3D; metadata.author;
const categories &#x3D; metadata.categories || [&#x27;&#x27;];
const json &#x3D; { &#x27;sticker-pack-id&#x27;: stickerPackId, &#x27;sticker-pack-name&#x27;: packname, &#x27;sticker-pack-publisher&#x27;: author, &#x27;emojis&#x27;: categories };
let exifAttr &#x3D; Buffer.from([0x49, 0x49, 0x2A, 0x00, 0x08, 0x00, 0x00, 0x00, 0x01, 0x00, 0x41, 0x57, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00]);
let jsonBuffer &#x3D; Buffer.from(JSON.stringify(json), &#x27;utf8&#x27;);
let exif &#x3D; Buffer.concat([exifAttr, jsonBuffer]);
exif.writeUIntLE(jsonBuffer.length, 14, 4);
await img.load(Buffer.from(webpMedia.data, &#x27;base64&#x27;));
img.exif &#x3D; exif;
webpMedia.data &#x3D; (await img.save(null)).toString(&#x27;base64&#x27;);
}
return webpMedia;
}
/**
* Configure ffmpeg path
* @param {string} path
*/
static setFfmpegPath(path) {
ffmpeg.setFfmpegPath(path);
}
}
module.exports &#x3D; Util;
</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 September 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>

View File

@@ -1,9 +1,23 @@
const { Client } = require('./index')
const fs = require('fs');
const { Client, Location } = require('./index');
const client = new Client({puppeteer: {headless: false}});
const SESSION_FILE_PATH = './session.json';
let sessionCfg;
if (fs.existsSync(SESSION_FILE_PATH)) {
sessionCfg = require(SESSION_FILE_PATH);
}
const client = new Client({ puppeteer: { headless: false }, session: sessionCfg });
// You can use an existing session and avoid scanning a QR code by adding a "session" object to the client options.
// This object must include WABrowserId, WASecretBundle, WAToken1 and WAToken2.
// You also could connect to an existing instance of a browser
// {
// puppeteer: {
// browserWSEndpoint: `ws://localhost:3000`
// }
// }
client.initialize();
client.on('qr', (qr) => {
@@ -13,12 +27,18 @@ client.on('qr', (qr) => {
client.on('authenticated', (session) => {
console.log('AUTHENTICATED', session);
sessionCfg=session;
fs.writeFile(SESSION_FILE_PATH, JSON.stringify(session), function (err) {
if (err) {
console.error(err);
}
});
});
client.on('auth_failure', msg => {
// Fired if session restore was unsuccessfull
console.error('AUTHENTICATION FAILURE', msg);
})
});
client.on('ready', () => {
console.log('READY');
@@ -27,18 +47,28 @@ client.on('ready', () => {
client.on('message', async msg => {
console.log('MESSAGE RECEIVED', msg);
if (msg.body == '!ping reply') {
if (msg.body === '!ping reply') {
// Send a new message as a reply to the current one
msg.reply('pong');
} else if (msg.body == '!ping') {
} else if (msg.body === '!ping') {
// Send a new message to the same chat
client.sendMessage(msg.from, 'pong');
} else if (msg.body.startsWith('!sendto ')) {
// Direct send a new message to specific id
let number = msg.body.split(' ')[1];
let messageIndex = msg.body.indexOf(number) + number.length;
let message = msg.body.slice(messageIndex, msg.body.length);
number = number.includes('@c.us') ? number : `${number}@c.us`;
let chat = await msg.getChat();
chat.sendSeen();
client.sendMessage(number, message);
} else if (msg.body.startsWith('!subject ')) {
// Change the group subject
let chat = await msg.getChat();
if(chat.isGroup) {
if (chat.isGroup) {
let newSubject = msg.body.slice(9);
chat.setSubject(newSubject);
} else {
@@ -50,23 +80,31 @@ client.on('message', async msg => {
} else if (msg.body.startsWith('!desc ')) {
// Change the group description
let chat = await msg.getChat();
if(chat.isGroup) {
if (chat.isGroup) {
let newDescription = msg.body.slice(6);
chat.setDescription(newDescription);
} else {
msg.reply('This command can only be used in a group!');
}
} else if (msg.body == '!leave') {
} else if (msg.body === '!leave') {
// Leave the group
let chat = await msg.getChat();
if(chat.isGroup) {
if (chat.isGroup) {
chat.leave();
} else {
msg.reply('This command can only be used in a group!');
}
} else if(msg.body == '!groupinfo') {
} else if (msg.body.startsWith('!join ')) {
const inviteCode = msg.body.split(' ')[1];
try {
await client.acceptInvite(inviteCode);
msg.reply('Joined the group!');
} catch (e) {
msg.reply('That invite code seems to be invalid.');
}
} else if (msg.body === '!groupinfo') {
let chat = await msg.getChat();
if(chat.isGroup) {
if (chat.isGroup) {
msg.reply(`
*Group Details*
Name: ${chat.name}
@@ -78,10 +116,161 @@ client.on('message', async msg => {
} else {
msg.reply('This command can only be used in a group!');
}
} else if (msg.body === '!chats') {
const chats = await client.getChats();
client.sendMessage(msg.from, `The bot has ${chats.length} chats open.`);
} else if (msg.body === '!info') {
let info = client.info;
client.sendMessage(msg.from, `
*Connection info*
User name: ${info.pushname}
My number: ${info.me.user}
Platform: ${info.platform}
WhatsApp version: ${info.phone.wa_version}
`);
} else if (msg.body === '!mediainfo' && msg.hasMedia) {
const attachmentData = await msg.downloadMedia();
msg.reply(`
*Media info*
MimeType: ${attachmentData.mimetype}
Filename: ${attachmentData.filename}
Data (length): ${attachmentData.data.length}
`);
} else if (msg.body === '!quoteinfo' && msg.hasQuotedMsg) {
const quotedMsg = await msg.getQuotedMessage();
quotedMsg.reply(`
ID: ${quotedMsg.id._serialized}
Type: ${quotedMsg.type}
Author: ${quotedMsg.author || quotedMsg.from}
Timestamp: ${quotedMsg.timestamp}
Has Media? ${quotedMsg.hasMedia}
`);
} else if (msg.body === '!resendmedia' && msg.hasQuotedMsg) {
const quotedMsg = await msg.getQuotedMessage();
if (quotedMsg.hasMedia) {
const attachmentData = await quotedMsg.downloadMedia();
client.sendMessage(msg.from, attachmentData, { caption: 'Here\'s your requested media.' });
}
} else if (msg.body === '!location') {
msg.reply(new Location(37.422, -122.084, 'Googleplex\nGoogle Headquarters'));
} else if (msg.location) {
msg.reply(msg.location);
} else if (msg.body.startsWith('!status ')) {
const newStatus = msg.body.split(' ')[1];
await client.setStatus(newStatus);
msg.reply(`Status was updated to *${newStatus}*`);
} else if (msg.body === '!mention') {
const contact = await msg.getContact();
const chat = await msg.getChat();
chat.sendMessage(`Hi @${contact.number}!`, {
mentions: [contact]
});
} else if (msg.body === '!delete') {
if (msg.hasQuotedMsg) {
const quotedMsg = await msg.getQuotedMessage();
if (quotedMsg.fromMe) {
quotedMsg.delete(true);
} else {
msg.reply('I can only delete my own messages');
}
}
} else if (msg.body === '!pin') {
const chat = await msg.getChat();
await chat.pin();
} else if (msg.body === '!archive') {
const chat = await msg.getChat();
await chat.archive();
} else if (msg.body === '!mute') {
const chat = await msg.getChat();
// mute the chat for 20 seconds
const unmuteDate = new Date();
unmuteDate.setSeconds(unmuteDate.getSeconds() + 20);
await chat.mute(unmuteDate);
} else if (msg.body === '!typing') {
const chat = await msg.getChat();
// simulates typing in the chat
chat.sendStateTyping();
} else if (msg.body === '!recording') {
const chat = await msg.getChat();
// simulates recording audio in the chat
chat.sendStateRecording();
} else if (msg.body === '!clearstate') {
const chat = await msg.getChat();
// stops typing or recording in the chat
chat.clearState();
} else if (msg.body === '!jumpto') {
if (msg.hasQuotedMsg) {
const quotedMsg = await msg.getQuotedMessage();
client.interface.openChatWindowAt(quotedMsg.id._serialized);
}
}
});
client.on('disconnected', () => {
console.log('Client was logged out');
})
client.on('message_create', (msg) => {
// Fired on all message creations, including your own
if (msg.fromMe) {
// do stuff here
}
});
client.on('message_revoke_everyone', async (after, before) => {
// Fired whenever a message is deleted by anyone (including you)
console.log(after); // message after it was deleted.
if (before) {
console.log(before); // message before it was deleted.
}
});
client.on('message_revoke_me', async (msg) => {
// Fired whenever a message is only deleted in your own view.
console.log(msg.body); // message before it was deleted.
});
client.on('message_ack', (msg, ack) => {
/*
== ACK VALUES ==
ACK_ERROR: -1
ACK_PENDING: 0
ACK_SERVER: 1
ACK_DEVICE: 2
ACK_READ: 3
ACK_PLAYED: 4
*/
if(ack == 3) {
// The message was read
}
});
client.on('group_join', (notification) => {
// User has joined or been added to the group.
console.log('join', notification);
notification.reply('User joined.');
});
client.on('group_leave', (notification) => {
// User has left or been kicked from the group.
console.log('leave', notification);
notification.reply('User left.');
});
client.on('group_update', (notification) => {
// Group picture, subject or description has been updated.
console.log('update', notification);
});
client.on('change_battery', (batteryInfo) => {
// Battery percentage for attached device has changed
const { battery, plugged } = batteryInfo;
console.log(`Battery: ${battery}% - Charging? ${plugged}`);
});
client.on('change_state', state => {
console.log('CHANGE STATE', state );
});
client.on('disconnected', (reason) => {
console.log('Client was logged out', reason);
});

1102
index.d.ts vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -1,5 +1,7 @@
'use strict';
const Constants = require('./src/util/Constants');
module.exports = {
Client: require('./src/Client'),
@@ -9,5 +11,13 @@ module.exports = {
Chat: require('./src/structures/Chat'),
PrivateChat: require('./src/structures/PrivateChat'),
GroupChat: require('./src/structures/GroupChat'),
Message: require('./src/structures/Message')
};
Message: require('./src/structures/Message'),
MessageMedia: require('./src/structures/MessageMedia'),
Contact: require('./src/structures/Contact'),
PrivateContact: require('./src/structures/PrivateContact'),
BusinessContact: require('./src/structures/BusinessContact'),
ClientInfo: require('./src/structures/ClientInfo'),
Location: require('./src/structures/Location'),
ProductMetadata: require('./src/structures/ProductMetadata'),
...Constants
};

317
package-lock.json generated
View File

@@ -1,317 +0,0 @@
{
"name": "whatsapp-web.js",
"version": "0.1.1",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
"agent-base": {
"version": "4.2.1",
"resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.2.1.tgz",
"integrity": "sha512-JVwXMr9nHYTUXsBFKUqhJwvlcYU/blreOEUkhNR2eXZIvwd+c+o5V4MgDPKWnMS/56awN3TRzIP+KoPn+roQtg==",
"requires": {
"es6-promisify": "^5.0.0"
}
},
"async-limiter": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.0.tgz",
"integrity": "sha512-jp/uFnooOiO+L211eZOoSyzpOITMXx1rBITauYykG3BRYPu8h0UcxsPNB04RR5vo4Tyz3+ay17tR6JVf9qzYWg=="
},
"balanced-match": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
"integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c="
},
"brace-expansion": {
"version": "1.1.11",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
"requires": {
"balanced-match": "^1.0.0",
"concat-map": "0.0.1"
}
},
"buffer-from": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz",
"integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A=="
},
"concat-map": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
"integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s="
},
"concat-stream": {
"version": "1.6.2",
"resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz",
"integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==",
"requires": {
"buffer-from": "^1.0.0",
"inherits": "^2.0.3",
"readable-stream": "^2.2.2",
"typedarray": "^0.0.6"
}
},
"core-util-is": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
"integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac="
},
"debug": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
"integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
"requires": {
"ms": "^2.1.1"
}
},
"es6-promise": {
"version": "4.2.6",
"resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.6.tgz",
"integrity": "sha512-aRVgGdnmW2OiySVPUC9e6m+plolMAJKjZnQlCwNSuK5yQ0JN61DZSO1X1Ufd1foqWRAlig0rhduTCHe7sVtK5Q=="
},
"es6-promisify": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/es6-promisify/-/es6-promisify-5.0.0.tgz",
"integrity": "sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM=",
"requires": {
"es6-promise": "^4.0.3"
}
},
"extract-zip": {
"version": "1.6.7",
"resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-1.6.7.tgz",
"integrity": "sha1-qEC0uK9kAyZMjbV/Txp0Mz74H+k=",
"requires": {
"concat-stream": "1.6.2",
"debug": "2.6.9",
"mkdirp": "0.5.1",
"yauzl": "2.4.1"
},
"dependencies": {
"debug": {
"version": "2.6.9",
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
"integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
"requires": {
"ms": "2.0.0"
}
},
"ms": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
}
}
},
"fd-slicer": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.0.1.tgz",
"integrity": "sha1-i1vL2ewyfFBBv5qwI/1nUPEXfmU=",
"requires": {
"pend": "~1.2.0"
}
},
"fs.realpath": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
"integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8="
},
"glob": {
"version": "7.1.3",
"resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz",
"integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==",
"requires": {
"fs.realpath": "^1.0.0",
"inflight": "^1.0.4",
"inherits": "2",
"minimatch": "^3.0.4",
"once": "^1.3.0",
"path-is-absolute": "^1.0.0"
}
},
"https-proxy-agent": {
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-2.2.1.tgz",
"integrity": "sha512-HPCTS1LW51bcyMYbxUIOO4HEOlQ1/1qRaFWcyxvwaqUS9TY88aoEuHUY33kuAh1YhVVaDQhLZsnPd+XNARWZlQ==",
"requires": {
"agent-base": "^4.1.0",
"debug": "^3.1.0"
},
"dependencies": {
"debug": {
"version": "3.2.6",
"resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz",
"integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==",
"requires": {
"ms": "^2.1.1"
}
}
}
},
"inflight": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
"integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
"requires": {
"once": "^1.3.0",
"wrappy": "1"
}
},
"inherits": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
"integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4="
},
"isarray": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
"integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE="
},
"mime": {
"version": "2.4.0",
"resolved": "https://registry.npmjs.org/mime/-/mime-2.4.0.tgz",
"integrity": "sha512-ikBcWwyqXQSHKtciCcctu9YfPbFYZ4+gbHEmE0Q8jzcTYQg5dHCr3g2wwAZjPoJfQVXZq6KXAjpXOTf5/cjT7w=="
},
"minimatch": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
"integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
"requires": {
"brace-expansion": "^1.1.7"
}
},
"minimist": {
"version": "0.0.8",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
"integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0="
},
"mkdirp": {
"version": "0.5.1",
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz",
"integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=",
"requires": {
"minimist": "0.0.8"
}
},
"ms": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz",
"integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg=="
},
"once": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
"integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
"requires": {
"wrappy": "1"
}
},
"path-is-absolute": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
"integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18="
},
"pend": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz",
"integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA="
},
"process-nextick-args": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz",
"integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw=="
},
"progress": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz",
"integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA=="
},
"proxy-from-env": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.0.0.tgz",
"integrity": "sha1-M8UDmPcOp+uW0h97gXYwpVeRx+4="
},
"puppeteer": {
"version": "1.12.2",
"resolved": "https://registry.npmjs.org/puppeteer/-/puppeteer-1.12.2.tgz",
"integrity": "sha512-xWSyCeD6EazGlfnQweMpM+Hs6X6PhUYhNTHKFj/axNZDq4OmrVERf70isBf7HsnFgB3zOC1+23/8+wCAZYg+Pg==",
"requires": {
"debug": "^4.1.0",
"extract-zip": "^1.6.6",
"https-proxy-agent": "^2.2.1",
"mime": "^2.0.3",
"progress": "^2.0.1",
"proxy-from-env": "^1.0.0",
"rimraf": "^2.6.1",
"ws": "^6.1.0"
}
},
"readable-stream": {
"version": "2.3.6",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz",
"integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==",
"requires": {
"core-util-is": "~1.0.0",
"inherits": "~2.0.3",
"isarray": "~1.0.0",
"process-nextick-args": "~2.0.0",
"safe-buffer": "~5.1.1",
"string_decoder": "~1.1.1",
"util-deprecate": "~1.0.1"
}
},
"rimraf": {
"version": "2.6.3",
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz",
"integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==",
"requires": {
"glob": "^7.1.3"
}
},
"safe-buffer": {
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
},
"string_decoder": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
"integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
"requires": {
"safe-buffer": "~5.1.0"
}
},
"typedarray": {
"version": "0.0.6",
"resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz",
"integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c="
},
"util-deprecate": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
"integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8="
},
"wrappy": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8="
},
"ws": {
"version": "6.1.4",
"resolved": "https://registry.npmjs.org/ws/-/ws-6.1.4.tgz",
"integrity": "sha512-eqZfL+NE/YQc1/ZynhojeV8q+H050oR8AZ2uIev7RU10svA9ZnJUddHcOUZTJLinZ9yEfdA2kSATS2qZK5fhJA==",
"requires": {
"async-limiter": "~1.0.0"
}
},
"yauzl": {
"version": "2.4.1",
"resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.4.1.tgz",
"integrity": "sha1-lSj0QtqxsihOWLQ3m7GU4i4MQAU=",
"requires": {
"fd-slicer": "~1.0.1"
}
}
}
}

View File

@@ -1,10 +1,13 @@
{
"name": "whatsapp-web.js",
"version": "0.1.1",
"version": "1.14.1",
"description": "Library for interacting with the WhatsApp Web API ",
"main": "./index.js",
"typings": "./index.d.ts",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
"test": "mocha tests",
"shell": "node --experimental-repl-await ./shell.js",
"generate-docs": "node_modules/.bin/jsdoc --configure .jsdoc.json --verbose"
},
"repository": {
"type": "git",
@@ -23,8 +26,28 @@
"bugs": {
"url": "https://github.com/pedroslopez/whatsapp-web.js/issues"
},
"homepage": "https://github.com/pedroslopez/whatsapp-web.js#readme",
"homepage": "https://guide.wwebjs.dev/",
"dependencies": {
"puppeteer": "^1.12.2"
"@pedroslopez/moduleraid": "^5.0.2",
"fluent-ffmpeg": "^2.1.2",
"jsqr": "^1.3.1",
"mime": "^2.4.5",
"node-webpmux": "^3.1.0",
"puppeteer": "^10.1.0",
"sharp": "^0.28.3"
},
"devDependencies": {
"@types/node-fetch": "^2.5.11",
"chai": "^4.3.4",
"dotenv": "^10.0.0",
"eslint": "^7.27.0",
"eslint-plugin-mocha": "^9.0.0",
"jsdoc": "^3.6.4",
"jsdoc-baseline": "^0.1.5",
"mocha": "^9.0.2",
"sinon": "^11.1.1"
},
"engines": {
"node": ">=12.0.0"
}
}

39
shell.js Normal file
View File

@@ -0,0 +1,39 @@
/**
* ==== wwebjs-shell ====
* Used for quickly testing library features
*
* Running `npm run shell` will start WhatsApp Web in headless mode
* and then drop you into Node REPL with `client` in its context.
*/
const repl = require('repl');
const fs = require('fs');
const { Client } = require('./index');
const SESSION_FILE_PATH = './session.json';
let sessionCfg;
if (fs.existsSync(SESSION_FILE_PATH)) {
sessionCfg = require(SESSION_FILE_PATH);
}
const client = new Client({
puppeteer: { headless: false },
session: sessionCfg
});
console.log('Initializing...');
client.initialize();
client.on('qr', () => {
console.log('Please scan the QR code on the browser.');
});
client.on('ready', () => {
const shell = repl.start('wwebjs> ');
shell.context.client = client;
shell.on('exit', async () => {
await client.destroy();
});
});

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,16 @@
'use strict';
const PrivateContact = require('../structures/PrivateContact');
const BusinessContact = require('../structures/BusinessContact');
class ContactFactory {
static create(client, data) {
if(data.isBusiness) {
return new BusinessContact(client, data);
}
return new PrivateContact(client, data);
}
}
module.exports = ContactFactory;

View File

@@ -14,26 +14,9 @@ class Base {
_clone() {
return Object.assign(Object.create(this), this);
}
}
_patch(data) { return data; }
/**
* Name that represents this model in the WhatsApp Web Store
* @readonly
*/
static get WAppModel() {
return this.name;
}
/**
* Extra fields to add to model serialization
* @readonly
*/
static get extraFields() {
return [];
}
}
module.exports = Base;

View File

@@ -0,0 +1,21 @@
'use strict';
const Contact = require('./Contact');
/**
* Represents a Business Contact on WhatsApp
* @extends {Contact}
*/
class BusinessContact extends Contact {
_patch(data) {
/**
* The contact's business profile
*/
this.businessProfile = data.businessProfile;
return super._patch(data);
}
}
module.exports = BusinessContact;

68
src/structures/Call.js Normal file
View File

@@ -0,0 +1,68 @@
'use strict';
const Base = require('./Base');
/**
* Represents a Call on WhatsApp
* @extends {Base}
*/
class Call extends Base {
constructor(client, data) {
super(client);
if (data) this._patch(data);
}
_patch(data) {
/**
* Call ID
* @type {string}
*/
this.id = data.id;
/**
* From
* @type {string}
*/
this.from = data.peerJid;
/**
* Unix timestamp for when the call was created
* @type {number}
*/
this.timestamp = data.offerTime;
/**
* Is video
* @type {boolean}
*/
this.isVideo = data.isVideo;
/**
* Is Group
* @type {boolean}
*/
this.isGroup = data.isGroup;
/**
* Indicates if the call was sent by the current user
* @type {boolean}
*/
this.fromMe = data.outgoing;
/**
* Indicates if the call can be handled in waweb
* @type {boolean}
*/
this.canHandleLocally = data.canHandleLocally;
/**
* Indicates if the call Should be handled in waweb
* @type {boolean}
*/
this.webClientShouldHandle = data.webClientShouldHandle;
/**
* Object with participants
* @type {object}
*/
this.participants = data.participants;
return super._patch(data);
}
}
module.exports = Call;

View File

@@ -1,6 +1,7 @@
'use strict';
const Base = require('./Base');
const Message = require('./Message');
/**
* Represents a Chat on WhatsApp
@@ -10,24 +11,239 @@ class Chat extends Base {
constructor(client, data) {
super(client);
if(data) this._patch(data);
if (data) this._patch(data);
}
_patch(data) {
/**
* ID that represents the chat
* @type {object}
*/
this.id = data.id;
/**
* Title of the chat
* @type {string}
*/
this.name = data.formattedTitle;
/**
* Indicates if the Chat is a Group Chat
* @type {boolean}
*/
this.isGroup = data.isGroup;
/**
* Indicates if the Chat is readonly
* @type {boolean}
*/
this.isReadOnly = data.isReadOnly;
/**
* Amount of messages unread
* @type {number}
*/
this.unreadCount = data.unreadCount;
/**
* Unix timestamp for when the last activity occurred
* @type {number}
*/
this.timestamp = data.t;
/**
* Indicates if the Chat is archived
* @type {boolean}
*/
this.archived = data.archive;
/**
* Indicates if the Chat is pinned
* @type {boolean}
*/
this.pinned = !!data.pin;
/**
* Indicates if the chat is muted or not
* @type {number}
*/
this.isMuted = data.isMuted;
/**
* Unix timestamp for when the mute expires
* @type {number}
*/
this.muteExpiration = data.muteExpiration;
return super._patch(data);
}
sendMessage(message) {
return this.client.sendMessage(this.id._serialized, message);
/**
* Send a message to this chat
* @param {string|MessageMedia|Location} content
* @param {MessageSendOptions} [options]
* @returns {Promise<Message>} Message that was just sent
*/
async sendMessage(content, options) {
return this.client.sendMessage(this.id._serialized, content, options);
}
/**
* Set the message as seen
* @returns {Promise<Boolean>} result
*/
async sendSeen() {
return this.client.sendSeen(this.id._serialized);
}
/**
* Clears all messages from the chat
* @returns {Promise<Boolean>} result
*/
async clearMessages() {
return this.client.pupPage.evaluate(chatId => {
return window.WWebJS.sendClearChat(chatId);
}, this.id._serialized);
}
/**
* Deletes the chat
* @returns {Promise<Boolean>} result
*/
async delete() {
return this.client.pupPage.evaluate(chatId => {
return window.WWebJS.sendDeleteChat(chatId);
}, this.id._serialized);
}
/**
* Archives this chat
*/
async archive() {
return this.client.archiveChat(this.id._serialized);
}
/**
* un-archives this chat
*/
async unarchive() {
return this.client.unarchiveChat(this.id._serialized);
}
/**
* Pins this chat
* @returns {Promise<boolean>} New pin state. Could be false if the max number of pinned chats was reached.
*/
async pin() {
return this.client.pinChat(this.id._serialized);
}
/**
* Unpins this chat
* @returns {Promise<boolean>} New pin state
*/
async unpin() {
return this.client.unpinChat(this.id._serialized);
}
/**
* Mutes this chat until a specified date
* @param {Date} unmuteDate Date at which the Chat will be unmuted
*/
async mute(unmuteDate) {
return this.client.muteChat(this.id._serialized, unmuteDate);
}
/**
* Unmutes this chat
*/
async unmute() {
return this.client.unmuteChat(this.id._serialized);
}
/**
* Mark this chat as unread
*/
async markUnread(){
return this.client.markChatUnread(this.id._serialized);
}
/**
* Loads chat messages, sorted from earliest to latest.
* @param {Object} searchOptions Options for searching messages. Right now only limit is supported.
* @param {Number} [searchOptions.limit=50] The amount of messages to return. Note that the actual number of returned messages may be smaller if there aren't enough messages in the conversation. Set this to Infinity to load all messages.
* @returns {Promise<Array<Message>>}
*/
async fetchMessages(searchOptions) {
if (!searchOptions || !searchOptions.limit) {
searchOptions = { limit: 50 };
}
let messages = await this.client.pupPage.evaluate(async (chatId, limit) => {
const msgFilter = m => !m.isNotification; // dont include notification messages
const chat = window.Store.Chat.get(chatId);
let msgs = chat.msgs.models.filter(msgFilter);
while (msgs.length < limit) {
const loadedMessages = await chat.loadEarlierMsgs();
if (!loadedMessages) break;
msgs = [...loadedMessages.filter(msgFilter), ...msgs];
}
msgs.sort((a, b) => (a.t > b.t) ? 1 : -1);
if (msgs.length > limit) msgs = msgs.splice(msgs.length - limit);
return msgs.map(m => window.WWebJS.getMessageModel(m));
}, this.id._serialized, searchOptions.limit);
return messages.map(m => new Message(this.client, m));
}
/**
* Simulate typing in chat. This will last for 25 seconds.
*/
async sendStateTyping() {
return this.client.pupPage.evaluate(chatId => {
window.WWebJS.sendChatstate('typing', chatId);
return true;
}, this.id._serialized);
}
/**
* Simulate recording audio in chat. This will last for 25 seconds.
*/
async sendStateRecording() {
return this.client.pupPage.evaluate(chatId => {
window.WWebJS.sendChatstate('recording', chatId);
return true;
}, this.id._serialized);
}
/**
* Stops typing or recording in chat immediately.
*/
async clearState() {
return this.client.pupPage.evaluate(chatId => {
window.WWebJS.sendChatstate('stop', chatId);
return true;
}, this.id._serialized);
}
/**
* Returns the Contact that corresponds to this Chat.
* @returns {Promise<Contact>}
*/
async getContact() {
return await this.client.getContactById(this.id._serialized);
}
/**
* Returns array of all Labels assigned to this Chat
* @returns {Promise<Array<Label>>}
*/
async getLabels() {
return this.client.getChatLabels(this.id._serialized);
}
}
module.exports = Chat;
module.exports = Chat;

View File

@@ -0,0 +1,70 @@
'use strict';
const Base = require('./Base');
/**
* Current connection information
* @extends {Base}
*/
class ClientInfo extends Base {
constructor(client, data) {
super(client);
if (data) this._patch(data);
}
_patch(data) {
/**
* Name configured to be shown in push notifications
* @type {string}
*/
this.pushname = data.pushname;
/**
* @type {object}
* @deprecated Use .wid instead
*/
this.me = data.wid;
/**
* Current user ID
* @type {object}
*/
this.wid = data.wid;
/**
* Information about the phone this client is connected to
* @type {object}
* @property {string} wa_version WhatsApp Version running on the phone
* @property {string} os_version OS Version running on the phone (iOS or Android version)
* @property {string} device_manufacturer Device manufacturer
* @property {string} device_model Device model
* @property {string} os_build_number OS build number
*/
this.phone = data.phone;
/**
* Platform the phone is running on
* @type {string}
*/
this.platform = data.platform;
return super._patch(data);
}
/**
* Get current battery percentage and charging status for the attached device
* @returns {object} batteryStatus
* @returns {number} batteryStatus.battery - The current battery percentage
* @returns {boolean} batteryStatus.plugged - Indicates if the phone is plugged in (true) or not (false)
*/
async getBatteryStatus() {
return await this.client.pupPage.evaluate(() => {
const { battery, plugged } = window.Store.Conn;
return { battery, plugged };
});
}
}
module.exports = ClientInfo;

181
src/structures/Contact.js Normal file
View File

@@ -0,0 +1,181 @@
'use strict';
const Base = require('./Base');
/**
* ID that represents a contact
* @typedef {Object} ContactId
* @property {string} server
* @property {string} user
* @property {string} _serialized
*/
/**
* Represents a Contact on WhatsApp
* @extends {Base}
*/
class Contact extends Base {
constructor(client, data) {
super(client);
if(data) this._patch(data);
}
_patch(data) {
/**
* ID that represents the contact
* @type {ContactId}
*/
this.id = data.id;
/**
* Contact's phone number
* @type {string}
*/
this.number = data.userid;
/**
* Indicates if the contact is a business contact
* @type {boolean}
*/
this.isBusiness = data.isBusiness;
/**
* Indicates if the contact is an enterprise contact
* @type {boolean}
*/
this.isEnterprise = data.isEnterprise;
this.labels = data.labels;
/**
* The contact's name, as saved by the current user
* @type {?string}
*/
this.name = data.name;
/**
* The name that the contact has configured to be shown publically
* @type {string}
*/
this.pushname = data.pushname;
this.sectionHeader = data.sectionHeader;
/**
* A shortened version of name
* @type {?string}
*/
this.shortName = data.shortName;
this.statusMute = data.statusMute;
this.type = data.type;
this.verifiedLevel = data.verifiedLevel;
this.verifiedName = data.verifiedName;
/**
* Indicates if the contact is the current user's contact
* @type {boolean}
*/
this.isMe = data.isMe;
/**
* Indicates if the contact is a user contact
* @type {boolean}
*/
this.isUser = data.isUser;
/**
* Indicates if the contact is a group contact
* @type {boolean}
*/
this.isGroup = data.isGroup;
/**
* Indicates if the number is registered on WhatsApp
* @type {boolean}
*/
this.isWAContact = data.isWAContact;
/**
* Indicates if the number is saved in the current phone's contacts
* @type {boolean}
*/
this.isMyContact = data.isMyContact;
/**
* Indicates if you have blocked this contact
* @type {boolean}
*/
this.isBlocked = data.isBlocked;
return super._patch(data);
}
/**
* Returns the contact's profile picture URL, if privacy settings allow it
* @returns {Promise<string>}
*/
async getProfilePicUrl() {
return await this.client.getProfilePicUrl(this.id._serialized);
}
/**
* Returns the Chat that corresponds to this Contact.
* Will return null when getting chat for currently logged in user.
* @returns {Promise<Chat>}
*/
async getChat() {
if(this.isMe) return null;
return await this.client.getChatById(this.id._serialized);
}
/**
* Blocks this contact from WhatsApp
* @returns {Promise<boolean>}
*/
async block() {
if(this.isGroup) return false;
await this.client.pupPage.evaluate(async (contactId) => {
const contact = window.Store.Contact.get(contactId);
await window.Store.BlockContact.blockContact(contact);
}, this.id._serialized);
return true;
}
/**
* Unblocks this contact from WhatsApp
* @returns {Promise<boolean>}
*/
async unblock() {
if(this.isGroup) return false;
await this.client.pupPage.evaluate(async (contactId) => {
const contact = window.Store.Contact.get(contactId);
await window.Store.BlockContact.unblockContact(contact);
}, this.id._serialized);
return true;
}
/**
* Gets the Contact's current "about" info. Returns null if you don't have permission to read their status.
* @returns {Promise<?string>}
*/
async getAbout() {
const about = await this.client.pupPage.evaluate(async (contactId) => {
return window.Store.Wap.statusFind(contactId);
}, this.id._serialized);
if (typeof about.status !== 'string')
return null;
return about.status;
}
}
module.exports = Contact;

View File

@@ -2,6 +2,14 @@
const Chat = require('./Chat');
/**
* Group participant information
* @typedef {Object} GroupParticipant
* @property {ContactId} id
* @property {boolean} isAdmin
* @property {boolean} isSuperAdmin
*/
/**
* Represents a Group Chat on WhatsApp
* @extends {Chat}
@@ -15,6 +23,7 @@ class GroupChat extends Chat {
/**
* Gets the group owner
* @type {ContactId}
*/
get owner() {
return this.groupMetadata.owner;
@@ -22,6 +31,7 @@ class GroupChat extends Chat {
/**
* Gets the date at which the group was created
* @type {date}
*/
get createdAt() {
return new Date(this.groupMetadata.creation * 1000);
@@ -29,12 +39,15 @@ class GroupChat extends Chat {
/**
* Gets the group description
* @type {string}
*/
get description() {
return this.groupMetadata.desc;
}
/**
* Gets the group participants
* @type {Array<GroupParticipant>}
*/
get participants() {
return this.groupMetadata.participants;
@@ -42,51 +55,56 @@ class GroupChat extends Chat {
/**
* Adds a list of participants by ID to the group
* @param {Array[string]} participantIds
* @param {Array<string>} participantIds
* @returns {Promise<Object>}
*/
async addParticipants(participantIds) {
return await this.client.pupPage.evaluate((chatId, participantIds) => {
return Store.Wap.addParticipants(chatId, participantIds);
return window.Store.Wap.addParticipants(chatId, participantIds);
}, this.id._serialized, participantIds);
}
/**
* Removes a list of participants by ID to the group
* @param {Array[string]} participantIds
* @param {Array<string>} participantIds
* @returns {Promise<Object>}
*/
async removeParticipants(participantIds) {
return await this.client.pupPage.evaluate((chatId, participantIds) => {
return Store.Wap.removeParticipants(chatId, participantIds);
return window.Store.Wap.removeParticipants(chatId, participantIds);
}, this.id._serialized, participantIds);
}
/**
* Promotes participants by IDs to admins
* @param {Array[string]} participantIds
* @param {Array<string>} participantIds
* @returns {Promise<{ status: number }>} Object with status code indicating if the operation was successful
*/
async promoteParticipants(participantIds) {
return await this.client.pupPage.evaluate((chatId, participantIds) => {
return Store.Wap.promoteParticipants(chatId, participantIds);
return window.Store.Wap.promoteParticipants(chatId, participantIds);
}, this.id._serialized, participantIds);
}
/**
* Demotes participants by IDs to regular users
* @param {Array[string]} participantIds
* @param {Array<string>} participantIds
* @returns {Promise<{ status: number }>} Object with status code indicating if the operation was successful
*/
async demoteParticipants(participantIds) {
return await this.client.pupPage.evaluate((chatId, participantIds) => {
return Store.Wap.demoteParticipants(chatId, participantIds);
return window.Store.Wap.demoteParticipants(chatId, participantIds);
}, this.id._serialized, participantIds);
}
/**
* Updates the group subject
* @param {string} subject
* @returns {Promise}
*/
async setSubject(subject) {
let res = await this.client.pupPage.evaluate((chatId, subject) => {
return Store.Chat.get(chatId).setSubject(subject);
return window.Store.Wap.changeSubject(chatId, subject);
}, this.id._serialized, subject);
if(res.status == 200) {
@@ -97,10 +115,12 @@ class GroupChat extends Chat {
/**
* Updates the group description
* @param {string} description
* @returns {Promise}
*/
async setDescription(description) {
let res = await this.client.pupPage.evaluate((chatId, description) => {
return Store.Chat.get(chatId).setGroupDesc(description);
let descId = window.Store.GroupMetadata.get(chatId).descId;
return window.Store.Wap.setGroupDescription(chatId, description, window.Store.genId(), descId);
}, this.id._serialized, description);
if (res.status == 200) {
@@ -108,56 +128,71 @@ class GroupChat extends Chat {
}
}
/**
* Updates the group settings to only allow admins to send messages.
* @param {boolean} [adminsOnly=true] Enable or disable this option
* @returns {Promise<boolean>} Returns true if the setting was properly updated. This can return false if the user does not have the necessary permissions.
*/
async setMessagesAdminsOnly(adminsOnly=true) {
let res = await this.client.pupPage.evaluate((chatId, value) => {
return window.Store.Wap.setGroupProperty(chatId, 'announcement', value);
}, this.id._serialized, adminsOnly);
if (res.status !== 200) return false;
this.groupMetadata.announce = adminsOnly;
return true;
}
/**
* Updates the group settings to only allow admins to edit group info (title, description, photo).
* @param {boolean} [adminsOnly=true] Enable or disable this option
* @returns {Promise<boolean>} Returns true if the setting was properly updated. This can return false if the user does not have the necessary permissions.
*/
async setInfoAdminsOnly(adminsOnly=true) {
let res = await this.client.pupPage.evaluate((chatId, value) => {
return window.Store.Wap.setGroupProperty(chatId, 'restrict', value);
}, this.id._serialized, adminsOnly);
if (res.status !== 200) return false;
this.groupMetadata.restrict = adminsOnly;
return true;
}
/**
* Gets the invite code for a specific group
* @returns {Promise<string>} Group's invite code
*/
async getInviteCode() {
let res = await this.client.pupPage.evaluate(chatId => {
return Store.Wap.groupInviteCode(chatId);
return window.Store.Wap.groupInviteCode(chatId);
}, this.id._serialized);
if (res.status == 200) {
return res.code;
}
throw new Error('Not authorized')
throw new Error('Not authorized');
}
/**
* Invalidates the current group invite code and generates a new one
* @returns {Promise}
*/
async revokeInvite() {
return await this.client.pupPage.evaluate(chatId => {
return Store.Wap.revokeGroupInvite(chatId);
}, chatId);
}
/**
* Returns an object with information about the invite code's group
* @param {string} inviteCode
*/
static async getInviteInfo(inviteCode) {
return await this.client.pupPage.evaluate(inviteCode => {
return Store.Wap.groupInviteInfo(inviteCode);
}, inviteCode);
}
/**
* Joins a group with an invite code
* @param {string} inviteCode
*/
static async join(inviteCode) {
return await this.client.pupPage.evaluate(inviteCode => {
return Store.Wap.acceptGroupInvite(inviteCode);
}, inviteCode);
return window.Store.Wap.revokeGroupInvite(chatId);
}, this.id._serialized);
}
/**
* Makes the bot leave the group
* @returns {Promise}
*/
async leave() {
return await this.client.pupPage.evaluate(chatId => {
return Store.Wap.leaveGroup(chatId);
return window.Store.Wap.leaveGroup(chatId);
}, this.id._serialized);
}

View File

@@ -0,0 +1,104 @@
'use strict';
const Base = require('./Base');
/**
* Represents a GroupNotification on WhatsApp
* @extends {Base}
*/
class GroupNotification extends Base {
constructor(client, data) {
super(client);
if(data) this._patch(data);
}
_patch(data) {
/**
* ID that represents the groupNotification
* @type {object}
*/
this.id = data.id;
/**
* Extra content
* @type {string}
*/
this.body = data.body || '';
/**
* GroupNotification type
* @type {GroupNotificationTypes}
*/
this.type = data.subtype;
/**
* Unix timestamp for when the groupNotification was created
* @type {number}
*/
this.timestamp = data.t;
/**
* ID for the Chat that this groupNotification was sent for.
*
* @type {string}
*/
this.chatId = typeof (data.from) === 'object' ? data.from._serialized : data.from;
/**
* ContactId for the user that produced the GroupNotification.
* @type {string}
*/
this.author = typeof (data.author) === 'object' ? data.author._serialized : data.author;
/**
* Contact IDs for the users that were affected by this GroupNotification.
* @type {Array<string>}
*/
this.recipientIds = [];
if (data.recipients) {
this.recipientIds = data.recipients;
}
return super._patch(data);
}
/**
* Returns the Chat this groupNotification was sent in
* @returns {Promise<Chat>}
*/
getChat() {
return this.client.getChatById(this.chatId);
}
/**
* Returns the Contact this GroupNotification was produced by
* @returns {Promise<Contact>}
*/
getContact() {
return this.client.getContactById(this.author);
}
/**
* Returns the Contacts affected by this GroupNotification.
* @returns {Promise<Array<Contact>>}
*/
async getRecipients() {
return await Promise.all(this.recipientIds.map(async m => await this.client.getContactById(m)));
}
/**
* Sends a message to the same chat this GroupNotification was produced in.
*
* @param {string|MessageMedia|Location} content
* @param {object} options
* @returns {Promise<Message>}
*/
async reply(content, options={}) {
return this.client.sendMessage(this.chatId, content, options);
}
}
module.exports = GroupNotification;

50
src/structures/Label.js Normal file
View File

@@ -0,0 +1,50 @@
'use strict';
const Base = require('./Base');
// eslint-disable-next-line no-unused-vars
const Chat = require('./Chat');
/**
* WhatsApp Business Label information
*/
class Label extends Base {
/**
* @param {Base} client
* @param {object} labelData
*/
constructor(client, labelData){
super(client);
if(labelData) this._patch(labelData);
}
_patch(labelData){
/**
* Label ID
* @type {string}
*/
this.id = labelData.id;
/**
* Label name
* @type {string}
*/
this.name = labelData.name;
/**
* Label hex color
* @type {string}
*/
this.hexColor = labelData.hexColor;
}
/**
* Get all chats that have been assigned this Label
* @returns {Promise<Array<Chat>>}
*/
async getChats(){
return this.client.getChatsByLabelId(this.id);
}
}
module.exports = Label;

View File

@@ -0,0 +1,33 @@
'use strict';
/**
* Location information
*/
class Location {
/**
* @param {number} latitude
* @param {number} longitude
* @param {?string} description
*/
constructor(latitude, longitude, description) {
/**
* Location latitude
* @type {number}
*/
this.latitude = latitude;
/**
* Location longitude
* @type {number}
*/
this.longitude = longitude;
/**
* Name for the location
* @type {?string}
*/
this.description = description;
}
}
module.exports = Location;

View File

@@ -1,6 +1,10 @@
'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
@@ -10,65 +14,430 @@ class Message extends Base {
constructor(client, data) {
super(client);
if(data) this._patch(data);
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;
this.body = data.body;
/**
* 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 && 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;
this.from = data.from;
this.to = data.to;
this.author = data.author;
/**
* 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' && 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' && 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' && 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<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<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<{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<Chat>}
*/
getChat() {
return this.client.getChatById(this.from);
return this.client.getChatById(this._getChatId());
}
/**
* Sends a message as a reply. If chatId is specified, it will be sent
* Returns the Contact this message was sent from
* @returns {Promise<Contact>}
*/
getContact() {
return this.client.getContactById(this.author || this.from);
}
/**
* Returns the Contacts mentioned in this message
* @returns {Promise<Array<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<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} message
* @param {?string} chatId
*
* @param {string|MessageMedia|Location} content
* @param {string} [chatId]
* @param {MessageSendOptions} [options]
* @returns {Promise<Message>}
*/
async reply(message, chatId) {
async reply(content, chatId, options = {}) {
if (!chatId) {
chatId = this.from;
chatId = this._getChatId();
}
return await this.client.pupPage.evaluate((chatId, quotedMessageId, message) => {
let quotedMessage = Store.Msg.get(quotedMessageId);
if(quotedMessage.canReply()) {
const chat = Store.Chat.get(chatId);
chat.composeQuotedMsg = quotedMessage;
window.Store.SendMessage(chat, message, {quotedMsg: quotedMessage});
chat.composeQuotedMsg = null;
} else {
throw new Error('This message cannot be replied to.');
options = {
...options,
quotedMessageId: this.id._serialized
};
return this.client.sendMessage(chatId, content, options);
}
/**
* Accept Group V4 Invite
* @returns {Promise<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<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 && 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 && msg.id.fromMe && 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<{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<{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<{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<?MessageInfo>}
*/
async getInfo() {
const info = await this.client.pupPage.evaluate(async (msgId) => {
const msg = window.Store.Msg.get(msgId);
if(!msg) return null;
}, chatId, this.id._serialized, message);
return await window.Store.Wap.queryMsgInfo(msg.id);
}, this.id._serialized);
if(info.status) {
return null;
}
return info;
}
static get WAppModel() {
return 'Msg';
}
static get extraFields() {
return [
'isNewMsg'
];
/**
* Gets the order associated with a given message
* @return {Promise<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;
module.exports = Message;

View File

@@ -0,0 +1,100 @@
'use strict';
const fs = require('fs');
const path = require('path');
const mime = require('mime');
const fetch = require('node-fetch');
const { URL } = require('url');
/**
* Media attached to a message
* @param {string} mimetype MIME type of the attachment
* @param {string} data Base64-encoded data of the file
* @param {?string} filename Document file name
*/
class MessageMedia {
constructor(mimetype, data, filename) {
/**
* MIME type of the attachment
* @type {string}
*/
this.mimetype = mimetype;
/**
* Base64 encoded data that represents the file
* @type {string}
*/
this.data = data;
/**
* Name of the file (for documents)
* @type {?string}
*/
this.filename = filename;
}
/**
* Creates a MessageMedia instance from a local file path
* @param {string} filePath
* @returns {MessageMedia}
*/
static fromFilePath(filePath) {
const b64data = fs.readFileSync(filePath, {encoding: 'base64'});
const mimetype = mime.getType(filePath);
const filename = path.basename(filePath);
return new MessageMedia(mimetype, b64data, filename);
}
/**
* Creates a MessageMedia instance from a URL
* @param {string} url
* @param {Object} [options]
* @param {number} [options.unsafeMime=false]
* @param {object} [options.client]
* @param {object} [options.reqOptions]
* @param {number} [options.reqOptions.size=0]
* @returns {Promise<MessageMedia>}
*/
static async fromUrl(url, options = {}) {
let mimetype;
if (!options.unsafeMime) {
const pUrl = new URL(url);
mimetype = mime.getType(pUrl.pathname);
if (!mimetype)
throw new Error('Unable to determine MIME type');
}
async function fetchData (url, options) {
const reqOptions = Object.assign({ headers: { accept: 'image/* video/* text/* audio/*' } }, options);
const response = await fetch(url, reqOptions);
const mime = response.headers.get('Content-Type');
let data = '';
if (response.buffer) {
data = (await response.buffer()).toString('base64');
} else {
const bArray = new Uint8Array(await response.arrayBuffer());
bArray.forEach((b) => {
data += String.fromCharCode(b);
});
data = btoa(data);
}
return { data, mime };
}
const res = options.client
? (await options.client.pupPage.evaluate(fetchData, url, options.reqOptions))
: (await fetchData(url, options.reqOptions));
if (!mimetype)
mimetype = res.mime;
return new MessageMedia(mimetype, res.data, null);
}
}
module.exports = MessageMedia;

52
src/structures/Order.js Normal file
View File

@@ -0,0 +1,52 @@
'use strict';
const Base = require('./Base');
const Product = require('./Product');
/**
* Represents a Order on WhatsApp
* @extends {Base}
*/
class Order extends Base {
constructor(client, data) {
super(client);
if (data) this._patch(data);
}
_patch(data) {
/**
* List of products
* @type {Array<Product>}
*/
if (data.products) {
this.products = data.products.map(product => new Product(this.client, product));
}
/**
* Order Subtotal
* @type {string}
*/
this.subtotal = data.subtotal;
/**
* Order Total
* @type {string}
*/
this.total = data.total;
/**
* Order Currency
* @type {string}
*/
this.currency = data.currency;
/**
* Order Created At
* @type {number}
*/
this.createdAt = data.createdAt;
return super._patch(data);
}
}
module.exports = Order;

View File

@@ -0,0 +1,13 @@
'use strict';
const Contact = require('./Contact');
/**
* Represents a Private Contact on WhatsApp
* @extends {Contact}
*/
class PrivateContact extends Contact {
}
module.exports = PrivateContact;

68
src/structures/Product.js Normal file
View File

@@ -0,0 +1,68 @@
'use strict';
const Base = require('./Base');
const ProductMetadata = require('./ProductMetadata');
/**
* Represents a Product on WhatsAppBusiness
* @extends {Base}
*/
class Product extends Base {
constructor(client, data) {
super(client);
if (data) this._patch(data);
}
_patch(data) {
/**
* Product ID
* @type {string}
*/
this.id = data.id;
/**
* Price
* @type {string}
*/
this.price = data.price ? data.price : '';
/**
* Product Thumbnail
* @type {string}
*/
this.thumbnailUrl = data.thumbnailUrl;
/**
* Currency
* @type {string}
*/
this.currency = data.currency;
/**
* Product Name
* @type {string}
*/
this.name = data.name;
/**
* Product Quantity
* @type {number}
*/
this.quantity = data.quantity;
/** Product metadata */
this.data = null;
return super._patch(data);
}
async getData() {
if (this.data === null) {
let result = await this.client.pupPage.evaluate((productId) => {
return window.WWebJS.getProductMetadata(productId);
}, this.id);
if (!result) {
this.data = undefined;
} else {
this.data = new ProductMetadata(this.client, result);
}
}
return this.data;
}
}
module.exports = Product;

View File

@@ -0,0 +1,25 @@
const Base = require('./Base');
class ProductMetadata extends Base {
constructor(client, data) {
super(client);
if (data) this._patch(data);
}
_patch(data) {
/** Product ID */
this.id = data.id;
/** Retailer ID */
this.retailer_id = data.retailer_id;
/** Product Name */
this.name = data.name;
/** Product Description */
this.description = data.description;
return super._patch(data);
}
}
module.exports = ProductMetadata;

18
src/structures/index.js Normal file
View File

@@ -0,0 +1,18 @@
module.exports = {
Base: require('./Base'),
BusinessContact: require('./BusinessContact'),
Chat: require('./Chat'),
ClientInfo: require('./ClientInfo'),
Contact: require('./Contact'),
GroupChat: require('./GroupChat'),
Location: require('./Location'),
Message: require('./Message'),
MessageMedia: require('./MessageMedia'),
PrivateChat: require('./PrivateChat'),
PrivateContact: require('./PrivateContact'),
GroupNotification: require('./GroupNotification'),
Label: require('./Label.js'),
Order: require('./Order'),
Product: require('./Product'),
Call: require('./Call')
};

View File

@@ -1,31 +1,64 @@
'use strict';
exports.WhatsWebURL = 'https://web.whatsapp.com/'
exports.UserAgent = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.109 Safari/537.36';
exports.WhatsWebURL = 'https://web.whatsapp.com/';
exports.DefaultOptions = {
puppeteer: {
headless: true
headless: true,
defaultViewport: null
},
session: false
}
session: false,
qrTimeoutMs: 45000,
qrRefreshIntervalMs: 20000,
authTimeoutMs: 45000,
takeoverOnConflict: false,
takeoverTimeoutMs: 0,
userAgent: 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.109 Safari/537.36',
ffmpegPath: 'ffmpeg',
bypassCSP: false
};
/**
* Client status
* @readonly
* @enum {number}
*/
exports.Status = {
INITIALIZING: 0,
AUTHENTICATING: 1,
READY: 3
}
};
/**
* Events that can be emitted by the client
* @readonly
* @enum {string}
*/
exports.Events = {
AUTHENTICATED: 'authenticated',
AUTHENTICATION_FAILURE: 'auth_failure',
READY: 'ready',
MESSAGE_CREATE: 'message',
MESSAGE_RECEIVED: 'message',
MESSAGE_CREATE: 'message_create',
MESSAGE_REVOKED_EVERYONE: 'message_revoke_everyone',
MESSAGE_REVOKED_ME: 'message_revoke_me',
MESSAGE_ACK: 'message_ack',
MEDIA_UPLOADED: 'media_uploaded',
GROUP_JOIN: 'group_join',
GROUP_LEAVE: 'group_leave',
GROUP_UPDATE: 'group_update',
QR_RECEIVED: 'qr',
DISCONNECTED: 'disconnected'
}
DISCONNECTED: 'disconnected',
STATE_CHANGED: 'change_state',
BATTERY_CHANGED: 'change_battery',
INCOMING_CALL: 'incoming_call'
};
/**
* Message types
* @readonly
* @enum {string}
*/
exports.MessageTypes = {
TEXT: 'chat',
AUDIO: 'audio',
@@ -33,11 +66,75 @@ exports.MessageTypes = {
IMAGE: 'image',
VIDEO: 'video',
DOCUMENT: 'document',
STICKER: 'sticker'
}
STICKER: 'sticker',
LOCATION: 'location',
CONTACT_CARD: 'vcard',
CONTACT_CARD_MULTI: 'multi_vcard',
ORDER: 'order',
REVOKED: 'revoked',
PRODUCT: 'product',
UNKNOWN: 'unknown',
GROUP_INVITE: 'groups_v4_invite'
};
/**
* Group notification types
* @readonly
* @enum {string}
*/
exports.GroupNotificationTypes = {
ADD: 'add',
INVITE: 'invite',
REMOVE: 'remove',
LEAVE: 'leave',
SUBJECT: 'subject',
DESCRIPTION: 'description',
PICTURE: 'picture',
ANNOUNCE: 'announce',
RESTRICT: 'restrict',
};
/**
* Chat types
* @readonly
* @enum {string}
*/
exports.ChatTypes = {
SOLO: 'solo',
GROUP: 'group',
UNKNOWN: 'unknown'
}
};
/**
* WhatsApp state
* @readonly
* @enum {string}
*/
exports.WAState = {
CONFLICT: 'CONFLICT',
CONNECTED: 'CONNECTED',
DEPRECATED_VERSION: 'DEPRECATED_VERSION',
OPENING: 'OPENING',
PAIRING: 'PAIRING',
PROXYBLOCK: 'PROXYBLOCK',
SMB_TOS_BLOCK: 'SMB_TOS_BLOCK',
TIMEOUT: 'TIMEOUT',
TOS_BLOCK: 'TOS_BLOCK',
UNLAUNCHED: 'UNLAUNCHED',
UNPAIRED: 'UNPAIRED',
UNPAIRED_IDLE: 'UNPAIRED_IDLE'
};
/**
* Message ACK
* @readonly
* @enum {number}
*/
exports.MessageAck = {
ACK_ERROR: -1,
ACK_PENDING: 0,
ACK_SERVER: 1,
ACK_DEVICE: 2,
ACK_READ: 3,
ACK_PLAYED: 4,
};

View File

@@ -1,201 +1,477 @@
'use strict';
/**
* Exposes the internal Store to the WhatsApp Web client
*/
exports.ExposeStore = () => {
// CREDITS: moduleRaid by PixelDesu
// https://github.com/pixeldesu/moduleRaid/blob/master/moduleraid.js
// Exposes the internal Store to the WhatsApp Web client
exports.ExposeStore = (moduleRaidStr) => {
eval('var moduleRaid = ' + moduleRaidStr);
// eslint-disable-next-line no-undef
window.mR = moduleRaid();
window.Store = window.mR.findModule('Chat')[0].default;
window.Store.AppState = window.mR.findModule('STREAM')[0].default;
window.Store.Conn = window.mR.findModule('Conn')[0].default;
window.Store.CryptoLib = window.mR.findModule('decryptE2EMedia')[0];
window.Store.Wap = window.mR.findModule('Wap')[0].default;
window.Store.SendSeen = window.mR.findModule('sendSeen')[0];
window.Store.SendClear = window.mR.findModule('sendClear')[0];
window.Store.SendDelete = window.mR.findModule('sendDelete')[0];
window.Store.genId = window.mR.findModule('randomId')[0].default;
window.Store.SendMessage = window.mR.findModule('addAndSendMsgToChat')[0];
window.Store.MsgKey = window.mR.findModule((module) => module.default && module.default.fromString)[0].default;
window.Store.Invite = window.mR.findModule('sendJoinGroupViaInvite')[0];
window.Store.OpaqueData = window.mR.findModule(module => module.default && module.default.createFromData)[0].default;
window.Store.MediaPrep = window.mR.findModule('MediaPrep')[0];
window.Store.MediaObject = window.mR.findModule('getOrCreateMediaObject')[0];
window.Store.MediaUpload = window.mR.findModule('uploadMedia')[0];
window.Store.Cmd = window.mR.findModule('Cmd')[0].default;
window.Store.MediaTypes = window.mR.findModule('msgToMediaType')[0];
window.Store.VCard = window.mR.findModule('vcardFromContactModel')[0];
window.Store.UserConstructor = window.mR.findModule((module) => (module.default && module.default.prototype && module.default.prototype.isServer && module.default.prototype.isUser) ? module.default : null)[0].default;
window.Store.Validators = window.mR.findModule('findLinks')[0];
window.Store.WidFactory = window.mR.findModule('createWid')[0];
window.Store.BlockContact = window.mR.findModule('blockContact')[0];
window.Store.GroupMetadata = window.mR.findModule((module) => module.default && module.default.handlePendingInvite)[0].default;
window.Store.Sticker = window.mR.findModule('Sticker')[0].default.Sticker;
window.Store.UploadUtils = window.mR.findModule((module) => (module.default && module.default.encryptAndUpload) ? module.default : null)[0].default;
window.Store.Label = window.mR.findModule('LabelCollection')[0].default;
window.Store.Features = window.mR.findModule('FEATURE_CHANGE_EVENT')[0].default;
window.Store.QueryOrder = window.mR.findModule('queryOrder')[0];
window.Store.QueryProduct = window.mR.findModule('queryProduct')[0];
window.Store.DownloadManager = window.mR.findModule('DownloadManager')[0].default;
window.Store.Call = window.mR.findModule('CallCollection')[0].default;
const moduleRaid = function (debug) {
moduleRaid.mID = Math.random().toString(36).substring(7);
moduleRaid.mObj = {};
moduleRaid.cArr = [];
moduleRaid.mGet = null;
if (debug) {
moduleRaid.debug = true;
} else if (window.mRdebug) {
moduleRaid.debug = true;
} else {
moduleRaid.debug = false;
}
moduleRaid.log = function (message) {
if (moduleRaid.debug) {
console.warn(`[moduleRaid] ${message}`);
}
}
moduleRaid.args = [
[[0], [function(e, t, i) {
mCac = i.c;
Object.keys(mCac).forEach (function(mod) {
moduleRaid.mObj[mod] = mCac[mod].exports;
})
moduleRaid.cArr = i.m;
moduleRaid.mGet = i;
}]],
[[1e3], {[moduleRaid.mID]: function(e, t, i) {
mCac = i.c;
Object.keys(mCac).forEach (function(mod) {
moduleRaid.mObj[mod] = mCac[mod].exports;
})
moduleRaid.cArr = i.m;
moduleRaid.mGet = i;
}}, [[moduleRaid.mID]]]
]
fillModuleArray = function() {
if (typeof webpackJsonp === 'function') {
moduleRaid.args.forEach(function (argument, index) {
try {
webpackJsonp(...argument);
}
catch (err) {
moduleRaid.log(`moduleRaid.args[${index}] failed: ${err}`);
}
})
}
else {
try {
webpackJsonp.push(moduleRaid.args[1]);
}
catch (err) {
moduleRaid.log(`Pushing moduleRaid.args[1] into webpackJsonp failed: ${err}`);
}
}
if (moduleRaid.mObj.length == 0) {
mEnd = false;
mIter = 0;
if (!webpackJsonp([],[],[mIter])) {
throw Error('Unknown Webpack structure');
}
while (!mEnd) {
try {
moduleRaid.mObj[mIter] = webpackJsonp([],[],[mIter]);
mIter++;
}
catch (err) {
mEnd = true;
}
}
}
}
fillModuleArray()
get = function get (id) {
return moduleRaid.mObj[id]
}
findModule = function findModule (query) {
results = [];
modules = Object.keys(moduleRaid.mObj);
modules.forEach(function(mKey) {
mod = moduleRaid.mObj[mKey];
if (typeof mod !== 'undefined') {
if (typeof mod.default === 'object') {
for (key in mod.default) {
if (key == query) results.push(mod);
}
}
for (key in mod) {
if (key == query) results.push(mod);
}
}
})
return results;
}
findFunction = function(query) {
if (moduleRaid.cArr.length == 0) {
throw Error('No module constructors to search through!');
}
results = [];
if (typeof query === 'string') {
moduleRaid.cArr.forEach(function (ctor, index) {
if (ctor.toString().includes(query)) {
results.push(moduleRaid.mObj[index]);
}
})
} else if (typeof query === 'function') {
modules = Object.keys(moduleRaid.mObj);
modules.forEach(function(mKey, index) {
mod = moduleRaid.mObj[mKey];
if (query(mod)) {
results.push(moduleRaid.mObj[index]);
}
})
} else {
throw new TypeError('findFunction can only find via string and function, ' + (typeof query) + ' was passed');
}
return results;
}
return {
modules: moduleRaid.mObj,
constructors: moduleRaid.cArr,
findModule: findModule,
findFunction: findFunction,
get: moduleRaid.mGet ? moduleRaid.mGet : get
}
}
if (typeof module === 'object' && module.exports) {
module.exports = moduleRaid;
} else {
window.mR = moduleRaid();
if(!window.Store.Chat._find) {
window.Store.Chat._find = e => {
const target = window.Store.Chat.get(e);
return target ? Promise.resolve(target) : Promise.resolve({
id: e
});
};
}
};
window.Store = window.mR.findModule("Conn")[0].default;
window.Store.SendMessage = window.mR.findModule("sendTextMsgToChat")[0].sendTextMsgToChat;
}
/**
* Adds extra props to the serialization of a model
*/
exports.LoadExtraProps = (model, props) => {
Store[model].models[0].__props = Store[model].models[0].__props.concat(props);
}
exports.LoadCustomSerializers = () => {
exports.LoadUtils = () => {
window.WWebJS = {};
window.WWebJS.getChatModel = chat => {
window.WWebJS.getNumberId = async (id) => {
let result = await window.Store.Wap.queryExist(id);
if (result.jid === undefined)
throw 'The number provided is not a registered whatsapp user';
return result.jid;
};
window.WWebJS.sendSeen = async (chatId) => {
let chat = window.Store.Chat.get(chatId);
if (chat !== undefined) {
await window.Store.SendSeen.sendSeen(chat, false);
return true;
}
return false;
};
window.WWebJS.sendMessage = async (chat, content, options = {}) => {
let attOptions = {};
if (options.attachment) {
attOptions = options.sendMediaAsSticker
? await window.WWebJS.processStickerData(options.attachment)
: await window.WWebJS.processMediaData(options.attachment, {
forceVoice: options.sendAudioAsVoice,
forceDocument: options.sendMediaAsDocument,
forceGif: options.sendVideoAsGif
});
content = options.sendMediaAsSticker ? undefined : attOptions.preview;
delete options.attachment;
delete options.sendMediaAsSticker;
}
let quotedMsgOptions = {};
if (options.quotedMessageId) {
let quotedMessage = window.Store.Msg.get(options.quotedMessageId);
if (quotedMessage.canReply()) {
quotedMsgOptions = quotedMessage.msgContextInfo(chat);
}
delete options.quotedMessageId;
}
if (options.mentionedJidList) {
options.mentionedJidList = options.mentionedJidList.map(cId => window.Store.Contact.get(cId).id);
}
let locationOptions = {};
if (options.location) {
locationOptions = {
type: 'location',
loc: options.location.description,
lat: options.location.latitude,
lng: options.location.longitude
};
delete options.location;
}
let vcardOptions = {};
if (options.contactCard) {
let contact = window.Store.Contact.get(options.contactCard);
vcardOptions = {
body: window.Store.VCard.vcardFromContactModel(contact).vcard,
type: 'vcard',
vcardFormattedName: contact.formattedName
};
delete options.contactCard;
} else if (options.contactCardList) {
let contacts = options.contactCardList.map(c => window.Store.Contact.get(c));
let vcards = contacts.map(c => window.Store.VCard.vcardFromContactModel(c));
vcardOptions = {
type: 'multi_vcard',
vcardList: vcards,
body: undefined
};
delete options.contactCardList;
} else if (options.parseVCards && typeof (content) === 'string' && content.startsWith('BEGIN:VCARD')) {
delete options.parseVCards;
try {
const parsed = window.Store.VCard.parseVcard(content);
if (parsed) {
vcardOptions = {
type: 'vcard',
vcardFormattedName: window.Store.VCard.vcardGetNameFromParsed(parsed)
};
}
} catch (_) {
// not a vcard
}
}
if (options.linkPreview) {
delete options.linkPreview;
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 newMsgId = new window.Store.MsgKey({
fromMe: true,
remote: chat.id,
id: window.Store.genId(),
});
const message = {
...options,
id: newMsgId,
ack: 0,
body: content,
from: window.Store.Conn.wid,
to: chat.id,
local: true,
self: 'out',
t: parseInt(new Date().getTime() / 1000),
isNewMsg: true,
type: 'chat',
...locationOptions,
...attOptions,
...quotedMsgOptions,
...vcardOptions
};
await window.Store.SendMessage.addAndSendMsgToChat(chat, message);
return window.Store.Msg.get(newMsgId._serialized);
};
window.WWebJS.processStickerData = async (mediaInfo) => {
if (mediaInfo.mimetype !== 'image/webp') throw new Error('Invalid media type');
const file = window.WWebJS.mediaInfoToFile(mediaInfo);
let filehash = await window.WWebJS.getFileHash(file);
let mediaKey = await window.WWebJS.generateHash(32);
const controller = new AbortController();
const uploadedInfo = await window.Store.UploadUtils.encryptAndUpload({
blob: file,
type: 'sticker',
signal: controller.signal,
mediaKey
});
const stickerInfo = {
...uploadedInfo,
clientUrl: uploadedInfo.url,
deprecatedMms3Url: uploadedInfo.url,
uploadhash: uploadedInfo.encFilehash,
size: file.size,
type: 'sticker',
filehash
};
return stickerInfo;
};
window.WWebJS.processMediaData = async (mediaInfo, { forceVoice, forceDocument, forceGif }) => {
const file = window.WWebJS.mediaInfoToFile(mediaInfo);
const mData = await window.Store.OpaqueData.createFromData(file, file.type);
const mediaPrep = window.Store.MediaPrep.prepRawMedia(mData, { asDocument: forceDocument });
const mediaData = await mediaPrep.waitForPrep();
const mediaObject = window.Store.MediaObject.getOrCreateMediaObject(mediaData.filehash);
const mediaType = window.Store.MediaTypes.msgToMediaType({
type: mediaData.type,
isGif: mediaData.isGif
});
if (forceVoice && mediaData.type === 'audio') {
mediaData.type = 'ptt';
}
if (forceGif && mediaData.type === 'video') {
mediaData.isGif = true;
}
if (forceDocument) {
mediaData.type = 'document';
}
if (!(mediaData.mediaBlob instanceof window.Store.OpaqueData)) {
mediaData.mediaBlob = await window.Store.OpaqueData.createFromData(mediaData.mediaBlob, mediaData.mediaBlob.type);
}
mediaData.renderableUrl = mediaData.mediaBlob.url();
mediaObject.consolidate(mediaData.toJSON());
mediaData.mediaBlob.autorelease();
const uploadedMedia = await window.Store.MediaUpload.uploadMedia({
mimetype: mediaData.mimetype,
mediaObject,
mediaType
});
const mediaEntry = uploadedMedia.mediaEntry;
if (!mediaEntry) {
throw new Error('upload failed: media entry was not created');
}
mediaData.set({
clientUrl: mediaEntry.mmsUrl,
deprecatedMms3Url: mediaEntry.deprecatedMms3Url,
directPath: mediaEntry.directPath,
mediaKey: mediaEntry.mediaKey,
mediaKeyTimestamp: mediaEntry.mediaKeyTimestamp,
filehash: mediaObject.filehash,
encFilehash: mediaEntry.encFilehash,
uploadhash: mediaEntry.uploadHash,
size: mediaObject.size,
streamingSidecar: mediaEntry.sidecar,
firstFrameSidecar: mediaEntry.firstFrameSidecar
});
return mediaData;
};
window.WWebJS.getMessageModel = message => {
const msg = message.serialize();
msg.isStatusV3 = message.isStatusV3;
msg.links = (message.getLinks()).map(link => ({
link: link.href,
isSuspicious: Boolean(link.suspiciousCharacters && link.suspiciousCharacters.size)
}));
if (msg.buttons) {
msg.buttons = msg.buttons.serialize();
}
if(msg.replyButtons) {
msg.replyButtons = msg.replyButtons.serialize();
}
delete msg.pendingAckUpdate;
return msg;
};
window.WWebJS.getChatModel = async chat => {
let res = chat.serialize();
res.isGroup = chat.isGroup;
res.formattedTitle = chat.formattedTitle;
res.isMuted = chat.mute && chat.mute.isMuted;
if(chat.groupMetadata) {
if (chat.groupMetadata) {
await window.Store.GroupMetadata.update(chat.id._serialized);
res.groupMetadata = chat.groupMetadata.serialize();
}
return res;
}
delete res.msgs;
delete res.msgUnsyncedButtonReplyMsgs;
delete res.unsyncedButtonReplies;
window.WWebJS.getChat = chatId => {
const chat = Store.Chat.get(chatId);
return WWebJS.getChatModel(chat);
}
}
return res;
};
window.WWebJS.getChat = async chatId => {
const chatWid = window.Store.WidFactory.createWid(chatId);
const chat = await window.Store.Chat.find(chatWid);
return await window.WWebJS.getChatModel(chat);
};
window.WWebJS.getChats = async () => {
const chats = window.Store.Chat.models;
const chatPromises = chats.map(chat => window.WWebJS.getChatModel(chat));
return await Promise.all(chatPromises);
};
window.WWebJS.getContactModel = contact => {
let res = contact.serialize();
res.isBusiness = contact.isBusiness;
if (contact.businessProfile) {
res.businessProfile = contact.businessProfile.serialize();
}
res.isMe = contact.isMe;
res.isUser = contact.isUser;
res.isGroup = contact.isGroup;
res.isWAContact = contact.isWAContact;
res.isMyContact = contact.isMyContact;
res.isBlocked = contact.isContactBlocked;
res.userid = contact.userid;
return res;
};
window.WWebJS.getContact = async contactId => {
const wid = window.Store.WidFactory.createWid(contactId);
const contact = await window.Store.Contact.find(wid);
return window.WWebJS.getContactModel(contact);
};
window.WWebJS.getContacts = () => {
const contacts = window.Store.Contact.models;
return contacts.map(contact => window.WWebJS.getContactModel(contact));
};
window.WWebJS.mediaInfoToFile = ({ data, mimetype, filename }) => {
const binaryData = atob(data);
const buffer = new ArrayBuffer(binaryData.length);
const view = new Uint8Array(buffer);
for (let i = 0; i < binaryData.length; i++) {
view[i] = binaryData.charCodeAt(i);
}
const blob = new Blob([buffer], { type: mimetype });
return new File([blob], filename, {
type: mimetype,
lastModified: Date.now()
});
};
window.WWebJS.arrayBufferToBase64 = (arrayBuffer) => {
let binary = '';
const bytes = new Uint8Array( arrayBuffer );
const len = bytes.byteLength;
for (let i = 0; i < len; i++) {
binary += String.fromCharCode( bytes[ i ] );
}
return window.btoa( binary );
};
window.WWebJS.getFileHash = async (data) => {
let buffer = await data.arrayBuffer();
const hashBuffer = await crypto.subtle.digest('SHA-256', buffer);
return btoa(String.fromCharCode(...new Uint8Array(hashBuffer)));
};
window.WWebJS.generateHash = async (length) => {
var result = '';
var characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
var charactersLength = characters.length;
for ( var i = 0; i < length; i++ ) {
result += characters.charAt(Math.floor(Math.random() * charactersLength));
}
return result;
};
window.WWebJS.sendClearChat = async (chatId) => {
let chat = window.Store.Chat.get(chatId);
if (chat !== undefined) {
await window.Store.SendClear.sendClear(chat, false);
return true;
}
return false;
};
window.WWebJS.sendDeleteChat = async (chatId) => {
let chat = window.Store.Chat.get(chatId);
if (chat !== undefined) {
await window.Store.SendDelete.sendDelete(chat);
return true;
}
return false;
};
window.WWebJS.sendChatstate = async (state, chatId) => {
switch (state) {
case 'typing':
await window.Store.Wap.sendChatstateComposing(chatId);
break;
case 'recording':
await window.Store.Wap.sendChatstateRecording(chatId);
break;
case 'stop':
await window.Store.Wap.sendChatstatePaused(chatId);
break;
default:
throw 'Invalid chatstate';
}
return true;
};
window.WWebJS.getLabelModel = label => {
let res = label.serialize();
res.hexColor = label.hexColor;
return res;
};
window.WWebJS.getLabels = () => {
const labels = window.Store.Label.models;
return labels.map(label => window.WWebJS.getLabelModel(label));
};
window.WWebJS.getLabel = (labelId) => {
const label = window.Store.Label.get(labelId);
return window.WWebJS.getLabelModel(label);
};
window.WWebJS.getChatLabels = async (chatId) => {
const chat = await window.WWebJS.getChat(chatId);
return (chat.labels || []).map(id => window.WWebJS.getLabel(id));
};
window.WWebJS.getOrderDetail = async (orderId, token) => {
return window.Store.QueryOrder.queryOrder(orderId, 80, 80, token);
};
window.WWebJS.getProductMetadata = async (productId) => {
let sellerId = window.Store.Conn.wid;
let product = await window.Store.QueryProduct.queryProduct(sellerId, productId);
if (product && product.data) {
return product.data;
}
return undefined;
};
};
exports.MarkAllRead = () => {
let Chats = Store.Chat.models;
let Chats = window.Store.Chat.models;
for (chatIndex in Chats) {
for (let chatIndex in Chats) {
if (isNaN(chatIndex)) {
continue;
}
@@ -204,7 +480,7 @@ exports.MarkAllRead = () => {
if (chat.unreadCount > 0) {
chat.markSeen();
Store.Wap.sendConversationSeen(chat.id, chat.getLastMsgKeyForAction(), chat.unreadCount - chat.pendingSeenCount);
window.Store.Wap.sendConversationSeen(chat.id, chat.getLastMsgKeyForAction(), chat.unreadCount - chat.pendingSeenCount);
}
}
}
};

View File

@@ -0,0 +1,121 @@
'use strict';
/**
* Interface Controller
*/
class InterfaceController {
constructor(props) {
this.pupPage = props.pupPage;
}
/**
* Opens the Chat Window
* @param {string} chatId ID of the chat window that will be opened
*/
async openChatWindow(chatId) {
await this.pupPage.evaluate(async chatId => {
let chatWid = window.Store.WidFactory.createWid(chatId);
let chat = await window.Store.Chat.find(chatWid);
await window.Store.Cmd.openChatAt(chat);
}, chatId);
}
/**
* Opens the Chat Drawer
* @param {string} chatId ID of the chat drawer that will be opened
*/
async openChatDrawer(chatId) {
await this.pupPage.evaluate(async chatId => {
let chat = await window.Store.Chat.get(chatId);
await window.Store.Cmd.chatInfoDrawer(chat);
}, chatId);
}
/**
* Opens the Chat Search
* @param {string} chatId ID of the chat search that will be opened
*/
async openChatSearch(chatId) {
await this.pupPage.evaluate(async chatId => {
let chat = await window.Store.Chat.get(chatId);
await window.Store.Cmd.chatSearch(chat);
}, chatId);
}
/**
* Opens or Scrolls the Chat Window to the position of the message
* @param {string} msgId ID of the message that will be scrolled to
*/
async openChatWindowAt(msgId) {
await this.pupPage.evaluate(async msgId => {
let msg = await window.Store.Msg.get(msgId);
await window.Store.Cmd.openChatAt(msg.chat, msg.chat.getSearchContext(msg));
}, msgId);
}
/**
* Opens the Message Drawer
* @param {string} msgId ID of the message drawer that will be opened
*/
async openMessageDrawer(msgId) {
await this.pupPage.evaluate(async msgId => {
let msg = await window.Store.Msg.get(msgId);
await window.Store.Cmd.msgInfoDrawer(msg);
}, msgId);
}
/**
* Closes the Right Drawer
*/
async closeRightDrawer() {
await this.pupPage.evaluate(async () => {
await window.Store.Cmd.closeDrawerRight();
});
}
/**
* Get all Features
*/
async getFeatures() {
return await this.pupPage.evaluate(() => {
return window.Store.Features.F;
});
}
/**
* Check if Feature is enabled
* @param {string} feature status to check
*/
async checkFeatureStatus(feature) {
return await this.pupPage.evaluate((feature) => {
return window.Store.Features.supportsFeature(feature);
}, feature);
}
/**
* Enable Features
* @param {string[]} features to be enabled
*/
async enableFeatures(features) {
await this.pupPage.evaluate((features) => {
for (const feature in features) {
window.Store.Features.setFeature(features[feature], true);
}
}, features);
}
/**
* Disable Features
* @param {string[]} features to be disabled
*/
async disableFeatures(features) {
await this.pupPage.evaluate((features) => {
for (const feature in features) {
window.Store.Features.setFeature(features[feature], false);
}
}, features);
}
}
module.exports = InterfaceController;

View File

@@ -1,5 +1,13 @@
'use strict';
const sharp = require('sharp');
const path = require('path');
const Crypto = require('crypto');
const { tmpdir } = require('os');
const ffmpeg = require('fluent-ffmpeg');
const webp = require('node-webpmux');
const fs = require('fs').promises;
const has = (o, k) => Object.prototype.hasOwnProperty.call(o, k);
/**
@@ -7,29 +15,189 @@ const has = (o, k) => Object.prototype.hasOwnProperty.call(o, k);
*/
class Util {
constructor() {
throw new Error(`The ${this.constructor.name} class may not be instantiated.`);
}
/**
* Sets default properties on an object that aren't already specified.
* @param {Object} def Default properties
* @param {Object} given Object to assign defaults to
* @returns {Object}
* @private
*/
static mergeDefault(def, given) {
if (!given) return def;
for (const key in def) {
if (!has(given, key) || given[key] === undefined) {
given[key] = def[key];
} else if (given[key] === Object(given[key])) {
given[key] = Util.mergeDefault(def[key], given[key]);
}
constructor() {
throw new Error(`The ${this.constructor.name} class may not be instantiated.`);
}
return given;
}
static generateHash(length) {
var result = '';
var characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
var charactersLength = characters.length;
for ( var i = 0; i < length; i++ ) {
result += characters.charAt(Math.floor(Math.random() * charactersLength));
}
return result;
}
/**
* Sets default properties on an object that aren't already specified.
* @param {Object} def Default properties
* @param {Object} given Object to assign defaults to
* @returns {Object}
* @private
*/
static mergeDefault(def, given) {
if (!given) return def;
for (const key in def) {
if (!has(given, key) || given[key] === undefined) {
given[key] = def[key];
} else if (given[key] === Object(given[key])) {
given[key] = Util.mergeDefault(def[key], given[key]);
}
}
return given;
}
/**
* Formats a image to webp
* @param {MessageMedia} media
*
* @returns {Promise<MessageMedia>} media in webp format
*/
static async formatImageToWebpSticker(media) {
if (!media.mimetype.includes('image'))
throw new Error('media is not a image');
if (media.mimetype.includes('webp')) {
return media;
}
const buff = Buffer.from(media.data, 'base64');
let sharpImg = sharp(buff);
sharpImg = sharpImg.webp();
sharpImg = sharpImg.resize(512, 512, {
fit: 'contain',
background: { r: 0, g: 0, b: 0, alpha: 0 },
});
let webpBase64 = (await sharpImg.toBuffer()).toString('base64');
return {
mimetype: 'image/webp',
data: webpBase64,
filename: media.filename,
};
}
/**
* Formats a video to webp
* @param {MessageMedia} media
*
* @returns {Promise<MessageMedia>} media in webp format
*/
static async formatVideoToWebpSticker(media) {
if (!media.mimetype.includes('video'))
throw new Error('media is not a video');
const videoType = media.mimetype.split('/')[1];
const tempFile = path.join(
tmpdir(),
`${Crypto.randomBytes(6).readUIntLE(0, 6).toString(36)}.webp`
);
const stream = new (require('stream').Readable)();
const buffer = Buffer.from(
media.data.replace(`data:${media.mimetype};base64,`, ''),
'base64'
);
stream.push(buffer);
stream.push(null);
await new Promise((resolve, reject) => {
ffmpeg(stream)
.inputFormat(videoType)
.on('error', reject)
.on('end', () => resolve(true))
.addOutputOptions([
'-vcodec',
'libwebp',
'-vf',
// eslint-disable-next-line no-useless-escape
'scale=\'iw*min(300/iw\,300/ih)\':\'ih*min(300/iw\,300/ih)\',format=rgba,pad=300:300:\'(300-iw)/2\':\'(300-ih)/2\':\'#00000000\',setsar=1,fps=10',
'-loop',
'0',
'-ss',
'00:00:00.0',
'-t',
'00:00:05.0',
'-preset',
'default',
'-an',
'-vsync',
'0',
'-s',
'512:512',
])
.toFormat('webp')
.save(tempFile);
});
const data = await fs.readFile(tempFile, 'base64');
await fs.unlink(tempFile);
return {
mimetype: 'image/webp',
data: data,
filename: media.filename,
};
}
/**
* Sticker metadata.
* @typedef {Object} StickerMetadata
* @property {string} [name]
* @property {string} [author]
* @property {string[]} [categories]
*/
/**
* Formats a media to webp
* @param {MessageMedia} media
* @param {StickerMetadata} metadata
*
* @returns {Promise<MessageMedia>} media in webp format
*/
static async formatToWebpSticker(media, metadata) {
let webpMedia;
if (media.mimetype.includes('image'))
webpMedia = await this.formatImageToWebpSticker(media);
else if (media.mimetype.includes('video'))
webpMedia = await this.formatVideoToWebpSticker(media);
else
throw new Error('Invalid media format');
if (metadata.name || metadata.author) {
const img = new webp.Image();
const hash = this.generateHash(32);
const stickerPackId = hash;
const packname = metadata.name;
const author = metadata.author;
const categories = metadata.categories || [''];
const json = { 'sticker-pack-id': stickerPackId, 'sticker-pack-name': packname, 'sticker-pack-publisher': author, 'emojis': categories };
let exifAttr = Buffer.from([0x49, 0x49, 0x2A, 0x00, 0x08, 0x00, 0x00, 0x00, 0x01, 0x00, 0x41, 0x57, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00]);
let jsonBuffer = Buffer.from(JSON.stringify(json), 'utf8');
let exif = Buffer.concat([exifAttr, jsonBuffer]);
exif.writeUIntLE(jsonBuffer.length, 14, 4);
await img.load(Buffer.from(webpMedia.data, 'base64'));
img.exif = exif;
webpMedia.data = (await img.save(null)).toString('base64');
}
return webpMedia;
}
/**
* Configure ffmpeg path
* @param {string} path
*/
static setFfmpegPath(path) {
ffmpeg.setFfmpegPath(path);
}
}
module.exports = Util;
module.exports = Util;

10
tests/README.md Normal file
View File

@@ -0,0 +1,10 @@
## Running tests
These tests require an authenticated WhatsApp Web session, as well as an additional phone that you can send messages to.
This can be configured using the following environment variables:
- `WWEBJS_TEST_SESSION`: A JSON-formatted string with the session details. Must include `WABrowserId`, `WASecretBundle`, `WAToken1` and `WAToken2`.
- `WWEBJS_TEST_SESSION_PATH`: Path to a JSON file that contains the session details. Must include `WABrowserId`, `WASecretBundle`, `WAToken1` and `WAToken2`.
- `WWEBJS_TEST_REMOTE_ID`: A valid WhatsApp ID that you can send messages to, e.g. `123456789@c.us`. It should be different from the ID used by the provided session.
You *must* set `WWEBJS_TEST_REMOTE_ID` **and** either `WWEBJS_TEST_SESSION` or `WWEBJS_TEST_SESSION_PATH` for the tests to run properly.

417
tests/client.js Normal file
View File

@@ -0,0 +1,417 @@
const {expect} = require('chai');
const sinon = require('sinon');
const helper = require('./helper');
const Chat = require('../src/structures/Chat');
const Contact = require('../src/structures/Contact');
const Message = require('../src/structures/Message');
const MessageMedia = require('../src/structures/MessageMedia');
const Location = require('../src/structures/Location');
const { MessageTypes } = require('../src/util/Constants');
const remoteId = helper.remoteId;
describe('Client', function() {
describe('Authentication', function() {
it('should emit QR code if not authenticated', async function() {
this.timeout(25000);
const callback = sinon.spy();
const client = helper.createClient();
client.on('qr', callback);
client.initialize();
await helper.sleep(20000);
expect(callback.called).to.equal(true);
expect(callback.args[0][0]).to.have.lengthOf(152);
await client.destroy();
});
it('should fail auth if session is invalid', async function() {
this.timeout(40000);
const authFailCallback = sinon.spy();
const qrCallback = sinon.spy();
const readyCallback = sinon.spy();
const client = helper.createClient({
options: {
session: {
WABrowserId: 'invalid',
WASecretBundle: 'invalid',
WAToken1: 'invalid',
WAToken2: 'invalid'
},
authTimeoutMs: 10000,
restartOnAuthFail: false
}
});
client.on('qr', qrCallback);
client.on('auth_failure', authFailCallback);
client.on('ready', readyCallback);
client.initialize();
await helper.sleep(25000);
expect(authFailCallback.called).to.equal(true);
expect(authFailCallback.args[0][0]).to.equal('Unable to log in. Are the session details valid?');
expect(readyCallback.called).to.equal(false);
expect(qrCallback.called).to.equal(false);
await client.destroy();
});
it('can restart without a session if session was invalid and restartOnAuthFail=true', async function() {
this.timeout(40000);
const authFailCallback = sinon.spy();
const qrCallback = sinon.spy();
const client = helper.createClient({
options:{
session: {
WABrowserId: 'invalid',
WASecretBundle: 'invalid',
WAToken1: 'invalid',
WAToken2: 'invalid'
},
authTimeoutMs: 10000,
restartOnAuthFail: true
}
});
client.on('auth_failure', authFailCallback);
client.on('qr', qrCallback);
client.initialize();
await helper.sleep(35000);
expect(authFailCallback.called).to.equal(true);
expect(qrCallback.called).to.equal(true);
expect(qrCallback.args[0][0]).to.have.lengthOf(152);
await client.destroy();
});
it('should authenticate with existing session', async function() {
this.timeout(40000);
const authenticatedCallback = sinon.spy();
const qrCallback = sinon.spy();
const readyCallback = sinon.spy();
const client = helper.createClient({withSession: true});
client.on('qr', qrCallback);
client.on('authenticated', authenticatedCallback);
client.on('ready', readyCallback);
await client.initialize();
expect(authenticatedCallback.called).to.equal(true);
const newSession = authenticatedCallback.args[0][0];
expect(newSession).to.have.key([
'WABrowserId',
'WASecretBundle',
'WAToken1',
'WAToken2'
]);
expect(authenticatedCallback.called).to.equal(true);
expect(readyCallback.called).to.equal(true);
expect(qrCallback.called).to.equal(false);
await client.destroy();
});
});
describe('Authenticated', function() {
let client;
before(async function() {
this.timeout(35000);
client = helper.createClient({withSession: true});
await client.initialize();
});
after(async function () {
await client.destroy();
});
describe('Expose Store', function() {
it('exposes the store', async function() {
const exposed = await client.pupPage.evaluate(() => {
return Boolean(window.Store);
});
expect(exposed).to.equal(true);
});
it('exposes all required WhatsApp Web internal models', async function() {
const expectedModules = [
'Chat',
'Msg',
'Contact',
'Conn',
'AppState',
'CryptoLib',
'Wap',
'SendSeen',
'SendClear',
'SendDelete',
'genId',
'SendMessage',
'MsgKey',
'Invite',
'OpaqueData',
'MediaPrep',
'MediaObject',
'MediaUpload',
'Cmd',
'MediaTypes',
'VCard',
'UserConstructor',
'Validators',
'WidFactory',
'BlockContact',
'GroupMetadata',
'Sticker',
'UploadUtils',
'Label',
'Features',
'QueryOrder',
'QueryProduct',
'DownloadManager'
];
const loadedModules = await client.pupPage.evaluate(() => {
return Object.keys(window.Store);
});
expect(loadedModules).to.include.members(expectedModules);
});
});
describe('Send Messages', function () {
it('can send a message', async function() {
const msg = await client.sendMessage(remoteId, 'hello world');
expect(msg).to.be.instanceOf(Message);
expect(msg.type).to.equal(MessageTypes.TEXT);
expect(msg.fromMe).to.equal(true);
expect(msg.body).to.equal('hello world');
expect(msg.to).to.equal(remoteId);
});
it('can send a media message', async function() {
const media = new MessageMedia(
'image/png',
'iVBORw0KGgoAAAANSUhEUgAAAV4AAACWBAMAAABkyf1EAAAAG1BMVEXMzMyWlpacnJyqqqrFxcWxsbGjo6O3t7e+vr6He3KoAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAEcElEQVR4nO2aTW/bRhCGh18ij1zKknMkbbf2UXITIEeyMhIfRaF1exQLA/JRclslRykO+rs7s7s0VwytNmhJtsA8gHZEcox9PTs7uysQgGEYhmEYhmEYhmEYhmEYhmEYhmEYhmEYhmEYhmEYhmGYr2OWRK/ReIKI8Zt7Hb19wTcQ0uTkGh13bQupcw7gPOvdo12/5CzNtNR7xLUtNtT3CGBQ6g3InjY720pvofUec22LJPr8PhEp2OMPyI40PdwWUdronCu9yQpdPx53bQlfLKnfOVhlnDYRBXve4Ov+IZTeMgdedm0NR+xoXJeQvdJ3CvziykSukwil16W/Oe7aGjIjqc/9ib4jQlJy0uArtN4A0+cvXFvDkmUJ47sJ1Y1ATLDNVXZkNPIepQzxy1ki9fqiwbUj/I+64zxWNzyZnPuhvohJ9K70VvXBixpcu2SAHU+Xd9EKdEJDNpYP3AQr3bQSpPQ6Y6/4dl1z7ZDbArsszjA7L0g7ibB0CDcidUWVoErvIMKZh2Xs0LUzcLW6V5NfiUgNEbaYmAVL6bXl0nJRc+1S72ua/D/cTjGPlQj7eUqd7A096rYlRjdPYlhz7VIvxpVG3cemDKF+WAwLY/6XelOZKTXXzsC4xvDjjtSN6kHLhLke6PrwM8h1raf40qjrGO7H9aTEbduucjS04ZrYU/4iuS5Z2Hdt0rvCLFdmLEXcU30AGddST62o+sLcf5l6k7CP+ru4pLYqX/VFyxbm/utQbx/r22ZEbTb2f5I2kns1Y1OQR8ZyofX+TjJxj1Rz7QQVnf1QzR26Oth0ueJVYcRP6ZUPac/Rx/5M6ixO1dhSrT3Y1DpiYmx3tF4ZUdpz9LD/dSg9PXES0LB71BwcGjKROuV28lnvnv7HHJsezheBGH5+X2CfSfRbMKW+5aGs3JFjMrjGibJc0S7TJzqjHrh2hDybj9XRXNZa89Aro55XBdbW5wti2c/5WJ7jJ1RolVUn/HWpb0I58Tziup6Rx7Dm2hnbRP1GM9PW/NFmQ4PtVRVN63Wvxfmu5sowDMMwDMMwDMMwDMMwDMMwDMMwzL+CpT//F/6beoV8zb2Jmt4Qryx6lTUCsENQ75HOkhXAO3EPVgyQtKtUy3C/e+FJg17Zjnew1Xrdb9InbG4WqfUAftG+WhLwPVyfg536+MU7m4C1CMk4ZznpXZzDYI1PDL2nS1hpvc5cNd7E2sJg05Fe7/7d3Fln8Cvc3bwB616auxsKl4WPghjemHrDqyDWeu1UNW5s2btPnSQ75oOdunEwWazfwgVG0kqluYCM9OIjWOGnfA2b9G4Ha63XKpvQ8perTvTifJNhi6+WMWmi7smEZf6G8MmhlyGq+NqP8GV84TLuJr7UIQVx+bDEoEpRZIz42gs40OuN4Mv8hXzelV7KX1isH+ewTWckikyVv+CfHuqVF7I16gN0VKypX6wPsE+zFPzkinolU9UH8OMGvSpnZqKsv13p/RsMun6X5x/y2LeAr8O66lsBwzBMP/wJfyGq8pgBk6IAAAAASUVORK5CYII='
);
const msg = await client.sendMessage(remoteId, media, {caption: 'here\'s my media'});
expect(msg).to.be.instanceOf(Message);
expect(msg.type).to.equal(MessageTypes.IMAGE);
expect(msg.fromMe).to.equal(true);
expect(msg.hasMedia).to.equal(true);
expect(msg.body).to.equal('here\'s my media');
expect(msg.to).to.equal(remoteId);
});
it('can send a media message as a document', async function() {
const media = new MessageMedia(
'image/png',
'iVBORw0KGgoAAAANSUhEUgAAAV4AAACWBAMAAABkyf1EAAAAG1BMVEXMzMyWlpacnJyqqqrFxcWxsbGjo6O3t7e+vr6He3KoAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAEcElEQVR4nO2aTW/bRhCGh18ij1zKknMkbbf2UXITIEeyMhIfRaF1exQLA/JRclslRykO+rs7s7s0VwytNmhJtsA8gHZEcox9PTs7uysQgGEYhmEYhmEYhmEYhmEYhmEYhmEYhmEYhmEYhmEYhmGYr2OWRK/ReIKI8Zt7Hb19wTcQ0uTkGh13bQupcw7gPOvdo12/5CzNtNR7xLUtNtT3CGBQ6g3InjY720pvofUec22LJPr8PhEp2OMPyI40PdwWUdronCu9yQpdPx53bQlfLKnfOVhlnDYRBXve4Ov+IZTeMgdedm0NR+xoXJeQvdJ3CvziykSukwil16W/Oe7aGjIjqc/9ib4jQlJy0uArtN4A0+cvXFvDkmUJ47sJ1Y1ATLDNVXZkNPIepQzxy1ki9fqiwbUj/I+64zxWNzyZnPuhvohJ9K70VvXBixpcu2SAHU+Xd9EKdEJDNpYP3AQr3bQSpPQ6Y6/4dl1z7ZDbArsszjA7L0g7ibB0CDcidUWVoErvIMKZh2Xs0LUzcLW6V5NfiUgNEbaYmAVL6bXl0nJRc+1S72ua/D/cTjGPlQj7eUqd7A096rYlRjdPYlhz7VIvxpVG3cemDKF+WAwLY/6XelOZKTXXzsC4xvDjjtSN6kHLhLke6PrwM8h1raf40qjrGO7H9aTEbduucjS04ZrYU/4iuS5Z2Hdt0rvCLFdmLEXcU30AGddST62o+sLcf5l6k7CP+ru4pLYqX/VFyxbm/utQbx/r22ZEbTb2f5I2kns1Y1OQR8ZyofX+TjJxj1Rz7QQVnf1QzR26Oth0ueJVYcRP6ZUPac/Rx/5M6ixO1dhSrT3Y1DpiYmx3tF4ZUdpz9LD/dSg9PXES0LB71BwcGjKROuV28lnvnv7HHJsezheBGH5+X2CfSfRbMKW+5aGs3JFjMrjGibJc0S7TJzqjHrh2hDybj9XRXNZa89Aro55XBdbW5wti2c/5WJ7jJ1RolVUn/HWpb0I58Tziup6Rx7Dm2hnbRP1GM9PW/NFmQ4PtVRVN63Wvxfmu5sowDMMwDMMwDMMwDMMwDMMwDMMwzL+CpT//F/6beoV8zb2Jmt4Qryx6lTUCsENQ75HOkhXAO3EPVgyQtKtUy3C/e+FJg17Zjnew1Xrdb9InbG4WqfUAftG+WhLwPVyfg536+MU7m4C1CMk4ZznpXZzDYI1PDL2nS1hpvc5cNd7E2sJg05Fe7/7d3Fln8Cvc3bwB616auxsKl4WPghjemHrDqyDWeu1UNW5s2btPnSQ75oOdunEwWazfwgVG0kqluYCM9OIjWOGnfA2b9G4Ha63XKpvQ8perTvTifJNhi6+WMWmi7smEZf6G8MmhlyGq+NqP8GV84TLuJr7UIQVx+bDEoEpRZIz42gs40OuN4Mv8hXzelV7KX1isH+ewTWckikyVv+CfHuqVF7I16gN0VKypX6wPsE+zFPzkinolU9UH8OMGvSpnZqKsv13p/RsMun6X5x/y2LeAr8O66lsBwzBMP/wJfyGq8pgBk6IAAAAASUVORK5CYII=',
'this is my filename.png'
);
const msg = await client.sendMessage(remoteId, media, { sendMediaAsDocument: true});
expect(msg).to.be.instanceOf(Message);
expect(msg.type).to.equal(MessageTypes.DOCUMENT);
expect(msg.fromMe).to.equal(true);
expect(msg.hasMedia).to.equal(true);
expect(msg.body).to.equal('this is my filename.png');
expect(msg.to).to.equal(remoteId);
});
it('can send a sticker message', async function() {
const media = new MessageMedia(
'image/png',
'iVBORw0KGgoAAAANSUhEUgAAAV4AAACWBAMAAABkyf1EAAAAG1BMVEXMzMyWlpacnJyqqqrFxcWxsbGjo6O3t7e+vr6He3KoAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAEcElEQVR4nO2aTW/bRhCGh18ij1zKknMkbbf2UXITIEeyMhIfRaF1exQLA/JRclslRykO+rs7s7s0VwytNmhJtsA8gHZEcox9PTs7uysQgGEYhmEYhmEYhmEYhmEYhmEYhmEYhmEYhmEYhmEYhmGYr2OWRK/ReIKI8Zt7Hb19wTcQ0uTkGh13bQupcw7gPOvdo12/5CzNtNR7xLUtNtT3CGBQ6g3InjY720pvofUec22LJPr8PhEp2OMPyI40PdwWUdronCu9yQpdPx53bQlfLKnfOVhlnDYRBXve4Ov+IZTeMgdedm0NR+xoXJeQvdJ3CvziykSukwil16W/Oe7aGjIjqc/9ib4jQlJy0uArtN4A0+cvXFvDkmUJ47sJ1Y1ATLDNVXZkNPIepQzxy1ki9fqiwbUj/I+64zxWNzyZnPuhvohJ9K70VvXBixpcu2SAHU+Xd9EKdEJDNpYP3AQr3bQSpPQ6Y6/4dl1z7ZDbArsszjA7L0g7ibB0CDcidUWVoErvIMKZh2Xs0LUzcLW6V5NfiUgNEbaYmAVL6bXl0nJRc+1S72ua/D/cTjGPlQj7eUqd7A096rYlRjdPYlhz7VIvxpVG3cemDKF+WAwLY/6XelOZKTXXzsC4xvDjjtSN6kHLhLke6PrwM8h1raf40qjrGO7H9aTEbduucjS04ZrYU/4iuS5Z2Hdt0rvCLFdmLEXcU30AGddST62o+sLcf5l6k7CP+ru4pLYqX/VFyxbm/utQbx/r22ZEbTb2f5I2kns1Y1OQR8ZyofX+TjJxj1Rz7QQVnf1QzR26Oth0ueJVYcRP6ZUPac/Rx/5M6ixO1dhSrT3Y1DpiYmx3tF4ZUdpz9LD/dSg9PXES0LB71BwcGjKROuV28lnvnv7HHJsezheBGH5+X2CfSfRbMKW+5aGs3JFjMrjGibJc0S7TJzqjHrh2hDybj9XRXNZa89Aro55XBdbW5wti2c/5WJ7jJ1RolVUn/HWpb0I58Tziup6Rx7Dm2hnbRP1GM9PW/NFmQ4PtVRVN63Wvxfmu5sowDMMwDMMwDMMwDMMwDMMwDMMwzL+CpT//F/6beoV8zb2Jmt4Qryx6lTUCsENQ75HOkhXAO3EPVgyQtKtUy3C/e+FJg17Zjnew1Xrdb9InbG4WqfUAftG+WhLwPVyfg536+MU7m4C1CMk4ZznpXZzDYI1PDL2nS1hpvc5cNd7E2sJg05Fe7/7d3Fln8Cvc3bwB616auxsKl4WPghjemHrDqyDWeu1UNW5s2btPnSQ75oOdunEwWazfwgVG0kqluYCM9OIjWOGnfA2b9G4Ha63XKpvQ8perTvTifJNhi6+WMWmi7smEZf6G8MmhlyGq+NqP8GV84TLuJr7UIQVx+bDEoEpRZIz42gs40OuN4Mv8hXzelV7KX1isH+ewTWckikyVv+CfHuqVF7I16gN0VKypX6wPsE+zFPzkinolU9UH8OMGvSpnZqKsv13p/RsMun6X5x/y2LeAr8O66lsBwzBMP/wJfyGq8pgBk6IAAAAASUVORK5CYII='
);
const msg = await client.sendMessage(remoteId, media, {sendMediaAsSticker: true});
expect(msg).to.be.instanceOf(Message);
expect(msg.type).to.equal(MessageTypes.STICKER);
expect(msg.fromMe).to.equal(true);
expect(msg.hasMedia).to.equal(true);
expect(msg.to).to.equal(remoteId);
});
it('can send a sticker message with custom author and name', async function() {
const media = new MessageMedia(
'image/png',
'iVBORw0KGgoAAAANSUhEUgAAAV4AAACWBAMAAABkyf1EAAAAG1BMVEXMzMyWlpacnJyqqqrFxcWxsbGjo6O3t7e+vr6He3KoAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAEcElEQVR4nO2aTW/bRhCGh18ij1zKknMkbbf2UXITIEeyMhIfRaF1exQLA/JRclslRykO+rs7s7s0VwytNmhJtsA8gHZEcox9PTs7uysQgGEYhmEYhmEYhmEYhmEYhmEYhmEYhmEYhmEYhmEYhmGYr2OWRK/ReIKI8Zt7Hb19wTcQ0uTkGh13bQupcw7gPOvdo12/5CzNtNR7xLUtNtT3CGBQ6g3InjY720pvofUec22LJPr8PhEp2OMPyI40PdwWUdronCu9yQpdPx53bQlfLKnfOVhlnDYRBXve4Ov+IZTeMgdedm0NR+xoXJeQvdJ3CvziykSukwil16W/Oe7aGjIjqc/9ib4jQlJy0uArtN4A0+cvXFvDkmUJ47sJ1Y1ATLDNVXZkNPIepQzxy1ki9fqiwbUj/I+64zxWNzyZnPuhvohJ9K70VvXBixpcu2SAHU+Xd9EKdEJDNpYP3AQr3bQSpPQ6Y6/4dl1z7ZDbArsszjA7L0g7ibB0CDcidUWVoErvIMKZh2Xs0LUzcLW6V5NfiUgNEbaYmAVL6bXl0nJRc+1S72ua/D/cTjGPlQj7eUqd7A096rYlRjdPYlhz7VIvxpVG3cemDKF+WAwLY/6XelOZKTXXzsC4xvDjjtSN6kHLhLke6PrwM8h1raf40qjrGO7H9aTEbduucjS04ZrYU/4iuS5Z2Hdt0rvCLFdmLEXcU30AGddST62o+sLcf5l6k7CP+ru4pLYqX/VFyxbm/utQbx/r22ZEbTb2f5I2kns1Y1OQR8ZyofX+TjJxj1Rz7QQVnf1QzR26Oth0ueJVYcRP6ZUPac/Rx/5M6ixO1dhSrT3Y1DpiYmx3tF4ZUdpz9LD/dSg9PXES0LB71BwcGjKROuV28lnvnv7HHJsezheBGH5+X2CfSfRbMKW+5aGs3JFjMrjGibJc0S7TJzqjHrh2hDybj9XRXNZa89Aro55XBdbW5wti2c/5WJ7jJ1RolVUn/HWpb0I58Tziup6Rx7Dm2hnbRP1GM9PW/NFmQ4PtVRVN63Wvxfmu5sowDMMwDMMwDMMwDMMwDMMwDMMwzL+CpT//F/6beoV8zb2Jmt4Qryx6lTUCsENQ75HOkhXAO3EPVgyQtKtUy3C/e+FJg17Zjnew1Xrdb9InbG4WqfUAftG+WhLwPVyfg536+MU7m4C1CMk4ZznpXZzDYI1PDL2nS1hpvc5cNd7E2sJg05Fe7/7d3Fln8Cvc3bwB616auxsKl4WPghjemHrDqyDWeu1UNW5s2btPnSQ75oOdunEwWazfwgVG0kqluYCM9OIjWOGnfA2b9G4Ha63XKpvQ8perTvTifJNhi6+WMWmi7smEZf6G8MmhlyGq+NqP8GV84TLuJr7UIQVx+bDEoEpRZIz42gs40OuN4Mv8hXzelV7KX1isH+ewTWckikyVv+CfHuqVF7I16gN0VKypX6wPsE+zFPzkinolU9UH8OMGvSpnZqKsv13p/RsMun6X5x/y2LeAr8O66lsBwzBMP/wJfyGq8pgBk6IAAAAASUVORK5CYII='
);
const msg = await client.sendMessage(remoteId, media, {
sendMediaAsSticker: true,
stickerAuthor: 'WWEBJS',
stickerName: 'My Sticker'
});
expect(msg).to.be.instanceOf(Message);
expect(msg.type).to.equal(MessageTypes.STICKER);
expect(msg.fromMe).to.equal(true);
expect(msg.hasMedia).to.equal(true);
expect(msg.to).to.equal(remoteId);
});
it('can send a location message', async function() {
const location = new Location(37.422, -122.084, 'Googleplex\nGoogle Headquarters');
const msg = await client.sendMessage(remoteId, location);
expect(msg).to.be.instanceOf(Message);
expect(msg.type).to.equal(MessageTypes.LOCATION);
expect(msg.fromMe).to.equal(true);
expect(msg.to).to.equal(remoteId);
expect(msg.location).to.be.instanceOf(Location);
expect(msg.location.latitude).to.equal(37.422);
expect(msg.location.longitude).to.equal(-122.084);
expect(msg.location.description).to.equal('Googleplex\nGoogle Headquarters');
});
it('can send a vCard as a contact card message', async function() {
const vCard = `BEGIN:VCARD
VERSION:3.0
FN;CHARSET=UTF-8:John Doe
N;CHARSET=UTF-8:Doe;John;;;
EMAIL;CHARSET=UTF-8;type=HOME,INTERNET:john@doe.com
TEL;TYPE=HOME,VOICE:1234567890
REV:2021-06-06T02:35:53.559Z
END:VCARD`;
const msg = await client.sendMessage(remoteId, vCard);
expect(msg).to.be.instanceOf(Message);
expect(msg.type).to.equal(MessageTypes.CONTACT_CARD);
expect(msg.fromMe).to.equal(true);
expect(msg.to).to.equal(remoteId);
expect(msg.body).to.equal(vCard);
expect(msg.vCards).to.have.lengthOf(1);
expect(msg.vCards[0]).to.equal(vCard);
});
it('can optionally turn off vCard parsing', async function() {
const vCard = `BEGIN:VCARD
VERSION:3.0
FN;CHARSET=UTF-8:John Doe
N;CHARSET=UTF-8:Doe;John;;;
EMAIL;CHARSET=UTF-8;type=HOME,INTERNET:john@doe.com
TEL;TYPE=HOME,VOICE:1234567890
REV:2021-06-06T02:35:53.559Z
END:VCARD`;
const msg = await client.sendMessage(remoteId, vCard, {parseVCards: false});
expect(msg).to.be.instanceOf(Message);
expect(msg.type).to.equal(MessageTypes.TEXT); // not a contact card
expect(msg.fromMe).to.equal(true);
expect(msg.to).to.equal(remoteId);
expect(msg.body).to.equal(vCard);
});
it('can send a Contact as a contact card message', async function() {
const contact = await client.getContactById(remoteId);
const msg = await client.sendMessage(remoteId, contact);
expect(msg).to.be.instanceOf(Message);
expect(msg.type).to.equal(MessageTypes.CONTACT_CARD);
expect(msg.fromMe).to.equal(true);
expect(msg.to).to.equal(remoteId);
expect(msg.body).to.match(/BEGIN:VCARD/);
expect(msg.vCards).to.have.lengthOf(1);
expect(msg.vCards[0]).to.match(/BEGIN:VCARD/);
});
it('can send multiple Contacts as a contact card message', async function () {
const contact1 = await client.getContactById(remoteId);
const contact2 = await client.getContactById('5511942167462@c.us'); //iFood
const msg = await client.sendMessage(remoteId, [contact1, contact2]);
expect(msg).to.be.instanceOf(Message);
expect(msg.type).to.equal(MessageTypes.CONTACT_CARD_MULTI);
expect(msg.fromMe).to.equal(true);
expect(msg.to).to.equal(remoteId);
expect(msg.vCards).to.have.lengthOf(2);
expect(msg.vCards[0]).to.match(/BEGIN:VCARD/);
expect(msg.vCards[1]).to.match(/BEGIN:VCARD/);
});
});
describe('Get Chats', function () {
it('can get a chat by its ID', async function () {
const chat = await client.getChatById(remoteId);
expect(chat).to.be.instanceOf(Chat);
expect(chat.id._serialized).to.eql(remoteId);
expect(chat.isGroup).to.eql(false);
});
it('can get all chats', async function () {
const chats = await client.getChats();
expect(chats.length).to.be.greaterThanOrEqual(1);
const chat = chats.find(c => c.id._serialized === remoteId);
expect(chat).to.exist;
expect(chat).to.be.instanceOf(Chat);
});
});
describe('Get Contacts', function () {
it('can get a contact by its ID', async function () {
const contact = await client.getContactById(remoteId);
expect(contact).to.be.instanceOf(Contact);
expect(contact.id._serialized).to.eql(remoteId);
expect(contact.number).to.eql(remoteId.split('@')[0]);
});
it('can get all contacts', async function () {
const contacts = await client.getContacts();
expect(contacts.length).to.be.greaterThanOrEqual(1);
const contact = contacts.find(c => c.id._serialized === remoteId);
expect(contact).to.exist;
expect(contact).to.be.instanceOf(Contact);
});
});
describe('Numbers and Users', function () {
it('can verify that a user is registered', async function () {
const isRegistered = await client.isRegisteredUser(remoteId);
expect(isRegistered).to.be.true;
});
it('can verify that a user is not registered', async function () {
const isRegistered = await client.isRegisteredUser('9999999999@c.us');
expect(isRegistered).to.be.false;
});
it('can get a number\'s whatsapp id', async function () {
const number = remoteId.split('@')[0];
const numberId = await client.getNumberId(number);
expect(numberId).to.eql({
server: 'c.us',
user: number,
_serialized: `${number}@c.us`
});
});
it('returns null when getting an unregistered number\'s whatsapp id', async function () {
const number = '9999999999';
const numberId = await client.getNumberId(number);
expect(numberId).to.eql(null);
});
});
});
});

40
tests/helper.js Normal file
View File

@@ -0,0 +1,40 @@
const path = require('path');
const Client = require('../src/Client');
const Util = require('../src/util/Util');
require('dotenv').config();
const remoteId = process.env.WWEBJS_TEST_REMOTE_ID;
if(!remoteId) throw new Error('The WWEBJS_TEST_REMOTE_ID environment variable has not been set.');
function getSessionFromEnv() {
const envSession = process.env.WWEBJS_TEST_SESSION;
if(envSession) return JSON.parse(envSession);
const envSessionPath = process.env.WWEBJS_TEST_SESSION_PATH;
if(envSessionPath) {
const absPath = path.resolve(process.cwd(), envSessionPath);
return require(absPath);
}
throw new Error('No session found in environment.');
}
function createClient({withSession, options: additionalOpts}={}) {
const options = {};
if(withSession) {
options.session = getSessionFromEnv();
}
return new Client(Util.mergeDefault(options, additionalOpts || {}));
}
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
module.exports = {
sleep,
createClient,
remoteId
};

View File

@@ -0,0 +1 @@
2.2126.14

View File

@@ -0,0 +1,46 @@
#!/usr/bin/env node
const fs = require('fs');
const fetch = require('node-fetch');
const getLatestVersion = async (currentVersion) => {
const res = await fetch(`https://web.whatsapp.com/check-update?version=${currentVersion}&platform=web`);
const data = await res.json();
return data.currentVersion;
};
const getCurrentVersion = () => {
try {
const versionFile = fs.readFileSync('./.version');
return versionFile ? versionFile.toString().trim() : null;
} catch(_) {
return null;
}
};
const updateVersion = async (oldVersion, newVersion) => {
const readmePath = '../../README.md';
const readme = fs.readFileSync(readmePath);
const newReadme = readme.toString().replaceAll(oldVersion, newVersion);
fs.writeFileSync(readmePath, newReadme);
fs.writeFileSync('./.version', newVersion);
};
(async () => {
const currentVersion = getCurrentVersion();
const version = await getLatestVersion(currentVersion);
console.log(`Current version: ${currentVersion}`);
console.log(`Latest version: ${version}`);
if(currentVersion !== version) {
console.log('Updating files...');
await updateVersion(currentVersion, version);
console.log('Updated!');
} else {
console.log('No changes.');
}
})();