@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
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* JAP@Add --- Status + channel post schedulers.
|
|
3
|
+
*
|
|
4
|
+
* ```js
|
|
5
|
+
* import { StatusScheduler, ChannelScheduler, StatusHelper } from '@japofc/baileys'
|
|
6
|
+
* const statusQ = new StatusScheduler(sock)
|
|
7
|
+
* statusQ.schedule(StatusHelper.text('Selamat pagi! ☀️'), new Date('2026-09-11T06:00:00+07:00'))
|
|
8
|
+
* statusQ.scheduleIn(StatusHelper.text('Promo!'), 3600_000, { repeatMs: 86400_000 }) // hourly-ish
|
|
9
|
+
*
|
|
10
|
+
* const channelQ = new ChannelScheduler(sock)
|
|
11
|
+
* channelQ.schedule('123@newsletter', { text: 'Update harian' }, runAt)
|
|
12
|
+
* ```
|
|
13
|
+
*
|
|
14
|
+
* In-memory only (jobs vanish on restart — persist `pending()` yourself if needed).
|
|
15
|
+
*/
|
|
16
|
+
import { Boom } from '@hapi/boom';
|
|
17
|
+
import { StatusHelper } from './status.js';
|
|
18
|
+
class BaseTimedPoster {
|
|
19
|
+
constructor(sock, { onError } = {}) {
|
|
20
|
+
if (!sock || typeof sock.sendMessage !== 'function') {
|
|
21
|
+
throw new Boom('Scheduler(sock, ...) requires an active Baileys socket', { statusCode: 400 });
|
|
22
|
+
}
|
|
23
|
+
this.sock = sock;
|
|
24
|
+
this.onError = typeof onError === 'function' ? onError : null;
|
|
25
|
+
this.jobs = new Map();
|
|
26
|
+
this.seq = 0;
|
|
27
|
+
}
|
|
28
|
+
_schedule(sendFn, when, { repeatMs, maxRepeats } = {}) {
|
|
29
|
+
const target = when instanceof Date ? when.getTime() : Number(when);
|
|
30
|
+
if (!Number.isFinite(target)) {
|
|
31
|
+
throw new Boom('schedule(when) needs a Date or epoch-ms number', { statusCode: 400 });
|
|
32
|
+
}
|
|
33
|
+
if (repeatMs !== undefined && (!Number.isFinite(Number(repeatMs)) || Number(repeatMs) <= 0)) {
|
|
34
|
+
throw new Boom('repeatMs must be a positive number', { statusCode: 400 });
|
|
35
|
+
}
|
|
36
|
+
const id = `post_${Date.now()}_${++this.seq}`;
|
|
37
|
+
const job = { id, timer: null, runs: 0, cancelled: false };
|
|
38
|
+
const tick = async () => {
|
|
39
|
+
if (job.cancelled) {
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
job.runs++;
|
|
43
|
+
try {
|
|
44
|
+
await sendFn();
|
|
45
|
+
}
|
|
46
|
+
catch (err) {
|
|
47
|
+
try {
|
|
48
|
+
this.onError?.(err, id);
|
|
49
|
+
}
|
|
50
|
+
catch { }
|
|
51
|
+
}
|
|
52
|
+
if (job.cancelled) {
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
if (repeatMs && (maxRepeats == null || job.runs < maxRepeats)) {
|
|
56
|
+
job.timer = setTimeout(tick, Number(repeatMs));
|
|
57
|
+
job.timer.unref?.();
|
|
58
|
+
}
|
|
59
|
+
else {
|
|
60
|
+
this.jobs.delete(id);
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
job.timer = setTimeout(tick, Math.max(0, target - Date.now()));
|
|
64
|
+
job.timer.unref?.();
|
|
65
|
+
this.jobs.set(id, job);
|
|
66
|
+
return id;
|
|
67
|
+
}
|
|
68
|
+
/** Cancel one job. Returns true if it existed. */
|
|
69
|
+
cancel(id) {
|
|
70
|
+
const job = this.jobs.get(id);
|
|
71
|
+
if (!job) {
|
|
72
|
+
return false;
|
|
73
|
+
}
|
|
74
|
+
job.cancelled = true;
|
|
75
|
+
clearTimeout(job.timer);
|
|
76
|
+
this.jobs.delete(id);
|
|
77
|
+
return true;
|
|
78
|
+
}
|
|
79
|
+
/** Cancel everything. */
|
|
80
|
+
clear() {
|
|
81
|
+
for (const id of [...this.jobs.keys()]) {
|
|
82
|
+
this.cancel(id);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
/** List pending job ids + run counts. */
|
|
86
|
+
pending() {
|
|
87
|
+
return [...this.jobs.values()].map(({ id, runs }) => ({ id, runs }));
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
/** Schedule status posts (broadcast or targeted via `jids`). */
|
|
91
|
+
export class StatusScheduler extends BaseTimedPoster {
|
|
92
|
+
schedule(content, when, { jids = [], repeatMs, maxRepeats } = {}) {
|
|
93
|
+
return this._schedule(() => StatusHelper.send(this.sock, content, jids), when, { repeatMs, maxRepeats });
|
|
94
|
+
}
|
|
95
|
+
scheduleIn(content, delayMs, opts = {}) {
|
|
96
|
+
return this.schedule(content, Date.now() + Number(delayMs), opts);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
/** Schedule channel/newsletter posts. */
|
|
100
|
+
export class ChannelScheduler extends BaseTimedPoster {
|
|
101
|
+
schedule(channelJid, content, when, { repeatMs, maxRepeats } = {}) {
|
|
102
|
+
if (typeof channelJid !== 'string' || !channelJid.endsWith('@newsletter')) {
|
|
103
|
+
throw new Boom('ChannelScheduler.schedule needs a channel JID (@newsletter)', { statusCode: 400 });
|
|
104
|
+
}
|
|
105
|
+
return this._schedule(() => this.sock.sendMessage(channelJid, content), when, { repeatMs, maxRepeats });
|
|
106
|
+
}
|
|
107
|
+
scheduleIn(channelJid, content, delayMs, opts = {}) {
|
|
108
|
+
return this.schedule(channelJid, content, Date.now() + Number(delayMs), opts);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import type { WAMessage, AnyMessageContent } from '../Types/index.js';
|
|
2
|
+
export interface SchedulerOptions {
|
|
3
|
+
maxQueue?: number;
|
|
4
|
+
checkInterval?: number;
|
|
5
|
+
onSent?: (scheduled: ScheduledMessage, message?: WAMessage) => void;
|
|
6
|
+
onFailed?: (scheduled: ScheduledMessage, error: Error) => void;
|
|
7
|
+
}
|
|
8
|
+
export type ScheduledMessageStatus = 'pending' | 'sent' | 'failed' | 'cancelled';
|
|
9
|
+
export interface RepeatOptions {
|
|
10
|
+
repeatIntervalMs?: number;
|
|
11
|
+
maxRepeats?: number;
|
|
12
|
+
}
|
|
13
|
+
export interface ScheduledMessage {
|
|
14
|
+
id: string;
|
|
15
|
+
jid: string;
|
|
16
|
+
content: AnyMessageContent;
|
|
17
|
+
scheduledTime: Date;
|
|
18
|
+
createdAt: Date;
|
|
19
|
+
status: ScheduledMessageStatus;
|
|
20
|
+
messageId?: string;
|
|
21
|
+
error?: string;
|
|
22
|
+
repeatIntervalMs?: number;
|
|
23
|
+
maxRepeats?: number;
|
|
24
|
+
repeatCount?: number;
|
|
25
|
+
}
|
|
26
|
+
export declare class MessageScheduler {
|
|
27
|
+
private queue;
|
|
28
|
+
private timer;
|
|
29
|
+
private sendMessage;
|
|
30
|
+
private options;
|
|
31
|
+
constructor(sendMessage: (jid: string, content: AnyMessageContent) => Promise<WAMessage | undefined>, options?: SchedulerOptions);
|
|
32
|
+
schedule(jid: string, content: AnyMessageContent, scheduledTime: Date, repeatOptions?: RepeatOptions): ScheduledMessage;
|
|
33
|
+
scheduleDelay(jid: string, content: AnyMessageContent, delayMs: number, repeatOptions?: RepeatOptions): ScheduledMessage;
|
|
34
|
+
cancel(id: string): boolean;
|
|
35
|
+
cancelForJid(jid: string): number;
|
|
36
|
+
getPending(): ScheduledMessage[];
|
|
37
|
+
get(id: string): ScheduledMessage | undefined;
|
|
38
|
+
clearAll(): number;
|
|
39
|
+
stop(): void;
|
|
40
|
+
start(): void;
|
|
41
|
+
}
|
|
42
|
+
export declare const createMessageScheduler: (sendMessage: (jid: string, content: AnyMessageContent) => Promise<WAMessage | undefined>, options?: SchedulerOptions) => MessageScheduler;
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* JAP@Add --- part of the @japofc/baileys utils (scheduling.ts) + message-scheduler.ts.
|
|
3
|
+
* These were originally two separate, overlapping schedulers (one class-based
|
|
4
|
+
* with polling, one function-based with setTimeout + repeat support). Merged here into
|
|
5
|
+
* a single class-based scheduler so multiple independent instances can be bound to
|
|
6
|
+
* different sendMessage functions (e.g. multi-session bots), while keeping the
|
|
7
|
+
* repeat-interval/maxRepeats feature from the function-based version.
|
|
8
|
+
*/
|
|
9
|
+
export class MessageScheduler {
|
|
10
|
+
queue = new Map();
|
|
11
|
+
timer = null;
|
|
12
|
+
sendMessage;
|
|
13
|
+
options;
|
|
14
|
+
constructor(sendMessage, options = {}) {
|
|
15
|
+
this.sendMessage = sendMessage;
|
|
16
|
+
this.options = {
|
|
17
|
+
maxQueue: options.maxQueue ?? 1000,
|
|
18
|
+
checkInterval: options.checkInterval ?? 1000,
|
|
19
|
+
onSent: options.onSent ?? (() => { }),
|
|
20
|
+
onFailed: options.onFailed ?? (() => { })
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
generateId() {
|
|
24
|
+
return `sched_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Schedule a message for a specific Date. Pass `repeatIntervalMs` to
|
|
28
|
+
* re-queue the job that many ms after each send (optionally capped by
|
|
29
|
+
* `maxRepeats`).
|
|
30
|
+
*/
|
|
31
|
+
schedule(jid, content, scheduledTime, repeatOptions) {
|
|
32
|
+
if (this.queue.size >= this.options.maxQueue)
|
|
33
|
+
throw new Error(`Maximum queue size (${this.options.maxQueue}) reached`);
|
|
34
|
+
if (scheduledTime.getTime() <= Date.now())
|
|
35
|
+
throw new Error('Scheduled time must be in the future');
|
|
36
|
+
const scheduled = {
|
|
37
|
+
id: this.generateId(),
|
|
38
|
+
jid,
|
|
39
|
+
content,
|
|
40
|
+
scheduledTime,
|
|
41
|
+
createdAt: new Date(),
|
|
42
|
+
status: 'pending',
|
|
43
|
+
repeatIntervalMs: repeatOptions?.repeatIntervalMs,
|
|
44
|
+
maxRepeats: repeatOptions?.maxRepeats,
|
|
45
|
+
repeatCount: 0
|
|
46
|
+
};
|
|
47
|
+
this.queue.set(scheduled.id, scheduled);
|
|
48
|
+
this.ensureTimerRunning();
|
|
49
|
+
return scheduled;
|
|
50
|
+
}
|
|
51
|
+
scheduleDelay(jid, content, delayMs, repeatOptions) {
|
|
52
|
+
return this.schedule(jid, content, new Date(Date.now() + delayMs), repeatOptions);
|
|
53
|
+
}
|
|
54
|
+
cancel(id) {
|
|
55
|
+
const s = this.queue.get(id);
|
|
56
|
+
if (s?.status === 'pending') {
|
|
57
|
+
s.status = 'cancelled';
|
|
58
|
+
this.queue.delete(id);
|
|
59
|
+
return true;
|
|
60
|
+
}
|
|
61
|
+
return false;
|
|
62
|
+
}
|
|
63
|
+
cancelForJid(jid) {
|
|
64
|
+
let cancelled = 0;
|
|
65
|
+
for (const [id, s] of this.queue) {
|
|
66
|
+
if (s.jid === jid && s.status === 'pending') {
|
|
67
|
+
s.status = 'cancelled';
|
|
68
|
+
this.queue.delete(id);
|
|
69
|
+
cancelled++;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
return cancelled;
|
|
73
|
+
}
|
|
74
|
+
getPending() {
|
|
75
|
+
return Array.from(this.queue.values()).filter((s) => s.status === 'pending');
|
|
76
|
+
}
|
|
77
|
+
get(id) {
|
|
78
|
+
return this.queue.get(id);
|
|
79
|
+
}
|
|
80
|
+
clearAll() {
|
|
81
|
+
const count = this.queue.size;
|
|
82
|
+
this.queue.clear();
|
|
83
|
+
this.stopTimer();
|
|
84
|
+
return count;
|
|
85
|
+
}
|
|
86
|
+
async processQueue() {
|
|
87
|
+
const now = Date.now();
|
|
88
|
+
for (const [id, s] of this.queue) {
|
|
89
|
+
if (s.status !== 'pending')
|
|
90
|
+
continue;
|
|
91
|
+
if (s.scheduledTime.getTime() > now)
|
|
92
|
+
continue;
|
|
93
|
+
try {
|
|
94
|
+
const message = await this.sendMessage(s.jid, s.content);
|
|
95
|
+
s.messageId = message?.key?.id ?? undefined;
|
|
96
|
+
this.options.onSent(s, message);
|
|
97
|
+
// Handle repeating jobs — re-arm instead of removing from the queue.
|
|
98
|
+
if (s.repeatIntervalMs && s.repeatIntervalMs > 0) {
|
|
99
|
+
const nextCount = (s.repeatCount ?? 0) + 1;
|
|
100
|
+
if (s.maxRepeats === undefined || nextCount < s.maxRepeats) {
|
|
101
|
+
s.repeatCount = nextCount;
|
|
102
|
+
s.scheduledTime = new Date(Date.now() + s.repeatIntervalMs);
|
|
103
|
+
s.status = 'pending';
|
|
104
|
+
continue;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
s.status = 'sent';
|
|
108
|
+
}
|
|
109
|
+
catch (error) {
|
|
110
|
+
s.status = 'failed';
|
|
111
|
+
s.error = error?.message || String(error);
|
|
112
|
+
this.options.onFailed(s, error);
|
|
113
|
+
}
|
|
114
|
+
this.queue.delete(id);
|
|
115
|
+
}
|
|
116
|
+
if (this.queue.size === 0)
|
|
117
|
+
this.stopTimer();
|
|
118
|
+
}
|
|
119
|
+
ensureTimerRunning() {
|
|
120
|
+
if (!this.timer) {
|
|
121
|
+
this.timer = setInterval(() => this.processQueue(), this.options.checkInterval);
|
|
122
|
+
this.timer?.unref?.();
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
stopTimer() {
|
|
126
|
+
if (this.timer) {
|
|
127
|
+
clearInterval(this.timer);
|
|
128
|
+
this.timer = null;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
stop() {
|
|
132
|
+
this.stopTimer();
|
|
133
|
+
}
|
|
134
|
+
start() {
|
|
135
|
+
if (this.queue.size > 0)
|
|
136
|
+
this.ensureTimerRunning();
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
export const createMessageScheduler = (sendMessage, options) => new MessageScheduler(sendMessage, options);
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
export function createSignalIdentity(wid: any, accountSignatureKey: any): {
|
|
2
|
+
identifier: {
|
|
3
|
+
name: any;
|
|
4
|
+
deviceId: number;
|
|
5
|
+
};
|
|
6
|
+
identifierKey: any;
|
|
7
|
+
};
|
|
8
|
+
export function getPreKeys({ get }: {
|
|
9
|
+
get: any;
|
|
10
|
+
}, min: any, limit: any): Promise<any>;
|
|
11
|
+
export function generateOrGetPreKeys(creds: any, range: any): {
|
|
12
|
+
newPreKeys: {};
|
|
13
|
+
lastPreKeyId: number;
|
|
14
|
+
preKeysRange: any[];
|
|
15
|
+
};
|
|
16
|
+
export function xmppSignedPreKey(key: any): {
|
|
17
|
+
tag: string;
|
|
18
|
+
attrs: {};
|
|
19
|
+
content: {
|
|
20
|
+
tag: string;
|
|
21
|
+
attrs: {};
|
|
22
|
+
content: any;
|
|
23
|
+
}[];
|
|
24
|
+
};
|
|
25
|
+
export function xmppPreKey(pair: any, id: any): {
|
|
26
|
+
tag: string;
|
|
27
|
+
attrs: {};
|
|
28
|
+
content: {
|
|
29
|
+
tag: string;
|
|
30
|
+
attrs: {};
|
|
31
|
+
content: any;
|
|
32
|
+
}[];
|
|
33
|
+
};
|
|
34
|
+
export function extractE2ESessionFromRetryReceipt(receipt: any): {
|
|
35
|
+
registrationId: number | undefined;
|
|
36
|
+
identityKey: any;
|
|
37
|
+
signedPreKey: {
|
|
38
|
+
keyId: number | undefined;
|
|
39
|
+
publicKey: any;
|
|
40
|
+
signature: any;
|
|
41
|
+
};
|
|
42
|
+
preKey: {
|
|
43
|
+
keyId: number | undefined;
|
|
44
|
+
publicKey: any;
|
|
45
|
+
} | undefined;
|
|
46
|
+
} | null;
|
|
47
|
+
export function parseAndInjectE2ESessions(node: any, repository: any): Promise<void>;
|
|
48
|
+
export function extractDeviceJids(result: any, myJid: any, myLid: any, excludeZeroDevices: any): {
|
|
49
|
+
user: any;
|
|
50
|
+
device: any;
|
|
51
|
+
domainType: any;
|
|
52
|
+
server: any;
|
|
53
|
+
}[];
|
|
54
|
+
export function getNextPreKeys({ creds, keys }: {
|
|
55
|
+
creds: any;
|
|
56
|
+
keys: any;
|
|
57
|
+
}, count: any): Promise<{
|
|
58
|
+
update: {
|
|
59
|
+
nextPreKeyId: number;
|
|
60
|
+
firstUnuploadedPreKeyId: number;
|
|
61
|
+
};
|
|
62
|
+
preKeys: any;
|
|
63
|
+
}>;
|
|
64
|
+
export function getNextPreKeysNode(state: any, count: any): Promise<{
|
|
65
|
+
update: {
|
|
66
|
+
nextPreKeyId: number;
|
|
67
|
+
firstUnuploadedPreKeyId: number;
|
|
68
|
+
};
|
|
69
|
+
node: {
|
|
70
|
+
tag: string;
|
|
71
|
+
attrs: {
|
|
72
|
+
xmlns: string;
|
|
73
|
+
type: string;
|
|
74
|
+
to: string;
|
|
75
|
+
};
|
|
76
|
+
content: {
|
|
77
|
+
tag: string;
|
|
78
|
+
attrs: {};
|
|
79
|
+
content: any;
|
|
80
|
+
}[];
|
|
81
|
+
};
|
|
82
|
+
}>;
|
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
import { KEY_BUNDLE_TYPE } from '../Defaults/index.js';
|
|
2
|
+
import { assertNodeErrorFree, getBinaryNodeChild, getBinaryNodeChildBuffer, getBinaryNodeChildren, getBinaryNodeChildUInt, getServerFromDomainType, jidDecode, S_WHATSAPP_NET, WAJIDDomains } from '../WABinary/index.js';
|
|
3
|
+
import { Curve, generateSignalPubKey } from './crypto.js';
|
|
4
|
+
import { encodeBigEndian } from './generics.js';
|
|
5
|
+
function chunk(array, size) {
|
|
6
|
+
const chunks = [];
|
|
7
|
+
for (let i = 0; i < array.length; i += size) {
|
|
8
|
+
chunks.push(array.slice(i, i + size));
|
|
9
|
+
}
|
|
10
|
+
return chunks;
|
|
11
|
+
}
|
|
12
|
+
export const createSignalIdentity = (wid, accountSignatureKey) => {
|
|
13
|
+
return {
|
|
14
|
+
identifier: { name: wid, deviceId: 0 },
|
|
15
|
+
identifierKey: generateSignalPubKey(accountSignatureKey)
|
|
16
|
+
};
|
|
17
|
+
};
|
|
18
|
+
export const getPreKeys = async ({ get }, min, limit) => {
|
|
19
|
+
const idList = [];
|
|
20
|
+
for (let id = min; id < limit; id++) {
|
|
21
|
+
idList.push(id.toString());
|
|
22
|
+
}
|
|
23
|
+
return get('pre-key', idList);
|
|
24
|
+
};
|
|
25
|
+
export const generateOrGetPreKeys = (creds, range) => {
|
|
26
|
+
const avaliable = creds.nextPreKeyId - creds.firstUnuploadedPreKeyId;
|
|
27
|
+
const remaining = range - avaliable;
|
|
28
|
+
const lastPreKeyId = creds.nextPreKeyId + remaining - 1;
|
|
29
|
+
const newPreKeys = {};
|
|
30
|
+
if (remaining > 0) {
|
|
31
|
+
for (let i = creds.nextPreKeyId; i <= lastPreKeyId; i++) {
|
|
32
|
+
newPreKeys[i] = Curve.generateKeyPair();
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
return {
|
|
36
|
+
newPreKeys,
|
|
37
|
+
lastPreKeyId,
|
|
38
|
+
preKeysRange: [creds.firstUnuploadedPreKeyId, range]
|
|
39
|
+
};
|
|
40
|
+
};
|
|
41
|
+
export const xmppSignedPreKey = (key) => ({
|
|
42
|
+
tag: 'skey',
|
|
43
|
+
attrs: {},
|
|
44
|
+
content: [
|
|
45
|
+
{ tag: 'id', attrs: {}, content: encodeBigEndian(key.keyId, 3) },
|
|
46
|
+
{ tag: 'value', attrs: {}, content: key.keyPair.public },
|
|
47
|
+
{ tag: 'signature', attrs: {}, content: key.signature }
|
|
48
|
+
]
|
|
49
|
+
});
|
|
50
|
+
export const xmppPreKey = (pair, id) => ({
|
|
51
|
+
tag: 'key',
|
|
52
|
+
attrs: {},
|
|
53
|
+
content: [
|
|
54
|
+
{ tag: 'id', attrs: {}, content: encodeBigEndian(id, 3) },
|
|
55
|
+
{ tag: 'value', attrs: {}, content: pair.public }
|
|
56
|
+
]
|
|
57
|
+
});
|
|
58
|
+
const isValidUInt = (n) => typeof n === 'number' && Number.isInteger(n);
|
|
59
|
+
export const extractE2ESessionFromRetryReceipt = (receipt) => {
|
|
60
|
+
const keysNode = getBinaryNodeChild(receipt, 'keys');
|
|
61
|
+
if (!keysNode)
|
|
62
|
+
return null;
|
|
63
|
+
const typeBuf = getBinaryNodeChildBuffer(keysNode, 'type');
|
|
64
|
+
if (!typeBuf || typeBuf.length !== 1 || typeBuf[0] !== KEY_BUNDLE_TYPE[0])
|
|
65
|
+
return null;
|
|
66
|
+
const identity = getBinaryNodeChildBuffer(keysNode, 'identity');
|
|
67
|
+
const skey = getBinaryNodeChild(keysNode, 'skey');
|
|
68
|
+
if (!identity || identity.length !== 32 || !skey)
|
|
69
|
+
return null;
|
|
70
|
+
const registrationId = getBinaryNodeChildUInt(receipt, 'registration', 4);
|
|
71
|
+
if (!isValidUInt(registrationId))
|
|
72
|
+
return null;
|
|
73
|
+
const signedPubKey = getBinaryNodeChildBuffer(skey, 'value');
|
|
74
|
+
const signedSig = getBinaryNodeChildBuffer(skey, 'signature');
|
|
75
|
+
const signedKeyId = getBinaryNodeChildUInt(skey, 'id', 3);
|
|
76
|
+
if (!signedPubKey || signedPubKey.length !== 32 || !signedSig || !isValidUInt(signedKeyId)) {
|
|
77
|
+
return null;
|
|
78
|
+
}
|
|
79
|
+
const preKeyNode = getBinaryNodeChild(keysNode, 'key');
|
|
80
|
+
let preKey;
|
|
81
|
+
if (preKeyNode) {
|
|
82
|
+
const preKeyPub = getBinaryNodeChildBuffer(preKeyNode, 'value');
|
|
83
|
+
const preKeyId = getBinaryNodeChildUInt(preKeyNode, 'id', 3);
|
|
84
|
+
if (!preKeyPub || preKeyPub.length !== 32 || !isValidUInt(preKeyId)) {
|
|
85
|
+
return null;
|
|
86
|
+
}
|
|
87
|
+
preKey = { keyId: preKeyId, publicKey: generateSignalPubKey(preKeyPub) };
|
|
88
|
+
}
|
|
89
|
+
return {
|
|
90
|
+
registrationId,
|
|
91
|
+
identityKey: generateSignalPubKey(identity),
|
|
92
|
+
signedPreKey: {
|
|
93
|
+
keyId: signedKeyId,
|
|
94
|
+
publicKey: generateSignalPubKey(signedPubKey),
|
|
95
|
+
signature: signedSig
|
|
96
|
+
},
|
|
97
|
+
preKey
|
|
98
|
+
};
|
|
99
|
+
};
|
|
100
|
+
export const parseAndInjectE2ESessions = async (node, repository) => {
|
|
101
|
+
const extractKey = (key) => key
|
|
102
|
+
? {
|
|
103
|
+
keyId: getBinaryNodeChildUInt(key, 'id', 3),
|
|
104
|
+
publicKey: generateSignalPubKey(getBinaryNodeChildBuffer(key, 'value')),
|
|
105
|
+
signature: getBinaryNodeChildBuffer(key, 'signature')
|
|
106
|
+
}
|
|
107
|
+
: undefined;
|
|
108
|
+
const nodes = getBinaryNodeChildren(getBinaryNodeChild(node, 'list'), 'user');
|
|
109
|
+
for (const node of nodes) {
|
|
110
|
+
assertNodeErrorFree(node);
|
|
111
|
+
}
|
|
112
|
+
// Most of the work in repository.injectE2ESession is CPU intensive, not IO
|
|
113
|
+
// So Promise.all doesn't really help here,
|
|
114
|
+
// but blocks even loop if we're using it inside keys.transaction, and it makes it "sync" actually
|
|
115
|
+
// This way we chunk it in smaller parts and between those parts we can yield to the event loop
|
|
116
|
+
// It's rare case when you need to E2E sessions for so many users, but it's possible
|
|
117
|
+
const chunkSize = 100;
|
|
118
|
+
const chunks = chunk(nodes, chunkSize);
|
|
119
|
+
for (const nodesChunk of chunks) {
|
|
120
|
+
for (const node of nodesChunk) {
|
|
121
|
+
const signedKey = getBinaryNodeChild(node, 'skey');
|
|
122
|
+
const key = getBinaryNodeChild(node, 'key');
|
|
123
|
+
const identity = getBinaryNodeChildBuffer(node, 'identity');
|
|
124
|
+
const jid = node.attrs.jid;
|
|
125
|
+
const registrationId = getBinaryNodeChildUInt(node, 'registration', 4);
|
|
126
|
+
await repository.injectE2ESession({
|
|
127
|
+
jid,
|
|
128
|
+
session: {
|
|
129
|
+
registrationId: registrationId,
|
|
130
|
+
identityKey: generateSignalPubKey(identity),
|
|
131
|
+
signedPreKey: extractKey(signedKey),
|
|
132
|
+
preKey: extractKey(key)
|
|
133
|
+
}
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
};
|
|
138
|
+
export const extractDeviceJids = (result, myJid, myLid, excludeZeroDevices) => {
|
|
139
|
+
const { user: myUser, device: myDevice } = jidDecode(myJid);
|
|
140
|
+
const extracted = [];
|
|
141
|
+
for (const userResult of result) {
|
|
142
|
+
const { devices, id } = userResult;
|
|
143
|
+
const decoded = jidDecode(id), { user, server } = decoded;
|
|
144
|
+
let { domainType } = decoded;
|
|
145
|
+
const deviceList = devices?.deviceList;
|
|
146
|
+
if (!Array.isArray(deviceList))
|
|
147
|
+
continue;
|
|
148
|
+
for (const { id: device, keyIndex, isHosted } of deviceList) {
|
|
149
|
+
if ((!excludeZeroDevices || device !== 0) && // if zero devices are not-excluded, or device is non zero
|
|
150
|
+
((myUser !== user && myLid !== user) || myDevice !== device) && // either different user or if me user, not this device
|
|
151
|
+
(device === 0 || !!keyIndex) // ensure that "key-index" is specified for "non-zero" devices, produces a bad req otherwise
|
|
152
|
+
) {
|
|
153
|
+
if (isHosted) {
|
|
154
|
+
domainType = domainType === WAJIDDomains.LID ? WAJIDDomains.HOSTED_LID : WAJIDDomains.HOSTED;
|
|
155
|
+
}
|
|
156
|
+
extracted.push({
|
|
157
|
+
user,
|
|
158
|
+
device,
|
|
159
|
+
domainType,
|
|
160
|
+
server: getServerFromDomainType(server, domainType)
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
return extracted;
|
|
166
|
+
};
|
|
167
|
+
/**
|
|
168
|
+
* get the next N keys for upload or processing
|
|
169
|
+
* @param count number of pre-keys to get or generate
|
|
170
|
+
*/
|
|
171
|
+
export const getNextPreKeys = async ({ creds, keys }, count) => {
|
|
172
|
+
const { newPreKeys, lastPreKeyId, preKeysRange } = generateOrGetPreKeys(creds, count);
|
|
173
|
+
const update = {
|
|
174
|
+
nextPreKeyId: Math.max(lastPreKeyId + 1, creds.nextPreKeyId),
|
|
175
|
+
firstUnuploadedPreKeyId: Math.max(creds.firstUnuploadedPreKeyId, lastPreKeyId + 1)
|
|
176
|
+
};
|
|
177
|
+
await keys.set({ 'pre-key': newPreKeys });
|
|
178
|
+
const preKeys = await getPreKeys(keys, preKeysRange[0], preKeysRange[0] + preKeysRange[1]);
|
|
179
|
+
return { update, preKeys };
|
|
180
|
+
};
|
|
181
|
+
export const getNextPreKeysNode = async (state, count) => {
|
|
182
|
+
const { creds } = state;
|
|
183
|
+
const { update, preKeys } = await getNextPreKeys(state, count);
|
|
184
|
+
const node = {
|
|
185
|
+
tag: 'iq',
|
|
186
|
+
attrs: {
|
|
187
|
+
xmlns: 'encrypt',
|
|
188
|
+
type: 'set',
|
|
189
|
+
to: S_WHATSAPP_NET
|
|
190
|
+
},
|
|
191
|
+
content: [
|
|
192
|
+
{ tag: 'registration', attrs: {}, content: encodeBigEndian(creds.registrationId) },
|
|
193
|
+
{ tag: 'type', attrs: {}, content: KEY_BUNDLE_TYPE },
|
|
194
|
+
{ tag: 'identity', attrs: {}, content: creds.signedIdentityKey.public },
|
|
195
|
+
{ tag: 'list', attrs: {}, content: Object.keys(preKeys).map(k => xmppPreKey(preKeys[+k], +k)) },
|
|
196
|
+
xmppSignedPreKey(creds.signedPreKey)
|
|
197
|
+
]
|
|
198
|
+
};
|
|
199
|
+
return { update, node };
|
|
200
|
+
};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Builds an ACK stanza for a received node.
|
|
3
|
+
* Pure function -- no I/O, no side effects.
|
|
4
|
+
*
|
|
5
|
+
* Mirrors WhatsApp Web's ACK construction:
|
|
6
|
+
* - WAWebHandleMsgSendAck.sendAck / sendNack
|
|
7
|
+
* - WAWebCreateNackFromStanza.createNackFromStanza
|
|
8
|
+
*/
|
|
9
|
+
export function buildAckStanza(node: any, errorCode: any, meId: any): {
|
|
10
|
+
tag: string;
|
|
11
|
+
attrs: {
|
|
12
|
+
id: any;
|
|
13
|
+
to: any;
|
|
14
|
+
class: any;
|
|
15
|
+
};
|
|
16
|
+
};
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Builds an ACK stanza for a received node.
|
|
3
|
+
* Pure function -- no I/O, no side effects.
|
|
4
|
+
*
|
|
5
|
+
* Mirrors WhatsApp Web's ACK construction:
|
|
6
|
+
* - WAWebHandleMsgSendAck.sendAck / sendNack
|
|
7
|
+
* - WAWebCreateNackFromStanza.createNackFromStanza
|
|
8
|
+
*/
|
|
9
|
+
export function buildAckStanza(node, errorCode, meId) {
|
|
10
|
+
const { tag, attrs } = node;
|
|
11
|
+
const stanza = {
|
|
12
|
+
tag: 'ack',
|
|
13
|
+
attrs: {
|
|
14
|
+
id: attrs.id,
|
|
15
|
+
to: attrs.from,
|
|
16
|
+
class: tag
|
|
17
|
+
}
|
|
18
|
+
};
|
|
19
|
+
if (errorCode) {
|
|
20
|
+
stanza.attrs.error = errorCode.toString();
|
|
21
|
+
}
|
|
22
|
+
if (attrs.participant) {
|
|
23
|
+
stanza.attrs.participant = attrs.participant;
|
|
24
|
+
}
|
|
25
|
+
if (attrs.recipient) {
|
|
26
|
+
stanza.attrs.recipient = attrs.recipient;
|
|
27
|
+
}
|
|
28
|
+
// WA Web always includes type when present: `n.type || DROP_ATTR`
|
|
29
|
+
if (attrs.type) {
|
|
30
|
+
stanza.attrs.type = attrs.type;
|
|
31
|
+
}
|
|
32
|
+
// WA Web WAWebHandleMsgSendAck.sendAck/sendNack always include `from` for message-class ACKs
|
|
33
|
+
if (tag === 'message' && meId) {
|
|
34
|
+
stanza.attrs.from = meId;
|
|
35
|
+
}
|
|
36
|
+
return stanza;
|
|
37
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import type { AnyMessageContent } from '../Types/index.js';
|
|
2
|
+
import type makeWASocket from '../Socket/index.js';
|
|
3
|
+
type WASocket = ReturnType<typeof makeWASocket>;
|
|
4
|
+
export declare const STATUS_BROADCAST_JID = "status@broadcast";
|
|
5
|
+
export declare const STATUS_BACKGROUNDS: {
|
|
6
|
+
solid: Record<string, string>;
|
|
7
|
+
gradient: Record<string, string[]>;
|
|
8
|
+
};
|
|
9
|
+
export declare const STATUS_FONTS: {
|
|
10
|
+
readonly SANS_SERIF: 0;
|
|
11
|
+
readonly SERIF: 1;
|
|
12
|
+
readonly NORICAN: 2;
|
|
13
|
+
readonly BRYNDAN: 3;
|
|
14
|
+
readonly BEBASNEUE: 4;
|
|
15
|
+
readonly OSWALD: 5;
|
|
16
|
+
readonly DAMION: 6;
|
|
17
|
+
readonly DANCING: 7;
|
|
18
|
+
readonly COMFORTAA: 8;
|
|
19
|
+
readonly EXOTWO: 9;
|
|
20
|
+
};
|
|
21
|
+
export type StatusFont = (typeof STATUS_FONTS)[keyof typeof STATUS_FONTS];
|
|
22
|
+
export declare const generateStatusMessageId: () => string;
|
|
23
|
+
export type TextStatusOptions = {
|
|
24
|
+
text: string;
|
|
25
|
+
backgroundColor?: string;
|
|
26
|
+
font?: StatusFont;
|
|
27
|
+
textColor?: string;
|
|
28
|
+
mentions?: string[];
|
|
29
|
+
};
|
|
30
|
+
export type MediaStatusOptions = {
|
|
31
|
+
caption?: string;
|
|
32
|
+
gifPlayback?: boolean;
|
|
33
|
+
waveform?: Uint8Array;
|
|
34
|
+
};
|
|
35
|
+
export declare const createTextStatus: (options: TextStatusOptions) => AnyMessageContent;
|
|
36
|
+
export declare const createImageStatus: (media: Buffer | string, options?: MediaStatusOptions) => AnyMessageContent;
|
|
37
|
+
export declare const createVideoStatus: (media: Buffer | string, options?: MediaStatusOptions) => AnyMessageContent;
|
|
38
|
+
export declare const createAudioStatus: (media: Buffer | string, options?: MediaStatusOptions) => AnyMessageContent;
|
|
39
|
+
export declare const getStatusJid: () => string;
|
|
40
|
+
export declare const StatusHelper: {
|
|
41
|
+
text: (text: string, backgroundColor?: string, font?: StatusFont) => AnyMessageContent;
|
|
42
|
+
image: (buffer: Buffer, caption?: string) => AnyMessageContent;
|
|
43
|
+
imageUrl: (url: string, caption?: string) => AnyMessageContent;
|
|
44
|
+
video: (buffer: Buffer, caption?: string) => AnyMessageContent;
|
|
45
|
+
videoUrl: (url: string, caption?: string) => AnyMessageContent;
|
|
46
|
+
gif: (buffer: Buffer, caption?: string) => AnyMessageContent;
|
|
47
|
+
voiceNote: (buffer: Buffer) => AnyMessageContent;
|
|
48
|
+
send: (sock: WASocket, content: AnyMessageContent, jidList?: string[]) => Promise<any>;
|
|
49
|
+
};
|
|
50
|
+
export {};
|