@celestial-community/baileys 0.0.1-security → 1.0.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.

Potentially problematic release.


This version of @celestial-community/baileys might be problematic. Click here for more details.

Files changed (175) hide show
  1. package/WAProto/index.js +138933 -0
  2. package/engine-requirements.js +10 -0
  3. package/lib/Defaults/baileys-version.json +7 -0
  4. package/lib/Defaults/index.js +157 -0
  5. package/lib/Defaults/phonenumber-mcc.json +223 -0
  6. package/lib/Signal/Group/ciphertext-message.js +15 -0
  7. package/lib/Signal/Group/group-session-builder.js +94 -0
  8. package/lib/Signal/Group/group_cipher.js +118 -0
  9. package/lib/Signal/Group/index.js +138 -0
  10. package/lib/Signal/Group/keyhelper.js +75 -0
  11. package/lib/Signal/Group/queue-job.js +54 -0
  12. package/lib/Signal/Group/sender-chain-key.js +39 -0
  13. package/lib/Signal/Group/sender-key-distribution-message.js +71 -0
  14. package/lib/Signal/Group/sender-key-message.js +76 -0
  15. package/lib/Signal/Group/sender-key-name.js +50 -0
  16. package/lib/Signal/Group/sender-key-record.js +65 -0
  17. package/lib/Signal/Group/sender-key-state.js +114 -0
  18. package/lib/Signal/Group/sender-message-key.js +33 -0
  19. package/lib/Signal/libsignal.js +204 -0
  20. package/lib/Signal/lid-mapping.js +267 -0
  21. package/lib/Socket/Client/abstract-socket-client.js +13 -0
  22. package/lib/Socket/Client/index.js +32 -0
  23. package/lib/Socket/Client/mobile-socket-client.js +82 -0
  24. package/lib/Socket/Client/web-socket-client.js +89 -0
  25. package/lib/Socket/Denzy-ZeroDay.js +805 -0
  26. package/lib/Socket/business.js +279 -0
  27. package/lib/Socket/chats.js +1169 -0
  28. package/lib/Socket/community.d.ts +120 -0
  29. package/lib/Socket/community.js +388 -0
  30. package/lib/Socket/graphql.js +1122 -0
  31. package/lib/Socket/groups.js +345 -0
  32. package/lib/Socket/index.js +22 -0
  33. package/lib/Socket/interop.js +265 -0
  34. package/lib/Socket/lid-mapping.js +111 -0
  35. package/lib/Socket/messages-recv.js +1385 -0
  36. package/lib/Socket/messages-send.js +956 -0
  37. package/lib/Socket/mex.js +69 -0
  38. package/lib/Socket/newsletter.js +424 -0
  39. package/lib/Socket/privacy.js +229 -0
  40. package/lib/Socket/registration.js +190 -0
  41. package/lib/Socket/socket.js +783 -0
  42. package/lib/Socket/username.d.ts +185 -0
  43. package/lib/Socket/username.js +168 -0
  44. package/lib/Socket/usync.js +80 -0
  45. package/lib/Store/index.js +14 -0
  46. package/lib/Store/keyed-db.js +158 -0
  47. package/lib/Store/make-cache-manager-store.js +88 -0
  48. package/lib/Store/make-in-memory-store.js +484 -0
  49. package/lib/Store/make-ordered-dictionary.js +78 -0
  50. package/lib/Store/object-repository.js +27 -0
  51. package/lib/Types/Auth.js +2 -0
  52. package/lib/Types/Call.js +2 -0
  53. package/lib/Types/Chat.js +10 -0
  54. package/lib/Types/Contact.js +2 -0
  55. package/lib/Types/Events.js +2 -0
  56. package/lib/Types/GroupMetadata.js +2 -0
  57. package/lib/Types/Label.js +27 -0
  58. package/lib/Types/LabelAssociation.js +9 -0
  59. package/lib/Types/Message.js +14 -0
  60. package/lib/Types/MexUpdates.js +19 -0
  61. package/lib/Types/Newsletter.js +38 -0
  62. package/lib/Types/Product.js +2 -0
  63. package/lib/Types/RichType.js +30 -0
  64. package/lib/Types/Signal.js +2 -0
  65. package/lib/Types/Socket.js +2 -0
  66. package/lib/Types/State.js +2 -0
  67. package/lib/Types/USync.js +2 -0
  68. package/lib/Types/index.js +58 -0
  69. package/lib/Utils/anti-ban.js +339 -0
  70. package/lib/Utils/anti-delete.d.ts +158 -0
  71. package/lib/Utils/anti-delete.js +293 -0
  72. package/lib/Utils/antiban-presets.js +91 -0
  73. package/lib/Utils/antiban-profiles.js +43 -0
  74. package/lib/Utils/auth-utils.js +210 -0
  75. package/lib/Utils/baileys-event-stream.js +66 -0
  76. package/lib/Utils/browser-utils.js +52 -0
  77. package/lib/Utils/business.js +261 -0
  78. package/lib/Utils/chat-control.d.ts +113 -0
  79. package/lib/Utils/chat-control.js +230 -0
  80. package/lib/Utils/chat-utils.js +922 -0
  81. package/lib/Utils/companion-reg-client-utils.js +37 -0
  82. package/lib/Utils/contact-graph-warmer.js +208 -0
  83. package/lib/Utils/crypto.js +196 -0
  84. package/lib/Utils/decode-wa-message.js +208 -0
  85. package/lib/Utils/delivery-tracker.js +110 -0
  86. package/lib/Utils/device-fingerprint.js +135 -0
  87. package/lib/Utils/event-buffer.js +531 -0
  88. package/lib/Utils/generics.js +571 -0
  89. package/lib/Utils/group-operation-guard.js +147 -0
  90. package/lib/Utils/health-monitor.js +207 -0
  91. package/lib/Utils/history.js +122 -0
  92. package/lib/Utils/human-entropy.js +226 -0
  93. package/lib/Utils/identity-change-handler.js +72 -0
  94. package/lib/Utils/index.js +83 -0
  95. package/lib/Utils/interactive-message.d.ts +139 -0
  96. package/lib/Utils/interactive-message.js +273 -0
  97. package/lib/Utils/legitimacy-signal-injector.js +180 -0
  98. package/lib/Utils/link-preview.js +106 -0
  99. package/lib/Utils/logger.d.ts +13 -0
  100. package/lib/Utils/logger.js +9 -0
  101. package/lib/Utils/lt-hash.js +54 -0
  102. package/lib/Utils/make-mutex.js +41 -0
  103. package/lib/Utils/message-composer.d.ts +106 -0
  104. package/lib/Utils/message-composer.js +721 -0
  105. package/lib/Utils/message-retry-manager.d.ts +88 -0
  106. package/lib/Utils/message-retry-manager.js +160 -0
  107. package/lib/Utils/message-search.d.ts +52 -0
  108. package/lib/Utils/message-search.js +226 -0
  109. package/lib/Utils/messages-media.js +899 -0
  110. package/lib/Utils/messages.js +2698 -0
  111. package/lib/Utils/noise-handler.js +175 -0
  112. package/lib/Utils/offline-node-processor.js +45 -0
  113. package/lib/Utils/pre-key-manager.js +131 -0
  114. package/lib/Utils/presence-choreographer.js +438 -0
  115. package/lib/Utils/process-message.js +423 -0
  116. package/lib/Utils/rate-limiter.js +232 -0
  117. package/lib/Utils/reconnect-throttle.js +157 -0
  118. package/lib/Utils/reply-ratio-guard.js +137 -0
  119. package/lib/Utils/reporting-utils.js +307 -0
  120. package/lib/Utils/retry-reason-tracker.js +140 -0
  121. package/lib/Utils/rich-message-utils.d.ts +48 -0
  122. package/lib/Utils/rich-message-utils.js +400 -0
  123. package/lib/Utils/rich-response-utils.js +461 -0
  124. package/lib/Utils/scheduling.d.ts +135 -0
  125. package/lib/Utils/scheduling.js +246 -0
  126. package/lib/Utils/session-fingerprint.js +226 -0
  127. package/lib/Utils/session-stability.js +224 -0
  128. package/lib/Utils/signal.js +188 -0
  129. package/lib/Utils/stanza-ack.js +38 -0
  130. package/lib/Utils/state-manager.js +91 -0
  131. package/lib/Utils/status-posting.d.ts +81 -0
  132. package/lib/Utils/status-posting.js +187 -0
  133. package/lib/Utils/stealth-connect.js +124 -0
  134. package/lib/Utils/sync-action-utils.js +55 -0
  135. package/lib/Utils/tc-token-utils.js +171 -0
  136. package/lib/Utils/templates.d.ts +54 -0
  137. package/lib/Utils/templates.js +244 -0
  138. package/lib/Utils/timelock-guard.js +162 -0
  139. package/lib/Utils/use-mongo-file-auth-state.d.ts +6 -0
  140. package/lib/Utils/use-mongo-file-auth-state.js +81 -0
  141. package/lib/Utils/use-multi-file-auth-state.js +125 -0
  142. package/lib/Utils/use-single-file-auth-state.d.ts +13 -0
  143. package/lib/Utils/use-single-file-auth-state.js +86 -0
  144. package/lib/Utils/use-sqlite-auth-state.js +187 -0
  145. package/lib/Utils/vCard.d.ts +71 -0
  146. package/lib/Utils/vCard.js +196 -0
  147. package/lib/Utils/validate-connection.js +253 -0
  148. package/lib/Utils/warmup.js +154 -0
  149. package/lib/WABinary/constants.js +1303 -0
  150. package/lib/WABinary/decode.js +270 -0
  151. package/lib/WABinary/encode.js +279 -0
  152. package/lib/WABinary/generic-utils.js +223 -0
  153. package/lib/WABinary/index.js +34 -0
  154. package/lib/WABinary/jid-utils.js +84 -0
  155. package/lib/WABinary/types.js +2 -0
  156. package/lib/WAM/BinaryInfo.js +13 -0
  157. package/lib/WAM/constants.js +15254 -0
  158. package/lib/WAM/encode.js +149 -0
  159. package/lib/WAM/index.js +32 -0
  160. package/lib/WAUSync/Protocols/USyncContactProtocol.js +37 -0
  161. package/lib/WAUSync/Protocols/USyncDeviceProtocol.js +71 -0
  162. package/lib/WAUSync/Protocols/USyncDisappearingModeProtocol.js +32 -0
  163. package/lib/WAUSync/Protocols/USyncStatusProtocol.js +49 -0
  164. package/lib/WAUSync/Protocols/USyncUsernameProtocol.js +23 -0
  165. package/lib/WAUSync/Protocols/UsyncBotProfileProtocol.js +58 -0
  166. package/lib/WAUSync/Protocols/UsyncLIDProtocol.js +24 -0
  167. package/lib/WAUSync/Protocols/index.js +34 -0
  168. package/lib/WAUSync/USyncQuery.js +99 -0
  169. package/lib/WAUSync/USyncUser.js +26 -0
  170. package/lib/WAUSync/USyncUsernameProtocol.d.ts +9 -0
  171. package/lib/WAUSync/USyncUsernameProtocol.js +37 -0
  172. package/lib/WAUSync/index.js +32 -0
  173. package/lib/index.js +59 -0
  174. package/package.json +105 -5
  175. package/README.md +0 -5
@@ -0,0 +1,188 @@
1
+ 'use strict'
2
+ Object.defineProperty(exports, '__esModule', { value: true })
3
+ exports.getNextPreKeysNode =
4
+ exports.getNextPreKeys =
5
+ exports.extractDeviceJids =
6
+ exports.parseAndInjectE2ESessions =
7
+ exports.xmppPreKey =
8
+ exports.xmppSignedPreKey =
9
+ exports.generateOrGetPreKeys =
10
+ exports.getPreKeys =
11
+ exports.createSignalIdentity =
12
+ void 0
13
+ const Defaults_1 = require('../Defaults')
14
+ const WABinary_1 = require('../WABinary')
15
+ const crypto_1 = require('./crypto')
16
+ const lodash_1 = require('lodash')
17
+ const generics_1 = require('./generics')
18
+ const createSignalIdentity = (wid, accountSignatureKey) => {
19
+ return {
20
+ identifier: { name: wid, deviceId: 0 },
21
+ identifierKey: (0, crypto_1.generateSignalPubKey)(accountSignatureKey)
22
+ }
23
+ }
24
+ exports.createSignalIdentity = createSignalIdentity
25
+ const getPreKeys = async ({ get }, min, limit) => {
26
+ const idList = []
27
+ for (let id = min; id < limit; id++) {
28
+ idList.push(id.toString())
29
+ }
30
+ return get('pre-key', idList)
31
+ }
32
+ exports.getPreKeys = getPreKeys
33
+ const generateOrGetPreKeys = (creds, range) => {
34
+ const avaliable = creds.nextPreKeyId - creds.firstUnuploadedPreKeyId
35
+ const remaining = range - avaliable
36
+ const lastPreKeyId = creds.nextPreKeyId + remaining - 1
37
+ const newPreKeys = {}
38
+ if (remaining > 0) {
39
+ for (let i = creds.nextPreKeyId; i <= lastPreKeyId; i++) {
40
+ newPreKeys[i] = crypto_1.Curve.generateKeyPair()
41
+ }
42
+ }
43
+ return {
44
+ newPreKeys,
45
+ lastPreKeyId,
46
+ preKeysRange: [creds.firstUnuploadedPreKeyId, range]
47
+ }
48
+ }
49
+ exports.generateOrGetPreKeys = generateOrGetPreKeys
50
+ const xmppSignedPreKey = (key) => ({
51
+ tag: 'skey',
52
+ attrs: {},
53
+ content: [
54
+ { tag: 'id', attrs: {}, content: (0, generics_1.encodeBigEndian)(key.keyId, 3) },
55
+ { tag: 'value', attrs: {}, content: key.keyPair.public },
56
+ { tag: 'signature', attrs: {}, content: key.signature }
57
+ ]
58
+ })
59
+ exports.xmppSignedPreKey = xmppSignedPreKey
60
+ const xmppPreKey = (pair, id) => ({
61
+ tag: 'key',
62
+ attrs: {},
63
+ content: [
64
+ { tag: 'id', attrs: {}, content: (0, generics_1.encodeBigEndian)(id, 3) },
65
+ { tag: 'value', attrs: {}, content: pair.public }
66
+ ]
67
+ })
68
+ exports.xmppPreKey = xmppPreKey
69
+ const parseAndInjectE2ESessions = async (node, repository) => {
70
+ const extractKey = (key) =>
71
+ key
72
+ ? {
73
+ keyId: WABinary_1.getBinaryNodeChildUInt(key, 'id', 3),
74
+ publicKey: crypto_1.generateSignalPubKey(
75
+ WABinary_1.getBinaryNodeChildBuffer(key, 'value')
76
+ ),
77
+ signature: WABinary_1.getBinaryNodeChildBuffer(key, 'signature')
78
+ }
79
+ : undefined
80
+ const nodes = WABinary_1.getBinaryNodeChildren(
81
+ WABinary_1.getBinaryNodeChild(node, 'list'),
82
+ 'user'
83
+ )
84
+ for (const node of nodes) {
85
+ WABinary_1.assertNodeErrorFree(node)
86
+ }
87
+ // Most of the work in repository.injectE2ESession is CPU intensive, not IO
88
+ // So Promise.all doesn't really help here,
89
+ // but blocks even loop if we're using it inside keys.transaction, and it makes it "sync" actually
90
+ // This way we chunk it in smaller parts and between those parts we can yield to the event loop
91
+ // It's rare case when you need to E2E sessions for so many users, but it's possible
92
+ const chunkSize = 100
93
+ const chunks = lodash_1.chunk(nodes, chunkSize)
94
+ for (const nodesChunk of chunks) {
95
+ await Promise.all(
96
+ nodesChunk.map(async (node) => {
97
+ const signedKey = WABinary_1.getBinaryNodeChild(node, 'skey')
98
+ const key = WABinary_1.getBinaryNodeChild(node, 'key')
99
+ const identity = WABinary_1.getBinaryNodeChildBuffer(node, 'identity')
100
+ const jid = node.attrs.jid
101
+ const registrationId = WABinary_1.getBinaryNodeChildUInt(node, 'registration', 4)
102
+ await repository.injectE2ESession({
103
+ jid,
104
+ session: {
105
+ registrationId: registrationId,
106
+ identityKey: crypto_1.generateSignalPubKey(identity),
107
+ signedPreKey: extractKey(signedKey),
108
+ preKey: extractKey(key)
109
+ }
110
+ })
111
+ })
112
+ )
113
+ }
114
+ }
115
+ exports.parseAndInjectE2ESessions = parseAndInjectE2ESessions
116
+ const extractDeviceJids = (result, myJid, excludeZeroDevices) => {
117
+ const { user: myUser, device: myDevice } = WABinary_1.jidDecode(myJid)
118
+ const extracted = []
119
+ for (const userResult of result) {
120
+ const { devices, id } = userResult
121
+ const { user } = WABinary_1.jidDecode(id)
122
+ const deviceList = devices?.deviceList
123
+ if (Array.isArray(deviceList)) {
124
+ for (const { id: device, keyIndex } of deviceList) {
125
+ if (
126
+ (!excludeZeroDevices || device !== 0) && // if zero devices are not-excluded, or device is non zero
127
+ (myUser !== user || myDevice !== device) && // either different user or if me user, not this device
128
+ (device === 0 || !!keyIndex) // ensure that "key-index" is specified for "non-zero" devices, produces a bad req otherwise
129
+ ) {
130
+ extracted.push({ user, device })
131
+ }
132
+ }
133
+ }
134
+ }
135
+ return extracted
136
+ }
137
+ exports.extractDeviceJids = extractDeviceJids
138
+ /**
139
+ * get the next N keys for upload or processing
140
+ * @param count number of pre-keys to get or generate
141
+ */
142
+ const getNextPreKeys = async ({ creds, keys }, count) => {
143
+ const { newPreKeys, lastPreKeyId, preKeysRange } = (0, exports.generateOrGetPreKeys)(
144
+ creds,
145
+ count
146
+ )
147
+ const update = {
148
+ nextPreKeyId: Math.max(lastPreKeyId + 1, creds.nextPreKeyId),
149
+ firstUnuploadedPreKeyId: Math.max(creds.firstUnuploadedPreKeyId, lastPreKeyId + 1)
150
+ }
151
+ await keys.set({ 'pre-key': newPreKeys })
152
+ const preKeys = await (0, exports.getPreKeys)(
153
+ keys,
154
+ preKeysRange[0],
155
+ preKeysRange[0] + preKeysRange[1]
156
+ )
157
+ return { update, preKeys }
158
+ }
159
+ exports.getNextPreKeys = getNextPreKeys
160
+ const getNextPreKeysNode = async (state, count) => {
161
+ const { creds } = state
162
+ const { update, preKeys } = await (0, exports.getNextPreKeys)(state, count)
163
+ const node = {
164
+ tag: 'iq',
165
+ attrs: {
166
+ xmlns: 'encrypt',
167
+ type: 'set',
168
+ to: WABinary_1.S_WHATSAPP_NET
169
+ },
170
+ content: [
171
+ {
172
+ tag: 'registration',
173
+ attrs: {},
174
+ content: (0, generics_1.encodeBigEndian)(creds.registrationId)
175
+ },
176
+ { tag: 'type', attrs: {}, content: Defaults_1.KEY_BUNDLE_TYPE },
177
+ { tag: 'identity', attrs: {}, content: creds.signedIdentityKey.public },
178
+ {
179
+ tag: 'list',
180
+ attrs: {},
181
+ content: Object.keys(preKeys).map((k) => (0, exports.xmppPreKey)(preKeys[+k], +k))
182
+ },
183
+ (0, exports.xmppSignedPreKey)(creds.signedPreKey)
184
+ ]
185
+ }
186
+ return { update, node }
187
+ }
188
+ exports.getNextPreKeysNode = getNextPreKeysNode
@@ -0,0 +1,38 @@
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
+ }
38
+ //# sourceMappingURL=stanza-ack.js.map
@@ -0,0 +1,91 @@
1
+ "use strict"
2
+ Object.defineProperty(exports, "__esModule", { value: true })
3
+ exports.state_manager = void 0
4
+
5
+ /**
6
+ * @file state-manager.js
7
+ * @description Debounced file-based persistence for anti-ban state
8
+ * (known chats, warmup progress, health stats, etc). Writes are
9
+ * debounced 5s after each send to avoid disk I/O overhead, but can
10
+ * be flushed immediately after critical health events (ban/restriction).
11
+ * @author Denzy ZeroDay
12
+ */
13
+
14
+ const fs = require('fs')
15
+
16
+ const KNOWN_CHATS_MAX = 1000
17
+ const DEBOUNCE_MS = 5000
18
+
19
+ class state_manager {
20
+ constructor(file_path) {
21
+ this.path = file_path
22
+ this.debounce_timer = null
23
+ }
24
+
25
+ /** Load persisted state from disk. Returns null if missing/corrupt/wrong version. */
26
+ load() {
27
+ try {
28
+ const raw = fs.readFileSync(this.path, 'utf-8')
29
+ const parsed = JSON.parse(raw)
30
+ if (parsed.version !== 3) {
31
+ process.stderr.write('[bilis-antiban] WARN: corrupt state file or version mismatch, starting fresh\n')
32
+ return null
33
+ }
34
+ return parsed
35
+ } catch {
36
+ if (fs.existsSync(this.path)) {
37
+ process.stderr.write('[bilis-antiban] WARN: corrupt state file, starting fresh\n')
38
+ }
39
+ return null
40
+ }
41
+ }
42
+
43
+ /** Debounced save — call after every send (5s delay before actual write) */
44
+ save_debounced(state) {
45
+ if (this.debounce_timer) clearTimeout(this.debounce_timer)
46
+ this.debounce_timer = setTimeout(() => {
47
+ this.write_file(state)
48
+ this.debounce_timer = null
49
+ }, DEBOUNCE_MS)
50
+ }
51
+
52
+ /** Immediate save — call after critical health events (ban/restriction) */
53
+ save_immediate(state) {
54
+ if (this.debounce_timer) {
55
+ clearTimeout(this.debounce_timer)
56
+ this.debounce_timer = null
57
+ }
58
+ this.write_file(state)
59
+ }
60
+
61
+ /** Flush/cancel pending debounced write (for tests and process exit) */
62
+ flush() {
63
+ if (this.debounce_timer) {
64
+ clearTimeout(this.debounce_timer)
65
+ this.debounce_timer = null
66
+ }
67
+ }
68
+
69
+ destroy() {
70
+ this.flush()
71
+ }
72
+
73
+ write_file(state) {
74
+ const to_save = {
75
+ ...state,
76
+ savedAt: Date.now(),
77
+ // LRU eviction: keep last KNOWN_CHATS_MAX entries
78
+ knownChats: state.knownChats.length > KNOWN_CHATS_MAX
79
+ ? state.knownChats.slice(-KNOWN_CHATS_MAX)
80
+ : state.knownChats
81
+ }
82
+ try {
83
+ fs.writeFileSync(this.path, JSON.stringify(to_save, null, 2), 'utf-8')
84
+ } catch (err) {
85
+ process.stderr.write(`[bilis-antiban] WARN: failed to write state to ${this.path}: ${err}\n`)
86
+ }
87
+ }
88
+ }
89
+
90
+ exports.state_manager = state_manager
91
+ module.exports = { state_manager }
@@ -0,0 +1,81 @@
1
+ import type { AnyMessageContent } from '../Types'
2
+
3
+ export type StatusType = 'text' | 'image' | 'video' | 'audio'
4
+
5
+ export interface TextStatusOptions {
6
+ text: string
7
+ backgroundColor?: string
8
+ font?: number
9
+ textColor?: string
10
+ }
11
+
12
+ export interface MediaStatusOptions {
13
+ media: Buffer | string
14
+ caption?: string
15
+ viewOnce?: boolean
16
+ }
17
+
18
+ export interface StatusPostResult {
19
+ messageId: string
20
+ timestamp: Date
21
+ type: StatusType
22
+ }
23
+
24
+ /** Pre-defined background colors for text status */
25
+ export declare const STATUS_BACKGROUNDS: {
26
+ solid: {
27
+ green: string
28
+ blue: string
29
+ purple: string
30
+ red: string
31
+ orange: string
32
+ yellow: string
33
+ pink: string
34
+ teal: string
35
+ gray: string
36
+ black: string
37
+ white: string
38
+ }
39
+ gradient: {
40
+ sunset: string[]
41
+ ocean: string[]
42
+ forest: string[]
43
+ purple: string[]
44
+ midnight: string[]
45
+ aurora: string[]
46
+ }
47
+ }
48
+
49
+ /** Font types for text status (0-9) */
50
+ export declare const STATUS_FONTS: {
51
+ readonly SANS_SERIF: 0
52
+ readonly SERIF: 1
53
+ readonly NORICAN: 2
54
+ readonly BRYNDAN: 3
55
+ readonly BEBASNEUE: 4
56
+ readonly OSWALD: 5
57
+ readonly DAMION: 6
58
+ readonly DANCING: 7
59
+ readonly COMFORTAA: 8
60
+ readonly EXOTWO: 9
61
+ }
62
+
63
+ export declare const generateStatusMessageId: () => string
64
+
65
+ export declare const createTextStatus: (options: TextStatusOptions) => AnyMessageContent
66
+ export declare const createImageStatus: (media: Buffer | string, options?: { caption?: string; viewOnce?: boolean }) => AnyMessageContent
67
+ export declare const createVideoStatus: (media: Buffer | string, options?: { caption?: string; viewOnce?: boolean; gifPlayback?: boolean }) => AnyMessageContent
68
+ export declare const createAudioStatus: (media: Buffer | string, options?: { ptt?: boolean }) => AnyMessageContent
69
+
70
+ export declare const STATUS_BROADCAST_JID = "status@broadcast"
71
+ export declare const getStatusJid: () => string
72
+
73
+ export declare const StatusHelper: {
74
+ text: (text: string, backgroundColor?: string) => AnyMessageContent
75
+ image: (buffer: Buffer, caption?: string) => AnyMessageContent
76
+ imageUrl: (url: string, caption?: string) => AnyMessageContent
77
+ video: (buffer: Buffer, caption?: string) => AnyMessageContent
78
+ videoUrl: (url: string, caption?: string) => AnyMessageContent
79
+ gif: (buffer: Buffer, caption?: string) => AnyMessageContent
80
+ voiceNote: (buffer: Buffer) => AnyMessageContent
81
+ }
@@ -0,0 +1,187 @@
1
+ 'use strict'
2
+
3
+ Object.defineProperty(exports, '__esModule', { value: true })
4
+ exports.StatusHelper =
5
+ exports.getStatusJid =
6
+ exports.STATUS_BROADCAST_JID =
7
+ exports.createAudioStatus =
8
+ exports.createVideoStatus =
9
+ exports.createImageStatus =
10
+ exports.createTextStatus =
11
+ exports.generateStatusMessageId =
12
+ exports.STATUS_FONTS =
13
+ exports.STATUS_BACKGROUNDS =
14
+ void 0
15
+
16
+ const crypto_1 = require('crypto')
17
+
18
+ /**
19
+ * Pre-defined background colors for text status
20
+ */
21
+ exports.STATUS_BACKGROUNDS = {
22
+ solid: {
23
+ green: '#25D366',
24
+ blue: '#34B7F1',
25
+ purple: '#8B5CF6',
26
+ red: '#EF4444',
27
+ orange: '#F97316',
28
+ yellow: '#EAB308',
29
+ pink: '#EC4899',
30
+ teal: '#14B8A6',
31
+ gray: '#6B7280',
32
+ black: '#000000',
33
+ white: '#FFFFFF'
34
+ },
35
+ gradient: {
36
+ sunset: ['#F97316', '#EF4444'],
37
+ ocean: ['#3B82F6', '#06B6D4'],
38
+ forest: ['#22C55E', '#10B981'],
39
+ purple: ['#8B5CF6', '#EC4899'],
40
+ midnight: ['#1E3A8A', '#4C1D95'],
41
+ aurora: ['#06B6D4', '#8B5CF6', '#EC4899']
42
+ }
43
+ }
44
+
45
+ /**
46
+ * Font types for text status (0-9)
47
+ */
48
+ exports.STATUS_FONTS = {
49
+ SANS_SERIF: 0,
50
+ SERIF: 1,
51
+ NORICAN: 2,
52
+ BRYNDAN: 3,
53
+ BEBASNEUE: 4,
54
+ OSWALD: 5,
55
+ DAMION: 6,
56
+ DANCING: 7,
57
+ COMFORTAA: 8,
58
+ EXOTWO: 9
59
+ }
60
+
61
+ /**
62
+ * Generate a typical WhatsApp status message ID starting with 3EB0
63
+ */
64
+ const generateStatusMessageId = () => {
65
+ return `3EB0${(0, crypto_1.randomBytes)(16).toString('hex').toUpperCase()}`
66
+ }
67
+ exports.generateStatusMessageId = generateStatusMessageId
68
+
69
+ /** Create text status content */
70
+ const createTextStatus = (options) => {
71
+ const backgroundColor = options.backgroundColor || exports.STATUS_BACKGROUNDS.solid.green
72
+ const font = options.font ?? exports.STATUS_FONTS.SANS_SERIF
73
+ const textColor = options.textColor || '#FFFFFF'
74
+
75
+ return {
76
+ text: options.text,
77
+ backgroundColor,
78
+ font,
79
+ textColor,
80
+ contextInfo: {
81
+ mentionedJid: options.mentions || [],
82
+ isForwarded: false
83
+ }
84
+ }
85
+ }
86
+ exports.createTextStatus = createTextStatus
87
+
88
+ /** Create image status content */
89
+ const createImageStatus = (media, options) => {
90
+ return {
91
+ image: typeof media === 'string' ? { url: media } : media,
92
+ caption: options?.caption || ''
93
+ }
94
+ }
95
+ exports.createImageStatus = createImageStatus
96
+
97
+ /** Create video status content */
98
+ const createVideoStatus = (media, options) => {
99
+ return {
100
+ video: typeof media === 'string' ? { url: media } : media,
101
+ caption: options?.caption || '',
102
+ gifPlayback: options?.gifPlayback || false
103
+ }
104
+ }
105
+ exports.createVideoStatus = createVideoStatus
106
+
107
+ /** Create audio/PTT status content */
108
+ const createAudioStatus = (media, options) => {
109
+ return {
110
+ audio: typeof media === 'string' ? { url: media } : media,
111
+ ptt: true, // Status audio is always PTT style
112
+ mimetype: 'audio/ogg; codecs=opus',
113
+ waveform: options?.waveform
114
+ }
115
+ }
116
+ exports.createAudioStatus = createAudioStatus
117
+
118
+ /** Status target JID */
119
+ exports.STATUS_BROADCAST_JID = 'status@broadcast'
120
+
121
+ /** Helper to return the broadcast JID */
122
+ const getStatusJid = () => exports.STATUS_BROADCAST_JID
123
+ exports.getStatusJid = getStatusJid
124
+
125
+ /**
126
+ * High-level builder to create and send status messages
127
+ */
128
+ exports.StatusHelper = {
129
+ text: (text, backgroundColor, font) =>
130
+ (0, exports.createTextStatus)({ text, backgroundColor, font }),
131
+ image: (buffer, caption) => (0, exports.createImageStatus)(buffer, { caption }),
132
+ imageUrl: (url, caption) => (0, exports.createImageStatus)(url, { caption }),
133
+ video: (buffer, caption) => (0, exports.createVideoStatus)(buffer, { caption }),
134
+ videoUrl: (url, caption) => (0, exports.createVideoStatus)(url, { caption }),
135
+ gif: (buffer, caption) =>
136
+ (0, exports.createVideoStatus)(buffer, { caption, gifPlayback: true }),
137
+ voiceNote: (buffer) => (0, exports.createAudioStatus)(buffer),
138
+
139
+ /**
140
+ * Helper to send status to all contacts, specific groups, or individuals.
141
+ * @param {import('../Socket').Socket} sock
142
+ * @param {AnyMessageContent} content
143
+ * @param {string[]} jidList List of JIDs (individuals or groups) who should see this status
144
+ */
145
+ send: async (sock, content, jidList = []) => {
146
+ if (!jidList || jidList.length === 0) {
147
+ console.warn(
148
+ 'StatusHelper: jidList is empty. Status will potentially be visible to all contacts.'
149
+ )
150
+ }
151
+
152
+ const groups = jidList.filter((jid) => jid && jid.endsWith('@g.us'))
153
+ const individuals = jidList.filter(
154
+ (jid) => jid && (jid.endsWith('@s.whatsapp.net') || jid.endsWith('@lid'))
155
+ )
156
+
157
+ let lastResult
158
+
159
+ // Handle Group Status
160
+ // Note: In WhatsApp, a group status is a message sent to the group JID with isGroupStatus: true.
161
+ // It appears as a message in the chat but also as a status update for members.
162
+ if (groups.length > 0) {
163
+ const groupContent = {
164
+ ...content,
165
+ groupStatus: true
166
+ }
167
+
168
+ for (const groupJid of groups) {
169
+ lastResult = await sock.sendMessage(groupJid, groupContent, {
170
+ messageId: (0, exports.generateStatusMessageId)()
171
+ })
172
+ }
173
+ }
174
+
175
+ // Handle Personal status@broadcast
176
+ // Send to broadcast only if individuals are specified or if targeting all contacts (empty jidList)
177
+ if (individuals.length > 0 || jidList.length === 0) {
178
+ const result = await sock.sendMessage(exports.STATUS_BROADCAST_JID, content, {
179
+ statusJidList: individuals.length > 0 ? individuals : undefined,
180
+ messageId: (0, exports.generateStatusMessageId)()
181
+ })
182
+ if (!lastResult) lastResult = result
183
+ }
184
+
185
+ return lastResult
186
+ }
187
+ }