@japofc/baileys 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/NOTICE.md +111 -0
- package/README.md +1254 -0
- package/WAProto/index.d.ts +9 -0
- package/WAProto/index.js +142276 -0
- package/engine-requirements.js +13 -0
- package/lib/Builders/A2UI.d.ts +242 -0
- package/lib/Builders/A2UI.js +308 -0
- package/lib/Builders/AIRich.d.ts +105 -0
- package/lib/Builders/AIRich.js +2286 -0
- package/lib/Builders/Button.d.ts +103 -0
- package/lib/Builders/Button.js +883 -0
- package/lib/Builders/ButtonV2.d.ts +28 -0
- package/lib/Builders/ButtonV2.js +144 -0
- package/lib/Builders/ButtonV3.d.ts +25 -0
- package/lib/Builders/ButtonV3.js +184 -0
- package/lib/Builders/Carousel.d.ts +22 -0
- package/lib/Builders/Carousel.js +111 -0
- package/lib/Builders/JapBaileys.d.ts +34 -0
- package/lib/Builders/JapBaileys.js +108 -0
- package/lib/Builders/Poll.d.ts +25 -0
- package/lib/Builders/Poll.js +128 -0
- package/lib/Builders/index.d.ts +17 -0
- package/lib/Builders/index.js +11 -0
- package/lib/Builders/shared.d.ts +67 -0
- package/lib/Builders/shared.js +652 -0
- package/lib/Defaults/index.d.ts +154 -0
- package/lib/Defaults/index.js +178 -0
- package/lib/Framework/Bot.d.ts +61 -0
- package/lib/Framework/Bot.js +248 -0
- package/lib/Framework/Context.d.ts +21 -0
- package/lib/Framework/Context.js +89 -0
- package/lib/Framework/MediaManager.d.ts +17 -0
- package/lib/Framework/MediaManager.js +151 -0
- package/lib/Framework/SessionManager.d.ts +13 -0
- package/lib/Framework/SessionManager.js +33 -0
- package/lib/Framework/StatsManager.d.ts +26 -0
- package/lib/Framework/StatsManager.js +119 -0
- package/lib/Framework/Store/SQLiteStore.d.ts +11 -0
- package/lib/Framework/Store/SQLiteStore.js +73 -0
- package/lib/Framework/index.d.ts +9 -0
- package/lib/Framework/index.js +10 -0
- package/lib/Signal/Group/ciphertext-message.d.ts +9 -0
- package/lib/Signal/Group/ciphertext-message.js +11 -0
- package/lib/Signal/Group/group-session-builder.d.ts +7 -0
- package/lib/Signal/Group/group-session-builder.js +29 -0
- package/lib/Signal/Group/group_cipher.d.ts +10 -0
- package/lib/Signal/Group/group_cipher.js +81 -0
- package/lib/Signal/Group/index.d.ts +11 -0
- package/lib/Signal/Group/index.js +11 -0
- package/lib/Signal/Group/keyhelper.d.ts +6 -0
- package/lib/Signal/Group/keyhelper.js +17 -0
- package/lib/Signal/Group/sender-chain-key.d.ts +13 -0
- package/lib/Signal/Group/sender-chain-key.js +25 -0
- package/lib/Signal/Group/sender-key-distribution-message.d.ts +16 -0
- package/lib/Signal/Group/sender-key-distribution-message.js +62 -0
- package/lib/Signal/Group/sender-key-message.d.ts +18 -0
- package/lib/Signal/Group/sender-key-message.js +65 -0
- package/lib/Signal/Group/sender-key-name.d.ts +11 -0
- package/lib/Signal/Group/sender-key-name.js +47 -0
- package/lib/Signal/Group/sender-key-record.d.ts +12 -0
- package/lib/Signal/Group/sender-key-record.js +40 -0
- package/lib/Signal/Group/sender-key-state.d.ts +16 -0
- package/lib/Signal/Group/sender-key-state.js +83 -0
- package/lib/Signal/Group/sender-message-key.d.ts +11 -0
- package/lib/Signal/Group/sender-message-key.js +25 -0
- package/lib/Signal/libsignal.d.ts +54 -0
- package/lib/Signal/libsignal.js +430 -0
- package/lib/Signal/lid-mapping.d.ts +20 -0
- package/lib/Signal/lid-mapping.js +276 -0
- package/lib/Socket/Client/index.d.ts +2 -0
- package/lib/Socket/Client/index.js +2 -0
- package/lib/Socket/Client/types.d.ts +5 -0
- package/lib/Socket/Client/types.js +10 -0
- package/lib/Socket/Client/websocket.d.ts +12 -0
- package/lib/Socket/Client/websocket.js +53 -0
- package/lib/Socket/business.d.ts +395 -0
- package/lib/Socket/business.js +379 -0
- package/lib/Socket/chats.d.ts +136 -0
- package/lib/Socket/chats.js +1327 -0
- package/lib/Socket/communities.d.ts +562 -0
- package/lib/Socket/communities.js +439 -0
- package/lib/Socket/dugong.d.ts +117 -0
- package/lib/Socket/dugong.js +798 -0
- package/lib/Socket/groups.d.ts +285 -0
- package/lib/Socket/groups.js +354 -0
- package/lib/Socket/index.d.ts +585 -0
- package/lib/Socket/index.js +52 -0
- package/lib/Socket/messages-recv.d.ts +333 -0
- package/lib/Socket/messages-recv.js +1781 -0
- package/lib/Socket/messages-send.d.ts +353 -0
- package/lib/Socket/messages-send.js +1524 -0
- package/lib/Socket/mex.d.ts +1 -0
- package/lib/Socket/mex.js +41 -0
- package/lib/Socket/newsletter.d.ts +286 -0
- package/lib/Socket/newsletter.js +364 -0
- package/lib/Socket/socket.d.ts +60 -0
- package/lib/Socket/socket.js +1012 -0
- package/lib/Socket/username.d.ts +82 -0
- package/lib/Socket/username.js +159 -0
- package/lib/Store/index.d.ts +3 -0
- package/lib/Store/index.js +3 -0
- package/lib/Store/make-in-memory-store.d.ts +62 -0
- package/lib/Store/make-in-memory-store.js +428 -0
- package/lib/Store/make-ordered-dictionary.d.ts +12 -0
- package/lib/Store/make-ordered-dictionary.js +78 -0
- package/lib/Store/object-repository.d.ts +10 -0
- package/lib/Store/object-repository.js +23 -0
- package/lib/Types/Auth.d.ts +117 -0
- package/lib/Types/Auth.js +1 -0
- package/lib/Types/Bussines.d.ts +25 -0
- package/lib/Types/Call.d.ts +15 -0
- package/lib/Types/Call.js +1 -0
- package/lib/Types/Chat.d.ts +124 -0
- package/lib/Types/Chat.js +7 -0
- package/lib/Types/Contact.d.ts +26 -0
- package/lib/Types/Contact.js +1 -0
- package/lib/Types/Events.d.ts +256 -0
- package/lib/Types/Events.js +1 -0
- package/lib/Types/GroupMetadata.d.ts +71 -0
- package/lib/Types/GroupMetadata.js +1 -0
- package/lib/Types/Label.d.ts +5 -0
- package/lib/Types/Label.js +24 -0
- package/lib/Types/LabelAssociation.d.ts +6 -0
- package/lib/Types/LabelAssociation.js +6 -0
- package/lib/Types/Message.d.ts +62 -0
- package/lib/Types/Message.js +17 -0
- package/lib/Types/Mex.d.ts +2 -0
- package/lib/Types/Mex.js +38 -0
- package/lib/Types/Product.d.ts +79 -0
- package/lib/Types/Product.js +1 -0
- package/lib/Types/RichType.d.ts +2 -0
- package/lib/Types/RichType.js +22 -0
- package/lib/Types/Signal.d.ts +87 -0
- package/lib/Types/Signal.js +1 -0
- package/lib/Types/Socket.d.ts +138 -0
- package/lib/Types/Socket.js +1 -0
- package/lib/Types/State.d.ts +8 -0
- package/lib/Types/State.js +55 -0
- package/lib/Types/USync.d.ts +26 -0
- package/lib/Types/index.d.ts +68 -0
- package/lib/Types/index.js +27 -0
- package/lib/Utils/MessageBuilder.d.ts +2 -0
- package/lib/Utils/MessageBuilder.js +2 -0
- package/lib/Utils/PersistentStore.d.ts +60 -0
- package/lib/Utils/PersistentStore.js +592 -0
- package/lib/Utils/anti-delete.d.ts +74 -0
- package/lib/Utils/anti-delete.js +221 -0
- package/lib/Utils/auth-secure.d.ts +86 -0
- package/lib/Utils/auth-secure.js +764 -0
- package/lib/Utils/auth-utils.d.ts +57 -0
- package/lib/Utils/auth-utils.js +306 -0
- package/lib/Utils/auto-reply.d.ts +47 -0
- package/lib/Utils/auto-reply.js +157 -0
- package/lib/Utils/baileys-event-stream.d.ts +8 -0
- package/lib/Utils/baileys-event-stream.js +62 -0
- package/lib/Utils/browser-utils.d.ts +8 -0
- package/lib/Utils/browser-utils.js +27 -0
- package/lib/Utils/business.d.ts +49 -0
- package/lib/Utils/business.js +239 -0
- package/lib/Utils/button-helper-utils.d.ts +53 -0
- package/lib/Utils/button-helper-utils.js +312 -0
- package/lib/Utils/button-sender.d.ts +54 -0
- package/lib/Utils/button-sender.js +822 -0
- package/lib/Utils/chat-control.d.ts +159 -0
- package/lib/Utils/chat-control.js +230 -0
- package/lib/Utils/chat-history-helpers.d.ts +21 -0
- package/lib/Utils/chat-history-helpers.js +70 -0
- package/lib/Utils/chat-utils.d.ts +407 -0
- package/lib/Utils/chat-utils.js +885 -0
- package/lib/Utils/companion-reg-client-utils.d.ts +4 -0
- package/lib/Utils/companion-reg-client-utils.js +39 -0
- package/lib/Utils/crypto.d.ts +41 -0
- package/lib/Utils/crypto.js +147 -0
- package/lib/Utils/decode-wa-message.d.ts +83 -0
- package/lib/Utils/decode-wa-message.js +316 -0
- package/lib/Utils/event-buffer.d.ts +12 -0
- package/lib/Utils/event-buffer.js +635 -0
- package/lib/Utils/generics.d.ts +69 -0
- package/lib/Utils/generics.js +438 -0
- package/lib/Utils/history-share.d.ts +11 -0
- package/lib/Utils/history-share.js +70 -0
- package/lib/Utils/history.d.ts +90 -0
- package/lib/Utils/history.js +146 -0
- package/lib/Utils/humanizer.d.ts +12 -0
- package/lib/Utils/humanizer.js +73 -0
- package/lib/Utils/identity-change-handler.d.ts +13 -0
- package/lib/Utils/identity-change-handler.js +49 -0
- package/lib/Utils/index.d.ts +57 -0
- package/lib/Utils/index.js +56 -0
- package/lib/Utils/jid-tools.d.ts +6 -0
- package/lib/Utils/jid-tools.js +77 -0
- package/lib/Utils/link-preview.d.ts +12 -0
- package/lib/Utils/link-preview.js +84 -0
- package/lib/Utils/logger.d.ts +4 -0
- package/lib/Utils/logger.js +2 -0
- package/lib/Utils/lt-hash.d.ts +12 -0
- package/lib/Utils/lt-hash.js +26 -0
- package/lib/Utils/make-mutex.d.ts +6 -0
- package/lib/Utils/make-mutex.js +32 -0
- package/lib/Utils/media-messages.d.ts +18 -0
- package/lib/Utils/media-messages.js +70 -0
- package/lib/Utils/media-set.d.ts +13 -0
- package/lib/Utils/media-set.js +171 -0
- package/lib/Utils/message-kind.d.ts +32 -0
- package/lib/Utils/message-kind.js +136 -0
- package/lib/Utils/message-retry-manager.d.ts +79 -0
- package/lib/Utils/message-retry-manager.js +264 -0
- package/lib/Utils/message-search.d.ts +44 -0
- package/lib/Utils/message-search.js +188 -0
- package/lib/Utils/messages-media.d.ts +135 -0
- package/lib/Utils/messages-media.js +868 -0
- package/lib/Utils/messages.d.ts +44 -0
- package/lib/Utils/messages.js +2326 -0
- package/lib/Utils/meta-ai.d.ts +13 -0
- package/lib/Utils/meta-ai.js +74 -0
- package/lib/Utils/mini-app.d.ts +35 -0
- package/lib/Utils/mini-app.js +213 -0
- package/lib/Utils/noise-handler.d.ts +20 -0
- package/lib/Utils/noise-handler.js +200 -0
- package/lib/Utils/offline-node-processor.d.ts +9 -0
- package/lib/Utils/offline-node-processor.js +39 -0
- package/lib/Utils/past-participants.d.ts +14 -0
- package/lib/Utils/past-participants.js +40 -0
- package/lib/Utils/pre-key-manager.d.ts +25 -0
- package/lib/Utils/pre-key-manager.js +105 -0
- package/lib/Utils/process-message.d.ts +82 -0
- package/lib/Utils/process-message.js +808 -0
- package/lib/Utils/qr-render.d.ts +59 -0
- package/lib/Utils/qr-render.js +179 -0
- package/lib/Utils/qrcodegen.d.ts +79 -0
- package/lib/Utils/qrcodegen.js +848 -0
- package/lib/Utils/reporting-utils.d.ts +12 -0
- package/lib/Utils/reporting-utils.js +257 -0
- package/lib/Utils/rich-message-utils.d.ts +48 -0
- package/lib/Utils/rich-message-utils.js +444 -0
- package/lib/Utils/router.d.ts +37 -0
- package/lib/Utils/router.js +165 -0
- package/lib/Utils/scheduled-posts.d.ts +30 -0
- package/lib/Utils/scheduled-posts.js +110 -0
- package/lib/Utils/scheduling.d.ts +42 -0
- package/lib/Utils/scheduling.js +139 -0
- package/lib/Utils/signal.d.ts +82 -0
- package/lib/Utils/signal.js +200 -0
- package/lib/Utils/stanza-ack.d.ts +16 -0
- package/lib/Utils/stanza-ack.js +37 -0
- package/lib/Utils/status.d.ts +50 -0
- package/lib/Utils/status.js +107 -0
- package/lib/Utils/stickerpack.d.ts +51 -0
- package/lib/Utils/stickerpack.js +274 -0
- package/lib/Utils/sync-action-utils.d.ts +2 -0
- package/lib/Utils/sync-action-utils.js +48 -0
- package/lib/Utils/tag.d.ts +12 -0
- package/lib/Utils/tag.js +44 -0
- package/lib/Utils/tc-token-utils.d.ts +29 -0
- package/lib/Utils/tc-token-utils.js +162 -0
- package/lib/Utils/templates.d.ts +76 -0
- package/lib/Utils/templates.js +150 -0
- package/lib/Utils/transcribe.d.ts +12 -0
- package/lib/Utils/transcribe.js +107 -0
- package/lib/Utils/use-cache-manager-auth-state.d.ts +13 -0
- package/lib/Utils/use-cache-manager-auth-state.js +81 -0
- package/lib/Utils/use-multi-file-auth-state.d.ts +10 -0
- package/lib/Utils/use-multi-file-auth-state.js +166 -0
- package/lib/Utils/use-single-file-auth-state.d.ts +10 -0
- package/lib/Utils/use-single-file-auth-state.js +113 -0
- package/lib/Utils/use-sqlite-auth-state.d.ts +11 -0
- package/lib/Utils/use-sqlite-auth-state.js +169 -0
- package/lib/Utils/validate-connection.d.ts +42 -0
- package/lib/Utils/validate-connection.js +198 -0
- package/lib/Utils/vcard.d.ts +58 -0
- package/lib/Utils/vcard.js +104 -0
- package/lib/Utils/voice-note.d.ts +15 -0
- package/lib/Utils/voice-note.js +63 -0
- package/lib/VoIP/audio-feeder.d.ts +18 -0
- package/lib/VoIP/audio-feeder.js +160 -0
- package/lib/VoIP/call-recorder.d.ts +13 -0
- package/lib/VoIP/call-recorder.js +73 -0
- package/lib/VoIP/index.d.ts +86 -0
- package/lib/VoIP/index.js +611 -0
- package/lib/VoIP/relay-transport.d.ts +43 -0
- package/lib/VoIP/relay-transport.js +563 -0
- package/lib/VoIP/signaling.d.ts +26 -0
- package/lib/VoIP/signaling.js +662 -0
- package/lib/VoIP/types.d.ts +69 -0
- package/lib/VoIP/types.js +17 -0
- package/lib/VoIP/wasm-engine.d.ts +120 -0
- package/lib/VoIP/wasm-engine.js +1358 -0
- package/lib/VoIP/worker-bootstrap.d.ts +4 -0
- package/lib/VoIP/worker-bootstrap.js +1046 -0
- package/lib/WABinary/constants.d.ts +61 -0
- package/lib/WABinary/constants.js +1466 -0
- package/lib/WABinary/decode.d.ts +9 -0
- package/lib/WABinary/decode.js +261 -0
- package/lib/WABinary/encode.d.ts +2 -0
- package/lib/WABinary/encode.js +219 -0
- package/lib/WABinary/generic-utils.d.ts +74 -0
- package/lib/WABinary/generic-utils.js +276 -0
- package/lib/WABinary/index.d.ts +5 -0
- package/lib/WABinary/index.js +5 -0
- package/lib/WABinary/jid-utils.d.ts +28 -0
- package/lib/WABinary/jid-utils.js +95 -0
- package/lib/WABinary/types.d.ts +19 -0
- package/lib/WABinary/types.js +1 -0
- package/lib/WAM/BinaryInfo.d.ts +7 -0
- package/lib/WAM/BinaryInfo.js +9 -0
- package/lib/WAM/constants.d.ts +34926 -0
- package/lib/WAM/constants.js +22852 -0
- package/lib/WAM/encode.d.ts +1 -0
- package/lib/WAM/encode.js +149 -0
- package/lib/WAM/index.d.ts +3 -0
- package/lib/WAM/index.js +3 -0
- package/lib/WAUSync/Protocols/USyncContactProtocol.d.ts +36 -0
- package/lib/WAUSync/Protocols/USyncContactProtocol.js +51 -0
- package/lib/WAUSync/Protocols/USyncDeviceProtocol.d.ts +29 -0
- package/lib/WAUSync/Protocols/USyncDeviceProtocol.js +62 -0
- package/lib/WAUSync/Protocols/USyncDisappearingModeProtocol.d.ts +12 -0
- package/lib/WAUSync/Protocols/USyncDisappearingModeProtocol.js +26 -0
- package/lib/WAUSync/Protocols/USyncStatusProtocol.d.ts +12 -0
- package/lib/WAUSync/Protocols/USyncStatusProtocol.js +37 -0
- package/lib/WAUSync/Protocols/USyncUsernameProtocol.d.ts +9 -0
- package/lib/WAUSync/Protocols/USyncUsernameProtocol.js +24 -0
- package/lib/WAUSync/Protocols/UsyncBotProfileProtocol.d.ts +38 -0
- package/lib/WAUSync/Protocols/UsyncBotProfileProtocol.js +50 -0
- package/lib/WAUSync/Protocols/UsyncLIDProtocol.d.ts +14 -0
- package/lib/WAUSync/Protocols/UsyncLIDProtocol.js +28 -0
- package/lib/WAUSync/Protocols/index.d.ts +7 -0
- package/lib/WAUSync/Protocols/index.js +7 -0
- package/lib/WAUSync/USyncQuery.d.ts +20 -0
- package/lib/WAUSync/USyncQuery.js +121 -0
- package/lib/WAUSync/USyncUser.d.ts +16 -0
- package/lib/WAUSync/USyncUser.js +30 -0
- package/lib/WAUSync/index.d.ts +3 -0
- package/lib/WAUSync/index.js +3 -0
- package/lib/assets/wasm/loader.d.ts +5 -0
- package/lib/assets/wasm/loader.js +5 -0
- package/lib/assets/wasm/whatsapp.wasm +0 -0
- package/lib/assets/wasm/worker-modules.d.ts +5 -0
- package/lib/assets/wasm/worker-modules.js +273 -0
- package/lib/index.d.ts +18 -0
- package/lib/index.js +23 -0
- package/package.json +180 -0
- package/postinstall-banner.js +82 -0
package/README.md
ADDED
|
@@ -0,0 +1,1254 @@
|
|
|
1
|
+
<div align="center" id="top">
|
|
2
|
+
|
|
3
|
+
<img src="https://capsule-render.vercel.app/api?type=waving&color=0:2ecc71,100:1d6a23&height=180§ion=header&text=%40japofc%2Fbaileys&fontSize=48&fontColor=ffffff&animation=fadeIn&fontAlignY=35&desc=WhatsApp%20Web%20API%20%E2%80%94%20typed%2C%20extended%2C%20battle-tested&descSize=16&descAlignY=55" width="100%" alt="@japofc/baileys banner"/>
|
|
4
|
+
|
|
5
|
+
<p>
|
|
6
|
+
<img src="https://readme-typing-svg.demolab.com?font=Fira+Code&size=18&pause=1200&color=2ECC71¢er=true&vCenter=true&width=650&lines=Extended+interactive+messages+%26+native+flow;Status+tools+%2B+quality-of-life+fixes;WhatsApp+automation+toolkit" alt="Typing SVG" />
|
|
7
|
+
</p>
|
|
8
|
+
|
|
9
|
+
<p>
|
|
10
|
+
<a href="https://www.npmjs.com/package/@japofc/baileys" target="_blank"><img src="https://img.shields.io/npm/v/@japofc/baileys?color=2ecc71&label=npm&style=for-the-badge" alt="npm version"/></a>
|
|
11
|
+
<a href="https://www.npmjs.com/package/@japofc/baileys" target="_blank"><img src="https://img.shields.io/npm/dt/@japofc/baileys?color=3498db&style=for-the-badge" alt="npm downloads"/></a>
|
|
12
|
+
<a href="https://github.com/JAPofc/baileys/stargazers" target="_blank"><img src="https://img.shields.io/github/stars/JAPofc/baileys?color=f1c40f&style=for-the-badge" alt="GitHub stars"/></a>
|
|
13
|
+
<a href="https://github.com/JAPofc/baileys/issues" target="_blank"><img src="https://img.shields.io/github/issues/JAPofc/baileys?color=e74c3c&style=for-the-badge" alt="GitHub issues"/></a>
|
|
14
|
+
</p>
|
|
15
|
+
<p>
|
|
16
|
+
<a href="https://github.com/JAPofc/baileys/actions/workflows/ci.yml" target="_blank"><img src="https://img.shields.io/github/actions/workflow/status/JAPofc/baileys/ci.yml?branch=main&style=flat-square&label=CI&color=2ecc71" alt="CI status"/></a>
|
|
17
|
+
<img src="https://img.shields.io/badge/tests-174%20passing-2ecc71?style=flat-square" alt="Tests"/>
|
|
18
|
+
<img src="https://img.shields.io/badge/tsc%20--strict-clean-3178c6?style=flat-square&logo=typescript&logoColor=white" alt="tsc strict clean"/>
|
|
19
|
+
<img src="https://img.shields.io/github/last-commit/JAPofc/baileys?color=9b59b6&style=flat-square" alt="Last commit"/>
|
|
20
|
+
<img src="https://img.shields.io/github/languages/code-size/JAPofc/baileys?color=e67e22&style=flat-square" alt="Code size"/>
|
|
21
|
+
<img src="https://img.shields.io/badge/node-%3E%3D20-brightgreen?style=flat-square" alt="Node >=20"/>
|
|
22
|
+
<img src="https://img.shields.io/badge/module-ESM-blue?style=flat-square" alt="ESM"/>
|
|
23
|
+
<img src="https://img.shields.io/badge/dependencies-zero%20QR%2FPNG%20deps-success?style=flat-square" alt="Zero extra deps"/>
|
|
24
|
+
<img src="https://img.shields.io/badge/license-see%20NOTICE-lightgrey?style=flat-square" alt="License"/>
|
|
25
|
+
</p>
|
|
26
|
+
|
|
27
|
+
<p>
|
|
28
|
+
<img src="https://komarev.com/ghpvc/?username=JAPofc&repo=baileys&color=2ecc71&style=for-the-badge&label=Repo+Views" alt="Visitor count"/>
|
|
29
|
+
</p>
|
|
30
|
+
|
|
31
|
+
<p>
|
|
32
|
+
<a href="#-why-this-fork">About</a>  | 
|
|
33
|
+
<a href="#-comparison">Comparison</a>  | 
|
|
34
|
+
<a href="#-features">Features</a>  | 
|
|
35
|
+
<a href="#-installation">Installation</a>  | 
|
|
36
|
+
<a href="#-quick-start">Quick Start</a>  | 
|
|
37
|
+
<a href="#-usage-examples">Examples</a>  | 
|
|
38
|
+
<a href="#-faq--troubleshooting">FAQ</a>  | 
|
|
39
|
+
<a href="#-contributing">Contributing</a>  | 
|
|
40
|
+
<a href="#-credits">Credits</a>  | 
|
|
41
|
+
<a href="#-maintainer">Maintainer</a>
|
|
42
|
+
</p>
|
|
43
|
+
|
|
44
|
+
<details>
|
|
45
|
+
<summary>📖 Full table of contents</summary>
|
|
46
|
+
<br/>
|
|
47
|
+
|
|
48
|
+
- [🍃 Why this fork](#-why-this-fork)
|
|
49
|
+
- [🆚 Comparison](#-comparison)
|
|
50
|
+
- [🧰 Built With](#-built-with)
|
|
51
|
+
- [🔥 Features](#-features)
|
|
52
|
+
- [✨ Exclusive J.AP Enhancements](#-exclusive-jap-enhancements)
|
|
53
|
+
- [📦 Installation](#-installation)
|
|
54
|
+
- [🚀 Quick Start](#-quick-start)
|
|
55
|
+
- [🔐 Authentication](#-authentication)
|
|
56
|
+
- [🗄️ Store Backends](#-store-backends)
|
|
57
|
+
- [💡 Usage Examples](#-usage-examples)
|
|
58
|
+
- [📨 Message Helpers](#-message-helpers)
|
|
59
|
+
- [🧰 Channels, History & Transcripts](#-channels-history--transcripts)
|
|
60
|
+
- [🔐 Security Pack](#-security-pack)
|
|
61
|
+
- [🆕 WA 2026 catch-up](#-wa-2026-catch-up)
|
|
62
|
+
- [🆕 Everyday Utilities](#-everyday-utilities)
|
|
63
|
+
- [Buttons & Native Flow](#buttons--native-flow)
|
|
64
|
+
- [Poll](#poll)
|
|
65
|
+
- [Carousel](#carousel)
|
|
66
|
+
- [AIRich — rich response cards](#airich--rich-response-cards)
|
|
67
|
+
- [📁 Builders Folder Map](#-builders-folder-map-libbuilders)
|
|
68
|
+
- [📌 Pin / Keep in Chat](#-pin--keep-in-chat)
|
|
69
|
+
- [📞 Scheduled Call](#-scheduled-call)
|
|
70
|
+
- [📱 Mini App](#-mini-app)
|
|
71
|
+
- [📞 Voice & Video Calls](#-voice--video-calls)
|
|
72
|
+
- [🔎 User Sync Queries](#-user-sync-queries)
|
|
73
|
+
- [👤 Username Management](#-username-management)
|
|
74
|
+
- [🤖 Bot Framework](#-bot-framework)
|
|
75
|
+
- [🧩 Utility Modules](#-utility-modules)
|
|
76
|
+
- [🛎️ System Notification Filter](#system-notification-filter)
|
|
77
|
+
- [🛠 Recommended Environment](#-recommended-environment)
|
|
78
|
+
- [📘 TypeScript Support](#-typescript-support)
|
|
79
|
+
- [❓ FAQ & Troubleshooting](#-faq--troubleshooting)
|
|
80
|
+
- [🤝 Contributing](#-contributing)
|
|
81
|
+
- [🙏 Credits](#-credits)
|
|
82
|
+
- [👑 Maintainer](#-maintainer)
|
|
83
|
+
- [⚠️ Disclaimer](#-disclaimer)
|
|
84
|
+
- [📝 Patch Notes](#-v210-patch-notes)
|
|
85
|
+
|
|
86
|
+
</details>
|
|
87
|
+
|
|
88
|
+
</div>
|
|
89
|
+
|
|
90
|
+
---
|
|
91
|
+
|
|
92
|
+
## 🍃 Why this fork?
|
|
93
|
+
|
|
94
|
+
This fork focuses on:
|
|
95
|
+
|
|
96
|
+
| | |
|
|
97
|
+
|---|---|
|
|
98
|
+
| 🚀 | Better developer experience |
|
|
99
|
+
| 🎯 | Extended native flow support |
|
|
100
|
+
| 📢 | Advanced status & broadcast features |
|
|
101
|
+
| 🧩 | More interactive message types |
|
|
102
|
+
| ⚡ | Cleaner implementation for bot developers |
|
|
103
|
+
| 🔧 | Extra utilities not available in standard Baileys forks |
|
|
104
|
+
| 🗄️ | Multiple auth & store backends out of the box (file, SQLite, MongoDB, MySQL, PostgreSQL, Redis) |
|
|
105
|
+
| 📞 | Experimental voice-call (VoIP) support |
|
|
106
|
+
|
|
107
|
+
---
|
|
108
|
+
|
|
109
|
+
## 🆚 Comparison
|
|
110
|
+
|
|
111
|
+
How `@japofc/baileys` stacks up against other Baileys libraries:
|
|
112
|
+
|
|
113
|
+
| Capability | `@japofc/baileys` | Other forks (typical) |
|
|
114
|
+
|---|:---:|:---:|
|
|
115
|
+
| Native Flow buttons (V1/V2/V3) | ✅ | ⚠️ partial |
|
|
116
|
+
| Carousel messages | ✅ | ❌ |
|
|
117
|
+
| Rich response cards (AIRich) | ✅ | ❌ |
|
|
118
|
+
| Commerce flow (catalog/order/payment) | ✅ | ⚠️ partial |
|
|
119
|
+
| Voice calling (VoIP) | ✅ experimental | ❌ |
|
|
120
|
+
| Multi-backend store (SQL/Mongo/Redis) | ✅ | ⚠️ partial |
|
|
121
|
+
| Full `.d.ts` TypeScript definitions | ✅ | ⚠️ partial |
|
|
122
|
+
| User sync queries (WAUSync) | ✅ | ✅ |
|
|
123
|
+
| Username management (check/set/pin/recommend) | ✅ | ❌ |
|
|
124
|
+
| Bot framework (middleware, session, stats) | ✅ | ❌ |
|
|
125
|
+
| Built-in QR render (terminal/SVG/PNG, zero deps) | ✅ | ❌ needs `qrcode-terminal` |
|
|
126
|
+
| Auto WA Web version resolution | ✅ | ❌ hardcoded |
|
|
127
|
+
|
|
128
|
+
> Tabel ini menggambarkan fitur di level package, bukan benchmark performa. PR untuk memperbarui/mengoreksi tabel ini dipersilakan lewat [Contributing](#-contributing).
|
|
129
|
+
|
|
130
|
+
---
|
|
131
|
+
|
|
132
|
+
## 🧰 Built With
|
|
133
|
+
|
|
134
|
+
<p>
|
|
135
|
+
<img src="https://img.shields.io/badge/node.js-%2343853D.svg?style=for-the-badge&logo=node.js&logoColor=white" alt="Node.js"/>
|
|
136
|
+
<img src="https://img.shields.io/badge/javascript-%23323330.svg?style=for-the-badge&logo=javascript&logoColor=%23F7DF1E" alt="JavaScript"/>
|
|
137
|
+
<img src="https://img.shields.io/badge/esm-%23F7DF1E.svg?style=for-the-badge&logo=javascript&logoColor=black" alt="ESM"/>
|
|
138
|
+
<img src="https://img.shields.io/badge/websocket-%23000000.svg?style=for-the-badge&logo=socket.io&logoColor=white" alt="WebSocket"/>
|
|
139
|
+
<img src="https://img.shields.io/badge/signal%20protocol-%233A76F0.svg?style=for-the-badge&logo=signal&logoColor=white" alt="Signal Protocol"/>
|
|
140
|
+
<img src="https://img.shields.io/badge/protobuf-%23345?style=for-the-badge&logo=google&logoColor=white" alt="Protobuf"/>
|
|
141
|
+
<img src="https://img.shields.io/badge/npm-%23CB3837.svg?style=for-the-badge&logo=npm&logoColor=white" alt="npm"/>
|
|
142
|
+
</p>
|
|
143
|
+
|
|
144
|
+
<p>
|
|
145
|
+
<a href="https://skillicons.dev">
|
|
146
|
+
<img src="https://skillicons.dev/icons?i=nodejs,js,ts,npm,docker,redis,mongodb,mysql,postgresql,sqlite" alt="Tech stack icons"/>
|
|
147
|
+
</a>
|
|
148
|
+
</p>
|
|
149
|
+
|
|
150
|
+
---
|
|
151
|
+
|
|
152
|
+
## 🔥 Features
|
|
153
|
+
|
|
154
|
+
<table>
|
|
155
|
+
<tr>
|
|
156
|
+
<th align="center">💬 Interactive Messages</th>
|
|
157
|
+
<th align="center">🛒 Commerce & Business</th>
|
|
158
|
+
<th align="center">🧩 Utility Features</th>
|
|
159
|
+
</tr>
|
|
160
|
+
<tr>
|
|
161
|
+
<td valign="top">
|
|
162
|
+
|
|
163
|
+
- Native Flow
|
|
164
|
+
- Buttons (V1 / V2 / V3)
|
|
165
|
+
- Lists
|
|
166
|
+
- Carousel Messages
|
|
167
|
+
- Poll & Quiz Messages
|
|
168
|
+
- Rich Response Messages (AIRich)
|
|
169
|
+
- CTA / Reply / URL Buttons
|
|
170
|
+
- Call Buttons
|
|
171
|
+
- OTP Buttons
|
|
172
|
+
- Authentication Buttons
|
|
173
|
+
|
|
174
|
+
</td>
|
|
175
|
+
<td valign="top">
|
|
176
|
+
|
|
177
|
+
- Catalog Message
|
|
178
|
+
- Order Details
|
|
179
|
+
- Order Status
|
|
180
|
+
- Review & Pay
|
|
181
|
+
- Payment Status
|
|
182
|
+
- Payment Method
|
|
183
|
+
- Track Order
|
|
184
|
+
- Reorder
|
|
185
|
+
- Cancel Order
|
|
186
|
+
|
|
187
|
+
</td>
|
|
188
|
+
<td valign="top">
|
|
189
|
+
|
|
190
|
+
- Group Status Support
|
|
191
|
+
- Mention All
|
|
192
|
+
- Lottie Sticker Support
|
|
193
|
+
- Newsletter Support
|
|
194
|
+
- ExternalAdReply Helper
|
|
195
|
+
- View Once Support
|
|
196
|
+
- Rich Formatting
|
|
197
|
+
- Code Highlighting
|
|
198
|
+
|
|
199
|
+
</td>
|
|
200
|
+
</tr>
|
|
201
|
+
</table>
|
|
202
|
+
|
|
203
|
+
<table>
|
|
204
|
+
<tr>
|
|
205
|
+
<th align="center">🔐 Auth & Storage</th>
|
|
206
|
+
<th align="center">📞 Realtime</th>
|
|
207
|
+
<th align="center">🛠 Developer Tooling</th>
|
|
208
|
+
</tr>
|
|
209
|
+
<tr>
|
|
210
|
+
<td valign="top">
|
|
211
|
+
|
|
212
|
+
- Multi-file auth state
|
|
213
|
+
- Single-file auth state
|
|
214
|
+
- SQLite auth state
|
|
215
|
+
- Cache-manager auth state
|
|
216
|
+
- In-memory store
|
|
217
|
+
- SQLite / MongoDB / MySQL /
|
|
218
|
+
PostgreSQL / Redis store adapters
|
|
219
|
+
|
|
220
|
+
</td>
|
|
221
|
+
<td valign="top">
|
|
222
|
+
|
|
223
|
+
- Voice calling (VoIP, WASM engine)
|
|
224
|
+
- User sync queries (WAUSync)
|
|
225
|
+
- Presence / status / device lookup
|
|
226
|
+
- Event buffer for high-volume bots
|
|
227
|
+
|
|
228
|
+
</td>
|
|
229
|
+
<td valign="top">
|
|
230
|
+
|
|
231
|
+
- Full TypeScript definitions (`.d.ts`)
|
|
232
|
+
- Anti-delete detection
|
|
233
|
+
- Message search helpers
|
|
234
|
+
- Auto-reply engine
|
|
235
|
+
- Scheduling helpers
|
|
236
|
+
- Message retry manager
|
|
237
|
+
|
|
238
|
+
</td>
|
|
239
|
+
</tr>
|
|
240
|
+
</table>
|
|
241
|
+
|
|
242
|
+
---
|
|
243
|
+
|
|
244
|
+
## ✨ Exclusive J.AP Enhancements
|
|
245
|
+
|
|
246
|
+
### Audio Group Status Fix
|
|
247
|
+
Audio status uses a more compatible implementation to avoid unsupported-version errors on older WhatsApp clients.
|
|
248
|
+
|
|
249
|
+
### AIRich — the rich-response message builder
|
|
250
|
+
A chainable builder (`AIRich`, also exported as `AIJap` / `LeafRich` / `JapAI` / `JapRich`) with 40+ `add*()`/`set*()` methods covering headings, formatted text (hyperlinks/citations/LaTeX), code blocks, tables, image/video/product/post cards, task & progress cards, tip banners, and quick-reply suggestions — the kind of rich card layout you'd normally only see from an official AI/assistant-style bot. See [Usage Examples](#airich--rich-response-cards) below.
|
|
251
|
+
|
|
252
|
+
### Native Flow Expansion
|
|
253
|
+
|
|
254
|
+
<table>
|
|
255
|
+
<tr>
|
|
256
|
+
<td valign="top" width="33%">
|
|
257
|
+
|
|
258
|
+
**Buttons & Actions**
|
|
259
|
+
- cta_reminder
|
|
260
|
+
- cta_cancel_reminder
|
|
261
|
+
- otp_button
|
|
262
|
+
- authentication_button
|
|
263
|
+
- call_button
|
|
264
|
+
- url_button
|
|
265
|
+
- reply_button
|
|
266
|
+
- voice_call
|
|
267
|
+
- video_call_button
|
|
268
|
+
|
|
269
|
+
</td>
|
|
270
|
+
<td valign="top" width="33%">
|
|
271
|
+
|
|
272
|
+
**Commerce Flow**
|
|
273
|
+
- catalog_message
|
|
274
|
+
- mpm
|
|
275
|
+
- card_message
|
|
276
|
+
- order_details
|
|
277
|
+
- order_status
|
|
278
|
+
- review_and_pay
|
|
279
|
+
- payment_status
|
|
280
|
+
- payment_method
|
|
281
|
+
|
|
282
|
+
</td>
|
|
283
|
+
<td valign="top" width="33%">
|
|
284
|
+
|
|
285
|
+
**Navigation & Misc**
|
|
286
|
+
- address_message
|
|
287
|
+
- send_location
|
|
288
|
+
- track_order
|
|
289
|
+
- reorder
|
|
290
|
+
- cancel_order
|
|
291
|
+
- clear_chat
|
|
292
|
+
- navigateToScreen
|
|
293
|
+
- flow_action
|
|
294
|
+
|
|
295
|
+
</td>
|
|
296
|
+
</tr>
|
|
297
|
+
</table>
|
|
298
|
+
|
|
299
|
+
### System Notification Filter
|
|
300
|
+
|
|
301
|
+
Messages include:
|
|
302
|
+
|
|
303
|
+
```js
|
|
304
|
+
message.isSystemNotification
|
|
305
|
+
```
|
|
306
|
+
|
|
307
|
+
Useful for filtering:
|
|
308
|
+
|
|
309
|
+
- E2E notices
|
|
310
|
+
- Meta service notices
|
|
311
|
+
- Other system-generated messages
|
|
312
|
+
|
|
313
|
+
---
|
|
314
|
+
|
|
315
|
+
## 📦 Installation
|
|
316
|
+
|
|
317
|
+
```bash
|
|
318
|
+
npm install @japofc/baileys
|
|
319
|
+
```
|
|
320
|
+
|
|
321
|
+
Directly from GitHub:
|
|
322
|
+
|
|
323
|
+
```bash
|
|
324
|
+
npm install github:JAPofc/baileys
|
|
325
|
+
```
|
|
326
|
+
|
|
327
|
+
> Requires **Node.js 20+** — install will refuse to run below that (checked by `engine-requirements.js` on `preinstall`).
|
|
328
|
+
|
|
329
|
+
### Optional peer dependencies
|
|
330
|
+
|
|
331
|
+
Everything below is **optional** — the socket works without any of them. Install only what the features you use need; missing ones fail with a clear install hint instead of a silent crash.
|
|
332
|
+
|
|
333
|
+
| Package | Unlocks |
|
|
334
|
+
|---|---|
|
|
335
|
+
| `sharp` | Fast image resizing/processing (used by the message builders' `Toolkit.resize`) |
|
|
336
|
+
| `@napi-rs/image` | Lighter native alternative to `sharp` for image ops |
|
|
337
|
+
| `jimp` | Pure-JS image fallback when neither of the above is installed |
|
|
338
|
+
| `fluent-ffmpeg` | Audio/video conversion for media messages |
|
|
339
|
+
| `audio-decode` | Audio waveform/duration extraction (voice notes, VoIP capture) |
|
|
340
|
+
| `link-preview-js` | Rich link previews for URLs in outgoing text messages |
|
|
341
|
+
| `better-sqlite3` | SQLite auth state, SQLite store adapter, **and** the [Bot Framework](#-bot-framework)'s `SQLiteStore`/`StatsManager` |
|
|
342
|
+
| `node-webpmux` | Packname/author EXIF metadata on stickers made via `MediaManager.convertToSticker()` — not needed for plain sticker conversion |
|
|
343
|
+
| `mongodb` | MongoDB store adapter |
|
|
344
|
+
| `mysql2` | MySQL store adapter |
|
|
345
|
+
| `pg` | PostgreSQL store adapter |
|
|
346
|
+
| `ioredis` | Redis store adapter |
|
|
347
|
+
| `@roamhq/wrtc` | Native WebRTC bindings for [voice calling](#-voice--video-calls) |
|
|
348
|
+
|
|
349
|
+
---
|
|
350
|
+
|
|
351
|
+
## 🚀 Quick Start
|
|
352
|
+
|
|
353
|
+
```js
|
|
354
|
+
import { makeWASocket, useMultiFileAuthState } from '@japofc/baileys'
|
|
355
|
+
|
|
356
|
+
const { state, saveCreds } = await useMultiFileAuthState('auth_info')
|
|
357
|
+
|
|
358
|
+
const sock = makeWASocket({
|
|
359
|
+
auth: state
|
|
360
|
+
})
|
|
361
|
+
|
|
362
|
+
// persist credentials whenever Baileys updates them
|
|
363
|
+
sock.ev.on('creds.update', saveCreds)
|
|
364
|
+
|
|
365
|
+
sock.ev.on('connection.update', (update) => {
|
|
366
|
+
const { connection, qr } = update
|
|
367
|
+
|
|
368
|
+
// Easiest: pass `printQRInTerminal: true` to makeWASocket and the QR is
|
|
369
|
+
// drawn automatically with the built-in zero-dependency renderer.
|
|
370
|
+
// Manual/custom rendering from the event also works:
|
|
371
|
+
// import { renderQRToTerminal, qrToSVG, qrToPNG } from '@japofc/baileys'
|
|
372
|
+
// if (qr) console.log(renderQRToTerminal(qr)) // terminal (▀▄█)
|
|
373
|
+
// if (qr) fs.writeFileSync('qr.svg', qrToSVG(qr)) // for a web UI
|
|
374
|
+
// if (qr) fs.writeFileSync('qr.png', qrToPNG(qr)) // raster (send anywhere)
|
|
375
|
+
if (qr) console.log('Got a pairing QR')
|
|
376
|
+
|
|
377
|
+
if (connection === 'open') console.log('🍃 Connected!')
|
|
378
|
+
})
|
|
379
|
+
|
|
380
|
+
sock.ev.on('messages.upsert', ({ messages }) => {
|
|
381
|
+
const msg = messages[0]
|
|
382
|
+
if (!msg.message || msg.key.fromMe) return
|
|
383
|
+
console.log('New message from', msg.key.remoteJid)
|
|
384
|
+
})
|
|
385
|
+
```
|
|
386
|
+
|
|
387
|
+
---
|
|
388
|
+
|
|
389
|
+
## 🔐 Authentication
|
|
390
|
+
|
|
391
|
+
Four auth-state backends ship out of the box. All return the same `{ state, saveCreds }` shape expected by `makeWASocket({ auth })`, so they're drop-in interchangeable.
|
|
392
|
+
|
|
393
|
+
| Function | Storage | Best for |
|
|
394
|
+
|---|---|---|
|
|
395
|
+
| `useMultiFileAuthState(folder)` | One JSON file per key, on disk | Default choice — simple, debuggable, works everywhere |
|
|
396
|
+
| `useSingleFileAuthState(fileName)` | One JSON file, on disk | Small bots where a single file is easier to manage/back up |
|
|
397
|
+
| `useSqliteAuthState(opts)` | SQLite (`better-sqlite3`) | Bots that already use SQLite, or want auth in one embedded DB file |
|
|
398
|
+
| `useCacheManagerAuthState(store, sessionKey)` | Any [`cacheable`](https://www.npmjs.com/package/@cacheable/node-cache)-compatible store | Multi-session hosting panels, Redis-backed setups |
|
|
399
|
+
|
|
400
|
+
```js
|
|
401
|
+
import { makeWASocket, useMultiFileAuthState } from '@japofc/baileys'
|
|
402
|
+
|
|
403
|
+
const { state, saveCreds } = await useMultiFileAuthState('auth_info')
|
|
404
|
+
const sock = makeWASocket({ auth: state })
|
|
405
|
+
sock.ev.on('creds.update', saveCreds)
|
|
406
|
+
```
|
|
407
|
+
|
|
408
|
+
```js
|
|
409
|
+
// SQLite variant
|
|
410
|
+
import { makeWASocket, useSqliteAuthState } from '@japofc/baileys'
|
|
411
|
+
|
|
412
|
+
const { state, saveCreds } = await useSqliteAuthState({ database: './auth.db' })
|
|
413
|
+
const sock = makeWASocket({ auth: state })
|
|
414
|
+
sock.ev.on('creds.update', saveCreds)
|
|
415
|
+
```
|
|
416
|
+
|
|
417
|
+
`useMultiFileAuthState` also exports `pruneStaleAuthFiles(folder, options)` to clean up old sender-key files on a schedule — useful for long-running bots that accumulate thousands of stale key files.
|
|
418
|
+
|
|
419
|
+
---
|
|
420
|
+
|
|
421
|
+
## 🗄️ Store Backends
|
|
422
|
+
|
|
423
|
+
`makeInMemoryStore()` from `lib/Store` gives you the classic in-memory chat/contact/message cache. For anything that needs to survive a restart, `makePersistentStore()` (from `PersistentStore.js`) wraps one of five backends behind the same interface:
|
|
424
|
+
|
|
425
|
+
| Backend | Function |
|
|
426
|
+
|---|---|
|
|
427
|
+
| SQLite | `createSqliteStoreAdapter(opts)` |
|
|
428
|
+
| MongoDB | `createMongoStoreAdapter(opts)` |
|
|
429
|
+
| MySQL | `createMysqlStoreAdapter(opts)` |
|
|
430
|
+
| PostgreSQL | `createPostgresStoreAdapter(opts)` |
|
|
431
|
+
| Redis | `createRedisStoreAdapter(opts)` |
|
|
432
|
+
|
|
433
|
+
```js
|
|
434
|
+
import { makeWASocket, makeInMemoryStore } from '@japofc/baileys'
|
|
435
|
+
|
|
436
|
+
const store = makeInMemoryStore({})
|
|
437
|
+
store.readFromFile('./baileys_store.json')
|
|
438
|
+
setInterval(() => store.writeToFile('./baileys_store.json'), 10_000)
|
|
439
|
+
|
|
440
|
+
const sock = makeWASocket({ /* ...auth etc */ })
|
|
441
|
+
store.bind(sock.ev)
|
|
442
|
+
```
|
|
443
|
+
|
|
444
|
+
---
|
|
445
|
+
|
|
446
|
+
## 💡 Usage Examples
|
|
447
|
+
|
|
448
|
+
### Buttons & Native Flow
|
|
449
|
+
|
|
450
|
+
```js
|
|
451
|
+
import { Button } from '@japofc/baileys'
|
|
452
|
+
|
|
453
|
+
await new Button(sock)
|
|
454
|
+
.setTitle('Promo Spesial')
|
|
455
|
+
.setBody('Diskon 20% cuma hari ini')
|
|
456
|
+
.setFooter('@japofc/baileys')
|
|
457
|
+
.addReply('Klaim Sekarang', 'claim_promo')
|
|
458
|
+
.addUrl('Lihat Katalog', 'https://example.com/catalog')
|
|
459
|
+
.addCall('Hubungi Kami', '628123456789')
|
|
460
|
+
.send(jid)
|
|
461
|
+
```
|
|
462
|
+
|
|
463
|
+
### Poll
|
|
464
|
+
|
|
465
|
+
```js
|
|
466
|
+
import { Poll } from '@japofc/baileys'
|
|
467
|
+
|
|
468
|
+
await new Poll(sock)
|
|
469
|
+
.setName('Mau makan apa hari ini?')
|
|
470
|
+
.addOptions(['Nasi Goreng', 'Mie Ayam', 'Bakso'])
|
|
471
|
+
.setSelectable(1)
|
|
472
|
+
.send(jid)
|
|
473
|
+
```
|
|
474
|
+
|
|
475
|
+
### Carousel
|
|
476
|
+
|
|
477
|
+
> Each card must be built with `Button(...).toCard()` first — a carousel card is really just a button card with an image/video header.
|
|
478
|
+
|
|
479
|
+
```js
|
|
480
|
+
import { Button, Carousel } from '@japofc/baileys'
|
|
481
|
+
|
|
482
|
+
const cardA = await new Button(sock)
|
|
483
|
+
.setImage('https://example.com/a.jpg')
|
|
484
|
+
.setTitle('Produk A')
|
|
485
|
+
.addUrl('Lihat', 'https://example.com/a')
|
|
486
|
+
.toCard()
|
|
487
|
+
|
|
488
|
+
const cardB = await new Button(sock)
|
|
489
|
+
.setImage('https://example.com/b.jpg')
|
|
490
|
+
.setTitle('Produk B')
|
|
491
|
+
.addUrl('Lihat', 'https://example.com/b')
|
|
492
|
+
.toCard()
|
|
493
|
+
|
|
494
|
+
await new Carousel(sock)
|
|
495
|
+
.setBody('Pilih salah satu produk di bawah ini')
|
|
496
|
+
.addCard([cardA, cardB])
|
|
497
|
+
.send(jid)
|
|
498
|
+
```
|
|
499
|
+
|
|
500
|
+
### AIRich — rich response cards
|
|
501
|
+
|
|
502
|
+
```js
|
|
503
|
+
import { AIRich } from '@japofc/baileys'
|
|
504
|
+
|
|
505
|
+
await new AIRich(sock)
|
|
506
|
+
.addHeading('Ringkasan Order')
|
|
507
|
+
.addText('Pesananmu sedang diproses.')
|
|
508
|
+
.addTable([
|
|
509
|
+
['Item', 'Qty'],
|
|
510
|
+
['Kopi Susu', '2']
|
|
511
|
+
])
|
|
512
|
+
.addTip('Pesanan biasanya siap dalam 15 menit')
|
|
513
|
+
.addSuggest('Lacak Order')
|
|
514
|
+
.send(jid)
|
|
515
|
+
```
|
|
516
|
+
|
|
517
|
+
`AIRich` supports `{ id, insertAt }` on every `add*()`/`set*()` call, so you can insert a block relative to one you added earlier instead of always appending to the end — handy for streaming/edit-in-place style responses combined with `sendEdit(jid, id)`.
|
|
518
|
+
|
|
519
|
+
Other builders worth knowing about: **`ButtonV2`** (simpler quick-reply-only buttons), **`ButtonV3`** (`loadFrom(msg)` to edit an existing template message in place), and **`Toolkit`** (static helpers: `Toolkit.resize()`, `Toolkit.fetchBuffer()`, `Toolkit.waitAllPromises()`, `Toolkit.extractIE()` for parsing `[label](url)` links/citations/LaTeX out of plain text).
|
|
520
|
+
|
|
521
|
+
### 📁 Builders Folder Map (`lib/Builders/`)
|
|
522
|
+
|
|
523
|
+
Every message builder lives in its own file under `lib/Builders/`, so you can trace exactly where a class comes from instead of digging through one giant `MessageBuilder.js`. `index.js` is just the barrel file that re-exports everything below (plus their aliases) for the top-level `import { ... } from '@japofc/baileys'` syntax.
|
|
524
|
+
|
|
525
|
+
| File | Exports | What it's for |
|
|
526
|
+
|---|---|---|
|
|
527
|
+
| `shared.js` | `Toolkit`, `BaseBuilder`, `RowBuilder` | The shared foundation every other builder is built on. `BaseBuilder` holds the common chainable `send()`/context-info plumbing, `RowBuilder` is the shared row/section helper, and `Toolkit` is the static-helper grab bag (`resize`, `fetchBuffer`, `waitAllPromises`, `extractIE`, media-duration/preview helpers). Nothing here is meant to be instantiated directly in bot code — it exists so `Button`, `Poll`, `Carousel`, etc. don't each reimplement the same plumbing. |
|
|
528
|
+
| `Button.js` | `Button`, `CardBuilder` | The main interactive/native-flow button builder — headers (image/video/document), CTA helpers (`addUrl`, `addCall`, `addReply`, and the wider native-flow set), and `.toCard()` to turn a button message into a `Carousel` card. |
|
|
529
|
+
| `ButtonV2.js` | `ButtonV2` | A lighter-weight variant limited to simple quick-reply buttons — reach for this when you don't need the full native-flow surface of `Button`. |
|
|
530
|
+
| `ButtonV3.js` | `ButtonV3` | Built around `loadFrom(msg)` — loads an existing `templateMessage` (e.g. one you fetched or that was quoted) so you can edit it in place instead of building one from scratch. |
|
|
531
|
+
| `Carousel.js` | `Carousel` | Chains `Button(...).toCard()` results into a swipeable card carousel. Capped at `Carousel.MAX_CARDS` (10) since WhatsApp silently truncates anything beyond that. |
|
|
532
|
+
| `Poll.js` | `Poll` | Poll/vote message builder — question, options, single/multi-select, hidden-voter mode, correct-answer marking, expiry. |
|
|
533
|
+
| `AIRich.js` | `AIRich` (+ aliases `ORich`, `AIJap`, `LeafRich`, `JapAI`, `JapRich`, `RichJap`) | The rich AI-assistant-style response builder described above — headings, formatted text, tables, media/product/post cards, task/progress cards, tip banners, quick-reply suggestions. |
|
|
534
|
+
| `A2UI.js` | `A2UI`, `sendA2UIWidget` | Lower-level A2UI/Bloks widget builder. Builds the flat `components` tree (Column/Row → `children`, Card/Button → `child`, Modal → `trigger`/`content`) that Bloks widgets expect and sends it through the same `getBizBinaryNode()` path as `Button`/`ButtonV2`, so the wire-level node always matches the button names actually sent. |
|
|
535
|
+
| `JapBaileys.js` | `JapBaileys` | A unified builder **hub** — one object that wraps all the builders above behind short method names (`.button()`, `.buttonV2()`, `.buttonV3()`, `.carousel()`, `.poll()`, `.airich()`, `.a2ui()`), plus PascalCase aliases (`.Button()`, `.Carousel()`, `.Poll()`, `.AIRich()`, `.A2UI()`) for developers who prefer that naming style. Nothing new is implemented here — it's purely a single entry point over the individual classes. |
|
|
536
|
+
| `index.js` | everything above, plus `MESSAGE_BUILDER_VERSION` | The barrel file — re-exports every builder and its aliases so `import { Button, Poll, AIRich, JapBaileys } from '@japofc/baileys'` works without reaching into individual files. `MESSAGE_BUILDER_VERSION` tracks the builder API surface's own version, independent of the package version. |
|
|
537
|
+
|
|
538
|
+
**Unified hub example** — useful if you'd rather carry one object around than import each builder individually:
|
|
539
|
+
|
|
540
|
+
```js
|
|
541
|
+
import { JapBaileys } from '@japofc/baileys'
|
|
542
|
+
|
|
543
|
+
const vx = new JapBaileys(sock)
|
|
544
|
+
|
|
545
|
+
await vx.button()
|
|
546
|
+
.setTitle('Promo Spesial')
|
|
547
|
+
.addReply('Klaim Sekarang', 'claim_promo')
|
|
548
|
+
.send(jid)
|
|
549
|
+
|
|
550
|
+
await vx.poll()
|
|
551
|
+
.setName('Mau makan apa hari ini?')
|
|
552
|
+
.addOptions(['Nasi Goreng', 'Mie Ayam'])
|
|
553
|
+
.send(jid)
|
|
554
|
+
```
|
|
555
|
+
|
|
556
|
+
---
|
|
557
|
+
|
|
558
|
+
### 📌 Pin / Keep in Chat
|
|
559
|
+
|
|
560
|
+
```js
|
|
561
|
+
// Pin a message for 7 days (default 24h), unpin, keep / unkeep in disappearing chats
|
|
562
|
+
await sock.sendPin(jid, msg.key, { durationSec: 7 * 86400 })
|
|
563
|
+
await sock.sendUnpin(jid, msg.key)
|
|
564
|
+
await sock.sendKeep(jid, msg.key)
|
|
565
|
+
await sock.sendUnkeep(jid, msg.key)
|
|
566
|
+
```
|
|
567
|
+
|
|
568
|
+
### 📅 Event
|
|
569
|
+
|
|
570
|
+
```js
|
|
571
|
+
await sock.sendEvent(jid, {
|
|
572
|
+
name: 'Rapat Mingguan',
|
|
573
|
+
description: 'Bahas progres bot',
|
|
574
|
+
startDate: new Date('2026-09-15T10:00:00+07:00'),
|
|
575
|
+
endDate: new Date('2026-09-15T11:00:00+07:00'),
|
|
576
|
+
location: { name: 'Kantor', address: 'Jakarta' },
|
|
577
|
+
extraGuestsAllowed: true
|
|
578
|
+
})
|
|
579
|
+
```
|
|
580
|
+
|
|
581
|
+
### 📞 Scheduled Call
|
|
582
|
+
|
|
583
|
+
Native scheduled-call message (the "Schedule call" card with a join reminder):
|
|
584
|
+
|
|
585
|
+
```js
|
|
586
|
+
// 'voice' (default) or 'video'
|
|
587
|
+
await sock.sendScheduledCall(jid, {
|
|
588
|
+
title: 'Daily standup',
|
|
589
|
+
scheduledAt: new Date('2026-09-15T09:00:00+07:00'),
|
|
590
|
+
callType: 'video'
|
|
591
|
+
})
|
|
592
|
+
|
|
593
|
+
// Cancel it later (needs the creation message's key)
|
|
594
|
+
await sock.cancelScheduledCall(jid, creationMsg.key)
|
|
595
|
+
```
|
|
596
|
+
|
|
597
|
+
### 📱 Mini App
|
|
598
|
+
|
|
599
|
+
Two modes — pass `url`, `flow`, or both (two buttons):
|
|
600
|
+
|
|
601
|
+
```js
|
|
602
|
+
import { sendMiniApp } from '@japofc/baileys'
|
|
603
|
+
|
|
604
|
+
await sendMiniApp(sock, jid, {
|
|
605
|
+
title: 'My Mini App',
|
|
606
|
+
body: 'Tap the button to open the app 👇',
|
|
607
|
+
// 1) webview mode: rich card + CTA opening your web app
|
|
608
|
+
// (in-app webview when supported, else the browser)
|
|
609
|
+
url: 'https://myapp.example.com',
|
|
610
|
+
params: { ref: 'wa-bot' }, // → appended as ?ref=wa-bot
|
|
611
|
+
buttonText: '🚀 Open App',
|
|
612
|
+
// 2) Flows mode: TRUE native in-chat mini app (forms/screens inside
|
|
613
|
+
// WhatsApp, no browser). Needs a published Flow ID from Flows Manager.
|
|
614
|
+
flow: { id: '123456789', cta: '📝 Isi Form', screen: 'WELCOME' },
|
|
615
|
+
thumbnail: 'https://myapp.example.com/icon.png' // url or Buffer
|
|
616
|
+
})
|
|
617
|
+
// or as a socket method: await sock.sendMiniApp(jid, { ... })
|
|
618
|
+
```
|
|
619
|
+
|
|
620
|
+
---
|
|
621
|
+
|
|
622
|
+
## 📨 Message Helpers
|
|
623
|
+
|
|
624
|
+
High-level one-liners for modern message types — validated, with friendly aliases:
|
|
625
|
+
|
|
626
|
+
```js
|
|
627
|
+
await sock.sendLocation(jid, { lat: -6.2, lng: 106.8, name: 'Jakarta' });
|
|
628
|
+
await sock.sendContact(jid, { name: 'Budi', vcard: 'BEGIN:VCARD\n...' });
|
|
629
|
+
await sock.sendGroupInvite(jid, { code: 'AbC123', jid: groupJid, subject: 'Komunitas' });
|
|
630
|
+
await sock.sendPaymentRequest(jid, { currency: 'IDR', amount: 50000, note: 'kopi ☕' });
|
|
631
|
+
await sock.sendInvoice(jid, { note: 'INV-001' });
|
|
632
|
+
await sock.sendPollOption(jid, pollKey, ['Opsi baru']);
|
|
633
|
+
await sock.sendEventInvite(jid, { eventTitle: 'Party', startTime: new Date(...) });
|
|
634
|
+
await sock.sendNewsletterInvite(jid, { newsletterJid, newsletterName: 'News' });
|
|
635
|
+
|
|
636
|
+
// Poll upgrades (already wired end-to-end):
|
|
637
|
+
await sock.sendPoll(jid, {
|
|
638
|
+
name: 'Jam berapa?', values: ['Pagi', 'Sore'],
|
|
639
|
+
endDate: new Date('2026-09-16T00:00:00Z'), // auto-close
|
|
640
|
+
hideVoter: true, // anonymous poll
|
|
641
|
+
canAddOption: true, // voters may add options
|
|
642
|
+
});
|
|
643
|
+
```
|
|
644
|
+
|
|
645
|
+
Music messages are experimental (real provider catalog IDs required):
|
|
646
|
+
|
|
647
|
+
```js
|
|
648
|
+
await sock.sendMusic(jid, { songUri, artworkUri, embeddedMusic: { songId, title, author } });
|
|
649
|
+
```
|
|
650
|
+
|
|
651
|
+
**Escape hatch:** every content key also works inline via `sendMessage`, and `{ raw: true, <AnyMessageField>: {...} }`
|
|
652
|
+
passes any proto field through untouched — full `WAProto` coverage with zero wrapper lag:
|
|
653
|
+
|
|
654
|
+
```js
|
|
655
|
+
await sock.sendMessage(jid, { raw: true, musicMessage: { songUri } });
|
|
656
|
+
```
|
|
657
|
+
|
|
658
|
+
TypeScript consumers get a typed `AnyMessageContent` (`import type { AnyMessageContent } from '@japofc/baileys'`).
|
|
659
|
+
|
|
660
|
+
## 🧰 Channels, History & Transcripts
|
|
661
|
+
|
|
662
|
+
**Channel management** (live queries):
|
|
663
|
+
|
|
664
|
+
```js
|
|
665
|
+
await sock.newsletterDelete(channelJid)
|
|
666
|
+
await sock.newsletterAdminCount(channelJid)
|
|
667
|
+
await sock.newsletterJoinInvite('invite-code')
|
|
668
|
+
await sock.newsletterChangeOwner(channelJid, newOwnerJid) // experimental
|
|
669
|
+
await sock.communityGetInviteCode(communityJid)
|
|
670
|
+
// ...plus existing follow/unfollow/mute/react/fetch + full community CRUD
|
|
671
|
+
```
|
|
672
|
+
|
|
673
|
+
**Group history sharing** for new members (forwards recent messages to their DM):
|
|
674
|
+
|
|
675
|
+
```js
|
|
676
|
+
import { getGroupHistoryFromStore } from '@japofc/baileys'
|
|
677
|
+
const messages = getGroupHistoryFromStore(store, groupJid, 10)
|
|
678
|
+
await sock.shareGroupHistory({ groupJid, members: newMemberJid, messages, greeting: true })
|
|
679
|
+
```
|
|
680
|
+
|
|
681
|
+
**Voice-note transcription** (pluggable provider — cloud Whisper or your own):
|
|
682
|
+
|
|
683
|
+
```js
|
|
684
|
+
import { openAIWhisperProvider } from '@japofc/baileys'
|
|
685
|
+
const provider = openAIWhisperProvider({ apiKey: process.env.OPENAI_API_KEY })
|
|
686
|
+
const { text } = await sock.transcribeMessage(voiceNoteMsg, { provider })
|
|
687
|
+
```
|
|
688
|
+
|
|
689
|
+
**Mini-app deep links** (HMAC-signed params your web app can verify):
|
|
690
|
+
|
|
691
|
+
```js
|
|
692
|
+
import { createMiniAppLink, parseMiniAppParams, buildFlowDataExchange } from '@japofc/baileys'
|
|
693
|
+
const link = createMiniAppLink('https://app.example.com/', { uid: '123' }, { secret: 's3cr3t' })
|
|
694
|
+
parseMiniAppParams(link, { secret: 's3cr3t' }) // → { uid: '123' } (throws if tampered)
|
|
695
|
+
buildFlowDataExchange('navigate', { screen: 'HOME' }) // Flows data_exchange payload
|
|
696
|
+
```
|
|
697
|
+
|
|
698
|
+
**A2UI widgets** now include `Slider`, `Switch`, `List`, `ProgressBar`, `Avatar`,
|
|
699
|
+
`Badge`, `Spacer`, and `Tabs` alongside the existing Text/Image/Video/Button/Card/Modal
|
|
700
|
+
set (all ref-validated at `build()`).
|
|
701
|
+
|
|
702
|
+
## 🔐 Security Pack
|
|
703
|
+
|
|
704
|
+
Drop-in hardening for auth state, secrets, and abuse — all in
|
|
705
|
+
`lib/Utils/auth-secure.js`, covered by `tests/security.test.js` (incl. fuzzing).
|
|
706
|
+
|
|
707
|
+
```js
|
|
708
|
+
import {
|
|
709
|
+
useEncryptedFileAuthState, secureLogger, withPairingGuard,
|
|
710
|
+
createQRGuard, backupAuthState, writeAuthIntegrity, repairAuthState, secureLogout
|
|
711
|
+
} from '@japofc/baileys'
|
|
712
|
+
|
|
713
|
+
// 1. AES-256-GCM encrypted auth state (reads legacy plaintext, migrates on save)
|
|
714
|
+
const { state, saveCreds } = await useEncryptedFileAuthState('./auth', { password: process.env.AUTH_PW })
|
|
715
|
+
const sock = makeWASocket({
|
|
716
|
+
auth: state,
|
|
717
|
+
logger: secureLogger(pino({ level: 'info' })), // 7. redacts qr/tokens/keys in every log line
|
|
718
|
+
})
|
|
719
|
+
|
|
720
|
+
// 2. pairing-code rate limit: 5/hour per number, 30s between attempts
|
|
721
|
+
withPairingGuard(sock, { maxPerHour: 5, minIntervalMs: 30_000 })
|
|
722
|
+
|
|
723
|
+
// 3. QR fist-guard: handle the first QR, swallow re-emits for 60s
|
|
724
|
+
const qrGuard = createQRGuard({ ttlMs: 60_000 })
|
|
725
|
+
sock.ev.on('connection.update', ({ qr }) => { qr = qrGuard.handle(qr); if (qr) show(qr) })
|
|
726
|
+
|
|
727
|
+
// 6/8. encrypted backup + integrity snapshot
|
|
728
|
+
await backupAuthState('./auth', './auth.jabackup', { password: process.env.BACKUP_PW })
|
|
729
|
+
await writeAuthIntegrity('./auth', { secret: process.env.INT_PW })
|
|
730
|
+
|
|
731
|
+
// 9. repair corrupt stores (quarantines + restores creds from backup)
|
|
732
|
+
await repairAuthState('./auth', { password: process.env.AUTH_PW, backupFile: './auth.jabackup', backupPassword: process.env.BACKUP_PW })
|
|
733
|
+
|
|
734
|
+
// 4. logout + overwrite/unlink every auth file + scrub in-memory creds
|
|
735
|
+
await secureLogout(sock, { authFolder: './auth' })
|
|
736
|
+
```
|
|
737
|
+
|
|
738
|
+
Single-file variant: `useEncryptedSingleFileAuthState(file, { password })`.
|
|
739
|
+
|
|
740
|
+
## 🆕 WA 2026 catch-up
|
|
741
|
+
|
|
742
|
+
WhatsApp 2026 features, wired into JAP-Baileys. Everything here was audited against the
|
|
743
|
+
latest official clients — only gaps were added; what already worked is just documented.
|
|
744
|
+
|
|
745
|
+
### Usernames (chat without phone numbers)
|
|
746
|
+
|
|
747
|
+
```js
|
|
748
|
+
await sock.checkUsername('japstore'); // availability
|
|
749
|
+
await sock.setUsername('japstore'); // claim it
|
|
750
|
+
await sock.reserveUsername('japstore'); // reserve it (2026 reservation flow)
|
|
751
|
+
await sock.findUserByUsername('japstore'); // USync lookup → JID
|
|
752
|
+
const u = await sock.fetchContactUsernames(['62812@s.whatsapp.net']);
|
|
753
|
+
```
|
|
754
|
+
|
|
755
|
+
### Editable polls (`editPoll`)
|
|
756
|
+
|
|
757
|
+
Polls are editable for ~15 minutes after creation (server-side rule):
|
|
758
|
+
|
|
759
|
+
```js
|
|
760
|
+
const sent = await sock.sendPoll(jid, { name: 'Jam berapa?', values: ['Pagi', 'Sore'] });
|
|
761
|
+
await sock.editPoll(jid, sent.key, { name: 'Jam berapa?', values: ['Pagi', 'Siang', 'Sore'] });
|
|
762
|
+
```
|
|
763
|
+
|
|
764
|
+
### Mass mention (`sendMentionAll`)
|
|
765
|
+
|
|
766
|
+
```js
|
|
767
|
+
await sock.sendMentionAll(groupJid, 'Pengumuman: rapat jam 9!');
|
|
768
|
+
```
|
|
769
|
+
|
|
770
|
+
> In groups with 32+ members `@all` is admin-only and the rule is enforced
|
|
771
|
+
> server-side — non-admin calls are silently dropped by WhatsApp.
|
|
772
|
+
|
|
773
|
+
### Event reminders
|
|
774
|
+
|
|
775
|
+
```js
|
|
776
|
+
await sock.sendMessage(jid, {
|
|
777
|
+
event: {
|
|
778
|
+
title: 'Rapat', description: 'Q3', startDate: new Date('2026-09-15T09:00:00+07:00'),
|
|
779
|
+
reminder: true, reminderOffsetSec: 1800, // remind 30 min before start
|
|
780
|
+
}
|
|
781
|
+
});
|
|
782
|
+
```
|
|
783
|
+
|
|
784
|
+
### Sender phone from LID events (`resolveSenderPn`)
|
|
785
|
+
|
|
786
|
+
Fixes LID-only payloads (e.g. call offers where `caller_pn` is missing):
|
|
787
|
+
|
|
788
|
+
```js
|
|
789
|
+
sock.ev.on('messages.upsert', async ({ messages }) => {
|
|
790
|
+
for (const m of messages) console.log(await sock.resolveSenderPn(m)); // '62812…' | null
|
|
791
|
+
});
|
|
792
|
+
```
|
|
793
|
+
|
|
794
|
+
### View-once voice notes
|
|
795
|
+
|
|
796
|
+
`sendVoiceNote()` content composes with `viewOnce`:
|
|
797
|
+
|
|
798
|
+
```js
|
|
799
|
+
await sock.sendMessage(jid, { ...(await buildVoiceNoteContent('./a.ogg')), viewOnce: true });
|
|
800
|
+
```
|
|
801
|
+
|
|
802
|
+
### Member tags (groups)
|
|
803
|
+
|
|
804
|
+
Already exposed — no new code, documented here:
|
|
805
|
+
|
|
806
|
+
```js
|
|
807
|
+
await sock.updateMemberLabel({ groupJid, lid, label: 'Admin' });
|
|
808
|
+
```
|
|
809
|
+
|
|
810
|
+
### Honestly not implemented (and why)
|
|
811
|
+
|
|
812
|
+
- **Voice message transcripts** — generated on-device by official clients only; there is
|
|
813
|
+
no transcript API on the wire.
|
|
814
|
+
- **Group message history sharing** — the wire format isn't captured by any public Baileys
|
|
815
|
+
fork yet (verified against the latest upstream Baileys release, whose proto is 100+
|
|
816
|
+
fields behind this repo).
|
|
817
|
+
- **Music messages** — `MusicMessage` needs Spotify/Apple catalog IDs plus an artwork
|
|
818
|
+
upload flow we haven't captured; the proto struct exists, sending real ones doesn't.
|
|
819
|
+
- **`mediaKeyDomain` — IMPLEMENTED.** Backported from rc14 onto all 5 media types
|
|
820
|
+
(`Audio/Document/Image/Sticker/VideoMessage`, enum `UNSET/E2EE_CHAT/STATUS/CAPI/BOT`)
|
|
821
|
+
with a send passthrough: `sendMessage(jid, { image: buf, mediaKeyDomain: 1 })`.
|
|
822
|
+
Unset by default (recommended — the server labels it). Skipped only on
|
|
823
|
+
`MMSThumbnailMetadata`, where upstream's field number 8 collides with the newer
|
|
824
|
+
`messageHistoryMetadata` in our proto.
|
|
825
|
+
|
|
826
|
+
## 🆕 Everyday Utilities
|
|
827
|
+
|
|
828
|
+
One-liners for daily bot work (also usable standalone — see `examples/`):
|
|
829
|
+
|
|
830
|
+
```js
|
|
831
|
+
// 📊 Poll (chats/groups) + Quiz (channels only)
|
|
832
|
+
await sock.sendPoll(jid, { name: 'Makan apa?', options: ['Nasi', 'Mie'] })
|
|
833
|
+
await sock.sendQuiz(channelJid, { name: 'Kuis', options: ['A', 'B'], correctAnswer: 'A' })
|
|
834
|
+
|
|
835
|
+
// 🎙️ Voice note — auto-converts mp3/wav/… to Opus PTT (needs fluent-ffmpeg)
|
|
836
|
+
await sock.sendVoiceNote(jid, './hello.mp3') // path | Buffer | { url }
|
|
837
|
+
|
|
838
|
+
// 📞 Tag everyone (visible @list vs hidden)
|
|
839
|
+
await sock.tagAll(groupJid, 'Rapat jam 10!')
|
|
840
|
+
await sock.hideTag(groupJid, 'Pengumuman 📢')
|
|
841
|
+
|
|
842
|
+
// 🔍 LID → phone number (best-effort, null when unknown)
|
|
843
|
+
await sock.getPhoneNumber('12345@lid') // → '62812…'
|
|
844
|
+
await sock.getLidForPhone('62812…') // reverse lookup
|
|
845
|
+
|
|
846
|
+
// 🧍 Humanized send — typing… + natural delay + per-chat queue
|
|
847
|
+
await sock.sendHumanized(jid, { text: 'Halo!' })
|
|
848
|
+
|
|
849
|
+
// 🤖 Meta AI chat (experimental — needs Meta AI on the account/region)
|
|
850
|
+
const { text } = await sock.askMetaAI('Jelaskan black hole!')
|
|
851
|
+
```
|
|
852
|
+
|
|
853
|
+
**Command router** for prefix bots (`!menu`, `.sticker`) with middleware + auto-help:
|
|
854
|
+
|
|
855
|
+
```js
|
|
856
|
+
import { createRouter } from '@japofc/baileys'
|
|
857
|
+
const router = createRouter({ prefix: '!' })
|
|
858
|
+
router.command('ping', async (ctx) => ctx.reply('pong! 🏓'), { desc: 'Check bot' })
|
|
859
|
+
router.attach(sock) // → detach()
|
|
860
|
+
```
|
|
861
|
+
|
|
862
|
+
**Status / channel schedulers** (in-memory):
|
|
863
|
+
|
|
864
|
+
```js
|
|
865
|
+
import { StatusScheduler, ChannelScheduler, StatusHelper } from '@japofc/baileys'
|
|
866
|
+
new StatusScheduler(sock).schedule(StatusHelper.text('Pagi! ☀️'), new Date('2026-09-11T06:00:00+07:00'))
|
|
867
|
+
new ChannelScheduler(sock).schedule(channelJid, { text: 'Update' }, Date.now() + 3600_000)
|
|
868
|
+
```
|
|
869
|
+
|
|
870
|
+
`npm test` runs the offline suite (`tests/`, 68 asserts, no network needed).
|
|
871
|
+
|
|
872
|
+
---
|
|
873
|
+
|
|
874
|
+
## 📞 Voice & Video Calls
|
|
875
|
+
|
|
876
|
+
Experimental audio-call support via a bundled WASM call stack + WebRTC relay. Requires the optional `@roamhq/wrtc` peer dependency.
|
|
877
|
+
|
|
878
|
+
```js
|
|
879
|
+
import { VoipClient } from '@japofc/baileys'
|
|
880
|
+
|
|
881
|
+
const voip = new VoipClient({ resourcesPath: './voip-resources' })
|
|
882
|
+
await voip.connectWithSocket(sock)
|
|
883
|
+
|
|
884
|
+
const call = await voip.call('628123456789')
|
|
885
|
+
|
|
886
|
+
call.on('ringing', () => console.log('Ringing...'))
|
|
887
|
+
call.on('connected', () => console.log('Call connected'))
|
|
888
|
+
call.on('ended', (reason) => console.log('Call ended:', reason))
|
|
889
|
+
```
|
|
890
|
+
|
|
891
|
+
`ActiveCall` (returned by `.call()`) and `CallState` are also exported directly if you need finer-grained control over call state.
|
|
892
|
+
|
|
893
|
+
**Answering inbound calls** — offers are tracked, so the bot can pick up (1:1) or join (group):
|
|
894
|
+
|
|
895
|
+
```js
|
|
896
|
+
import { attachVoip } from '@japofc/baileys'
|
|
897
|
+
const voip = await attachVoip(sock) // also stored as sock.voip
|
|
898
|
+
|
|
899
|
+
voip.on('incoming-call', async ({ callId, from, isGroupCall, busy }) => {
|
|
900
|
+
if (busy) return
|
|
901
|
+
if (isGroupCall) await voip.joinGroupCall(callId, { audioSource: './greeting.mp3' })
|
|
902
|
+
else await voip.answerCall(callId, { audioSource: './greeting.mp3' })
|
|
903
|
+
})
|
|
904
|
+
|
|
905
|
+
// ...or fully automatic:
|
|
906
|
+
await attachVoip(sock, { autoAnswer: true }) // pick up 1:1 calls
|
|
907
|
+
await attachVoip(sock, { autoJoinGroup: true }) // join group calls
|
|
908
|
+
await attachVoip(sock, { autoReject: true, autoRejectText: 'Bot cannot take calls 🙏' })
|
|
909
|
+
|
|
910
|
+
// still-pending offers (answer before `offerTtlMs`, default 45s):
|
|
911
|
+
voip.getPendingCalls() // → [{ callId, from, isGroupCall, ... }]
|
|
912
|
+
```
|
|
913
|
+
|
|
914
|
+
**Group / multi-party calls:**
|
|
915
|
+
|
|
916
|
+
```js
|
|
917
|
+
const gcall = await voip.startGroupCall(groupJid, ['62812…', '62813…'], { chatName: 'Rapat' })
|
|
918
|
+
await voip.inviteToGroupCall('62814…')
|
|
919
|
+
await voip.removeGroupParticipant('62813@s.whatsapp.net')
|
|
920
|
+
await voip.rejoinGroupCall() // recovery after a drop
|
|
921
|
+
|
|
922
|
+
voip.on('group-call-started', console.log)
|
|
923
|
+
voip.on('group-call-joined', console.log)
|
|
924
|
+
```
|
|
925
|
+
|
|
926
|
+
Calls also support reactions, hand-raise, recording, and call links:
|
|
927
|
+
|
|
928
|
+
```js
|
|
929
|
+
const call = await voip.call('628123456789', { audioSource: './greeting.mp3' })
|
|
930
|
+
call.react('👍')
|
|
931
|
+
call.setHandRaised(true)
|
|
932
|
+
const stopRecording = call.recordToFile('./call.wav') // remote peer → .wav
|
|
933
|
+
await voip.previewCallLink('call-link-token')
|
|
934
|
+
```
|
|
935
|
+
|
|
936
|
+
**Reconnect & recovery** — a watchdog monitors the relay transport during every call
|
|
937
|
+
(`watchdogIntervalMs`/`watchdogMaxSilent`); on a dead relay it emits `call-degraded`
|
|
938
|
+
and automatically re-sends the crypto rekey + offer. Manual controls:
|
|
939
|
+
|
|
940
|
+
```js
|
|
941
|
+
voip.on('call-degraded', ({ callId }) => console.log('relay dead, recovering', callId))
|
|
942
|
+
voip.on('call-recovery', (r) => console.log('recovery result', r))
|
|
943
|
+
await voip.recoverCall({}) // manual: { rekey: true, offer: true }
|
|
944
|
+
voip.getStats() // { busy, callId, call, relay }
|
|
945
|
+
sock.ev.on('call', (calls) => { /* standard offer/reject path still works */ })
|
|
946
|
+
```
|
|
947
|
+
|
|
948
|
+
**Refreshing the WASM stack** — if calls break after a WA Web update, re-fetch the official VoIP build from your own browser (Chrome with `--remote-debugging-port=9222` + web.whatsapp.com open):
|
|
949
|
+
|
|
950
|
+
```bash
|
|
951
|
+
npm run voip:fetch-wasm
|
|
952
|
+
```
|
|
953
|
+
|
|
954
|
+
---
|
|
955
|
+
|
|
956
|
+
## 🔎 User Sync Queries
|
|
957
|
+
|
|
958
|
+
`WAUSync` (`USyncQuery` / `USyncUser` + protocols) lets you check things like WhatsApp registration, device lists, status, and username info for a JID before you message it — the same mechanism behind `sock.onWhatsApp()`.
|
|
959
|
+
|
|
960
|
+
```js
|
|
961
|
+
import { USyncQuery, USyncUser, USyncContactProtocol } from '@japofc/baileys'
|
|
962
|
+
|
|
963
|
+
const query = new USyncQuery()
|
|
964
|
+
.withContext('interactive')
|
|
965
|
+
.withMode('query')
|
|
966
|
+
.withUser(new USyncUser().withPhone('628123456789'))
|
|
967
|
+
|
|
968
|
+
query.protocols.push(new USyncContactProtocol())
|
|
969
|
+
|
|
970
|
+
const result = await sock.executeUSyncQuery(query)
|
|
971
|
+
```
|
|
972
|
+
|
|
973
|
+
Available protocols: `USyncContactProtocol`, `USyncDeviceProtocol`, `USyncStatusProtocol`, `USyncUsernameProtocol`, `USyncDisappearingModeProtocol`, `UsyncBotProfileProtocol`, `UsyncLIDProtocol`.
|
|
974
|
+
|
|
975
|
+
---
|
|
976
|
+
|
|
977
|
+
## 👤 Username Management
|
|
978
|
+
|
|
979
|
+
High-level wrappers around WhatsApp's username feature (the `@username` handle you can set instead of exposing your phone number), sitting on top of `USyncUsernameProtocol`. Query IDs are captured from live WA Web sessions — if a call starts throwing `unexpected response structure`, WA has rotated them and they need re-capturing.
|
|
980
|
+
|
|
981
|
+
```js
|
|
982
|
+
// Check availability + get suggestions if taken
|
|
983
|
+
const check = await sock.checkUsername('J.AP')
|
|
984
|
+
// { available: true, username: 'J.AP' }
|
|
985
|
+
// or: { available: false, suggestions: [...], rejectionReasons: [...] }
|
|
986
|
+
|
|
987
|
+
// Claim a username
|
|
988
|
+
await sock.setUsername('J.AP', { source: sock.USERNAME_SOURCE.USER_INPUT })
|
|
989
|
+
|
|
990
|
+
// Lock it behind a PIN so it can't be changed without one
|
|
991
|
+
await sock.setUsernamePin('123456')
|
|
992
|
+
|
|
993
|
+
// Read your own username / drop it
|
|
994
|
+
const mine = await sock.getMyUsername()
|
|
995
|
+
await sock.deleteUsername()
|
|
996
|
+
|
|
997
|
+
// Resolve a username to a JID (USync-based, like onWhatsApp() but by username)
|
|
998
|
+
const user = await sock.findUserByUsername('someone')
|
|
999
|
+
// { jid: '628...@s.whatsapp.net', contact: false }
|
|
1000
|
+
|
|
1001
|
+
// Batch-resolve usernames for a list of known contacts
|
|
1002
|
+
const usernames = await sock.fetchContactUsernames(jid1, jid2, jid3)
|
|
1003
|
+
|
|
1004
|
+
// Get WA's own suggestions (e.g. for onboarding flows)
|
|
1005
|
+
const recs = await sock.getUsernameRecommendations()
|
|
1006
|
+
```
|
|
1007
|
+
|
|
1008
|
+
> Requires a Community/Contact-tier account in good standing — accounts under WA's usual restrictions for new/unverified numbers may see `INVALID` or empty suggestions regardless of the username's actual availability.
|
|
1009
|
+
|
|
1010
|
+
---
|
|
1011
|
+
|
|
1012
|
+
<div align="center">
|
|
1013
|
+
<img src="https://capsule-render.vercel.app/api?type=soft&color=0:2ecc71,100:1d6a23&height=70§ion=header" width="100%"/>
|
|
1014
|
+
</div>
|
|
1015
|
+
|
|
1016
|
+
## 🤖 Bot Framework
|
|
1017
|
+
|
|
1018
|
+
An optional, higher-level layer on top of the raw socket: middleware routing, a `!command` dispatcher, a message queue that survives disconnects, exponential-backoff auto-reconnect, per-JID session storage, group activity stats, and media (sticker/voice-note) conversion helpers — so a new bot project doesn't have to hand-roll session/context management every time.
|
|
1019
|
+
|
|
1020
|
+
Needs the `better-sqlite3` peer dependency (session + stats storage) and `fluent-ffmpeg` (sticker/voice-note conversion, already listed above) — both fail with an install hint rather than crashing if you use a Framework feature that needs them without installing them first.
|
|
1021
|
+
|
|
1022
|
+
```js
|
|
1023
|
+
import { Bot } from '@japofc/baileys'
|
|
1024
|
+
|
|
1025
|
+
const bot = new Bot({
|
|
1026
|
+
socketConfig: { printQRInTerminal: true },
|
|
1027
|
+
dbPath: './bot.db', // sessions + stats, defaults to 'baileys_store.db'
|
|
1028
|
+
enableStats: true // group message/sticker leaderboards + ghost detection
|
|
1029
|
+
})
|
|
1030
|
+
|
|
1031
|
+
bot.command('!ping', async (ctx) => {
|
|
1032
|
+
await ctx.reply({ text: 'pong' })
|
|
1033
|
+
})
|
|
1034
|
+
|
|
1035
|
+
bot.command('!sticker', async (ctx) => {
|
|
1036
|
+
if (!ctx.quoted?.imageMessage) return ctx.reply({ text: 'Reply to an image with !sticker' })
|
|
1037
|
+
// ctx.replySticker() handles the WebP conversion for you
|
|
1038
|
+
await ctx.replySticker(imageBuffer, { packname: 'J.AP Pack', author: 'you' })
|
|
1039
|
+
})
|
|
1040
|
+
|
|
1041
|
+
bot.onText(async (ctx) => {
|
|
1042
|
+
// ctx.session() / ctx.setSession() / ctx.updateSession() / ctx.clearSession()
|
|
1043
|
+
// persist small per-chat state (e.g. multi-step flows) to SQLite automatically
|
|
1044
|
+
const state = ctx.session()
|
|
1045
|
+
if (state?.awaitingReply) {
|
|
1046
|
+
ctx.updateSession((s) => ({ ...s, awaitingReply: false }))
|
|
1047
|
+
}
|
|
1048
|
+
})
|
|
1049
|
+
|
|
1050
|
+
await bot.start()
|
|
1051
|
+
```
|
|
1052
|
+
|
|
1053
|
+
`Context`, `SessionManager`, `StatsManager`, `MediaManager`, and `SQLiteStore` are also exported individually if you only need one piece rather than the full `Bot` class.
|
|
1054
|
+
|
|
1055
|
+
> These files ship as plain `.js` for now — hand-written `.d.ts` declarations for the Framework module haven't been added yet, unlike the rest of this fork's fully-typed surface.
|
|
1056
|
+
|
|
1057
|
+
---
|
|
1058
|
+
|
|
1059
|
+
## 🧩 Utility Modules
|
|
1060
|
+
|
|
1061
|
+
A sample of the utilities exported from `lib/Utils` beyond the message builders above:
|
|
1062
|
+
|
|
1063
|
+
| Module | What it does |
|
|
1064
|
+
|---|---|
|
|
1065
|
+
| `anti-delete` | Detect and recover messages the sender deleted for everyone |
|
|
1066
|
+
| `auto-reply` | Simple keyword/pattern-based auto-responder engine |
|
|
1067
|
+
| `message-search` | Search cached/stored messages, peeling off ephemeral/view-once wrappers first |
|
|
1068
|
+
| `message-retry-manager` | Handles WhatsApp's retry-receipt protocol for undecryptable messages |
|
|
1069
|
+
| `scheduling` | Schedule messages/actions for later delivery |
|
|
1070
|
+
| `business` | Business-profile & catalog helpers |
|
|
1071
|
+
| `chat-control` | Pin, mute, archive, and mark-read/unread helpers |
|
|
1072
|
+
| `chat-history-helpers` | Work with synced chat history payloads |
|
|
1073
|
+
| `link-preview` | Generate link preview metadata for outgoing messages |
|
|
1074
|
+
| `stickerpack` | Build and send sticker packs (including animated/Lottie) |
|
|
1075
|
+
| `templates` | Legacy WhatsApp Business template message helpers |
|
|
1076
|
+
| `vcard` | Build vCard (contact card) payloads |
|
|
1077
|
+
| `status` | Post and manage WhatsApp Status updates |
|
|
1078
|
+
| `event-buffer` | Buffers/coalesces high-volume socket events for heavier bots |
|
|
1079
|
+
|
|
1080
|
+
Every module above ships a matching `.d.ts`, so your editor will show full hover-docs regardless of which ones you import.
|
|
1081
|
+
|
|
1082
|
+
---
|
|
1083
|
+
|
|
1084
|
+
## 🛠 Recommended Environment
|
|
1085
|
+
|
|
1086
|
+
| Requirement | Version |
|
|
1087
|
+
|---|---|
|
|
1088
|
+
| Node.js | 20+ |
|
|
1089
|
+
| Module system | ESM |
|
|
1090
|
+
| WhatsApp | Latest Multi Device |
|
|
1091
|
+
|
|
1092
|
+
---
|
|
1093
|
+
|
|
1094
|
+
## 📘 TypeScript Support
|
|
1095
|
+
|
|
1096
|
+
Full `.d.ts`: every shipped `.js` file has a matching TypeScript declaration (guarded by `tests/types-parity.test.js`), and the whole package verifies at zero errors under `tsc --strict`. `import { ... } from '@japofc/baileys'` resolves with no `@types/` package needed (beyond the standard `@types/node` every Node TS project has): `makeWASocket` incl. the username methods and `USERNAME_*` constants, all `Types/*` definitions, `WAProto`, stores, `Utils/*`, the message builders (`Button`, `Poll`, `Carousel`, `AIRich`, `A2UI`, … with Bloks node types), the Bot Framework (`Bot`, `Context`, …), and the VoIP client (`VoipClient`, `ActiveCall`, …). Complex wire payloads are typed as loose records where WhatsApp publishes no schema.
|
|
1097
|
+
|
|
1098
|
+
---
|
|
1099
|
+
|
|
1100
|
+
## ❓ FAQ & Troubleshooting
|
|
1101
|
+
|
|
1102
|
+
<details>
|
|
1103
|
+
<summary><b>Koneksi terus putus / reconnect loop</b></summary>
|
|
1104
|
+
<br/>
|
|
1105
|
+
|
|
1106
|
+
Cek `connection.update` untuk field `lastDisconnect.error`. Kalau status code-nya `401` (loggedOut), sesi memang sudah invalid dan perlu scan ulang QR — jangan auto-reconnect di kondisi ini. Untuk status lain (`428`, `440`, dsb.), reconnect dengan backoff biasanya cukup.
|
|
1107
|
+
|
|
1108
|
+
</details>
|
|
1109
|
+
|
|
1110
|
+
<details>
|
|
1111
|
+
<summary><b>QR tidak muncul / tidak ke-scan</b></summary>
|
|
1112
|
+
<br/>
|
|
1113
|
+
|
|
1114
|
+
Di upstream Baileys `printQRInTerminal` sudah dihapus, tapi di paket ini opsi tersebut **berfungsi lagi** — QR digambar otomatis oleh renderer bawaan (vendored [qrcodegen](https://github.com/nayuki/QR-Code-generator), tanpa dependency tambahan). Bisa juga render manual dari event `qr` dengan `renderQRToTerminal(qr)` / `qrToSVG(qr)` / `qrToPNG(qr)` / `qrToMatrix(qr)`. Kalau QR muncul tapi gagal linking, biasanya karena versi WA Web (`version` di `makeWASocket`) sudah kedaluwarsa; fetch versi terbaru lewat `fetchBestWaVersion()` (chain: sw.js WA → fork baileys → fallback). Framework `Bot` sudah melakukannya otomatis tiap `start()`/reconnect (matikan dengan `versionCheck: false`). QR kelihatan "kebalik" di terminal tema terang? Pakai `renderQRToTerminal(qr, { inverted: true })`.
|
|
1115
|
+
|
|
1116
|
+
</details>
|
|
1117
|
+
|
|
1118
|
+
<details>
|
|
1119
|
+
<summary><b>Error "Bad MAC" / pesan gagal didekripsi</b></summary>
|
|
1120
|
+
<br/>
|
|
1121
|
+
|
|
1122
|
+
Umumnya terjadi kalau folder auth state korup atau sesi dipakai di lebih dari satu proses secara bersamaan. Pastikan hanya satu instance yang menulis ke folder auth state yang sama, dan pertimbangkan `pruneStaleAuthFiles()` untuk membersihkan sender-key lama secara berkala.
|
|
1123
|
+
|
|
1124
|
+
</details>
|
|
1125
|
+
|
|
1126
|
+
<details>
|
|
1127
|
+
<summary><b>Memory terus naik di bot yang jalan lama</b></summary>
|
|
1128
|
+
<br/>
|
|
1129
|
+
|
|
1130
|
+
Kalau pakai `makeInMemoryStore()`, cache chat/message/contact akan terus tumbuh tanpa batas. Untuk bot yang jalan lama, pertimbangkan pindah ke salah satu backend `makePersistentStore()` (SQLite/Redis/dst) dan pakai `event-buffer` untuk meredam lonjakan event di trafik tinggi.
|
|
1131
|
+
|
|
1132
|
+
</details>
|
|
1133
|
+
|
|
1134
|
+
<details>
|
|
1135
|
+
<summary><b>Voice call gagal connect</b></summary>
|
|
1136
|
+
<br/>
|
|
1137
|
+
|
|
1138
|
+
Fitur ini masih experimental dan butuh peer dependency `@roamhq/wrtc` — pastikan sudah terinstall dan platform kamu didukung native binding-nya. Cek event `call.on('ended', reason => ...)` untuk detail penyebab gagalnya.
|
|
1139
|
+
|
|
1140
|
+
</details>
|
|
1141
|
+
|
|
1142
|
+
---
|
|
1143
|
+
|
|
1144
|
+
## 🤝 Contributing
|
|
1145
|
+
|
|
1146
|
+
Kontribusi dipersilakan, terutama untuk perbaikan bug, dokumentasi, dan enhancement pada `MessageBuilder` / `AIRich`.
|
|
1147
|
+
|
|
1148
|
+
1. Fork repo ini, buat branch dari `main` (`feat/nama-fitur` atau `fix/nama-bug`)
|
|
1149
|
+
2. Pastikan perubahan tetap ESM-only dan menyertakan/menyesuaikan `.d.ts` terkait
|
|
1150
|
+
3. Uji perubahan pada minimal satu jalur auth state + satu store backend sebelum PR
|
|
1151
|
+
4. Buka Pull Request dengan deskripsi singkat: apa yang berubah dan kenapa
|
|
1152
|
+
|
|
1153
|
+
Untuk laporan bug, sertakan versi Node.js, cara reproduksi, dan potongan log `lastDisconnect.error` bila relevan.
|
|
1154
|
+
|
|
1155
|
+
---
|
|
1156
|
+
|
|
1157
|
+
## 🙏 Credits
|
|
1158
|
+
|
|
1159
|
+
Built on the shoulders of the open-source WhatsApp community.
|
|
1160
|
+
|
|
1161
|
+
Full details and license terms per component: see [`NOTICE.md`](./NOTICE.md).
|
|
1162
|
+
|
|
1163
|
+
---
|
|
1164
|
+
|
|
1165
|
+
## 👑 Maintainer
|
|
1166
|
+
|
|
1167
|
+
<table>
|
|
1168
|
+
<tr>
|
|
1169
|
+
<td width="180" align="center">
|
|
1170
|
+
<img src="https://github.com/JAPofc.png" width="160" alt="J.AP avatar" style="border-radius:50%"/>
|
|
1171
|
+
</td>
|
|
1172
|
+
<td>
|
|
1173
|
+
|
|
1174
|
+
**J.AP**
|
|
1175
|
+
|
|
1176
|
+
- GitHub: [github.com/JAPofc](https://github.com/JAPofc)
|
|
1177
|
+
- Package: [`@japofc/baileys`](https://www.npmjs.com/package/@japofc/baileys)
|
|
1178
|
+
- ✦ Maintains this fork solo — issues & PRs are welcome and reviewed personally.
|
|
1179
|
+
|
|
1180
|
+
</td>
|
|
1181
|
+
</tr>
|
|
1182
|
+
</table>
|
|
1183
|
+
|
|
1184
|
+
<p align="center">
|
|
1185
|
+
<img src="https://raw.githubusercontent.com/JAPofc/JAPofc/output/github-contribution-grid-snake.svg" width="100%" alt="Contribution snake animation"/>
|
|
1186
|
+
</p>
|
|
1187
|
+
|
|
1188
|
+
---
|
|
1189
|
+
|
|
1190
|
+
## ⚠️ Disclaimer
|
|
1191
|
+
|
|
1192
|
+
This project is an independent fork.
|
|
1193
|
+
Use responsibly and follow WhatsApp Terms of Service.
|
|
1194
|
+
|
|
1195
|
+
---
|
|
1196
|
+
|
|
1197
|
+
## 📝 v2.1.0 Patch Notes
|
|
1198
|
+
|
|
1199
|
+
> Ringkasan — detail lengkap di [CHANGELOG.md](./CHANGELOG.md).
|
|
1200
|
+
|
|
1201
|
+
- **QR bawaan, nol dependency**: vendored [qrcodegen](https://github.com/nayuki/QR-Code-generator) (Nayuki, MIT) + renderer sendiri — `renderQRToTerminal` (half-block `▀▄█`, setengah tinggi renderer klasik), `qrToSVG`, `qrToPNG` (encoder PNG hand-rolled di atas zlib Node), `qrToMatrix`, `formatPairingCode`. Round-trip diverifikasi decoder independen (jsQR) di CI.
|
|
1202
|
+
- **`printQRInTerminal` berfungsi lagi** — bukan warning deprecated: QR digambar otomatis di terminal tiap `connection.update`.
|
|
1203
|
+
- **Fix spam VoIP `VoipStatsTracker is not a constructor`**: shim Metro di `worker-bootstrap.js` menggeser `module`/`exports` satu posisi (argumen ke-5 `null`). Diperbaiki untuk kedua konvensi export bundle FB Comet (flag-66 → arg 6, flag-98 → arg 7, 124/204 modul) + fallback `?.exports` di loader. Diverifikasi worker asli boot sampai `worker_ready` tanpa error shim.
|
|
1204
|
+
- **Auto WA-version di Framework `Bot`**: tiap `start()`/reconnect resolve versi tersegar via `fetchBestWaVersion()` (sw.js WA → fork → fallback), mencegah 405 pairing gara-gara versi basi. Opt-out: `versionCheck: false` atau pin `socketConfig.version`.
|
|
1205
|
+
- **Full `.d.ts` beneran**: setiap `.js` yang di-ship punya deklarasi pasangan, dijaga test parity + harness `tsc --strict` di CI.
|
|
1206
|
+
- **CI + release automation**: GitHub Actions (test di Node 20/22, type-check, pack sanity) dan publish workflow ber-provenance yang terpicu tag `v*`.
|
|
1207
|
+
|
|
1208
|
+
---
|
|
1209
|
+
|
|
1210
|
+
## 📝 V6 Patch Notes
|
|
1211
|
+
|
|
1212
|
+
- Fixed a `package.json` typo: the version field was mistakenly left at `1.0.1` instead of `2.0.1` after the V5 release — corrected to `2.0.1` so the published package version matches the intended release.
|
|
1213
|
+
- Expanded README documentation, especially around `lib/Builders/`:
|
|
1214
|
+
- Added the new [📁 Builders Folder Map](#-builders-folder-map-libbuilders) section — a per-file breakdown of everything under `lib/Builders/` (`shared.js`, `Button.js`, `ButtonV2.js`, `ButtonV3.js`, `Carousel.js`, `Poll.js`, `AIRich.js`, `A2UI.js`, `JapBaileys.js`, `index.js`), what each file exports, and what it's for — previously `A2UI` and `JapBaileys` in particular had no usage documentation at all.
|
|
1215
|
+
- Added a usage example for the `JapBaileys` unified builder hub.
|
|
1216
|
+
- Redesigned `postinstall-banner.js`: cleaner box layout with a divider separating the title block from a small info section (Node version + docs link), a 256-color palette instead of basic ANSI colors, and a plain-text fallback when stdout isn't a TTY or `NO_COLOR` is set (CI logs, piped output) instead of forcing a box that may render misaligned.
|
|
1217
|
+
|
|
1218
|
+
---
|
|
1219
|
+
|
|
1220
|
+
## 📝 V5 Patch Notes
|
|
1221
|
+
|
|
1222
|
+
- Added [Username Management](#-username-management): `checkUsername`, `checkUsernameMulti`, `setUsername`, `deleteUsername`, `getMyUsername`, `setUsernamePin`, `findUserByUsername`, `fetchContactUsernames`, `getUsernameRecommendations`, layered onto the existing `USyncUsernameProtocol` support.
|
|
1223
|
+
- Added the [Bot Framework](#-bot-framework) (`Bot`, `Context`, `SessionManager`, `StatsManager`, `MediaManager`, `SQLiteStore`). Adapted on the way in:
|
|
1224
|
+
- `SQLiteStore`/`StatsManager` construction moved behind an async `.create()` factory so `better-sqlite3` stays a lazily-loaded optional peer dep instead of a hard top-level import that would crash the Framework module for anyone without it installed.
|
|
1225
|
+
- `MediaManager`'s sticker/voice-note conversion now reuses this fork's existing lazy `fluent-ffmpeg` loader (see `Utils/MessageBuilder.js`) instead of adding `ffmpeg-static` + a second ffmpeg dependency; `node-webpmux` (sticker EXIF metadata) is lazy-loaded the same way and only when packname/author is actually requested.
|
|
1226
|
+
- `Bot`'s default logger now falls back to this fork's own pino instance instead of a silent no-op stub.
|
|
1227
|
+
- No `.d.ts` files were written for the new Framework module yet — see the note in that section.
|
|
1228
|
+
- Bumped to `1.0.1`.
|
|
1229
|
+
|
|
1230
|
+
---
|
|
1231
|
+
|
|
1232
|
+
## 📝 V4 Patch Notes
|
|
1233
|
+
|
|
1234
|
+
- Kept the existing J.AP custom MessageBuilder classes and AIRich implementation intact.
|
|
1235
|
+
- Added `whatsapp-rust-bridge@0.5.5` as a runtime dependency. The library already dynamically imports this module for LT Hash/app-state and crypto helpers; declaring it prevents accidental missing-module fallbacks in normal installations.
|
|
1236
|
+
- Existing guarded fallbacks for platforms where the native bridge cannot load remain in place.
|
|
1237
|
+
- ESM-only package metadata is preserved; no CommonJS build is included.
|
|
1238
|
+
|
|
1239
|
+
|
|
1240
|
+
---
|
|
1241
|
+
|
|
1242
|
+
<div align="center">
|
|
1243
|
+
|
|
1244
|
+
Made with 🍃 by **JAP**
|
|
1245
|
+
|
|
1246
|
+
Thanks for visiting, bye 👋
|
|
1247
|
+
|
|
1248
|
+
<img src="https://capsule-render.vercel.app/api?type=waving&color=0:2ecc71,100:1d6a23&height=100§ion=footer" width="100%"/>
|
|
1249
|
+
|
|
1250
|
+
|
|
1251
|
+
|
|
1252
|
+
<a href="#top">⬆️ Back to top</a>
|
|
1253
|
+
|
|
1254
|
+
</div>
|