Compare commits

...

233 Commits

Author SHA1 Message Date
Pedro Lopez
8afe71d959 add constants to version updater 2022-11-26 18:17:44 -04:00
Pedro Lopez
afb0b5d7d3 feat: use specific whatsapp web version 2022-11-26 18:17:19 -04:00
Pedro Lopez
6fe1017bd3 chore: mark version v1.18.4 2022-11-26 05:27:37 -04:00
github-actions[bot]
a15f1b8428 Update supported WhatsApp Web version to v2.2245.9 (#1764)
Co-authored-by: pedroslopez <pedroslopez@users.noreply.github.com>
2022-11-26 05:26:46 -04:00
Pedro S. Lopez
dc91562f3c fix: star/unstar messages (#1843) 2022-11-26 05:12:54 -04:00
Pedro S. Lopez
db55d869f8 fix: delete messages for everyone (#1842) 2022-11-26 04:44:35 -04:00
Pedro S. Lopez
d9f9c28276 fix: get quoted msg (#1841) 2022-11-26 04:38:29 -04:00
Pedro Lopez
a60f5ebf40 chore: mark version v1.18.3 2022-11-13 21:12:55 -05:00
WWebJS Bot
e8bae22b03 1.18.3-alpha.0 2022-11-13 17:54:03 +00:00
Felipe Martins
82120f0446 Fix GroupMetadata module (#1789)
* Fix GroupMetadata module

* Update src/util/Injected.js

Co-authored-by: Felipe Martins <felipe.dev@virtuamax.com.br>
Co-authored-by: Rajeh Taher <rajeh@reforward.dev>
2022-11-13 12:36:06 +01:00
Pedro Lopez
6f7c5c2dd9 chore: mark version v1.18.2 2022-10-26 23:32:56 -04:00
Pedro S. Lopez
9981723505 fix: message replies compatible with WhatsApp Web v2.2241.6 (#1765)
* fix message replies

* fix up some tests
2022-10-26 23:32:06 -04:00
Pedro Lopez
7bb7f13f07 bump supported version 2022-10-26 22:45:05 -04:00
Pedro Lopez
7d672078cd chore: mark version v1.18.1 2022-10-26 22:44:05 -04:00
Pedro S. Lopez
088ec32b7b Support for WhatsApp Web 2.2241.6 (#1762)
* proposed fix

* Fixes

* Add condition for older versions of WA

* fix for old node version support

* fix: default to mdbackend = true

Co-authored-by: purpshell <rajeh@reforward.dev>
2022-10-26 22:43:19 -04:00
Pedro Lopez
ef3eadc6e5 chore: mark version 1.18.0 2022-10-21 00:25:57 -04:00
github-actions[bot]
ab87fecfd9 Update supported WhatsApp Web version to v2.2240.7 (#1592)
Co-authored-by: pedroslopez <pedroslopez@users.noreply.github.com>
2022-10-21 00:22:56 -04:00
Pedro S. Lopez
36aa37f1ac fix: set ephemeral fields and get links from messages (#1752)
* fix setting ephemeral fields

* fix missing links method
2022-10-21 00:12:02 -04:00
tuyuribr
45972fb47e Create pull_request_template (#1632)
Any Ideas on how to improve this template?


https://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/creating-a-pull-request-template-for-your-repository

Co-authored-by: Rajeh Taher <rajeh@reforward.dev>
Co-authored-by: Aliyss Snow <33941859+Aliyss@users.noreply.github.com>
2022-10-10 22:45:48 +02:00
stefanfuchs
55f75b8f69 fix: typescript compilation (#1693)
Co-authored-by: Rajeh Taher <rajeh@reforward.dev>
2022-10-04 14:24:03 +02:00
blox
b1e0fce504 Allow the deletion of others' messages (#1688) 2022-09-18 16:33:43 -03:00
༺ LᴇG̸ᴇɴD ༻
62623347e8 [Update] - adding catch block on promise for windows error (#1659) 2022-08-18 20:26:46 +03:00
Shir Serlui
705d4d31fd Use getCommonGroups not contact (#1623) 2022-08-18 13:20:30 -03:00
WWebJS Bot
bd4df4cf75 1.18.0-alpha.1 2022-08-15 07:54:39 +00:00
Pedro S. Lopez
7fe3574730 fix(release): try setting PAT to push to main 2022-08-15 03:53:57 -04:00
Pedro Lopez
09a81d0e1e v1.18.0-alpha.0 2022-08-15 03:47:51 -04:00
Pedro S. Lopez
c09a22c533 fix(publish): exit if pushing to github failed 2022-08-15 03:42:06 -04:00
Pedro S. Lopez
bb09bb74e7 fix(publish): add git user 2022-08-15 03:32:40 -04:00
Pedro Lopez
694a52bf26 fix(publish): ouput, remove message 2022-08-15 03:22:43 -04:00
Pedro Lopez
c459eca799 add release action 2022-08-15 02:52:17 -04:00
Roi Greenberg
b74246d69a Add "fromMe" option to fetchMessages (#1444) 2022-08-14 12:30:14 -03:00
Yuri
ab7ee0eb4f Fixing remote auth optional depencies error (#1640)
Co-authored-by: Rajeh Taher <rajeh@reforward.dev>
2022-08-10 19:46:43 +03:00
jurajmatus
537e843a49 Async buffer->BASE64 conversion (#1481)
* Async buffer->BASE64 conversion

* ESLint fixes
2022-08-10 16:31:04 +00:00
༺ LᴇG̸ᴇɴD ༻
76f7a6e279 feat: RemoteAuth Strategy (#1450)
* index.js

* [authReady] - new BaseAuthStrategy function

* [RemoteAuth] - new Class RemoteAuth added

* Eslint Fixes

* Eslint Fixes

* Added types for RemoteAuth (mostly assumed types from PR message and src/authStrategies/RemoteAuth.js)

* [dependency updates] - added unzipper & archiver

* [Types] - Fixing typescript declarations

* Renaming Base Class Hook

* auth hook rename on client

* [Error Handling] - Delegate responsability to end users

* [Refactor] - deletemetadata code refactor

* [Refactor] - backupSyncIntervalMs renamed

* [Refactor] - Minor improvement on deleteMetadata

* [Refactor] - backupSyncIntervalMs rename on index.d.ts

* [Update] - Fix for Ubuntu crahsing on extractSession

* [Update] - Delegate responsability to stores of making sure the previous session is deleted strictly only after the new one is saved

* [Update] - Improve file paths handling & naming (reduce assumptions between RemoteAuth and stores)

* [Update] - Adding new event <REMOTE_SESSION_SAVED> on Constants.js

* [Update] - Adding new authHooks <destroy> & <disconnect>

* [Update] - Adding <destroy> & <disconnect> hooks on Client.js

* [Update] - Adding new features to index.d.ts

* [RemoteAuth] - New Features added to RemoteAuth Class

* [dependency updates] - added fs-extra

* [Cross Platform] - Windows is now compatible with RemoteAuth

* [optionalDependencies] - moved archiver, fs-extra & unzipper to optional dependencies on package.json

* [optionalDependencies] - adding validation for when optional dependencies are missing

* [Update] - Node Deprecation warining for rmdir changed for rm instead

Co-authored-by: h110m <nichtwitzig228@gmail.com>
2022-08-10 13:03:07 +02:00
Wictor Nogueira
f2ec77f969 Feat: add message_reaction event (#1619)
* Add 'message_reaction' event
2022-08-09 16:09:16 -03:00
Jeremy Andes
fd368361df Fix: Cannot read properties of undefined (reading 'id') (#1604)
This change fix `react` evaluation:

```
Error: Evaluation failed: TypeError: Cannot read properties of undefined (reading 'id')
    at Object.<anonymous> (https://web.whatsapp.com/bootstrap_main.44dc3fdf06d9bb8b053d.js:2:103021)
    at Generator.next (<anonymous>)
    at t (https://web.whatsapp.com/vendor1~bootstrap_qr.5922e52928d864c0918c.js:2:66483)
    at s (https://web.whatsapp.com/vendor1~bootstrap_qr.5922e52928d864c0918c.js:2:66694)
    at https://web.whatsapp.com/vendor1~bootstrap_qr.5922e52928d864c0918c.js:2:66753
    at Y (https://web.whatsapp.com/bootstrap_qr.f74b98c729dd38392a5f.js:37:128505)
    at new y (https://web.whatsapp.com/bootstrap_qr.f74b98c729dd38392a5f.js:37:121072)
    at Object.<anonymous> (https://web.whatsapp.com/vendor1~bootstrap_qr.5922e52928d864c0918c.js:2:66634)
    at Object.k (https://web.whatsapp.com/bootstrap_main.44dc3fdf06d9bb8b053d.js:2:105511)
    at Object.t.sendReactionToMsg (https://web.whatsapp.com/bootstrap_main.44dc3fdf06d9bb8b053d.js:2:102647)
    at ExecutionContext._evaluateInternal (/app/node_modules/puppeteer/lib/cjs/puppeteer/common/ExecutionContext.js:221:19)
    at runMicrotasks (<anonymous>)
    at processTicksAndRejections (node:internal/process/task_queues:96:5)
    at async ExecutionContext.evaluate (/app/node_modules/puppeteer/lib/cjs/puppeteer/common/ExecutionContext.js:110:16)
    at async Message.react (/app/node_modules/whatsapp-web.js/src/structures/Message.js:344:9)
```

Co-authored-by: Rajeh Taher <rajeh@reforward.dev>
2022-08-09 15:30:56 +00:00
Rajeh Taher
bd553f75d3 feat: Adding file size by bytes to MessageMedia (#1273)
* Update index.d.ts

* Update Message.js

* Update Message.js

* Update MessageMedia.js

* Update MessageMedia.js
2022-08-09 15:29:59 +00:00
tonbotfy
c5c705a553 feat: [Updated] Loading screen listener with percent and message (#1563)
* last update

* eslint fix

* headless fix

* Update index.d.ts

Co-authored-by: stefanfuchs <stefan1234@gmail.com>

* Update index.d.ts - Add 'LOADING_SCREEN' type to Enum

Co-authored-by: stefanfuchs <stefan1234@gmail.com>
Co-authored-by: Rajeh Taher <rajeh@reforward.dev>
2022-08-09 15:27:35 +00:00
Yehuda Eisenberg
6e047cb9be Update User agent (#1470)
I encountered errors because of this (it says that the chrome version needs to be updated)

Co-authored-by: Rajeh Taher <rajeh@reforward.dev>
2022-08-09 15:26:45 +00:00
Ruvian S
56343497e9 fix: star Error: Evaluation failed: TypeError: msg.chat.sendStarMsgs is not a function (#1598)
Co-authored-by: Rajeh Taher <rajeh@reforward.dev>
2022-08-09 15:25:53 +00:00
Nowbie S
6a4fca0a77 updating forward documentation. (#1624)
* updating forward documentation.

* Update Message.js

* Update index.d.ts

* Update docs/Message.html

Co-authored-by: Rajeh Taher <rajeh@reforward.dev>
2022-08-09 18:24:43 +03:00
github-actions[bot]
e91077a615 Update supported WhatsApp Web version to v2.2224.8 (#1532)
Co-authored-by: pedroslopez <pedroslopez@users.noreply.github.com>
2022-07-10 02:24:57 -04:00
Pedro Lopez
0e5bd9f38e chore: mark version v1.17.1 2022-07-10 02:22:20 -04:00
Thomas
75d3c635f0 Add missing deviceType property in Message interface (#1510)
Co-authored-by: Rajeh Taher <rajeh@reforward.dev>
2022-07-10 02:15:11 -04:00
Keenan Yafiq
8497a3d7e5 Add "React to message" in README (#1534)
* Add "React message" in Supported features list

* Update README.md

Co-authored-by: Pedro S. Lopez <pedroslopez@me.com>
2022-07-10 02:14:16 -04:00
Maksim
e7025ceca1 Fix TS declaration for Promise of new "react" method (#1561)
Without explicit delaration of void <T> for Promise running tsc causing the error:

```
node_modules/whatsapp-web.js/index.d.ts:707:38 - error TS2314: Generic type 'Promise<T>' requires 1 type argument(s).
```
2022-07-10 02:11:34 -04:00
Caio Agiani
b8b41920e3 chore(client): adjust typo (#1565) 2022-07-10 02:10:53 -04:00
༺ LᴇG̸ᴇɴD ༻
73e4b3b6e0 fix: getNumberId Error: Evaluation failed: TypeError: e.isLid is not a function (#1571) 2022-07-10 02:07:57 -04:00
Pedro Lopez
af431df1c9 chore: mark version v1.17.0 2022-06-21 01:36:19 -04:00
Alon Schwartzblat
61c0a6be56 Reaction feature added. (#1400)
* Fix get order.

* Fix types.

* Add set picture for profile and for groups.

* Fix bug.

* Fix

* Fix types

* Fix eslint

* Add send reaction feature.

* Add send reaction feature.

* Add set picture for profile and for groups.

* Add send reaction feature.

* Add send reaction feature.

* Add send reaction feature.

* Add send reaction feature.

* Add send reaction feature.

* Add send reaction feature.

* Update src/structures/Reaction.js

Co-authored-by: Noah van der Aa <ndvdaa@gmail.com>

* Bug fixes.

* Bug fixes.

* Bug fixes.

* Fix

* Fix

* Fix example

* Fix conflict

* Fix conflict

* Fix conflict

* Fix conflict

* Fix conflict

* Fix conflict

* move implementation to message model

Co-authored-by: Noah van der Aa <ndvdaa@gmail.com>
Co-authored-by: Pedro Lopez <pedroslopez@me.com>
2022-06-21 00:46:07 -04:00
Pedro S. Lopez
a0b18fb685 fix: set user agent as a launch arg for usage in serviceworker (#1518) 2022-06-21 00:01:59 -04:00
jurajmatus
98ff761cfb fix: fetchMessages infinite loop when there are no messages in the chat (#1480)
* Fix of fetchMessages

* Node 12 compatibility
2022-06-14 00:22:53 -04:00
Pedro Lopez
c0ef9223ed chore: mark version 1.16.7 2022-06-09 23:57:17 -04:00
github-actions[bot]
294e5027b0 Update supported WhatsApp Web version to v2.2220.8 (#1416)
Co-authored-by: pedroslopez <pedroslopez@users.noreply.github.com>
2022-06-09 23:47:17 -04:00
Shir Serlui
ebc56bc280 fix: correctly get models and fetchMessages in WhatsApp Web v2.2220.8
* Fix models is undefined

* Feat models is undefined

* Feat models is undefined

* Fix loadEarlierMsgs

* use `getModelsArray()` to get models

* fix: correctly loadEarlierMsgs with ConversationMsgs module

Co-authored-by: Pedro Lopez <pedroslopez@me.com>
2022-06-09 23:41:25 -04:00
Pedro Lopez
b16e1cdf83 chore: mark version 1.16.6 2022-04-21 17:58:08 -04:00
github-actions[bot]
a24294ec61 Update supported WhatsApp Web version to v2.2212.8 (#1381)
Co-authored-by: pedroslopez <pedroslopez@users.noreply.github.com>
2022-04-21 17:32:42 -04:00
Pedro Lopez
374983b9a6 fix: find old features module 2022-04-21 17:18:47 -04:00
Rajeh Taher
5e2e9dd139 Fix: Cannot read properties of undefined (reading 'features') // original: (#1407) (#1410)
* Fix: Cannot read properties of undefined (reading 'features') (#1407)

* Fix: Cannot read properties of undefined (reading 'features')

Find MD backend without features

* Fix for tests

* Update Client.js

* Update LegacySessionAuth.js

Co-authored-by: Shir Serlui <70711723+shirser121@users.noreply.github.com>
2022-04-21 17:15:00 -04:00
Pedro Lopez
3a2acf71c2 chore: mark version v1.16.5 2022-03-28 23:47:16 -04:00
Pedro Lopez
f32f3c71ba fix: get groupnotification chat
close #1329
2022-03-28 23:44:04 -04:00
github-actions[bot]
017dd4b783 Update supported WhatsApp Web version to v2.2210.9 (#1340)
Co-authored-by: pedroslopez <pedroslopez@users.noreply.github.com>
2022-03-28 23:28:09 -04:00
Ahmed Fouzan
fa9f6610d7 fix(typings): Add ConnectOptions typings (#1354)
* Add ConnectOptions typings

* simplify type

Co-authored-by: Pedro S. Lopez <pedroslopez@me.com>
2022-03-28 23:22:51 -04:00
༺ LᴇG̸ᴇɴD ༻
e9104b390d Fix: Cannot read properties of undefined (reading 'getProfilePicFull') (#1362)
* Fix for issue#1356 - Cannot read properties of undefined reading getProfilePicFull

* use cross-compatible profilePicFind function

Co-authored-by: Joaquin Touris <joaquin@192.168.1.6>
Co-authored-by: Pedro Lopez <pedroslopez@me.com>
2022-03-28 23:17:55 -04:00
ogxing
a23c285f3c fix: group chat create (#1319) 2022-03-28 22:56:07 -04:00
github-actions[bot]
281aec40ad Update supported WhatsApp Web version to v2.2208.7 (#1287)
Co-authored-by: pedroslopez <pedroslopez@users.noreply.github.com>
Co-authored-by: Pedro S. Lopez <pedroslopez@me.com>
2022-03-09 18:32:04 -04:00
Pedro Lopez
2e4890d113 chore: mark version v1.16.4 2022-03-09 18:26:05 -04:00
Pedro Lopez
0bd8eb9d96 chore: mark version v1.16.4-alpha.0 2022-03-09 00:57:36 -04:00
Pedro S. Lopez
2718c1328c fix compatibility issues with WhatsApp Web 2.2208.7 (#1311)
* fix compatiblity issues with v2.2208.7

* remove expclusive test
2022-03-09 00:54:57 -04:00
Pedro Lopez
24f8b4622b chore: mark version v1.16.3 2022-03-06 23:30:20 -04:00
Pedro Lopez
9ab9c48f7b fix(typings): LegacySessionAuth restartOnAuthFail 2022-03-06 01:35:58 -04:00
༺ LᴇG̸ᴇɴD ༻
b96607338a getProfilePicture Fix => Evaluation failed: Error: Comms::sendIq called before startComms (#1264)
* Fix: Evaluation failed: Error: Comms::sendIq called before startComms

* [Requested Changes] - Only call Wap if we're not on MD & vice-versa

Co-authored-by: Joaquin Touris <joaquin@192.168.1.5>
2022-03-05 16:24:40 +02:00
Pedro S. Lopez
ea2cc81d47 add feature request form template 2022-03-05 02:30:49 -04:00
Clifford Fajardo
56644f4f03 add github ISSUE_TEMPLATE files (#1195)
* add github ISSUE_TEMPLATE files

* Update .github/ISSUE_TEMPLATE/config.yml

* Update .github/ISSUE_TEMPLATE/bug_report.yml

Co-authored-by: Rajeh Taher <rajeh@reforward.dev>

* apply updates per feedback that was given

* Update bug_report.yml

* Update bug_report.yml

* Update bug_report.yml

* Update bug_report.yml

* Update bug_report.yml

* Update bug_report.yml

Co-authored-by: clifford <cfajardo@linkedin.com>
Co-authored-by: Rajeh Taher <rajeh@reforward.dev>
Co-authored-by: Pedro S. Lopez <pedroslopez@me.com>
2022-03-05 02:26:49 -04:00
Pedro Lopez
fcb78a1cd4 chore: mark version v1.16.2 2022-03-01 23:23:26 -04:00
Fábio Dias
f88bd274be fix(LocalAuth): logout method (#1267)
The logout method was trying to use a function call passing the "dataDir" as the "this" reference
2022-03-01 23:15:08 -04:00
Alon Schwartzblat
c45fae5c15 Fix get order. (#1274)
* Fix get order.

* Fix types.
2022-03-01 23:08:27 -04:00
Pedro Lopez
1b75d0d243 fix(LocalAuth): only throw user-supplied userDataDir error if path is different
fix #1261
2022-03-01 22:25:22 -04:00
Filipe
cc78e9863d add typings for LocalAuth attributes (#1262) 2022-02-28 23:00:21 -04:00
inceabdullah
fc205ff530 fix: Cannot destructure property 'session' of 'undefined' as it is undefined. (#1259) 2022-02-28 22:59:54 -04:00
Pedro Lopez
6ab98a5365 chore: mark version v1.16.1 2022-02-28 00:51:59 -04:00
Pedro Lopez
3c24df085a add back deprecated info.me 2022-02-28 00:51:28 -04:00
Pedro Lopez
979e97ea42 chore: mark version v1.16.0 2022-02-27 23:30:03 -04:00
Pedro Lopez
1f4328c7a3 fix tests 2022-02-27 23:29:09 -04:00
Pedro Lopez
6691d25282 fix: message.getInfo() works for both MD and non-MD 2022-02-27 23:28:57 -04:00
Pedro S. Lopez
12d9735b73 Update README.md 2022-02-27 22:58:39 -04:00
SuperChang
ab5167c4ad fix: ChangeParticipantsPermissions typo in index.d.ts (#1206)
Co-authored-by: Pedro S. Lopez <pedroslopez@me.com>
2022-02-27 22:34:12 -04:00
YaronD
52c8336236 Added message duration in seconds (#1230)
Co-authored-by: Pedro S. Lopez <pedroslopez@me.com>
2022-02-27 22:30:47 -04:00
Pedro Lopez
9fe91692cf update tests to work with authStrategies 2022-02-27 22:18:54 -04:00
Pedro S. Lopez
f6de161c7d Auth Strategies (#1257)
* auth strategies

* default to no auth

* rename base auth strategy

* rename base strategy cont.

* refactor auth strategy methods and LocalAuth

* activate old session options even if is falsy value

* move restartOnAuthFail to LegacyAuthStrategy option

* add link to guide item

* update example/shell

* types
2022-02-27 22:02:49 -04:00
Rajeh Taher
0d55d40885 feat: Multi-device support (#889)
* 🚑 Added ready selector for multi-device

* SendMessage fix

* File management system and some fixes

* cleanup

* cleanup again

* eslint

* critical fix for reloading the same session

* Checking for valid folder name (regex)

* ESLint hotfix (regex escapes)

* Typings cleanup

* cleanup listener

* Multi-device Branch merge (#888)

* Duplicate

* qr fix and allow non-beta users to connect

* urgent: selector fix

* urgent: qr timeout fix

* fix

* Updated type so no TS error when sending list/buttons

* Update index.d.ts

* fix QueryExist for Multidevice (#928)

* creates isRegisteredUserBeta

* fix QueryExist

* fix Error: GROUP_JID: invalid jid type: Not an instance of WID issue (#926)

* fix Error: GROUP_JID: invalid jid type: Not an instance of WID issue

* clean code

* Cleanup

* Fix for update chrome error

* ESLint fix

* :red_light: fix for RMDIR

* Update README.md

* Update README.md

* fix: getProfilePicUrl fix by victormga (#941)

* fix: MD presence available/unavailable (#942)

* delete session when appropriate & fix for SW

* ignore QR timeout errors

* Presence and ChatState updates working for MD+Non-MD

* shell uses new session storage

* lint fix

* support session.json-based auth for non-md

* md fix

* md fix

* fix shell clientId

* remove exclusive mocha test

* make linkPreview default to false

* remove ignored errors on getQuotedMessage

* fix: dont modify existing this.options.puppeteer object

* tests work with new dir auth

* remove exclusive test

* fixes and tests for group creation and participant functions

* remove unused function

* wip fix group settings functions

* isRegisteredUser && getNumberId hotFix (#955)

* isRegisteredUser && getNumberId hotFix

A fix for client.isRegisteredUser and client.getNumberId. Use for reference or if you are stuck with MD and NEEDS this function. Problably Whatsapp will break this in a couple weeks

* fix for non-md

Co-authored-by: Rajeh Taher <rajeh@reforward.dev>

* Fix WA 2.2146.9 MD +  victormga branch (#991)

* qrcode now uses observers instead of timeout

* automatic auth/qrcode detection

* Fix WA 2.2146.9 MD

Got from github:victormga/whatsapp-web.js#multidevice maybe it's behind pedro branch

Co-authored-by: victormga <victor_mga@hotmail.com>

* fix

* fix*

* getnumberid to multidevice (#1027)

* getNumberId to main

 isRegisteredUser && getNumberId hotFix #955 To main

* Update Client.js

Co-authored-by: tuyuribr <45042245+tuyuribr@users.noreply.github.com>

* Update Client.js

* Message.raw() (#1005)

* Message.raw()

* i just noticed

* Update index.d.ts

* Update index.d.ts

* Update Message.js

* Get rid of sharp now!!!!!!!! (#1045)

* commit 1

* finally, gotten rid of sharp

* pckg.json

* service worker fix & disableMessage option

* typings

* Update example.js

* clear session system

* Update Client.js

* Update Client.js

* Fix accepting group private invite (#1094)

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>

* [MD] Add getCommonGroups with specific user. (#1097)

* Add getCommonGroups with specific user.

* Fix

* Fix

* Fix

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>

* Fix getCommonGroups. (#1122)

* Fix of Unexpected identifier async destroy() (#1123)

* Fix of Unexpected identifier async destroy()

* Fix made in #1107

* Temporary fix for "Sticker" module

* some really quick changes

* Update Injected.js

* Update Injected.js

* Update index.d.ts

* fix: getNumberId Solved (#1142)

* getNumberId Solved

* isRegisteredUser Solved

* formmated

* Apply suggestions from code review

* Update src/util/Injected.js

Co-authored-by: Rajeh Taher <rajeh@reforward.dev>

* Fix: "Chrome user data dir was not found ..."

fixes the error caused by puppeteer.

* Update Client.js (#1154)

* fix: getNumberId and isRegisteredUser (#1159)

* fix: getNumberId and isRegisteredUser

* Apply suggestions from code review

Co-authored-by: Rajeh Taher <rajeh@reforward.dev>

* Update client.js

* Update Injected.js

* Update Client.js

* Update index.d.ts

* Update Client.js

* Update Client.js

* fix lint indentation

* fix auth_failure event for non-md, tests

* fix setting group subject

* fix finding Label module

* set remember-me after clearing localStorage

* fix: send messages to groups correctly on MD, use new ID format

* fix setting / getting contact status

* fix msg.getInfo, add message tests

* fix group settings functions

* fix set group description, handle errors in setSubject

* fix group invite functions

* fix leaving group

* bring back phone info for non-md users

* remove unused option, update typings

* add back jsdoc for qr event

* fix setting sticker metadata, clean up sticker functions

* rawData is a get only property

* fix and simplify getNumberId/isRegisteredUser

* fix getInviteInfo

* setDisplayName returns bool, not yet implemented for md

* fix: stream module (#1241)

* linkPreview has no effect on MD, return default to true

* fix: del linkPreview option on md

* cleanup, types and docs updates

* update readmes / test notes

* remove DS_Store

* DS_Store in gitignore

* test stability (timeouts/sleeps)

Co-authored-by: Rajeh Taher <rajeh@reforward.tk>
Co-authored-by: Gustavo B <52040719+Gugabit@users.noreply.github.com>
Co-authored-by: Maikel Ortega Hernández <maikeloh@gmail.com>
Co-authored-by: victormga <victor_mga@hotmail.com>
Co-authored-by: Pedro Lopez <pedroslopez@me.com>
Co-authored-by: tuyuribr <45042245+tuyuribr@users.noreply.github.com>
Co-authored-by: gon <68490103+nekiak@users.noreply.github.com>
Co-authored-by: Alon Schwartzblat <63599777+Schwartzblat@users.noreply.github.com>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: Šebestíček <44745014+SebestikCZ@users.noreply.github.com>
Co-authored-by: Emmanuel Anaya Luna <38712443+KeruMx@users.noreply.github.com>
Co-authored-by: L337C0D3R <51872799+L337C0D3R@users.noreply.github.com>
Co-authored-by: Reni Delonzek <renidelonzek@gmail.com>
2022-02-27 18:51:08 -04:00
Pedro Lopez
8ef37b68ae chore: mark version v1.15.8 2022-02-25 17:45:33 -04:00
github-actions[bot]
bd5cfdc936 Update supported WhatsApp Web version to v2.2206.5 (#1247)
Co-authored-by: pedroslopez <pedroslopez@users.noreply.github.com>
2022-02-25 17:43:30 -04:00
༺ LᴇG̸ᴇɴD ༻
f0e49efcf9 [Main Branch]: Fix Cannot read properties of undefined (reading 'Socket') (#1249)
Co-authored-by: Joaquin Touris <joaquin@192.168.1.5>
2022-02-25 17:11:28 -04:00
Pedro Lopez
5d83b45ed4 chore: mark version v1.15.7 2022-02-19 15:48:03 -04:00
github-actions[bot]
e29354fca3 Update supported WhatsApp Web version to v2.2204.13 (#1210)
Co-authored-by: pedroslopez <pedroslopez@users.noreply.github.com>
2022-02-19 15:45:21 -04:00
Shir Serlui
66283da903 Fix message.delete(true) (#1211)
* Fix message.delete(true)

* Fix for tests
2022-02-19 15:31:23 -04:00
Tomas Melone
d7f7889b0f fix: Remove duplicate identifier (#1205) 2022-02-19 15:18:34 -04:00
Pedro Lopez
11955e9f03 chore: mark version v1.15.6 2022-02-08 22:38:33 -04:00
Md. Fahim Bin Amin
444abc2c76 added the Code of Conduct, closing #1156 (#1176) 2022-02-08 22:34:33 -04:00
Pedro S. Lopez
20f3bc7a8b fix: dont cause redirect loop due to session restore (#1181)
* fix: dont cause redirect loop due to session restore

* back to `state` in docs

* use referer to determine first injection

* bring bzck disconnect on nav

* revert some changes
2022-02-08 22:33:20 -04:00
Pedro Lopez
93c8a2b05e chore: mark version v1.15.5 2022-02-06 22:20:08 -04:00
Pedro S. Lopez
70ca073f38 fix: send messages properly when disappearing mode is on (#1174)
* fix: send messages properly when dissappearing mode is on

* add `isEphemeral` to message model
2022-02-06 21:48:55 -04:00
Shir Serlui
7e36cceaf0 extra options can override other options when sending message (#1103)
* Fix the option to use special options

When we want to use some extra function we need to pass it into the options object, but because it inserted in the first line, the auto options reset some options (like 'type').
This is minor change that can help to add functionallity

* Update Injected.js

Put the special options in the end

* Update Injected.js

Fix , mistake

* only `extra` options can override everything else

Co-authored-by: Pedro Lopez <pedroslopez@me.com>
2022-02-06 21:00:10 -04:00
Noam Zaks
303ea3ab6b fix types and docs for Buttons class (#1070)
* fix: typing of buttons class

* fix remaining types

Co-authored-by: Pedro Lopez <pedroslopez@me.com>
2022-02-07 00:56:57 +00:00
Pedro Lopez
4aae8b0f32 fix: sort before splicing when fetching messages 2022-02-06 20:03:59 -04:00
Pedro Lopez
64803c2ba6 update typings for fetchMessages changes 2022-02-06 19:30:13 -04:00
Azeem Haider
aa9e19a19e fetchMessages gets currently available messages by default (#1015)
* get chat default messages fix #1014

* fixing format

* Update src/structures/Chat.js

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

Co-authored-by: Pedro S. Lopez <pedroslopez@me.com>
2022-02-06 19:27:38 -04:00
Pedro S. Lopez
7631400de1 add back the pull_request trigger on lint 2022-02-06 19:16:57 -04:00
Pedro Lopez
d7478de68a fix: emit message events after ciphertext is decrypted
fixes #924
fixes #1041
2022-02-06 18:54:10 -04:00
Pedro Lopez
a9b2a1aab8 remove duplicated message type 2022-02-06 16:30:44 -04:00
Pedro Lopez
3b4632201d fix: add missing message types 2022-02-06 16:26:25 -04:00
Pedro Lopez
2200390d4c disable eslint warning on intentionally skipped test 2022-02-05 23:36:05 -04:00
dependabot[bot]
b1f7ff01bc chore(deps-dev): bump sinon from 12.0.1 to 13.0.1 (#1160)
Bumps [sinon](https://github.com/sinonjs/sinon) from 12.0.1 to 13.0.1.
- [Release notes](https://github.com/sinonjs/sinon/releases)
- [Changelog](https://github.com/sinonjs/sinon/blob/master/docs/changelog.md)
- [Commits](https://github.com/sinonjs/sinon/compare/v12.0.1...v13.0.1)

---
updated-dependencies:
- dependency-name: sinon
  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>
2022-02-05 23:35:04 -04:00
dependabot[bot]
21d565154a chore(deps-dev): bump dotenv from 10.0.0 to 16.0.0 (#1171)
Bumps [dotenv](https://github.com/motdotla/dotenv) from 10.0.0 to 16.0.0.
- [Release notes](https://github.com/motdotla/dotenv/releases)
- [Changelog](https://github.com/motdotla/dotenv/blob/master/CHANGELOG.md)
- [Commits](https://github.com/motdotla/dotenv/compare/v10.0.0...v16.0.0)

---
updated-dependencies:
- dependency-name: dotenv
  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>
2022-02-05 23:32:53 -04:00
dependabot[bot]
09cbee0e65 chore(deps-dev): bump eslint-plugin-mocha from 9.0.0 to 10.0.3 (#1087)
Bumps [eslint-plugin-mocha](https://github.com/lo1tuma/eslint-plugin-mocha) from 9.0.0 to 10.0.3.
- [Release notes](https://github.com/lo1tuma/eslint-plugin-mocha/releases)
- [Changelog](https://github.com/lo1tuma/eslint-plugin-mocha/blob/master/CHANGELOG.md)
- [Commits](https://github.com/lo1tuma/eslint-plugin-mocha/compare/9.0.0...10.0.3)

---
updated-dependencies:
- dependency-name: eslint-plugin-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>
2022-02-05 23:32:30 -04:00
github-actions[bot]
fa9f5aba38 Update supported WhatsApp Web version to v2.2202.12 (#1152)
Co-authored-by: pedroslopez <pedroslopez@users.noreply.github.com>
2022-02-05 23:17:11 -04:00
Pedro S. Lopez
c859ac39ce fix: dont crash when calling .destroy() while waiting for qr scan (#1172)
fixes #739
fixes #951
2022-02-05 23:05:01 -04:00
Pedro S. Lopez
221d29736a remove unnecessary pull_request trigger for lint 2022-02-05 23:04:47 -04:00
Igor Nunes
078933f061 fix(typings): add MessageTypes BUTTONS_RESPONSE (#1032)
fixes #1104
2022-02-05 22:11:53 -04:00
Pedro S. Lopez
f149516d0d chore(tests): add Chat model tests (#784)
* add search and status tests

* reset to previous status in test

* move version to its own test

* add tests for Chat model

* keep hooks at the top

* run tests recursively in default script
2022-02-05 22:05:42 -04:00
Pedro S. Lopez
2f1c894a34 add tests for takeoverOnConflict (#1170)
* add tests

* fix module test, remove unused CryptoLib
2022-02-05 20:04:00 -04:00
Pedro S. Lopez
32e47d818a fix: only emit disconnected event on navigation when state is PAIRING (#1169) 2022-02-05 18:19:02 -04:00
Zulfikar
20aee44c3b fix getLabels error (#1049)
Co-authored-by: Rajeh Taher <rajeh@reforward.dev>
2022-02-05 16:41:27 -04:00
Shir Serlui
bb2ef88e0a fix: message.delete() can revoke for everyone (#1107)
Change msg.canRevoke to msg._canRevoke according to WhatsApp code change
2022-02-05 15:52:04 -04:00
tuyuribr
6878598a5d fix: await promise when setting user agent (#1113)
Some of my devices were bugging out because the setUserAgent didn't had an await, after this everything was working fine (try loading the wwebjs in a broken microSd ahhaha).

We need some testing but on my limited testing everything is working

Co-authored-by: Rajeh Taher <rajeh@reforward.dev>
2022-02-05 15:42:25 -04:00
Pedro Lopez
4e6a00dffe chore: mark version v1.15.4 2022-01-25 20:49:07 -04:00
Pedro Lopez
b93c7b4b76 fix invalid jsdoc 2022-01-25 20:48:44 -04:00
Pedro Lopez
a37ff69692 fix: restore node 12 support 2022-01-25 20:40:50 -04:00
github-actions[bot]
3705d1fea9 Update supported WhatsApp Web version to v2.2202.8 (#1084)
Co-authored-by: pedroslopez <pedroslopez@users.noreply.github.com>
Co-authored-by: Pedro S. Lopez <pedroslopez@me.com>
2022-01-25 20:16:08 -04:00
Pedro S. Lopez
7950aae5d1 fix: find Store in v2.2202.8 (#1130)
Co-authored-by: Rajeh Taher <rajeh@reforward.dev>
2022-01-25 20:15:19 -04:00
Pedro Lopez
bdff59fb44 fix: remove problematic import 2022-01-25 19:45:57 -04:00
Wictor Nogueira
d05803074a update MessageMedia.fromUrl (#811)
* fix MessageMedia.fromUrl docs

* use content-type as fallback

* set filename based on url

* fix empty filename

* wrap expression in parentheses

* hotfix

* JSDoc fix

* fix for jsdog

* eslint gets retirement home

Co-authored-by: Rajeh Taher <rajeh@reforward.dev>
Co-authored-by: Aliyss Snow <33941859+Aliyss@users.noreply.github.com>
2022-01-21 23:57:15 +01:00
Rajeh Taher
d86c39de3c fix: Fix inactivity issue (#946)
* Fixed Remember me issue

* Update Client.js
2021-12-16 15:25:35 +00:00
shirser121
46ba9c5e9a Add isGif to message._patch (#963)
* Update Message.js

Add isGif to the message data

* add typings

Co-authored-by: Rajeh Taher <rajeh@reforward.dev>
Co-authored-by: Pedro Lopez <pedroslopez@me.com>
2021-12-12 21:57:11 -04:00
Pedro Lopez
d7a493e68a fix: use correct @types/node-fetch ver, use working node-fetch ver from puppeteer, add test 2021-12-12 21:28:38 -04:00
dependabot[bot]
da95d927b9 chore(deps): bump puppeteer from 10.4.0 to 13.0.0 (#1057)
Bumps [puppeteer](https://github.com/puppeteer/puppeteer) from 10.4.0 to 13.0.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/v10.4.0...v13.0.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-12-12 21:09:56 -04:00
dependabot[bot]
92bc5e62ab chore(deps-dev): bump eslint from 7.32.0 to 8.4.1 (#1038)
Bumps [eslint](https://github.com/eslint/eslint) from 7.32.0 to 8.4.1.
- [Release notes](https://github.com/eslint/eslint/releases)
- [Changelog](https://github.com/eslint/eslint/blob/main/CHANGELOG.md)
- [Commits](https://github.com/eslint/eslint/compare/v7.32.0...v8.4.1)

---
updated-dependencies:
- dependency-name: eslint
  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-12-12 19:47:11 -04:00
dependabot[bot]
73a3e28a4b chore(deps-dev): bump @types/node-fetch from 2.5.12 to 3.0.3 (#911)
Bumps [@types/node-fetch](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node-fetch) from 2.5.12 to 3.0.3.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node-fetch)

---
updated-dependencies:
- dependency-name: "@types/node-fetch"
  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-12-12 19:46:30 -04:00
dependabot[bot]
4f376fc2fa chore(deps-dev): bump sinon from 11.1.2 to 12.0.1 (#1024)
Bumps [sinon](https://github.com/sinonjs/sinon) from 11.1.2 to 12.0.1.
- [Release notes](https://github.com/sinonjs/sinon/releases)
- [Changelog](https://github.com/sinonjs/sinon/blob/master/docs/changelog.md)
- [Commits](https://github.com/sinonjs/sinon/compare/v11.1.2...v12.0.1)

---
updated-dependencies:
- dependency-name: sinon
  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-12-12 19:41:08 -04:00
dependabot[bot]
a20c8ef8f8 chore(deps): bump mime from 2.6.0 to 3.0.0 (#1023)
Bumps [mime](https://github.com/broofa/mime) from 2.6.0 to 3.0.0.
- [Release notes](https://github.com/broofa/mime/releases)
- [Changelog](https://github.com/broofa/mime/blob/master/CHANGELOG.md)
- [Commits](https://github.com/broofa/mime/compare/v2.6.0...v3.0.0)

---
updated-dependencies:
- dependency-name: mime
  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-12-12 19:38:33 -04:00
tuyuribr
2052e0479d Fix: multiple list sections (#1004)
* Fix multiple list sections

* singleQuotes

* Update src/structures/List.js

Co-authored-by: Rajeh Taher <rajeh@reforward.dev>
2021-12-10 20:47:07 +01:00
Pedro Lopez
c55db82f73 mark version v1.15.3 2021-12-07 23:06:53 -04:00
github-actions[bot]
4e837b00f9 Update supported WhatsApp Web version to v2.2147.14 (#1033)
Co-authored-by: pedroslopez <pedroslopez@users.noreply.github.com>
2021-12-07 23:05:54 -04:00
tuyuribr
89a06b15a8 Hot Fix WA 2.2147.14 (#1035)
* Hot Fix WA 2.2147.14

* Update Injected.js

* Update Client.js

* sendPresence1

* Update Client.js

* queryLinkPreview

* openChatDrawer

* revert back to using Wap

Co-authored-by: Pedro Lopez <pedroslopez@me.com>
2021-12-07 23:04:44 -04:00
Pedro Lopez
55247576da add script to get change log 2021-11-24 10:07:27 -04:00
Pedro Lopez
8a1f6f0648 chore: mark version v1.15.2 2021-11-24 09:49:16 -04:00
github-actions[bot]
254ca884aa Update supported WhatsApp Web version to v2.2146.9 (#969)
Co-authored-by: pedroslopez <pedroslopez@users.noreply.github.com>
Co-authored-by: Pedro S. Lopez <pslamoros@hotmail.com>
2021-11-24 09:43:59 -04:00
tuyuribr
3958105926 Fix WA 2.2146.9 (#990)
* Fix WA 2.2146.9

WA is serving two versions to me,  so we need to check window.mR.findModule('Conn').lengh for a while

* to singleQuotes

* Update Injected.js

* simplify getting `Conn` module, use different object for `Store`

Co-authored-by: Pedro Lopez <pedroslopez@me.com>
2021-11-24 09:40:01 -04:00
Pedro Lopez
818bf48e5d fix: convert button ids to string 2021-11-01 21:30:34 -04:00
Pedro S. Lopez
d71544566c move links section in readme 2021-10-30 21:29:39 -04:00
Pedro S. Lopez
187aa50131 Url updates for wwebjs.dev (#944)
* Update package.json

* update links in readme
2021-10-30 21:27:08 -04:00
Pedro Lopez
e11e00d938 chore: update docs for v1.15.1 2021-10-30 00:46:37 -04:00
Pedro Lopez
d9dd89ccaf chore: mark version v1.15.1 2021-10-30 00:46:09 -04:00
Pedro Lopez
3aa0e4f7b3 fix: dont modify id reference when serializing message 2021-10-30 00:45:04 -04:00
Pedro Lopez
d82cf448d9 chore: mark version v1.15.0 2021-10-30 00:15:24 -04:00
github-actions[bot]
3f576c990c Update supported WhatsApp Web version to v2.2142.12 (#827)
Co-authored-by: pedroslopez <pedroslopez@users.noreply.github.com>
Co-authored-by: Pedro S. Lopez <pslamoros@hotmail.com>
2021-10-30 00:14:07 -04:00
Pedro Lopez
d44a525b02 fix: serialize message id remote when fetching messages
close #825
2021-10-30 00:12:06 -04:00
Pedro Lopez
d8217029ba add test for maxQrRetries 2021-10-30 00:03:19 -04:00
victormga
2a7337b142 max qr refresh before giving up (#852)
* max qr refresh before giving up

* Update src/Client.js

Co-authored-by: Rajeh Taher <rajeh@reforward.dev>

Co-authored-by: Rajeh Taher <rajeh@reforward.dev>
2021-10-29 23:45:04 -04:00
Pedro S. Lopez
1fcfaa0362 Update README.md (#907) 2021-10-29 23:43:27 -04:00
Pedro Lopez
c434e04e41 fix countrycode and formatted number functions, add tests 2021-10-29 23:41:49 -04:00
Rajeh Taher
97a1d399ee Format phone numbers (#650)
* 📦 Declared NumberInfo in store

* 📝 Add client.js functionality

* 🚨 eslint just admires singlequote strings

* 📝 Add shortcuts to using client method

*  Adding parity between the ids

*  Same method name parity

* 🚨 ESLint indentation error.

* 🚨 ESLint doublequote string error.

* 🎨 Proposed changes

* 🎨 Fixed badly done code :v and applied proposed changes.

*  fixed calling the wrong function (sigh)

*  Fixed missing try-catch code.

* 🚨 Fixes ESLint indentation errors.

*  fix the documentation issues.

* 🏷️ typescript

* 🏷️ Typo in function name

Co-authored-by: Rajeh Taher <rajeh@reforward.tk>
2021-10-29 23:33:38 -04:00
Rajeh Taher
dbf9bf2158 Type file improvements (#855)
* Updated Types

* Updated types to include (#868)

* Update index.d.ts

* fix list type

Co-authored-by: Pedro Lopez <pedroslopez@me.com>
Co-authored-by: Pedro S. Lopez <pslamoros@hotmail.com>
2021-10-29 23:32:13 -04:00
Pedro Lopez
353af130d0 remove unnecessary default 2021-10-29 23:25:06 -04:00
Rajeh Taher
06107af67d Allow a chat to be muted indefinitely (#849)
* muteChat fixed

* Update src/Client.js

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

* Update src/Client.js

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

* date fix

Co-authored-by: Pedro S. Lopez <pedroslopez@me.com>
2021-10-29 23:24:36 -04:00
Muhamad Ristiyanto
4338664590 Add getBlockedContacts method (#770)
* add simple method to get blocked ids

* Change getBlockedList to getBlockedIds

* getBlockedIds to getBlockedContacts

* typo

* ESLint & other changes

* 🏷️ types

* fix: no `this.client`

* add tests

Co-authored-by: Rajeh Taher <rajeh@reforward.dev>
Co-authored-by: Pedro Lopez <pedroslopez@me.com>
Co-authored-by: Pedro S. Lopez <pslamoros@hotmail.com>
2021-10-30 03:18:26 +00:00
Rajeh Taher
95facee885 Fixes GroupNotification.getChat() returning client's chat. (#699)
* 🥅 getChat returns expected, instead of the client's chat.

* 🥅 Fixed .reply method too

* revert + fix
2021-10-29 23:00:10 -04:00
Pedro Lopez
1f38b762ed add warning for multidevice, keep working for forced upgrade 2021-10-29 22:58:57 -04:00
tuyuribr
b60029ed09 feat: Send buttons and Lists (#756) 2021-09-14 00:06:05 +03:00
tuyuribr
ab415ff9be feat: Include payment info (#684) 2021-09-13 23:58:39 +03:00
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
118 changed files with 12137 additions and 1399 deletions

3
.env.example Normal file
View File

@@ -0,0 +1,3 @@
WWEBJS_TEST_REMOTE_ID=XXXXXXXXXX@c.us
WWEBJS_TEST_CLIENT_ID=authenticated
WWEBJS_TEST_MD=1

View File

@@ -5,14 +5,16 @@
"es6": true, "es6": true,
"node": true "node": true
}, },
"extends": "eslint:recommended", "extends": ["eslint:recommended", "plugin:mocha/recommended"],
"globals": { "globals": {
"Atomics": "readonly", "Atomics": "readonly",
"SharedArrayBuffer": "readonly" "SharedArrayBuffer": "readonly"
}, },
"parserOptions": { "parserOptions": {
"ecmaVersion": 2018 "ecmaVersion": 2020
}, },
"plugins": ["mocha"],
"ignorePatterns": ["docs"],
"rules": { "rules": {
"indent": [ "indent": [
"error", "error",

View File

@@ -1,38 +0,0 @@
---
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:
### Additional context
Add any other context about the problem here.

105
.github/ISSUE_TEMPLATE/bug_report.yml vendored Normal file
View File

@@ -0,0 +1,105 @@
name: '🐛 Bug report'
description: Create a report to help us improve
labels: bug
body:
- type: markdown
attributes:
value: |
Thank you for reporting an issue :pray:.
This issue tracker is for reporting bugs found in [`whatsapp-web.js`](https://github.com/pedroslopez/whatsapp-web.js).
If you have a question about how to achieve something and are struggling, please post a question in our [Discord server](https://discord.gg/wyKybbF) instead.
Before submitting a new bug/issue, please check the links below to see if there is a solution or question posted there already:
- `whatsapp-web.js` [Issues tab](https://github.com/pedroslopez/whatsapp-web.js/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc)
- `whatsapp-web.js` [closed Issues tab](https://github.com/pedroslopez/whatsapp-web.js/issues?q=is%3Aissue+sort%3Aupdated-desc+is%3Aclosed)
The more information you fill in, the better the community can help you.
- type: checkboxes
attributes:
label: Is there an existing issue for this?
description: Please search to see if an issue already exists for the bug you encountered.
options:
- label: I have searched the existing issues
required: true
- type: textarea
id: description
attributes:
label: Describe the bug
description: Provide a clear and concise description of the challenge you are running into.
validations:
required: true
- type: textarea
id: expected
attributes:
label: Expected behavior
description: Provide a clear and concise description of what you expected to happen.
placeholder: |
As a user, I expected ___ behavior but I am seeing ___
validations:
required: true
- type: textarea
id: steps
attributes:
label: Steps to Reproduce the Bug or Issue
description: Describe the steps we have to take to reproduce the behavior.
placeholder: |
1. Do X
2. Do Y
3. Do Z
4. See error
validations:
required: true
- type: textarea
id: relevant_code
attributes:
label: Relevant Code
description: If applicable, add code snippets to help explain your problem.
validations:
required: false
- type: dropdown
id: browser_type
attributes:
label: Browser Type
description: What web browser are you using?
options:
- Chromium
- Google Chrome
- Other (please write in Additional Context)
validations:
required: true
- type: dropdown
id: whatsapp_type
attributes:
label: WhatsApp Account Type
options:
- Standard
- WhatsApp Business
validations:
required: true
- type: dropdown
id: multidevice
attributes:
label: Does your WhatsApp account have multidevice enabled?
options:
- Yes, I am using Multi Device
- No, I am not using Multi Device
validations:
required: true
- type: textarea
attributes:
label: Environment
description: |
- OS: [e.g. Mac, Windows, Linux, Docker + Ubuntu 18, etc]
- Phone OS: [e.g. Android, iOS]
- whatsapp-web.js version [e.g. 1.2.3]
- WhatsApp Web version [run `await client.getWWebVersion()`]:
- Node.js Version [e.g. 1.2.3]
validations:
required: true
- type: textarea
id: additional
attributes:
label: Additional context
description: Add any other context about the problem here.

View File

@@ -1,20 +0,0 @@
---
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.

View File

@@ -0,0 +1,42 @@
name: 🚀 Feature request
description: Suggest an idea for this project
labels: enhancement
body:
- type: checkboxes
attributes:
label: Is there an existing issue for this?
description: Please search to see if an issue related to this feature request already exists.
options:
- label: I have searched the existing issues
required: true
- type: textarea
attributes:
label: Is your feature request related to a problem? Please describe.
description: A concise description of the problem you are facing or the motivetion behind this feature request.
placeholder: I faced a problem due to ...
validations:
required: false
- type: textarea
attributes:
label: Describe the solution you'd like.
description: A concise description of the solution for the issue.
validations:
required: true
- type: textarea
attributes:
label: Describe an alternate solution.
description: Is there any other approach to solve the problem?
validations:
required: false
- type: textarea
attributes:
label: Additional context
description: |
Links? Screenshots? References? Anything that will give us more context about what you would like to see!
validations:
required: false

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"

41
.github/pull_request_template.md vendored Normal file
View File

@@ -0,0 +1,41 @@
# PR Details
<!--- Provide a general summary of your changes in the Title above -->
## Description
<!--- Describe your changes in detail -->
## Related Issue
<!--- Optional --->
<!--- If there is an issue link it here: -->
## Motivation and Context
<!--- Optional --->
<!--- Why is this change required? What problem does it solve? -->
## How Has This Been Tested
<!--- Please describe in detail how you tested your changes. -->
<!--- Include details of your testing environment, and the tests you ran to -->
## Types of changes
<!--- What types of changes does your code introduce? Put an `x` in all the boxes that apply: -->
- [ ] Dependency change
- [ ] Bug fix (non-breaking change which fixes an issue)
- [ ] New feature (non-breaking change which adds functionality)
- [ ] Breaking change (fix or feature that would cause existing functionality to change)
## Checklist
<!--- Go over all the following points, and put an `x` in all the boxes that apply. -->
- [ ] My code follows the code style of this project.
- [ ] I have updated the documentation accordingly (index.d.ts).

View File

@@ -6,19 +6,15 @@ on:
jobs: jobs:
eslint: eslint:
name: eslint name: ESLint
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v1 - uses: actions/checkout@v2
- name: install node v12 - name: Install node v14
uses: actions/setup-node@v1 uses: actions/setup-node@v2
with: with:
node-version: 12 node-version: '14'
- name: npm install - name: Install dependencies
run: npm install run: npm install
- name: eslint - name: Run ESLint
uses: icrawl/action-eslint@v1 run: ./node_modules/.bin/eslint .
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
job-name: eslint

32
.github/workflows/release.yml vendored Normal file
View File

@@ -0,0 +1,32 @@
name: release
on:
workflow_dispatch:
inputs:
release_type:
description: "`alpha`, `alpha-minor`, `alpha-major` release?"
required: true
default: "alpha"
jobs:
release:
runs-on: ubuntu-latest
if: ${{ github.repository == 'pedroslopez/whatsapp-web.js' }}
steps:
- uses: actions/checkout@v2
with:
token: ${{ secrets.RELEASE_GITHUB_TOKEN }}
- run: git config --global user.email "hello@wwebjs.dev"
- run: git config --global user.name "WWebJS Bot"
- name: Bump version and publish to NPM
id: publish
run: ./tools/publish ${{ github.event.inputs.release_type }}
env:
NPM_TOKEN: ${{ secrets.RELEASE_NPM_TOKEN }}
- name: Create GitHub Release
id: create_release
uses: ncipollo/release-action@v1
with:
prerelease: ${{ steps.publish.outputs.PRERELEASE }}
generateReleaseNotes: true
tag: v${{ steps.publish.outputs.NEW_VERSION }}

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

6
.gitignore vendored
View File

@@ -64,8 +64,10 @@ typings/
# next.js build output # next.js build output
.next .next
# macOS Thumbnails # macOS
._* ._*
.DS_Store
# Test sessions # Test sessions
*session.json *session.json
.wwebjs_auth/

View File

@@ -12,3 +12,8 @@ yarn-debug.log*
yarn-error.log* yarn-error.log*
*session.json *session.json
.wwebjs_auth/
.env
tools/
tests/

133
CODE_OF_CONDUCT.md Normal file
View File

@@ -0,0 +1,133 @@
# Contributor Covenant Code of Conduct
## Our Pledge
We as members, contributors, and leaders pledge to make participation in our
community a harassment-free experience for everyone, regardless of age, body
size, visible or invisible disability, ethnicity, sex characteristics, gender
identity and expression, level of experience, education, socio-economic status,
nationality, personal appearance, race, religion, or sexual identity
and orientation.
We pledge to act and interact in ways that contribute to an open, welcoming,
diverse, inclusive, and healthy community.
## Our Standards
Examples of behavior that contributes to a positive environment for our
community include:
* Demonstrating empathy and kindness toward other people
* Being respectful of differing opinions, viewpoints, and experiences
* Giving and gracefully accepting constructive feedback
* Accepting responsibility and apologizing to those affected by our mistakes,
and learning from the experience
* Focusing on what is best not just for us as individuals, but for the
overall community
Examples of unacceptable behavior include:
* The use of sexualized language or imagery, and sexual attention or
advances of any kind
* Trolling, insulting or derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or email
address, without their explicit permission
* Other conduct which could reasonably be considered inappropriate in a
professional setting
## Enforcement Responsibilities
Community leaders are responsible for clarifying and enforcing our standards of
acceptable behavior and will take appropriate and fair corrective action in
response to any behavior that they deem inappropriate, threatening, offensive,
or harmful.
Community leaders have the right and responsibility to remove, edit, or reject
comments, commits, code, wiki edits, issues, and other contributions that are
not aligned to this Code of Conduct, and will communicate reasons for moderation
decisions when appropriate.
## Scope
This Code of Conduct applies within all community spaces, and also applies when
an individual is officially representing the community in public spaces.
Examples of representing our community include using an official e-mail address,
posting via an official social media account, or acting as an appointed
representative at an online or offline event.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported to the community leaders responsible for enforcement at
[pedroslopez@me.com](mailto:pedroslopez@me.com).
All complaints will be reviewed and investigated promptly and fairly.
All community leaders are obligated to respect the privacy and security of the
reporter of any incident.
## Enforcement Guidelines
Community leaders will follow these Community Impact Guidelines in determining
the consequences for any action they deem in violation of this Code of Conduct:
### 1. Correction
**Community Impact**: Use of inappropriate language or other behavior deemed
unprofessional or unwelcome in the community.
**Consequence**: A private, written warning from community leaders, providing
clarity around the nature of the violation and an explanation of why the
behavior was inappropriate. A public apology may be requested.
### 2. Warning
**Community Impact**: A violation through a single incident or series
of actions.
**Consequence**: A warning with consequences for continued behavior. No
interaction with the people involved, including unsolicited interaction with
those enforcing the Code of Conduct, for a specified period of time. This
includes avoiding interactions in community spaces as well as external channels
like social media. Violating these terms may lead to a temporary or
permanent ban.
### 3. Temporary Ban
**Community Impact**: A serious violation of community standards, including
sustained inappropriate behavior.
**Consequence**: A temporary ban from any sort of interaction or public
communication with the community for a specified period of time. No public or
private interaction with the people involved, including unsolicited interaction
with those enforcing the Code of Conduct, is allowed during this period.
Violating these terms may lead to a permanent ban.
### 4. Permanent Ban
**Community Impact**: Demonstrating a pattern of violation of community
standards, including sustained inappropriate behavior, harassment of an
individual, or aggression toward or disparagement of classes of individuals.
**Consequence**: A permanent ban from any sort of public interaction within
the community.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
version 2.0, available at
[https://www.contributor-covenant.org/version/2/0/code_of_conduct.html][v2.0].
Community Impact Guidelines were inspired by
[Mozilla's code of conduct enforcement ladder][Mozilla CoC].
For answers to common questions about this code of conduct, see the FAQ at
[https://www.contributor-covenant.org/faq][FAQ]. Translations are available
at [https://www.contributor-covenant.org/translations][translations].
[homepage]: https://www.contributor-covenant.org
[v2.0]: https://www.contributor-covenant.org/version/2/0/code_of_conduct.html
[Mozilla CoC]: https://github.com/mozilla/diversity
[FAQ]: https://www.contributor-covenant.org/faq
[translations]: https://www.contributor-covenant.org/translations

View File

@@ -1,4 +1,4 @@
[![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.2106.5](https://img.shields.io/badge/WhatsApp_Web-2.2106.5-brightgreen.svg) [![Discord Chat](https://img.shields.io/discord/698610475432411196.svg?logo=discord)](https://discord.gg/H7DqQs4) [![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.2245.9](https://img.shields.io/badge/WhatsApp_Web-2.2245.9-brightgreen.svg) [![Discord Chat](https://img.shields.io/discord/698610475432411196.svg?logo=discord)](https://discord.gg/H7DqQs4)
# whatsapp-web.js # whatsapp-web.js
A WhatsApp API client that connects through the WhatsApp Web browser app A WhatsApp API client that connects through the WhatsApp Web browser app
@@ -7,16 +7,24 @@ 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. **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.
## Quick Links
* [Guide / Getting Started](https://wwebjs.dev/guide) _(work in progress)_
* [Reference documentation](https://docs.wwebjs.dev/)
* [GitHub](https://github.com/pedroslopez/whatsapp-web.js)
* [npm](https://npmjs.org/package/whatsapp-web.js)
## Installation ## Installation
The module is now available on npm! `npm i whatsapp-web.js` The module is now available on npm! `npm i whatsapp-web.js`
Please note that Node v10.18.1+ is required due to Puppeteer. Please note that Node v12+ is required.
## Example usage ## Example usage
```js ```js
const { Client } = require('whatsapp-web.js'); const { Client } = require('whatsapp-web.js');
const client = new Client(); const client = new Client();
client.on('qr', (qr) => { client.on('qr', (qr) => {
@@ -39,18 +47,24 @@ 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. Take a look at [example.js](https://github.com/pedroslopez/whatsapp-web.js/blob/master/example.js) for another example with more use cases.
For more information on saving and restoring sessions, check out the available [Authentication Strategies](https://wwebjs.dev/guide/authentication.html).
## Supported features ## Supported features
| Feature | Status | | Feature | Status |
| ------------- | ------------- | | ------------- | ------------- |
| Multi Device | ✅ |
| Send messages | ✅ | | Send messages | ✅ |
| Receive messages | ✅ | | Receive messages | ✅ |
| Send media (images/audio/documents) | ✅ | | Send media (images/audio/documents) | ✅ |
| Send media (video) | ✅ [(requires google chrome)](https://waguide.pedroslopez.me/features/handling-attachments#caveat-for-sending-videos-and-gifs) | | Send media (video) | ✅ [(requires google chrome)](https://wwebjs.dev/guide/handling-attachments.html#caveat-for-sending-videos-and-gifs) |
| Send stickers | ✅ | | Send stickers | ✅ |
| Receive media (images/audio/video/documents) | ✅ | | Receive media (images/audio/video/documents) | ✅ |
| Send contact cards | ✅ | | Send contact cards | ✅ |
| Send location | ✅ | | Send location | ✅ |
| Send buttons | ✅ |
| Send lists | ✅ (business accounts not supported) |
| Receive location | ✅ | | Receive location | ✅ |
| Message replies | ✅ | | Message replies | ✅ |
| Join groups by invite | ✅ | | Join groups by invite | ✅ |
@@ -66,24 +80,21 @@ Take a look at [example.js](https://github.com/pedroslopez/whatsapp-web.js/blob/
| Get contact info | ✅ | | Get contact info | ✅ |
| Get profile pictures | ✅ | | Get profile pictures | ✅ |
| Set user status message | ✅ | | Set user status message | ✅ |
| React to messages | ✅ |
Something missing? Make an issue and let us know! Something missing? Make an issue and let us know!
## Links
* [Reference](https://pedroslopez.me/whatsapp-web.js)
* [Guide](https://waguide.pedroslopez.me/) _(work in progress)_
* [GitHub](https://github.com/pedroslopez/whatsapp-web.js)
## Contributing ## Contributing
Pull requests are welcome! If you see something you'd like to add, please do. For drastic changes, please open an issue first. Pull requests are welcome! If you see something you'd like to add, please do. For drastic changes, please open an issue first.
## Donating ## Supporting the project
You can support the maintainer of this project through the link below You can support the maintainer of this project through the links below
[![Support via PayPal](https://cdn.rawgit.com/twolfson/paypal-github-button/1.0.0/dist/button.svg)](https://www.paypal.me/psla/) - [Support via GitHub Sponsors](https://github.com/sponsors/pedroslopez)
- [Support via PayPal](https://www.paypal.me/psla/)
- [Sign up for DigitalOcean](https://m.do.co/c/73f906a36ed4) and get $100 in credit when you sign up (Referral)
## Disclaimer ## Disclaimer

View File

@@ -2,9 +2,9 @@
<html> <html>
<head> <head>
<meta name="generator" content="JSDoc 3.6.6"> <meta name="generator" content="JSDoc 3.6.7">
<meta charset="utf-8"> <meta charset="utf-8">
<title>whatsapp-web.js 1.12.6 &raquo; Class: Base</title> <title>whatsapp-web.js 1.18.4 &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/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/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 rel="stylesheet" href="https://brick.a.ssl.fastly.net/Inconsolata:500" type="text/css">
@@ -15,7 +15,7 @@
<nav id="jsdoc-navbar" role="navigation" class="jsdoc-navbar"> <nav id="jsdoc-navbar" role="navigation" class="jsdoc-navbar">
<div id="jsdoc-navbar-container"> <div id="jsdoc-navbar-container">
<div id="jsdoc-navbar-content"> <div id="jsdoc-navbar-content">
<a href="index.html" class="jsdoc-navbar-package-name">whatsapp-web.<wbr>js 1.<wbr>12.<wbr>6</a> <a href="index.html" class="jsdoc-navbar-package-name">whatsapp-web.<wbr>js 1.<wbr>18.<wbr>4</a>
</div> </div>
</div> </div>
</nav> </nav>
@@ -50,7 +50,7 @@
<footer id="jsdoc-footer" class="jsdoc-footer"> <footer id="jsdoc-footer" class="jsdoc-footer">
<div id="jsdoc-footer-container"> <div id="jsdoc-footer-container">
<p> <p>
Generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc</a> 3.6.6 on April 20, 2021. Generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc</a> 3.6.7 on November 26, 2022.
</p> </p>
</div> </div>
</footer> </footer>

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.18.4 &raquo; Class: BaseAuthStrategy</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>18.<wbr>4</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">BaseAuthStrategy</span></h1>
<p class="source-link">Source: <a href="authStrategies_BaseAuthStrategy.js.html#source-line-6">authStrategies/<wbr>BaseAuthStrategy.<wbr>js:6</a></p>
<div class="symbol-classdesc">
<p>Base class which all authentication strategies extend</p>
</div>
<dl class="dl-compact">
</dl>
</header>
<section id="summary">
</section>
<section>
<h2 id="BaseAuthStrategy">new&nbsp;<span class="symbol-name">BaseAuthStrategy</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 November 26, 2022.
</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

@@ -2,9 +2,9 @@
<html> <html>
<head> <head>
<meta name="generator" content="JSDoc 3.6.6"> <meta name="generator" content="JSDoc 3.6.7">
<meta charset="utf-8"> <meta charset="utf-8">
<title>whatsapp-web.js 1.12.6 &raquo; Class: BusinessContact</title> <title>whatsapp-web.js 1.18.4 &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/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/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 rel="stylesheet" href="https://brick.a.ssl.fastly.net/Inconsolata:500" type="text/css">
@@ -15,7 +15,7 @@
<nav id="jsdoc-navbar" role="navigation" class="jsdoc-navbar"> <nav id="jsdoc-navbar" role="navigation" class="jsdoc-navbar">
<div id="jsdoc-navbar-container"> <div id="jsdoc-navbar-container">
<div id="jsdoc-navbar-content"> <div id="jsdoc-navbar-content">
<a href="index.html" class="jsdoc-navbar-package-name">whatsapp-web.<wbr>js 1.<wbr>12.<wbr>6</a> <a href="index.html" class="jsdoc-navbar-package-name">whatsapp-web.<wbr>js 1.<wbr>18.<wbr>4</a>
</div> </div>
</div> </div>
</nav> </nav>
@@ -104,20 +104,29 @@
<dt><a href="BusinessContact.html#getAbout">getAbout()</a></dt> <dt><a href="BusinessContact.html#getAbout">getAbout()</a></dt>
<dd> <dd>
</dd> </dd>
</dl>
</div>
<div class="summary-column">
<dl class="dl-summary-callout">
<dt><a href="BusinessContact.html#getChat">getChat()</a></dt> <dt><a href="BusinessContact.html#getChat">getChat()</a></dt>
<dd> <dd>
</dd> </dd>
<dt><a href="BusinessContact.html#getProfilePicUrl">getProfilePicUrl()</a></dt> </dl>
</div>
<div class="summary-column">
<dl class="dl-summary-callout">
<dt><a href="BusinessContact.html#getCommonGroups">getCommonGroups()</a></dt>
<dd>
</dd>
<dt><a href="BusinessContact.html#getCountryCode">getCountryCode()</a></dt>
<dd>
</dd>
<dt><a href="BusinessContact.html#getFormattedNumber">getFormattedNumber()</a></dt>
<dd> <dd>
</dd> </dd>
</dl> </dl>
</div> </div>
<div class="summary-column"> <div class="summary-column">
<dl class="dl-summary-callout"> <dl class="dl-summary-callout">
<dt><a href="BusinessContact.html#getProfilePicUrl">getProfilePicUrl()</a></dt>
<dd>
</dd>
<dt><a href="BusinessContact.html#unblock">unblock()</a></dt> <dt><a href="BusinessContact.html#unblock">unblock()</a></dt>
<dd> <dd>
</dd> </dd>
@@ -263,6 +272,33 @@
<dd></dd> <dd></dd>
</dl> </dl>
<div class="symbol-detail-labels"><span class="label label-async">async</span></div> <div class="symbol-detail-labels"><span class="label label-async">async</span></div>
<h3 id="getCommonGroups"><span class="symbol-name">getCommonGroups</span><span class="signature"><span class="signature-params">()</span>&nbsp;&rarr; <span class="signature-returns"> Promise containing Array of WAWebJS.ChatId</span></span></h3>
<p>Gets the Contact's common groups with you. Returns empty array if you don't have any common group.</p>
<dl class="dl-compact">
<dt>Inherited from</dt>
<dd><a href="Contact.html#getCommonGroups">Contact#getCommonGroups</a></dd>
<dt>Returns</dt>
<dd></dd>
</dl>
<div class="symbol-detail-labels"><span class="label label-async">async</span></div>
<h3 id="getCountryCode"><span class="symbol-name">getCountryCode</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 countrycode, (1541859685@c.us) =&gt; (1)</p>
<dl class="dl-compact">
<dt>Inherited from</dt>
<dd><a href="Contact.html#getCountryCode">Contact#getCountryCode</a></dd>
<dt>Returns</dt>
<dd></dd>
</dl>
<div class="symbol-detail-labels"><span class="label label-async">async</span></div>
<h3 id="getFormattedNumber"><span class="symbol-name">getFormattedNumber</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 formatted phone number, (12345678901@c.us) =&gt; (+1 (234) 5678-901)</p>
<dl class="dl-compact">
<dt>Inherited from</dt>
<dd><a href="Contact.html#getFormattedNumber">Contact#getFormattedNumber</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> <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> <p>Returns the contact's profile picture URL, if privacy settings allow it</p>
<dl class="dl-compact"> <dl class="dl-compact">
@@ -290,7 +326,7 @@
<footer id="jsdoc-footer" class="jsdoc-footer"> <footer id="jsdoc-footer" class="jsdoc-footer">
<div id="jsdoc-footer-container"> <div id="jsdoc-footer-container">
<p> <p>
Generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc</a> 3.6.6 on April 20, 2021. Generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc</a> 3.6.7 on November 26, 2022.
</p> </p>
</div> </div>
</footer> </footer>

249
docs/Buttons.html Normal file
View File

@@ -0,0 +1,249 @@
<!doctype html>
<html>
<head>
<meta name="generator" content="JSDoc 3.6.7">
<meta charset="utf-8">
<title>whatsapp-web.js 1.18.4 &raquo; Class: Buttons</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>18.<wbr>4</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">Buttons</span></h1>
<p class="source-link">Source: <a href="structures_Buttons.js.html#source-line-23">structures/<wbr>Buttons.<wbr>js:23</a></p>
<div class="symbol-classdesc">
<p>Message type buttons</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="Buttons.html#body">body</a></dt>
<dd>
</dd>
<dt><a href="Buttons.html#buttons">buttons</a></dt>
<dd>
</dd>
</dl>
</div>
<div class="summary-column">
<dl class="dl-summary-callout">
<dt><a href="Buttons.html#footer">footer</a></dt>
<dd>
</dd>
<dt><a href="Buttons.html#title">title</a></dt>
<dd>
</dd>
</dl>
</div>
<div class="summary-column">
</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="Buttons.html#_format">_format(buttons)</a></dt>
<dd>
</dd>
</dl>
</div>
<div class="summary-column">
</div>
<div class="summary-column">
</div>
</div>
</div>
</section>
<section>
<h2 id="Buttons">new&nbsp;<span class="symbol-name">Buttons</span><span class="signature"><span class="signature-params">(body, buttons, title, footer)</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>body</p>
</td>
<td>
<p>&nbsp;</p>
</td>
<td>
<p>&nbsp;</p>
</td>
<td>
</td>
</tr>
<tr>
<td>
<p>buttons</p>
</td>
<td>
<p>&nbsp;</p>
</td>
<td>
<p>&nbsp;</p>
</td>
<td>
<p>See <a href="global.html#ButtonSpec"><code>ButtonSpec</code></a></p>
</td>
</tr>
<tr>
<td>
<p>title</p>
</td>
<td>
<p>&nbsp;</p>
</td>
<td>
<p>&nbsp;</p>
</td>
<td>
<p>Value can be null.</p>
</td>
</tr>
<tr>
<td>
<p>footer</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="body"><span class="symbol-name">body</span><small class="property-type">
&nbsp;(string or <a href="MessageMedia.html">MessageMedia</a>)</small></h3>
<p>Message body</p>
<dl class="dl-compact">
</dl>
<h3 id="buttons"><span class="symbol-name">buttons</span><small class="property-type">
&nbsp;Array of <a href="global.html#FormattedButtonSpec">FormattedButtonSpec</a></small></h3>
<p>buttons of message</p>
<dl class="dl-compact">
</dl>
<h3 id="footer"><span class="symbol-name">footer</span><small class="property-type">
&nbsp;string</small></h3>
<p>footer of message</p>
<dl class="dl-compact">
</dl>
<h3 id="title"><span class="symbol-name">title</span><small class="property-type">
&nbsp;string</small></h3>
<p>title of message</p>
<dl class="dl-compact">
</dl>
</section>
<h2>Method</h2>
<section>
<h3 id="_format"><span class="symbol-name">_format</span><span class="signature"><span class="signature-params">(buttons)</span>&nbsp;&rarr; <span class="signature-returns"> Array of <a href="global.html#FormattedButtonSpec">FormattedButtonSpec</a></span></span></h3>
<p>Creates button array from simple array</p>
<section>
<h4>
Example
</h4>
<div>
<pre class="prettyprint"><code>Input: [{id:&#x27;customId&#x27;,body:&#x27;button1&#x27;},{body:&#x27;button2&#x27;},{body:&#x27;button3&#x27;},{body:&#x27;button4&#x27;}]
Returns: [{ buttonId:&#x27;customId&#x27;,buttonText:{&#x27;displayText&#x27;:&#x27;button1&#x27;},type: 1 },{buttonId:&#x27;n3XKsL&#x27;,buttonText:{&#x27;displayText&#x27;:&#x27;button2&#x27;},type:1},{buttonId:&#x27;NDJk0a&#x27;,buttonText:{&#x27;displayText&#x27;:&#x27;button3&#x27;},type:1}]</code></pre>
</div>
</section>
<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>buttons</p>
</td>
<td>
<p>Array of <a href="global.html#ButtonSpec">ButtonSpec</a></p>
</td>
<td>
<p>&nbsp;</p>
</td>
<td>
</td>
</tr>
</tbody>
</table>
</section>
<dl class="dl-compact">
<dt>Returns</dt>
<dd>
<p><code>Array of <a href="global.html#FormattedButtonSpec">FormattedButtonSpec</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 November 26, 2022.
</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.18.4 &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>18.<wbr>4</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 November 26, 2022.
</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

@@ -2,9 +2,9 @@
<html> <html>
<head> <head>
<meta name="generator" content="JSDoc 3.6.6"> <meta name="generator" content="JSDoc 3.6.7">
<meta charset="utf-8"> <meta charset="utf-8">
<title>whatsapp-web.js 1.12.6 &raquo; Class: Chat</title> <title>whatsapp-web.js 1.18.4 &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/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/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 rel="stylesheet" href="https://brick.a.ssl.fastly.net/Inconsolata:500" type="text/css">
@@ -15,7 +15,7 @@
<nav id="jsdoc-navbar" role="navigation" class="jsdoc-navbar"> <nav id="jsdoc-navbar" role="navigation" class="jsdoc-navbar">
<div id="jsdoc-navbar-container"> <div id="jsdoc-navbar-container">
<div id="jsdoc-navbar-content"> <div id="jsdoc-navbar-content">
<a href="index.html" class="jsdoc-navbar-package-name">whatsapp-web.<wbr>js 1.<wbr>12.<wbr>6</a> <a href="index.html" class="jsdoc-navbar-package-name">whatsapp-web.<wbr>js 1.<wbr>18.<wbr>4</a>
</div> </div>
</div> </div>
</nav> </nav>
@@ -176,7 +176,7 @@
<dl class="dl-compact"> <dl class="dl-compact">
</dl> </dl>
<h3 id="isMuted"><span class="symbol-name">isMuted</span><small class="property-type"> <h3 id="isMuted"><span class="symbol-name">isMuted</span><small class="property-type">
&nbsp;number</small></h3> &nbsp;boolean</small></h3>
<p>Indicates if the chat is muted or not</p> <p>Indicates if the chat is muted or not</p>
<dl class="dl-compact"> <dl class="dl-compact">
</dl> </dl>
@@ -224,7 +224,8 @@
<dl class="dl-compact"> <dl class="dl-compact">
<dt>Returns</dt> <dt>Returns</dt>
<dd> <dd>
<p><code>Promise containing Boolean</code> <p>result</p> <p><code>Promise containing Boolean</code> 
<p>result</p>
</p> </p>
</dd> </dd>
</dl> </dl>
@@ -239,7 +240,8 @@
<dl class="dl-compact"> <dl class="dl-compact">
<dt>Returns</dt> <dt>Returns</dt>
<dd> <dd>
<p><code>Promise containing Boolean</code> <p>result</p> <p><code>Promise containing Boolean</code> 
<p>result</p>
</p> </p>
</dd> </dd>
</dl> </dl>
@@ -269,7 +271,7 @@
<p>&nbsp;</p> <p>&nbsp;</p>
</td> </td>
<td> <td>
<p>Options for searching messages. Right now only limit is supported.</p> <p>Options for searching messages. Right now only limit and fromMe is supported.</p>
<p>Values in <code>searchOptions</code> have the following properties:</p> <p>Values in <code>searchOptions</code> have the following properties:</p>
<table class="jsdoc-details-table"> <table class="jsdoc-details-table">
<thead> <thead>
@@ -292,8 +294,21 @@
<p>Yes</p> <p>Yes</p>
</td> </td>
<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>The amount of messages to return. If no limit is specified, the available messages will be returned. 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>
<tr>
<td>
<p>fromMe</p>
</td>
<td>
<p>Boolean</p>
</td>
<td>
<p>Yes</p>
</td>
<td>
<p>Return only messages from the bot number or vise versa. To get all messages, leave the option undefined.</p>
</td> </td>
</tr> </tr>
</tbody> </tbody>
@@ -334,7 +349,7 @@
</dl> </dl>
<div class="symbol-detail-labels"><span class="label label-async">async</span></div> <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> <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> <p>Mutes this chat forever, unless a date is specified</p>
<section> <section>
<h4>Parameter</h4> <h4>Parameter</h4>
<table class="jsdoc-details-table"> <table class="jsdoc-details-table">
@@ -358,7 +373,8 @@
<p>&nbsp;</p> <p>&nbsp;</p>
</td> </td>
<td> <td>
<p>Date at which the Chat will be unmuted</p> <p>Date at which the Chat will be unmuted, leave as is to mute forever</p>
<p>Value can be null.</p>
</td> </td>
</tr> </tr>
</tbody> </tbody>
@@ -372,7 +388,8 @@
<dl class="dl-compact"> <dl class="dl-compact">
<dt>Returns</dt> <dt>Returns</dt>
<dd> <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><code>Promise containing boolean</code> 
<p>New pin state. Could be false if the max number of pinned chats was reached.</p>
</p> </p>
</dd> </dd>
</dl> </dl>
@@ -423,7 +440,8 @@
<dl class="dl-compact"> <dl class="dl-compact">
<dt>Returns</dt> <dt>Returns</dt>
<dd> <dd>
<p><code>Promise containing <a href="Message.html">Message</a></code> <p>Message that was just sent</p> <p><code>Promise containing <a href="Message.html">Message</a></code> 
<p>Message that was just sent</p>
</p> </p>
</dd> </dd>
</dl> </dl>
@@ -433,7 +451,8 @@
<dl class="dl-compact"> <dl class="dl-compact">
<dt>Returns</dt> <dt>Returns</dt>
<dd> <dd>
<p><code>Promise containing Boolean</code> <p>result</p> <p><code>Promise containing Boolean</code> 
<p>result</p>
</p> </p>
</dd> </dd>
</dl> </dl>
@@ -463,7 +482,8 @@
<dl class="dl-compact"> <dl class="dl-compact">
<dt>Returns</dt> <dt>Returns</dt>
<dd> <dd>
<p><code>Promise containing boolean</code> <p>New pin state</p> <p><code>Promise containing boolean</code> 
<p>New pin state</p>
</p> </p>
</dd> </dd>
</dl> </dl>
@@ -477,7 +497,7 @@
<footer id="jsdoc-footer" class="jsdoc-footer"> <footer id="jsdoc-footer" class="jsdoc-footer">
<div id="jsdoc-footer-container"> <div id="jsdoc-footer-container">
<p> <p>
Generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc</a> 3.6.6 on April 20, 2021. Generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc</a> 3.6.7 on November 26, 2022.
</p> </p>
</div> </div>
</footer> </footer>

File diff suppressed because it is too large Load Diff

View File

@@ -2,9 +2,9 @@
<html> <html>
<head> <head>
<meta name="generator" content="JSDoc 3.6.6"> <meta name="generator" content="JSDoc 3.6.7">
<meta charset="utf-8"> <meta charset="utf-8">
<title>whatsapp-web.js 1.12.6 &raquo; Source: Client.js</title> <title>whatsapp-web.js 1.18.4 &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/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/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 rel="stylesheet" href="https://brick.a.ssl.fastly.net/Inconsolata:500" type="text/css">
@@ -15,7 +15,7 @@
<nav id="jsdoc-navbar" role="navigation" class="jsdoc-navbar"> <nav id="jsdoc-navbar" role="navigation" class="jsdoc-navbar">
<div id="jsdoc-navbar-container"> <div id="jsdoc-navbar-container">
<div id="jsdoc-navbar-content"> <div id="jsdoc-navbar-content">
<a href="index.html" class="jsdoc-navbar-package-name">whatsapp-web.<wbr>js 1.<wbr>12.<wbr>6</a> <a href="index.html" class="jsdoc-navbar-package-name">whatsapp-web.<wbr>js 1.<wbr>18.<wbr>4</a>
</div> </div>
</div> </div>
</nav> </nav>
@@ -34,7 +34,6 @@
const EventEmitter &#x3D; require(&#x27;events&#x27;); const EventEmitter &#x3D; require(&#x27;events&#x27;);
const puppeteer &#x3D; require(&#x27;puppeteer&#x27;); const puppeteer &#x3D; require(&#x27;puppeteer&#x27;);
const moduleRaid &#x3D; require(&#x27;@pedroslopez/moduleraid/moduleraid&#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 Util &#x3D; require(&#x27;./util/Util&#x27;);
const InterfaceController &#x3D; require(&#x27;./util/InterfaceController&#x27;); const InterfaceController &#x3D; require(&#x27;./util/InterfaceController&#x27;);
@@ -42,25 +41,25 @@ const { WhatsWebURL, DefaultOptions, Events, WAState } &#x3D; require(&#x27;./ut
const { ExposeStore, LoadUtils } &#x3D; require(&#x27;./util/Injected&#x27;); const { ExposeStore, LoadUtils } &#x3D; require(&#x27;./util/Injected&#x27;);
const ChatFactory &#x3D; require(&#x27;./factories/ChatFactory&#x27;); const ChatFactory &#x3D; require(&#x27;./factories/ChatFactory&#x27;);
const ContactFactory &#x3D; require(&#x27;./factories/ContactFactory&#x27;); const ContactFactory &#x3D; require(&#x27;./factories/ContactFactory&#x27;);
const { ClientInfo, Message, MessageMedia, Contact, Location, GroupNotification , Label } &#x3D; require(&#x27;./structures&#x27;); const { ClientInfo, Message, MessageMedia, Contact, Location, GroupNotification, Label, Call, Buttons, List, Reaction } &#x3D; require(&#x27;./structures&#x27;);
const LegacySessionAuth &#x3D; require(&#x27;./authStrategies/LegacySessionAuth&#x27;);
const NoAuth &#x3D; require(&#x27;./authStrategies/NoAuth&#x27;);
/** /**
* Starting point for interacting with the WhatsApp Web API * Starting point for interacting with the WhatsApp Web API
* @extends {EventEmitter} * @extends {EventEmitter}
* @param {object} options - Client options * @param {object} options - Client options
* @param {AuthStrategy} options.authStrategy - Determines how to save and restore sessions. Will use LegacySessionAuth if options.session is set. Otherwise, NoAuth will be used.
* @param {number} options.authTimeoutMs - Timeout for authentication selector in puppeteer * @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 {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.qrMaxRetries - How many times should the qrcode be refreshed before giving up
* @param {number} options.qrTimeoutMs - Timeout for qr code selector in puppeteer * @param {string} options.restartOnAuthFail - @deprecated This option should be set directly on the LegacySessionAuth.
* @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 - @deprecated Only here for backwards-compatibility. You should move to using LocalAuth, or set the authStrategy to LegacySessionAuth explicitly.
* @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.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 {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.userAgent - User agent to use in puppeteer
* @param {string} options.ffmpegPath - Ffmpeg path to use when formating videos to webp while sending stickers * @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#qr
* @fires Client#authenticated * @fires Client#authenticated
@@ -77,13 +76,33 @@ const { ClientInfo, Message, MessageMedia, Contact, Location, GroupNotification
* @fires Client#group_update * @fires Client#group_update
* @fires Client#disconnected * @fires Client#disconnected
* @fires Client#change_state * @fires Client#change_state
* @fires Client#change_battery
*/ */
class Client extends EventEmitter { class Client extends EventEmitter {
constructor(options &#x3D; {}) { constructor(options &#x3D; {}) {
super(); super();
this.options &#x3D; Util.mergeDefault(DefaultOptions, options); this.options &#x3D; Util.mergeDefault(DefaultOptions, options);
if(!this.options.authStrategy) {
if(Object.prototype.hasOwnProperty.call(this.options, &#x27;session&#x27;)) {
process.emitWarning(
&#x27;options.session is deprecated and will be removed in a future release due to incompatibility with multi-device. &#x27; +
&#x27;Use the LocalAuth authStrategy, don\&#x27;t pass in a session as an option, or suppress this warning by using the LegacySessionAuth strategy explicitly (see https://wwebjs.dev/guide/authentication.html#legacysessionauth-strategy).&#x27;,
&#x27;DeprecationWarning&#x27;
);
this.authStrategy &#x3D; new LegacySessionAuth({
session: this.options.session,
restartOnAuthFail: this.options.restartOnAuthFail
});
} else {
this.authStrategy &#x3D; new NoAuth();
}
} else {
this.authStrategy &#x3D; this.options.authStrategy;
}
this.authStrategy.setup(this);
this.pupBrowser &#x3D; null; this.pupBrowser &#x3D; null;
this.pupPage &#x3D; null; this.pupPage &#x3D; null;
@@ -95,115 +114,207 @@ class Client extends EventEmitter {
* Sets up events and requirements, kicks off authentication request * Sets up events and requirements, kicks off authentication request
*/ */
async initialize() { async initialize() {
const browser &#x3D; await puppeteer.launch(this.options.puppeteer); let [browser, page] &#x3D; [null, null];
const page &#x3D; (await browser.pages())[0];
page.setUserAgent(this.options.userAgent); await this.authStrategy.beforeBrowserInitialized();
const puppeteerOpts &#x3D; this.options.puppeteer;
if (puppeteerOpts &amp;amp;&amp;amp; puppeteerOpts.browserWSEndpoint) {
browser &#x3D; await puppeteer.connect(puppeteerOpts);
page &#x3D; await browser.newPage();
} else {
const browserArgs &#x3D; [...(puppeteerOpts.args || [])];
if(!browserArgs.find(arg &#x3D;&gt; arg.includes(&#x27;--user-agent&#x27;))) {
browserArgs.push(&#x60;--user-agent&#x3D;${this.options.userAgent}&#x60;);
}
browser &#x3D; await puppeteer.launch({...puppeteerOpts, args: browserArgs});
page &#x3D; (await browser.pages())[0];
}
await page.setUserAgent(this.options.userAgent);
if (this.options.bypassCSP) await page.setBypassCSP(true);
this.pupBrowser &#x3D; browser; this.pupBrowser &#x3D; browser;
this.pupPage &#x3D; page; this.pupPage &#x3D; page;
if (this.options.session) { await this.authStrategy.afterBrowserInitialized();
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);
}
await page.goto(WhatsWebURL, { await page.goto(WhatsWebURL, {
waitUntil: &#x27;load&#x27;, waitUntil: &#x27;load&#x27;,
timeout: 0, timeout: 0,
referer: &#x27;https://whatsapp.com/&#x27;
}); });
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;; await page.evaluate(&#x60;function getElementByXpath(path) {
return document.evaluate(path, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
}&#x60;);
if (this.options.session) { let lastPercent &#x3D; null,
// Check if session restore was successfull lastPercentMessage &#x3D; null;
try {
await page.waitForSelector(KEEP_PHONE_CONNECTED_IMG_SELECTOR, { timeout: this.options.authTimeoutMs }); await page.exposeFunction(&#x27;loadingScreen&#x27;, async (percent, message) &#x3D;&gt; {
} catch (err) { if (lastPercent !&#x3D;&#x3D; percent || lastPercentMessage !&#x3D;&#x3D; message) {
if (err.name &#x3D;&#x3D;&#x3D; &#x27;TimeoutError&#x27;) { this.emit(Events.LOADING_SCREEN, percent, message);
/** lastPercent &#x3D; percent;
* Emitted when there has been an error while trying to restore an existing session lastPercentMessage &#x3D; message;
* @event Client#auth_failure }
* @param {string} message });
*/
this.emit(Events.AUTHENTICATION_FAILURE, &#x27;Unable to log in. Are the session details valid?&#x27;); await page.evaluate(
browser.close(); async function (selectors) {
if (this.options.restartOnAuthFail) { var observer &#x3D; new MutationObserver(function () {
// session restore failed so try again but without session to force new authentication let progressBar &#x3D; window.getElementByXpath(
this.options.session &#x3D; null; selectors.PROGRESS
this.initialize(); );
let progressMessage &#x3D; window.getElementByXpath(
selectors.PROGRESS_MESSAGE
);
if (progressBar) {
window.loadingScreen(
progressBar.value,
progressMessage.innerText
);
} }
return; });
}
throw err; observer.observe(document, {
attributes: true,
childList: true,
characterData: true,
subtree: true,
});
},
{
PROGRESS: &#x27;//*[@id&#x3D;\&#x27;app\&#x27;]/div/div/div[2]/progress&#x27;,
PROGRESS_MESSAGE: &#x27;//*[@id&#x3D;\&#x27;app\&#x27;]/div/div/div[3]&#x27;,
}
);
const INTRO_IMG_SELECTOR &#x3D; &#x27;[data-testid&#x3D;&quot;intro-md-beta-logo-dark&quot;], [data-testid&#x3D;&quot;intro-md-beta-logo-light&quot;], [data-asset-intro-image-light&#x3D;&quot;true&quot;], [data-asset-intro-image-dark&#x3D;&quot;true&quot;]&#x27;;
const INTRO_QRCODE_SELECTOR &#x3D; &#x27;div[data-ref] canvas&#x27;;
// Checks which selector appears first
const needAuthentication &#x3D; await Promise.race([
new Promise(resolve &#x3D;&gt; {
page.waitForSelector(INTRO_IMG_SELECTOR, { timeout: this.options.authTimeoutMs })
.then(() &#x3D;&gt; resolve(false))
.catch((err) &#x3D;&gt; resolve(err));
}),
new Promise(resolve &#x3D;&gt; {
page.waitForSelector(INTRO_QRCODE_SELECTOR, { timeout: this.options.authTimeoutMs })
.then(() &#x3D;&gt; resolve(true))
.catch((err) &#x3D;&gt; resolve(err));
})
]);
// Checks if an error occurred on the first found selector. The second will be discarded and ignored by .race;
if (needAuthentication instanceof Error) throw needAuthentication;
// Scan-qrcode selector was found. Needs authentication
if (needAuthentication) {
const { failed, failureEventPayload, restart } &#x3D; await this.authStrategy.onAuthenticationNeeded();
if(failed) {
/**
* 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, failureEventPayload);
await this.destroy();
if (restart) {
// session restore failed so try again but without session to force new authentication
return this.initialize();
}
return;
} }
} else { const QR_CONTAINER &#x3D; &#x27;div[data-ref]&#x27;;
const getQrCode &#x3D; async () &#x3D;&gt; { const QR_RETRY_BUTTON &#x3D; &#x27;div[data-ref] &gt; span &gt; button&#x27;;
// Check if retry button is present let qrRetries &#x3D; 0;
var QR_RETRY_SELECTOR &#x3D; &#x27;div[data-ref] &gt; span &gt; button&#x27;; await page.exposeFunction(&#x27;qrChanged&#x27;, async (qr) &#x3D;&gt; {
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 * Emitted when a QR code is received
* @event Client#qr * @event Client#qr
* @param {string} qr QR Code * @param {string} qr QR Code
*/ */
this.emit(Events.QR_RECEIVED, qr); this.emit(Events.QR_RECEIVED, qr);
}; if (this.options.qrMaxRetries &gt; 0) {
getQrCode(); qrRetries++;
this._qrRefreshInterval &#x3D; setInterval(getQrCode, this.options.qrRefreshIntervalMs); if (qrRetries &gt; this.options.qrMaxRetries) {
this.emit(Events.DISCONNECTED, &#x27;Max qrcode retries reached&#x27;);
await this.destroy();
}
}
});
await page.evaluate(function (selectors) {
const qr_container &#x3D; document.querySelector(selectors.QR_CONTAINER);
window.qrChanged(qr_container.dataset.ref);
const obs &#x3D; new MutationObserver((muts) &#x3D;&gt; {
muts.forEach(mut &#x3D;&gt; {
// Listens to qr token change
if (mut.type &#x3D;&#x3D;&#x3D; &#x27;attributes&#x27; &amp;amp;&amp;amp; mut.attributeName &#x3D;&#x3D;&#x3D; &#x27;data-ref&#x27;) {
window.qrChanged(mut.target.dataset.ref);
} else
// Listens to retry button, when found, click it
if (mut.type &#x3D;&#x3D;&#x3D; &#x27;childList&#x27;) {
const retry_button &#x3D; document.querySelector(selectors.QR_RETRY_BUTTON);
if (retry_button) retry_button.click();
}
});
});
obs.observe(qr_container.parentElement, {
subtree: true,
childList: true,
attributes: true,
attributeFilter: [&#x27;data-ref&#x27;],
});
}, {
QR_CONTAINER,
QR_RETRY_BUTTON
});
// Wait for code scan // Wait for code scan
await page.waitForSelector(KEEP_PHONE_CONNECTED_IMG_SELECTOR, { timeout: 0 }); try {
clearInterval(this._qrRefreshInterval); await page.waitForSelector(INTRO_IMG_SELECTOR, { timeout: 0 });
this._qrRefreshInterval &#x3D; undefined; } catch(error) {
if (
error.name &#x3D;&#x3D;&#x3D; &#x27;ProtocolError&#x27; &amp;amp;&amp;amp;
error.message &amp;amp;&amp;amp;
error.message.match(/Target closed/)
) {
// something has called .destroy() while waiting
return;
}
throw error;
}
} }
await page.evaluate(ExposeStore, moduleRaid.toString()); await page.evaluate(ExposeStore, moduleRaid.toString());
const authEventPayload &#x3D; await this.authStrategy.getAuthEventPayload();
// 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 * Emitted when authentication is successful
* @event Client#authenticated * @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); this.emit(Events.AUTHENTICATED, authEventPayload);
// Check window.Store Injection // Check window.Store Injection
await page.waitForFunction(&#x27;window.Store !&#x3D; undefined&#x27;); await page.waitForFunction(&#x27;window.Store !&#x3D; undefined&#x27;);
await page.evaluate(async () &#x3D;&gt; {
// safely unregister service workers
const registrations &#x3D; await navigator.serviceWorker.getRegistrations();
for (let registration of registrations) {
registration.unregister();
}
});
//Load util functions (serializers, helper functions) //Load util functions (serializers, helper functions)
await page.evaluate(LoadUtils); await page.evaluate(LoadUtils);
@@ -213,7 +324,7 @@ class Client extends EventEmitter {
* @type {ClientInfo} * @type {ClientInfo}
*/ */
this.info &#x3D; new ClientInfo(this, await page.evaluate(() &#x3D;&gt; { this.info &#x3D; new ClientInfo(this, await page.evaluate(() &#x3D;&gt; {
return window.Store.Conn.serialize(); return { ...window.Store.Conn.serialize(), wid: window.Store.User.getMeUser() };
})); }));
// Add InterfaceController // Add InterfaceController
@@ -221,8 +332,6 @@ class Client extends EventEmitter {
// Register events // Register events
await page.exposeFunction(&#x27;onAddMessageEvent&#x27;, msg &#x3D;&gt; { await page.exposeFunction(&#x27;onAddMessageEvent&#x27;, msg &#x3D;&gt; {
if (!msg.isNewMsg) return;
if (msg.type &#x3D;&#x3D;&#x3D; &#x27;gp2&#x27;) { if (msg.type &#x3D;&#x3D;&#x3D; &#x27;gp2&#x27;) {
const notification &#x3D; new GroupNotification(this, msg); const notification &#x3D; new GroupNotification(this, msg);
if (msg.subtype &#x3D;&#x3D;&#x3D; &#x27;add&#x27; || msg.subtype &#x3D;&#x3D;&#x3D; &#x27;invite&#x27;) { if (msg.subtype &#x3D;&#x3D;&#x3D; &#x27;add&#x27; || msg.subtype &#x3D;&#x3D;&#x3D; &#x27;invite&#x27;) {
@@ -341,7 +450,7 @@ class Client extends EventEmitter {
this.emit(Events.MEDIA_UPLOADED, message); this.emit(Events.MEDIA_UPLOADED, message);
}); });
await page.exposeFunction(&#x27;onAppStateChangedEvent&#x27;, (state) &#x3D;&gt; { await page.exposeFunction(&#x27;onAppStateChangedEvent&#x27;, async (state) &#x3D;&gt; {
/** /**
* Emitted when the connection state changes * Emitted when the connection state changes
@@ -368,6 +477,7 @@ class Client extends EventEmitter {
* @event Client#disconnected * @event Client#disconnected
* @param {WAState|&quot;NAVIGATION&quot;} reason reason that caused the disconnect * @param {WAState|&quot;NAVIGATION&quot;} reason reason that caused the disconnect
*/ */
await this.authStrategy.disconnect();
this.emit(Events.DISCONNECTED, state); this.emit(Events.DISCONNECTED, state);
this.destroy(); this.destroy();
} }
@@ -379,24 +489,90 @@ class Client extends EventEmitter {
if (battery &#x3D;&#x3D;&#x3D; undefined) return; if (battery &#x3D;&#x3D;&#x3D; undefined) return;
/** /**
* Emitted when the battery percentage for the attached device changes * Emitted when the battery percentage for the attached device changes. Will not be sent if using multi-device.
* @event Client#change_battery * @event Client#change_battery
* @param {object} batteryInfo * @param {object} batteryInfo
* @param {number} batteryInfo.battery - The current battery percentage * @param {number} batteryInfo.battery - The current battery percentage
* @param {boolean} batteryInfo.plugged - Indicates if the phone is plugged in (true) or not (false) * @param {boolean} batteryInfo.plugged - Indicates if the phone is plugged in (true) or not (false)
* @deprecated
*/ */
this.emit(Events.BATTERY_CHANGED, { battery, plugged }); 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.exposeFunction(&#x27;onReaction&#x27;, (reactions) &#x3D;&gt; {
for (const reaction of reactions) {
/**
* Emitted when a reaction is sent, received, updated or removed
* @event Client#message_reaction
* @param {object} reaction
* @param {object} reaction.id - Reaction id
* @param {number} reaction.orphan - Orphan
* @param {?string} reaction.orphanReason - Orphan reason
* @param {number} reaction.timestamp - Timestamp
* @param {string} reaction.reaction - Reaction
* @param {boolean} reaction.read - Read
* @param {object} reaction.msgId - Parent message id
* @param {string} reaction.senderId - Sender id
* @param {?number} reaction.ack - Ack
*/
this.emit(Events.MESSAGE_REACTION, new Reaction(this, reaction));
}
});
await page.evaluate(() &#x3D;&gt; { 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&#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: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: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;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.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.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.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); });
window.Store.Msg.on(&#x27;add&#x27;, (msg) &#x3D;&gt; {
if (msg.isNewMsg) {
if(msg.type &#x3D;&#x3D;&#x3D; &#x27;ciphertext&#x27;) {
// defer message event until ciphertext is resolved (type changed)
msg.once(&#x27;change:type&#x27;, (_msg) &#x3D;&gt; window.onAddMessageEvent(window.WWebJS.getMessageModel(_msg)));
} else {
window.onAddMessageEvent(window.WWebJS.getMessageModel(msg));
}
}
});
{
const module &#x3D; window.Store.createOrUpdateReactionsModule;
const ogMethod &#x3D; module.createOrUpdateReactions;
module.createOrUpdateReactions &#x3D; ((...args) &#x3D;&gt; {
window.onReaction(args[0].map(reaction &#x3D;&gt; {
const msgKey &#x3D; window.Store.MsgKey.fromString(reaction.msgKey);
const parentMsgKey &#x3D; window.Store.MsgKey.fromString(reaction.parentMsgKey);
const timestamp &#x3D; reaction.timestamp / 1000;
return {...reaction, msgKey, parentMsgKey, timestamp };
}));
return ogMethod(...args);
}).bind(module);
}
}); });
/** /**
@@ -404,12 +580,16 @@ class Client extends EventEmitter {
* @event Client#ready * @event Client#ready
*/ */
this.emit(Events.READY); this.emit(Events.READY);
this.authStrategy.afterAuthReady();
// Disconnect when navigating away // Disconnect when navigating away when in PAIRING state (detect logout)
// 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.pupPage.on(&#x27;framenavigated&#x27;, async () &#x3D;&gt; {
this.emit(Events.DISCONNECTED, &#x27;NAVIGATION&#x27;); const appState &#x3D; await this.getState();
await this.destroy(); if(!appState || appState &#x3D;&#x3D;&#x3D; WAState.PAIRING) {
await this.authStrategy.disconnect();
this.emit(Events.DISCONNECTED, &#x27;NAVIGATION&#x27;);
await this.destroy();
}
}); });
} }
@@ -417,19 +597,19 @@ class Client extends EventEmitter {
* Closes the client * Closes the client
*/ */
async destroy() { async destroy() {
if (this._qrRefreshInterval) {
clearInterval(this._qrRefreshInterval);
}
await this.pupBrowser.close(); await this.pupBrowser.close();
await this.authStrategy.destroy();
} }
/** /**
* Logs out the client, closing the current session * Logs out the client, closing the current session
*/ */
async logout() { async logout() {
return await this.pupPage.evaluate(() &#x3D;&gt; { await this.pupPage.evaluate(() &#x3D;&gt; {
return window.Store.AppState.logout(); return window.Store.AppState.logout();
}); });
await this.authStrategy.logout();
} }
/** /**
@@ -459,8 +639,9 @@ class Client extends EventEmitter {
/** /**
* Message options. * Message options.
* @typedef {Object} MessageSendOptions * @typedef {Object} MessageSendOptions
* @property {boolean} [linkPreview&#x3D;true] - Show links preview * @property {boolean} [linkPreview&#x3D;true] - Show links preview. Has no effect on multi-device accounts.
* @property {boolean} [sendAudioAsVoice&#x3D;false] - Send audio as voice message * @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} [sendMediaAsSticker&#x3D;false] - Send media as a sticker
* @property {boolean} [sendMediaAsDocument&#x3D;false] - Send media as a document * @property {boolean} [sendMediaAsDocument&#x3D;false] - Send media as a document
* @property {boolean} [parseVCards&#x3D;true] - Automatically parse vCards and send them as contacts * @property {boolean} [parseVCards&#x3D;true] - Automatically parse vCards and send them as contacts
@@ -468,13 +649,16 @@ class Client extends EventEmitter {
* @property {string} [quotedMessageId] - Id of the message that is being quoted (or replied to) * @property {string} [quotedMessageId] - Id of the message that is being quoted (or replied to)
* @property {Contact[]} [mentions] - Contacts that are being mentioned in the message * @property {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 {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 * @property {MessageMedia} [media] - Media to be sent
*/ */
/** /**
* Send a message to a specific chatId * Send a message to a specific chatId
* @param {string} chatId * @param {string} chatId
* @param {string|MessageMedia|Location|Contact|Array&amp;lt;Contact&gt;} content * @param {string|MessageMedia|Location|Contact|Array&amp;lt;Contact&gt;|Buttons|List} content
* @param {MessageSendOptions} [options] - Options used when sending the message * @param {MessageSendOptions} [options] - Options used when sending the message
* *
* @returns {Promise&amp;lt;Message&gt;} Message that was just sent * @returns {Promise&amp;lt;Message&gt;} Message that was just sent
@@ -483,12 +667,14 @@ class Client extends EventEmitter {
let internalOptions &#x3D; { let internalOptions &#x3D; {
linkPreview: options.linkPreview &#x3D;&#x3D;&#x3D; false ? undefined : true, linkPreview: options.linkPreview &#x3D;&#x3D;&#x3D; false ? undefined : true,
sendAudioAsVoice: options.sendAudioAsVoice, sendAudioAsVoice: options.sendAudioAsVoice,
sendVideoAsGif: options.sendVideoAsGif,
sendMediaAsSticker: options.sendMediaAsSticker, sendMediaAsSticker: options.sendMediaAsSticker,
sendMediaAsDocument: options.sendMediaAsDocument, sendMediaAsDocument: options.sendMediaAsDocument,
caption: options.caption, caption: options.caption,
quotedMessageId: options.quotedMessageId, quotedMessageId: options.quotedMessageId,
parseVCards: options.parseVCards &#x3D;&#x3D;&#x3D; false ? false : true, parseVCards: options.parseVCards &#x3D;&#x3D;&#x3D; false ? false : true,
mentionedJidList: Array.isArray(options.mentions) ? options.mentions.map(contact &#x3D;&gt; contact.id._serialized) : [] mentionedJidList: Array.isArray(options.mentions) ? options.mentions.map(contact &#x3D;&gt; contact.id._serialized) : [],
extraOptions: options.extra
}; };
const sendSeen &#x3D; typeof options.sendSeen &#x3D;&#x3D;&#x3D; &#x27;undefined&#x27; ? true : options.sendSeen; const sendSeen &#x3D; typeof options.sendSeen &#x3D;&#x3D;&#x3D; &#x27;undefined&#x27; ? true : options.sendSeen;
@@ -503,22 +689,36 @@ class Client extends EventEmitter {
} else if (content instanceof Location) { } else if (content instanceof Location) {
internalOptions.location &#x3D; content; internalOptions.location &#x3D; content;
content &#x3D; &#x27;&#x27;; content &#x3D; &#x27;&#x27;;
} else if(content instanceof Contact) { } else if (content instanceof Contact) {
internalOptions.contactCard &#x3D; content.id._serialized; internalOptions.contactCard &#x3D; content.id._serialized;
content &#x3D; &#x27;&#x27;; 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) { } 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); internalOptions.contactCardList &#x3D; content.map(contact &#x3D;&gt; contact.id._serialized);
content &#x3D; &#x27;&#x27;; content &#x3D; &#x27;&#x27;;
} else if (content instanceof Buttons) {
if (content.type !&#x3D;&#x3D; &#x27;chat&#x27;) { internalOptions.attachment &#x3D; content.body; }
internalOptions.buttons &#x3D; content;
content &#x3D; &#x27;&#x27;;
} else if (content instanceof List) {
internalOptions.list &#x3D; content;
content &#x3D; &#x27;&#x27;;
} }
if (internalOptions.sendMediaAsSticker &amp;amp;&amp;amp; internalOptions.attachment) { if (internalOptions.sendMediaAsSticker &amp;amp;&amp;amp; internalOptions.attachment) {
internalOptions.attachment &#x3D; await Util.formatToWebpSticker(internalOptions.attachment); internalOptions.attachment &#x3D; await Util.formatToWebpSticker(
internalOptions.attachment, {
name: options.stickerName,
author: options.stickerAuthor,
categories: options.stickerCategories
}, this.pupPage
);
} }
const newMessage &#x3D; await this.pupPage.evaluate(async (chatId, message, options, sendSeen) &#x3D;&gt; { const newMessage &#x3D; await this.pupPage.evaluate(async (chatId, message, options, sendSeen) &#x3D;&gt; {
const chatWid &#x3D; window.Store.WidFactory.createWid(chatId); const chatWid &#x3D; window.Store.WidFactory.createWid(chatId);
const chat &#x3D; await window.Store.Chat.find(chatWid); const chat &#x3D; await window.Store.Chat.find(chatWid);
if (sendSeen) { if (sendSeen) {
window.WWebJS.sendSeen(chatId); window.WWebJS.sendSeen(chatId);
} }
@@ -530,6 +730,24 @@ class Client extends EventEmitter {
return new Message(this, newMessage); 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 * Get all current chat instances
* @returns {Promise&amp;lt;Array&amp;lt;Chat&gt;&gt;} * @returns {Promise&amp;lt;Array&amp;lt;Chat&gt;&gt;}
@@ -587,7 +805,7 @@ class Client extends EventEmitter {
*/ */
async getInviteInfo(inviteCode) { async getInviteInfo(inviteCode) {
return await this.pupPage.evaluate(inviteCode &#x3D;&gt; { return await this.pupPage.evaluate(inviteCode &#x3D;&gt; {
return window.Store.Wap.groupInviteInfo(inviteCode); return window.Store.InviteInfo.sendQueryGroupInvite(inviteCode);
}, inviteCode); }, inviteCode);
} }
@@ -604,13 +822,27 @@ class Client extends EventEmitter {
return chatId._serialized; return chatId._serialized;
} }
/**
* Accepts a private invitation to join a group
* @param {object} inviteInfo 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 this.pupPage.evaluate(async inviteInfo &#x3D;&gt; {
let { groupId, fromId, inviteCode, inviteCodeExp } &#x3D; inviteInfo;
return await window.Store.JoinInviteV4.sendJoinGroupViaInviteV4(inviteCode, String(inviteCodeExp), groupId, fromId);
}, inviteInfo);
}
/** /**
* Sets the current user&#x27;s status message * Sets the current user&#x27;s status message
* @param {string} status New status message * @param {string} status New status message
*/ */
async setStatus(status) { async setStatus(status) {
await this.pupPage.evaluate(async status &#x3D;&gt; { await this.pupPage.evaluate(async status &#x3D;&gt; {
return await window.Store.Wap.sendSetStatus(status); return await window.Store.StatusUtils.setMyStatus(status);
}, status); }, status);
} }
@@ -618,19 +850,31 @@ class Client extends EventEmitter {
* Sets the current user&#x27;s display name. * 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. * 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 * @param {string} displayName New display name
* @returns {Promise&amp;lt;Boolean&gt;}
*/ */
async setDisplayName(displayName) { async setDisplayName(displayName) {
await this.pupPage.evaluate(async displayName &#x3D;&gt; { const couldSet &#x3D; await this.pupPage.evaluate(async displayName &#x3D;&gt; {
return await window.Store.Wap.setPushname(displayName); if(!window.Store.Conn.canSetMyPushname()) return false;
}, displayName);
}
if(window.Store.MDBackend) {
// TODO
return false;
} else {
const res &#x3D; await window.Store.Wap.setPushname(displayName);
return !res.status || res.status &#x3D;&#x3D;&#x3D; 200;
}
}, displayName);
return couldSet;
}
/** /**
* Gets the current connection state for the client * Gets the current connection state for the client
* @returns {WAState} * @returns {WAState}
*/ */
async getState() { async getState() {
return await this.pupPage.evaluate(() &#x3D;&gt; { return await this.pupPage.evaluate(() &#x3D;&gt; {
if(!window.Store) return null;
return window.Store.AppState.state; return window.Store.AppState.state;
}); });
} }
@@ -640,7 +884,16 @@ class Client extends EventEmitter {
*/ */
async sendPresenceAvailable() { async sendPresenceAvailable() {
return await this.pupPage.evaluate(() &#x3D;&gt; { return await this.pupPage.evaluate(() &#x3D;&gt; {
return window.Store.Wap.sendPresenceAvailable(); return window.Store.PresenceUtils.sendPresenceAvailable();
});
}
/**
* Marks the client as unavailable
*/
async sendPresenceUnavailable() {
return await this.pupPage.evaluate(() &#x3D;&gt; {
return window.Store.PresenceUtils.sendPresenceUnavailable();
}); });
} }
@@ -652,7 +905,7 @@ class Client extends EventEmitter {
return await this.pupPage.evaluate(async chatId &#x3D;&gt; { return await this.pupPage.evaluate(async chatId &#x3D;&gt; {
let chat &#x3D; await window.Store.Chat.get(chatId); let chat &#x3D; await window.Store.Chat.get(chatId);
await window.Store.Cmd.archiveChat(chat, true); await window.Store.Cmd.archiveChat(chat, true);
return chat.archive; return true;
}, chatId); }, chatId);
} }
@@ -664,7 +917,7 @@ class Client extends EventEmitter {
return await this.pupPage.evaluate(async chatId &#x3D;&gt; { return await this.pupPage.evaluate(async chatId &#x3D;&gt; {
let chat &#x3D; await window.Store.Chat.get(chatId); let chat &#x3D; await window.Store.Chat.get(chatId);
await window.Store.Cmd.archiveChat(chat, false); await window.Store.Cmd.archiveChat(chat, false);
return chat.archive; return false;
}, chatId); }, chatId);
} }
@@ -679,8 +932,9 @@ class Client extends EventEmitter {
return true; return true;
} }
const MAX_PIN_COUNT &#x3D; 3; const MAX_PIN_COUNT &#x3D; 3;
if (window.Store.Chat.models.length &gt; MAX_PIN_COUNT) { const chatModels &#x3D; window.Store.Chat.getModelsArray();
let maxPinned &#x3D; window.Store.Chat.models[MAX_PIN_COUNT - 1].pin; if (chatModels.length &gt; MAX_PIN_COUNT) {
let maxPinned &#x3D; chatModels[MAX_PIN_COUNT - 1].pin;
if (maxPinned) { if (maxPinned) {
return false; return false;
} }
@@ -706,15 +960,16 @@ class Client extends EventEmitter {
} }
/** /**
* Mutes the Chat until a specified date * Mutes this chat forever, unless a date is specified
* @param {string} chatId ID of the chat that will be muted * @param {string} chatId ID of the chat that will be muted
* @param {Date} unmuteDate Date when the chat will be unmuted * @param {?Date} unmuteDate Date when the chat will be unmuted, leave as is to mute forever
*/ */
async muteChat(chatId, unmuteDate) { async muteChat(chatId, unmuteDate) {
unmuteDate &#x3D; unmuteDate ? unmuteDate.getTime() / 1000 : -1;
await this.pupPage.evaluate(async (chatId, timestamp) &#x3D;&gt; { await this.pupPage.evaluate(async (chatId, timestamp) &#x3D;&gt; {
let chat &#x3D; await window.Store.Chat.get(chatId); let chat &#x3D; await window.Store.Chat.get(chatId);
await chat.mute.mute(timestamp, !0); await chat.mute.mute(timestamp, !0);
}, chatId, unmuteDate.getTime() / 1000); }, chatId, unmuteDate || -1);
} }
/** /**
@@ -745,13 +1000,49 @@ class Client extends EventEmitter {
* @returns {Promise&amp;lt;string&gt;} * @returns {Promise&amp;lt;string&gt;}
*/ */
async getProfilePicUrl(contactId) { async getProfilePicUrl(contactId) {
const profilePic &#x3D; await this.pupPage.evaluate((contactId) &#x3D;&gt; { const profilePic &#x3D; await this.pupPage.evaluate(async contactId &#x3D;&gt; {
return window.Store.Wap.profilePicFind(contactId); try {
const chatWid &#x3D; window.Store.WidFactory.createWid(contactId);
return await window.Store.ProfilePic.profilePicFind(chatWid);
} catch (err) {
if(err.name &#x3D;&#x3D;&#x3D; &#x27;ServerStatusCodeError&#x27;) return undefined;
throw err;
}
}, contactId); }, contactId);
return profilePic ? profilePic.eurl : undefined; return profilePic ? profilePic.eurl : undefined;
} }
/**
* Gets the Contact&#x27;s common groups with you. Returns empty array if you don&#x27;t have any common group.
* @param {string} contactId the whatsapp user&#x27;s ID (_serialized format)
* @returns {Promise&amp;lt;WAWebJS.ChatId[]&gt;}
*/
async getCommonGroups(contactId) {
const commonGroups &#x3D; await this.pupPage.evaluate(async (contactId) &#x3D;&gt; {
let contact &#x3D; window.Store.Contact.get(contactId);
if (!contact) {
const wid &#x3D; window.Store.WidFactory.createUserWid(contactId);
const chatConstructor &#x3D; window.Store.Contact.getModelsArray().find(c&#x3D;&gt;!c.isGroup).constructor;
contact &#x3D; new chatConstructor({id: wid});
}
if (contact.commonGroups) {
return contact.commonGroups.serialize();
}
const status &#x3D; await window.Store.findCommonGroups(contact);
if (status) {
return contact.commonGroups.serialize();
}
return [];
}, contactId);
const chats &#x3D; [];
for (const group of commonGroups) {
chats.push(group.id);
}
return chats;
}
/** /**
* Force reset of connection state for the client * Force reset of connection state for the client
*/ */
@@ -767,10 +1058,7 @@ class Client extends EventEmitter {
* @returns {Promise&amp;lt;Boolean&gt;} * @returns {Promise&amp;lt;Boolean&gt;}
*/ */
async isRegisteredUser(id) { async isRegisteredUser(id) {
return await this.pupPage.evaluate(async (id) &#x3D;&gt; { return Boolean(await this.getNumberId(id));
let result &#x3D; await window.Store.Wap.queryExist(id);
return result.jid !&#x3D;&#x3D; undefined;
}, id);
} }
/** /**
@@ -780,17 +1068,43 @@ class Client extends EventEmitter {
* @returns {Promise&amp;lt;Object|null&gt;} * @returns {Promise&amp;lt;Object|null&gt;}
*/ */
async getNumberId(number) { async getNumberId(number) {
if(!number.endsWith(&#x27;@c.us&#x27;)) { if (!number.endsWith(&#x27;@c.us&#x27;)) {
number +&#x3D; &#x27;@c.us&#x27;; number +&#x3D; &#x27;@c.us&#x27;;
} }
try { return await this.pupPage.evaluate(async number &#x3D;&gt; {
return await this.pupPage.evaluate(async numberId &#x3D;&gt; { const wid &#x3D; window.Store.WidFactory.createWid(number);
return window.WWebJS.getNumberId(numberId); const result &#x3D; await window.Store.QueryExist(wid);
}, number); if (!result || result.wid &#x3D;&#x3D;&#x3D; undefined) return null;
} catch(_) { return result.wid;
return null; }, number);
} }
/**
* Get the formatted number of a WhatsApp ID.
* @param {string} number Number or ID
* @returns {Promise&amp;lt;string&gt;}
*/
async getFormattedNumber(number) {
if (!number.endsWith(&#x27;@s.whatsapp.net&#x27;)) number &#x3D; number.replace(&#x27;c.us&#x27;, &#x27;s.whatsapp.net&#x27;);
if (!number.includes(&#x27;@s.whatsapp.net&#x27;)) number &#x3D; &#x60;${number}@s.whatsapp.net&#x60;;
return await this.pupPage.evaluate(async numberId &#x3D;&gt; {
return window.Store.NumberInfo.formattedPhoneNumber(numberId);
}, number);
}
/**
* Get the country code of a WhatsApp ID.
* @param {string} number Number or ID
* @returns {Promise&amp;lt;string&gt;}
*/
async getCountryCode(number) {
number &#x3D; number.replace(&#x27; &#x27;, &#x27;&#x27;).replace(&#x27;+&#x27;, &#x27;&#x27;).replace(&#x27;@c.us&#x27;, &#x27;&#x27;);
return await this.pupPage.evaluate(async numberId &#x3D;&gt; {
return window.Store.NumberInfo.findCC(numberId);
}, number);
} }
/** /**
@@ -811,12 +1125,9 @@ class Client extends EventEmitter {
} }
const createRes &#x3D; await this.pupPage.evaluate(async (name, participantIds) &#x3D;&gt; { const createRes &#x3D; await this.pupPage.evaluate(async (name, participantIds) &#x3D;&gt; {
const res &#x3D; await window.Store.Wap.createGroup(name, participantIds); const participantWIDs &#x3D; participantIds.map(p &#x3D;&gt; window.Store.WidFactory.createWid(p));
console.log(res); const id &#x3D; window.Store.MsgKey.newId();
if (!res.status &#x3D;&#x3D;&#x3D; 200) { const res &#x3D; await window.Store.GroupUtils.sendCreateGroup(name, participantWIDs, undefined, id);
throw &#x27;An error occurred while creating the group!&#x27;;
}
return res; return res;
}, name, participants); }, name, participants);
@@ -837,9 +1148,9 @@ class Client extends EventEmitter {
async getLabels() { async getLabels() {
const labels &#x3D; await this.pupPage.evaluate(async () &#x3D;&gt; { const labels &#x3D; await this.pupPage.evaluate(async () &#x3D;&gt; {
return window.WWebJS.getLabels(); return window.WWebJS.getLabels();
}); });
return labels.map(data &#x3D;&gt; new Label(this , data)); return labels.map(data &#x3D;&gt; new Label(this, data));
} }
/** /**
@@ -850,7 +1161,7 @@ class Client extends EventEmitter {
async getLabelById(labelId) { async getLabelById(labelId) {
const label &#x3D; await this.pupPage.evaluate(async (labelId) &#x3D;&gt; { const label &#x3D; await this.pupPage.evaluate(async (labelId) &#x3D;&gt; {
return window.WWebJS.getLabel(labelId); return window.WWebJS.getLabel(labelId);
}, labelId); }, labelId);
return new Label(this, label); return new Label(this, label);
} }
@@ -860,12 +1171,12 @@ class Client extends EventEmitter {
* @param {string} chatId * @param {string} chatId
* @returns {Promise&amp;lt;Array&amp;lt;Label&gt;&gt;} * @returns {Promise&amp;lt;Array&amp;lt;Label&gt;&gt;}
*/ */
async getChatLabels(chatId){ async getChatLabels(chatId) {
const labels &#x3D; await this.pupPage.evaluate(async (chatId) &#x3D;&gt; { const labels &#x3D; await this.pupPage.evaluate(async (chatId) &#x3D;&gt; {
return window.WWebJS.getChatLabels(chatId); return window.WWebJS.getChatLabels(chatId);
}, chatId); }, chatId);
return labels.map(data &#x3D;&gt; new Label(this, data)); return labels.map(data &#x3D;&gt; new Label(this, data));
} }
/** /**
@@ -873,20 +1184,33 @@ class Client extends EventEmitter {
* @param {string} labelId * @param {string} labelId
* @returns {Promise&amp;lt;Array&amp;lt;Chat&gt;&gt;} * @returns {Promise&amp;lt;Array&amp;lt;Chat&gt;&gt;}
*/ */
async getChatsByLabelId(labelId){ async getChatsByLabelId(labelId) {
const chatIds &#x3D; await this.pupPage.evaluate(async (labelId) &#x3D;&gt; { const chatIds &#x3D; await this.pupPage.evaluate(async (labelId) &#x3D;&gt; {
const label &#x3D; window.Store.Label.get(labelId); const label &#x3D; window.Store.Label.get(labelId);
const labelItems &#x3D; label.labelItemCollection.models; const labelItems &#x3D; label.labelItemCollection.getModelsArray();
return labelItems.reduce((result, item) &#x3D;&gt; { return labelItems.reduce((result, item) &#x3D;&gt; {
if(item.parentType &#x3D;&#x3D;&#x3D; &#x27;Chat&#x27;){ if (item.parentType &#x3D;&#x3D;&#x3D; &#x27;Chat&#x27;) {
result.push(item.parentId); result.push(item.parentId);
} }
return result; return result;
},[]); }, []);
}, labelId); }, labelId);
return Promise.all(chatIds.map(id &#x3D;&gt; this.getChatById(id))); return Promise.all(chatIds.map(id &#x3D;&gt; this.getChatById(id)));
} }
/**
* Gets all blocked contacts by host account
* @returns {Promise&amp;lt;Array&amp;lt;Contact&gt;&gt;}
*/
async getBlockedContacts() {
const blockedContacts &#x3D; await this.pupPage.evaluate(() &#x3D;&gt; {
let chatIds &#x3D; window.Store.Blocklist.getModelsArray().map(a &#x3D;&gt; a.id._serialized);
return Promise.all(chatIds.map(id &#x3D;&gt; window.WWebJS.getContact(id)));
});
return blockedContacts.map(contact &#x3D;&gt; ContactFactory.create(this.client, contact));
}
} }
module.exports &#x3D; Client; module.exports &#x3D; Client;
@@ -900,7 +1224,7 @@ module.exports &#x3D; Client;
<footer id="jsdoc-footer" class="jsdoc-footer"> <footer id="jsdoc-footer" class="jsdoc-footer">
<div id="jsdoc-footer-container"> <div id="jsdoc-footer-container">
<p> <p>
Generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc</a> 3.6.6 on April 20, 2021. Generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc</a> 3.6.7 on November 26, 2022.
</p> </p>
</div> </div>
</footer> </footer>

View File

@@ -2,9 +2,9 @@
<html> <html>
<head> <head>
<meta name="generator" content="JSDoc 3.6.6"> <meta name="generator" content="JSDoc 3.6.7">
<meta charset="utf-8"> <meta charset="utf-8">
<title>whatsapp-web.js 1.12.6 &raquo; Class: ClientInfo</title> <title>whatsapp-web.js 1.18.4 &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/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/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 rel="stylesheet" href="https://brick.a.ssl.fastly.net/Inconsolata:500" type="text/css">
@@ -15,7 +15,7 @@
<nav id="jsdoc-navbar" role="navigation" class="jsdoc-navbar"> <nav id="jsdoc-navbar" role="navigation" class="jsdoc-navbar">
<div id="jsdoc-navbar-container"> <div id="jsdoc-navbar-container">
<div id="jsdoc-navbar-content"> <div id="jsdoc-navbar-content">
<a href="index.html" class="jsdoc-navbar-package-name">whatsapp-web.<wbr>js 1.<wbr>12.<wbr>6</a> <a href="index.html" class="jsdoc-navbar-package-name">whatsapp-web.<wbr>js 1.<wbr>18.<wbr>4</a>
</div> </div>
</div> </div>
</nav> </nav>
@@ -101,7 +101,7 @@
</dl> </dl>
<h3 id="phone"><span class="symbol-name">phone</span><small class="property-type"> <h3 id="phone"><span class="symbol-name">phone</span><small class="property-type">
&nbsp;object</small></h3> &nbsp;object</small></h3>
<p>Information about the phone this client is connected to</p> <p>Information about the phone this client is connected to. Not available in multi-device.</p>
<section> <section>
<h4>Properties</h4> <h4>Properties</h4>
<table class="jsdoc-details-table"> <table class="jsdoc-details-table">
@@ -188,10 +188,12 @@
</table> </table>
</section> </section>
<dl class="dl-compact"> <dl class="dl-compact">
<dt>Deprecated</dt>
<dd></dd>
</dl> </dl>
<h3 id="platform"><span class="symbol-name">platform</span><small class="property-type"> <h3 id="platform"><span class="symbol-name">platform</span><small class="property-type">
&nbsp;string</small></h3> &nbsp;string</small></h3>
<p>Platform the phone is running on</p> <p>Platform WhatsApp is running on</p>
<dl class="dl-compact"> <dl class="dl-compact">
</dl> </dl>
<h3 id="pushname"><span class="symbol-name">pushname</span><small class="property-type"> <h3 id="pushname"><span class="symbol-name">pushname</span><small class="property-type">
@@ -211,17 +213,22 @@
<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> <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> <p>Get current battery percentage and charging status for the attached device</p>
<dl class="dl-compact"> <dl class="dl-compact">
<dt>Deprecated</dt>
<dd></dd>
<dt>Returns</dt> <dt>Returns</dt>
<dd> <dd>
<p><code>object</code> <p>batteryStatus</p> <p><code>object</code> 
<p>batteryStatus</p>
</p> </p>
</dd> </dd>
<dd> <dd>
<p><code>number</code> <p>batteryStatus.battery - The current battery percentage</p> <p><code>number</code> 
<p>batteryStatus.battery - The current battery percentage</p>
</p> </p>
</dd> </dd>
<dd> <dd>
<p><code>boolean</code> <p>batteryStatus.plugged - Indicates if the phone is plugged in (true) or not (false)</p> <p><code>boolean</code> 
<p>batteryStatus.plugged - Indicates if the phone is plugged in (true) or not (false)</p>
</p> </p>
</dd> </dd>
</dl> </dl>
@@ -235,7 +242,7 @@
<footer id="jsdoc-footer" class="jsdoc-footer"> <footer id="jsdoc-footer" class="jsdoc-footer">
<div id="jsdoc-footer-container"> <div id="jsdoc-footer-container">
<p> <p>
Generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc</a> 3.6.6 on April 20, 2021. Generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc</a> 3.6.7 on November 26, 2022.
</p> </p>
</div> </div>
</footer> </footer>

View File

@@ -2,9 +2,9 @@
<html> <html>
<head> <head>
<meta name="generator" content="JSDoc 3.6.6"> <meta name="generator" content="JSDoc 3.6.7">
<meta charset="utf-8"> <meta charset="utf-8">
<title>whatsapp-web.js 1.12.6 &raquo; Class: Contact</title> <title>whatsapp-web.js 1.18.4 &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/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/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 rel="stylesheet" href="https://brick.a.ssl.fastly.net/Inconsolata:500" type="text/css">
@@ -15,7 +15,7 @@
<nav id="jsdoc-navbar" role="navigation" class="jsdoc-navbar"> <nav id="jsdoc-navbar" role="navigation" class="jsdoc-navbar">
<div id="jsdoc-navbar-container"> <div id="jsdoc-navbar-container">
<div id="jsdoc-navbar-content"> <div id="jsdoc-navbar-content">
<a href="index.html" class="jsdoc-navbar-package-name">whatsapp-web.<wbr>js 1.<wbr>12.<wbr>6</a> <a href="index.html" class="jsdoc-navbar-package-name">whatsapp-web.<wbr>js 1.<wbr>18.<wbr>4</a>
</div> </div>
</div> </div>
</nav> </nav>
@@ -101,20 +101,29 @@
<dt><a href="Contact.html#getAbout">getAbout()</a></dt> <dt><a href="Contact.html#getAbout">getAbout()</a></dt>
<dd> <dd>
</dd> </dd>
</dl>
</div>
<div class="summary-column">
<dl class="dl-summary-callout">
<dt><a href="Contact.html#getChat">getChat()</a></dt> <dt><a href="Contact.html#getChat">getChat()</a></dt>
<dd> <dd>
</dd> </dd>
<dt><a href="Contact.html#getProfilePicUrl">getProfilePicUrl()</a></dt> </dl>
</div>
<div class="summary-column">
<dl class="dl-summary-callout">
<dt><a href="Contact.html#getCommonGroups">getCommonGroups()</a></dt>
<dd>
</dd>
<dt><a href="Contact.html#getCountryCode">getCountryCode()</a></dt>
<dd>
</dd>
<dt><a href="Contact.html#getFormattedNumber">getFormattedNumber()</a></dt>
<dd> <dd>
</dd> </dd>
</dl> </dl>
</div> </div>
<div class="summary-column"> <div class="summary-column">
<dl class="dl-summary-callout"> <dl class="dl-summary-callout">
<dt><a href="Contact.html#getProfilePicUrl">getProfilePicUrl()</a></dt>
<dd>
</dd>
<dt><a href="Contact.html#unblock">unblock()</a></dt> <dt><a href="Contact.html#unblock">unblock()</a></dt>
<dd> <dd>
</dd> </dd>
@@ -230,6 +239,33 @@
</dd> </dd>
</dl> </dl>
<div class="symbol-detail-labels"><span class="label label-async">async</span></div> <div class="symbol-detail-labels"><span class="label label-async">async</span></div>
<h3 id="getCommonGroups"><span class="symbol-name">getCommonGroups</span><span class="signature"><span class="signature-params">()</span>&nbsp;&rarr; <span class="signature-returns"> Promise containing Array of WAWebJS.ChatId</span></span></h3>
<p>Gets the Contact's common groups with you. Returns empty array if you don't have any common group.</p>
<dl class="dl-compact">
<dt>Returns</dt>
<dd>
<p><code>Promise containing Array of WAWebJS.ChatId</code> </p>
</dd>
</dl>
<div class="symbol-detail-labels"><span class="label label-async">async</span></div>
<h3 id="getCountryCode"><span class="symbol-name">getCountryCode</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 countrycode, (1541859685@c.us) =&gt; (1)</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="getFormattedNumber"><span class="symbol-name">getFormattedNumber</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 formatted phone number, (12345678901@c.us) =&gt; (+1 (234) 5678-901)</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="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> <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> <p>Returns the contact's profile picture URL, if privacy settings allow it</p>
<dl class="dl-compact"> <dl class="dl-compact">
@@ -257,7 +293,7 @@
<footer id="jsdoc-footer" class="jsdoc-footer"> <footer id="jsdoc-footer" class="jsdoc-footer">
<div id="jsdoc-footer-container"> <div id="jsdoc-footer-container">
<p> <p>
Generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc</a> 3.6.6 on April 20, 2021. Generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc</a> 3.6.7 on November 26, 2022.
</p> </p>
</div> </div>
</footer> </footer>

View File

@@ -2,9 +2,9 @@
<html> <html>
<head> <head>
<meta name="generator" content="JSDoc 3.6.6"> <meta name="generator" content="JSDoc 3.6.7">
<meta charset="utf-8"> <meta charset="utf-8">
<title>whatsapp-web.js 1.12.6 &raquo; Class: GroupChat</title> <title>whatsapp-web.js 1.18.4 &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/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/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 rel="stylesheet" href="https://brick.a.ssl.fastly.net/Inconsolata:500" type="text/css">
@@ -15,7 +15,7 @@
<nav id="jsdoc-navbar" role="navigation" class="jsdoc-navbar"> <nav id="jsdoc-navbar" role="navigation" class="jsdoc-navbar">
<div id="jsdoc-navbar-container"> <div id="jsdoc-navbar-container">
<div id="jsdoc-navbar-content"> <div id="jsdoc-navbar-content">
<a href="index.html" class="jsdoc-navbar-package-name">whatsapp-web.<wbr>js 1.<wbr>12.<wbr>6</a> <a href="index.html" class="jsdoc-navbar-package-name">whatsapp-web.<wbr>js 1.<wbr>18.<wbr>4</a>
</div> </div>
</div> </div>
</nav> </nav>
@@ -405,7 +405,8 @@
<dl class="dl-compact"> <dl class="dl-compact">
<dt>Returns</dt> <dt>Returns</dt>
<dd> <dd>
<p><code>Promise containing {status: number}</code> <p>Object with status code indicating if the operation was successful</p> <p><code>Promise containing {status: number}</code> 
<p>Object with status code indicating if the operation was successful</p>
</p> </p>
</dd> </dd>
</dl> </dl>
@@ -435,7 +436,7 @@
<p>&nbsp;</p> <p>&nbsp;</p>
</td> </td>
<td> <td>
<p>Options for searching messages. Right now only limit is supported.</p> <p>Options for searching messages. Right now only limit and fromMe is supported.</p>
<p>Values in <code>searchOptions</code> have the following properties:</p> <p>Values in <code>searchOptions</code> have the following properties:</p>
<table class="jsdoc-details-table"> <table class="jsdoc-details-table">
<thead> <thead>
@@ -458,8 +459,21 @@
<p>Yes</p> <p>Yes</p>
</td> </td>
<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>The amount of messages to return. If no limit is specified, the available messages will be returned. 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>
<tr>
<td>
<p>fromMe</p>
</td>
<td>
<p>&nbsp;</p>
</td>
<td>
<p>Yes</p>
</td>
<td>
<p>Return only messages from the bot number or vise versa. To get all messages, leave the option undefined.</p>
</td> </td>
</tr> </tr>
</tbody> </tbody>
@@ -490,7 +504,8 @@
<dl class="dl-compact"> <dl class="dl-compact">
<dt>Returns</dt> <dt>Returns</dt>
<dd> <dd>
<p><code>Promise containing string</code> <p>Group's invite code</p> <p><code>Promise containing string</code> 
<p>Group's invite code</p>
</p> </p>
</dd> </dd>
</dl> </dl>
@@ -521,7 +536,7 @@
</dl> </dl>
<div class="symbol-detail-labels"><span class="label label-async">async</span></div> <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> <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> <p>Mutes this chat forever, unless a date is specified</p>
<section> <section>
<h4>Parameter</h4> <h4>Parameter</h4>
<table class="jsdoc-details-table"> <table class="jsdoc-details-table">
@@ -545,7 +560,8 @@
<p>&nbsp;</p> <p>&nbsp;</p>
</td> </td>
<td> <td>
<p>Date at which the Chat will be unmuted</p> <p>Date at which the Chat will be unmuted, leave as is to mute forever</p>
<p>Value can be null.</p>
</td> </td>
</tr> </tr>
</tbody> </tbody>
@@ -600,7 +616,8 @@
<dl class="dl-compact"> <dl class="dl-compact">
<dt>Returns</dt> <dt>Returns</dt>
<dd> <dd>
<p><code>Promise containing {status: number}</code> <p>Object with status code indicating if the operation was successful</p> <p><code>Promise containing {status: number}</code> 
<p>Object with status code indicating if the operation was successful</p>
</p> </p>
</dd> </dd>
</dl> </dl>
@@ -642,12 +659,14 @@
</dd> </dd>
</dl> </dl>
<div class="symbol-detail-labels"><span class="label label-async">async</span></div> <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> <h3 id="revokeInvite"><span class="symbol-name">revokeInvite</span><span class="signature"><span class="signature-params">()</span>&nbsp;&rarr; <span class="signature-returns"> Promise containing string</span></span></h3>
<p>Invalidates the current group invite code and generates a new one</p> <p>Invalidates the current group invite code and generates a new one</p>
<dl class="dl-compact"> <dl class="dl-compact">
<dt>Returns</dt> <dt>Returns</dt>
<dd> <dd>
<p><code>Promise</code> </p> <p><code>Promise containing string</code> 
<p>New invite code</p>
</p>
</dd> </dd>
</dl> </dl>
<div class="symbol-detail-labels"><span class="label label-async">async</span></div> <div class="symbol-detail-labels"><span class="label label-async">async</span></div>
@@ -728,7 +747,7 @@
<dd><a href="Chat.html#sendStateTyping">Chat#sendStateTyping</a></dd> <dd><a href="Chat.html#sendStateTyping">Chat#sendStateTyping</a></dd>
</dl> </dl>
<div class="symbol-detail-labels"><span class="label label-async">async</span></div> <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> <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 containing boolean</span></span></h3>
<p>Updates the group description</p> <p>Updates the group description</p>
<section> <section>
<h4>Parameter</h4> <h4>Parameter</h4>
@@ -761,7 +780,9 @@
<dl class="dl-compact"> <dl class="dl-compact">
<dt>Returns</dt> <dt>Returns</dt>
<dd> <dd>
<p><code>Promise</code> </p> <p><code>Promise containing boolean</code> 
<p>Returns true if the description was properly updated. This can return false if the user does not have the necessary permissions.</p>
</p>
</dd> </dd>
</dl> </dl>
<div class="symbol-detail-labels"><span class="label label-async">async</span></div> <div class="symbol-detail-labels"><span class="label label-async">async</span></div>
@@ -800,7 +821,8 @@
<dl class="dl-compact"> <dl class="dl-compact">
<dt>Returns</dt> <dt>Returns</dt>
<dd> <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><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> </p>
</dd> </dd>
</dl> </dl>
@@ -840,12 +862,13 @@
<dl class="dl-compact"> <dl class="dl-compact">
<dt>Returns</dt> <dt>Returns</dt>
<dd> <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><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> </p>
</dd> </dd>
</dl> </dl>
<div class="symbol-detail-labels"><span class="label label-async">async</span></div> <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> <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 containing boolean</span></span></h3>
<p>Updates the group subject</p> <p>Updates the group subject</p>
<section> <section>
<h4>Parameter</h4> <h4>Parameter</h4>
@@ -878,7 +901,9 @@
<dl class="dl-compact"> <dl class="dl-compact">
<dt>Returns</dt> <dt>Returns</dt>
<dd> <dd>
<p><code>Promise</code> </p> <p><code>Promise containing boolean</code> 
<p>Returns true if the subject was properly updated. This can return false if the user does not have the necessary permissions.</p>
</p>
</dd> </dd>
</dl> </dl>
<div class="symbol-detail-labels"><span class="label label-async">async</span></div> <div class="symbol-detail-labels"><span class="label label-async">async</span></div>
@@ -916,7 +941,7 @@
<footer id="jsdoc-footer" class="jsdoc-footer"> <footer id="jsdoc-footer" class="jsdoc-footer">
<div id="jsdoc-footer-container"> <div id="jsdoc-footer-container">
<p> <p>
Generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc</a> 3.6.6 on April 20, 2021. Generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc</a> 3.6.7 on November 26, 2022.
</p> </p>
</div> </div>
</footer> </footer>

View File

@@ -2,9 +2,9 @@
<html> <html>
<head> <head>
<meta name="generator" content="JSDoc 3.6.6"> <meta name="generator" content="JSDoc 3.6.7">
<meta charset="utf-8"> <meta charset="utf-8">
<title>whatsapp-web.js 1.12.6 &raquo; Class: GroupNotification</title> <title>whatsapp-web.js 1.18.4 &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/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/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 rel="stylesheet" href="https://brick.a.ssl.fastly.net/Inconsolata:500" type="text/css">
@@ -15,7 +15,7 @@
<nav id="jsdoc-navbar" role="navigation" class="jsdoc-navbar"> <nav id="jsdoc-navbar" role="navigation" class="jsdoc-navbar">
<div id="jsdoc-navbar-container"> <div id="jsdoc-navbar-container">
<div id="jsdoc-navbar-content"> <div id="jsdoc-navbar-content">
<a href="index.html" class="jsdoc-navbar-package-name">whatsapp-web.<wbr>js 1.<wbr>12.<wbr>6</a> <a href="index.html" class="jsdoc-navbar-package-name">whatsapp-web.<wbr>js 1.<wbr>18.<wbr>4</a>
</div> </div>
</div> </div>
</nav> </nav>
@@ -233,7 +233,7 @@
<footer id="jsdoc-footer" class="jsdoc-footer"> <footer id="jsdoc-footer" class="jsdoc-footer">
<div id="jsdoc-footer-container"> <div id="jsdoc-footer-container">
<p> <p>
Generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc</a> 3.6.6 on April 20, 2021. Generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc</a> 3.6.7 on November 26, 2022.
</p> </p>
</div> </div>
</footer> </footer>

View File

@@ -2,9 +2,9 @@
<html> <html>
<head> <head>
<meta name="generator" content="JSDoc 3.6.6"> <meta name="generator" content="JSDoc 3.6.7">
<meta charset="utf-8"> <meta charset="utf-8">
<title>whatsapp-web.js 1.12.6 &raquo; Class: InterfaceController</title> <title>whatsapp-web.js 1.18.4 &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/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/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 rel="stylesheet" href="https://brick.a.ssl.fastly.net/Inconsolata:500" type="text/css">
@@ -15,7 +15,7 @@
<nav id="jsdoc-navbar" role="navigation" class="jsdoc-navbar"> <nav id="jsdoc-navbar" role="navigation" class="jsdoc-navbar">
<div id="jsdoc-navbar-container"> <div id="jsdoc-navbar-container">
<div id="jsdoc-navbar-content"> <div id="jsdoc-navbar-content">
<a href="index.html" class="jsdoc-navbar-package-name">whatsapp-web.<wbr>js 1.<wbr>12.<wbr>6</a> <a href="index.html" class="jsdoc-navbar-package-name">whatsapp-web.<wbr>js 1.<wbr>18.<wbr>4</a>
</div> </div>
</div> </div>
</nav> </nav>
@@ -39,16 +39,28 @@
<div class="summary-content"> <div class="summary-content">
<div class="summary-column"> <div class="summary-column">
<dl class="dl-summary-callout"> <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> <dt><a href="InterfaceController.html#closeRightDrawer">closeRightDrawer()</a></dt>
<dd> <dd>
</dd> </dd>
<dt><a href="InterfaceController.html#openChatDrawer">openChatDrawer(chatId)</a></dt> <dt><a href="InterfaceController.html#disableFeatures">disableFeatures(features)</a></dt>
<dd>
</dd>
<dt><a href="InterfaceController.html#enableFeatures">enableFeatures(features)</a></dt>
<dd> <dd>
</dd> </dd>
</dl> </dl>
</div> </div>
<div class="summary-column"> <div class="summary-column">
<dl class="dl-summary-callout"> <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> <dt><a href="InterfaceController.html#openChatSearch">openChatSearch(chatId)</a></dt>
<dd> <dd>
</dd> </dd>
@@ -78,12 +90,119 @@
<section> <section>
<h2>Methods</h2> <h2>Methods</h2>
<section> <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> <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> <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> <p>Closes the Right Drawer</p>
<dl class="dl-compact"> <dl class="dl-compact">
</dl> </dl>
<div class="symbol-detail-labels"><span class="label label-async">async</span></div> <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> <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> <p>Opens the Chat Drawer</p>
<section> <section>
@@ -263,7 +382,7 @@
<footer id="jsdoc-footer" class="jsdoc-footer"> <footer id="jsdoc-footer" class="jsdoc-footer">
<div id="jsdoc-footer-container"> <div id="jsdoc-footer-container">
<p> <p>
Generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc</a> 3.6.6 on April 20, 2021. Generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc</a> 3.6.7 on November 26, 2022.
</p> </p>
</div> </div>
</footer> </footer>

View File

@@ -2,9 +2,9 @@
<html> <html>
<head> <head>
<meta name="generator" content="JSDoc 3.6.6"> <meta name="generator" content="JSDoc 3.6.7">
<meta charset="utf-8"> <meta charset="utf-8">
<title>whatsapp-web.js 1.12.6 &raquo; Class: Label</title> <title>whatsapp-web.js 1.18.4 &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/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/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 rel="stylesheet" href="https://brick.a.ssl.fastly.net/Inconsolata:500" type="text/css">
@@ -15,7 +15,7 @@
<nav id="jsdoc-navbar" role="navigation" class="jsdoc-navbar"> <nav id="jsdoc-navbar" role="navigation" class="jsdoc-navbar">
<div id="jsdoc-navbar-container"> <div id="jsdoc-navbar-container">
<div id="jsdoc-navbar-content"> <div id="jsdoc-navbar-content">
<a href="index.html" class="jsdoc-navbar-package-name">whatsapp-web.<wbr>js 1.<wbr>12.<wbr>6</a> <a href="index.html" class="jsdoc-navbar-package-name">whatsapp-web.<wbr>js 1.<wbr>18.<wbr>4</a>
</div> </div>
</div> </div>
</nav> </nav>
@@ -163,7 +163,7 @@
<footer id="jsdoc-footer" class="jsdoc-footer"> <footer id="jsdoc-footer" class="jsdoc-footer">
<div id="jsdoc-footer-container"> <div id="jsdoc-footer-container">
<p> <p>
Generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc</a> 3.6.6 on April 20, 2021. Generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc</a> 3.6.7 on November 26, 2022.
</p> </p>
</div> </div>
</footer> </footer>

188
docs/LegacySessionAuth.html Normal file
View File

@@ -0,0 +1,188 @@
<!doctype html>
<html>
<head>
<meta name="generator" content="JSDoc 3.6.7">
<meta charset="utf-8">
<title>whatsapp-web.js 1.18.4 &raquo; Class: LegacySessionAuth</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>18.<wbr>4</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">LegacySessionAuth</span></h1>
<p class="source-link">Source: <a href="authStrategies_LegacySessionAuth.js.html#source-line-16">authStrategies/<wbr>LegacySessionAuth.<wbr>js:16</a></p>
<div class="symbol-classdesc">
<p>Legacy session auth strategy
Not compatible with multi-device accounts.</p>
</div>
<dl class="dl-compact">
</dl>
</header>
<section id="summary">
</section>
<section>
<h2 id="LegacySessionAuth">new&nbsp;<span class="symbol-name">LegacySessionAuth</span><span class="signature"><span class="signature-params">(options)</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>options</p>
</td>
<td>
<p>&nbsp;</p>
</td>
<td>
<p>&nbsp;</p>
</td>
<td>
<p>options</p>
<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>restartOnAuthFail</p>
</td>
<td>
<p>&nbsp;</p>
</td>
<td>
<p>&nbsp;</p>
</td>
<td>
<p>Restart client with a new session (i.e. use null 'session' var) if authentication fails</p>
</td>
</tr>
<tr>
<td>
<p>session</p>
</td>
<td>
<p>&nbsp;</p>
</td>
<td>
<p>&nbsp;</p>
</td>
<td>
<p>Whatsapp session to restore. If not set, will start a new session</p>
</td>
</tr>
<tr>
<td>
<p>session.WABrowserId</p>
</td>
<td>
<p>&nbsp;</p>
</td>
<td>
<p>&nbsp;</p>
</td>
<td>
</td>
</tr>
<tr>
<td>
<p>session.WASecretBundle</p>
</td>
<td>
<p>&nbsp;</p>
</td>
<td>
<p>&nbsp;</p>
</td>
<td>
</td>
</tr>
<tr>
<td>
<p>session.WAToken1</p>
</td>
<td>
<p>&nbsp;</p>
</td>
<td>
<p>&nbsp;</p>
</td>
<td>
</td>
</tr>
<tr>
<td>
<p>session.WAToken2</p>
</td>
<td>
<p>&nbsp;</p>
</td>
<td>
<p>&nbsp;</p>
</td>
<td>
</td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
</section>
<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 November 26, 2022.
</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>

271
docs/List.html Normal file
View File

@@ -0,0 +1,271 @@
<!doctype html>
<html>
<head>
<meta name="generator" content="JSDoc 3.6.7">
<meta charset="utf-8">
<title>whatsapp-web.js 1.18.4 &raquo; Class: List</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>18.<wbr>4</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">List</span></h1>
<p class="source-link">Source: <a href="structures_List.js.html#source-line-8">structures/<wbr>List.<wbr>js:8</a></p>
<div class="symbol-classdesc">
<p>Message type List</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="List.html#buttonText">buttonText</a></dt>
<dd>
</dd>
<dt><a href="List.html#description">description</a></dt>
<dd>
</dd>
</dl>
</div>
<div class="summary-column">
<dl class="dl-summary-callout">
<dt><a href="List.html#footer">footer</a></dt>
<dd>
</dd>
<dt><a href="List.html#sections">sections</a></dt>
<dd>
</dd>
</dl>
</div>
<div class="summary-column">
<dl class="dl-summary-callout">
<dt><a href="List.html#title">title</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="List.html#_format">_format(sections)</a></dt>
<dd>
</dd>
</dl>
</div>
<div class="summary-column">
</div>
<div class="summary-column">
</div>
</div>
</div>
</section>
<section>
<h2 id="List">new&nbsp;<span class="symbol-name">List</span><span class="signature"><span class="signature-params">(body, buttonText, sections, title, footer)</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>body</p>
</td>
<td>
<p>&nbsp;</p>
</td>
<td>
<p>&nbsp;</p>
</td>
<td>
</td>
</tr>
<tr>
<td>
<p>buttonText</p>
</td>
<td>
<p>&nbsp;</p>
</td>
<td>
<p>&nbsp;</p>
</td>
<td>
</td>
</tr>
<tr>
<td>
<p>sections</p>
</td>
<td>
<p>&nbsp;</p>
</td>
<td>
<p>&nbsp;</p>
</td>
<td>
</td>
</tr>
<tr>
<td>
<p>title</p>
</td>
<td>
<p>&nbsp;</p>
</td>
<td>
<p>&nbsp;</p>
</td>
<td>
<p>Value can be null.</p>
</td>
</tr>
<tr>
<td>
<p>footer</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="buttonText"><span class="symbol-name">buttonText</span><small class="property-type">
&nbsp;string</small></h3>
<p>List button text</p>
<dl class="dl-compact">
</dl>
<h3 id="description"><span class="symbol-name">description</span><small class="property-type">
&nbsp;string</small></h3>
<p>Message body</p>
<dl class="dl-compact">
</dl>
<h3 id="footer"><span class="symbol-name">footer</span><small class="property-type">
&nbsp;string</small></h3>
<p>footer of message</p>
<dl class="dl-compact">
</dl>
<h3 id="sections"><span class="symbol-name">sections</span><small class="property-type">
&nbsp;Array of any</small></h3>
<p>sections of message</p>
<dl class="dl-compact">
</dl>
<h3 id="title"><span class="symbol-name">title</span><small class="property-type">
&nbsp;string</small></h3>
<p>title of message</p>
<dl class="dl-compact">
</dl>
</section>
<h2>Method</h2>
<section>
<h3 id="_format"><span class="symbol-name">_format</span><span class="signature"><span class="signature-params">(sections)</span>&nbsp;&rarr; <span class="signature-returns"> Array of any</span></span></h3>
<p>Creates section array from simple array</p>
<section>
<h4>
Example
</h4>
<div>
<pre class="prettyprint"><code>Input: [{title:&#x27;sectionTitle&#x27;,rows:[{id:&#x27;customId&#x27;, title:&#x27;ListItem2&#x27;, description: &#x27;desc&#x27;},{title:&#x27;ListItem2&#x27;}]}}]
Returns: [{&#x27;title&#x27;:&#x27;sectionTitle&#x27;,&#x27;rows&#x27;:[{&#x27;rowId&#x27;:&#x27;customId&#x27;,&#x27;title&#x27;:&#x27;ListItem1&#x27;,&#x27;description&#x27;:&#x27;desc&#x27;},{&#x27;rowId&#x27;:&#x27;oGSRoD&#x27;,&#x27;title&#x27;:&#x27;ListItem2&#x27;,&#x27;description&#x27;:&#x27;&#x27;}]}]</code></pre>
</div>
</section>
<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>sections</p>
</td>
<td>
<p>Array of any</p>
</td>
<td>
<p>&nbsp;</p>
</td>
<td>
</td>
</tr>
</tbody>
</table>
</section>
<dl class="dl-compact">
<dt>Returns</dt>
<dd>
<p><code>Array of any</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 November 26, 2022.
</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>

135
docs/LocalAuth.html Normal file
View File

@@ -0,0 +1,135 @@
<!doctype html>
<html>
<head>
<meta name="generator" content="JSDoc 3.6.7">
<meta charset="utf-8">
<title>whatsapp-web.js 1.18.4 &raquo; Class: LocalAuth</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>18.<wbr>4</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">LocalAuth</span></h1>
<p class="source-link">Source: <a href="authStrategies_LocalAuth.js.html#source-line-13">authStrategies/<wbr>LocalAuth.<wbr>js:13</a></p>
<div class="symbol-classdesc">
<p>Local directory-based authentication</p>
</div>
<dl class="dl-compact">
</dl>
</header>
<section id="summary">
</section>
<section>
<h2 id="LocalAuth">new&nbsp;<span class="symbol-name">LocalAuth</span><span class="signature"><span class="signature-params">(options)</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>options</p>
</td>
<td>
<p>&nbsp;</p>
</td>
<td>
<p>&nbsp;</p>
</td>
<td>
<p>options</p>
<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>clientId</p>
</td>
<td>
<p>&nbsp;</p>
</td>
<td>
<p>&nbsp;</p>
</td>
<td>
<p>Client id to distinguish instances if you are using multiple, otherwise keep null if you are using only one instance</p>
</td>
</tr>
<tr>
<td>
<p>dataPath</p>
</td>
<td>
<p>&nbsp;</p>
</td>
<td>
<p>&nbsp;</p>
</td>
<td>
<p>Change the default path for saving session files, default is: &quot;./.wwebjs_auth/&quot;</p>
</td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
</section>
<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 November 26, 2022.
</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

@@ -2,9 +2,9 @@
<html> <html>
<head> <head>
<meta name="generator" content="JSDoc 3.6.6"> <meta name="generator" content="JSDoc 3.6.7">
<meta charset="utf-8"> <meta charset="utf-8">
<title>whatsapp-web.js 1.12.6 &raquo; Class: Location</title> <title>whatsapp-web.js 1.18.4 &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/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/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 rel="stylesheet" href="https://brick.a.ssl.fastly.net/Inconsolata:500" type="text/css">
@@ -15,7 +15,7 @@
<nav id="jsdoc-navbar" role="navigation" class="jsdoc-navbar"> <nav id="jsdoc-navbar" role="navigation" class="jsdoc-navbar">
<div id="jsdoc-navbar-container"> <div id="jsdoc-navbar-container">
<div id="jsdoc-navbar-content"> <div id="jsdoc-navbar-content">
<a href="index.html" class="jsdoc-navbar-package-name">whatsapp-web.<wbr>js 1.<wbr>12.<wbr>6</a> <a href="index.html" class="jsdoc-navbar-package-name">whatsapp-web.<wbr>js 1.<wbr>18.<wbr>4</a>
</div> </div>
</div> </div>
</nav> </nav>
@@ -149,7 +149,7 @@
<footer id="jsdoc-footer" class="jsdoc-footer"> <footer id="jsdoc-footer" class="jsdoc-footer">
<div id="jsdoc-footer-container"> <div id="jsdoc-footer-container">
<p> <p>
Generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc</a> 3.6.6 on April 20, 2021. Generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc</a> 3.6.7 on November 26, 2022.
</p> </p>
</div> </div>
</footer> </footer>

View File

@@ -2,9 +2,9 @@
<html> <html>
<head> <head>
<meta name="generator" content="JSDoc 3.6.6"> <meta name="generator" content="JSDoc 3.6.7">
<meta charset="utf-8"> <meta charset="utf-8">
<title>whatsapp-web.js 1.12.6 &raquo; Class: Message</title> <title>whatsapp-web.js 1.18.4 &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/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/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 rel="stylesheet" href="https://brick.a.ssl.fastly.net/Inconsolata:500" type="text/css">
@@ -15,7 +15,7 @@
<nav id="jsdoc-navbar" role="navigation" class="jsdoc-navbar"> <nav id="jsdoc-navbar" role="navigation" class="jsdoc-navbar">
<div id="jsdoc-navbar-container"> <div id="jsdoc-navbar-container">
<div id="jsdoc-navbar-content"> <div id="jsdoc-navbar-content">
<a href="index.html" class="jsdoc-navbar-package-name">whatsapp-web.<wbr>js 1.<wbr>12.<wbr>6</a> <a href="index.html" class="jsdoc-navbar-package-name">whatsapp-web.<wbr>js 1.<wbr>18.<wbr>4</a>
</div> </div>
</div> </div>
</nav> </nav>
@@ -26,7 +26,7 @@
<header class="page-header"> <header class="page-header">
<div class="symbol-detail-labels"><span class="label label-kind">class</span></div> <div class="symbol-detail-labels"><span class="label label-kind">class</span></div>
<h1><small></small><span class="symbol-name">Message</span></h1> <h1><small></small><span class="symbol-name">Message</span></h1>
<p class="source-link">Source: <a href="structures_Message.js.html#source-line-12">structures/<wbr>Message.<wbr>js:12</a></p> <p class="source-link">Source: <a href="structures_Message.js.html#source-line-14">structures/<wbr>Message.<wbr>js:14</a></p>
<div class="symbol-classdesc"> <div class="symbol-classdesc">
<p>Represents a Message on WhatsApp</p> <p>Represents a Message on WhatsApp</p>
</div> </div>
@@ -51,6 +51,15 @@
<dt><a href="Message.html#broadcast">broadcast</a></dt> <dt><a href="Message.html#broadcast">broadcast</a></dt>
<dd> <dd>
</dd> </dd>
<dt><a href="Message.html#deviceType">deviceType</a></dt>
<dd>
</dd>
<dt><a href="Message.html#duration">duration</a></dt>
<dd>
</dd>
<dt><a href="Message.html#forwardingScore">forwardingScore</a></dt>
<dd>
</dd>
<dt><a href="Message.html#from">from</a></dt> <dt><a href="Message.html#from">from</a></dt>
<dd> <dd>
</dd> </dd>
@@ -70,9 +79,18 @@
<dt><a href="Message.html#id">id</a></dt> <dt><a href="Message.html#id">id</a></dt>
<dd> <dd>
</dd> </dd>
<dt><a href="Message.html#inviteV4">inviteV4</a></dt>
<dd>
</dd>
<dt><a href="Message.html#isEphemeral">isEphemeral</a></dt>
<dd>
</dd>
<dt><a href="Message.html#isForwarded">isForwarded</a></dt> <dt><a href="Message.html#isForwarded">isForwarded</a></dt>
<dd> <dd>
</dd> </dd>
<dt><a href="Message.html#isGif">isGif</a></dt>
<dd>
</dd>
<dt><a href="Message.html#isStarred">isStarred</a></dt> <dt><a href="Message.html#isStarred">isStarred</a></dt>
<dd> <dd>
</dd> </dd>
@@ -95,12 +113,21 @@
<dt><a href="Message.html#mentionedIds">mentionedIds</a></dt> <dt><a href="Message.html#mentionedIds">mentionedIds</a></dt>
<dd> <dd>
</dd> </dd>
<dt><a href="Message.html#orderId">orderId</a></dt>
<dd>
</dd>
<dt><a href="Message.html#rawData">rawData</a></dt>
<dd>
</dd>
<dt><a href="Message.html#timestamp">timestamp</a></dt> <dt><a href="Message.html#timestamp">timestamp</a></dt>
<dd> <dd>
</dd> </dd>
<dt><a href="Message.html#to">to</a></dt> <dt><a href="Message.html#to">to</a></dt>
<dd> <dd>
</dd> </dd>
<dt><a href="Message.html#token">token</a></dt>
<dd>
</dd>
<dt><a href="Message.html#type">type</a></dt> <dt><a href="Message.html#type">type</a></dt>
<dd> <dd>
</dd> </dd>
@@ -116,6 +143,9 @@
<div class="summary-content"> <div class="summary-content">
<div class="summary-column"> <div class="summary-column">
<dl class="dl-summary-callout"> <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> <dt><a href="Message.html#delete">delete(everyone)</a></dt>
<dd> <dd>
</dd> </dd>
@@ -128,26 +158,38 @@
<dt><a href="Message.html#getChat">getChat()</a></dt> <dt><a href="Message.html#getChat">getChat()</a></dt>
<dd> <dd>
</dd> </dd>
<dt><a href="Message.html#getContact">getContact()</a></dt>
<dd>
</dd>
</dl> </dl>
</div> </div>
<div class="summary-column"> <div class="summary-column">
<dl class="dl-summary-callout"> <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> <dt><a href="Message.html#getInfo">getInfo()</a></dt>
<dd> <dd>
</dd> </dd>
<dt><a href="Message.html#getMentions">getMentions()</a></dt> <dt><a href="Message.html#getMentions">getMentions()</a></dt>
<dd> <dd>
</dd> </dd>
<dt><a href="Message.html#getOrder">getOrder()</a></dt>
<dd>
</dd>
<dt><a href="Message.html#getPayment">getPayment()</a></dt>
<dd>
</dd>
<dt><a href="Message.html#getQuotedMessage">getQuotedMessage()</a></dt> <dt><a href="Message.html#getQuotedMessage">getQuotedMessage()</a></dt>
<dd> <dd>
</dd> </dd>
<dt><a href="Message.html#react">react(reaction)</a></dt>
<dd>
</dd>
</dl> </dl>
</div> </div>
<div class="summary-column"> <div class="summary-column">
<dl class="dl-summary-callout"> <dl class="dl-summary-callout">
<dt><a href="Message.html#reload">reload()</a></dt>
<dd>
</dd>
<dt><a href="Message.html#reply">reply(content[, chatId][, options])</a></dt> <dt><a href="Message.html#reply">reply(content[, chatId][, options])</a></dt>
<dd> <dd>
</dd> </dd>
@@ -192,6 +234,22 @@
<p>Indicates if the message was a broadcast</p> <p>Indicates if the message was a broadcast</p>
<dl class="dl-compact"> <dl class="dl-compact">
</dl> </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="duration"><span class="symbol-name">duration</span><small class="property-type">
&nbsp;string</small></h3>
<p>Indicates the duration of the message in seconds</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"> <h3 id="from"><span class="symbol-name">from</span><small class="property-type">
&nbsp;string</small></h3> &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> <p>ID for the Chat that this message was sent to, except if the message was sent by the current user.</p>
@@ -217,11 +275,26 @@
<p>ID that represents the message</p> <p>ID that represents the message</p>
<dl class="dl-compact"> <dl class="dl-compact">
</dl> </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="isEphemeral"><span class="symbol-name">isEphemeral</span><small class="property-type">
&nbsp;boolean</small></h3>
<p>Indicates if the message will disappear after it expires</p>
<dl class="dl-compact">
</dl>
<h3 id="isForwarded"><span class="symbol-name">isForwarded</span><small class="property-type"> <h3 id="isForwarded"><span class="symbol-name">isForwarded</span><small class="property-type">
&nbsp;boolean</small></h3> &nbsp;boolean</small></h3>
<p>Indicates if the message was forwarded</p> <p>Indicates if the message was forwarded</p>
<dl class="dl-compact"> <dl class="dl-compact">
</dl> </dl>
<h3 id="isGif"><span class="symbol-name">isGif</span><small class="property-type">
&nbsp;boolean</small></h3>
<p>Indicates whether the message is a Gif</p>
<dl class="dl-compact">
</dl>
<h3 id="isStarred"><span class="symbol-name">isStarred</span><small class="property-type"> <h3 id="isStarred"><span class="symbol-name">isStarred</span><small class="property-type">
&nbsp;boolean</small></h3> &nbsp;boolean</small></h3>
<p>Indicates if the message was starred</p> <p>Indicates if the message was starred</p>
@@ -233,7 +306,7 @@
<dl class="dl-compact"> <dl class="dl-compact">
</dl> </dl>
<h3 id="links"><span class="symbol-name">links</span><small class="property-type"> <h3 id="links"><span class="symbol-name">links</span><small class="property-type">
&nbsp;Array of string</small></h3> &nbsp;Array of {link: string, isSuspicious: boolean}</small></h3>
<p>Links included in the message.</p> <p>Links included in the message.</p>
<dl class="dl-compact"> <dl class="dl-compact">
</dl> </dl>
@@ -252,6 +325,16 @@
<p>Indicates the mentions in the message body.</p> <p>Indicates the mentions in the message body.</p>
<dl class="dl-compact"> <dl class="dl-compact">
</dl> </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="rawData"><span class="symbol-name">rawData</span><small class="property-type">
&nbsp;Object</small></h3>
<p>Returns message in a raw format</p>
<dl class="dl-compact">
</dl>
<h3 id="timestamp"><span class="symbol-name">timestamp</span><small class="property-type"> <h3 id="timestamp"><span class="symbol-name">timestamp</span><small class="property-type">
&nbsp;number</small></h3> &nbsp;number</small></h3>
<p>Unix timestamp for when the message was created</p> <p>Unix timestamp for when the message was created</p>
@@ -264,6 +347,11 @@
If the message is sent by another user, it will be the ID for the current user.</p> If the message is sent by another user, it will be the ID for the current user.</p>
<dl class="dl-compact"> <dl class="dl-compact">
</dl> </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"> <h3 id="type"><span class="symbol-name">type</span><small class="property-type">
&nbsp;<a href="global.html#MessageTypes">MessageTypes</a></small></h3> &nbsp;<a href="global.html#MessageTypes">MessageTypes</a></small></h3>
<p>Message type</p> <p>Message type</p>
@@ -277,6 +365,15 @@
</section> </section>
<h2>Methods</h2> <h2>Methods</h2>
<section> <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> <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> <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> <p>Deletes a message from the chat</p>
@@ -303,7 +400,7 @@
<p>&nbsp;</p> <p>&nbsp;</p>
</td> </td>
<td> <td>
<p>If true and the message is sent by the current user, will delete it for everyone in the chat.</p> <p>If true and the message is sent by the current user or the user is an admin, will delete it for everyone in the chat.</p>
<p>Value can be null.</p> <p>Value can be null.</p>
</td> </td>
</tr> </tr>
@@ -323,7 +420,7 @@
</dl> </dl>
<div class="symbol-detail-labels"><span class="label label-async">async</span></div> <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> <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> <p>Forwards this message to another chat (that you chatted before, otherwise it will fail)</p>
<section> <section>
<h4>Parameter</h4> <h4>Parameter</h4>
<table class="jsdoc-details-table"> <table class="jsdoc-details-table">
@@ -394,6 +491,24 @@
</dd> </dd>
</dl> </dl>
<div class="symbol-detail-labels"><span class="label label-async">async</span></div> <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="getPayment"><span class="symbol-name">getPayment</span><span class="signature"><span class="signature-params">()</span>&nbsp;&rarr; <span class="signature-returns"> Promise containing <a href="Payment.html">Payment</a></span></span></h3>
<p>Gets the payment details associated with a given message</p>
<dl class="dl-compact">
<dt>Returns</dt>
<dd>
<p><code>Promise containing <a href="Payment.html">Payment</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> <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> <p>Returns the quoted message, if any</p>
<dl class="dl-compact"> <dl class="dl-compact">
@@ -403,6 +518,54 @@
</dd> </dd>
</dl> </dl>
<div class="symbol-detail-labels"><span class="label label-async">async</span></div> <div class="symbol-detail-labels"><span class="label label-async">async</span></div>
<h3 id="react"><span class="symbol-name">react</span><span class="signature"><span class="signature-params">(reaction)</span>&nbsp;&rarr; <span class="signature-returns"> Promise</span></span></h3>
<p>React to this message with an emoji</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>reaction</p>
</td>
<td>
<p>string</p>
</td>
<td>
<p>&nbsp;</p>
</td>
<td>
<p>Emoji to react with. Send an empty string to remove the reaction.</p>
</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="reload"><span class="symbol-name">reload</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>Reloads this Message object's data in-place with the latest values from WhatsApp Web.
Note that the Message must still be in the web app cache for this to work, otherwise will return null.</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> <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 <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 through the specified Chat. If not, it will send the message
@@ -487,7 +650,7 @@
<footer id="jsdoc-footer" class="jsdoc-footer"> <footer id="jsdoc-footer" class="jsdoc-footer">
<div id="jsdoc-footer-container"> <div id="jsdoc-footer-container">
<p> <p>
Generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc</a> 3.6.6 on April 20, 2021. Generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc</a> 3.6.7 on November 26, 2022.
</p> </p>
</div> </div>
</footer> </footer>

View File

@@ -2,9 +2,9 @@
<html> <html>
<head> <head>
<meta name="generator" content="JSDoc 3.6.6"> <meta name="generator" content="JSDoc 3.6.7">
<meta charset="utf-8"> <meta charset="utf-8">
<title>whatsapp-web.js 1.12.6 &raquo; Class: MessageMedia</title> <title>whatsapp-web.js 1.18.4 &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/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/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 rel="stylesheet" href="https://brick.a.ssl.fastly.net/Inconsolata:500" type="text/css">
@@ -15,7 +15,7 @@
<nav id="jsdoc-navbar" role="navigation" class="jsdoc-navbar"> <nav id="jsdoc-navbar" role="navigation" class="jsdoc-navbar">
<div id="jsdoc-navbar-container"> <div id="jsdoc-navbar-container">
<div id="jsdoc-navbar-content"> <div id="jsdoc-navbar-content">
<a href="index.html" class="jsdoc-navbar-package-name">whatsapp-web.<wbr>js 1.<wbr>12.<wbr>6</a> <a href="index.html" class="jsdoc-navbar-package-name">whatsapp-web.<wbr>js 1.<wbr>18.<wbr>4</a>
</div> </div>
</div> </div>
</nav> </nav>
@@ -26,7 +26,7 @@
<header class="page-header"> <header class="page-header">
<div class="symbol-detail-labels"><span class="label label-kind">class</span></div> <div class="symbol-detail-labels"><span class="label label-kind">class</span></div>
<h1><small></small><span class="symbol-name">MessageMedia</span></h1> <h1><small></small><span class="symbol-name">MessageMedia</span></h1>
<p class="source-link">Source: <a href="structures_MessageMedia.js.html#source-line-13">structures/<wbr>MessageMedia.<wbr>js:13</a></p> <p class="source-link">Source: <a href="structures_MessageMedia.js.html#source-line-16">structures/<wbr>MessageMedia.<wbr>js:16</a></p>
<div class="symbol-classdesc"> <div class="symbol-classdesc">
<p>Media attached to a message</p> <p>Media attached to a message</p>
</div> </div>
@@ -42,10 +42,6 @@
<dt><a href="MessageMedia.html#data">data</a></dt> <dt><a href="MessageMedia.html#data">data</a></dt>
<dd> <dd>
</dd> </dd>
</dl>
</div>
<div class="summary-column">
<dl class="dl-summary-callout">
<dt><a href="MessageMedia.html#filename">filename</a></dt> <dt><a href="MessageMedia.html#filename">filename</a></dt>
<dd> <dd>
</dd> </dd>
@@ -53,15 +49,20 @@
</div> </div>
<div class="summary-column"> <div class="summary-column">
<dl class="dl-summary-callout"> <dl class="dl-summary-callout">
<dt><a href="MessageMedia.html#filesize">filesize</a></dt>
<dd>
</dd>
<dt><a href="MessageMedia.html#mimetype">mimetype</a></dt> <dt><a href="MessageMedia.html#mimetype">mimetype</a></dt>
<dd> <dd>
</dd> </dd>
</dl> </dl>
</div> </div>
<div class="summary-column">
</div>
</div> </div>
</div> </div>
<div class="summary-callout"> <div class="summary-callout">
<h2 class="summary-callout-heading">Method</h2> <h2 class="summary-callout-heading">Methods</h2>
<div class="summary-content"> <div class="summary-content">
<div class="summary-column"> <div class="summary-column">
<dl class="dl-summary-callout"> <dl class="dl-summary-callout">
@@ -71,6 +72,11 @@
</dl> </dl>
</div> </div>
<div class="summary-column"> <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>
<div class="summary-column"> <div class="summary-column">
</div> </div>
@@ -78,7 +84,7 @@
</div> </div>
</section> </section>
<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> <h2 id="MessageMedia">new&nbsp;<span class="symbol-name">MessageMedia</span><span class="signature"><span class="signature-params">(mimetype, data, filename, filesize)</span></span></h2>
<section> <section>
<h3>Parameters</h3> <h3>Parameters</h3>
<table class="jsdoc-details-table"> <table class="jsdoc-details-table">
@@ -130,7 +136,22 @@
<p>&nbsp;</p> <p>&nbsp;</p>
</td> </td>
<td> <td>
<p>Document file name</p> <p>Document file name. Value can be null</p>
<p>Value can be null.</p>
</td>
</tr>
<tr>
<td>
<p>filesize</p>
</td>
<td>
<p>&nbsp;</p>
</td>
<td>
<p>&nbsp;</p>
</td>
<td>
<p>Document file size in bytes. Value can be null</p>
<p>Value can be null.</p> <p>Value can be null.</p>
</td> </td>
</tr> </tr>
@@ -150,7 +171,12 @@
</dl> </dl>
<h3 id="filename"><span class="symbol-name">filename</span><small class="property-type"> <h3 id="filename"><span class="symbol-name">filename</span><small class="property-type">
&nbsp;nullable string</small></h3> &nbsp;nullable string</small></h3>
<p>Name of the file (for documents)</p> <p>Document file name. Value can be null</p>
<dl class="dl-compact">
</dl>
<h3 id="filesize"><span class="symbol-name">filesize</span><small class="property-type">
&nbsp;nullable number</small></h3>
<p>Document file size in bytes. Value can be null</p>
<dl class="dl-compact"> <dl class="dl-compact">
</dl> </dl>
<h3 id="mimetype"><span class="symbol-name">mimetype</span><small class="property-type"> <h3 id="mimetype"><span class="symbol-name">mimetype</span><small class="property-type">
@@ -159,7 +185,7 @@
<dl class="dl-compact"> <dl class="dl-compact">
</dl> </dl>
</section> </section>
<h2>Method</h2> <h2>Methods</h2>
<section> <section>
<div class="symbol-detail-labels"><span class="label label-static">static</span></div> <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> <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>
@@ -198,6 +224,136 @@
<p><code><a href="MessageMedia.html">MessageMedia</a></code> </p> <p><code><a href="MessageMedia.html">MessageMedia</a></code> </p>
</dd> </dd>
</dl> </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>boolean</p>
</td>
<td>
<p>Yes</p>
</td>
<td>
<p>Defaults to <code>false</code>.</p>
</td>
</tr>
<tr>
<td>
<p>filename</p>
</td>
<td>
<p>string</p>
</td>
<td>
<p>Yes</p>
</td>
<td>
</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>
</section> </section>
</div> </div>
@@ -208,7 +364,7 @@
<footer id="jsdoc-footer" class="jsdoc-footer"> <footer id="jsdoc-footer" class="jsdoc-footer">
<div id="jsdoc-footer-container"> <div id="jsdoc-footer-container">
<p> <p>
Generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc</a> 3.6.6 on April 20, 2021. Generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc</a> 3.6.7 on November 26, 2022.
</p> </p>
</div> </div>
</footer> </footer>

66
docs/NoAuth.html Normal file
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.18.4 &raquo; Class: NoAuth</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>18.<wbr>4</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">NoAuth</span></h1>
<p class="source-link">Source: <a href="authStrategies_NoAuth.js.html#source-line-9">authStrategies/<wbr>NoAuth.<wbr>js:9</a></p>
<div class="symbol-classdesc">
<p>No session restoring functionality
Will need to authenticate via QR code every time</p>
</div>
<dl class="dl-compact">
</dl>
</header>
<section id="summary">
</section>
<section>
<h2 id="NoAuth">new&nbsp;<span class="symbol-name">NoAuth</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 November 26, 2022.
</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.18.4 &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>18.<wbr>4</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 November 26, 2022.
</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

@@ -2,9 +2,9 @@
<html> <html>
<head> <head>
<meta name="generator" content="JSDoc 3.6.6"> <meta name="generator" content="JSDoc 3.6.7">
<meta charset="utf-8"> <meta charset="utf-8">
<title>whatsapp-web.js 1.12.6 &raquo; Class: PrivateChat</title> <title>whatsapp-web.js 1.18.4 &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/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/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 rel="stylesheet" href="https://brick.a.ssl.fastly.net/Inconsolata:500" type="text/css">
@@ -15,7 +15,7 @@
<nav id="jsdoc-navbar" role="navigation" class="jsdoc-navbar"> <nav id="jsdoc-navbar" role="navigation" class="jsdoc-navbar">
<div id="jsdoc-navbar-container"> <div id="jsdoc-navbar-container">
<div id="jsdoc-navbar-content"> <div id="jsdoc-navbar-content">
<a href="index.html" class="jsdoc-navbar-package-name">whatsapp-web.<wbr>js 1.<wbr>12.<wbr>6</a> <a href="index.html" class="jsdoc-navbar-package-name">whatsapp-web.<wbr>js 1.<wbr>18.<wbr>4</a>
</div> </div>
</div> </div>
</nav> </nav>
@@ -295,7 +295,7 @@
<p>&nbsp;</p> <p>&nbsp;</p>
</td> </td>
<td> <td>
<p>Options for searching messages. Right now only limit is supported.</p> <p>Options for searching messages. Right now only limit and fromMe is supported.</p>
<p>Values in <code>searchOptions</code> have the following properties:</p> <p>Values in <code>searchOptions</code> have the following properties:</p>
<table class="jsdoc-details-table"> <table class="jsdoc-details-table">
<thead> <thead>
@@ -318,8 +318,21 @@
<p>Yes</p> <p>Yes</p>
</td> </td>
<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>The amount of messages to return. If no limit is specified, the available messages will be returned. 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>
<tr>
<td>
<p>fromMe</p>
</td>
<td>
<p>&nbsp;</p>
</td>
<td>
<p>Yes</p>
</td>
<td>
<p>Return only messages from the bot number or vise versa. To get all messages, leave the option undefined.</p>
</td> </td>
</tr> </tr>
</tbody> </tbody>
@@ -362,7 +375,7 @@
</dl> </dl>
<div class="symbol-detail-labels"><span class="label label-async">async</span></div> <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> <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> <p>Mutes this chat forever, unless a date is specified</p>
<section> <section>
<h4>Parameter</h4> <h4>Parameter</h4>
<table class="jsdoc-details-table"> <table class="jsdoc-details-table">
@@ -386,7 +399,8 @@
<p>&nbsp;</p> <p>&nbsp;</p>
</td> </td>
<td> <td>
<p>Date at which the Chat will be unmuted</p> <p>Date at which the Chat will be unmuted, leave as is to mute forever</p>
<p>Value can be null.</p>
</td> </td>
</tr> </tr>
</tbody> </tbody>
@@ -519,7 +533,7 @@
<footer id="jsdoc-footer" class="jsdoc-footer"> <footer id="jsdoc-footer" class="jsdoc-footer">
<div id="jsdoc-footer-container"> <div id="jsdoc-footer-container">
<p> <p>
Generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc</a> 3.6.6 on April 20, 2021. Generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc</a> 3.6.7 on November 26, 2022.
</p> </p>
</div> </div>
</footer> </footer>

View File

@@ -2,9 +2,9 @@
<html> <html>
<head> <head>
<meta name="generator" content="JSDoc 3.6.6"> <meta name="generator" content="JSDoc 3.6.7">
<meta charset="utf-8"> <meta charset="utf-8">
<title>whatsapp-web.js 1.12.6 &raquo; Class: PrivateContact</title> <title>whatsapp-web.js 1.18.4 &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/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/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 rel="stylesheet" href="https://brick.a.ssl.fastly.net/Inconsolata:500" type="text/css">
@@ -15,7 +15,7 @@
<nav id="jsdoc-navbar" role="navigation" class="jsdoc-navbar"> <nav id="jsdoc-navbar" role="navigation" class="jsdoc-navbar">
<div id="jsdoc-navbar-container"> <div id="jsdoc-navbar-container">
<div id="jsdoc-navbar-content"> <div id="jsdoc-navbar-content">
<a href="index.html" class="jsdoc-navbar-package-name">whatsapp-web.<wbr>js 1.<wbr>12.<wbr>6</a> <a href="index.html" class="jsdoc-navbar-package-name">whatsapp-web.<wbr>js 1.<wbr>18.<wbr>4</a>
</div> </div>
</div> </div>
</nav> </nav>
@@ -101,20 +101,29 @@
<dt><a href="PrivateContact.html#getAbout">getAbout()</a></dt> <dt><a href="PrivateContact.html#getAbout">getAbout()</a></dt>
<dd> <dd>
</dd> </dd>
</dl>
</div>
<div class="summary-column">
<dl class="dl-summary-callout">
<dt><a href="PrivateContact.html#getChat">getChat()</a></dt> <dt><a href="PrivateContact.html#getChat">getChat()</a></dt>
<dd> <dd>
</dd> </dd>
<dt><a href="PrivateContact.html#getProfilePicUrl">getProfilePicUrl()</a></dt> </dl>
</div>
<div class="summary-column">
<dl class="dl-summary-callout">
<dt><a href="PrivateContact.html#getCommonGroups">getCommonGroups()</a></dt>
<dd>
</dd>
<dt><a href="PrivateContact.html#getCountryCode">getCountryCode()</a></dt>
<dd>
</dd>
<dt><a href="PrivateContact.html#getFormattedNumber">getFormattedNumber()</a></dt>
<dd> <dd>
</dd> </dd>
</dl> </dl>
</div> </div>
<div class="summary-column"> <div class="summary-column">
<dl class="dl-summary-callout"> <dl class="dl-summary-callout">
<dt><a href="PrivateContact.html#getProfilePicUrl">getProfilePicUrl()</a></dt>
<dd>
</dd>
<dt><a href="PrivateContact.html#unblock">unblock()</a></dt> <dt><a href="PrivateContact.html#unblock">unblock()</a></dt>
<dd> <dd>
</dd> </dd>
@@ -256,6 +265,33 @@
<dd></dd> <dd></dd>
</dl> </dl>
<div class="symbol-detail-labels"><span class="label label-async">async</span></div> <div class="symbol-detail-labels"><span class="label label-async">async</span></div>
<h3 id="getCommonGroups"><span class="symbol-name">getCommonGroups</span><span class="signature"><span class="signature-params">()</span>&nbsp;&rarr; <span class="signature-returns"> Promise containing Array of WAWebJS.ChatId</span></span></h3>
<p>Gets the Contact's common groups with you. Returns empty array if you don't have any common group.</p>
<dl class="dl-compact">
<dt>Inherited from</dt>
<dd><a href="Contact.html#getCommonGroups">Contact#getCommonGroups</a></dd>
<dt>Returns</dt>
<dd></dd>
</dl>
<div class="symbol-detail-labels"><span class="label label-async">async</span></div>
<h3 id="getCountryCode"><span class="symbol-name">getCountryCode</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 countrycode, (1541859685@c.us) =&gt; (1)</p>
<dl class="dl-compact">
<dt>Inherited from</dt>
<dd><a href="Contact.html#getCountryCode">Contact#getCountryCode</a></dd>
<dt>Returns</dt>
<dd></dd>
</dl>
<div class="symbol-detail-labels"><span class="label label-async">async</span></div>
<h3 id="getFormattedNumber"><span class="symbol-name">getFormattedNumber</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 formatted phone number, (12345678901@c.us) =&gt; (+1 (234) 5678-901)</p>
<dl class="dl-compact">
<dt>Inherited from</dt>
<dd><a href="Contact.html#getFormattedNumber">Contact#getFormattedNumber</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> <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> <p>Returns the contact's profile picture URL, if privacy settings allow it</p>
<dl class="dl-compact"> <dl class="dl-compact">
@@ -283,7 +319,7 @@
<footer id="jsdoc-footer" class="jsdoc-footer"> <footer id="jsdoc-footer" class="jsdoc-footer">
<div id="jsdoc-footer-container"> <div id="jsdoc-footer-container">
<p> <p>
Generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc</a> 3.6.6 on April 20, 2021. Generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc</a> 3.6.7 on November 26, 2022.
</p> </p>
</div> </div>
</footer> </footer>

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.18.4 &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>18.<wbr>4</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 November 26, 2022.
</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>

159
docs/Reaction.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.18.4 &raquo; Class: Reaction</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>18.<wbr>4</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">Reaction</span></h1>
<p class="source-link">Source: <a href="structures_Reaction.js.html#source-line-9">structures/<wbr>Reaction.<wbr>js:9</a></p>
<div class="symbol-classdesc">
<p>Represents a Reaction 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="Reaction.html#ack">ack</a></dt>
<dd>
</dd>
<dt><a href="Reaction.html#id">id</a></dt>
<dd>
</dd>
<dt><a href="Reaction.html#msgId">msgId</a></dt>
<dd>
</dd>
</dl>
</div>
<div class="summary-column">
<dl class="dl-summary-callout">
<dt><a href="Reaction.html#orphan">orphan</a></dt>
<dd>
</dd>
<dt><a href="Reaction.html#orphanReason">orphanReason</a></dt>
<dd>
</dd>
<dt><a href="Reaction.html#reaction">reaction</a></dt>
<dd>
</dd>
</dl>
</div>
<div class="summary-column">
<dl class="dl-summary-callout">
<dt><a href="Reaction.html#read">read</a></dt>
<dd>
</dd>
<dt><a href="Reaction.html#senderId">senderId</a></dt>
<dd>
</dd>
<dt><a href="Reaction.html#timestamp">timestamp</a></dt>
<dd>
</dd>
</dl>
</div>
</div>
</div>
</section>
<section>
<h2 id="Reaction">new&nbsp;<span class="symbol-name">Reaction</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;nullable number</small></h3>
<p>ACK</p>
<dl class="dl-compact">
</dl>
<h3 id="id"><span class="symbol-name">id</span><small class="property-type">
&nbsp;object</small></h3>
<p>Reaction ID</p>
<dl class="dl-compact">
</dl>
<h3 id="msgId"><span class="symbol-name">msgId</span><small class="property-type">
&nbsp;object</small></h3>
<p>Message ID</p>
<dl class="dl-compact">
</dl>
<h3 id="orphan"><span class="symbol-name">orphan</span><small class="property-type">
&nbsp;number</small></h3>
<p>Orphan</p>
<dl class="dl-compact">
</dl>
<h3 id="orphanReason"><span class="symbol-name">orphanReason</span><small class="property-type">
&nbsp;nullable string</small></h3>
<p>Orphan reason</p>
<dl class="dl-compact">
</dl>
<h3 id="reaction"><span class="symbol-name">reaction</span><small class="property-type">
&nbsp;string</small></h3>
<p>Reaction</p>
<dl class="dl-compact">
</dl>
<h3 id="read"><span class="symbol-name">read</span><small class="property-type">
&nbsp;boolean</small></h3>
<p>Read</p>
<dl class="dl-compact">
</dl>
<h3 id="senderId"><span class="symbol-name">senderId</span><small class="property-type">
&nbsp;string</small></h3>
<p>Sender ID</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 reaction was created</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 November 26, 2022.
</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>

163
docs/RemoteAuth.html Normal file
View File

@@ -0,0 +1,163 @@
<!doctype html>
<html>
<head>
<meta name="generator" content="JSDoc 3.6.7">
<meta charset="utf-8">
<title>whatsapp-web.js 1.18.4 &raquo; Class: RemoteAuth</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>18.<wbr>4</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">RemoteAuth</span></h1>
<p class="source-link">Source: <a href="authStrategies_RemoteAuth.js.html#source-line-26">authStrategies/<wbr>RemoteAuth.<wbr>js:26</a></p>
<div class="symbol-classdesc">
<p>Remote-based authentication</p>
</div>
<dl class="dl-compact">
</dl>
</header>
<section id="summary">
</section>
<section>
<h2 id="RemoteAuth">new&nbsp;<span class="symbol-name">RemoteAuth</span><span class="signature"><span class="signature-params">(options)</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>options</p>
</td>
<td>
<p>&nbsp;</p>
</td>
<td>
<p>&nbsp;</p>
</td>
<td>
<p>options</p>
<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>store</p>
</td>
<td>
<p>&nbsp;</p>
</td>
<td>
<p>&nbsp;</p>
</td>
<td>
<p>Remote database store instance</p>
</td>
</tr>
<tr>
<td>
<p>clientId</p>
</td>
<td>
<p>&nbsp;</p>
</td>
<td>
<p>&nbsp;</p>
</td>
<td>
<p>Client id to distinguish instances if you are using multiple, otherwise keep null if you are using only one instance</p>
</td>
</tr>
<tr>
<td>
<p>dataPath</p>
</td>
<td>
<p>&nbsp;</p>
</td>
<td>
<p>&nbsp;</p>
</td>
<td>
<p>Change the default path for saving session files, default is: &quot;./.wwebjs_auth/&quot;</p>
</td>
</tr>
<tr>
<td>
<p>backupSyncIntervalMs</p>
</td>
<td>
<p>&nbsp;</p>
</td>
<td>
<p>&nbsp;</p>
</td>
<td>
<p>Sets the time interval for periodic session backups. Accepts values starting from 60000ms {1 minute}</p>
</td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
</section>
<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 November 26, 2022.
</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

@@ -2,9 +2,9 @@
<html> <html>
<head> <head>
<meta name="generator" content="JSDoc 3.6.6"> <meta name="generator" content="JSDoc 3.6.7">
<meta charset="utf-8"> <meta charset="utf-8">
<title>whatsapp-web.js 1.12.6 &raquo; Class: Util</title> <title>whatsapp-web.js 1.18.4 &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/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/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 rel="stylesheet" href="https://brick.a.ssl.fastly.net/Inconsolata:500" type="text/css">
@@ -15,7 +15,7 @@
<nav id="jsdoc-navbar" role="navigation" class="jsdoc-navbar"> <nav id="jsdoc-navbar" role="navigation" class="jsdoc-navbar">
<div id="jsdoc-navbar-container"> <div id="jsdoc-navbar-container">
<div id="jsdoc-navbar-content"> <div id="jsdoc-navbar-content">
<a href="index.html" class="jsdoc-navbar-package-name">whatsapp-web.<wbr>js 1.<wbr>12.<wbr>6</a> <a href="index.html" class="jsdoc-navbar-package-name">whatsapp-web.<wbr>js 1.<wbr>18.<wbr>4</a>
</div> </div>
</div> </div>
</nav> </nav>
@@ -26,7 +26,7 @@
<header class="page-header"> <header class="page-header">
<div class="symbol-detail-labels"><span class="label label-kind">class</span></div> <div class="symbol-detail-labels"><span class="label label-kind">class</span></div>
<h1><small></small><span class="symbol-name">Util</span></h1> <h1><small></small><span class="symbol-name">Util</span></h1>
<p class="source-link">Source: <a href="util_Util.js.html#source-line-15">util/<wbr>Util.<wbr>js:15</a></p> <p class="source-link">Source: <a href="util_Util.js.html#source-line-14">util/<wbr>Util.<wbr>js:14</a></p>
<div class="symbol-classdesc"> <div class="symbol-classdesc">
<p>Utility methods</p> <p>Utility methods</p>
</div> </div>
@@ -42,7 +42,7 @@
<dt><a href="Util.html#.formatImageToWebpSticker">formatImageToWebpSticker(media)</a></dt> <dt><a href="Util.html#.formatImageToWebpSticker">formatImageToWebpSticker(media)</a></dt>
<dd> <dd>
</dd> </dd>
<dt><a href="Util.html#.formatToWebpSticker">formatToWebpSticker(media)</a></dt> <dt><a href="Util.html#.formatToWebpSticker">formatToWebpSticker(media, metadata)</a></dt>
<dd> <dd>
</dd> </dd>
</dl> </dl>
@@ -104,15 +104,16 @@
<dl class="dl-compact"> <dl class="dl-compact">
<dt>Returns</dt> <dt>Returns</dt>
<dd> <dd>
<p><code>Promise containing <a href="MessageMedia.html">MessageMedia</a></code> <p>media in webp format</p> <p><code>Promise containing <a href="MessageMedia.html">MessageMedia</a></code> 
<p>media in webp format</p>
</p> </p>
</dd> </dd>
</dl> </dl>
<div class="symbol-detail-labels"><span class="label label-async">async</span>&nbsp;<span class="label label-static">static</span></div> <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)</span>&nbsp;&rarr; <span class="signature-returns"> Promise containing <a href="MessageMedia.html">MessageMedia</a></span></span></h3> <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> <p>Formats a media to webp</p>
<section> <section>
<h4>Parameter</h4> <h4>Parameters</h4>
<table class="jsdoc-details-table"> <table class="jsdoc-details-table">
<thead> <thead>
<tr> <tr>
@@ -136,13 +137,27 @@
<td> <td>
</td> </td>
</tr> </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> </tbody>
</table> </table>
</section> </section>
<dl class="dl-compact"> <dl class="dl-compact">
<dt>Returns</dt> <dt>Returns</dt>
<dd> <dd>
<p><code>Promise containing <a href="MessageMedia.html">MessageMedia</a></code> <p>media in webp format</p> <p><code>Promise containing <a href="MessageMedia.html">MessageMedia</a></code> 
<p>media in webp format</p>
</p> </p>
</dd> </dd>
</dl> </dl>
@@ -180,7 +195,8 @@
<dl class="dl-compact"> <dl class="dl-compact">
<dt>Returns</dt> <dt>Returns</dt>
<dd> <dd>
<p><code>Promise containing <a href="MessageMedia.html">MessageMedia</a></code> <p>media in webp format</p> <p><code>Promise containing <a href="MessageMedia.html">MessageMedia</a></code> 
<p>media in webp format</p>
</p> </p>
</dd> </dd>
</dl> </dl>
@@ -227,7 +243,7 @@
<footer id="jsdoc-footer" class="jsdoc-footer"> <footer id="jsdoc-footer" class="jsdoc-footer">
<div id="jsdoc-footer-container"> <div id="jsdoc-footer-container">
<p> <p>
Generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc</a> 3.6.6 on April 20, 2021. Generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc</a> 3.6.7 on November 26, 2022.
</p> </p>
</div> </div>
</footer> </footer>

View File

@@ -0,0 +1,80 @@
<!doctype html>
<html>
<head>
<meta name="generator" content="JSDoc 3.6.7">
<meta charset="utf-8">
<title>whatsapp-web.js 1.18.4 &raquo; Source: authStrategies/BaseAuthStrategy.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>18.<wbr>4</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: authStrategies/BaseAuthStrategy.js</h1>
</header>
<article>
<pre class="prettyprint linenums"><code>&#x27;use strict&#x27;;
/**
* Base class which all authentication strategies extend
*/
class BaseAuthStrategy {
constructor() {}
setup(client) {
this.client &#x3D; client;
}
async beforeBrowserInitialized() {}
async afterBrowserInitialized() {}
async onAuthenticationNeeded() {
return {
failed: false,
restart: false,
failureEventPayload: undefined
};
}
async getAuthEventPayload() {}
async afterAuthReady() {}
async disconnect() {}
async destroy() {}
async logout() {}
}
module.exports &#x3D; BaseAuthStrategy;</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 November 26, 2022.
</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,126 @@
<!doctype html>
<html>
<head>
<meta name="generator" content="JSDoc 3.6.7">
<meta charset="utf-8">
<title>whatsapp-web.js 1.18.4 &raquo; Source: authStrategies/LegacySessionAuth.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>18.<wbr>4</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: authStrategies/LegacySessionAuth.js</h1>
</header>
<article>
<pre class="prettyprint linenums"><code>&#x27;use strict&#x27;;
const BaseAuthStrategy &#x3D; require(&#x27;./BaseAuthStrategy&#x27;);
/**
* Legacy session auth strategy
* Not compatible with multi-device accounts.
* @param {object} options - options
* @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
*/
class LegacySessionAuth extends BaseAuthStrategy {
constructor({ session, restartOnAuthFail }&#x3D;{}) {
super();
this.session &#x3D; session;
this.restartOnAuthFail &#x3D; restartOnAuthFail;
}
async afterBrowserInitialized() {
if(this.session) {
await this.client.pupPage.evaluateOnNewDocument(session &#x3D;&gt; {
if (document.referrer &#x3D;&#x3D;&#x3D; &#x27;https://whatsapp.com/&#x27;) {
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);
}
localStorage.setItem(&#x27;remember-me&#x27;, &#x27;true&#x27;);
}, this.session);
}
}
async onAuthenticationNeeded() {
if(this.session) {
this.session &#x3D; null;
return {
failed: true,
restart: this.restartOnAuthFail,
failureEventPayload: &#x27;Unable to log in. Are the session details valid?&#x27;
};
}
return { failed: false };
}
async getAuthEventPayload() {
const isMD &#x3D; await this.client.pupPage.evaluate(() &#x3D;&gt; {
return window.Store.MDBackend;
});
if(isMD) throw new Error(&#x27;Authenticating via JSON session is not supported for MultiDevice-enabled WhatsApp accounts.&#x27;);
const localStorage &#x3D; JSON.parse(await this.client.pupPage.evaluate(() &#x3D;&gt; {
return JSON.stringify(window.localStorage);
}));
return {
WABrowserId: localStorage.WABrowserId,
WASecretBundle: localStorage.WASecretBundle,
WAToken1: localStorage.WAToken1,
WAToken2: localStorage.WAToken2
};
}
}
module.exports &#x3D; LegacySessionAuth;
</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 November 26, 2022.
</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,106 @@
<!doctype html>
<html>
<head>
<meta name="generator" content="JSDoc 3.6.7">
<meta charset="utf-8">
<title>whatsapp-web.js 1.18.4 &raquo; Source: authStrategies/LocalAuth.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>18.<wbr>4</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: authStrategies/LocalAuth.js</h1>
</header>
<article>
<pre class="prettyprint linenums"><code>&#x27;use strict&#x27;;
const path &#x3D; require(&#x27;path&#x27;);
const fs &#x3D; require(&#x27;fs&#x27;);
const BaseAuthStrategy &#x3D; require(&#x27;./BaseAuthStrategy&#x27;);
/**
* Local directory-based authentication
* @param {object} options - options
* @param {string} options.clientId - Client id to distinguish instances if you are using multiple, otherwise keep null if you are using only one instance
* @param {string} options.dataPath - Change the default path for saving session files, default is: &quot;./.wwebjs_auth/&quot;
*/
class LocalAuth extends BaseAuthStrategy {
constructor({ clientId, dataPath }&#x3D;{}) {
super();
const idRegex &#x3D; /^[-_\w]+$/i;
if(clientId &amp;amp;&amp;amp; !idRegex.test(clientId)) {
throw new Error(&#x27;Invalid clientId. Only alphanumeric characters, underscores and hyphens are allowed.&#x27;);
}
this.dataPath &#x3D; path.resolve(dataPath || &#x27;./.wwebjs_auth/&#x27;);
this.clientId &#x3D; clientId;
}
async beforeBrowserInitialized() {
const puppeteerOpts &#x3D; this.client.options.puppeteer;
const sessionDirName &#x3D; this.clientId ? &#x60;session-${this.clientId}&#x60; : &#x27;session&#x27;;
const dirPath &#x3D; path.join(this.dataPath, sessionDirName);
if(puppeteerOpts.userDataDir &amp;amp;&amp;amp; puppeteerOpts.userDataDir !&#x3D;&#x3D; dirPath) {
throw new Error(&#x27;LocalAuth is not compatible with a user-supplied userDataDir.&#x27;);
}
fs.mkdirSync(dirPath, { recursive: true });
this.client.options.puppeteer &#x3D; {
...puppeteerOpts,
userDataDir: dirPath
};
this.userDataDir &#x3D; dirPath;
}
async logout() {
if (this.userDataDir) {
return (fs.rmSync ? fs.rmSync : fs.rmdirSync).call(this, this.userDataDir, { recursive: true });
}
}
}
module.exports &#x3D; LocalAuth;</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 November 26, 2022.
</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,65 @@
<!doctype html>
<html>
<head>
<meta name="generator" content="JSDoc 3.6.7">
<meta charset="utf-8">
<title>whatsapp-web.js 1.18.4 &raquo; Source: authStrategies/NoAuth.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>18.<wbr>4</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: authStrategies/NoAuth.js</h1>
</header>
<article>
<pre class="prettyprint linenums"><code>&#x27;use strict&#x27;;
const BaseAuthStrategy &#x3D; require(&#x27;./BaseAuthStrategy&#x27;);
/**
* No session restoring functionality
* Will need to authenticate via QR code every time
*/
class NoAuth extends BaseAuthStrategy { }
module.exports &#x3D; NoAuth;</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 November 26, 2022.
</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,258 @@
<!doctype html>
<html>
<head>
<meta name="generator" content="JSDoc 3.6.7">
<meta charset="utf-8">
<title>whatsapp-web.js 1.18.4 &raquo; Source: authStrategies/RemoteAuth.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>18.<wbr>4</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: authStrategies/RemoteAuth.js</h1>
</header>
<article>
<pre class="prettyprint linenums"><code>&#x27;use strict&#x27;;
/* Require Optional Dependencies */
try {
var fs &#x3D; require(&#x27;fs-extra&#x27;);
var unzipper &#x3D; require(&#x27;unzipper&#x27;);
var archiver &#x3D; require(&#x27;archiver&#x27;);
} catch {
fs &#x3D; undefined;
unzipper &#x3D; undefined;
archiver &#x3D; undefined;
}
const path &#x3D; require(&#x27;path&#x27;);
const { Events } &#x3D; require(&#x27;./../util/Constants&#x27;);
const BaseAuthStrategy &#x3D; require(&#x27;./BaseAuthStrategy&#x27;);
/**
* Remote-based authentication
* @param {object} options - options
* @param {object} options.store - Remote database store instance
* @param {string} options.clientId - Client id to distinguish instances if you are using multiple, otherwise keep null if you are using only one instance
* @param {string} options.dataPath - Change the default path for saving session files, default is: &quot;./.wwebjs_auth/&quot;
* @param {number} options.backupSyncIntervalMs - Sets the time interval for periodic session backups. Accepts values starting from 60000ms {1 minute}
*/
class RemoteAuth extends BaseAuthStrategy {
constructor({ clientId, dataPath, store, backupSyncIntervalMs } &#x3D; {}) {
if (!fs &amp;amp;&amp;amp; !unzipper &amp;amp;&amp;amp; !archiver) throw new Error(&#x27;Optional Dependencies [fs-extra, unzipper, archiver] are required to use RemoteAuth. Make sure to run npm install correctly and remove the --no-optional flag&#x27;);
super();
const idRegex &#x3D; /^[-_\w]+$/i;
if (clientId &amp;amp;&amp;amp; !idRegex.test(clientId)) {
throw new Error(&#x27;Invalid clientId. Only alphanumeric characters, underscores and hyphens are allowed.&#x27;);
}
if (!backupSyncIntervalMs || backupSyncIntervalMs &amp;lt; 60000) {
throw new Error(&#x27;Invalid backupSyncIntervalMs. Accepts values starting from 60000ms {1 minute}.&#x27;);
}
if(!store) throw new Error(&#x27;Remote database store is required.&#x27;);
this.store &#x3D; store;
this.clientId &#x3D; clientId;
this.backupSyncIntervalMs &#x3D; backupSyncIntervalMs;
this.dataPath &#x3D; path.resolve(dataPath || &#x27;./.wwebjs_auth/&#x27;);
this.tempDir &#x3D; &#x60;${this.dataPath}/wwebjs_temp_session&#x60;;
this.requiredDirs &#x3D; [&#x27;Default&#x27;, &#x27;IndexedDB&#x27;, &#x27;Local Storage&#x27;]; /* &#x3D;&gt; Required Files &amp;amp; Dirs in WWebJS to restore session */
}
async beforeBrowserInitialized() {
const puppeteerOpts &#x3D; this.client.options.puppeteer;
const sessionDirName &#x3D; this.clientId ? &#x60;RemoteAuth-${this.clientId}&#x60; : &#x27;RemoteAuth&#x27;;
const dirPath &#x3D; path.join(this.dataPath, sessionDirName);
if (puppeteerOpts.userDataDir &amp;amp;&amp;amp; puppeteerOpts.userDataDir !&#x3D;&#x3D; dirPath) {
throw new Error(&#x27;RemoteAuth is not compatible with a user-supplied userDataDir.&#x27;);
}
this.userDataDir &#x3D; dirPath;
this.sessionName &#x3D; sessionDirName;
await this.extractRemoteSession();
this.client.options.puppeteer &#x3D; {
...puppeteerOpts,
userDataDir: dirPath
};
}
async logout() {
await this.disconnect();
}
async destroy() {
clearInterval(this.backupSync);
}
async disconnect() {
await this.deleteRemoteSession();
let pathExists &#x3D; await this.isValidPath(this.userDataDir);
if (pathExists) {
await fs.promises.rm(this.userDataDir, {
recursive: true,
force: true
}).catch(() &#x3D;&gt; {});
}
clearInterval(this.backupSync);
}
async afterAuthReady() {
const sessionExists &#x3D; await this.store.sessionExists({session: this.sessionName});
if(!sessionExists) {
await this.delay(60000); /* Initial delay sync required for session to be stable enough to recover */
await this.storeRemoteSession({emit: true});
}
var self &#x3D; this;
this.backupSync &#x3D; setInterval(async function () {
await self.storeRemoteSession();
}, this.backupSyncIntervalMs);
}
async storeRemoteSession(options) {
/* Compress &amp;amp; Store Session */
const pathExists &#x3D; await this.isValidPath(this.userDataDir);
if (pathExists) {
await this.compressSession();
await this.store.save({session: this.sessionName});
await fs.promises.unlink(&#x60;${this.sessionName}.zip&#x60;);
await fs.promises.rm(&#x60;${this.tempDir}&#x60;, {
recursive: true,
force: true
}).catch(() &#x3D;&gt; {});
if(options &amp;amp;&amp;amp; options.emit) this.client.emit(Events.REMOTE_SESSION_SAVED);
}
}
async extractRemoteSession() {
const pathExists &#x3D; await this.isValidPath(this.userDataDir);
const compressedSessionPath &#x3D; &#x60;${this.sessionName}.zip&#x60;;
const sessionExists &#x3D; await this.store.sessionExists({session: this.sessionName});
if (pathExists) {
await fs.promises.rm(this.userDataDir, {
recursive: true,
force: true
}).catch(() &#x3D;&gt; {});
}
if (sessionExists) {
await this.store.extract({session: this.sessionName, path: compressedSessionPath});
await this.unCompressSession(compressedSessionPath);
} else {
fs.mkdirSync(this.userDataDir, { recursive: true });
}
}
async deleteRemoteSession() {
const sessionExists &#x3D; await this.store.sessionExists({session: this.sessionName});
if (sessionExists) await this.store.delete({session: this.sessionName});
}
async compressSession() {
const archive &#x3D; archiver(&#x27;zip&#x27;);
const stream &#x3D; fs.createWriteStream(&#x60;${this.sessionName}.zip&#x60;);
await fs.copy(this.userDataDir, this.tempDir).catch(() &#x3D;&gt; {});
await this.deleteMetadata();
return new Promise((resolve, reject) &#x3D;&gt; {
archive
.directory(this.tempDir, false)
.on(&#x27;error&#x27;, err &#x3D;&gt; reject(err))
.pipe(stream);
stream.on(&#x27;close&#x27;, () &#x3D;&gt; resolve());
archive.finalize();
});
}
async unCompressSession(compressedSessionPath) {
var stream &#x3D; fs.createReadStream(compressedSessionPath);
await new Promise((resolve, reject) &#x3D;&gt; {
stream.pipe(unzipper.Extract({
path: this.userDataDir
}))
.on(&#x27;error&#x27;, err &#x3D;&gt; reject(err))
.on(&#x27;finish&#x27;, () &#x3D;&gt; resolve());
});
await fs.promises.unlink(compressedSessionPath);
}
async deleteMetadata() {
const sessionDirs &#x3D; [this.tempDir, path.join(this.tempDir, &#x27;Default&#x27;)];
for (const dir of sessionDirs) {
const sessionFiles &#x3D; await fs.promises.readdir(dir);
for (const element of sessionFiles) {
if (!this.requiredDirs.includes(element)) {
const dirElement &#x3D; path.join(dir, element);
const stats &#x3D; await fs.promises.lstat(dirElement);
if (stats.isDirectory()) {
await fs.promises.rm(dirElement, {
recursive: true,
force: true
}).catch(() &#x3D;&gt; {});
} else {
await fs.promises.unlink(dirElement).catch(() &#x3D;&gt; {});
}
}
}
}
}
async isValidPath(path) {
try {
await fs.promises.access(path);
return true;
} catch {
return false;
}
}
async delay(ms) {
return new Promise(resolve &#x3D;&gt; setTimeout(resolve, ms));
}
}
module.exports &#x3D; RemoteAuth;
</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 November 26, 2022.
</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

@@ -2,9 +2,9 @@
<html> <html>
<head> <head>
<meta name="generator" content="JSDoc 3.6.6"> <meta name="generator" content="JSDoc 3.6.7">
<meta charset="utf-8"> <meta charset="utf-8">
<title>whatsapp-web.js 1.12.6 &raquo; Globals</title> <title>whatsapp-web.js 1.18.4 &raquo; Globals</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/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/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 rel="stylesheet" href="https://brick.a.ssl.fastly.net/Inconsolata:500" type="text/css">
@@ -15,7 +15,7 @@
<nav id="jsdoc-navbar" role="navigation" class="jsdoc-navbar"> <nav id="jsdoc-navbar" role="navigation" class="jsdoc-navbar">
<div id="jsdoc-navbar-container"> <div id="jsdoc-navbar-container">
<div id="jsdoc-navbar-content"> <div id="jsdoc-navbar-content">
<a href="index.html" class="jsdoc-navbar-package-name">whatsapp-web.<wbr>js 1.<wbr>12.<wbr>6</a> <a href="index.html" class="jsdoc-navbar-package-name">whatsapp-web.<wbr>js 1.<wbr>18.<wbr>4</a>
</div> </div>
</div> </div>
</nav> </nav>
@@ -68,16 +68,22 @@
<div class="summary-content"> <div class="summary-content">
<div class="summary-column"> <div class="summary-column">
<dl class="dl-summary-callout"> <dl class="dl-summary-callout">
<dt><a href="global.html#ButtonSpec">ButtonSpec</a></dt>
<dd>
</dd>
<dt><a href="global.html#ContactId">ContactId</a></dt> <dt><a href="global.html#ContactId">ContactId</a></dt>
<dd> <dd>
</dd> </dd>
<dt><a href="global.html#GroupParticipant">GroupParticipant</a></dt> <dt><a href="global.html#FormattedButtonSpec">FormattedButtonSpec</a></dt>
<dd> <dd>
</dd> </dd>
</dl> </dl>
</div> </div>
<div class="summary-column"> <div class="summary-column">
<dl class="dl-summary-callout"> <dl class="dl-summary-callout">
<dt><a href="global.html#GroupParticipant">GroupParticipant</a></dt>
<dd>
</dd>
<dt><a href="global.html#MessageInfo">MessageInfo</a></dt> <dt><a href="global.html#MessageInfo">MessageInfo</a></dt>
<dd> <dd>
</dd> </dd>
@@ -87,6 +93,11 @@
</dl> </dl>
</div> </div>
<div class="summary-column"> <div class="summary-column">
<dl class="dl-summary-callout">
<dt><a href="global.html#StickerMetadata">StickerMetadata</a></dt>
<dd>
</dd>
</dl>
</div> </div>
</div> </div>
</div> </div>
@@ -274,6 +285,19 @@
<td> <td>
</td> </td>
</tr> </tr>
<tr>
<td>
<p>MESSAGE_REACTION</p>
</td>
<td>
<p>&nbsp;</p>
</td>
<td>
<p>&nbsp;</p>
</td>
<td>
</td>
</tr>
<tr> <tr>
<td> <td>
<p>MEDIA_UPLOADED</p> <p>MEDIA_UPLOADED</p>
@@ -339,6 +363,19 @@
<td> <td>
</td> </td>
</tr> </tr>
<tr>
<td>
<p>LOADING_SCREEN</p>
</td>
<td>
<p>&nbsp;</p>
</td>
<td>
<p>&nbsp;</p>
</td>
<td>
</td>
</tr>
<tr> <tr>
<td> <td>
<p>DISCONNECTED</p> <p>DISCONNECTED</p>
@@ -378,6 +415,32 @@
<td> <td>
</td> </td>
</tr> </tr>
<tr>
<td>
<p>INCOMING_CALL</p>
</td>
<td>
<p>&nbsp;</p>
</td>
<td>
<p>&nbsp;</p>
</td>
<td>
</td>
</tr>
<tr>
<td>
<p>REMOTE_SESSION_SAVED</p>
</td>
<td>
<p>&nbsp;</p>
</td>
<td>
<p>&nbsp;</p>
</td>
<td>
</td>
</tr>
</tbody> </tbody>
</table> </table>
</section> </section>
@@ -766,6 +829,19 @@
<td> <td>
</td> </td>
</tr> </tr>
<tr>
<td>
<p>ORDER</p>
</td>
<td>
<p>&nbsp;</p>
</td>
<td>
<p>&nbsp;</p>
</td>
<td>
</td>
</tr>
<tr> <tr>
<td> <td>
<p>REVOKED</p> <p>REVOKED</p>
@@ -779,6 +855,19 @@
<td> <td>
</td> </td>
</tr> </tr>
<tr>
<td>
<p>PRODUCT</p>
</td>
<td>
<p>&nbsp;</p>
</td>
<td>
<p>&nbsp;</p>
</td>
<td>
</td>
</tr>
<tr> <tr>
<td> <td>
<p>UNKNOWN</p> <p>UNKNOWN</p>
@@ -792,6 +881,279 @@
<td> <td>
</td> </td>
</tr> </tr>
<tr>
<td>
<p>GROUP_INVITE</p>
</td>
<td>
<p>&nbsp;</p>
</td>
<td>
<p>&nbsp;</p>
</td>
<td>
</td>
</tr>
<tr>
<td>
<p>LIST</p>
</td>
<td>
<p>&nbsp;</p>
</td>
<td>
<p>&nbsp;</p>
</td>
<td>
</td>
</tr>
<tr>
<td>
<p>LIST_RESPONSE</p>
</td>
<td>
<p>&nbsp;</p>
</td>
<td>
<p>&nbsp;</p>
</td>
<td>
</td>
</tr>
<tr>
<td>
<p>BUTTONS_RESPONSE</p>
</td>
<td>
<p>&nbsp;</p>
</td>
<td>
<p>&nbsp;</p>
</td>
<td>
</td>
</tr>
<tr>
<td>
<p>PAYMENT</p>
</td>
<td>
<p>&nbsp;</p>
</td>
<td>
<p>&nbsp;</p>
</td>
<td>
</td>
</tr>
<tr>
<td>
<p>BROADCAST_NOTIFICATION</p>
</td>
<td>
<p>&nbsp;</p>
</td>
<td>
<p>&nbsp;</p>
</td>
<td>
</td>
</tr>
<tr>
<td>
<p>CALL_LOG</p>
</td>
<td>
<p>&nbsp;</p>
</td>
<td>
<p>&nbsp;</p>
</td>
<td>
</td>
</tr>
<tr>
<td>
<p>CIPHERTEXT</p>
</td>
<td>
<p>&nbsp;</p>
</td>
<td>
<p>&nbsp;</p>
</td>
<td>
</td>
</tr>
<tr>
<td>
<p>DEBUG</p>
</td>
<td>
<p>&nbsp;</p>
</td>
<td>
<p>&nbsp;</p>
</td>
<td>
</td>
</tr>
<tr>
<td>
<p>E2E_NOTIFICATION</p>
</td>
<td>
<p>&nbsp;</p>
</td>
<td>
<p>&nbsp;</p>
</td>
<td>
</td>
</tr>
<tr>
<td>
<p>GP2</p>
</td>
<td>
<p>&nbsp;</p>
</td>
<td>
<p>&nbsp;</p>
</td>
<td>
</td>
</tr>
<tr>
<td>
<p>GROUP_NOTIFICATION</p>
</td>
<td>
<p>&nbsp;</p>
</td>
<td>
<p>&nbsp;</p>
</td>
<td>
</td>
</tr>
<tr>
<td>
<p>HSM</p>
</td>
<td>
<p>&nbsp;</p>
</td>
<td>
<p>&nbsp;</p>
</td>
<td>
</td>
</tr>
<tr>
<td>
<p>INTERACTIVE</p>
</td>
<td>
<p>&nbsp;</p>
</td>
<td>
<p>&nbsp;</p>
</td>
<td>
</td>
</tr>
<tr>
<td>
<p>NATIVE_FLOW</p>
</td>
<td>
<p>&nbsp;</p>
</td>
<td>
<p>&nbsp;</p>
</td>
<td>
</td>
</tr>
<tr>
<td>
<p>NOTIFICATION</p>
</td>
<td>
<p>&nbsp;</p>
</td>
<td>
<p>&nbsp;</p>
</td>
<td>
</td>
</tr>
<tr>
<td>
<p>NOTIFICATION_TEMPLATE</p>
</td>
<td>
<p>&nbsp;</p>
</td>
<td>
<p>&nbsp;</p>
</td>
<td>
</td>
</tr>
<tr>
<td>
<p>OVERSIZED</p>
</td>
<td>
<p>&nbsp;</p>
</td>
<td>
<p>&nbsp;</p>
</td>
<td>
</td>
</tr>
<tr>
<td>
<p>PROTOCOL</p>
</td>
<td>
<p>&nbsp;</p>
</td>
<td>
<p>&nbsp;</p>
</td>
<td>
</td>
</tr>
<tr>
<td>
<p>REACTION</p>
</td>
<td>
<p>&nbsp;</p>
</td>
<td>
<p>&nbsp;</p>
</td>
<td>
</td>
</tr>
<tr>
<td>
<p>TEMPLATE_BUTTON_REPLY</p>
</td>
<td>
<p>&nbsp;</p>
</td>
<td>
<p>&nbsp;</p>
</td>
<td>
</td>
</tr>
</tbody> </tbody>
</table> </table>
</section> </section>
@@ -1037,6 +1399,54 @@
</section> </section>
<h2>Abstract types</h2> <h2>Abstract types</h2>
<section> <section>
<h3 id="ButtonSpec"><span class="symbol-name">ButtonSpec</span><small class="property-type">
&nbsp;Object</small></h3>
<p>Button spec used in Buttons constructor</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>id</p>
</td>
<td>
<p>string</p>
</td>
<td>
<p>Yes</p>
</td>
<td>
<p>Custom ID to set on the button. A random one will be generated if one is not passed.</p>
</td>
</tr>
<tr>
<td>
<p>body</p>
</td>
<td>
<p>string</p>
</td>
<td>
<p>&nbsp;</p>
</td>
<td>
<p>The text to show on the button.</p>
</td>
</tr>
</tbody>
</table>
</section>
<dl class="dl-compact">
</dl>
<h3 id="ContactId"><span class="symbol-name">ContactId</span><small class="property-type"> <h3 id="ContactId"><span class="symbol-name">ContactId</span><small class="property-type">
&nbsp;Object</small></h3> &nbsp;Object</small></h3>
<p>ID that represents a contact</p> <p>ID that represents a contact</p>
@@ -1096,6 +1506,64 @@
</section> </section>
<dl class="dl-compact"> <dl class="dl-compact">
</dl> </dl>
<h3 id="FormattedButtonSpec"><span class="symbol-name">FormattedButtonSpec</span><small class="property-type">
&nbsp;Object</small></h3>
<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>buttonId</p>
</td>
<td>
<p>string</p>
</td>
<td>
<p>&nbsp;</p>
</td>
<td>
</td>
</tr>
<tr>
<td>
<p>type</p>
</td>
<td>
<p>number</p>
</td>
<td>
<p>&nbsp;</p>
</td>
<td>
</td>
</tr>
<tr>
<td>
<p>buttonText</p>
</td>
<td>
<p>Object</p>
</td>
<td>
<p>&nbsp;</p>
</td>
<td>
</td>
</tr>
</tbody>
</table>
</section>
<dl class="dl-compact">
</dl>
<h3 id="GroupParticipant"><span class="symbol-name">GroupParticipant</span><small class="property-type"> <h3 id="GroupParticipant"><span class="symbol-name">GroupParticipant</span><small class="property-type">
&nbsp;Object</small></h3> &nbsp;Object</small></h3>
<p>Group participant information</p> <p>Group participant information</p>
@@ -1285,7 +1753,7 @@
<p>Yes</p> <p>Yes</p>
</td> </td>
<td> <td>
<p>Show links preview</p> <p>Show links preview. Has no effect on multi-device accounts.</p>
<p>Defaults to <code>true</code>.</p> <p>Defaults to <code>true</code>.</p>
</td> </td>
</tr> </tr>
@@ -1304,6 +1772,21 @@
<p>Defaults to <code>false</code>.</p> <p>Defaults to <code>false</code>.</p>
</td> </td>
</tr> </tr>
<tr>
<td>
<p>sendVideoAsGif</p>
</td>
<td>
<p>boolean</p>
</td>
<td>
<p>Yes</p>
</td>
<td>
<p>Send video as gif</p>
<p>Defaults to <code>false</code>.</p>
</td>
</tr>
<tr> <tr>
<td> <td>
<p>sendMediaAsSticker</p> <p>sendMediaAsSticker</p>
@@ -1406,6 +1889,48 @@
<p>Defaults to <code>true</code>.</p> <p>Defaults to <code>true</code>.</p>
</td> </td>
</tr> </tr>
<tr>
<td>
<p>stickerAuthor</p>
</td>
<td>
<p>string</p>
</td>
<td>
<p>Yes</p>
</td>
<td>
<p>Sets the author of the sticker, (if sendMediaAsSticker is true).</p>
</td>
</tr>
<tr>
<td>
<p>stickerName</p>
</td>
<td>
<p>string</p>
</td>
<td>
<p>Yes</p>
</td>
<td>
<p>Sets the name of the sticker, (if sendMediaAsSticker is true).</p>
</td>
</tr>
<tr>
<td>
<p>stickerCategories</p>
</td>
<td>
<p>Array of string</p>
</td>
<td>
<p>Yes</p>
</td>
<td>
<p>Sets the categories of the sticker, (if sendMediaAsSticker is true). Provide emoji char array, can be null.</p>
</td>
</tr>
<tr> <tr>
<td> <td>
<p>media</p> <p>media</p>
@@ -1425,6 +1950,65 @@
</section> </section>
<dl class="dl-compact"> <dl class="dl-compact">
</dl> </dl>
<h3 id="StickerMetadata"><span class="symbol-name">StickerMetadata</span><small class="property-type">
&nbsp;Object</small></h3>
<p>Sticker metadata.</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>name</p>
</td>
<td>
<p>string</p>
</td>
<td>
<p>Yes</p>
</td>
<td>
</td>
</tr>
<tr>
<td>
<p>author</p>
</td>
<td>
<p>string</p>
</td>
<td>
<p>Yes</p>
</td>
<td>
</td>
</tr>
<tr>
<td>
<p>categories</p>
</td>
<td>
<p>Array of string</p>
</td>
<td>
<p>Yes</p>
</td>
<td>
</td>
</tr>
</tbody>
</table>
</section>
<dl class="dl-compact">
</dl>
</section> </section>
</section> </section>
</div> </div>
@@ -1435,7 +2019,7 @@
<footer id="jsdoc-footer" class="jsdoc-footer"> <footer id="jsdoc-footer" class="jsdoc-footer">
<div id="jsdoc-footer-container"> <div id="jsdoc-footer-container">
<p> <p>
Generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc</a> 3.6.6 on April 20, 2021. Generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc</a> 3.6.7 on November 26, 2022.
</p> </p>
</div> </div>
</footer> </footer>

File diff suppressed because it is too large Load Diff

View File

@@ -6,7 +6,7 @@
treeNode.tree({ treeNode.tree({
autoEscape: false, autoEscape: false,
closedIcon: '&#x21e2;', 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=\"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=\"PrivateChat.html\">PrivateChat</a>","id":"PrivateChat","children":[]},{"label":"<a href=\"PrivateContact.html\">PrivateContact</a>","id":"PrivateContact","children":[]},{"label":"<a href=\"Util.html\">Util</a>","id":"Util","children":[]}], data: [{"label":"<a href=\"global.html\">Globals</a>","id":"global","children":[]},{"label":"<a href=\"Base.html\">Base</a>","id":"Base","children":[]},{"label":"<a href=\"BaseAuthStrategy.html\">BaseAuthStrategy</a>","id":"BaseAuthStrategy","children":[]},{"label":"<a href=\"BusinessContact.html\">BusinessContact</a>","id":"BusinessContact","children":[]},{"label":"<a href=\"Buttons.html\">Buttons</a>","id":"Buttons","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=\"LegacySessionAuth.html\">LegacySessionAuth</a>","id":"LegacySessionAuth","children":[]},{"label":"<a href=\"List.html\">List</a>","id":"List","children":[]},{"label":"<a href=\"LocalAuth.html\">LocalAuth</a>","id":"LocalAuth","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=\"NoAuth.html\">NoAuth</a>","id":"NoAuth","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=\"Reaction.html\">Reaction</a>","id":"Reaction","children":[]},{"label":"<a href=\"RemoteAuth.html\">RemoteAuth</a>","id":"RemoteAuth","children":[]},{"label":"<a href=\"Util.html\">Util</a>","id":"Util","children":[]}],
openedIcon: ' &#x21e3;', openedIcon: ' &#x21e3;',
saveState: false, saveState: false,
useContextMenu: false useContextMenu: false

View File

@@ -2,9 +2,9 @@
<html> <html>
<head> <head>
<meta name="generator" content="JSDoc 3.6.6"> <meta name="generator" content="JSDoc 3.6.7">
<meta charset="utf-8"> <meta charset="utf-8">
<title>whatsapp-web.js 1.12.6 &raquo; Source: structures/Base.js</title> <title>whatsapp-web.js 1.18.4 &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/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/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 rel="stylesheet" href="https://brick.a.ssl.fastly.net/Inconsolata:500" type="text/css">
@@ -15,7 +15,7 @@
<nav id="jsdoc-navbar" role="navigation" class="jsdoc-navbar"> <nav id="jsdoc-navbar" role="navigation" class="jsdoc-navbar">
<div id="jsdoc-navbar-container"> <div id="jsdoc-navbar-container">
<div id="jsdoc-navbar-content"> <div id="jsdoc-navbar-content">
<a href="index.html" class="jsdoc-navbar-package-name">whatsapp-web.<wbr>js 1.<wbr>12.<wbr>6</a> <a href="index.html" class="jsdoc-navbar-package-name">whatsapp-web.<wbr>js 1.<wbr>18.<wbr>4</a>
</div> </div>
</div> </div>
</nav> </nav>
@@ -60,7 +60,7 @@ module.exports &#x3D; Base;</code></pre>
<footer id="jsdoc-footer" class="jsdoc-footer"> <footer id="jsdoc-footer" class="jsdoc-footer">
<div id="jsdoc-footer-container"> <div id="jsdoc-footer-container">
<p> <p>
Generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc</a> 3.6.6 on April 20, 2021. Generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc</a> 3.6.7 on November 26, 2022.
</p> </p>
</div> </div>
</footer> </footer>

View File

@@ -2,9 +2,9 @@
<html> <html>
<head> <head>
<meta name="generator" content="JSDoc 3.6.6"> <meta name="generator" content="JSDoc 3.6.7">
<meta charset="utf-8"> <meta charset="utf-8">
<title>whatsapp-web.js 1.12.6 &raquo; Source: structures/BusinessContact.js</title> <title>whatsapp-web.js 1.18.4 &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/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/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 rel="stylesheet" href="https://brick.a.ssl.fastly.net/Inconsolata:500" type="text/css">
@@ -15,7 +15,7 @@
<nav id="jsdoc-navbar" role="navigation" class="jsdoc-navbar"> <nav id="jsdoc-navbar" role="navigation" class="jsdoc-navbar">
<div id="jsdoc-navbar-container"> <div id="jsdoc-navbar-container">
<div id="jsdoc-navbar-content"> <div id="jsdoc-navbar-content">
<a href="index.html" class="jsdoc-navbar-package-name">whatsapp-web.<wbr>js 1.<wbr>12.<wbr>6</a> <a href="index.html" class="jsdoc-navbar-package-name">whatsapp-web.<wbr>js 1.<wbr>18.<wbr>4</a>
</div> </div>
</div> </div>
</nav> </nav>
@@ -59,7 +59,7 @@ module.exports &#x3D; BusinessContact;</code></pre>
<footer id="jsdoc-footer" class="jsdoc-footer"> <footer id="jsdoc-footer" class="jsdoc-footer">
<div id="jsdoc-footer-container"> <div id="jsdoc-footer-container">
<p> <p>
Generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc</a> 3.6.6 on April 20, 2021. Generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc</a> 3.6.7 on November 26, 2022.
</p> </p>
</div> </div>
</footer> </footer>

View File

@@ -0,0 +1,135 @@
<!doctype html>
<html>
<head>
<meta name="generator" content="JSDoc 3.6.7">
<meta charset="utf-8">
<title>whatsapp-web.js 1.18.4 &raquo; Source: structures/Buttons.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>18.<wbr>4</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/Buttons.js</h1>
</header>
<article>
<pre class="prettyprint linenums"><code>&#x27;use strict&#x27;;
const MessageMedia &#x3D; require(&#x27;./MessageMedia&#x27;);
const Util &#x3D; require(&#x27;../util/Util&#x27;);
/**
* Button spec used in Buttons constructor
* @typedef {Object} ButtonSpec
* @property {string&#x3D;} id - Custom ID to set on the button. A random one will be generated if one is not passed.
* @property {string} body - The text to show on the button.
*/
/**
* @typedef {Object} FormattedButtonSpec
* @property {string} buttonId
* @property {number} type
* @property {Object} buttonText
*/
/**
* Message type buttons
*/
class Buttons {
/**
* @param {string|MessageMedia} body
* @param {ButtonSpec[]} buttons - See {@link ButtonSpec}
* @param {string?} title
* @param {string?} footer
*/
constructor(body, buttons, title, footer) {
/**
* Message body
* @type {string|MessageMedia}
*/
this.body &#x3D; body;
/**
* title of message
* @type {string}
*/
this.title &#x3D; title;
/**
* footer of message
* @type {string}
*/
this.footer &#x3D; footer;
if (body instanceof MessageMedia) {
this.type &#x3D; &#x27;media&#x27;;
this.title &#x3D; &#x27;&#x27;;
}else{
this.type &#x3D; &#x27;chat&#x27;;
}
/**
* buttons of message
* @type {FormattedButtonSpec[]}
*/
this.buttons &#x3D; this._format(buttons);
if(!this.buttons.length){ throw &#x27;[BT01] No buttons&#x27;;}
}
/**
* Creates button array from simple array
* @param {ButtonSpec[]} buttons
* @returns {FormattedButtonSpec[]}
* @example
* Input: [{id:&#x27;customId&#x27;,body:&#x27;button1&#x27;},{body:&#x27;button2&#x27;},{body:&#x27;button3&#x27;},{body:&#x27;button4&#x27;}]
* Returns: [{ buttonId:&#x27;customId&#x27;,buttonText:{&#x27;displayText&#x27;:&#x27;button1&#x27;},type: 1 },{buttonId:&#x27;n3XKsL&#x27;,buttonText:{&#x27;displayText&#x27;:&#x27;button2&#x27;},type:1},{buttonId:&#x27;NDJk0a&#x27;,buttonText:{&#x27;displayText&#x27;:&#x27;button3&#x27;},type:1}]
*/
_format(buttons){
buttons &#x3D; buttons.slice(0,3); // phone users can only see 3 buttons, so lets limit this
return buttons.map((btn) &#x3D;&gt; {
return {&#x27;buttonId&#x27;:btn.id ? String(btn.id) : Util.generateHash(6),&#x27;buttonText&#x27;:{&#x27;displayText&#x27;:btn.body},&#x27;type&#x27;:1};
});
}
}
module.exports &#x3D; Buttons;</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 November 26, 2022.
</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.18.4 &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>18.<wbr>4</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 November 26, 2022.
</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

@@ -2,9 +2,9 @@
<html> <html>
<head> <head>
<meta name="generator" content="JSDoc 3.6.6"> <meta name="generator" content="JSDoc 3.6.7">
<meta charset="utf-8"> <meta charset="utf-8">
<title>whatsapp-web.js 1.12.6 &raquo; Source: structures/Chat.js</title> <title>whatsapp-web.js 1.18.4 &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/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/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 rel="stylesheet" href="https://brick.a.ssl.fastly.net/Inconsolata:500" type="text/css">
@@ -15,7 +15,7 @@
<nav id="jsdoc-navbar" role="navigation" class="jsdoc-navbar"> <nav id="jsdoc-navbar" role="navigation" class="jsdoc-navbar">
<div id="jsdoc-navbar-container"> <div id="jsdoc-navbar-container">
<div id="jsdoc-navbar-content"> <div id="jsdoc-navbar-content">
<a href="index.html" class="jsdoc-navbar-package-name">whatsapp-web.<wbr>js 1.<wbr>12.<wbr>6</a> <a href="index.html" class="jsdoc-navbar-package-name">whatsapp-web.<wbr>js 1.<wbr>18.<wbr>4</a>
</div> </div>
</div> </div>
</nav> </nav>
@@ -96,7 +96,7 @@ class Chat extends Base {
/** /**
* Indicates if the chat is muted or not * Indicates if the chat is muted or not
* @type {number} * @type {boolean}
*/ */
this.isMuted &#x3D; data.isMuted; this.isMuted &#x3D; data.isMuted;
@@ -178,8 +178,8 @@ class Chat extends Base {
} }
/** /**
* Mutes this chat until a specified date * Mutes this chat forever, unless a date is specified
* @param {Date} unmuteDate Date at which the Chat will be unmuted * @param {?Date} unmuteDate Date at which the Chat will be unmuted, leave as is to mute forever
*/ */
async mute(unmuteDate) { async mute(unmuteDate) {
return this.client.muteChat(this.id._serialized, unmuteDate); return this.client.muteChat(this.id._serialized, unmuteDate);
@@ -201,31 +201,42 @@ class Chat extends Base {
/** /**
* Loads chat messages, sorted from earliest to latest. * Loads chat messages, sorted from earliest to latest.
* @param {Object} searchOptions Options for searching messages. Right now only limit is supported. * @param {Object} searchOptions Options for searching messages. Right now only limit and fromMe 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. * @param {Number} [searchOptions.limit] The amount of messages to return. If no limit is specified, the available messages will be returned. 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.
* @param {Boolean} [searchOptions.fromMe] Return only messages from the bot number or vise versa. To get all messages, leave the option undefined.
* @returns {Promise&amp;lt;Array&amp;lt;Message&gt;&gt;} * @returns {Promise&amp;lt;Array&amp;lt;Message&gt;&gt;}
*/ */
async fetchMessages(searchOptions) { async fetchMessages(searchOptions) {
if (!searchOptions || !searchOptions.limit) { let messages &#x3D; await this.client.pupPage.evaluate(async (chatId, searchOptions) &#x3D;&gt; {
searchOptions &#x3D; { limit: 50 }; const msgFilter &#x3D; (m) &#x3D;&gt; {
} if (m.isNotification) {
let messages &#x3D; await this.client.pupPage.evaluate(async (chatId, limit) &#x3D;&gt; { return false; // dont include notification messages
const msgFilter &#x3D; m &#x3D;&gt; !m.isNotification; // dont include notification messages }
if (searchOptions &amp;amp;&amp;amp; searchOptions.fromMe &amp;amp;&amp;amp; m.id.fromMe !&#x3D;&#x3D; searchOptions.fromMe) {
return false;
}
return true;
};
const chat &#x3D; window.Store.Chat.get(chatId); const chat &#x3D; window.Store.Chat.get(chatId);
let msgs &#x3D; chat.msgs.models.filter(msgFilter); let msgs &#x3D; chat.msgs.getModelsArray().filter(msgFilter);
while (msgs.length &amp;lt; limit) { if (searchOptions &amp;amp;&amp;amp; searchOptions.limit &gt; 0) {
const loadedMessages &#x3D; await chat.loadEarlierMsgs(); while (msgs.length &amp;lt; searchOptions.limit) {
if (!loadedMessages) break; const loadedMessages &#x3D; await window.Store.ConversationMsgs.loadEarlierMsgs(chat);
msgs &#x3D; [...loadedMessages.filter(msgFilter), ...msgs]; if (!loadedMessages || !loadedMessages.length) break;
msgs &#x3D; [...loadedMessages.filter(msgFilter), ...msgs];
}
if (msgs.length &gt; searchOptions.limit) {
msgs.sort((a, b) &#x3D;&gt; (a.t &gt; b.t) ? 1 : -1);
msgs &#x3D; msgs.splice(msgs.length - searchOptions.limit);
}
} }
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)); return msgs.map(m &#x3D;&gt; window.WWebJS.getMessageModel(m));
}, this.id._serialized, searchOptions.limit); }, this.id._serialized, searchOptions);
return messages.map(m &#x3D;&gt; new Message(this.client, m)); return messages.map(m &#x3D;&gt; new Message(this.client, m));
} }
@@ -288,7 +299,7 @@ module.exports &#x3D; Chat;
<footer id="jsdoc-footer" class="jsdoc-footer"> <footer id="jsdoc-footer" class="jsdoc-footer">
<div id="jsdoc-footer-container"> <div id="jsdoc-footer-container">
<p> <p>
Generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc</a> 3.6.6 on April 20, 2021. Generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc</a> 3.6.7 on November 26, 2022.
</p> </p>
</div> </div>
</footer> </footer>

View File

@@ -2,9 +2,9 @@
<html> <html>
<head> <head>
<meta name="generator" content="JSDoc 3.6.6"> <meta name="generator" content="JSDoc 3.6.7">
<meta charset="utf-8"> <meta charset="utf-8">
<title>whatsapp-web.js 1.12.6 &raquo; Source: structures/ClientInfo.js</title> <title>whatsapp-web.js 1.18.4 &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/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/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 rel="stylesheet" href="https://brick.a.ssl.fastly.net/Inconsolata:500" type="text/css">
@@ -15,7 +15,7 @@
<nav id="jsdoc-navbar" role="navigation" class="jsdoc-navbar"> <nav id="jsdoc-navbar" role="navigation" class="jsdoc-navbar">
<div id="jsdoc-navbar-container"> <div id="jsdoc-navbar-container">
<div id="jsdoc-navbar-content"> <div id="jsdoc-navbar-content">
<a href="index.html" class="jsdoc-navbar-package-name">whatsapp-web.<wbr>js 1.<wbr>12.<wbr>6</a> <a href="index.html" class="jsdoc-navbar-package-name">whatsapp-web.<wbr>js 1.<wbr>18.<wbr>4</a>
</div> </div>
</div> </div>
</nav> </nav>
@@ -51,12 +51,6 @@ class ClientInfo extends Base {
*/ */
this.pushname &#x3D; data.pushname; this.pushname &#x3D; data.pushname;
/**
* @type {object}
* @deprecated Use .wid instead
*/
this.me &#x3D; data.wid;
/** /**
* Current user ID * Current user ID
* @type {object} * @type {object}
@@ -64,18 +58,25 @@ class ClientInfo extends Base {
this.wid &#x3D; data.wid; this.wid &#x3D; data.wid;
/** /**
* Information about the phone this client is connected to * @type {object}
* @deprecated Use .wid instead
*/
this.me &#x3D; data.wid;
/**
* Information about the phone this client is connected to. Not available in multi-device.
* @type {object} * @type {object}
* @property {string} wa_version WhatsApp Version running on the phone * @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} os_version OS Version running on the phone (iOS or Android version)
* @property {string} device_manufacturer Device manufacturer * @property {string} device_manufacturer Device manufacturer
* @property {string} device_model Device model * @property {string} device_model Device model
* @property {string} os_build_number OS build number * @property {string} os_build_number OS build number
* @deprecated
*/ */
this.phone &#x3D; data.phone; this.phone &#x3D; data.phone;
/** /**
* Platform the phone is running on * Platform WhatsApp is running on
* @type {string} * @type {string}
*/ */
this.platform &#x3D; data.platform; this.platform &#x3D; data.platform;
@@ -88,6 +89,7 @@ class ClientInfo extends Base {
* @returns {object} batteryStatus * @returns {object} batteryStatus
* @returns {number} batteryStatus.battery - The current battery percentage * @returns {number} batteryStatus.battery - The current battery percentage
* @returns {boolean} batteryStatus.plugged - Indicates if the phone is plugged in (true) or not (false) * @returns {boolean} batteryStatus.plugged - Indicates if the phone is plugged in (true) or not (false)
* @deprecated
*/ */
async getBatteryStatus() { async getBatteryStatus() {
return await this.client.pupPage.evaluate(() &#x3D;&gt; { return await this.client.pupPage.evaluate(() &#x3D;&gt; {
@@ -95,7 +97,6 @@ class ClientInfo extends Base {
return { battery, plugged }; return { battery, plugged };
}); });
} }
} }
module.exports &#x3D; ClientInfo;</code></pre> module.exports &#x3D; ClientInfo;</code></pre>
@@ -108,7 +109,7 @@ module.exports &#x3D; ClientInfo;</code></pre>
<footer id="jsdoc-footer" class="jsdoc-footer"> <footer id="jsdoc-footer" class="jsdoc-footer">
<div id="jsdoc-footer-container"> <div id="jsdoc-footer-container">
<p> <p>
Generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc</a> 3.6.6 on April 20, 2021. Generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc</a> 3.6.7 on November 26, 2022.
</p> </p>
</div> </div>
</footer> </footer>

View File

@@ -2,9 +2,9 @@
<html> <html>
<head> <head>
<meta name="generator" content="JSDoc 3.6.6"> <meta name="generator" content="JSDoc 3.6.7">
<meta charset="utf-8"> <meta charset="utf-8">
<title>whatsapp-web.js 1.12.6 &raquo; Source: structures/Contact.js</title> <title>whatsapp-web.js 1.18.4 &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/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/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 rel="stylesheet" href="https://brick.a.ssl.fastly.net/Inconsolata:500" type="text/css">
@@ -15,7 +15,7 @@
<nav id="jsdoc-navbar" role="navigation" class="jsdoc-navbar"> <nav id="jsdoc-navbar" role="navigation" class="jsdoc-navbar">
<div id="jsdoc-navbar-container"> <div id="jsdoc-navbar-container">
<div id="jsdoc-navbar-content"> <div id="jsdoc-navbar-content">
<a href="index.html" class="jsdoc-navbar-package-name">whatsapp-web.<wbr>js 1.<wbr>12.<wbr>6</a> <a href="index.html" class="jsdoc-navbar-package-name">whatsapp-web.<wbr>js 1.<wbr>18.<wbr>4</a>
</div> </div>
</div> </div>
</nav> </nav>
@@ -139,7 +139,7 @@ class Contact extends Base {
* @type {boolean} * @type {boolean}
*/ */
this.isBlocked &#x3D; data.isBlocked; this.isBlocked &#x3D; data.isBlocked;
return super._patch(data); return super._patch(data);
} }
@@ -151,6 +151,22 @@ class Contact extends Base {
return await this.client.getProfilePicUrl(this.id._serialized); return await this.client.getProfilePicUrl(this.id._serialized);
} }
/**
* Returns the contact&#x27;s formatted phone number, (12345678901@c.us) &#x3D;&gt; (+1 (234) 5678-901)
* @returns {Promise&amp;lt;string&gt;}
*/
async getFormattedNumber() {
return await this.client.getFormattedNumber(this.id._serialized);
}
/**
* Returns the contact&#x27;s countrycode, (1541859685@c.us) &#x3D;&gt; (1)
* @returns {Promise&amp;lt;string&gt;}
*/
async getCountryCode() {
return await this.client.getCountryCode(this.id._serialized);
}
/** /**
* Returns the Chat that corresponds to this Contact. * Returns the Chat that corresponds to this Contact.
* Will return null when getting chat for currently logged in user. * Will return null when getting chat for currently logged in user.
@@ -198,7 +214,8 @@ class Contact extends Base {
*/ */
async getAbout() { async getAbout() {
const about &#x3D; await this.client.pupPage.evaluate(async (contactId) &#x3D;&gt; { const about &#x3D; await this.client.pupPage.evaluate(async (contactId) &#x3D;&gt; {
return window.Store.Wap.statusFind(contactId); const wid &#x3D; window.Store.WidFactory.createWid(contactId);
return window.Store.StatusUtils.getStatus(wid);
}, this.id._serialized); }, this.id._serialized);
if (typeof about.status !&#x3D;&#x3D; &#x27;string&#x27;) if (typeof about.status !&#x3D;&#x3D; &#x27;string&#x27;)
@@ -206,10 +223,19 @@ class Contact extends Base {
return about.status; return about.status;
} }
/**
* Gets the Contact&#x27;s common groups with you. Returns empty array if you don&#x27;t have any common group.
* @returns {Promise&amp;lt;WAWebJS.ChatId[]&gt;}
*/
async getCommonGroups() {
return await this.client.getCommonGroups(this.id._serialized);
}
} }
module.exports &#x3D; Contact;</code></pre> module.exports &#x3D; Contact;
</code></pre>
</article> </article>
</div> </div>
</div> </div>
@@ -219,7 +245,7 @@ module.exports &#x3D; Contact;</code></pre>
<footer id="jsdoc-footer" class="jsdoc-footer"> <footer id="jsdoc-footer" class="jsdoc-footer">
<div id="jsdoc-footer-container"> <div id="jsdoc-footer-container">
<p> <p>
Generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc</a> 3.6.6 on April 20, 2021. Generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc</a> 3.6.7 on November 26, 2022.
</p> </p>
</div> </div>
</footer> </footer>

View File

@@ -2,9 +2,9 @@
<html> <html>
<head> <head>
<meta name="generator" content="JSDoc 3.6.6"> <meta name="generator" content="JSDoc 3.6.7">
<meta charset="utf-8"> <meta charset="utf-8">
<title>whatsapp-web.js 1.12.6 &raquo; Source: structures/GroupChat.js</title> <title>whatsapp-web.js 1.18.4 &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/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/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 rel="stylesheet" href="https://brick.a.ssl.fastly.net/Inconsolata:500" type="text/css">
@@ -15,7 +15,7 @@
<nav id="jsdoc-navbar" role="navigation" class="jsdoc-navbar"> <nav id="jsdoc-navbar" role="navigation" class="jsdoc-navbar">
<div id="jsdoc-navbar-container"> <div id="jsdoc-navbar-container">
<div id="jsdoc-navbar-content"> <div id="jsdoc-navbar-content">
<a href="index.html" class="jsdoc-navbar-package-name">whatsapp-web.<wbr>js 1.<wbr>12.<wbr>6</a> <a href="index.html" class="jsdoc-navbar-package-name">whatsapp-web.<wbr>js 1.<wbr>18.<wbr>4</a>
</div> </div>
</div> </div>
</nav> </nav>
@@ -91,7 +91,9 @@ class GroupChat extends Chat {
*/ */
async addParticipants(participantIds) { async addParticipants(participantIds) {
return await this.client.pupPage.evaluate((chatId, participantIds) &#x3D;&gt; { return await this.client.pupPage.evaluate((chatId, participantIds) &#x3D;&gt; {
return window.Store.Wap.addParticipants(chatId, participantIds); const chatWid &#x3D; window.Store.WidFactory.createWid(chatId);
const participantWids &#x3D; participantIds.map(p &#x3D;&gt; window.Store.WidFactory.createWid(p));
return window.Store.GroupParticipants.sendAddParticipants(chatWid, participantWids);
}, this.id._serialized, participantIds); }, this.id._serialized, participantIds);
} }
@@ -102,7 +104,9 @@ class GroupChat extends Chat {
*/ */
async removeParticipants(participantIds) { async removeParticipants(participantIds) {
return await this.client.pupPage.evaluate((chatId, participantIds) &#x3D;&gt; { return await this.client.pupPage.evaluate((chatId, participantIds) &#x3D;&gt; {
return window.Store.Wap.removeParticipants(chatId, participantIds); const chatWid &#x3D; window.Store.WidFactory.createWid(chatId);
const participantWids &#x3D; participantIds.map(p &#x3D;&gt; window.Store.WidFactory.createWid(p));
return window.Store.GroupParticipants.sendRemoveParticipants(chatWid, participantWids);
}, this.id._serialized, participantIds); }, this.id._serialized, participantIds);
} }
@@ -113,7 +117,9 @@ class GroupChat extends Chat {
*/ */
async promoteParticipants(participantIds) { async promoteParticipants(participantIds) {
return await this.client.pupPage.evaluate((chatId, participantIds) &#x3D;&gt; { return await this.client.pupPage.evaluate((chatId, participantIds) &#x3D;&gt; {
return window.Store.Wap.promoteParticipants(chatId, participantIds); const chatWid &#x3D; window.Store.WidFactory.createWid(chatId);
const participantWids &#x3D; participantIds.map(p &#x3D;&gt; window.Store.WidFactory.createWid(p));
return window.Store.GroupParticipants.sendPromoteParticipants(chatWid, participantWids);
}, this.id._serialized, participantIds); }, this.id._serialized, participantIds);
} }
@@ -124,53 +130,73 @@ class GroupChat extends Chat {
*/ */
async demoteParticipants(participantIds) { async demoteParticipants(participantIds) {
return await this.client.pupPage.evaluate((chatId, participantIds) &#x3D;&gt; { return await this.client.pupPage.evaluate((chatId, participantIds) &#x3D;&gt; {
return window.Store.Wap.demoteParticipants(chatId, participantIds); const chatWid &#x3D; window.Store.WidFactory.createWid(chatId);
const participantWids &#x3D; participantIds.map(p &#x3D;&gt; window.Store.WidFactory.createWid(p));
return window.Store.GroupParticipants.sendDemoteParticipants(chatWid, participantWids);
}, this.id._serialized, participantIds); }, this.id._serialized, participantIds);
} }
/** /**
* Updates the group subject * Updates the group subject
* @param {string} subject * @param {string} subject
* @returns {Promise} * @returns {Promise&amp;lt;boolean&gt;} Returns true if the subject was properly updated. This can return false if the user does not have the necessary permissions.
*/ */
async setSubject(subject) { async setSubject(subject) {
let res &#x3D; await this.client.pupPage.evaluate((chatId, subject) &#x3D;&gt; { const success &#x3D; await this.client.pupPage.evaluate(async (chatId, subject) &#x3D;&gt; {
return window.Store.Wap.changeSubject(chatId, subject); const chatWid &#x3D; window.Store.WidFactory.createWid(chatId);
try {
return await window.Store.GroupUtils.sendSetGroupSubject(chatWid, subject);
} catch (err) {
if(err.name &#x3D;&#x3D;&#x3D; &#x27;ServerStatusCodeError&#x27;) return false;
throw err;
}
}, this.id._serialized, subject); }, this.id._serialized, subject);
if(res.status &#x3D;&#x3D; 200) { if(!success) return false;
this.name &#x3D; subject; this.name &#x3D; subject;
} return true;
} }
/** /**
* Updates the group description * Updates the group description
* @param {string} description * @param {string} description
* @returns {Promise} * @returns {Promise&amp;lt;boolean&gt;} Returns true if the description was properly updated. This can return false if the user does not have the necessary permissions.
*/ */
async setDescription(description) { async setDescription(description) {
let res &#x3D; await this.client.pupPage.evaluate((chatId, description) &#x3D;&gt; { const success &#x3D; await this.client.pupPage.evaluate(async (chatId, description) &#x3D;&gt; {
let descId &#x3D; window.Store.GroupMetadata.get(chatId).descId; const chatWid &#x3D; window.Store.WidFactory.createWid(chatId);
return window.Store.Wap.setGroupDescription(chatId, description, window.Store.genId(), descId); let descId &#x3D; window.Store.GroupMetadata.get(chatWid).descId;
try {
return await window.Store.GroupUtils.sendSetGroupDescription(chatWid, description, window.Store.MsgKey.newId(), descId);
} catch (err) {
if(err.name &#x3D;&#x3D;&#x3D; &#x27;ServerStatusCodeError&#x27;) return false;
throw err;
}
}, this.id._serialized, description); }, this.id._serialized, description);
if (res.status &#x3D;&#x3D; 200) { if(!success) return false;
this.groupMetadata.desc &#x3D; description; this.groupMetadata.desc &#x3D; description;
} return true;
} }
/** /**
* Updates the group settings to only allow admins to send messages. * Updates the group settings to only allow admins to send messages.
* @param {boolean} [adminsOnly&#x3D;true] Enable or disable this option * @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. * @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) { async setMessagesAdminsOnly(adminsOnly&#x3D;true) {
let res &#x3D; await this.client.pupPage.evaluate((chatId, value) &#x3D;&gt; { const success &#x3D; await this.client.pupPage.evaluate(async (chatId, adminsOnly) &#x3D;&gt; {
return window.Store.Wap.setGroupProperty(chatId, &#x27;announcement&#x27;, value); const chatWid &#x3D; window.Store.WidFactory.createWid(chatId);
try {
return await window.Store.GroupUtils.sendSetGroupProperty(chatWid, &#x27;announcement&#x27;, adminsOnly ? 1 : 0);
} catch (err) {
if(err.name &#x3D;&#x3D;&#x3D; &#x27;ServerStatusCodeError&#x27;) return false;
throw err;
}
}, this.id._serialized, adminsOnly); }, this.id._serialized, adminsOnly);
if (res.status !&#x3D;&#x3D; 200) return false; if(!success) return false;
this.groupMetadata.announce &#x3D; adminsOnly; this.groupMetadata.announce &#x3D; adminsOnly;
return true; return true;
} }
@@ -181,11 +207,17 @@ class GroupChat extends Chat {
* @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. * @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) { async setInfoAdminsOnly(adminsOnly&#x3D;true) {
let res &#x3D; await this.client.pupPage.evaluate((chatId, value) &#x3D;&gt; { const success &#x3D; await this.client.pupPage.evaluate(async (chatId, adminsOnly) &#x3D;&gt; {
return window.Store.Wap.setGroupProperty(chatId, &#x27;restrict&#x27;, value); const chatWid &#x3D; window.Store.WidFactory.createWid(chatId);
try {
return await window.Store.GroupUtils.sendSetGroupProperty(chatWid, &#x27;restrict&#x27;, adminsOnly ? 1 : 0);
} catch (err) {
if(err.name &#x3D;&#x3D;&#x3D; &#x27;ServerStatusCodeError&#x27;) return false;
throw err;
}
}, this.id._serialized, adminsOnly); }, this.id._serialized, adminsOnly);
if (res.status !&#x3D;&#x3D; 200) return false; if(!success) return false;
this.groupMetadata.restrict &#x3D; adminsOnly; this.groupMetadata.restrict &#x3D; adminsOnly;
return true; return true;
@@ -196,25 +228,25 @@ class GroupChat extends Chat {
* @returns {Promise&amp;lt;string&gt;} Group&#x27;s invite code * @returns {Promise&amp;lt;string&gt;} Group&#x27;s invite code
*/ */
async getInviteCode() { async getInviteCode() {
let res &#x3D; await this.client.pupPage.evaluate(chatId &#x3D;&gt; { const code &#x3D; await this.client.pupPage.evaluate(async chatId &#x3D;&gt; {
return window.Store.Wap.groupInviteCode(chatId); const chatWid &#x3D; window.Store.WidFactory.createWid(chatId);
return window.Store.Invite.sendQueryGroupInviteCode(chatWid);
}, this.id._serialized); }, this.id._serialized);
if (res.status &#x3D;&#x3D; 200) { return code;
return res.code;
}
throw new Error(&#x27;Not authorized&#x27;);
} }
/** /**
* Invalidates the current group invite code and generates a new one * Invalidates the current group invite code and generates a new one
* @returns {Promise} * @returns {Promise&amp;lt;string&gt;} New invite code
*/ */
async revokeInvite() { async revokeInvite() {
return await this.client.pupPage.evaluate(chatId &#x3D;&gt; { const code &#x3D; await this.client.pupPage.evaluate(chatId &#x3D;&gt; {
return window.Store.Wap.revokeGroupInvite(chatId); const chatWid &#x3D; window.Store.WidFactory.createWid(chatId);
return window.Store.Invite.sendRevokeGroupInviteCode(chatWid);
}, this.id._serialized); }, this.id._serialized);
return code;
} }
/** /**
@@ -222,8 +254,9 @@ class GroupChat extends Chat {
* @returns {Promise} * @returns {Promise}
*/ */
async leave() { async leave() {
return await this.client.pupPage.evaluate(chatId &#x3D;&gt; { await this.client.pupPage.evaluate(chatId &#x3D;&gt; {
return window.Store.Wap.leaveGroup(chatId); const chatWid &#x3D; window.Store.WidFactory.createWid(chatId);
return window.Store.GroupUtils.sendExitGroup(chatWid);
}, this.id._serialized); }, this.id._serialized);
} }
@@ -239,7 +272,7 @@ module.exports &#x3D; GroupChat;</code></pre>
<footer id="jsdoc-footer" class="jsdoc-footer"> <footer id="jsdoc-footer" class="jsdoc-footer">
<div id="jsdoc-footer-container"> <div id="jsdoc-footer-container">
<p> <p>
Generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc</a> 3.6.6 on April 20, 2021. Generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc</a> 3.6.7 on November 26, 2022.
</p> </p>
</div> </div>
</footer> </footer>

View File

@@ -2,9 +2,9 @@
<html> <html>
<head> <head>
<meta name="generator" content="JSDoc 3.6.6"> <meta name="generator" content="JSDoc 3.6.7">
<meta charset="utf-8"> <meta charset="utf-8">
<title>whatsapp-web.js 1.12.6 &raquo; Source: structures/GroupNotification.js</title> <title>whatsapp-web.js 1.18.4 &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/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/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 rel="stylesheet" href="https://brick.a.ssl.fastly.net/Inconsolata:500" type="text/css">
@@ -15,7 +15,7 @@
<nav id="jsdoc-navbar" role="navigation" class="jsdoc-navbar"> <nav id="jsdoc-navbar" role="navigation" class="jsdoc-navbar">
<div id="jsdoc-navbar-container"> <div id="jsdoc-navbar-container">
<div id="jsdoc-navbar-content"> <div id="jsdoc-navbar-content">
<a href="index.html" class="jsdoc-navbar-package-name">whatsapp-web.<wbr>js 1.<wbr>12.<wbr>6</a> <a href="index.html" class="jsdoc-navbar-package-name">whatsapp-web.<wbr>js 1.<wbr>18.<wbr>4</a>
</div> </div>
</div> </div>
</nav> </nav>
@@ -74,7 +74,7 @@ class GroupNotification extends Base {
* *
* @type {string} * @type {string}
*/ */
this.chatId &#x3D; typeof (data.from) &#x3D;&#x3D;&#x3D; &#x27;object&#x27; ? data.from._serialized : data.from; this.chatId &#x3D; typeof (data.id.remote) &#x3D;&#x3D;&#x3D; &#x27;object&#x27; ? data.id.remote._serialized : data.id.remote;
/** /**
* ContactId for the user that produced the GroupNotification. * ContactId for the user that produced the GroupNotification.
@@ -143,7 +143,7 @@ module.exports &#x3D; GroupNotification;
<footer id="jsdoc-footer" class="jsdoc-footer"> <footer id="jsdoc-footer" class="jsdoc-footer">
<div id="jsdoc-footer-container"> <div id="jsdoc-footer-container">
<p> <p>
Generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc</a> 3.6.6 on April 20, 2021. Generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc</a> 3.6.7 on November 26, 2022.
</p> </p>
</div> </div>
</footer> </footer>

View File

@@ -2,9 +2,9 @@
<html> <html>
<head> <head>
<meta name="generator" content="JSDoc 3.6.6"> <meta name="generator" content="JSDoc 3.6.7">
<meta charset="utf-8"> <meta charset="utf-8">
<title>whatsapp-web.js 1.12.6 &raquo; Source: structures/Label.js</title> <title>whatsapp-web.js 1.18.4 &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/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/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 rel="stylesheet" href="https://brick.a.ssl.fastly.net/Inconsolata:500" type="text/css">
@@ -15,7 +15,7 @@
<nav id="jsdoc-navbar" role="navigation" class="jsdoc-navbar"> <nav id="jsdoc-navbar" role="navigation" class="jsdoc-navbar">
<div id="jsdoc-navbar-container"> <div id="jsdoc-navbar-container">
<div id="jsdoc-navbar-content"> <div id="jsdoc-navbar-content">
<a href="index.html" class="jsdoc-navbar-package-name">whatsapp-web.<wbr>js 1.<wbr>12.<wbr>6</a> <a href="index.html" class="jsdoc-navbar-package-name">whatsapp-web.<wbr>js 1.<wbr>18.<wbr>4</a>
</div> </div>
</div> </div>
</nav> </nav>
@@ -88,7 +88,7 @@ module.exports &#x3D; Label;</code></pre>
<footer id="jsdoc-footer" class="jsdoc-footer"> <footer id="jsdoc-footer" class="jsdoc-footer">
<div id="jsdoc-footer-container"> <div id="jsdoc-footer-container">
<p> <p>
Generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc</a> 3.6.6 on April 20, 2021. Generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc</a> 3.6.7 on November 26, 2022.
</p> </p>
</div> </div>
</footer> </footer>

View File

@@ -0,0 +1,133 @@
<!doctype html>
<html>
<head>
<meta name="generator" content="JSDoc 3.6.7">
<meta charset="utf-8">
<title>whatsapp-web.js 1.18.4 &raquo; Source: structures/List.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>18.<wbr>4</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/List.js</h1>
</header>
<article>
<pre class="prettyprint linenums"><code>&#x27;use strict&#x27;;
const Util &#x3D; require(&#x27;../util/Util&#x27;);
/**
* Message type List
*/
class List {
/**
* @param {string} body
* @param {string} buttonText
* @param {Array&amp;lt;any&gt;} sections
* @param {string?} title
* @param {string?} footer
*/
constructor(body, buttonText, sections, title, footer) {
/**
* Message body
* @type {string}
*/
this.description &#x3D; body;
/**
* List button text
* @type {string}
*/
this.buttonText &#x3D; buttonText;
/**
* title of message
* @type {string}
*/
this.title &#x3D; title;
/**
* footer of message
* @type {string}
*/
this.footer &#x3D; footer;
/**
* sections of message
* @type {Array&amp;lt;any&gt;}
*/
this.sections &#x3D; this._format(sections);
}
/**
* Creates section array from simple array
* @param {Array&amp;lt;any&gt;} sections
* @returns {Array&amp;lt;any&gt;}
* @example
* Input: [{title:&#x27;sectionTitle&#x27;,rows:[{id:&#x27;customId&#x27;, title:&#x27;ListItem2&#x27;, description: &#x27;desc&#x27;},{title:&#x27;ListItem2&#x27;}]}}]
* Returns: [{&#x27;title&#x27;:&#x27;sectionTitle&#x27;,&#x27;rows&#x27;:[{&#x27;rowId&#x27;:&#x27;customId&#x27;,&#x27;title&#x27;:&#x27;ListItem1&#x27;,&#x27;description&#x27;:&#x27;desc&#x27;},{&#x27;rowId&#x27;:&#x27;oGSRoD&#x27;,&#x27;title&#x27;:&#x27;ListItem2&#x27;,&#x27;description&#x27;:&#x27;&#x27;}]}]
*/
_format(sections){
if(!sections.length){throw &#x27;[LT02] List without sections&#x27;;}
if(sections.length &gt; 1 &amp;amp;&amp;amp; sections.filter(s &#x3D;&gt; typeof s.title &#x3D;&#x3D; &#x27;undefined&#x27;).length &gt; 1){throw &#x27;[LT05] You can\&#x27;t have more than one empty title.&#x27;;}
return sections.map( (section) &#x3D;&gt;{
if(!section.rows.length){throw &#x27;[LT03] Section without rows&#x27;;}
return {
title: section.title ? section.title : undefined,
rows: section.rows.map( (row) &#x3D;&gt; {
if(!row.title){throw &#x27;[LT04] Row without title&#x27;;}
return {
rowId: row.id ? row.id : Util.generateHash(6),
title: row.title,
description: row.description ? row.description : &#x27;&#x27;
};
})
};
});
}
}
module.exports &#x3D; List;
</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 November 26, 2022.
</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

@@ -2,9 +2,9 @@
<html> <html>
<head> <head>
<meta name="generator" content="JSDoc 3.6.6"> <meta name="generator" content="JSDoc 3.6.7">
<meta charset="utf-8"> <meta charset="utf-8">
<title>whatsapp-web.js 1.12.6 &raquo; Source: structures/Location.js</title> <title>whatsapp-web.js 1.18.4 &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/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/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 rel="stylesheet" href="https://brick.a.ssl.fastly.net/Inconsolata:500" type="text/css">
@@ -15,7 +15,7 @@
<nav id="jsdoc-navbar" role="navigation" class="jsdoc-navbar"> <nav id="jsdoc-navbar" role="navigation" class="jsdoc-navbar">
<div id="jsdoc-navbar-container"> <div id="jsdoc-navbar-container">
<div id="jsdoc-navbar-content"> <div id="jsdoc-navbar-content">
<a href="index.html" class="jsdoc-navbar-package-name">whatsapp-web.<wbr>js 1.<wbr>12.<wbr>6</a> <a href="index.html" class="jsdoc-navbar-package-name">whatsapp-web.<wbr>js 1.<wbr>18.<wbr>4</a>
</div> </div>
</div> </div>
</nav> </nav>
@@ -71,7 +71,7 @@ module.exports &#x3D; Location;</code></pre>
<footer id="jsdoc-footer" class="jsdoc-footer"> <footer id="jsdoc-footer" class="jsdoc-footer">
<div id="jsdoc-footer-container"> <div id="jsdoc-footer-container">
<p> <p>
Generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc</a> 3.6.6 on April 20, 2021. Generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc</a> 3.6.7 on November 26, 2022.
</p> </p>
</div> </div>
</footer> </footer>

View File

@@ -2,9 +2,9 @@
<html> <html>
<head> <head>
<meta name="generator" content="JSDoc 3.6.6"> <meta name="generator" content="JSDoc 3.6.7">
<meta charset="utf-8"> <meta charset="utf-8">
<title>whatsapp-web.js 1.12.6 &raquo; Source: structures/Message.js</title> <title>whatsapp-web.js 1.18.4 &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/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/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 rel="stylesheet" href="https://brick.a.ssl.fastly.net/Inconsolata:500" type="text/css">
@@ -15,7 +15,7 @@
<nav id="jsdoc-navbar" role="navigation" class="jsdoc-navbar"> <nav id="jsdoc-navbar" role="navigation" class="jsdoc-navbar">
<div id="jsdoc-navbar-container"> <div id="jsdoc-navbar-container">
<div id="jsdoc-navbar-content"> <div id="jsdoc-navbar-content">
<a href="index.html" class="jsdoc-navbar-package-name">whatsapp-web.<wbr>js 1.<wbr>12.<wbr>6</a> <a href="index.html" class="jsdoc-navbar-package-name">whatsapp-web.<wbr>js 1.<wbr>18.<wbr>4</a>
</div> </div>
</div> </div>
</nav> </nav>
@@ -34,6 +34,8 @@
const Base &#x3D; require(&#x27;./Base&#x27;); const Base &#x3D; require(&#x27;./Base&#x27;);
const MessageMedia &#x3D; require(&#x27;./MessageMedia&#x27;); const MessageMedia &#x3D; require(&#x27;./MessageMedia&#x27;);
const Location &#x3D; require(&#x27;./Location&#x27;); const Location &#x3D; require(&#x27;./Location&#x27;);
const Order &#x3D; require(&#x27;./Order&#x27;);
const Payment &#x3D; require(&#x27;./Payment&#x27;);
const { MessageTypes } &#x3D; require(&#x27;../util/Constants&#x27;); const { MessageTypes } &#x3D; require(&#x27;../util/Constants&#x27;);
/** /**
@@ -48,13 +50,14 @@ class Message extends Base {
} }
_patch(data) { _patch(data) {
this._data &#x3D; data;
/** /**
* MediaKey that represents the sticker &#x27;ID&#x27; * MediaKey that represents the sticker &#x27;ID&#x27;
* @type {string} * @type {string}
*/ */
this.mediaKey &#x3D; data.mediaKey; this.mediaKey &#x3D; data.mediaKey;
/** /**
* ID that represents the message * ID that represents the message
* @type {object} * @type {object}
@@ -71,7 +74,7 @@ class Message extends Base {
* Indicates if the message has media available for download * Indicates if the message has media available for download
* @type {boolean} * @type {boolean}
*/ */
this.hasMedia &#x3D; data.clientUrl || data.deprecatedMms3Url ? true : false; this.hasMedia &#x3D; Boolean(data.mediaKey &amp;amp;&amp;amp; data.directPath);
/** /**
* Message content * Message content
@@ -79,7 +82,7 @@ class Message extends Base {
*/ */
this.body &#x3D; this.hasMedia ? data.caption || &#x27;&#x27; : data.body || &#x27;&#x27;; this.body &#x3D; this.hasMedia ? data.caption || &#x27;&#x27; : data.body || &#x27;&#x27;;
/** /**
* Message type * Message type
* @type {MessageTypes} * @type {MessageTypes}
*/ */
@@ -99,9 +102,9 @@ class Message extends Base {
/** /**
* ID for who this message is for. * 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 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. * If the message is sent by another user, it will be the ID for the current user.
* @type {string} * @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; 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;
@@ -112,12 +115,26 @@ class Message extends Base {
*/ */
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; 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 * Indicates if the message was forwarded
* @type {boolean} * @type {boolean}
*/ */
this.isForwarded &#x3D; data.isForwarded; 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 * Indicates if the message is a status update
* @type {boolean} * @type {boolean}
@@ -129,14 +146,14 @@ class Message extends Base {
* @type {boolean} * @type {boolean}
*/ */
this.isStarred &#x3D; data.star; this.isStarred &#x3D; data.star;
/** /**
* Indicates if the message was a broadcast * Indicates if the message was a broadcast
* @type {boolean} * @type {boolean}
*/ */
this.broadcast &#x3D; data.broadcast; this.broadcast &#x3D; data.broadcast;
/** /**
* Indicates if the message was sent by the current user * Indicates if the message was sent by the current user
* @type {boolean} * @type {boolean}
*/ */
@@ -148,6 +165,12 @@ class Message extends Base {
*/ */
this.hasQuotedMsg &#x3D; data.quotedMsg ? true : false; this.hasQuotedMsg &#x3D; data.quotedMsg ? true : false;
/**
* Indicates the duration of the message in seconds
* @type {string}
*/
this.duration &#x3D; data.duration ? data.duration : undefined;
/** /**
* Location information contained in the message, if the message is type &quot;location&quot; * Location information contained in the message, if the message is type &quot;location&quot;
* @type {Location} * @type {Location}
@@ -160,6 +183,19 @@ class Message extends Base {
*/ */
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] : []; 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. * Indicates the mentions in the message body.
* @type {Array&amp;lt;string&gt;} * @type {Array&amp;lt;string&gt;}
@@ -170,12 +206,71 @@ class Message extends Base {
this.mentionedIds &#x3D; 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;
/**
* Indicates whether the message is a Gif
* @type {boolean}
*/
this.isGif &#x3D; Boolean(data.isGif);
/**
* Indicates if the message will disappear after it expires
* @type {boolean}
*/
this.isEphemeral &#x3D; data.isEphemeral;
/** 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. * Links included in the message.
* @type {Array&amp;lt;string&gt;} * @type {Array&amp;lt;{link: string, isSuspicious: boolean}&gt;}
*
*/ */
this.links &#x3D; data.links; this.links &#x3D; data.links;
/** Buttons */
if (data.dynamicReplyButtons) {
this.dynamicReplyButtons &#x3D; data.dynamicReplyButtons;
}
/** Selected Button Id **/
if (data.selectedButtonId) {
this.selectedButtonId &#x3D; data.selectedButtonId;
}
/** Selected List row Id **/
if (data.listResponse &amp;amp;&amp;amp; data.listResponse.singleSelectReply.selectedRowId) {
this.selectedRowId &#x3D; data.listResponse.singleSelectReply.selectedRowId;
}
return super._patch(data); return super._patch(data);
} }
@@ -183,6 +278,32 @@ class Message extends Base {
return this.fromMe ? this.to : this.from; return this.fromMe ? this.to : this.from;
} }
/**
* Reloads this Message object&#x27;s data in-place with the latest values from WhatsApp Web.
* Note that the Message must still be in the web app cache for this to work, otherwise will return null.
* @returns {Promise&amp;lt;Message&gt;}
*/
async reload() {
const newData &#x3D; await this.client.pupPage.evaluate((msgId) &#x3D;&gt; {
const msg &#x3D; window.Store.Msg.get(msgId);
if(!msg) return null;
return window.WWebJS.getMessageModel(msg);
}, this.id._serialized);
if(!newData) return null;
this._patch(newData);
return this;
}
/**
* Returns message in a raw format
* @type {Object}
*/
get rawData() {
return this._data;
}
/** /**
* Returns the Chat this message was sent in * Returns the Chat this message was sent in
* @returns {Promise&amp;lt;Chat&gt;} * @returns {Promise&amp;lt;Chat&gt;}
@@ -215,20 +336,21 @@ class Message extends Base {
if (!this.hasQuotedMsg) return undefined; if (!this.hasQuotedMsg) return undefined;
const quotedMsg &#x3D; await this.client.pupPage.evaluate((msgId) &#x3D;&gt; { const quotedMsg &#x3D; await this.client.pupPage.evaluate((msgId) &#x3D;&gt; {
let msg &#x3D; window.Store.Msg.get(msgId); const msg &#x3D; window.Store.Msg.get(msgId);
return msg.quotedMsgObj().serialize(); const quotedMsg &#x3D; window.Store.QuotedMsg.getQuotedMsgObj(msg);
return window.WWebJS.getMessageModel(quotedMsg);
}, this.id._serialized); }, this.id._serialized);
return new Message(this.client, quotedMsg); return new Message(this.client, quotedMsg);
} }
/** /**
* Sends a message as a reply to this message. If chatId is specified, it will be sent * 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 * through the specified Chat. If not, it will send the message
* in the same Chat as the original message was sent. * in the same Chat as the original message was sent.
* *
* @param {string|MessageMedia|Location} content * @param {string|MessageMedia|Location} content
* @param {string} [chatId] * @param {string} [chatId]
* @param {MessageSendOptions} [options] * @param {MessageSendOptions} [options]
* @returns {Promise&amp;lt;Message&gt;} * @returns {Promise&amp;lt;Message&gt;}
*/ */
@@ -246,8 +368,30 @@ class Message extends Base {
} }
/** /**
* Forwards this message to another chat * React to this message with an emoji
* * @param {string} reaction - Emoji to react with. Send an empty string to remove the reaction.
* @return {Promise}
*/
async react(reaction){
await this.client.pupPage.evaluate(async (messageId, reaction) &#x3D;&gt; {
if (!messageId) { return undefined; }
const msg &#x3D; await window.Store.Msg.get(messageId);
await window.Store.sendReactionToMsg(msg, reaction);
}, this.id._serialized, reaction);
}
/**
* 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 (that you chatted before, otherwise it will fail)
*
* @param {string|Chat} chat Chat model or chat ID to which the message will be forwarded * @param {string|Chat} chat Chat model or chat ID to which the message will be forwarded
* @returns {Promise} * @returns {Promise}
*/ */
@@ -276,42 +420,57 @@ class Message extends Base {
if (msg.mediaData.mediaStage !&#x3D; &#x27;RESOLVED&#x27;) { if (msg.mediaData.mediaStage !&#x3D; &#x27;RESOLVED&#x27;) {
// try to resolve media // try to resolve media
await msg.downloadMedia(true, 1); await msg.downloadMedia({
downloadEvenIfExpensive: true,
rmrReason: 1
});
} }
if (msg.mediaData.mediaStage.includes(&#x27;ERROR&#x27;)) { if (msg.mediaData.mediaStage.includes(&#x27;ERROR&#x27;) || msg.mediaData.mediaStage &#x3D;&#x3D;&#x3D; &#x27;FETCHING&#x27;) {
// media could not be downloaded // media could not be downloaded
return undefined; return undefined;
} }
const mediaUrl &#x3D; msg.clientUrl || msg.deprecatedMms3Url; 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 buffer &#x3D; await window.WWebJS.downloadBuffer(mediaUrl); const data &#x3D; await window.WWebJS.arrayBufferToBase64Async(decryptedMedia);
const decrypted &#x3D; await window.Store.CryptoLib.decryptE2EMedia(msg.type, buffer, msg.mediaKey, msg.mimetype);
const data &#x3D; await window.WWebJS.readBlobAsync(decrypted._blob);
return {
data: data.split(&#x27;,&#x27;)[1],
mimetype: msg.mimetype,
filename: msg.filename
};
return {
data,
mimetype: msg.mimetype,
filename: msg.filename,
filesize: msg.size
};
} catch (e) {
if(e.status &amp;amp;&amp;amp; e.status &#x3D;&#x3D;&#x3D; 404) return undefined;
throw e;
}
}, this.id._serialized); }, this.id._serialized);
if (!result) return undefined; if (!result) return undefined;
return new MessageMedia(result.mimetype, result.data, result.filename); return new MessageMedia(result.mimetype, result.data, result.filename, result.filesize);
} }
/** /**
* Deletes a message from the chat * 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. * @param {?boolean} everyone If true and the message is sent by the current user or the user is an admin, will delete it for everyone in the chat.
*/ */
async delete(everyone) { async delete(everyone) {
await this.client.pupPage.evaluate((msgId, everyone) &#x3D;&gt; { await this.client.pupPage.evaluate((msgId, everyone) &#x3D;&gt; {
let msg &#x3D; window.Store.Msg.get(msgId); let msg &#x3D; window.Store.Msg.get(msgId);
if (everyone &amp;amp;&amp;amp; msg.id.fromMe &amp;amp;&amp;amp; msg.canRevoke()) { const canRevoke &#x3D; window.Store.MsgActionChecks.canSenderRevokeMsg(msg) || window.Store.MsgActionChecks.canAdminRevokeMsg(msg);
return window.Store.Cmd.sendRevokeMsgs(msg.chat, [msg], true); if (everyone &amp;amp;&amp;amp; canRevoke) {
return window.Store.Cmd.sendRevokeMsgs(msg.chat, [msg], { type: msg.id.fromMe ? &#x27;Sender&#x27; : &#x27;Admin&#x27; });
} }
return window.Store.Cmd.sendDeleteMsgs(msg.chat, [msg], true); return window.Store.Cmd.sendDeleteMsgs(msg.chat, [msg], true);
@@ -325,8 +484,8 @@ class Message extends Base {
await this.client.pupPage.evaluate((msgId) &#x3D;&gt; { await this.client.pupPage.evaluate((msgId) &#x3D;&gt; {
let msg &#x3D; window.Store.Msg.get(msgId); let msg &#x3D; window.Store.Msg.get(msgId);
if (msg.canStar()) { if (window.Store.MsgActionChecks.canStarMsg(msg)) {
return msg.chat.sendStarMsgs([msg], true); return window.Store.Cmd.sendStarMsgs(msg.chat, [msg], false);
} }
}, this.id._serialized); }, this.id._serialized);
} }
@@ -338,8 +497,8 @@ class Message extends Base {
await this.client.pupPage.evaluate((msgId) &#x3D;&gt; { await this.client.pupPage.evaluate((msgId) &#x3D;&gt; {
let msg &#x3D; window.Store.Msg.get(msgId); let msg &#x3D; window.Store.Msg.get(msgId);
if (msg.canStar()) { if (window.Store.MsgActionChecks.canStarMsg(msg)) {
return msg.chat.sendStarMsgs([msg], false); return window.Store.Cmd.sendUnstarMsgs(msg.chat, [msg], false);
} }
}, this.id._serialized); }, this.id._serialized);
} }
@@ -362,17 +521,43 @@ class Message extends Base {
async getInfo() { async getInfo() {
const info &#x3D; await this.client.pupPage.evaluate(async (msgId) &#x3D;&gt; { const info &#x3D; await this.client.pupPage.evaluate(async (msgId) &#x3D;&gt; {
const msg &#x3D; window.Store.Msg.get(msgId); const msg &#x3D; window.Store.Msg.get(msgId);
if(!msg) return null; if (!msg) return null;
return await window.Store.Wap.queryMsgInfo(msg.id); return await window.Store.MessageInfo.sendQueryMsgInfo(msg);
}, this.id._serialized); }, this.id._serialized);
if(info.status) {
return null;
}
return info; 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, chatId) &#x3D;&gt; {
return window.WWebJS.getOrderDetail(orderId, token, chatId);
}, this.orderId, this.token, this._getChatId());
if (!result) return undefined;
return new Order(this.client, result);
}
return undefined;
}
/**
* Gets the payment details associated with a given message
* @return {Promise&amp;lt;Payment&gt;}
*/
async getPayment() {
if (this.type &#x3D;&#x3D;&#x3D; MessageTypes.PAYMENT) {
const msg &#x3D; await this.client.pupPage.evaluate(async (msgId) &#x3D;&gt; {
const msg &#x3D; window.Store.Msg.get(msgId);
if(!msg) return null;
return msg.serialize();
}, this.id._serialized);
return new Payment(this.client, msg);
}
return undefined;
}
} }
module.exports &#x3D; Message; module.exports &#x3D; Message;
@@ -386,7 +571,7 @@ module.exports &#x3D; Message;
<footer id="jsdoc-footer" class="jsdoc-footer"> <footer id="jsdoc-footer" class="jsdoc-footer">
<div id="jsdoc-footer-container"> <div id="jsdoc-footer-container">
<p> <p>
Generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc</a> 3.6.6 on April 20, 2021. Generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc</a> 3.6.7 on November 26, 2022.
</p> </p>
</div> </div>
</footer> </footer>

View File

@@ -2,9 +2,9 @@
<html> <html>
<head> <head>
<meta name="generator" content="JSDoc 3.6.6"> <meta name="generator" content="JSDoc 3.6.7">
<meta charset="utf-8"> <meta charset="utf-8">
<title>whatsapp-web.js 1.12.6 &raquo; Source: structures/MessageMedia.js</title> <title>whatsapp-web.js 1.18.4 &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/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/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 rel="stylesheet" href="https://brick.a.ssl.fastly.net/Inconsolata:500" type="text/css">
@@ -15,7 +15,7 @@
<nav id="jsdoc-navbar" role="navigation" class="jsdoc-navbar"> <nav id="jsdoc-navbar" role="navigation" class="jsdoc-navbar">
<div id="jsdoc-navbar-container"> <div id="jsdoc-navbar-container">
<div id="jsdoc-navbar-content"> <div id="jsdoc-navbar-content">
<a href="index.html" class="jsdoc-navbar-package-name">whatsapp-web.<wbr>js 1.<wbr>12.<wbr>6</a> <a href="index.html" class="jsdoc-navbar-package-name">whatsapp-web.<wbr>js 1.<wbr>18.<wbr>4</a>
</div> </div>
</div> </div>
</nav> </nav>
@@ -34,15 +34,18 @@
const fs &#x3D; require(&#x27;fs&#x27;); const fs &#x3D; require(&#x27;fs&#x27;);
const path &#x3D; require(&#x27;path&#x27;); const path &#x3D; require(&#x27;path&#x27;);
const mime &#x3D; require(&#x27;mime&#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 * Media attached to a message
* @param {string} mimetype MIME type of the attachment * @param {string} mimetype MIME type of the attachment
* @param {string} data Base64-encoded data of the file * @param {string} data Base64-encoded data of the file
* @param {?string} filename Document file name * @param {?string} filename Document file name. Value can be null
* @param {?number} filesize Document file size in bytes. Value can be null
*/ */
class MessageMedia { class MessageMedia {
constructor(mimetype, data, filename) { constructor(mimetype, data, filename, filesize) {
/** /**
* MIME type of the attachment * MIME type of the attachment
* @type {string} * @type {string}
@@ -56,10 +59,16 @@ class MessageMedia {
this.data &#x3D; data; this.data &#x3D; data;
/** /**
* Name of the file (for documents) * Document file name. Value can be null
* @type {?string} * @type {?string}
*/ */
this.filename &#x3D; filename; this.filename &#x3D; filename;
/**
* Document file size in bytes. Value can be null
* @type {?number}
*/
this.filesize &#x3D; filesize;
} }
/** /**
@@ -74,9 +83,64 @@ class MessageMedia {
return new MessageMedia(mimetype, b64data, filename); return new MessageMedia(mimetype, b64data, filename);
} }
/**
* Creates a MessageMedia instance from a URL
* @param {string} url
* @param {Object} [options]
* @param {boolean} [options.unsafeMime&#x3D;false]
* @param {string} [options.filename]
* @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; {}) {
const pUrl &#x3D; new URL(url);
let mimetype &#x3D; mime.getType(pUrl.pathname);
if (!mimetype &amp;amp;&amp;amp; !options.unsafeMime)
throw new Error(&#x27;Unable to determine MIME type using URL. Set unsafeMime to true to download it anyway.&#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;);
const size &#x3D; response.headers.get(&#x27;Content-Length&#x27;);
const contentDisposition &#x3D; response.headers.get(&#x27;Content-Disposition&#x27;);
const name &#x3D; contentDisposition ? contentDisposition.match(/((?&amp;lt;&#x3D;filename&#x3D;&quot;)(.*)(?&#x3D;&quot;))/) : null;
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, name, size };
}
const res &#x3D; options.client
? (await options.client.pupPage.evaluate(fetchData, url, options.reqOptions))
: (await fetchData(url, options.reqOptions));
const filename &#x3D; options.filename ||
(res.name ? res.name[0] : (pUrl.pathname.split(&#x27;/&#x27;).pop() || &#x27;file&#x27;));
if (!mimetype)
mimetype &#x3D; res.mime;
return new MessageMedia(mimetype, res.data, filename, res.size || null);
}
} }
module.exports &#x3D; MessageMedia;</code></pre> module.exports &#x3D; MessageMedia;
</code></pre>
</article> </article>
</div> </div>
</div> </div>
@@ -86,7 +150,7 @@ module.exports &#x3D; MessageMedia;</code></pre>
<footer id="jsdoc-footer" class="jsdoc-footer"> <footer id="jsdoc-footer" class="jsdoc-footer">
<div id="jsdoc-footer-container"> <div id="jsdoc-footer-container">
<p> <p>
Generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc</a> 3.6.6 on April 20, 2021. Generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc</a> 3.6.7 on November 26, 2022.
</p> </p>
</div> </div>
</footer> </footer>

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.18.4 &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>18.<wbr>4</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 November 26, 2022.
</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,133 @@
<!doctype html>
<html>
<head>
<meta name="generator" content="JSDoc 3.6.7">
<meta charset="utf-8">
<title>whatsapp-web.js 1.18.4 &raquo; Source: structures/Payment.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>18.<wbr>4</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/Payment.js</h1>
</header>
<article>
<pre class="prettyprint linenums"><code>const Base &#x3D; require(&#x27;./Base&#x27;);
class Payment extends Base {
constructor(client, data) {
super(client);
if (data) this._patch(data);
}
_patch(data) {
/**
* The payment Id
* @type {object}
*/
this.id &#x3D; data.id;
/**
* The payment currency
* @type {string}
*/
this.paymentCurrency &#x3D; data.paymentCurrency;
/**
* The payment ammount ( R$ 1.00 &#x3D; 1000 )
* @type {number}
*/
this.paymentAmount1000 &#x3D; data.paymentAmount1000;
/**
* The payment receiver
* @type {object}
*/
this.paymentMessageReceiverJid &#x3D; data.paymentMessageReceiverJid;
/**
* The payment transaction timestamp
* @type {number}
*/
this.paymentTransactionTimestamp &#x3D; data.paymentTransactionTimestamp;
/**
* The paymentStatus
*
* Possible Status
* 0:UNKNOWN_STATUS
* 1:PROCESSING
* 2:SENT
* 3:NEED_TO_ACCEPT
* 4:COMPLETE
* 5:COULD_NOT_COMPLETE
* 6:REFUNDED
* 7:EXPIRED
* 8:REJECTED
* 9:CANCELLED
* 10:WAITING_FOR_PAYER
* 11:WAITING
*
* @type {number}
*/
this.paymentStatus &#x3D; data.paymentStatus;
/**
* Integer that represents the payment Text
* @type {number}
*/
this.paymentTxnStatus &#x3D; data.paymentTxnStatus;
/**
* The note sent with the payment
* @type {string}
*/
this.paymentNote &#x3D; !data.paymentNoteMsg ? undefined : data.paymentNoteMsg.body ? data.paymentNoteMsg.body : undefined ;
return super._patch(data);
}
}
module.exports &#x3D; Payment;
</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 November 26, 2022.
</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

@@ -2,9 +2,9 @@
<html> <html>
<head> <head>
<meta name="generator" content="JSDoc 3.6.6"> <meta name="generator" content="JSDoc 3.6.7">
<meta charset="utf-8"> <meta charset="utf-8">
<title>whatsapp-web.js 1.12.6 &raquo; Source: structures/PrivateChat.js</title> <title>whatsapp-web.js 1.18.4 &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/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/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 rel="stylesheet" href="https://brick.a.ssl.fastly.net/Inconsolata:500" type="text/css">
@@ -15,7 +15,7 @@
<nav id="jsdoc-navbar" role="navigation" class="jsdoc-navbar"> <nav id="jsdoc-navbar" role="navigation" class="jsdoc-navbar">
<div id="jsdoc-navbar-container"> <div id="jsdoc-navbar-container">
<div id="jsdoc-navbar-content"> <div id="jsdoc-navbar-content">
<a href="index.html" class="jsdoc-navbar-package-name">whatsapp-web.<wbr>js 1.<wbr>12.<wbr>6</a> <a href="index.html" class="jsdoc-navbar-package-name">whatsapp-web.<wbr>js 1.<wbr>18.<wbr>4</a>
</div> </div>
</div> </div>
</nav> </nav>
@@ -51,7 +51,7 @@ module.exports &#x3D; PrivateChat;</code></pre>
<footer id="jsdoc-footer" class="jsdoc-footer"> <footer id="jsdoc-footer" class="jsdoc-footer">
<div id="jsdoc-footer-container"> <div id="jsdoc-footer-container">
<p> <p>
Generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc</a> 3.6.6 on April 20, 2021. Generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc</a> 3.6.7 on November 26, 2022.
</p> </p>
</div> </div>
</footer> </footer>

View File

@@ -2,9 +2,9 @@
<html> <html>
<head> <head>
<meta name="generator" content="JSDoc 3.6.6"> <meta name="generator" content="JSDoc 3.6.7">
<meta charset="utf-8"> <meta charset="utf-8">
<title>whatsapp-web.js 1.12.6 &raquo; Source: structures/PrivateContact.js</title> <title>whatsapp-web.js 1.18.4 &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/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/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 rel="stylesheet" href="https://brick.a.ssl.fastly.net/Inconsolata:500" type="text/css">
@@ -15,7 +15,7 @@
<nav id="jsdoc-navbar" role="navigation" class="jsdoc-navbar"> <nav id="jsdoc-navbar" role="navigation" class="jsdoc-navbar">
<div id="jsdoc-navbar-container"> <div id="jsdoc-navbar-container">
<div id="jsdoc-navbar-content"> <div id="jsdoc-navbar-content">
<a href="index.html" class="jsdoc-navbar-package-name">whatsapp-web.<wbr>js 1.<wbr>12.<wbr>6</a> <a href="index.html" class="jsdoc-navbar-package-name">whatsapp-web.<wbr>js 1.<wbr>18.<wbr>4</a>
</div> </div>
</div> </div>
</nav> </nav>
@@ -51,7 +51,7 @@ module.exports &#x3D; PrivateContact;</code></pre>
<footer id="jsdoc-footer" class="jsdoc-footer"> <footer id="jsdoc-footer" class="jsdoc-footer">
<div id="jsdoc-footer-container"> <div id="jsdoc-footer-container">
<p> <p>
Generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc</a> 3.6.6 on April 20, 2021. Generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc</a> 3.6.7 on November 26, 2022.
</p> </p>
</div> </div>
</footer> </footer>

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.18.4 &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>18.<wbr>4</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 November 26, 2022.
</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.18.4 &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>18.<wbr>4</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 November 26, 2022.
</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,122 @@
<!doctype html>
<html>
<head>
<meta name="generator" content="JSDoc 3.6.7">
<meta charset="utf-8">
<title>whatsapp-web.js 1.18.4 &raquo; Source: structures/Reaction.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>18.<wbr>4</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/Reaction.js</h1>
</header>
<article>
<pre class="prettyprint linenums"><code>&#x27;use strict&#x27;;
const Base &#x3D; require(&#x27;./Base&#x27;);
/**
* Represents a Reaction on WhatsApp
* @extends {Base}
*/
class Reaction extends Base {
constructor(client, data) {
super(client);
if (data) this._patch(data);
}
_patch(data) {
/**
* Reaction ID
* @type {object}
*/
this.id &#x3D; data.msgKey;
/**
* Orphan
* @type {number}
*/
this.orphan &#x3D; data.orphan;
/**
* Orphan reason
* @type {?string}
*/
this.orphanReason &#x3D; data.orphanReason;
/**
* Unix timestamp for when the reaction was created
* @type {number}
*/
this.timestamp &#x3D; data.timestamp;
/**
* Reaction
* @type {string}
*/
this.reaction &#x3D; data.reactionText;
/**
* Read
* @type {boolean}
*/
this.read &#x3D; data.read;
/**
* Message ID
* @type {object}
*/
this.msgId &#x3D; data.parentMsgKey;
/**
* Sender ID
* @type {string}
*/
this.senderId &#x3D; data.senderUserJid;
/**
* ACK
* @type {?number}
*/
this.ack &#x3D; data.ack;
return super._patch(data);
}
}
module.exports &#x3D; Reaction;</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 November 26, 2022.
</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

@@ -2,9 +2,9 @@
<html> <html>
<head> <head>
<meta name="generator" content="JSDoc 3.6.6"> <meta name="generator" content="JSDoc 3.6.7">
<meta charset="utf-8"> <meta charset="utf-8">
<title>whatsapp-web.js 1.12.6 &raquo; Source: util/Constants.js</title> <title>whatsapp-web.js 1.18.4 &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/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/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 rel="stylesheet" href="https://brick.a.ssl.fastly.net/Inconsolata:500" type="text/css">
@@ -15,7 +15,7 @@
<nav id="jsdoc-navbar" role="navigation" class="jsdoc-navbar"> <nav id="jsdoc-navbar" role="navigation" class="jsdoc-navbar">
<div id="jsdoc-navbar-container"> <div id="jsdoc-navbar-container">
<div id="jsdoc-navbar-content"> <div id="jsdoc-navbar-content">
<a href="index.html" class="jsdoc-navbar-package-name">whatsapp-web.<wbr>js 1.<wbr>12.<wbr>6</a> <a href="index.html" class="jsdoc-navbar-package-name">whatsapp-web.<wbr>js 1.<wbr>18.<wbr>4</a>
</div> </div>
</div> </div>
</nav> </nav>
@@ -38,14 +38,13 @@ exports.DefaultOptions &#x3D; {
headless: true, headless: true,
defaultViewport: null defaultViewport: null
}, },
session: false, authTimeoutMs: 0,
qrTimeoutMs: 45000, qrMaxRetries: 0,
qrRefreshIntervalMs: 20000,
authTimeoutMs: 45000,
takeoverOnConflict: false, takeoverOnConflict: false,
takeoverTimeoutMs: 0, 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;, userAgent: &#x27;Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.67 Safari/537.36&#x27;,
ffmpegPath: &#x27;ffmpeg&#x27; ffmpegPath: &#x27;ffmpeg&#x27;,
bypassCSP: false
}; };
/** /**
@@ -73,14 +72,18 @@ exports.Events &#x3D; {
MESSAGE_REVOKED_EVERYONE: &#x27;message_revoke_everyone&#x27;, MESSAGE_REVOKED_EVERYONE: &#x27;message_revoke_everyone&#x27;,
MESSAGE_REVOKED_ME: &#x27;message_revoke_me&#x27;, MESSAGE_REVOKED_ME: &#x27;message_revoke_me&#x27;,
MESSAGE_ACK: &#x27;message_ack&#x27;, MESSAGE_ACK: &#x27;message_ack&#x27;,
MESSAGE_REACTION: &#x27;message_reaction&#x27;,
MEDIA_UPLOADED: &#x27;media_uploaded&#x27;, MEDIA_UPLOADED: &#x27;media_uploaded&#x27;,
GROUP_JOIN: &#x27;group_join&#x27;, GROUP_JOIN: &#x27;group_join&#x27;,
GROUP_LEAVE: &#x27;group_leave&#x27;, GROUP_LEAVE: &#x27;group_leave&#x27;,
GROUP_UPDATE: &#x27;group_update&#x27;, GROUP_UPDATE: &#x27;group_update&#x27;,
QR_RECEIVED: &#x27;qr&#x27;, QR_RECEIVED: &#x27;qr&#x27;,
LOADING_SCREEN: &#x27;loading_screen&#x27;,
DISCONNECTED: &#x27;disconnected&#x27;, DISCONNECTED: &#x27;disconnected&#x27;,
STATE_CHANGED: &#x27;change_state&#x27;, STATE_CHANGED: &#x27;change_state&#x27;,
BATTERY_CHANGED: &#x27;change_battery&#x27; BATTERY_CHANGED: &#x27;change_battery&#x27;,
INCOMING_CALL: &#x27;incoming_call&#x27;,
REMOTE_SESSION_SAVED: &#x27;remote_session_saved&#x27;
}; };
/** /**
@@ -99,8 +102,31 @@ exports.MessageTypes &#x3D; {
LOCATION: &#x27;location&#x27;, LOCATION: &#x27;location&#x27;,
CONTACT_CARD: &#x27;vcard&#x27;, CONTACT_CARD: &#x27;vcard&#x27;,
CONTACT_CARD_MULTI: &#x27;multi_vcard&#x27;, CONTACT_CARD_MULTI: &#x27;multi_vcard&#x27;,
ORDER: &#x27;order&#x27;,
REVOKED: &#x27;revoked&#x27;, REVOKED: &#x27;revoked&#x27;,
UNKNOWN: &#x27;unknown&#x27; PRODUCT: &#x27;product&#x27;,
UNKNOWN: &#x27;unknown&#x27;,
GROUP_INVITE: &#x27;groups_v4_invite&#x27;,
LIST: &#x27;list&#x27;,
LIST_RESPONSE: &#x27;list_response&#x27;,
BUTTONS_RESPONSE: &#x27;buttons_response&#x27;,
PAYMENT: &#x27;payment&#x27;,
BROADCAST_NOTIFICATION: &#x27;broadcast_notification&#x27;,
CALL_LOG: &#x27;call_log&#x27;,
CIPHERTEXT: &#x27;ciphertext&#x27;,
DEBUG: &#x27;debug&#x27;,
E2E_NOTIFICATION: &#x27;e2e_notification&#x27;,
GP2: &#x27;gp2&#x27;,
GROUP_NOTIFICATION: &#x27;group_notification&#x27;,
HSM: &#x27;hsm&#x27;,
INTERACTIVE: &#x27;interactive&#x27;,
NATIVE_FLOW: &#x27;native_flow&#x27;,
NOTIFICATION: &#x27;notification&#x27;,
NOTIFICATION_TEMPLATE: &#x27;notification_template&#x27;,
OVERSIZED: &#x27;oversized&#x27;,
PROTOCOL: &#x27;protocol&#x27;,
REACTION: &#x27;reaction&#x27;,
TEMPLATE_BUTTON_REPLY: &#x27;template_button_reply&#x27;,
}; };
/** /**
@@ -174,7 +200,7 @@ exports.MessageAck &#x3D; {
<footer id="jsdoc-footer" class="jsdoc-footer"> <footer id="jsdoc-footer" class="jsdoc-footer">
<div id="jsdoc-footer-container"> <div id="jsdoc-footer-container">
<p> <p>
Generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc</a> 3.6.6 on April 20, 2021. Generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc</a> 3.6.7 on November 26, 2022.
</p> </p>
</div> </div>
</footer> </footer>

View File

@@ -2,9 +2,9 @@
<html> <html>
<head> <head>
<meta name="generator" content="JSDoc 3.6.6"> <meta name="generator" content="JSDoc 3.6.7">
<meta charset="utf-8"> <meta charset="utf-8">
<title>whatsapp-web.js 1.12.6 &raquo; Source: util/InterfaceController.js</title> <title>whatsapp-web.js 1.18.4 &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/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/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 rel="stylesheet" href="https://brick.a.ssl.fastly.net/Inconsolata:500" type="text/css">
@@ -15,7 +15,7 @@
<nav id="jsdoc-navbar" role="navigation" class="jsdoc-navbar"> <nav id="jsdoc-navbar" role="navigation" class="jsdoc-navbar">
<div id="jsdoc-navbar-container"> <div id="jsdoc-navbar-container">
<div id="jsdoc-navbar-content"> <div id="jsdoc-navbar-content">
<a href="index.html" class="jsdoc-navbar-package-name">whatsapp-web.<wbr>js 1.<wbr>12.<wbr>6</a> <a href="index.html" class="jsdoc-navbar-package-name">whatsapp-web.<wbr>js 1.<wbr>18.<wbr>4</a>
</div> </div>
</div> </div>
</nav> </nav>
@@ -46,7 +46,8 @@ class InterfaceController {
*/ */
async openChatWindow(chatId) { async openChatWindow(chatId) {
await this.pupPage.evaluate(async chatId &#x3D;&gt; { await this.pupPage.evaluate(async chatId &#x3D;&gt; {
let chat &#x3D; await window.Store.Chat.get(chatId); let chatWid &#x3D; window.Store.WidFactory.createWid(chatId);
let chat &#x3D; await window.Store.Chat.find(chatWid);
await window.Store.Cmd.openChatAt(chat); await window.Store.Cmd.openChatAt(chat);
}, chatId); }, chatId);
} }
@@ -58,7 +59,7 @@ class InterfaceController {
async openChatDrawer(chatId) { async openChatDrawer(chatId) {
await this.pupPage.evaluate(async chatId &#x3D;&gt; { await this.pupPage.evaluate(async chatId &#x3D;&gt; {
let chat &#x3D; await window.Store.Chat.get(chatId); let chat &#x3D; await window.Store.Chat.get(chatId);
await window.Store.Cmd.chatInfoDrawer(chat); await window.Store.Cmd.openDrawerMid(chat);
}, chatId); }, chatId);
} }
@@ -103,10 +104,53 @@ class InterfaceController {
await window.Store.Cmd.closeDrawerRight(); 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> module.exports &#x3D; InterfaceController;
</code></pre>
</article> </article>
</div> </div>
</div> </div>
@@ -116,7 +160,7 @@ module.exports &#x3D; InterfaceController;</code></pre>
<footer id="jsdoc-footer" class="jsdoc-footer"> <footer id="jsdoc-footer" class="jsdoc-footer">
<div id="jsdoc-footer-container"> <div id="jsdoc-footer-container">
<p> <p>
Generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc</a> 3.6.6 on April 20, 2021. Generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc</a> 3.6.7 on November 26, 2022.
</p> </p>
</div> </div>
</footer> </footer>

View File

@@ -2,9 +2,9 @@
<html> <html>
<head> <head>
<meta name="generator" content="JSDoc 3.6.6"> <meta name="generator" content="JSDoc 3.6.7">
<meta charset="utf-8"> <meta charset="utf-8">
<title>whatsapp-web.js 1.12.6 &raquo; Source: util/Util.js</title> <title>whatsapp-web.js 1.18.4 &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/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/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 rel="stylesheet" href="https://brick.a.ssl.fastly.net/Inconsolata:500" type="text/css">
@@ -15,7 +15,7 @@
<nav id="jsdoc-navbar" role="navigation" class="jsdoc-navbar"> <nav id="jsdoc-navbar" role="navigation" class="jsdoc-navbar">
<div id="jsdoc-navbar-container"> <div id="jsdoc-navbar-container">
<div id="jsdoc-navbar-content"> <div id="jsdoc-navbar-content">
<a href="index.html" class="jsdoc-navbar-package-name">whatsapp-web.<wbr>js 1.<wbr>12.<wbr>6</a> <a href="index.html" class="jsdoc-navbar-package-name">whatsapp-web.<wbr>js 1.<wbr>18.<wbr>4</a>
</div> </div>
</div> </div>
</nav> </nav>
@@ -31,24 +31,32 @@
<article> <article>
<pre class="prettyprint linenums"><code>&#x27;use strict&#x27;; <pre class="prettyprint linenums"><code>&#x27;use strict&#x27;;
const sharp &#x3D; require(&#x27;sharp&#x27;);
const path &#x3D; require(&#x27;path&#x27;); const path &#x3D; require(&#x27;path&#x27;);
const Crypto &#x3D; require(&#x27;crypto&#x27;); const Crypto &#x3D; require(&#x27;crypto&#x27;);
const { tmpdir } &#x3D; require(&#x27;os&#x27;); const { tmpdir } &#x3D; require(&#x27;os&#x27;);
const ffmpeg &#x3D; require(&#x27;fluent-ffmpeg&#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 fs &#x3D; require(&#x27;fs&#x27;).promises;
const has &#x3D; (o, k) &#x3D;&gt; Object.prototype.hasOwnProperty.call(o, k); const has &#x3D; (o, k) &#x3D;&gt; Object.prototype.hasOwnProperty.call(o, k);
/** /**
* Utility methods * Utility methods
*/ */
class Util { class Util {
constructor() { constructor() {
throw new Error(&#x60;The ${this.constructor.name} class may not be instantiated.&#x60;); 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. * Sets default properties on an object that aren&#x27;t already specified.
* @param {Object} def Default properties * @param {Object} def Default properties
@@ -75,33 +83,19 @@ class Util {
* *
* @returns {Promise&amp;lt;MessageMedia&gt;} media in webp format * @returns {Promise&amp;lt;MessageMedia&gt;} media in webp format
*/ */
static async formatImageToWebpSticker(media) { static async formatImageToWebpSticker(media, pupPage) {
if (!media.mimetype.includes(&#x27;image&#x27;)) if (!media.mimetype.includes(&#x27;image&#x27;))
throw new Error(&#x27;media is not a image&#x27;); throw new Error(&#x27;media is not a image&#x27;);
if (media.mimetype.includes(&#x27;webp&#x27;)) { if (media.mimetype.includes(&#x27;webp&#x27;)) {
return media; return media;
} }
const buff &#x3D; Buffer.from(media.data, &#x27;base64&#x27;); return pupPage.evaluate((media) &#x3D;&gt; {
return window.WWebJS.toStickerData(media);
let sharpImg &#x3D; sharp(buff); }, media);
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 * Formats a video to webp
* @param {MessageMedia} media * @param {MessageMedia} media
@@ -111,14 +105,14 @@ class Util {
static async formatVideoToWebpSticker(media) { static async formatVideoToWebpSticker(media) {
if (!media.mimetype.includes(&#x27;video&#x27;)) if (!media.mimetype.includes(&#x27;video&#x27;))
throw new Error(&#x27;media is not a video&#x27;); throw new Error(&#x27;media is not a video&#x27;);
const videoType &#x3D; media.mimetype.split(&#x27;/&#x27;)[1]; const videoType &#x3D; media.mimetype.split(&#x27;/&#x27;)[1];
const tempFile &#x3D; path.join( const tempFile &#x3D; path.join(
tmpdir(), tmpdir(),
&#x60;${Crypto.randomBytes(6).readUIntLE(0, 6).toString(36)}.webp&#x60; &#x60;${Crypto.randomBytes(6).readUIntLE(0, 6).toString(36)}.webp&#x60;
); );
const stream &#x3D; new (require(&#x27;stream&#x27;).Readable)(); const stream &#x3D; new (require(&#x27;stream&#x27;).Readable)();
const buffer &#x3D; Buffer.from( const buffer &#x3D; Buffer.from(
media.data.replace(&#x60;data:${media.mimetype};base64,&#x60;, &#x27;&#x27;), media.data.replace(&#x60;data:${media.mimetype};base64,&#x60;, &#x27;&#x27;),
@@ -155,27 +149,60 @@ class Util {
.toFormat(&#x27;webp&#x27;) .toFormat(&#x27;webp&#x27;)
.save(tempFile); .save(tempFile);
}); });
const data &#x3D; await fs.readFile(tempFile, &#x27;base64&#x27;); const data &#x3D; await fs.readFile(tempFile, &#x27;base64&#x27;);
await fs.unlink(tempFile); await fs.unlink(tempFile);
return { return {
mimetype: &#x27;image/webp&#x27;, mimetype: &#x27;image/webp&#x27;,
data: data, data: data,
filename: media.filename, filename: media.filename,
}; };
} }
/**
* Sticker metadata.
* @typedef {Object} StickerMetadata
* @property {string} [name]
* @property {string} [author]
* @property {string[]} [categories]
*/
/** /**
* Formats a media to webp * Formats a media to webp
* @param {MessageMedia} media * @param {MessageMedia} media
* @param {StickerMetadata} metadata
* *
* @returns {Promise&amp;lt;MessageMedia&gt;} media in webp format * @returns {Promise&amp;lt;MessageMedia&gt;} media in webp format
*/ */
static async formatToWebpSticker(media) { static async formatToWebpSticker(media, metadata, pupPage) {
if (media.mimetype.includes(&#x27;image&#x27;)) return this.formatImageToWebpSticker(media); let webpMedia;
else if (media.mimetype.includes(&#x27;video&#x27;)) return this.formatVideoToWebpSticker(media);
else throw new Error(&#x27;Invalid media format&#x27;); if (media.mimetype.includes(&#x27;image&#x27;))
webpMedia &#x3D; await this.formatImageToWebpSticker(media, pupPage);
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;
} }
/** /**
@@ -187,7 +214,8 @@ class Util {
} }
} }
module.exports &#x3D; Util;</code></pre> module.exports &#x3D; Util;
</code></pre>
</article> </article>
</div> </div>
</div> </div>
@@ -197,7 +225,7 @@ module.exports &#x3D; Util;</code></pre>
<footer id="jsdoc-footer" class="jsdoc-footer"> <footer id="jsdoc-footer" class="jsdoc-footer">
<div id="jsdoc-footer-container"> <div id="jsdoc-footer-container">
<p> <p>
Generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc</a> 3.6.6 on April 20, 2021. Generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc</a> 3.6.7 on November 26, 2022.
</p> </p>
</div> </div>
</footer> </footer>

View File

@@ -1,35 +1,27 @@
const fs = require('fs'); const { Client, Location, List, Buttons, LocalAuth} = require('./index');
const { Client, Location } = require('./index');
const SESSION_FILE_PATH = './session.json'; const client = new Client({
let sessionCfg; authStrategy: new LocalAuth(),
if (fs.existsSync(SESSION_FILE_PATH)) { puppeteer: { headless: false }
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.
client.initialize(); client.initialize();
client.on('loading_screen', (percent, message) => {
console.log('LOADING SCREEN', percent, message);
});
client.on('qr', (qr) => { client.on('qr', (qr) => {
// NOTE: This event will not be fired if a session is specified. // NOTE: This event will not be fired if a session is specified.
console.log('QR RECEIVED', qr); console.log('QR RECEIVED', qr);
}); });
client.on('authenticated', (session) => { client.on('authenticated', () => {
console.log('AUTHENTICATED', session); console.log('AUTHENTICATED');
sessionCfg=session;
fs.writeFile(SESSION_FILE_PATH, JSON.stringify(session), function (err) {
if (err) {
console.error(err);
}
});
}); });
client.on('auth_failure', msg => { client.on('auth_failure', msg => {
// Fired if session restore was unsuccessfull // Fired if session restore was unsuccessful
console.error('AUTHENTICATION FAILURE', msg); console.error('AUTHENTICATION FAILURE', msg);
}); });
@@ -117,9 +109,8 @@ client.on('message', async msg => {
client.sendMessage(msg.from, ` client.sendMessage(msg.from, `
*Connection info* *Connection info*
User name: ${info.pushname} User name: ${info.pushname}
My number: ${info.me.user} My number: ${info.wid.user}
Platform: ${info.platform} Platform: ${info.platform}
WhatsApp version: ${info.phone.wa_version}
`); `);
} else if (msg.body === '!mediainfo' && msg.hasMedia) { } else if (msg.body === '!mediainfo' && msg.hasMedia) {
const attachmentData = await msg.downloadMedia(); const attachmentData = await msg.downloadMedia();
@@ -192,11 +183,20 @@ client.on('message', async msg => {
const chat = await msg.getChat(); const chat = await msg.getChat();
// stops typing or recording in the chat // stops typing or recording in the chat
chat.clearState(); chat.clearState();
} else if (msg.body === 'jumpto') { } else if (msg.body === '!jumpto') {
if (msg.hasQuotedMsg) { if (msg.hasQuotedMsg) {
const quotedMsg = await msg.getQuotedMessage(); const quotedMsg = await msg.getQuotedMessage();
client.interface.openChatWindowAt(quotedMsg.id._serialized); client.interface.openChatWindowAt(quotedMsg.id._serialized);
} }
} else if (msg.body === '!buttons') {
let button = new Buttons('Button body',[{body:'bt1'},{body:'bt2'},{body:'bt3'}],'title','footer');
client.sendMessage(msg.from, button);
} else if (msg.body === '!list') {
let sections = [{title:'sectionTitle',rows:[{title:'ListItem1', description: 'desc'},{title:'ListItem2'}]}];
let list = new List('List body','btnText',sections,'Title','footer');
client.sendMessage(msg.from, list);
} else if (msg.body === '!reaction') {
msg.react('👍');
} }
}); });
@@ -253,12 +253,6 @@ client.on('group_update', (notification) => {
console.log('update', notification); 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 => { client.on('change_state', state => {
console.log('CHANGE STATE', state ); console.log('CHANGE STATE', state );
}); });

550
index.d.ts vendored
View File

@@ -1,6 +1,7 @@
import { EventEmitter } from 'events' import { EventEmitter } from 'events'
import puppeteer = require('puppeteer') import { RequestInit } from 'node-fetch'
import * as puppeteer from 'puppeteer'
declare namespace WAWebJS { declare namespace WAWebJS {
@@ -19,6 +20,9 @@ declare namespace WAWebJS {
/**Accepts an invitation to join a group */ /**Accepts an invitation to join a group */
acceptInvite(inviteCode: string): Promise<string> acceptInvite(inviteCode: string): Promise<string>
/** Accepts a private invitation to join a group (v4 invite) */
acceptGroupV4Invite: (inviteV4: InviteV4Data) => Promise<{status: number}>
/**Returns an object with information about the invite code's group */ /**Returns an object with information about the invite code's group */
getInviteInfo(inviteCode: string): Promise<object> getInviteInfo(inviteCode: string): Promise<object>
@@ -44,6 +48,9 @@ declare namespace WAWebJS {
/** Logs out the client, closing the current session */ /** Logs out the client, closing the current session */
logout(): Promise<void> logout(): Promise<void>
/** Get all blocked contacts by host account */
getBlockedContacts(): Promise<Contact[]>
/** Get chat instance by ID */ /** Get chat instance by ID */
getChatById(chatId: string): Promise<Chat> getChatById(chatId: string): Promise<Chat>
@@ -55,6 +62,12 @@ declare namespace WAWebJS {
/** Get all current contact instances */ /** Get all current contact instances */
getContacts(): Promise<Contact[]> getContacts(): Promise<Contact[]>
/** Get the country code of a WhatsApp ID. (154185968@c.us) => (1) */
getCountryCode(number: string): Promise<string>
/** Get the formatted number of a WhatsApp ID. (12345678901@c.us) => (+1 (234) 5678-901) */
getFormattedNumber(number: string): Promise<string>
/** Get all current Labels */ /** Get all current Labels */
getLabels(): Promise<Label[]> getLabels(): Promise<Label[]>
@@ -71,6 +84,9 @@ declare namespace WAWebJS {
/** Returns the contact ID's profile picture URL, if privacy settings allow it */ /** Returns the contact ID's profile picture URL, if privacy settings allow it */
getProfilePicUrl(contactId: string): Promise<string> getProfilePicUrl(contactId: string): Promise<string>
/** Gets the Contact's common groups with you. Returns empty array if you don't have any common group. */
getCommonGroups(contactId: string): Promise<ChatId[]>
/** Gets the current connection state for the client */ /** Gets the current connection state for the client */
getState(): Promise<WAState> getState(): Promise<WAState>
@@ -87,21 +103,27 @@ declare namespace WAWebJS {
getNumberId(number: string): Promise<ContactId | null> getNumberId(number: string): Promise<ContactId | null>
/** /**
* Mutes the Chat until a specified date * Mutes this chat forever, unless a date is specified
* @param chatId ID of the chat that will be muted * @param chatId ID of the chat that will be muted
* @param unmuteDate Date when the chat will be unmuted * @param unmuteDate Date when the chat will be unmuted, leave as is to mute forever
*/ */
muteChat(chatId: string, unmuteDate: Date): Promise<void> muteChat(chatId: string, unmuteDate?: Date): Promise<void>
/** Force reset of connection state for the client */ /** Force reset of connection state for the client */
resetState(): Promise<void> resetState(): Promise<void>
/** Send a message to a specific chatId */ /** Send a message to a specific chatId */
sendMessage(chatId: string, content: MessageContent, options?: MessageSendOptions): Promise<Message> sendMessage(chatId: string, content: MessageContent, options?: MessageSendOptions): Promise<Message>
/** Searches for messages */
searchMessages(query: string, options?: { chatId?: string, page?: number, limit?: number }): Promise<Message[]>
/** Marks the client as online */ /** Marks the client as online */
sendPresenceAvailable(): Promise<void> sendPresenceAvailable(): Promise<void>
/** Marks the client as offline */
sendPresenceUnavailable(): Promise<void>
/** Mark as seen for the Chat */ /** Mark as seen for the Chat */
sendSeen(chatId: string): Promise<boolean> sendSeen(chatId: string): Promise<boolean>
@@ -118,8 +140,8 @@ declare namespace WAWebJS {
* Sets the current user's display name * Sets the current user's display name
* @param displayName New display name * @param displayName New display name
*/ */
setDisplayName(displayName: string): Promise<void> setDisplayName(displayName: string): Promise<boolean>
/** Changes and returns the archive state of the Chat */ /** Changes and returns the archive state of the Chat */
unarchiveChat(chatId: string): Promise<boolean> unarchiveChat(chatId: string): Promise<boolean>
@@ -134,11 +156,16 @@ declare namespace WAWebJS {
/** Emitted when authentication is successful */ /** Emitted when authentication is successful */
on(event: 'authenticated', listener: ( on(event: 'authenticated', listener: (
/** Object containing session information. Can be used to restore the session */ /**
session: ClientSession * Object containing session information, when using LegacySessionAuth. Can be used to restore the session
*/
session?: ClientSession
) => void): this ) => void): this
/** Emitted when the battery percentage for the attached device changes */ /**
* Emitted when the battery percentage for the attached device changes
* @deprecated
*/
on(event: 'change_battery', listener: (batteryInfo: BatteryInfo) => void): this on(event: 'change_battery', listener: (batteryInfo: BatteryInfo) => void): this
/** Emitted when the connection state changes */ /** Emitted when the connection state changes */
@@ -150,7 +177,7 @@ declare namespace WAWebJS {
/** Emitted when the client has been disconnected */ /** Emitted when the client has been disconnected */
on(event: 'disconnected', listener: ( on(event: 'disconnected', listener: (
/** reason that caused the disconnect */ /** reason that caused the disconnect */
reason: WAState | "NAVIGATED" reason: WAState | "NAVIGATION"
) => void): this ) => void): this
/** Emitted when a user joins the chat via invite link or is added by an admin */ /** Emitted when a user joins the chat via invite link or is added by an admin */
@@ -214,6 +241,15 @@ declare namespace WAWebJS {
message: Message message: Message
) => void): this ) => void): this
/** Emitted when a reaction is sent, received, updated or removed */
on(event: 'message_reaction', listener: (
/** The reaction object */
reaction: Reaction
) => void): this
/** Emitted when loading screen is appearing */
on(event: 'loading_screen', listener: (percent: string, message: string) => void): this
/** Emitted when the QR code is received */ /** Emitted when the QR code is received */
on(event: 'qr', listener: ( on(event: 'qr', listener: (
/** qr code string /** qr code string
@@ -221,8 +257,17 @@ declare namespace WAWebJS {
qr: string qr: string
) => void): this ) => void): this
/** Emitted when a call is received */
on(event: 'call', listener: (
/** The call that started */
call: Call
) => void): this
/** Emitted when the client has initialized and is ready to receive messages */ /** Emitted when the client has initialized and is ready to receive messages */
on(event: 'ready', listener: () => void): this on(event: 'ready', listener: () => void): this
/** Emitted when the RemoteAuth session is saved successfully on the external Database */
on(event: 'remote_session_saved', listener: () => void): this
} }
/** Current connection information */ /** Current connection information */
@@ -234,7 +279,10 @@ declare namespace WAWebJS {
me: ContactId me: ContactId
/** Current user ID */ /** Current user ID */
wid: ContactId wid: ContactId
/** Information about the phone this client is connected to */ /**
* Information about the phone this client is connected to. Not available in multi-device.
* @deprecated
*/
phone: ClientInfoPhone phone: ClientInfoPhone
/** Platform the phone is running on */ /** Platform the phone is running on */
platform: string platform: string
@@ -245,7 +293,10 @@ declare namespace WAWebJS {
getBatteryStatus: () => Promise<BatteryInfo> getBatteryStatus: () => Promise<BatteryInfo>
} }
/** Information about the phone this client is connected to */ /**
* Information about the phone this client is connected to
* @deprecated
*/
export interface ClientInfoPhone { export interface ClientInfoPhone {
/** WhatsApp Version running on the phone */ /** WhatsApp Version running on the phone */
wa_version: string wa_version: string
@@ -262,20 +313,22 @@ declare namespace WAWebJS {
/** Options for initializing the whatsapp client */ /** Options for initializing the whatsapp client */
export interface ClientOptions { export interface ClientOptions {
/** Timeout for authentication selector in puppeteer /** Timeout for authentication selector in puppeteer
* @default 45000 */ * @default 0 */
authTimeoutMs?: number, authTimeoutMs?: number,
/** Puppeteer launch options. View docs here: https://github.com/puppeteer/puppeteer/ */ /** Puppeteer launch options. View docs here: https://github.com/puppeteer/puppeteer/ */
puppeteer?: puppeteer.LaunchOptions puppeteer?: puppeteer.PuppeteerNodeLaunchOptions & puppeteer.ConnectOptions
/** Refresh interval for qr code (how much time to wait before checking if the qr code has changed) /** Determines how to save and restore sessions. Will use LegacySessionAuth if options.session is set. Otherwise, NoAuth will be used. */
* @default 20000 */ authStrategy?: AuthStrategy,
qrRefreshIntervalMs?: number /** How many times should the qrcode be refreshed before giving up
/** Timeout for qr code selector in puppeteer * @default 0 (disabled) */
* @default 45000 */ qrMaxRetries?: number,
qrTimeoutMs?: number, /**
/** Restart client with a new session (i.e. use null 'session' var) if authentication fails * @deprecated This option should be set directly on the LegacySessionAuth
* @default false */ */
restartOnAuthFail?: boolean restartOnAuthFail?: boolean
/** Whatsapp session to restore. If not set, will start a new session */ /**
* @deprecated Only here for backwards-compatibility. You should move to using LocalAuth, or set the authStrategy to LegacySessionAuth explicitly.
*/
session?: ClientSession session?: ClientSession
/** If another whatsapp web session is detected (another browser), take over the session in the current browser /** If another whatsapp web session is detected (another browser), take over the session in the current browser
* @default false */ * @default false */
@@ -291,7 +344,81 @@ declare namespace WAWebJS {
ffmpegPath?: string ffmpegPath?: string
} }
/** Represents a Whatsapp client session */ /**
* Base class which all authentication strategies extend
*/
export abstract class AuthStrategy {
setup: (client: Client) => void;
beforeBrowserInitialized: () => Promise<void>;
afterBrowserInitialized: () => Promise<void>;
onAuthenticationNeeded: () => Promise<{
failed?: boolean;
restart?: boolean;
failureEventPayload?: any
}>;
getAuthEventPayload: () => Promise<any>;
afterAuthReady: () => Promise<void>;
disconnect: () => Promise<void>;
destroy: () => Promise<void>;
logout: () => Promise<void>;
}
/**
* No session restoring functionality
* Will need to authenticate via QR code every time
*/
export class NoAuth extends AuthStrategy {}
/**
* Local directory-based authentication
*/
export class LocalAuth extends AuthStrategy {
public clientId?: string;
public dataPath?: string;
constructor(options?: {
clientId?: string,
dataPath?: string
})
}
/**
* Remote-based authentication
*/
export class RemoteAuth extends AuthStrategy {
public clientId?: string;
public dataPath?: string;
constructor(options?: {
store: Store,
clientId?: string,
dataPath?: string,
backupSyncIntervalMs: number
})
}
/**
* Remote store interface
*/
export interface Store {
sessionExists: (options: { session: string }) => Promise<boolean> | boolean,
delete: (options: { session: string }) => Promise<any> | any,
save: (options: { session: string }) => Promise<any> | any,
extract: (options: { session: string, path: string }) => Promise<any> | any,
}
/**
* Legacy session auth strategy
* Not compatible with multi-device accounts.
*/
export class LegacySessionAuth extends AuthStrategy {
constructor(options?: {
session?: ClientSession,
restartOnAuthFail?: boolean,
})
}
/**
* Represents a WhatsApp client session
*/
export interface ClientSession { export interface ClientSession {
WABrowserId: string, WABrowserId: string,
WASecretBundle: string, WASecretBundle: string,
@@ -299,6 +426,9 @@ declare namespace WAWebJS {
WAToken2: string, WAToken2: string,
} }
/**
* @deprecated
*/
export interface BatteryInfo { export interface BatteryInfo {
/** The current battery percentage */ /** The current battery percentage */
battery: number, battery: number,
@@ -343,7 +473,7 @@ declare namespace WAWebJS {
reply: (content: MessageContent, options?: MessageSendOptions) => Promise<Message>, reply: (content: MessageContent, options?: MessageSendOptions) => Promise<Message>,
} }
/** whatsapp web url */ /** whatsapp web url */
export const WhatsWebURL: string export const WhatsWebURL: string
@@ -372,9 +502,11 @@ declare namespace WAWebJS {
GROUP_LEAVE = 'group_leave', GROUP_LEAVE = 'group_leave',
GROUP_UPDATE = 'group_update', GROUP_UPDATE = 'group_update',
QR_RECEIVED = 'qr', QR_RECEIVED = 'qr',
LOADING_SCREEN = 'loading_screen',
DISCONNECTED = 'disconnected', DISCONNECTED = 'disconnected',
STATE_CHANGED = 'change_state', STATE_CHANGED = 'change_state',
BATTERY_CHANGED = 'change_battery', BATTERY_CHANGED = 'change_battery',
REMOTE_SESSION_SAVED = 'remote_session_saved'
} }
/** Group notification types */ /** Group notification types */
@@ -413,7 +545,30 @@ declare namespace WAWebJS {
CONTACT_CARD = 'vcard', CONTACT_CARD = 'vcard',
CONTACT_CARD_MULTI = 'multi_vcard', CONTACT_CARD_MULTI = 'multi_vcard',
REVOKED = 'revoked', REVOKED = 'revoked',
ORDER = 'order',
PRODUCT = 'product',
PAYMENT = 'payment',
UNKNOWN = 'unknown', UNKNOWN = 'unknown',
GROUP_INVITE = 'groups_v4_invite',
LIST = 'list',
LIST_RESPONSE = 'list_response',
BUTTONS_RESPONSE = 'buttons_response',
BROADCAST_NOTIFICATION = 'broadcast_notification',
CALL_LOG = 'call_log',
CIPHERTEXT = 'ciphertext',
DEBUG = 'debug',
E2E_NOTIFICATION = 'e2e_notification',
GP2 = 'gp2',
GROUP_NOTIFICATION = 'group_notification',
HSM = 'hsm',
INTERACTIVE = 'interactive',
NATIVE_FLOW = 'native_flow',
NOTIFICATION = 'notification',
NOTIFICATION_TEMPLATE = 'notification_template',
OVERSIZED = 'oversized',
PROTOCOL = 'protocol',
REACTION = 'reaction',
TEMPLATE_BUTTON_REPLY = 'template_button_reply',
} }
/** Client status */ /** Client status */
@@ -448,6 +603,15 @@ declare namespace WAWebJS {
readRemaining: number readRemaining: number
} }
export type InviteV4Data = {
inviteCode: string,
inviteCodeExp: number,
groupId: string,
groupName?: string,
fromId: string,
toId: string
}
/** /**
* Represents a Message on WhatsApp * Represents a Message on WhatsApp
* *
@@ -481,12 +645,18 @@ declare namespace WAWebJS {
ack: MessageAck, ack: MessageAck,
/** If the message was sent to a group, this field will contain the user that sent the message. */ /** If the message was sent to a group, this field will contain the user that sent the message. */
author?: string, author?: string,
/** String that represents from which device type the message was sent */
deviceType: string,
/** Message content */ /** Message content */
body: string, body: string,
/** Indicates if the message was a broadcast */ /** Indicates if the message was a broadcast */
broadcast: boolean, broadcast: boolean,
/** Indicates if the message was a status update */ /** Indicates if the message was a status update */
isStatus: boolean, isStatus: boolean,
/** Indicates if the message is a Gif */
isGif: boolean,
/** Indicates if the message will disappear after it expires */
isEphemeral: boolean,
/** ID for the Chat that this message was sent to, except if the message was sent by the current user */ /** ID for the Chat that this message was sent to, except if the message was sent by the current user */
from: string, from: string,
/** Indicates if the message was sent by the current user */ /** Indicates if the message was sent by the current user */
@@ -495,16 +665,25 @@ declare namespace WAWebJS {
hasMedia: boolean, hasMedia: boolean,
/** Indicates if the message was sent as a reply to another message */ /** Indicates if the message was sent as a reply to another message */
hasQuotedMsg: boolean, hasQuotedMsg: boolean,
/** Indicates the duration of the message in seconds */
duration: string,
/** ID that represents the message */ /** ID that represents the message */
id: MessageId, id: MessageId,
/** Indicates if the message was forwarded */ /** Indicates if the message was forwarded */
isForwarded: boolean, isForwarded: boolean,
/**
* Indicates how many times the message was forwarded.
* The maximum value is 127.
*/
forwardingScore: number,
/** Indicates if the message was starred */ /** Indicates if the message was starred */
isStarred: boolean, isStarred: boolean,
/** Location information contained in the message, if the message is type "location" */ /** Location information contained in the message, if the message is type "location" */
location: Location, location: Location,
/** List of vCards contained in the message */ /** List of vCards contained in the message */
vCards: string[], vCards: string[],
/** Invite v4 info */
inviteV4?: InviteV4Data,
/** MediaKey that represents the sticker 'ID' */ /** MediaKey that represents the sticker 'ID' */
mediaKey?: string, mediaKey?: string,
/** Indicates the mentions in the message body. */ /** Indicates the mentions in the message body. */
@@ -520,11 +699,38 @@ declare namespace WAWebJS {
/** Message type */ /** Message type */
type: MessageTypes, type: MessageTypes,
/** Links included in the message. */ /** Links included in the message. */
links: string[], links: Array<{
link: string,
isSuspicious: boolean
}>,
/** Order ID */
orderId: string,
/** title */
title?: string,
/** description*/
description?: string,
/** Business Owner JID */
businessOwnerJid?: string,
/** Product JID */
productId?: string,
/** Message buttons */
dynamicReplyButtons?: object,
/** Selected button ID */
selectedButtonId?: string,
/** Selected list row ID */
selectedRowId?: string,
/** Returns message in a raw format */
rawData: object,
/*
* Reloads this Message object's data in-place with the latest values from WhatsApp Web.
* Note that the Message must still be in the web app cache for this to work, otherwise will return null.
*/
reload: () => Promise<Message>,
/** Accept the Group V4 Invite in message */
acceptGroupV4Invite: () => Promise<{status: number}>,
/** Deletes the message from the chat */ /** Deletes the message from the chat */
delete: (everyone?: boolean) => Promise<void>, delete: (everyone?: boolean) => Promise<void>,
/** Downloads and returns the attatched message media */ /** Downloads and returns the attached message media */
downloadMedia: () => Promise<MessageMedia>, downloadMedia: () => Promise<MessageMedia>,
/** Returns the Chat this message was sent in */ /** Returns the Chat this message was sent in */
getChat: () => Promise<Chat>, getChat: () => Promise<Chat>,
@@ -540,16 +746,26 @@ declare namespace WAWebJS {
* If not, it will send the message in the same Chat as the original message was sent. * If not, it will send the message in the same Chat as the original message was sent.
*/ */
reply: (content: MessageContent, chatId?: string, options?: MessageSendOptions) => Promise<Message>, reply: (content: MessageContent, chatId?: string, options?: MessageSendOptions) => Promise<Message>,
/** React to this message with an emoji*/
react: (reaction: string) => Promise<void>,
/** /**
* Forwards this message to another chat * Forwards this message to another chat (that you chatted before, otherwise it will fail)
*/ */
forward: (chat: Chat | string) => Promise<void>, forward: (chat: Chat | string) => Promise<void>,
/** Star this message */ /** Star this message */
star: () => Promise<void>, star: () => Promise<void>,
/** Unstar this message */ /** Unstar this message */
unstar: () => Promise<void>, unstar: () => Promise<void>,
/** Get information about message delivery statuso */ /** Get information about message delivery status */
getInfo: () => Promise<MessageInfo | null> getInfo: () => Promise<MessageInfo | null>,
/**
* Gets the order associated with a given message
*/
getOrder: () => Promise<Order>,
/**
* Gets the payment details associated with a given message
*/
getPayment: () => Promise<Payment>,
} }
/** ID that represents a message */ /** ID that represents a message */
@@ -560,10 +776,13 @@ declare namespace WAWebJS {
_serialized: string, _serialized: string,
} }
export interface Location { /** Location information */
description?: string | null, export class Location {
latitude: string, description?: string | null
longitude: string, latitude: string
longitude: string
constructor(latitude: number, longitude: number, description?: string)
} }
export interface Label { export interface Label {
@@ -580,10 +799,12 @@ declare namespace WAWebJS {
/** Options for sending a message */ /** Options for sending a message */
export interface MessageSendOptions { export interface MessageSendOptions {
/** Show links preview */ /** Show links preview. Has no effect on multi-device accounts. */
linkPreview?: boolean linkPreview?: boolean
/** Send audio as voice message */ /** Send audio as voice message */
sendAudioAsVoice?: boolean sendAudioAsVoice?: boolean
/** Send video as gif */
sendVideoAsGif?: boolean
/** Send media as sticker */ /** Send media as sticker */
sendMediaAsSticker?: boolean sendMediaAsSticker?: boolean
/** Send media as document */ /** Send media as document */
@@ -600,6 +821,21 @@ declare namespace WAWebJS {
sendSeen?: boolean sendSeen?: boolean
/** Media to be sent */ /** Media to be sent */
media?: MessageMedia media?: MessageMedia
/** Extra options */
extra?: any
/** Sticker name, if sendMediaAsSticker is true */
stickerName?: string
/** Sticker author, if sendMediaAsSticker is true */
stickerAuthor?: string
/** Sticker categories, if sendMediaAsSticker is true */
stickerCategories?: string[]
}
export interface MediaFromURLOptions {
client?: Client
filename?: string
unsafeMime?: boolean
reqOptions?: RequestInit
} }
/** Media attached to a message */ /** Media attached to a message */
@@ -610,19 +846,25 @@ declare namespace WAWebJS {
data: string data: string
/** Document file name. Value can be null */ /** Document file name. Value can be null */
filename?: string | null filename?: string | null
/** Document file size in bytes. Value can be null. */
filesize?: number | null
/** /**
* @param {string} mimetype MIME type of the attachment * @param {string} mimetype MIME type of the attachment
* @param {string} data Base64-encoded data of the file * @param {string} data Base64-encoded data of the file
* @param {?string} filename Document file name. Value can be null * @param {?string} filename Document file name. Value can be null
* @param {?number} filesize Document file size in bytes. Value can be null.
*/ */
constructor(mimetype: string, data: string, filename?: string | null) constructor(mimetype: string, data: string, filename?: string | null, filesize?: number | null)
/** Creates a MessageMedia instance from a local file path */ /** Creates a MessageMedia instance from a local file path */
static fromFilePath: (filePath: string) => MessageMedia static fromFilePath: (filePath: string) => MessageMedia
/** Creates a MessageMedia instance from a URL */
static fromUrl: (url: string, options?: MediaFromURLOptions) => Promise<MessageMedia>
} }
export type MessageContent = string | MessageMedia | Location | Contact | Contact[] export type MessageContent = string | MessageMedia | Location | Contact | Contact[] | List | Buttons
/** /**
* Represents a Contact on WhatsApp * Represents a Contact on WhatsApp
@@ -700,14 +942,24 @@ declare namespace WAWebJS {
* Will return null when getting chat for currently logged in user. * Will return null when getting chat for currently logged in user.
*/ */
getChat: () => Promise<Chat>, getChat: () => Promise<Chat>,
/** Returns the contact's countrycode, (1541859685@c.us) => (1) */
getCountryCode(): Promise<string>,
/** Returns the contact's formatted phone number, (12345678901@c.us) => (+1 (234) 5678-901) */
getFormattedNumber(): Promise<string>,
/** Blocks this contact from WhatsApp */ /** Blocks this contact from WhatsApp */
block: () => Promise<boolean>, block: () => Promise<boolean>,
/** Unlocks this contact from WhatsApp */ /** Unlocks this contact from WhatsApp */
unblock: () => Promise<boolean>, unblock: () => Promise<boolean>,
/** Gets the Contact's current "about" info. Returns null if you don't have permission to read their status. */ /** Gets the Contact's current "about" info. Returns null if you don't have permission to read their status. */
getAbout: () => Promise<string | null>, getAbout: () => Promise<string | null>,
/** Gets the Contact's common groups with you. Returns empty array if you don't have any common group. */
getCommonGroups: () => Promise<ChatId[]>
} }
@@ -781,8 +1033,8 @@ declare namespace WAWebJS {
delete: () => Promise<boolean>, delete: () => Promise<boolean>,
/** Loads chat messages, sorted from earliest to latest. */ /** Loads chat messages, sorted from earliest to latest. */
fetchMessages: (searchOptions: MessageSearchOptions) => Promise<Message[]>, fetchMessages: (searchOptions: MessageSearchOptions) => Promise<Message[]>,
/** Mutes this chat until a specified date */ /** Mutes this chat forever, unless a date is specified */
mute: (unmuteDate: Date) => Promise<void>, mute: (unmuteDate?: Date) => Promise<void>,
/** Send a message to this chat */ /** Send a message to this chat */
sendMessage: (content: MessageContent, options?: MessageSendOptions) => Promise<Message>, sendMessage: (content: MessageContent, options?: MessageSendOptions) => Promise<Message>,
/** Set the message as seen */ /** Set the message as seen */
@@ -805,12 +1057,15 @@ declare namespace WAWebJS {
export interface MessageSearchOptions { export interface MessageSearchOptions {
/** /**
* The amount of messages to return. * The amount of messages to return. If no limit is specified, the available messages will be returned.
* Note that the actual number of returned messages may be smaller if there aren't enough messages in the conversation. * 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. * Set this to Infinity to load all messages.
* @default 50
*/ */
limit?: number limit?: number
/**
* Return only messages from the bot number or vise versa. To get all messages, leave the option undefined.
*/
fromMe?: boolean
} }
/** /**
@@ -852,7 +1107,7 @@ declare namespace WAWebJS {
} }
/** Promotes or demotes participants by IDs to regular users or admins */ /** Promotes or demotes participants by IDs to regular users or admins */
export type ChangeParticipantsPermisions = export type ChangeParticipantsPermissions =
(participantIds: Array<string>) => Promise<{ status: number }> (participantIds: Array<string>) => Promise<{ status: number }>
/** Adds or removes a list of participants by ID to the group */ /** Adds or removes a list of participants by ID to the group */
@@ -882,13 +1137,13 @@ declare namespace WAWebJS {
/** Removes a list of participants by ID to the group */ /** Removes a list of participants by ID to the group */
removeParticipants: ChangeGroupParticipants; removeParticipants: ChangeGroupParticipants;
/** Promotes participants by IDs to admins */ /** Promotes participants by IDs to admins */
promoteParticipants: ChangeParticipantsPermisions; promoteParticipants: ChangeParticipantsPermissions;
/** Demotes participants by IDs to regular users */ /** Demotes participants by IDs to regular users */
demoteParticipants: ChangeParticipantsPermisions; demoteParticipants: ChangeParticipantsPermissions;
/** Updates the group subject */ /** Updates the group subject */
setSubject: (subject: string) => Promise<void>; setSubject: (subject: string) => Promise<boolean>;
/** Updates the group description */ /** Updates the group description */
setDescription: (description: string) => Promise<void>; setDescription: (description: string) => Promise<boolean>;
/** Updates the group settings to only allow admins to send messages /** Updates the group settings to only allow admins to send messages
* @param {boolean} [adminsOnly=true] Enable or disable this option * @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. * @returns {Promise<boolean>} Returns true if the setting was properly updated. This can return false if the user does not have the necessary permissions.
@@ -907,6 +1162,205 @@ declare namespace WAWebJS {
/** Makes the bot leave the group */ /** Makes the bot leave the group */
leave: () => Promise<void>; leave: () => Promise<void>;
} }
/**
* Represents the metadata associated with a given product
*
*/
export interface ProductMetadata {
/** Product Id */
id: string,
/** Product Name */
name: string,
/** Product Description */
description: string,
/** Retailer ID */
retailer_id?: string
}
/**
* Represents a Product on Whatsapp
* @example
* {
* "id": "123456789",
* "price": "150000",
* "thumbnailId": "123456789",
* "thumbnailUrl": "https://mmg.whatsapp.net",
* "currency": "GTQ",
* "name": "Store Name",
* "quantity": 1
* }
*/
export interface Product {
/** Product Id */
id: string,
/** Price */
price?: string,
/** Product Thumbnail*/
thumbnailUrl: string,
/** Currency */
currency: string,
/** Product Name */
name: string,
/** Product Quantity*/
quantity: number,
/** Gets the Product metadata */
getData: () => Promise<ProductMetadata>
}
/**
* Represents a Order on WhatsApp
*
* @example
* {
* "products": [
* {
* "id": "123456789",
* "price": "150000",
* "thumbnailId": "123456789",
* "thumbnailUrl": "https://mmg.whatsapp.net",
* "currency": "GTQ",
* "name": "Store Name",
* "quantity": 1
* }
* ],
* "subtotal": "150000",
* "total": "150000",
* "currency": "GTQ",
* "createdAt": 1610136796,
* "sellerJid": "55555555@s.whatsapp.net"
* }
*/
export interface Order {
/** List of products*/
products: Array<Product>,
/** Order Subtotal */
subtotal: string,
/** Order Total */
total: string,
/** Order Currency */
currency: string,
/** Order Created At*/
createdAt: number;
}
/**
* Represents a Payment on WhatsApp
*
* @example
* {
* id: {
* fromMe: true,
* remote: {
* server: 'c.us',
* user: '5511999999999',
* _serialized: '5511999999999@c.us'
* },
* id: 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA',
* _serialized: 'true_5511999999999@c.us_AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'
* },
* paymentCurrency: 'BRL',
* paymentAmount1000: 1000,
* paymentMessageReceiverJid: {
* server: 'c.us',
* user: '5511999999999',
* _serialized: '5511999999999@c.us'
* },
* paymentTransactionTimestamp: 1623463058,
* paymentStatus: 4,
* paymentTxnStatus: 4,
* paymentNote: 'note'
* }
*/
export interface Payment {
/** Payment Id*/
id: object,
/** Payment currency */
paymentCurrency: string,
/** Payment ammount */
paymentAmount1000 : number,
/** Payment receiver */
paymentMessageReceiverJid : object,
/** Payment transaction timestamp */
paymentTransactionTimestamp : number,
/** Payment paymentStatus */
paymentStatus : number,
/** Integer that represents the payment Text */
paymentTxnStatus : number,
/** The note sent with the payment */
paymentNote : string;
}
/**
* Represents a Call on WhatsApp
*
* @example
* Call {
* id: 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA',
* from: '5511999999@c.us',
* timestamp: 1625003709,
* isVideo: false,
* isGroup: false,
* fromMe: false,
* canHandleLocally: false,
* webClientShouldHandle: false,
* participants: []
* }
*/
export interface Call {
/** Call Id */
id: string,
/** from */
from?: string,
/** Unix timestamp for when the call was created*/
timestamp: number,
/** Is video */
isVideo: boolean,
/** Is Group */
isGroup: boolean,
/** Indicates if the call was sent by the current user */
fromMe: boolean,
/** indicates if the call can be handled in waweb */
canHandleLocally: boolean,
/** indicates if the call should be handled in waweb */
webClientShouldHandle: boolean,
/** Object with participants */
participants: object
}
/** Message type List */
export class List {
body: string
buttonText: string
sections: Array<any>
title?: string | null
footer?: string | null
constructor(body: string, buttonText: string, sections: Array<any>, title?: string | null, footer?: string | null)
}
/** Message type Buttons */
export class Buttons {
body: string | MessageMedia
buttons: Array<{ buttonId: string; buttonText: {displayText: string}; type: number }>
title?: string | null
footer?: string | null
constructor(body: string, buttons: Array<{ id?: string; body: string }>, title?: string | null, footer?: string | null)
}
/** Message type Reaction */
export class Reaction {
id: MessageId
orphan: number
orphanReason?: string
timestamp: number
reaction: string
read: boolean
msgId: MessageId
senderId: string
ack?: number
}
} }
export = WAWebJS export = WAWebJS

View File

@@ -18,6 +18,15 @@ module.exports = {
BusinessContact: require('./src/structures/BusinessContact'), BusinessContact: require('./src/structures/BusinessContact'),
ClientInfo: require('./src/structures/ClientInfo'), ClientInfo: require('./src/structures/ClientInfo'),
Location: require('./src/structures/Location'), Location: require('./src/structures/Location'),
ProductMetadata: require('./src/structures/ProductMetadata'),
List: require('./src/structures/List'),
Buttons: require('./src/structures/Buttons'),
// Auth Strategies
NoAuth: require('./src/authStrategies/NoAuth'),
LocalAuth: require('./src/authStrategies/LocalAuth'),
RemoteAuth: require('./src/authStrategies/RemoteAuth'),
LegacySessionAuth: require('./src/authStrategies/LegacySessionAuth'),
...Constants ...Constants
}; };

View File

@@ -1,11 +1,12 @@
{ {
"name": "whatsapp-web.js", "name": "whatsapp-web.js",
"version": "1.12.6", "version": "1.18.4",
"description": "Library for interacting with the WhatsApp Web API ", "description": "Library for interacting with the WhatsApp Web API ",
"main": "./index.js", "main": "./index.js",
"typings": "./index.d.ts", "typings": "./index.d.ts",
"scripts": { "scripts": {
"test": "echo \"Error: no test specified\" && exit 1", "test": "mocha tests --recursive --timeout 5000",
"test-single": "mocha",
"shell": "node --experimental-repl-await ./shell.js", "shell": "node --experimental-repl-await ./shell.js",
"generate-docs": "node_modules/.bin/jsdoc --configure .jsdoc.json --verbose" "generate-docs": "node_modules/.bin/jsdoc --configure .jsdoc.json --verbose"
}, },
@@ -26,18 +27,34 @@
"bugs": { "bugs": {
"url": "https://github.com/pedroslopez/whatsapp-web.js/issues" "url": "https://github.com/pedroslopez/whatsapp-web.js/issues"
}, },
"homepage": "https://waguide.pedroslopez.me/", "homepage": "https://wwebjs.dev/",
"dependencies": { "dependencies": {
"@pedroslopez/moduleraid": "^5.0.0", "@pedroslopez/moduleraid": "^5.0.2",
"fluent-ffmpeg": "^2.1.2", "fluent-ffmpeg": "^2.1.2",
"jsqr": "^1.3.1", "jsqr": "^1.3.1",
"mime": "^2.4.5", "mime": "^3.0.0",
"puppeteer": "^5.2.1", "node-fetch": "^2.6.5",
"sharp": "^0.26.3" "node-webpmux": "^3.1.0",
"puppeteer": "^13.0.0"
}, },
"devDependencies": { "devDependencies": {
"eslint": "^6.8.0", "@types/node-fetch": "^2.5.12",
"chai": "^4.3.4",
"chai-as-promised": "^7.1.1",
"dotenv": "^16.0.0",
"eslint": "^8.4.1",
"eslint-plugin-mocha": "^10.0.3",
"jsdoc": "^3.6.4", "jsdoc": "^3.6.4",
"jsdoc-baseline": "^0.1.5" "jsdoc-baseline": "^0.1.5",
"mocha": "^9.0.2",
"sinon": "^13.0.1"
},
"engines": {
"node": ">=12.0.0"
},
"optionalDependencies": {
"archiver": "^5.3.1",
"fs-extra": "^10.1.0",
"unzipper": "^0.10.11"
} }
} }

View File

@@ -2,24 +2,17 @@
* ==== wwebjs-shell ==== * ==== wwebjs-shell ====
* Used for quickly testing library features * Used for quickly testing library features
* *
* Running `npm run shell` will start WhatsApp Web in headless mode * Running `npm run shell` will start WhatsApp Web with headless=false
* and then drop you into Node REPL with `client` in its context. * and then drop you into Node REPL with `client` in its context.
*/ */
const repl = require('repl'); const repl = require('repl');
const fs = require('fs');
const { Client } = require('./index'); const { Client, LocalAuth } = 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({ const client = new Client({
puppeteer: { headless: false }, puppeteer: { headless: false },
session: sessionCfg authStrategy: new LocalAuth()
}); });
console.log('Initializing...'); console.log('Initializing...');
@@ -30,6 +23,10 @@ client.on('qr', () => {
console.log('Please scan the QR code on the browser.'); console.log('Please scan the QR code on the browser.');
}); });
client.on('authenticated', (session) => {
console.log(JSON.stringify(session));
});
client.on('ready', () => { client.on('ready', () => {
const shell = repl.start('wwebjs> '); const shell = repl.start('wwebjs> ');
shell.context.client = client; shell.context.client = client;

View File

@@ -3,33 +3,33 @@
const EventEmitter = require('events'); const EventEmitter = require('events');
const puppeteer = require('puppeteer'); const puppeteer = require('puppeteer');
const moduleRaid = require('@pedroslopez/moduleraid/moduleraid'); const moduleRaid = require('@pedroslopez/moduleraid/moduleraid');
const jsQR = require('jsqr');
const Util = require('./util/Util'); const Util = require('./util/Util');
const InterfaceController = require('./util/InterfaceController'); const InterfaceController = require('./util/InterfaceController');
const { getIndexForVersion } = require('./util/VersionResolver');
const { WhatsWebURL, DefaultOptions, Events, WAState } = require('./util/Constants'); const { WhatsWebURL, DefaultOptions, Events, WAState } = require('./util/Constants');
const { ExposeStore, LoadUtils } = require('./util/Injected'); const { ExposeStore, LoadUtils } = require('./util/Injected');
const ChatFactory = require('./factories/ChatFactory'); const ChatFactory = require('./factories/ChatFactory');
const ContactFactory = require('./factories/ContactFactory'); const ContactFactory = require('./factories/ContactFactory');
const { ClientInfo, Message, MessageMedia, Contact, Location, GroupNotification , Label } = require('./structures'); const { ClientInfo, Message, MessageMedia, Contact, Location, GroupNotification, Label, Call, Buttons, List, Reaction } = require('./structures');
const LegacySessionAuth = require('./authStrategies/LegacySessionAuth');
const NoAuth = require('./authStrategies/NoAuth');
/** /**
* Starting point for interacting with the WhatsApp Web API * Starting point for interacting with the WhatsApp Web API
* @extends {EventEmitter} * @extends {EventEmitter}
* @param {object} options - Client options * @param {object} options - Client options
* @param {AuthStrategy} options.authStrategy - Determines how to save and restore sessions. Will use LegacySessionAuth if options.session is set. Otherwise, NoAuth will be used.
* @param {number} options.authTimeoutMs - Timeout for authentication selector in puppeteer * @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 {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.qrMaxRetries - How many times should the qrcode be refreshed before giving up
* @param {number} options.qrTimeoutMs - Timeout for qr code selector in puppeteer * @param {string} options.restartOnAuthFail - @deprecated This option should be set directly on the LegacySessionAuth.
* @param {string} options.restartOnAuthFail - Restart client with a new session (i.e. use null 'session' var) if authentication fails * @param {object} options.session - @deprecated Only here for backwards-compatibility. You should move to using LocalAuth, or set the authStrategy to LegacySessionAuth explicitly.
* @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.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 {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.userAgent - User agent to use in puppeteer
* @param {string} options.ffmpegPath - Ffmpeg path to use when formating videos to webp while sending stickers * @param {string} options.ffmpegPath - Ffmpeg path to use when formating videos to webp while sending stickers
* @param {boolean} options.bypassCSP - Sets bypassing of page's Content-Security-Policy.
* *
* @fires Client#qr * @fires Client#qr
* @fires Client#authenticated * @fires Client#authenticated
@@ -46,13 +46,33 @@ const { ClientInfo, Message, MessageMedia, Contact, Location, GroupNotification
* @fires Client#group_update * @fires Client#group_update
* @fires Client#disconnected * @fires Client#disconnected
* @fires Client#change_state * @fires Client#change_state
* @fires Client#change_battery
*/ */
class Client extends EventEmitter { class Client extends EventEmitter {
constructor(options = {}) { constructor(options = {}) {
super(); super();
this.options = Util.mergeDefault(DefaultOptions, options); this.options = Util.mergeDefault(DefaultOptions, options);
if(!this.options.authStrategy) {
if(Object.prototype.hasOwnProperty.call(this.options, 'session')) {
process.emitWarning(
'options.session is deprecated and will be removed in a future release due to incompatibility with multi-device. ' +
'Use the LocalAuth authStrategy, don\'t pass in a session as an option, or suppress this warning by using the LegacySessionAuth strategy explicitly (see https://wwebjs.dev/guide/authentication.html#legacysessionauth-strategy).',
'DeprecationWarning'
);
this.authStrategy = new LegacySessionAuth({
session: this.options.session,
restartOnAuthFail: this.options.restartOnAuthFail
});
} else {
this.authStrategy = new NoAuth();
}
} else {
this.authStrategy = this.options.authStrategy;
}
this.authStrategy.setup(this);
this.pupBrowser = null; this.pupBrowser = null;
this.pupPage = null; this.pupPage = null;
@@ -64,115 +84,208 @@ class Client extends EventEmitter {
* Sets up events and requirements, kicks off authentication request * Sets up events and requirements, kicks off authentication request
*/ */
async initialize() { async initialize() {
const browser = await puppeteer.launch(this.options.puppeteer); let [browser, page] = [null, null];
const page = (await browser.pages())[0];
page.setUserAgent(this.options.userAgent); await this.authStrategy.beforeBrowserInitialized();
const puppeteerOpts = this.options.puppeteer;
if (puppeteerOpts && puppeteerOpts.browserWSEndpoint) {
browser = await puppeteer.connect(puppeteerOpts);
page = await browser.newPage();
} else {
const browserArgs = [...(puppeteerOpts.args || [])];
if(!browserArgs.find(arg => arg.includes('--user-agent'))) {
browserArgs.push(`--user-agent=${this.options.userAgent}`);
}
browser = await puppeteer.launch({...puppeteerOpts, args: browserArgs});
page = (await browser.pages())[0];
}
await page.setUserAgent(this.options.userAgent);
if (this.options.bypassCSP) await page.setBypassCSP(true);
this.pupBrowser = browser; this.pupBrowser = browser;
this.pupPage = page; this.pupPage = page;
if (this.options.session) { await this.authStrategy.afterBrowserInitialized();
await page.evaluateOnNewDocument( await this.initVersionOverride();
session => {
localStorage.clear();
localStorage.setItem('WABrowserId', session.WABrowserId);
localStorage.setItem('WASecretBundle', session.WASecretBundle);
localStorage.setItem('WAToken1', session.WAToken1);
localStorage.setItem('WAToken2', session.WAToken2);
}, this.options.session);
}
await page.goto(WhatsWebURL, { await page.goto(WhatsWebURL, {
waitUntil: 'load', waitUntil: 'load',
timeout: 0, timeout: 0,
referer: 'https://whatsapp.com/'
}); });
const KEEP_PHONE_CONNECTED_IMG_SELECTOR = '[data-asset-intro-image-light="true"], [data-asset-intro-image-dark="true"]'; await page.evaluate(`function getElementByXpath(path) {
return document.evaluate(path, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
}`);
if (this.options.session) { let lastPercent = null,
// Check if session restore was successfull lastPercentMessage = null;
try {
await page.waitForSelector(KEEP_PHONE_CONNECTED_IMG_SELECTOR, { timeout: this.options.authTimeoutMs }); await page.exposeFunction('loadingScreen', async (percent, message) => {
} catch (err) { if (lastPercent !== percent || lastPercentMessage !== message) {
if (err.name === 'TimeoutError') { this.emit(Events.LOADING_SCREEN, percent, message);
/** lastPercent = percent;
* Emitted when there has been an error while trying to restore an existing session lastPercentMessage = message;
* @event Client#auth_failure }
* @param {string} message });
*/
this.emit(Events.AUTHENTICATION_FAILURE, 'Unable to log in. Are the session details valid?'); await page.evaluate(
browser.close(); async function (selectors) {
if (this.options.restartOnAuthFail) { var observer = new MutationObserver(function () {
// session restore failed so try again but without session to force new authentication let progressBar = window.getElementByXpath(
this.options.session = null; selectors.PROGRESS
this.initialize(); );
let progressMessage = window.getElementByXpath(
selectors.PROGRESS_MESSAGE
);
if (progressBar) {
window.loadingScreen(
progressBar.value,
progressMessage.innerText
);
} }
return; });
}
throw err; observer.observe(document, {
attributes: true,
childList: true,
characterData: true,
subtree: true,
});
},
{
PROGRESS: '//*[@id=\'app\']/div/div/div[2]/progress',
PROGRESS_MESSAGE: '//*[@id=\'app\']/div/div/div[3]',
}
);
const INTRO_IMG_SELECTOR = '[data-testid="intro-md-beta-logo-dark"], [data-testid="intro-md-beta-logo-light"], [data-asset-intro-image-light="true"], [data-asset-intro-image-dark="true"]';
const INTRO_QRCODE_SELECTOR = 'div[data-ref] canvas';
// Checks which selector appears first
const needAuthentication = await Promise.race([
new Promise(resolve => {
page.waitForSelector(INTRO_IMG_SELECTOR, { timeout: this.options.authTimeoutMs })
.then(() => resolve(false))
.catch((err) => resolve(err));
}),
new Promise(resolve => {
page.waitForSelector(INTRO_QRCODE_SELECTOR, { timeout: this.options.authTimeoutMs })
.then(() => resolve(true))
.catch((err) => resolve(err));
})
]);
// Checks if an error occurred on the first found selector. The second will be discarded and ignored by .race;
if (needAuthentication instanceof Error) throw needAuthentication;
// Scan-qrcode selector was found. Needs authentication
if (needAuthentication) {
const { failed, failureEventPayload, restart } = await this.authStrategy.onAuthenticationNeeded();
if(failed) {
/**
* 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, failureEventPayload);
await this.destroy();
if (restart) {
// session restore failed so try again but without session to force new authentication
return this.initialize();
}
return;
} }
} else { const QR_CONTAINER = 'div[data-ref]';
const getQrCode = async () => { const QR_RETRY_BUTTON = 'div[data-ref] > span > button';
// Check if retry button is present let qrRetries = 0;
var QR_RETRY_SELECTOR = 'div[data-ref] > span > button'; await page.exposeFunction('qrChanged', async (qr) => {
var qrRetry = await page.$(QR_RETRY_SELECTOR);
if (qrRetry) {
await qrRetry.click();
}
// Wait for QR Code
const QR_CANVAS_SELECTOR = 'canvas';
await page.waitForSelector(QR_CANVAS_SELECTOR, { timeout: this.options.qrTimeoutMs });
const qrImgData = await page.$eval(QR_CANVAS_SELECTOR, canvas => [].slice.call(canvas.getContext('2d').getImageData(0, 0, 264, 264).data));
const qr = jsQR(qrImgData, 264, 264).data;
/** /**
* Emitted when the QR code is received * Emitted when a QR code is received
* @event Client#qr * @event Client#qr
* @param {string} qr QR Code * @param {string} qr QR Code
*/ */
this.emit(Events.QR_RECEIVED, qr); this.emit(Events.QR_RECEIVED, qr);
}; if (this.options.qrMaxRetries > 0) {
getQrCode(); qrRetries++;
this._qrRefreshInterval = setInterval(getQrCode, this.options.qrRefreshIntervalMs); if (qrRetries > this.options.qrMaxRetries) {
this.emit(Events.DISCONNECTED, 'Max qrcode retries reached');
await this.destroy();
}
}
});
await page.evaluate(function (selectors) {
const qr_container = document.querySelector(selectors.QR_CONTAINER);
window.qrChanged(qr_container.dataset.ref);
const obs = new MutationObserver((muts) => {
muts.forEach(mut => {
// Listens to qr token change
if (mut.type === 'attributes' && mut.attributeName === 'data-ref') {
window.qrChanged(mut.target.dataset.ref);
} else
// Listens to retry button, when found, click it
if (mut.type === 'childList') {
const retry_button = document.querySelector(selectors.QR_RETRY_BUTTON);
if (retry_button) retry_button.click();
}
});
});
obs.observe(qr_container.parentElement, {
subtree: true,
childList: true,
attributes: true,
attributeFilter: ['data-ref'],
});
}, {
QR_CONTAINER,
QR_RETRY_BUTTON
});
// Wait for code scan // Wait for code scan
await page.waitForSelector(KEEP_PHONE_CONNECTED_IMG_SELECTOR, { timeout: 0 }); try {
clearInterval(this._qrRefreshInterval); await page.waitForSelector(INTRO_IMG_SELECTOR, { timeout: 0 });
this._qrRefreshInterval = undefined; } catch(error) {
if (
error.name === 'ProtocolError' &&
error.message &&
error.message.match(/Target closed/)
) {
// something has called .destroy() while waiting
return;
}
throw error;
}
} }
await page.evaluate(ExposeStore, moduleRaid.toString()); await page.evaluate(ExposeStore, moduleRaid.toString());
const authEventPayload = await this.authStrategy.getAuthEventPayload();
// Get session tokens
const localStorage = JSON.parse(await page.evaluate(() => {
return JSON.stringify(window.localStorage);
}));
const session = {
WABrowserId: localStorage.WABrowserId,
WASecretBundle: localStorage.WASecretBundle,
WAToken1: localStorage.WAToken1,
WAToken2: localStorage.WAToken2
};
/** /**
* Emitted when authentication is successful * Emitted when authentication is successful
* @event Client#authenticated * @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); this.emit(Events.AUTHENTICATED, authEventPayload);
// Check window.Store Injection // Check window.Store Injection
await page.waitForFunction('window.Store != undefined'); await page.waitForFunction('window.Store != undefined');
await page.evaluate(async () => {
// safely unregister service workers
const registrations = await navigator.serviceWorker.getRegistrations();
for (let registration of registrations) {
registration.unregister();
}
});
//Load util functions (serializers, helper functions) //Load util functions (serializers, helper functions)
await page.evaluate(LoadUtils); await page.evaluate(LoadUtils);
@@ -182,7 +295,7 @@ class Client extends EventEmitter {
* @type {ClientInfo} * @type {ClientInfo}
*/ */
this.info = new ClientInfo(this, await page.evaluate(() => { this.info = new ClientInfo(this, await page.evaluate(() => {
return window.Store.Conn.serialize(); return { ...window.Store.Conn.serialize(), wid: window.Store.User.getMeUser() };
})); }));
// Add InterfaceController // Add InterfaceController
@@ -190,8 +303,6 @@ class Client extends EventEmitter {
// Register events // Register events
await page.exposeFunction('onAddMessageEvent', msg => { await page.exposeFunction('onAddMessageEvent', msg => {
if (!msg.isNewMsg) return;
if (msg.type === 'gp2') { if (msg.type === 'gp2') {
const notification = new GroupNotification(this, msg); const notification = new GroupNotification(this, msg);
if (msg.subtype === 'add' || msg.subtype === 'invite') { if (msg.subtype === 'add' || msg.subtype === 'invite') {
@@ -310,7 +421,7 @@ class Client extends EventEmitter {
this.emit(Events.MEDIA_UPLOADED, message); this.emit(Events.MEDIA_UPLOADED, message);
}); });
await page.exposeFunction('onAppStateChangedEvent', (state) => { await page.exposeFunction('onAppStateChangedEvent', async (state) => {
/** /**
* Emitted when the connection state changes * Emitted when the connection state changes
@@ -337,6 +448,7 @@ class Client extends EventEmitter {
* @event Client#disconnected * @event Client#disconnected
* @param {WAState|"NAVIGATION"} reason reason that caused the disconnect * @param {WAState|"NAVIGATION"} reason reason that caused the disconnect
*/ */
await this.authStrategy.disconnect();
this.emit(Events.DISCONNECTED, state); this.emit(Events.DISCONNECTED, state);
this.destroy(); this.destroy();
} }
@@ -348,24 +460,90 @@ class Client extends EventEmitter {
if (battery === undefined) return; if (battery === undefined) return;
/** /**
* Emitted when the battery percentage for the attached device changes * Emitted when the battery percentage for the attached device changes. Will not be sent if using multi-device.
* @event Client#change_battery * @event Client#change_battery
* @param {object} batteryInfo * @param {object} batteryInfo
* @param {number} batteryInfo.battery - The current battery percentage * @param {number} batteryInfo.battery - The current battery percentage
* @param {boolean} batteryInfo.plugged - Indicates if the phone is plugged in (true) or not (false) * @param {boolean} batteryInfo.plugged - Indicates if the phone is plugged in (true) or not (false)
* @deprecated
*/ */
this.emit(Events.BATTERY_CHANGED, { battery, plugged }); this.emit(Events.BATTERY_CHANGED, { battery, plugged });
}); });
await page.exposeFunction('onIncomingCall', (call) => {
/**
* 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 = new Call(this, call);
this.emit(Events.INCOMING_CALL, cll);
});
await page.exposeFunction('onReaction', (reactions) => {
for (const reaction of reactions) {
/**
* Emitted when a reaction is sent, received, updated or removed
* @event Client#message_reaction
* @param {object} reaction
* @param {object} reaction.id - Reaction id
* @param {number} reaction.orphan - Orphan
* @param {?string} reaction.orphanReason - Orphan reason
* @param {number} reaction.timestamp - Timestamp
* @param {string} reaction.reaction - Reaction
* @param {boolean} reaction.read - Read
* @param {object} reaction.msgId - Parent message id
* @param {string} reaction.senderId - Sender id
* @param {?number} reaction.ack - Ack
*/
this.emit(Events.MESSAGE_REACTION, new Reaction(this, reaction));
}
});
await page.evaluate(() => { await page.evaluate(() => {
window.Store.Msg.on('add', (msg) => { if (msg.isNewMsg) window.onAddMessageEvent(window.WWebJS.getMessageModel(msg)); });
window.Store.Msg.on('change', (msg) => { window.onChangeMessageEvent(window.WWebJS.getMessageModel(msg)); }); window.Store.Msg.on('change', (msg) => { window.onChangeMessageEvent(window.WWebJS.getMessageModel(msg)); });
window.Store.Msg.on('change:type', (msg) => { window.onChangeMessageTypeEvent(window.WWebJS.getMessageModel(msg)); }); window.Store.Msg.on('change:type', (msg) => { window.onChangeMessageTypeEvent(window.WWebJS.getMessageModel(msg)); });
window.Store.Msg.on('change:ack', (msg,ack) => { window.onMessageAckEvent(window.WWebJS.getMessageModel(msg), ack); }); window.Store.Msg.on('change:ack', (msg, ack) => { window.onMessageAckEvent(window.WWebJS.getMessageModel(msg), ack); });
window.Store.Msg.on('change:isUnsentMedia', (msg, unsent) => { if (msg.id.fromMe && !unsent) window.onMessageMediaUploadedEvent(window.WWebJS.getMessageModel(msg)); }); window.Store.Msg.on('change:isUnsentMedia', (msg, unsent) => { if (msg.id.fromMe && !unsent) window.onMessageMediaUploadedEvent(window.WWebJS.getMessageModel(msg)); });
window.Store.Msg.on('remove', (msg) => { if (msg.isNewMsg) window.onRemoveMessageEvent(window.WWebJS.getMessageModel(msg)); }); window.Store.Msg.on('remove', (msg) => { if (msg.isNewMsg) window.onRemoveMessageEvent(window.WWebJS.getMessageModel(msg)); });
window.Store.AppState.on('change:state', (_AppState, state) => { window.onAppStateChangedEvent(state); }); window.Store.AppState.on('change:state', (_AppState, state) => { window.onAppStateChangedEvent(state); });
window.Store.Conn.on('change:battery', (state) => { window.onBatteryStateChangedEvent(state); }); window.Store.Conn.on('change:battery', (state) => { window.onBatteryStateChangedEvent(state); });
window.Store.Call.on('add', (call) => { window.onIncomingCall(call); });
window.Store.Msg.on('add', (msg) => {
if (msg.isNewMsg) {
if(msg.type === 'ciphertext') {
// defer message event until ciphertext is resolved (type changed)
msg.once('change:type', (_msg) => window.onAddMessageEvent(window.WWebJS.getMessageModel(_msg)));
} else {
window.onAddMessageEvent(window.WWebJS.getMessageModel(msg));
}
}
});
{
const module = window.Store.createOrUpdateReactionsModule;
const ogMethod = module.createOrUpdateReactions;
module.createOrUpdateReactions = ((...args) => {
window.onReaction(args[0].map(reaction => {
const msgKey = window.Store.MsgKey.fromString(reaction.msgKey);
const parentMsgKey = window.Store.MsgKey.fromString(reaction.parentMsgKey);
const timestamp = reaction.timestamp / 1000;
return {...reaction, msgKey, parentMsgKey, timestamp };
}));
return ogMethod(...args);
}).bind(module);
}
}); });
/** /**
@@ -373,12 +551,32 @@ class Client extends EventEmitter {
* @event Client#ready * @event Client#ready
*/ */
this.emit(Events.READY); this.emit(Events.READY);
this.authStrategy.afterAuthReady();
// Disconnect when navigating away // Disconnect when navigating away when in PAIRING state (detect logout)
// Because WhatsApp Web now reloads when logging out from the device, this also covers that case
this.pupPage.on('framenavigated', async () => { this.pupPage.on('framenavigated', async () => {
this.emit(Events.DISCONNECTED, 'NAVIGATION'); const appState = await this.getState();
await this.destroy(); if(!appState || appState === WAState.PAIRING) {
await this.authStrategy.disconnect();
this.emit(Events.DISCONNECTED, 'NAVIGATION');
await this.destroy();
}
});
}
async initVersionOverride() {
const version = this.options.webVersion;
await this.pupPage.setRequestInterception(true);
this.pupPage.on('request', async (req) => {
if(req.url() === WhatsWebURL) {
req.respond({
status: 200,
contentType: 'text/html',
body: await getIndexForVersion(version)
});
} else {
req.continue();
}
}); });
} }
@@ -386,19 +584,19 @@ class Client extends EventEmitter {
* Closes the client * Closes the client
*/ */
async destroy() { async destroy() {
if (this._qrRefreshInterval) {
clearInterval(this._qrRefreshInterval);
}
await this.pupBrowser.close(); await this.pupBrowser.close();
await this.authStrategy.destroy();
} }
/** /**
* Logs out the client, closing the current session * Logs out the client, closing the current session
*/ */
async logout() { async logout() {
return await this.pupPage.evaluate(() => { await this.pupPage.evaluate(() => {
return window.Store.AppState.logout(); return window.Store.AppState.logout();
}); });
await this.authStrategy.logout();
} }
/** /**
@@ -428,8 +626,9 @@ class Client extends EventEmitter {
/** /**
* Message options. * Message options.
* @typedef {Object} MessageSendOptions * @typedef {Object} MessageSendOptions
* @property {boolean} [linkPreview=true] - Show links preview * @property {boolean} [linkPreview=true] - Show links preview. Has no effect on multi-device accounts.
* @property {boolean} [sendAudioAsVoice=false] - Send audio as voice message * @property {boolean} [sendAudioAsVoice=false] - Send audio as voice message
* @property {boolean} [sendVideoAsGif=false] - Send video as gif
* @property {boolean} [sendMediaAsSticker=false] - Send media as a sticker * @property {boolean} [sendMediaAsSticker=false] - Send media as a sticker
* @property {boolean} [sendMediaAsDocument=false] - Send media as a document * @property {boolean} [sendMediaAsDocument=false] - Send media as a document
* @property {boolean} [parseVCards=true] - Automatically parse vCards and send them as contacts * @property {boolean} [parseVCards=true] - Automatically parse vCards and send them as contacts
@@ -437,13 +636,16 @@ class Client extends EventEmitter {
* @property {string} [quotedMessageId] - Id of the message that is being quoted (or replied to) * @property {string} [quotedMessageId] - Id of the message that is being quoted (or replied to)
* @property {Contact[]} [mentions] - Contacts that are being mentioned in the message * @property {Contact[]} [mentions] - Contacts that are being mentioned in the message
* @property {boolean} [sendSeen=true] - Mark the conversation as seen after sending the message * @property {boolean} [sendSeen=true] - Mark the conversation as seen after sending the message
* @property {string} [stickerAuthor=undefined] - Sets the author of the sticker, (if sendMediaAsSticker is true).
* @property {string} [stickerName=undefined] - Sets the name of the sticker, (if sendMediaAsSticker is true).
* @property {string[]} [stickerCategories=undefined] - Sets the categories of the sticker, (if sendMediaAsSticker is true). Provide emoji char array, can be null.
* @property {MessageMedia} [media] - Media to be sent * @property {MessageMedia} [media] - Media to be sent
*/ */
/** /**
* Send a message to a specific chatId * Send a message to a specific chatId
* @param {string} chatId * @param {string} chatId
* @param {string|MessageMedia|Location|Contact|Array<Contact>} content * @param {string|MessageMedia|Location|Contact|Array<Contact>|Buttons|List} content
* @param {MessageSendOptions} [options] - Options used when sending the message * @param {MessageSendOptions} [options] - Options used when sending the message
* *
* @returns {Promise<Message>} Message that was just sent * @returns {Promise<Message>} Message that was just sent
@@ -452,12 +654,14 @@ class Client extends EventEmitter {
let internalOptions = { let internalOptions = {
linkPreview: options.linkPreview === false ? undefined : true, linkPreview: options.linkPreview === false ? undefined : true,
sendAudioAsVoice: options.sendAudioAsVoice, sendAudioAsVoice: options.sendAudioAsVoice,
sendVideoAsGif: options.sendVideoAsGif,
sendMediaAsSticker: options.sendMediaAsSticker, sendMediaAsSticker: options.sendMediaAsSticker,
sendMediaAsDocument: options.sendMediaAsDocument, sendMediaAsDocument: options.sendMediaAsDocument,
caption: options.caption, caption: options.caption,
quotedMessageId: options.quotedMessageId, quotedMessageId: options.quotedMessageId,
parseVCards: options.parseVCards === false ? false : true, parseVCards: options.parseVCards === false ? false : true,
mentionedJidList: Array.isArray(options.mentions) ? options.mentions.map(contact => contact.id._serialized) : [] mentionedJidList: Array.isArray(options.mentions) ? options.mentions.map(contact => contact.id._serialized) : [],
extraOptions: options.extra
}; };
const sendSeen = typeof options.sendSeen === 'undefined' ? true : options.sendSeen; const sendSeen = typeof options.sendSeen === 'undefined' ? true : options.sendSeen;
@@ -472,22 +676,36 @@ class Client extends EventEmitter {
} else if (content instanceof Location) { } else if (content instanceof Location) {
internalOptions.location = content; internalOptions.location = content;
content = ''; content = '';
} else if(content instanceof Contact) { } else if (content instanceof Contact) {
internalOptions.contactCard = content.id._serialized; internalOptions.contactCard = content.id._serialized;
content = ''; content = '';
} else if(Array.isArray(content) && content.length > 0 && content[0] instanceof Contact) { } else if (Array.isArray(content) && content.length > 0 && content[0] instanceof Contact) {
internalOptions.contactCardList = content.map(contact => contact.id._serialized); internalOptions.contactCardList = content.map(contact => contact.id._serialized);
content = ''; content = '';
} else if (content instanceof Buttons) {
if (content.type !== 'chat') { internalOptions.attachment = content.body; }
internalOptions.buttons = content;
content = '';
} else if (content instanceof List) {
internalOptions.list = content;
content = '';
} }
if (internalOptions.sendMediaAsSticker && internalOptions.attachment) { if (internalOptions.sendMediaAsSticker && internalOptions.attachment) {
internalOptions.attachment = await Util.formatToWebpSticker(internalOptions.attachment); internalOptions.attachment = await Util.formatToWebpSticker(
internalOptions.attachment, {
name: options.stickerName,
author: options.stickerAuthor,
categories: options.stickerCategories
}, this.pupPage
);
} }
const newMessage = await this.pupPage.evaluate(async (chatId, message, options, sendSeen) => { const newMessage = await this.pupPage.evaluate(async (chatId, message, options, sendSeen) => {
const chatWid = window.Store.WidFactory.createWid(chatId); const chatWid = window.Store.WidFactory.createWid(chatId);
const chat = await window.Store.Chat.find(chatWid); const chat = await window.Store.Chat.find(chatWid);
if (sendSeen) { if (sendSeen) {
window.WWebJS.sendSeen(chatId); window.WWebJS.sendSeen(chatId);
} }
@@ -499,6 +717,24 @@ class Client extends EventEmitter {
return new Message(this, newMessage); return new Message(this, newMessage);
} }
/**
* Searches for messages
* @param {string} query
* @param {Object} [options]
* @param {number} [options.page]
* @param {number} [options.limit]
* @param {string} [options.chatId]
* @returns {Promise<Message[]>}
*/
async searchMessages(query, options = {}) {
const messages = await this.pupPage.evaluate(async (query, page, count, remote) => {
const { messages } = await window.Store.Msg.search(query, page, count, remote);
return messages.map(msg => window.WWebJS.getMessageModel(msg));
}, query, options.page, options.limit, options.chatId);
return messages.map(msg => new Message(this, msg));
}
/** /**
* Get all current chat instances * Get all current chat instances
* @returns {Promise<Array<Chat>>} * @returns {Promise<Array<Chat>>}
@@ -556,7 +792,7 @@ class Client extends EventEmitter {
*/ */
async getInviteInfo(inviteCode) { async getInviteInfo(inviteCode) {
return await this.pupPage.evaluate(inviteCode => { return await this.pupPage.evaluate(inviteCode => {
return window.Store.Wap.groupInviteInfo(inviteCode); return window.Store.InviteInfo.sendQueryGroupInvite(inviteCode);
}, inviteCode); }, inviteCode);
} }
@@ -573,13 +809,27 @@ class Client extends EventEmitter {
return chatId._serialized; return chatId._serialized;
} }
/**
* Accepts a private invitation to join a group
* @param {object} inviteInfo Invite V4 Info
* @returns {Promise<Object>}
*/
async acceptGroupV4Invite(inviteInfo) {
if (!inviteInfo.inviteCode) throw 'Invalid invite code, try passing the message.inviteV4 object';
if (inviteInfo.inviteCodeExp == 0) throw 'Expired invite code';
return this.pupPage.evaluate(async inviteInfo => {
let { groupId, fromId, inviteCode, inviteCodeExp } = inviteInfo;
return await window.Store.JoinInviteV4.sendJoinGroupViaInviteV4(inviteCode, String(inviteCodeExp), groupId, fromId);
}, inviteInfo);
}
/** /**
* Sets the current user's status message * Sets the current user's status message
* @param {string} status New status message * @param {string} status New status message
*/ */
async setStatus(status) { async setStatus(status) {
await this.pupPage.evaluate(async status => { await this.pupPage.evaluate(async status => {
return await window.Store.Wap.sendSetStatus(status); return await window.Store.StatusUtils.setMyStatus(status);
}, status); }, status);
} }
@@ -587,19 +837,31 @@ class Client extends EventEmitter {
* Sets the current user's display name. * Sets the current user'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. * 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 * @param {string} displayName New display name
* @returns {Promise<Boolean>}
*/ */
async setDisplayName(displayName) { async setDisplayName(displayName) {
await this.pupPage.evaluate(async displayName => { const couldSet = await this.pupPage.evaluate(async displayName => {
return await window.Store.Wap.setPushname(displayName); if(!window.Store.Conn.canSetMyPushname()) return false;
}, displayName);
}
if(window.Store.MDBackend) {
// TODO
return false;
} else {
const res = await window.Store.Wap.setPushname(displayName);
return !res.status || res.status === 200;
}
}, displayName);
return couldSet;
}
/** /**
* Gets the current connection state for the client * Gets the current connection state for the client
* @returns {WAState} * @returns {WAState}
*/ */
async getState() { async getState() {
return await this.pupPage.evaluate(() => { return await this.pupPage.evaluate(() => {
if(!window.Store) return null;
return window.Store.AppState.state; return window.Store.AppState.state;
}); });
} }
@@ -609,7 +871,16 @@ class Client extends EventEmitter {
*/ */
async sendPresenceAvailable() { async sendPresenceAvailable() {
return await this.pupPage.evaluate(() => { return await this.pupPage.evaluate(() => {
return window.Store.Wap.sendPresenceAvailable(); return window.Store.PresenceUtils.sendPresenceAvailable();
});
}
/**
* Marks the client as unavailable
*/
async sendPresenceUnavailable() {
return await this.pupPage.evaluate(() => {
return window.Store.PresenceUtils.sendPresenceUnavailable();
}); });
} }
@@ -621,7 +892,7 @@ class Client extends EventEmitter {
return await this.pupPage.evaluate(async chatId => { return await this.pupPage.evaluate(async chatId => {
let chat = await window.Store.Chat.get(chatId); let chat = await window.Store.Chat.get(chatId);
await window.Store.Cmd.archiveChat(chat, true); await window.Store.Cmd.archiveChat(chat, true);
return chat.archive; return true;
}, chatId); }, chatId);
} }
@@ -633,7 +904,7 @@ class Client extends EventEmitter {
return await this.pupPage.evaluate(async chatId => { return await this.pupPage.evaluate(async chatId => {
let chat = await window.Store.Chat.get(chatId); let chat = await window.Store.Chat.get(chatId);
await window.Store.Cmd.archiveChat(chat, false); await window.Store.Cmd.archiveChat(chat, false);
return chat.archive; return false;
}, chatId); }, chatId);
} }
@@ -648,8 +919,9 @@ class Client extends EventEmitter {
return true; return true;
} }
const MAX_PIN_COUNT = 3; const MAX_PIN_COUNT = 3;
if (window.Store.Chat.models.length > MAX_PIN_COUNT) { const chatModels = window.Store.Chat.getModelsArray();
let maxPinned = window.Store.Chat.models[MAX_PIN_COUNT - 1].pin; if (chatModels.length > MAX_PIN_COUNT) {
let maxPinned = chatModels[MAX_PIN_COUNT - 1].pin;
if (maxPinned) { if (maxPinned) {
return false; return false;
} }
@@ -675,15 +947,16 @@ class Client extends EventEmitter {
} }
/** /**
* Mutes the Chat until a specified date * Mutes this chat forever, unless a date is specified
* @param {string} chatId ID of the chat that will be muted * @param {string} chatId ID of the chat that will be muted
* @param {Date} unmuteDate Date when the chat will be unmuted * @param {?Date} unmuteDate Date when the chat will be unmuted, leave as is to mute forever
*/ */
async muteChat(chatId, unmuteDate) { async muteChat(chatId, unmuteDate) {
unmuteDate = unmuteDate ? unmuteDate.getTime() / 1000 : -1;
await this.pupPage.evaluate(async (chatId, timestamp) => { await this.pupPage.evaluate(async (chatId, timestamp) => {
let chat = await window.Store.Chat.get(chatId); let chat = await window.Store.Chat.get(chatId);
await chat.mute.mute(timestamp, !0); await chat.mute.mute(timestamp, !0);
}, chatId, unmuteDate.getTime() / 1000); }, chatId, unmuteDate || -1);
} }
/** /**
@@ -714,13 +987,49 @@ class Client extends EventEmitter {
* @returns {Promise<string>} * @returns {Promise<string>}
*/ */
async getProfilePicUrl(contactId) { async getProfilePicUrl(contactId) {
const profilePic = await this.pupPage.evaluate((contactId) => { const profilePic = await this.pupPage.evaluate(async contactId => {
return window.Store.Wap.profilePicFind(contactId); try {
const chatWid = window.Store.WidFactory.createWid(contactId);
return await window.Store.ProfilePic.profilePicFind(chatWid);
} catch (err) {
if(err.name === 'ServerStatusCodeError') return undefined;
throw err;
}
}, contactId); }, contactId);
return profilePic ? profilePic.eurl : undefined; return profilePic ? profilePic.eurl : undefined;
} }
/**
* Gets the Contact's common groups with you. Returns empty array if you don't have any common group.
* @param {string} contactId the whatsapp user's ID (_serialized format)
* @returns {Promise<WAWebJS.ChatId[]>}
*/
async getCommonGroups(contactId) {
const commonGroups = await this.pupPage.evaluate(async (contactId) => {
let contact = window.Store.Contact.get(contactId);
if (!contact) {
const wid = window.Store.WidFactory.createUserWid(contactId);
const chatConstructor = window.Store.Contact.getModelsArray().find(c=>!c.isGroup).constructor;
contact = new chatConstructor({id: wid});
}
if (contact.commonGroups) {
return contact.commonGroups.serialize();
}
const status = await window.Store.findCommonGroups(contact);
if (status) {
return contact.commonGroups.serialize();
}
return [];
}, contactId);
const chats = [];
for (const group of commonGroups) {
chats.push(group.id);
}
return chats;
}
/** /**
* Force reset of connection state for the client * Force reset of connection state for the client
*/ */
@@ -736,10 +1045,7 @@ class Client extends EventEmitter {
* @returns {Promise<Boolean>} * @returns {Promise<Boolean>}
*/ */
async isRegisteredUser(id) { async isRegisteredUser(id) {
return await this.pupPage.evaluate(async (id) => { return Boolean(await this.getNumberId(id));
let result = await window.Store.Wap.queryExist(id);
return result.jid !== undefined;
}, id);
} }
/** /**
@@ -749,17 +1055,43 @@ class Client extends EventEmitter {
* @returns {Promise<Object|null>} * @returns {Promise<Object|null>}
*/ */
async getNumberId(number) { async getNumberId(number) {
if(!number.endsWith('@c.us')) { if (!number.endsWith('@c.us')) {
number += '@c.us'; number += '@c.us';
} }
try { return await this.pupPage.evaluate(async number => {
return await this.pupPage.evaluate(async numberId => { const wid = window.Store.WidFactory.createWid(number);
return window.WWebJS.getNumberId(numberId); const result = await window.Store.QueryExist(wid);
}, number); if (!result || result.wid === undefined) return null;
} catch(_) { return result.wid;
return null; }, number);
} }
/**
* Get the formatted number of a WhatsApp ID.
* @param {string} number Number or ID
* @returns {Promise<string>}
*/
async getFormattedNumber(number) {
if (!number.endsWith('@s.whatsapp.net')) number = number.replace('c.us', 's.whatsapp.net');
if (!number.includes('@s.whatsapp.net')) number = `${number}@s.whatsapp.net`;
return await this.pupPage.evaluate(async numberId => {
return window.Store.NumberInfo.formattedPhoneNumber(numberId);
}, number);
}
/**
* Get the country code of a WhatsApp ID.
* @param {string} number Number or ID
* @returns {Promise<string>}
*/
async getCountryCode(number) {
number = number.replace(' ', '').replace('+', '').replace('@c.us', '');
return await this.pupPage.evaluate(async numberId => {
return window.Store.NumberInfo.findCC(numberId);
}, number);
} }
/** /**
@@ -780,12 +1112,9 @@ class Client extends EventEmitter {
} }
const createRes = await this.pupPage.evaluate(async (name, participantIds) => { const createRes = await this.pupPage.evaluate(async (name, participantIds) => {
const res = await window.Store.Wap.createGroup(name, participantIds); const participantWIDs = participantIds.map(p => window.Store.WidFactory.createWid(p));
console.log(res); const id = window.Store.MsgKey.newId();
if (!res.status === 200) { const res = await window.Store.GroupUtils.sendCreateGroup(name, participantWIDs, undefined, id);
throw 'An error occurred while creating the group!';
}
return res; return res;
}, name, participants); }, name, participants);
@@ -806,9 +1135,9 @@ class Client extends EventEmitter {
async getLabels() { async getLabels() {
const labels = await this.pupPage.evaluate(async () => { const labels = await this.pupPage.evaluate(async () => {
return window.WWebJS.getLabels(); return window.WWebJS.getLabels();
}); });
return labels.map(data => new Label(this , data)); return labels.map(data => new Label(this, data));
} }
/** /**
@@ -819,7 +1148,7 @@ class Client extends EventEmitter {
async getLabelById(labelId) { async getLabelById(labelId) {
const label = await this.pupPage.evaluate(async (labelId) => { const label = await this.pupPage.evaluate(async (labelId) => {
return window.WWebJS.getLabel(labelId); return window.WWebJS.getLabel(labelId);
}, labelId); }, labelId);
return new Label(this, label); return new Label(this, label);
} }
@@ -829,12 +1158,12 @@ class Client extends EventEmitter {
* @param {string} chatId * @param {string} chatId
* @returns {Promise<Array<Label>>} * @returns {Promise<Array<Label>>}
*/ */
async getChatLabels(chatId){ async getChatLabels(chatId) {
const labels = await this.pupPage.evaluate(async (chatId) => { const labels = await this.pupPage.evaluate(async (chatId) => {
return window.WWebJS.getChatLabels(chatId); return window.WWebJS.getChatLabels(chatId);
}, chatId); }, chatId);
return labels.map(data => new Label(this, data)); return labels.map(data => new Label(this, data));
} }
/** /**
@@ -842,20 +1171,33 @@ class Client extends EventEmitter {
* @param {string} labelId * @param {string} labelId
* @returns {Promise<Array<Chat>>} * @returns {Promise<Array<Chat>>}
*/ */
async getChatsByLabelId(labelId){ async getChatsByLabelId(labelId) {
const chatIds = await this.pupPage.evaluate(async (labelId) => { const chatIds = await this.pupPage.evaluate(async (labelId) => {
const label = window.Store.Label.get(labelId); const label = window.Store.Label.get(labelId);
const labelItems = label.labelItemCollection.models; const labelItems = label.labelItemCollection.getModelsArray();
return labelItems.reduce((result, item) => { return labelItems.reduce((result, item) => {
if(item.parentType === 'Chat'){ if (item.parentType === 'Chat') {
result.push(item.parentId); result.push(item.parentId);
} }
return result; return result;
},[]); }, []);
}, labelId); }, labelId);
return Promise.all(chatIds.map(id => this.getChatById(id))); return Promise.all(chatIds.map(id => this.getChatById(id)));
} }
/**
* Gets all blocked contacts by host account
* @returns {Promise<Array<Contact>>}
*/
async getBlockedContacts() {
const blockedContacts = await this.pupPage.evaluate(() => {
let chatIds = window.Store.Blocklist.getModelsArray().map(a => a.id._serialized);
return Promise.all(chatIds.map(id => window.WWebJS.getContact(id)));
});
return blockedContacts.map(contact => ContactFactory.create(this.client, contact));
}
} }
module.exports = Client; module.exports = Client;

View File

@@ -0,0 +1,27 @@
'use strict';
/**
* Base class which all authentication strategies extend
*/
class BaseAuthStrategy {
constructor() {}
setup(client) {
this.client = client;
}
async beforeBrowserInitialized() {}
async afterBrowserInitialized() {}
async onAuthenticationNeeded() {
return {
failed: false,
restart: false,
failureEventPayload: undefined
};
}
async getAuthEventPayload() {}
async afterAuthReady() {}
async disconnect() {}
async destroy() {}
async logout() {}
}
module.exports = BaseAuthStrategy;

View File

@@ -0,0 +1,72 @@
'use strict';
const BaseAuthStrategy = require('./BaseAuthStrategy');
/**
* Legacy session auth strategy
* Not compatible with multi-device accounts.
* @param {object} options - options
* @param {string} options.restartOnAuthFail - Restart client with a new session (i.e. use null 'session' 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
*/
class LegacySessionAuth extends BaseAuthStrategy {
constructor({ session, restartOnAuthFail }={}) {
super();
this.session = session;
this.restartOnAuthFail = restartOnAuthFail;
}
async afterBrowserInitialized() {
if(this.session) {
await this.client.pupPage.evaluateOnNewDocument(session => {
if (document.referrer === 'https://whatsapp.com/') {
localStorage.clear();
localStorage.setItem('WABrowserId', session.WABrowserId);
localStorage.setItem('WASecretBundle', session.WASecretBundle);
localStorage.setItem('WAToken1', session.WAToken1);
localStorage.setItem('WAToken2', session.WAToken2);
}
localStorage.setItem('remember-me', 'true');
}, this.session);
}
}
async onAuthenticationNeeded() {
if(this.session) {
this.session = null;
return {
failed: true,
restart: this.restartOnAuthFail,
failureEventPayload: 'Unable to log in. Are the session details valid?'
};
}
return { failed: false };
}
async getAuthEventPayload() {
const isMD = await this.client.pupPage.evaluate(() => {
return window.Store.MDBackend;
});
if(isMD) throw new Error('Authenticating via JSON session is not supported for MultiDevice-enabled WhatsApp accounts.');
const localStorage = JSON.parse(await this.client.pupPage.evaluate(() => {
return JSON.stringify(window.localStorage);
}));
return {
WABrowserId: localStorage.WABrowserId,
WASecretBundle: localStorage.WASecretBundle,
WAToken1: localStorage.WAToken1,
WAToken2: localStorage.WAToken2
};
}
}
module.exports = LegacySessionAuth;

View File

@@ -0,0 +1,53 @@
'use strict';
const path = require('path');
const fs = require('fs');
const BaseAuthStrategy = require('./BaseAuthStrategy');
/**
* Local directory-based authentication
* @param {object} options - options
* @param {string} options.clientId - Client id to distinguish instances if you are using multiple, otherwise keep null if you are using only one instance
* @param {string} options.dataPath - Change the default path for saving session files, default is: "./.wwebjs_auth/"
*/
class LocalAuth extends BaseAuthStrategy {
constructor({ clientId, dataPath }={}) {
super();
const idRegex = /^[-_\w]+$/i;
if(clientId && !idRegex.test(clientId)) {
throw new Error('Invalid clientId. Only alphanumeric characters, underscores and hyphens are allowed.');
}
this.dataPath = path.resolve(dataPath || './.wwebjs_auth/');
this.clientId = clientId;
}
async beforeBrowserInitialized() {
const puppeteerOpts = this.client.options.puppeteer;
const sessionDirName = this.clientId ? `session-${this.clientId}` : 'session';
const dirPath = path.join(this.dataPath, sessionDirName);
if(puppeteerOpts.userDataDir && puppeteerOpts.userDataDir !== dirPath) {
throw new Error('LocalAuth is not compatible with a user-supplied userDataDir.');
}
fs.mkdirSync(dirPath, { recursive: true });
this.client.options.puppeteer = {
...puppeteerOpts,
userDataDir: dirPath
};
this.userDataDir = dirPath;
}
async logout() {
if (this.userDataDir) {
return (fs.rmSync ? fs.rmSync : fs.rmdirSync).call(this, this.userDataDir, { recursive: true });
}
}
}
module.exports = LocalAuth;

View File

@@ -0,0 +1,12 @@
'use strict';
const BaseAuthStrategy = require('./BaseAuthStrategy');
/**
* No session restoring functionality
* Will need to authenticate via QR code every time
*/
class NoAuth extends BaseAuthStrategy { }
module.exports = NoAuth;

View File

@@ -0,0 +1,204 @@
'use strict';
/* Require Optional Dependencies */
try {
var fs = require('fs-extra');
var unzipper = require('unzipper');
var archiver = require('archiver');
} catch {
fs = undefined;
unzipper = undefined;
archiver = undefined;
}
const path = require('path');
const { Events } = require('./../util/Constants');
const BaseAuthStrategy = require('./BaseAuthStrategy');
/**
* Remote-based authentication
* @param {object} options - options
* @param {object} options.store - Remote database store instance
* @param {string} options.clientId - Client id to distinguish instances if you are using multiple, otherwise keep null if you are using only one instance
* @param {string} options.dataPath - Change the default path for saving session files, default is: "./.wwebjs_auth/"
* @param {number} options.backupSyncIntervalMs - Sets the time interval for periodic session backups. Accepts values starting from 60000ms {1 minute}
*/
class RemoteAuth extends BaseAuthStrategy {
constructor({ clientId, dataPath, store, backupSyncIntervalMs } = {}) {
if (!fs && !unzipper && !archiver) throw new Error('Optional Dependencies [fs-extra, unzipper, archiver] are required to use RemoteAuth. Make sure to run npm install correctly and remove the --no-optional flag');
super();
const idRegex = /^[-_\w]+$/i;
if (clientId && !idRegex.test(clientId)) {
throw new Error('Invalid clientId. Only alphanumeric characters, underscores and hyphens are allowed.');
}
if (!backupSyncIntervalMs || backupSyncIntervalMs < 60000) {
throw new Error('Invalid backupSyncIntervalMs. Accepts values starting from 60000ms {1 minute}.');
}
if(!store) throw new Error('Remote database store is required.');
this.store = store;
this.clientId = clientId;
this.backupSyncIntervalMs = backupSyncIntervalMs;
this.dataPath = path.resolve(dataPath || './.wwebjs_auth/');
this.tempDir = `${this.dataPath}/wwebjs_temp_session`;
this.requiredDirs = ['Default', 'IndexedDB', 'Local Storage']; /* => Required Files & Dirs in WWebJS to restore session */
}
async beforeBrowserInitialized() {
const puppeteerOpts = this.client.options.puppeteer;
const sessionDirName = this.clientId ? `RemoteAuth-${this.clientId}` : 'RemoteAuth';
const dirPath = path.join(this.dataPath, sessionDirName);
if (puppeteerOpts.userDataDir && puppeteerOpts.userDataDir !== dirPath) {
throw new Error('RemoteAuth is not compatible with a user-supplied userDataDir.');
}
this.userDataDir = dirPath;
this.sessionName = sessionDirName;
await this.extractRemoteSession();
this.client.options.puppeteer = {
...puppeteerOpts,
userDataDir: dirPath
};
}
async logout() {
await this.disconnect();
}
async destroy() {
clearInterval(this.backupSync);
}
async disconnect() {
await this.deleteRemoteSession();
let pathExists = await this.isValidPath(this.userDataDir);
if (pathExists) {
await fs.promises.rm(this.userDataDir, {
recursive: true,
force: true
}).catch(() => {});
}
clearInterval(this.backupSync);
}
async afterAuthReady() {
const sessionExists = await this.store.sessionExists({session: this.sessionName});
if(!sessionExists) {
await this.delay(60000); /* Initial delay sync required for session to be stable enough to recover */
await this.storeRemoteSession({emit: true});
}
var self = this;
this.backupSync = setInterval(async function () {
await self.storeRemoteSession();
}, this.backupSyncIntervalMs);
}
async storeRemoteSession(options) {
/* Compress & Store Session */
const pathExists = await this.isValidPath(this.userDataDir);
if (pathExists) {
await this.compressSession();
await this.store.save({session: this.sessionName});
await fs.promises.unlink(`${this.sessionName}.zip`);
await fs.promises.rm(`${this.tempDir}`, {
recursive: true,
force: true
}).catch(() => {});
if(options && options.emit) this.client.emit(Events.REMOTE_SESSION_SAVED);
}
}
async extractRemoteSession() {
const pathExists = await this.isValidPath(this.userDataDir);
const compressedSessionPath = `${this.sessionName}.zip`;
const sessionExists = await this.store.sessionExists({session: this.sessionName});
if (pathExists) {
await fs.promises.rm(this.userDataDir, {
recursive: true,
force: true
}).catch(() => {});
}
if (sessionExists) {
await this.store.extract({session: this.sessionName, path: compressedSessionPath});
await this.unCompressSession(compressedSessionPath);
} else {
fs.mkdirSync(this.userDataDir, { recursive: true });
}
}
async deleteRemoteSession() {
const sessionExists = await this.store.sessionExists({session: this.sessionName});
if (sessionExists) await this.store.delete({session: this.sessionName});
}
async compressSession() {
const archive = archiver('zip');
const stream = fs.createWriteStream(`${this.sessionName}.zip`);
await fs.copy(this.userDataDir, this.tempDir).catch(() => {});
await this.deleteMetadata();
return new Promise((resolve, reject) => {
archive
.directory(this.tempDir, false)
.on('error', err => reject(err))
.pipe(stream);
stream.on('close', () => resolve());
archive.finalize();
});
}
async unCompressSession(compressedSessionPath) {
var stream = fs.createReadStream(compressedSessionPath);
await new Promise((resolve, reject) => {
stream.pipe(unzipper.Extract({
path: this.userDataDir
}))
.on('error', err => reject(err))
.on('finish', () => resolve());
});
await fs.promises.unlink(compressedSessionPath);
}
async deleteMetadata() {
const sessionDirs = [this.tempDir, path.join(this.tempDir, 'Default')];
for (const dir of sessionDirs) {
const sessionFiles = await fs.promises.readdir(dir);
for (const element of sessionFiles) {
if (!this.requiredDirs.includes(element)) {
const dirElement = path.join(dir, element);
const stats = await fs.promises.lstat(dirElement);
if (stats.isDirectory()) {
await fs.promises.rm(dirElement, {
recursive: true,
force: true
}).catch(() => {});
} else {
await fs.promises.unlink(dirElement).catch(() => {});
}
}
}
}
}
async isValidPath(path) {
try {
await fs.promises.access(path);
return true;
} catch {
return false;
}
}
async delay(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
}
module.exports = RemoteAuth;

82
src/structures/Buttons.js Normal file
View File

@@ -0,0 +1,82 @@
'use strict';
const MessageMedia = require('./MessageMedia');
const Util = require('../util/Util');
/**
* Button spec used in Buttons constructor
* @typedef {Object} ButtonSpec
* @property {string=} id - Custom ID to set on the button. A random one will be generated if one is not passed.
* @property {string} body - The text to show on the button.
*/
/**
* @typedef {Object} FormattedButtonSpec
* @property {string} buttonId
* @property {number} type
* @property {Object} buttonText
*/
/**
* Message type buttons
*/
class Buttons {
/**
* @param {string|MessageMedia} body
* @param {ButtonSpec[]} buttons - See {@link ButtonSpec}
* @param {string?} title
* @param {string?} footer
*/
constructor(body, buttons, title, footer) {
/**
* Message body
* @type {string|MessageMedia}
*/
this.body = body;
/**
* title of message
* @type {string}
*/
this.title = title;
/**
* footer of message
* @type {string}
*/
this.footer = footer;
if (body instanceof MessageMedia) {
this.type = 'media';
this.title = '';
}else{
this.type = 'chat';
}
/**
* buttons of message
* @type {FormattedButtonSpec[]}
*/
this.buttons = this._format(buttons);
if(!this.buttons.length){ throw '[BT01] No buttons';}
}
/**
* Creates button array from simple array
* @param {ButtonSpec[]} buttons
* @returns {FormattedButtonSpec[]}
* @example
* Input: [{id:'customId',body:'button1'},{body:'button2'},{body:'button3'},{body:'button4'}]
* Returns: [{ buttonId:'customId',buttonText:{'displayText':'button1'},type: 1 },{buttonId:'n3XKsL',buttonText:{'displayText':'button2'},type:1},{buttonId:'NDJk0a',buttonText:{'displayText':'button3'},type:1}]
*/
_format(buttons){
buttons = buttons.slice(0,3); // phone users can only see 3 buttons, so lets limit this
return buttons.map((btn) => {
return {'buttonId':btn.id ? String(btn.id) : Util.generateHash(6),'buttonText':{'displayText':btn.body},'type':1};
});
}
}
module.exports = Buttons;

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

@@ -65,7 +65,7 @@ class Chat extends Base {
/** /**
* Indicates if the chat is muted or not * Indicates if the chat is muted or not
* @type {number} * @type {boolean}
*/ */
this.isMuted = data.isMuted; this.isMuted = data.isMuted;
@@ -147,8 +147,8 @@ class Chat extends Base {
} }
/** /**
* Mutes this chat until a specified date * Mutes this chat forever, unless a date is specified
* @param {Date} unmuteDate Date at which the Chat will be unmuted * @param {?Date} unmuteDate Date at which the Chat will be unmuted, leave as is to mute forever
*/ */
async mute(unmuteDate) { async mute(unmuteDate) {
return this.client.muteChat(this.id._serialized, unmuteDate); return this.client.muteChat(this.id._serialized, unmuteDate);
@@ -170,31 +170,42 @@ class Chat extends Base {
/** /**
* Loads chat messages, sorted from earliest to latest. * Loads chat messages, sorted from earliest to latest.
* @param {Object} searchOptions Options for searching messages. Right now only limit is supported. * @param {Object} searchOptions Options for searching messages. Right now only limit and fromMe 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. * @param {Number} [searchOptions.limit] The amount of messages to return. If no limit is specified, the available messages will be returned. 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.
* @param {Boolean} [searchOptions.fromMe] Return only messages from the bot number or vise versa. To get all messages, leave the option undefined.
* @returns {Promise<Array<Message>>} * @returns {Promise<Array<Message>>}
*/ */
async fetchMessages(searchOptions) { async fetchMessages(searchOptions) {
if (!searchOptions || !searchOptions.limit) { let messages = await this.client.pupPage.evaluate(async (chatId, searchOptions) => {
searchOptions = { limit: 50 }; const msgFilter = (m) => {
} if (m.isNotification) {
let messages = await this.client.pupPage.evaluate(async (chatId, limit) => { return false; // dont include notification messages
const msgFilter = m => !m.isNotification; // dont include notification messages }
if (searchOptions && searchOptions.fromMe && m.id.fromMe !== searchOptions.fromMe) {
return false;
}
return true;
};
const chat = window.Store.Chat.get(chatId); const chat = window.Store.Chat.get(chatId);
let msgs = chat.msgs.models.filter(msgFilter); let msgs = chat.msgs.getModelsArray().filter(msgFilter);
while (msgs.length < limit) { if (searchOptions && searchOptions.limit > 0) {
const loadedMessages = await chat.loadEarlierMsgs(); while (msgs.length < searchOptions.limit) {
if (!loadedMessages) break; const loadedMessages = await window.Store.ConversationMsgs.loadEarlierMsgs(chat);
msgs = [...loadedMessages.filter(msgFilter), ...msgs]; if (!loadedMessages || !loadedMessages.length) break;
msgs = [...loadedMessages.filter(msgFilter), ...msgs];
}
if (msgs.length > searchOptions.limit) {
msgs.sort((a, b) => (a.t > b.t) ? 1 : -1);
msgs = msgs.splice(msgs.length - searchOptions.limit);
}
} }
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)); return msgs.map(m => window.WWebJS.getMessageModel(m));
}, this.id._serialized, searchOptions.limit); }, this.id._serialized, searchOptions);
return messages.map(m => new Message(this.client, m)); return messages.map(m => new Message(this.client, m));
} }

View File

@@ -20,12 +20,6 @@ class ClientInfo extends Base {
*/ */
this.pushname = data.pushname; this.pushname = data.pushname;
/**
* @type {object}
* @deprecated Use .wid instead
*/
this.me = data.wid;
/** /**
* Current user ID * Current user ID
* @type {object} * @type {object}
@@ -33,18 +27,25 @@ class ClientInfo extends Base {
this.wid = data.wid; this.wid = data.wid;
/** /**
* Information about the phone this client is connected to * @type {object}
* @deprecated Use .wid instead
*/
this.me = data.wid;
/**
* Information about the phone this client is connected to. Not available in multi-device.
* @type {object} * @type {object}
* @property {string} wa_version WhatsApp Version running on the phone * @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} os_version OS Version running on the phone (iOS or Android version)
* @property {string} device_manufacturer Device manufacturer * @property {string} device_manufacturer Device manufacturer
* @property {string} device_model Device model * @property {string} device_model Device model
* @property {string} os_build_number OS build number * @property {string} os_build_number OS build number
* @deprecated
*/ */
this.phone = data.phone; this.phone = data.phone;
/** /**
* Platform the phone is running on * Platform WhatsApp is running on
* @type {string} * @type {string}
*/ */
this.platform = data.platform; this.platform = data.platform;
@@ -57,6 +58,7 @@ class ClientInfo extends Base {
* @returns {object} batteryStatus * @returns {object} batteryStatus
* @returns {number} batteryStatus.battery - The current battery percentage * @returns {number} batteryStatus.battery - The current battery percentage
* @returns {boolean} batteryStatus.plugged - Indicates if the phone is plugged in (true) or not (false) * @returns {boolean} batteryStatus.plugged - Indicates if the phone is plugged in (true) or not (false)
* @deprecated
*/ */
async getBatteryStatus() { async getBatteryStatus() {
return await this.client.pupPage.evaluate(() => { return await this.client.pupPage.evaluate(() => {
@@ -64,7 +66,6 @@ class ClientInfo extends Base {
return { battery, plugged }; return { battery, plugged };
}); });
} }
} }
module.exports = ClientInfo; module.exports = ClientInfo;

View File

@@ -108,7 +108,7 @@ class Contact extends Base {
* @type {boolean} * @type {boolean}
*/ */
this.isBlocked = data.isBlocked; this.isBlocked = data.isBlocked;
return super._patch(data); return super._patch(data);
} }
@@ -120,6 +120,22 @@ class Contact extends Base {
return await this.client.getProfilePicUrl(this.id._serialized); return await this.client.getProfilePicUrl(this.id._serialized);
} }
/**
* Returns the contact's formatted phone number, (12345678901@c.us) => (+1 (234) 5678-901)
* @returns {Promise<string>}
*/
async getFormattedNumber() {
return await this.client.getFormattedNumber(this.id._serialized);
}
/**
* Returns the contact's countrycode, (1541859685@c.us) => (1)
* @returns {Promise<string>}
*/
async getCountryCode() {
return await this.client.getCountryCode(this.id._serialized);
}
/** /**
* Returns the Chat that corresponds to this Contact. * Returns the Chat that corresponds to this Contact.
* Will return null when getting chat for currently logged in user. * Will return null when getting chat for currently logged in user.
@@ -167,7 +183,8 @@ class Contact extends Base {
*/ */
async getAbout() { async getAbout() {
const about = await this.client.pupPage.evaluate(async (contactId) => { const about = await this.client.pupPage.evaluate(async (contactId) => {
return window.Store.Wap.statusFind(contactId); const wid = window.Store.WidFactory.createWid(contactId);
return window.Store.StatusUtils.getStatus(wid);
}, this.id._serialized); }, this.id._serialized);
if (typeof about.status !== 'string') if (typeof about.status !== 'string')
@@ -175,7 +192,15 @@ class Contact extends Base {
return about.status; return about.status;
} }
/**
* Gets the Contact's common groups with you. Returns empty array if you don't have any common group.
* @returns {Promise<WAWebJS.ChatId[]>}
*/
async getCommonGroups() {
return await this.client.getCommonGroups(this.id._serialized);
}
} }
module.exports = Contact; module.exports = Contact;

View File

@@ -60,7 +60,9 @@ class GroupChat extends Chat {
*/ */
async addParticipants(participantIds) { async addParticipants(participantIds) {
return await this.client.pupPage.evaluate((chatId, participantIds) => { return await this.client.pupPage.evaluate((chatId, participantIds) => {
return window.Store.Wap.addParticipants(chatId, participantIds); const chatWid = window.Store.WidFactory.createWid(chatId);
const participantWids = participantIds.map(p => window.Store.WidFactory.createWid(p));
return window.Store.GroupParticipants.sendAddParticipants(chatWid, participantWids);
}, this.id._serialized, participantIds); }, this.id._serialized, participantIds);
} }
@@ -71,7 +73,9 @@ class GroupChat extends Chat {
*/ */
async removeParticipants(participantIds) { async removeParticipants(participantIds) {
return await this.client.pupPage.evaluate((chatId, participantIds) => { return await this.client.pupPage.evaluate((chatId, participantIds) => {
return window.Store.Wap.removeParticipants(chatId, participantIds); const chatWid = window.Store.WidFactory.createWid(chatId);
const participantWids = participantIds.map(p => window.Store.WidFactory.createWid(p));
return window.Store.GroupParticipants.sendRemoveParticipants(chatWid, participantWids);
}, this.id._serialized, participantIds); }, this.id._serialized, participantIds);
} }
@@ -82,7 +86,9 @@ class GroupChat extends Chat {
*/ */
async promoteParticipants(participantIds) { async promoteParticipants(participantIds) {
return await this.client.pupPage.evaluate((chatId, participantIds) => { return await this.client.pupPage.evaluate((chatId, participantIds) => {
return window.Store.Wap.promoteParticipants(chatId, participantIds); const chatWid = window.Store.WidFactory.createWid(chatId);
const participantWids = participantIds.map(p => window.Store.WidFactory.createWid(p));
return window.Store.GroupParticipants.sendPromoteParticipants(chatWid, participantWids);
}, this.id._serialized, participantIds); }, this.id._serialized, participantIds);
} }
@@ -93,53 +99,73 @@ class GroupChat extends Chat {
*/ */
async demoteParticipants(participantIds) { async demoteParticipants(participantIds) {
return await this.client.pupPage.evaluate((chatId, participantIds) => { return await this.client.pupPage.evaluate((chatId, participantIds) => {
return window.Store.Wap.demoteParticipants(chatId, participantIds); const chatWid = window.Store.WidFactory.createWid(chatId);
const participantWids = participantIds.map(p => window.Store.WidFactory.createWid(p));
return window.Store.GroupParticipants.sendDemoteParticipants(chatWid, participantWids);
}, this.id._serialized, participantIds); }, this.id._serialized, participantIds);
} }
/** /**
* Updates the group subject * Updates the group subject
* @param {string} subject * @param {string} subject
* @returns {Promise} * @returns {Promise<boolean>} Returns true if the subject was properly updated. This can return false if the user does not have the necessary permissions.
*/ */
async setSubject(subject) { async setSubject(subject) {
let res = await this.client.pupPage.evaluate((chatId, subject) => { const success = await this.client.pupPage.evaluate(async (chatId, subject) => {
return window.Store.Wap.changeSubject(chatId, subject); const chatWid = window.Store.WidFactory.createWid(chatId);
try {
return await window.Store.GroupUtils.sendSetGroupSubject(chatWid, subject);
} catch (err) {
if(err.name === 'ServerStatusCodeError') return false;
throw err;
}
}, this.id._serialized, subject); }, this.id._serialized, subject);
if(res.status == 200) { if(!success) return false;
this.name = subject; this.name = subject;
} return true;
} }
/** /**
* Updates the group description * Updates the group description
* @param {string} description * @param {string} description
* @returns {Promise} * @returns {Promise<boolean>} Returns true if the description was properly updated. This can return false if the user does not have the necessary permissions.
*/ */
async setDescription(description) { async setDescription(description) {
let res = await this.client.pupPage.evaluate((chatId, description) => { const success = await this.client.pupPage.evaluate(async (chatId, description) => {
let descId = window.Store.GroupMetadata.get(chatId).descId; const chatWid = window.Store.WidFactory.createWid(chatId);
return window.Store.Wap.setGroupDescription(chatId, description, window.Store.genId(), descId); let descId = window.Store.GroupMetadata.get(chatWid).descId;
try {
return await window.Store.GroupUtils.sendSetGroupDescription(chatWid, description, window.Store.MsgKey.newId(), descId);
} catch (err) {
if(err.name === 'ServerStatusCodeError') return false;
throw err;
}
}, this.id._serialized, description); }, this.id._serialized, description);
if (res.status == 200) { if(!success) return false;
this.groupMetadata.desc = description; this.groupMetadata.desc = description;
} return true;
} }
/** /**
* Updates the group settings to only allow admins to send messages. * Updates the group settings to only allow admins to send messages.
* @param {boolean} [adminsOnly=true] Enable or disable this option * @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. * @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) { async setMessagesAdminsOnly(adminsOnly=true) {
let res = await this.client.pupPage.evaluate((chatId, value) => { const success = await this.client.pupPage.evaluate(async (chatId, adminsOnly) => {
return window.Store.Wap.setGroupProperty(chatId, 'announcement', value); const chatWid = window.Store.WidFactory.createWid(chatId);
try {
return await window.Store.GroupUtils.sendSetGroupProperty(chatWid, 'announcement', adminsOnly ? 1 : 0);
} catch (err) {
if(err.name === 'ServerStatusCodeError') return false;
throw err;
}
}, this.id._serialized, adminsOnly); }, this.id._serialized, adminsOnly);
if (res.status !== 200) return false; if(!success) return false;
this.groupMetadata.announce = adminsOnly; this.groupMetadata.announce = adminsOnly;
return true; return true;
} }
@@ -150,11 +176,17 @@ class GroupChat extends Chat {
* @returns {Promise<boolean>} Returns true if the setting was properly updated. This can return false if the user does not have the necessary permissions. * @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) { async setInfoAdminsOnly(adminsOnly=true) {
let res = await this.client.pupPage.evaluate((chatId, value) => { const success = await this.client.pupPage.evaluate(async (chatId, adminsOnly) => {
return window.Store.Wap.setGroupProperty(chatId, 'restrict', value); const chatWid = window.Store.WidFactory.createWid(chatId);
try {
return await window.Store.GroupUtils.sendSetGroupProperty(chatWid, 'restrict', adminsOnly ? 1 : 0);
} catch (err) {
if(err.name === 'ServerStatusCodeError') return false;
throw err;
}
}, this.id._serialized, adminsOnly); }, this.id._serialized, adminsOnly);
if (res.status !== 200) return false; if(!success) return false;
this.groupMetadata.restrict = adminsOnly; this.groupMetadata.restrict = adminsOnly;
return true; return true;
@@ -165,25 +197,25 @@ class GroupChat extends Chat {
* @returns {Promise<string>} Group's invite code * @returns {Promise<string>} Group's invite code
*/ */
async getInviteCode() { async getInviteCode() {
let res = await this.client.pupPage.evaluate(chatId => { const code = await this.client.pupPage.evaluate(async chatId => {
return window.Store.Wap.groupInviteCode(chatId); const chatWid = window.Store.WidFactory.createWid(chatId);
return window.Store.Invite.sendQueryGroupInviteCode(chatWid);
}, this.id._serialized); }, this.id._serialized);
if (res.status == 200) { return code;
return res.code;
}
throw new Error('Not authorized');
} }
/** /**
* Invalidates the current group invite code and generates a new one * Invalidates the current group invite code and generates a new one
* @returns {Promise} * @returns {Promise<string>} New invite code
*/ */
async revokeInvite() { async revokeInvite() {
return await this.client.pupPage.evaluate(chatId => { const code = await this.client.pupPage.evaluate(chatId => {
return window.Store.Wap.revokeGroupInvite(chatId); const chatWid = window.Store.WidFactory.createWid(chatId);
return window.Store.Invite.sendRevokeGroupInviteCode(chatWid);
}, this.id._serialized); }, this.id._serialized);
return code;
} }
/** /**
@@ -191,8 +223,9 @@ class GroupChat extends Chat {
* @returns {Promise} * @returns {Promise}
*/ */
async leave() { async leave() {
return await this.client.pupPage.evaluate(chatId => { await this.client.pupPage.evaluate(chatId => {
return window.Store.Wap.leaveGroup(chatId); const chatWid = window.Store.WidFactory.createWid(chatId);
return window.Store.GroupUtils.sendExitGroup(chatWid);
}, this.id._serialized); }, this.id._serialized);
} }

View File

@@ -43,7 +43,7 @@ class GroupNotification extends Base {
* *
* @type {string} * @type {string}
*/ */
this.chatId = typeof (data.from) === 'object' ? data.from._serialized : data.from; this.chatId = typeof (data.id.remote) === 'object' ? data.id.remote._serialized : data.id.remote;
/** /**
* ContactId for the user that produced the GroupNotification. * ContactId for the user that produced the GroupNotification.

79
src/structures/List.js Normal file
View File

@@ -0,0 +1,79 @@
'use strict';
const Util = require('../util/Util');
/**
* Message type List
*/
class List {
/**
* @param {string} body
* @param {string} buttonText
* @param {Array<any>} sections
* @param {string?} title
* @param {string?} footer
*/
constructor(body, buttonText, sections, title, footer) {
/**
* Message body
* @type {string}
*/
this.description = body;
/**
* List button text
* @type {string}
*/
this.buttonText = buttonText;
/**
* title of message
* @type {string}
*/
this.title = title;
/**
* footer of message
* @type {string}
*/
this.footer = footer;
/**
* sections of message
* @type {Array<any>}
*/
this.sections = this._format(sections);
}
/**
* Creates section array from simple array
* @param {Array<any>} sections
* @returns {Array<any>}
* @example
* Input: [{title:'sectionTitle',rows:[{id:'customId', title:'ListItem2', description: 'desc'},{title:'ListItem2'}]}}]
* Returns: [{'title':'sectionTitle','rows':[{'rowId':'customId','title':'ListItem1','description':'desc'},{'rowId':'oGSRoD','title':'ListItem2','description':''}]}]
*/
_format(sections){
if(!sections.length){throw '[LT02] List without sections';}
if(sections.length > 1 && sections.filter(s => typeof s.title == 'undefined').length > 1){throw '[LT05] You can\'t have more than one empty title.';}
return sections.map( (section) =>{
if(!section.rows.length){throw '[LT03] Section without rows';}
return {
title: section.title ? section.title : undefined,
rows: section.rows.map( (row) => {
if(!row.title){throw '[LT04] Row without title';}
return {
rowId: row.id ? row.id : Util.generateHash(6),
title: row.title,
description: row.description ? row.description : ''
};
})
};
});
}
}
module.exports = List;

View File

@@ -3,6 +3,8 @@
const Base = require('./Base'); const Base = require('./Base');
const MessageMedia = require('./MessageMedia'); const MessageMedia = require('./MessageMedia');
const Location = require('./Location'); const Location = require('./Location');
const Order = require('./Order');
const Payment = require('./Payment');
const { MessageTypes } = require('../util/Constants'); const { MessageTypes } = require('../util/Constants');
/** /**
@@ -17,13 +19,14 @@ class Message extends Base {
} }
_patch(data) { _patch(data) {
this._data = data;
/** /**
* MediaKey that represents the sticker 'ID' * MediaKey that represents the sticker 'ID'
* @type {string} * @type {string}
*/ */
this.mediaKey = data.mediaKey; this.mediaKey = data.mediaKey;
/** /**
* ID that represents the message * ID that represents the message
* @type {object} * @type {object}
@@ -40,7 +43,7 @@ class Message extends Base {
* Indicates if the message has media available for download * Indicates if the message has media available for download
* @type {boolean} * @type {boolean}
*/ */
this.hasMedia = data.clientUrl || data.deprecatedMms3Url ? true : false; this.hasMedia = Boolean(data.mediaKey && data.directPath);
/** /**
* Message content * Message content
@@ -48,7 +51,7 @@ class Message extends Base {
*/ */
this.body = this.hasMedia ? data.caption || '' : data.body || ''; this.body = this.hasMedia ? data.caption || '' : data.body || '';
/** /**
* Message type * Message type
* @type {MessageTypes} * @type {MessageTypes}
*/ */
@@ -68,9 +71,9 @@ class Message extends Base {
/** /**
* ID for who this message is for. * 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 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. * If the message is sent by another user, it will be the ID for the current user.
* @type {string} * @type {string}
*/ */
this.to = (typeof (data.to) === 'object' && data.to !== null) ? data.to._serialized : data.to; this.to = (typeof (data.to) === 'object' && data.to !== null) ? data.to._serialized : data.to;
@@ -81,12 +84,26 @@ class Message extends Base {
*/ */
this.author = (typeof (data.author) === 'object' && data.author !== null) ? data.author._serialized : data.author; 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 * Indicates if the message was forwarded
* @type {boolean} * @type {boolean}
*/ */
this.isForwarded = data.isForwarded; 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 * Indicates if the message is a status update
* @type {boolean} * @type {boolean}
@@ -98,14 +115,14 @@ class Message extends Base {
* @type {boolean} * @type {boolean}
*/ */
this.isStarred = data.star; this.isStarred = data.star;
/** /**
* Indicates if the message was a broadcast * Indicates if the message was a broadcast
* @type {boolean} * @type {boolean}
*/ */
this.broadcast = data.broadcast; this.broadcast = data.broadcast;
/** /**
* Indicates if the message was sent by the current user * Indicates if the message was sent by the current user
* @type {boolean} * @type {boolean}
*/ */
@@ -117,6 +134,12 @@ class Message extends Base {
*/ */
this.hasQuotedMsg = data.quotedMsg ? true : false; this.hasQuotedMsg = data.quotedMsg ? true : false;
/**
* Indicates the duration of the message in seconds
* @type {string}
*/
this.duration = data.duration ? data.duration : undefined;
/** /**
* Location information contained in the message, if the message is type "location" * Location information contained in the message, if the message is type "location"
* @type {Location} * @type {Location}
@@ -129,6 +152,19 @@ class Message extends Base {
*/ */
this.vCards = data.type === MessageTypes.CONTACT_CARD_MULTI ? data.vcardList.map((c) => c.vcard) : data.type === MessageTypes.CONTACT_CARD ? [data.body] : []; 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. * Indicates the mentions in the message body.
* @type {Array<string>} * @type {Array<string>}
@@ -139,12 +175,71 @@ class Message extends Base {
this.mentionedIds = 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;
/**
* Indicates whether the message is a Gif
* @type {boolean}
*/
this.isGif = Boolean(data.isGif);
/**
* Indicates if the message will disappear after it expires
* @type {boolean}
*/
this.isEphemeral = data.isEphemeral;
/** 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. * Links included in the message.
* @type {Array<string>} * @type {Array<{link: string, isSuspicious: boolean}>}
*
*/ */
this.links = data.links; this.links = data.links;
/** Buttons */
if (data.dynamicReplyButtons) {
this.dynamicReplyButtons = data.dynamicReplyButtons;
}
/** Selected Button Id **/
if (data.selectedButtonId) {
this.selectedButtonId = data.selectedButtonId;
}
/** Selected List row Id **/
if (data.listResponse && data.listResponse.singleSelectReply.selectedRowId) {
this.selectedRowId = data.listResponse.singleSelectReply.selectedRowId;
}
return super._patch(data); return super._patch(data);
} }
@@ -152,6 +247,32 @@ class Message extends Base {
return this.fromMe ? this.to : this.from; return this.fromMe ? this.to : this.from;
} }
/**
* Reloads this Message object's data in-place with the latest values from WhatsApp Web.
* Note that the Message must still be in the web app cache for this to work, otherwise will return null.
* @returns {Promise<Message>}
*/
async reload() {
const newData = await this.client.pupPage.evaluate((msgId) => {
const msg = window.Store.Msg.get(msgId);
if(!msg) return null;
return window.WWebJS.getMessageModel(msg);
}, this.id._serialized);
if(!newData) return null;
this._patch(newData);
return this;
}
/**
* Returns message in a raw format
* @type {Object}
*/
get rawData() {
return this._data;
}
/** /**
* Returns the Chat this message was sent in * Returns the Chat this message was sent in
* @returns {Promise<Chat>} * @returns {Promise<Chat>}
@@ -184,20 +305,21 @@ class Message extends Base {
if (!this.hasQuotedMsg) return undefined; if (!this.hasQuotedMsg) return undefined;
const quotedMsg = await this.client.pupPage.evaluate((msgId) => { const quotedMsg = await this.client.pupPage.evaluate((msgId) => {
let msg = window.Store.Msg.get(msgId); const msg = window.Store.Msg.get(msgId);
return msg.quotedMsgObj().serialize(); const quotedMsg = window.Store.QuotedMsg.getQuotedMsgObj(msg);
return window.WWebJS.getMessageModel(quotedMsg);
}, this.id._serialized); }, this.id._serialized);
return new Message(this.client, quotedMsg); return new Message(this.client, quotedMsg);
} }
/** /**
* Sends a message as a reply to this message. If chatId is specified, it will be sent * 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 * through the specified Chat. If not, it will send the message
* in the same Chat as the original message was sent. * in the same Chat as the original message was sent.
* *
* @param {string|MessageMedia|Location} content * @param {string|MessageMedia|Location} content
* @param {string} [chatId] * @param {string} [chatId]
* @param {MessageSendOptions} [options] * @param {MessageSendOptions} [options]
* @returns {Promise<Message>} * @returns {Promise<Message>}
*/ */
@@ -215,8 +337,30 @@ class Message extends Base {
} }
/** /**
* Forwards this message to another chat * React to this message with an emoji
* * @param {string} reaction - Emoji to react with. Send an empty string to remove the reaction.
* @return {Promise}
*/
async react(reaction){
await this.client.pupPage.evaluate(async (messageId, reaction) => {
if (!messageId) { return undefined; }
const msg = await window.Store.Msg.get(messageId);
await window.Store.sendReactionToMsg(msg, reaction);
}, this.id._serialized, reaction);
}
/**
* Accept Group V4 Invite
* @returns {Promise<Object>}
*/
async acceptGroupV4Invite() {
return await this.client.acceptGroupV4Invite(this.inviteV4);
}
/**
* Forwards this message to another chat (that you chatted before, otherwise it will fail)
*
* @param {string|Chat} chat Chat model or chat ID to which the message will be forwarded * @param {string|Chat} chat Chat model or chat ID to which the message will be forwarded
* @returns {Promise} * @returns {Promise}
*/ */
@@ -245,42 +389,57 @@ class Message extends Base {
if (msg.mediaData.mediaStage != 'RESOLVED') { if (msg.mediaData.mediaStage != 'RESOLVED') {
// try to resolve media // try to resolve media
await msg.downloadMedia(true, 1); await msg.downloadMedia({
downloadEvenIfExpensive: true,
rmrReason: 1
});
} }
if (msg.mediaData.mediaStage.includes('ERROR')) { if (msg.mediaData.mediaStage.includes('ERROR') || msg.mediaData.mediaStage === 'FETCHING') {
// media could not be downloaded // media could not be downloaded
return undefined; return undefined;
} }
const mediaUrl = msg.clientUrl || msg.deprecatedMms3Url; 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 buffer = await window.WWebJS.downloadBuffer(mediaUrl); const data = await window.WWebJS.arrayBufferToBase64Async(decryptedMedia);
const decrypted = await window.Store.CryptoLib.decryptE2EMedia(msg.type, buffer, msg.mediaKey, msg.mimetype);
const data = await window.WWebJS.readBlobAsync(decrypted._blob);
return {
data: data.split(',')[1],
mimetype: msg.mimetype,
filename: msg.filename
};
return {
data,
mimetype: msg.mimetype,
filename: msg.filename,
filesize: msg.size
};
} catch (e) {
if(e.status && e.status === 404) return undefined;
throw e;
}
}, this.id._serialized); }, this.id._serialized);
if (!result) return undefined; if (!result) return undefined;
return new MessageMedia(result.mimetype, result.data, result.filename); return new MessageMedia(result.mimetype, result.data, result.filename, result.filesize);
} }
/** /**
* Deletes a message from the chat * 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. * @param {?boolean} everyone If true and the message is sent by the current user or the user is an admin, will delete it for everyone in the chat.
*/ */
async delete(everyone) { async delete(everyone) {
await this.client.pupPage.evaluate((msgId, everyone) => { await this.client.pupPage.evaluate((msgId, everyone) => {
let msg = window.Store.Msg.get(msgId); let msg = window.Store.Msg.get(msgId);
if (everyone && msg.id.fromMe && msg.canRevoke()) { const canRevoke = window.Store.MsgActionChecks.canSenderRevokeMsg(msg) || window.Store.MsgActionChecks.canAdminRevokeMsg(msg);
return window.Store.Cmd.sendRevokeMsgs(msg.chat, [msg], true); if (everyone && canRevoke) {
return window.Store.Cmd.sendRevokeMsgs(msg.chat, [msg], { type: msg.id.fromMe ? 'Sender' : 'Admin' });
} }
return window.Store.Cmd.sendDeleteMsgs(msg.chat, [msg], true); return window.Store.Cmd.sendDeleteMsgs(msg.chat, [msg], true);
@@ -294,8 +453,8 @@ class Message extends Base {
await this.client.pupPage.evaluate((msgId) => { await this.client.pupPage.evaluate((msgId) => {
let msg = window.Store.Msg.get(msgId); let msg = window.Store.Msg.get(msgId);
if (msg.canStar()) { if (window.Store.MsgActionChecks.canStarMsg(msg)) {
return msg.chat.sendStarMsgs([msg], true); return window.Store.Cmd.sendStarMsgs(msg.chat, [msg], false);
} }
}, this.id._serialized); }, this.id._serialized);
} }
@@ -307,8 +466,8 @@ class Message extends Base {
await this.client.pupPage.evaluate((msgId) => { await this.client.pupPage.evaluate((msgId) => {
let msg = window.Store.Msg.get(msgId); let msg = window.Store.Msg.get(msgId);
if (msg.canStar()) { if (window.Store.MsgActionChecks.canStarMsg(msg)) {
return msg.chat.sendStarMsgs([msg], false); return window.Store.Cmd.sendUnstarMsgs(msg.chat, [msg], false);
} }
}, this.id._serialized); }, this.id._serialized);
} }
@@ -331,17 +490,43 @@ class Message extends Base {
async getInfo() { async getInfo() {
const info = await this.client.pupPage.evaluate(async (msgId) => { const info = await this.client.pupPage.evaluate(async (msgId) => {
const msg = window.Store.Msg.get(msgId); const msg = window.Store.Msg.get(msgId);
if(!msg) return null; if (!msg) return null;
return await window.Store.Wap.queryMsgInfo(msg.id); return await window.Store.MessageInfo.sendQueryMsgInfo(msg);
}, this.id._serialized); }, this.id._serialized);
if(info.status) {
return null;
}
return info; return info;
} }
/**
* 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, chatId) => {
return window.WWebJS.getOrderDetail(orderId, token, chatId);
}, this.orderId, this.token, this._getChatId());
if (!result) return undefined;
return new Order(this.client, result);
}
return undefined;
}
/**
* Gets the payment details associated with a given message
* @return {Promise<Payment>}
*/
async getPayment() {
if (this.type === MessageTypes.PAYMENT) {
const msg = await this.client.pupPage.evaluate(async (msgId) => {
const msg = window.Store.Msg.get(msgId);
if(!msg) return null;
return msg.serialize();
}, this.id._serialized);
return new Payment(this.client, msg);
}
return undefined;
}
} }
module.exports = Message; module.exports = Message;

View File

@@ -3,15 +3,18 @@
const fs = require('fs'); const fs = require('fs');
const path = require('path'); const path = require('path');
const mime = require('mime'); const mime = require('mime');
const fetch = require('node-fetch');
const { URL } = require('url');
/** /**
* Media attached to a message * Media attached to a message
* @param {string} mimetype MIME type of the attachment * @param {string} mimetype MIME type of the attachment
* @param {string} data Base64-encoded data of the file * @param {string} data Base64-encoded data of the file
* @param {?string} filename Document file name * @param {?string} filename Document file name. Value can be null
* @param {?number} filesize Document file size in bytes. Value can be null
*/ */
class MessageMedia { class MessageMedia {
constructor(mimetype, data, filename) { constructor(mimetype, data, filename, filesize) {
/** /**
* MIME type of the attachment * MIME type of the attachment
* @type {string} * @type {string}
@@ -25,10 +28,16 @@ class MessageMedia {
this.data = data; this.data = data;
/** /**
* Name of the file (for documents) * Document file name. Value can be null
* @type {?string} * @type {?string}
*/ */
this.filename = filename; this.filename = filename;
/**
* Document file size in bytes. Value can be null
* @type {?number}
*/
this.filesize = filesize;
} }
/** /**
@@ -43,6 +52,60 @@ class MessageMedia {
return new MessageMedia(mimetype, b64data, filename); return new MessageMedia(mimetype, b64data, filename);
} }
/**
* Creates a MessageMedia instance from a URL
* @param {string} url
* @param {Object} [options]
* @param {boolean} [options.unsafeMime=false]
* @param {string} [options.filename]
* @param {object} [options.client]
* @param {object} [options.reqOptions]
* @param {number} [options.reqOptions.size=0]
* @returns {Promise<MessageMedia>}
*/
static async fromUrl(url, options = {}) {
const pUrl = new URL(url);
let mimetype = mime.getType(pUrl.pathname);
if (!mimetype && !options.unsafeMime)
throw new Error('Unable to determine MIME type using URL. Set unsafeMime to true to download it anyway.');
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');
const size = response.headers.get('Content-Length');
const contentDisposition = response.headers.get('Content-Disposition');
const name = contentDisposition ? contentDisposition.match(/((?<=filename=")(.*)(?="))/) : null;
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, name, size };
}
const res = options.client
? (await options.client.pupPage.evaluate(fetchData, url, options.reqOptions))
: (await fetchData(url, options.reqOptions));
const filename = options.filename ||
(res.name ? res.name[0] : (pUrl.pathname.split('/').pop() || 'file'));
if (!mimetype)
mimetype = res.mime;
return new MessageMedia(mimetype, res.data, filename, res.size || null);
}
} }
module.exports = MessageMedia; 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;

79
src/structures/Payment.js Normal file
View File

@@ -0,0 +1,79 @@
const Base = require('./Base');
class Payment extends Base {
constructor(client, data) {
super(client);
if (data) this._patch(data);
}
_patch(data) {
/**
* The payment Id
* @type {object}
*/
this.id = data.id;
/**
* The payment currency
* @type {string}
*/
this.paymentCurrency = data.paymentCurrency;
/**
* The payment ammount ( R$ 1.00 = 1000 )
* @type {number}
*/
this.paymentAmount1000 = data.paymentAmount1000;
/**
* The payment receiver
* @type {object}
*/
this.paymentMessageReceiverJid = data.paymentMessageReceiverJid;
/**
* The payment transaction timestamp
* @type {number}
*/
this.paymentTransactionTimestamp = data.paymentTransactionTimestamp;
/**
* The paymentStatus
*
* Possible Status
* 0:UNKNOWN_STATUS
* 1:PROCESSING
* 2:SENT
* 3:NEED_TO_ACCEPT
* 4:COMPLETE
* 5:COULD_NOT_COMPLETE
* 6:REFUNDED
* 7:EXPIRED
* 8:REJECTED
* 9:CANCELLED
* 10:WAITING_FOR_PAYER
* 11:WAITING
*
* @type {number}
*/
this.paymentStatus = data.paymentStatus;
/**
* Integer that represents the payment Text
* @type {number}
*/
this.paymentTxnStatus = data.paymentTxnStatus;
/**
* The note sent with the payment
* @type {string}
*/
this.paymentNote = !data.paymentNoteMsg ? undefined : data.paymentNoteMsg.body ? data.paymentNoteMsg.body : undefined ;
return super._patch(data);
}
}
module.exports = Payment;

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;

Some files were not shown because too many files have changed in this diff Show More