gifted-baileys 1.5.6 → 1.5.7

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.
Files changed (252) hide show
  1. package/README.md +9 -0
  2. package/WAProto/WAProto.proto +969 -88
  3. package/WAProto/index.d.ts +13199 -1260
  4. package/WAProto/index.js +124901 -74525
  5. package/lib/Defaults/baileys-version.json +3 -0
  6. package/lib/Defaults/index.d.ts +284 -0
  7. package/{src → lib}/Defaults/index.js +7 -14
  8. package/lib/Signal/libsignal.d.ts +3 -0
  9. package/lib/Signal/libsignal.js +161 -0
  10. package/lib/Socket/Client/abstract-socket-client.d.ts +15 -0
  11. package/lib/Socket/Client/index.d.ts +2 -0
  12. package/{src → lib}/Socket/Client/index.js +2 -3
  13. package/lib/Socket/Client/mobile-socket-client.d.ts +12 -0
  14. package/lib/Socket/Client/mobile-socket-client.js +65 -0
  15. package/lib/Socket/Client/types.d.ts +17 -0
  16. package/lib/Socket/Client/types.js +13 -0
  17. package/lib/Socket/Client/websocket.d.ts +12 -0
  18. package/lib/Socket/Client/websocket.js +62 -0
  19. package/lib/Socket/business.d.ts +170 -0
  20. package/{src → lib}/Socket/business.js +28 -33
  21. package/lib/Socket/chats.d.ts +81 -0
  22. package/{src → lib}/Socket/chats.js +174 -176
  23. package/lib/Socket/groups.d.ts +115 -0
  24. package/{src → lib}/Socket/groups.js +80 -68
  25. package/lib/Socket/index.d.ts +172 -0
  26. package/{src → lib}/Socket/index.js +4 -1
  27. package/lib/Socket/messages-recv.d.ts +158 -0
  28. package/{src → lib}/Socket/messages-recv.js +378 -211
  29. package/lib/Socket/messages-send.d.ts +155 -0
  30. package/{src → lib}/Socket/messages-send.js +452 -177
  31. package/lib/Socket/newsletter.d.ts +132 -0
  32. package/{src → lib}/Socket/newsletter.js +107 -98
  33. package/lib/Socket/registration.d.ts +264 -0
  34. package/{src → lib}/Socket/registration.js +56 -48
  35. package/lib/Socket/socket.d.ts +44 -0
  36. package/{src → lib}/Socket/socket.js +77 -77
  37. package/lib/Socket/usync.d.ts +37 -0
  38. package/lib/Socket/usync.js +70 -0
  39. package/lib/Store/index.d.ts +3 -0
  40. package/lib/Store/make-cache-manager-store.d.ts +14 -0
  41. package/{src → lib}/Store/make-cache-manager-store.js +25 -34
  42. package/lib/Store/make-in-memory-store.d.ts +118 -0
  43. package/{src → lib}/Store/make-in-memory-store.js +36 -32
  44. package/lib/Store/make-ordered-dictionary.d.ts +13 -0
  45. package/lib/Store/object-repository.d.ts +10 -0
  46. package/{src → lib}/Store/object-repository.js +1 -1
  47. package/lib/Types/Auth.d.ts +109 -0
  48. package/lib/Types/Call.d.ts +13 -0
  49. package/lib/Types/Chat.d.ts +107 -0
  50. package/{src/Types/Contact.ts → lib/Types/Contact.d.ts} +8 -9
  51. package/lib/Types/Events.d.ts +172 -0
  52. package/lib/Types/GroupMetadata.d.ts +56 -0
  53. package/lib/Types/Label.d.ts +46 -0
  54. package/{src/Types/LabelAssociation.ts → lib/Types/LabelAssociation.d.ts} +16 -22
  55. package/lib/Types/Message.d.ts +433 -0
  56. package/lib/Types/Newsletter.d.ts +92 -0
  57. package/lib/Types/Product.d.ts +78 -0
  58. package/lib/Types/Signal.d.ts +57 -0
  59. package/{src/Types/Socket.ts → lib/Types/Socket.d.ts} +61 -68
  60. package/lib/Types/State.d.ts +27 -0
  61. package/lib/Types/USync.d.ts +25 -0
  62. package/lib/Types/index.d.ts +66 -0
  63. package/lib/Utils/auth-utils.d.ts +18 -0
  64. package/{src → lib}/Utils/auth-utils.js +73 -90
  65. package/lib/Utils/baileys-event-stream.d.ts +16 -0
  66. package/lib/Utils/baileys-event-stream.js +63 -0
  67. package/lib/Utils/business.d.ts +22 -0
  68. package/{src → lib}/Utils/business.js +15 -43
  69. package/lib/Utils/chat-utils.d.ts +70 -0
  70. package/{src → lib}/Utils/chat-utils.js +87 -94
  71. package/lib/Utils/crypto.d.ts +40 -0
  72. package/{src → lib}/Utils/crypto.js +4 -2
  73. package/lib/Utils/decode-wa-message.d.ts +36 -0
  74. package/lib/Utils/decode-wa-message.js +226 -0
  75. package/lib/Utils/event-buffer.d.ts +35 -0
  76. package/{src → lib}/Utils/event-buffer.js +4 -13
  77. package/lib/Utils/generics.d.ts +88 -0
  78. package/{src → lib}/Utils/generics.js +67 -86
  79. package/lib/Utils/history.d.ts +19 -0
  80. package/{src → lib}/Utils/history.js +13 -39
  81. package/lib/Utils/index.d.ts +17 -0
  82. package/lib/Utils/link-preview.d.ts +21 -0
  83. package/{src → lib}/Utils/link-preview.js +17 -54
  84. package/lib/Utils/logger.d.ts +2 -0
  85. package/lib/Utils/lt-hash.d.ts +12 -0
  86. package/lib/Utils/make-mutex.d.ts +7 -0
  87. package/{src → lib}/Utils/make-mutex.js +4 -13
  88. package/lib/Utils/messages-media.d.ts +113 -0
  89. package/{src → lib}/Utils/messages-media.js +193 -255
  90. package/lib/Utils/messages.d.ts +77 -0
  91. package/{src → lib}/Utils/messages.js +588 -118
  92. package/lib/Utils/noise-handler.d.ts +20 -0
  93. package/lib/Utils/process-message.d.ts +41 -0
  94. package/{src → lib}/Utils/process-message.js +27 -30
  95. package/lib/Utils/signal.d.ts +33 -0
  96. package/{src → lib}/Utils/signal.js +25 -42
  97. package/lib/Utils/use-multi-file-auth-state.d.ts +12 -0
  98. package/{src → lib}/Utils/use-multi-file-auth-state.js +27 -28
  99. package/lib/Utils/validate-connection.d.ts +11 -0
  100. package/{src → lib}/Utils/validate-connection.js +40 -9
  101. package/lib/WABinary/constants.d.ts +27 -0
  102. package/lib/WABinary/decode.d.ts +6 -0
  103. package/lib/WABinary/encode.d.ts +2 -0
  104. package/{src → lib}/WABinary/encode.js +16 -10
  105. package/lib/WABinary/generic-utils.d.ts +14 -0
  106. package/lib/WABinary/index.d.ts +5 -0
  107. package/lib/WABinary/jid-utils.d.ts +31 -0
  108. package/lib/WABinary/types.d.ts +18 -0
  109. package/lib/WABinary/types.js +2 -0
  110. package/lib/WAM/BinaryInfo.d.ts +8 -0
  111. package/lib/WAM/constants.d.ts +38 -0
  112. package/lib/WAM/encode.d.ts +2 -0
  113. package/lib/WAM/index.d.ts +3 -0
  114. package/lib/WAUSync/Protocols/USyncContactProtocol.d.ts +9 -0
  115. package/lib/WAUSync/Protocols/USyncContactProtocol.js +32 -0
  116. package/lib/WAUSync/Protocols/USyncDeviceProtocol.d.ts +22 -0
  117. package/lib/WAUSync/Protocols/USyncDeviceProtocol.js +57 -0
  118. package/lib/WAUSync/Protocols/USyncDisappearingModeProtocol.d.ts +12 -0
  119. package/lib/WAUSync/Protocols/USyncDisappearingModeProtocol.js +30 -0
  120. package/lib/WAUSync/Protocols/USyncStatusProtocol.d.ts +12 -0
  121. package/lib/WAUSync/Protocols/USyncStatusProtocol.js +42 -0
  122. package/lib/WAUSync/Protocols/index.d.ts +4 -0
  123. package/lib/WAUSync/Protocols/index.js +20 -0
  124. package/lib/WAUSync/USyncQuery.d.ts +26 -0
  125. package/lib/WAUSync/USyncQuery.js +79 -0
  126. package/lib/WAUSync/USyncUser.d.ts +10 -0
  127. package/lib/WAUSync/USyncUser.js +22 -0
  128. package/lib/WAUSync/index.d.ts +3 -0
  129. package/lib/WAUSync/index.js +19 -0
  130. package/{src → lib}/index.js +1 -0
  131. package/package.json +26 -8
  132. package/LICENSE +0 -21
  133. package/src/Defaults/baileys-version.json +0 -3
  134. package/src/Defaults/index.ts +0 -131
  135. package/src/README.md +0 -1
  136. package/src/Signal/libsignal.js +0 -180
  137. package/src/Signal/libsignal.ts +0 -141
  138. package/src/Socket/Client/abstract-socket-client.ts +0 -19
  139. package/src/Socket/Client/index.ts +0 -3
  140. package/src/Socket/Client/mobile-socket-client.js +0 -78
  141. package/src/Socket/Client/mobile-socket-client.ts +0 -66
  142. package/src/Socket/Client/web-socket-client.js +0 -75
  143. package/src/Socket/Client/web-socket-client.ts +0 -57
  144. package/src/Socket/business.ts +0 -281
  145. package/src/Socket/chats.ts +0 -1030
  146. package/src/Socket/groups.ts +0 -356
  147. package/src/Socket/index.ts +0 -13
  148. package/src/Socket/messages-recv.ts +0 -985
  149. package/src/Socket/messages-send.ts +0 -871
  150. package/src/Socket/newsletter.ts +0 -282
  151. package/src/Socket/registration.ts +0 -250
  152. package/src/Socket/socket.ts +0 -777
  153. package/src/Store/index.ts +0 -3
  154. package/src/Store/make-cache-manager-store.ts +0 -100
  155. package/src/Store/make-in-memory-store.ts +0 -475
  156. package/src/Store/make-ordered-dictionary.ts +0 -86
  157. package/src/Store/object-repository.ts +0 -32
  158. package/src/Tests/test.app-state-sync.js +0 -204
  159. package/src/Tests/test.app-state-sync.ts +0 -207
  160. package/src/Tests/test.event-buffer.js +0 -270
  161. package/src/Tests/test.event-buffer.ts +0 -319
  162. package/src/Tests/test.key-store.js +0 -76
  163. package/src/Tests/test.key-store.ts +0 -92
  164. package/src/Tests/test.libsignal.js +0 -141
  165. package/src/Tests/test.libsignal.ts +0 -186
  166. package/src/Tests/test.media-download.js +0 -93
  167. package/src/Tests/test.media-download.ts +0 -76
  168. package/src/Tests/test.messages.js +0 -33
  169. package/src/Tests/test.messages.ts +0 -37
  170. package/src/Tests/utils.js +0 -34
  171. package/src/Tests/utils.ts +0 -36
  172. package/src/Types/Auth.ts +0 -113
  173. package/src/Types/Call.ts +0 -15
  174. package/src/Types/Chat.ts +0 -106
  175. package/src/Types/Events.ts +0 -93
  176. package/src/Types/GroupMetadata.ts +0 -53
  177. package/src/Types/Label.ts +0 -36
  178. package/src/Types/Message.ts +0 -288
  179. package/src/Types/Newsletter.ts +0 -98
  180. package/src/Types/Product.ts +0 -85
  181. package/src/Types/Signal.ts +0 -68
  182. package/src/Types/State.ts +0 -29
  183. package/src/Types/index.ts +0 -59
  184. package/src/Utils/auth-utils.ts +0 -222
  185. package/src/Utils/baileys-event-stream.js +0 -92
  186. package/src/Utils/baileys-event-stream.ts +0 -66
  187. package/src/Utils/business.ts +0 -275
  188. package/src/Utils/chat-utils.ts +0 -860
  189. package/src/Utils/crypto.ts +0 -131
  190. package/src/Utils/decode-wa-message.js +0 -211
  191. package/src/Utils/decode-wa-message.ts +0 -228
  192. package/src/Utils/event-buffer.ts +0 -613
  193. package/src/Utils/generics.ts +0 -434
  194. package/src/Utils/history.ts +0 -112
  195. package/src/Utils/index.ts +0 -17
  196. package/src/Utils/link-preview.ts +0 -122
  197. package/src/Utils/logger.ts +0 -3
  198. package/src/Utils/lt-hash.ts +0 -61
  199. package/src/Utils/make-mutex.ts +0 -44
  200. package/src/Utils/messages-media.ts +0 -847
  201. package/src/Utils/messages.ts +0 -956
  202. package/src/Utils/noise-handler.ts +0 -197
  203. package/src/Utils/process-message.ts +0 -414
  204. package/src/Utils/signal.ts +0 -177
  205. package/src/Utils/use-multi-file-auth-state.ts +0 -90
  206. package/src/Utils/validate-connection.ts +0 -238
  207. package/src/WABinary/constants.ts +0 -42
  208. package/src/WABinary/decode.ts +0 -265
  209. package/src/WABinary/encode.ts +0 -236
  210. package/src/WABinary/generic-utils.ts +0 -121
  211. package/src/WABinary/index.ts +0 -5
  212. package/src/WABinary/jid-utils.ts +0 -68
  213. package/src/WABinary/types.ts +0 -17
  214. package/src/WAM/BinaryInfo.ts +0 -12
  215. package/src/WAM/constants.ts +0 -15382
  216. package/src/WAM/encode.ts +0 -174
  217. package/src/WAM/index.ts +0 -3
  218. package/src/gifted +0 -1
  219. package/src/index.ts +0 -13
  220. /package/{src → lib}/Defaults/phonenumber-mcc.json +0 -0
  221. /package/{src → lib}/Socket/Client/abstract-socket-client.js +0 -0
  222. /package/{src → lib}/Store/index.js +0 -0
  223. /package/{src → lib}/Store/make-ordered-dictionary.js +0 -0
  224. /package/{src → lib}/Types/Auth.js +0 -0
  225. /package/{src → lib}/Types/Call.js +0 -0
  226. /package/{src → lib}/Types/Chat.js +0 -0
  227. /package/{src → lib}/Types/Contact.js +0 -0
  228. /package/{src → lib}/Types/Events.js +0 -0
  229. /package/{src → lib}/Types/GroupMetadata.js +0 -0
  230. /package/{src → lib}/Types/Label.js +0 -0
  231. /package/{src → lib}/Types/LabelAssociation.js +0 -0
  232. /package/{src → lib}/Types/Message.js +0 -0
  233. /package/{src → lib}/Types/Newsletter.js +0 -0
  234. /package/{src → lib}/Types/Product.js +0 -0
  235. /package/{src → lib}/Types/Signal.js +0 -0
  236. /package/{src → lib}/Types/Socket.js +0 -0
  237. /package/{src → lib}/Types/State.js +0 -0
  238. /package/{src/WABinary/types.js → lib/Types/USync.js} +0 -0
  239. /package/{src → lib}/Types/index.js +0 -0
  240. /package/{src → lib}/Utils/index.js +0 -0
  241. /package/{src → lib}/Utils/logger.js +0 -0
  242. /package/{src → lib}/Utils/lt-hash.js +0 -0
  243. /package/{src → lib}/Utils/noise-handler.js +0 -0
  244. /package/{src → lib}/WABinary/constants.js +0 -0
  245. /package/{src → lib}/WABinary/decode.js +0 -0
  246. /package/{src → lib}/WABinary/generic-utils.js +0 -0
  247. /package/{src → lib}/WABinary/index.js +0 -0
  248. /package/{src → lib}/WABinary/jid-utils.js +0 -0
  249. /package/{src → lib}/WAM/BinaryInfo.js +0 -0
  250. /package/{src → lib}/WAM/constants.js +0 -0
  251. /package/{src → lib}/WAM/encode.js +0 -0
  252. /package/{src → lib}/WAM/index.js +0 -0
@@ -1,197 +0,0 @@
1
- import { Boom } from '@hapi/boom'
2
- import { Logger } from 'pino'
3
- import { proto } from '../../WAProto'
4
- import { NOISE_MODE, WA_CERT_DETAILS } from '../Defaults'
5
- import { KeyPair } from '../Types'
6
- import { BinaryNode, decodeBinaryNode } from '../WABinary'
7
- import { aesDecryptGCM, aesEncryptGCM, Curve, hkdf, sha256 } from './crypto'
8
-
9
- const generateIV = (counter: number) => {
10
- const iv = new ArrayBuffer(12)
11
- new DataView(iv).setUint32(8, counter)
12
-
13
- return new Uint8Array(iv)
14
- }
15
-
16
- export const makeNoiseHandler = ({
17
- keyPair: { private: privateKey, public: publicKey },
18
- NOISE_HEADER,
19
- mobile,
20
- logger,
21
- routingInfo
22
- }: {
23
- keyPair: KeyPair
24
- NOISE_HEADER: Uint8Array
25
- mobile: boolean
26
- logger: Logger
27
- routingInfo?: Buffer | undefined
28
- }) => {
29
- logger = logger.child({ class: 'ns' })
30
-
31
- const authenticate = (data: Uint8Array) => {
32
- if(!isFinished) {
33
- hash = sha256(Buffer.concat([hash, data]))
34
- }
35
- }
36
-
37
- const encrypt = (plaintext: Uint8Array) => {
38
- const result = aesEncryptGCM(plaintext, encKey, generateIV(writeCounter), hash)
39
-
40
- writeCounter += 1
41
-
42
- authenticate(result)
43
- return result
44
- }
45
-
46
- const decrypt = (ciphertext: Uint8Array) => {
47
- // before the handshake is finished, we use the same counter
48
- // after handshake, the counters are different
49
- const iv = generateIV(isFinished ? readCounter : writeCounter)
50
- const result = aesDecryptGCM(ciphertext, decKey, iv, hash)
51
-
52
- if(isFinished) {
53
- readCounter += 1
54
- } else {
55
- writeCounter += 1
56
- }
57
-
58
- authenticate(ciphertext)
59
- return result
60
- }
61
-
62
- const localHKDF = (data: Uint8Array) => {
63
- const key = hkdf(Buffer.from(data), 64, { salt, info: '' })
64
- return [key.slice(0, 32), key.slice(32)]
65
- }
66
-
67
- const mixIntoKey = (data: Uint8Array) => {
68
- const [write, read] = localHKDF(data)
69
- salt = write
70
- encKey = read
71
- decKey = read
72
- readCounter = 0
73
- writeCounter = 0
74
- }
75
-
76
- const finishInit = () => {
77
- const [write, read] = localHKDF(new Uint8Array(0))
78
- encKey = write
79
- decKey = read
80
- hash = Buffer.from([])
81
- readCounter = 0
82
- writeCounter = 0
83
- isFinished = true
84
- }
85
-
86
- const data = Buffer.from(NOISE_MODE)
87
- let hash = Buffer.from(data.byteLength === 32 ? data : sha256(data))
88
- let salt = hash
89
- let encKey = hash
90
- let decKey = hash
91
- let readCounter = 0
92
- let writeCounter = 0
93
- let isFinished = false
94
- let sentIntro = false
95
-
96
- let inBytes = Buffer.alloc(0)
97
-
98
- authenticate(NOISE_HEADER)
99
- authenticate(publicKey)
100
-
101
- return {
102
- encrypt,
103
- decrypt,
104
- authenticate,
105
- mixIntoKey,
106
- finishInit,
107
- processHandshake: ({ serverHello }: proto.HandshakeMessage, noiseKey: KeyPair) => {
108
- authenticate(serverHello!.ephemeral!)
109
- mixIntoKey(Curve.sharedKey(privateKey, serverHello!.ephemeral!))
110
-
111
- const decStaticContent = decrypt(serverHello!.static!)
112
- mixIntoKey(Curve.sharedKey(privateKey, decStaticContent))
113
-
114
- const certDecoded = decrypt(serverHello!.payload!)
115
-
116
- if(mobile) {
117
- proto.CertChain.NoiseCertificate.decode(certDecoded)
118
- } else {
119
- const { intermediate: certIntermediate } = proto.CertChain.decode(certDecoded)
120
-
121
- const { issuerSerial } = proto.CertChain.NoiseCertificate.Details.decode(certIntermediate!.details!)
122
-
123
- if(issuerSerial !== WA_CERT_DETAILS.SERIAL) {
124
- throw new Boom('certification match failed', { statusCode: 400 })
125
- }
126
- }
127
-
128
- const keyEnc = encrypt(noiseKey.public)
129
- mixIntoKey(Curve.sharedKey(noiseKey.private, serverHello!.ephemeral!))
130
-
131
- return keyEnc
132
- },
133
- encodeFrame: (data: Buffer | Uint8Array) => {
134
- if(isFinished) {
135
- data = encrypt(data)
136
- }
137
-
138
- let header: Buffer
139
-
140
- if(routingInfo) {
141
- header = Buffer.alloc(7)
142
- header.write('ED', 0, 'utf8')
143
- header.writeUint8(0, 2)
144
- header.writeUint8(1, 3)
145
- header.writeUint8(routingInfo.byteLength >> 16, 4)
146
- header.writeUint16BE(routingInfo.byteLength & 65535, 5)
147
- header = Buffer.concat([header, routingInfo, NOISE_HEADER])
148
- } else {
149
- header = Buffer.from(NOISE_HEADER)
150
- }
151
-
152
- const introSize = sentIntro ? 0 : header.length
153
- const frame = Buffer.alloc(introSize + 3 + data.byteLength)
154
-
155
- if(!sentIntro) {
156
- frame.set(header)
157
- sentIntro = true
158
- }
159
-
160
- frame.writeUInt8(data.byteLength >> 16, introSize)
161
- frame.writeUInt16BE(65535 & data.byteLength, introSize + 1)
162
- frame.set(data, introSize + 3)
163
-
164
- return frame
165
- },
166
- decodeFrame: (newData: Buffer | Uint8Array, onFrame: (buff: Uint8Array | BinaryNode) => void) => {
167
- // the binary protocol uses its own framing mechanism
168
- // on top of the WS frames
169
- // so we get this data and separate out the frames
170
- const getBytesSize = () => {
171
- if(inBytes.length >= 3) {
172
- return (inBytes.readUInt8() << 16) | inBytes.readUInt16BE(1)
173
- }
174
- }
175
-
176
- inBytes = Buffer.concat([ inBytes, newData ])
177
-
178
- logger.trace(`recv ${newData.length} bytes, total recv ${inBytes.length} bytes`)
179
-
180
- let size = getBytesSize()
181
- while(size && inBytes.length >= size + 3) {
182
- let frame: Uint8Array | BinaryNode = inBytes.slice(3, size + 3)
183
- inBytes = inBytes.slice(size + 3)
184
-
185
- if(isFinished) {
186
- const result = decrypt(frame as Uint8Array)
187
- frame = decodeBinaryNode(result)
188
- }
189
-
190
- logger.trace({ msg: (frame as any)?.attrs?.id }, 'recv frame')
191
-
192
- onFrame(frame)
193
- size = getBytesSize()
194
- }
195
- }
196
- }
197
- }
@@ -1,414 +0,0 @@
1
- import { AxiosRequestConfig } from 'axios'
2
- import type { Logger } from 'pino'
3
- import { proto } from '../../WAProto'
4
- import { AuthenticationCreds, BaileysEventEmitter, Chat, GroupMetadata, ParticipantAction, SignalKeyStoreWithTransaction, SocketConfig, WAMessageStubType } from '../Types'
5
- import { getContentType, normalizeMessageContent } from '../Utils/messages'
6
- import { areJidsSameUser, isJidBroadcast, isJidStatusBroadcast, jidNormalizedUser } from '../WABinary'
7
- import { aesDecryptGCM, hmacSign } from './crypto'
8
- import { getKeyAuthor, toNumber } from './generics'
9
- import { downloadAndProcessHistorySyncNotification } from './history'
10
-
11
- type ProcessMessageContext = {
12
- shouldProcessHistoryMsg: boolean
13
- creds: AuthenticationCreds
14
- keyStore: SignalKeyStoreWithTransaction
15
- ev: BaileysEventEmitter
16
- getMessage: SocketConfig['getMessage']
17
- logger?: Logger
18
- options: AxiosRequestConfig<{}>
19
- }
20
-
21
- const REAL_MSG_STUB_TYPES = new Set([
22
- WAMessageStubType.CALL_MISSED_GROUP_VIDEO,
23
- WAMessageStubType.CALL_MISSED_GROUP_VOICE,
24
- WAMessageStubType.CALL_MISSED_VIDEO,
25
- WAMessageStubType.CALL_MISSED_VOICE
26
- ])
27
-
28
- const REAL_MSG_REQ_ME_STUB_TYPES = new Set([
29
- WAMessageStubType.GROUP_PARTICIPANT_ADD
30
- ])
31
-
32
- /** Cleans a received message to further processing */
33
- export const cleanMessage = (message: proto.IWebMessageInfo, meId: string) => {
34
- // ensure remoteJid and participant doesn't have device or agent in it
35
- message.key.remoteJid = jidNormalizedUser(message.key.remoteJid!)
36
- message.key.participant = message.key.participant ? jidNormalizedUser(message.key.participant!) : undefined
37
- const content = normalizeMessageContent(message.message)
38
- // if the message has a reaction, ensure fromMe & remoteJid are from our perspective
39
- if(content?.reactionMessage) {
40
- normaliseKey(content.reactionMessage.key!)
41
- }
42
-
43
- if(content?.pollUpdateMessage) {
44
- normaliseKey(content.pollUpdateMessage.pollCreationMessageKey!)
45
- }
46
-
47
- function normaliseKey(msgKey: proto.IMessageKey) {
48
- // if the reaction is from another user
49
- // we've to correctly map the key to this user's perspective
50
- if(!message.key.fromMe) {
51
- // if the sender believed the message being reacted to is not from them
52
- // we've to correct the key to be from them, or some other participant
53
- msgKey.fromMe = !msgKey.fromMe
54
- ? areJidsSameUser(msgKey.participant || msgKey.remoteJid!, meId)
55
- // if the message being reacted to, was from them
56
- // fromMe automatically becomes false
57
- : false
58
- // set the remoteJid to being the same as the chat the message came from
59
- msgKey.remoteJid = message.key.remoteJid
60
- // set participant of the message
61
- msgKey.participant = msgKey.participant || message.key.participant
62
- }
63
- }
64
- }
65
-
66
- export const isRealMessage = (message: proto.IWebMessageInfo, meId: string) => {
67
- const normalizedContent = normalizeMessageContent(message.message)
68
- const hasSomeContent = !!getContentType(normalizedContent)
69
- return (
70
- !!normalizedContent
71
- || REAL_MSG_STUB_TYPES.has(message.messageStubType!)
72
- || (
73
- REAL_MSG_REQ_ME_STUB_TYPES.has(message.messageStubType!)
74
- && message.messageStubParameters?.some(p => areJidsSameUser(meId, p))
75
- )
76
- )
77
- && hasSomeContent
78
- && !normalizedContent?.protocolMessage
79
- && !normalizedContent?.reactionMessage
80
- && !normalizedContent?.pollUpdateMessage
81
- }
82
-
83
- export const shouldIncrementChatUnread = (message: proto.IWebMessageInfo) => (
84
- !message.key.fromMe && !message.messageStubType
85
- )
86
-
87
- /**
88
- * Get the ID of the chat from the given key.
89
- * Typically -- that'll be the remoteJid, but for broadcasts, it'll be the participant
90
- */
91
- export const getChatId = ({ remoteJid, participant, fromMe }: proto.IMessageKey) => {
92
- if(
93
- isJidBroadcast(remoteJid!)
94
- && !isJidStatusBroadcast(remoteJid!)
95
- && !fromMe
96
- ) {
97
- return participant!
98
- }
99
-
100
- return remoteJid!
101
- }
102
-
103
- type PollContext = {
104
- /** normalised jid of the person that created the poll */
105
- pollCreatorJid: string
106
- /** ID of the poll creation message */
107
- pollMsgId: string
108
- /** poll creation message enc key */
109
- pollEncKey: Uint8Array
110
- /** jid of the person that voted */
111
- voterJid: string
112
- }
113
-
114
- /**
115
- * Decrypt a poll vote
116
- * @param vote encrypted vote
117
- * @param ctx additional info about the poll required for decryption
118
- * @returns list of SHA256 options
119
- */
120
- export function decryptPollVote(
121
- { encPayload, encIv }: proto.Message.IPollEncValue,
122
- {
123
- pollCreatorJid,
124
- pollMsgId,
125
- pollEncKey,
126
- voterJid,
127
- }: PollContext
128
- ) {
129
- const sign = Buffer.concat(
130
- [
131
- toBinary(pollMsgId),
132
- toBinary(pollCreatorJid),
133
- toBinary(voterJid),
134
- toBinary('Poll Vote'),
135
- new Uint8Array([1])
136
- ]
137
- )
138
-
139
- const key0 = hmacSign(pollEncKey, new Uint8Array(32), 'sha256')
140
- const decKey = hmacSign(sign, key0, 'sha256')
141
- const aad = toBinary(`${pollMsgId}\u0000${voterJid}`)
142
-
143
- const decrypted = aesDecryptGCM(encPayload!, decKey, encIv!, aad)
144
- return proto.Message.PollVoteMessage.decode(decrypted)
145
-
146
- function toBinary(txt: string) {
147
- return Buffer.from(txt)
148
- }
149
- }
150
-
151
- const processMessage = async(
152
- message: proto.IWebMessageInfo,
153
- {
154
- shouldProcessHistoryMsg,
155
- ev,
156
- creds,
157
- keyStore,
158
- logger,
159
- options,
160
- getMessage
161
- }: ProcessMessageContext
162
- ) => {
163
- const meId = creds.me!.id
164
- const { accountSettings } = creds
165
-
166
- const chat: Partial<Chat> = { id: jidNormalizedUser(getChatId(message.key)) }
167
- const isRealMsg = isRealMessage(message, meId)
168
-
169
- if(isRealMsg) {
170
- chat.conversationTimestamp = toNumber(message.messageTimestamp)
171
- // only increment unread count if not CIPHERTEXT and from another person
172
- if(shouldIncrementChatUnread(message)) {
173
- chat.unreadCount = (chat.unreadCount || 0) + 1
174
- }
175
- }
176
-
177
- const content = normalizeMessageContent(message.message)
178
-
179
- // unarchive chat if it's a real message, or someone reacted to our message
180
- // and we've the unarchive chats setting on
181
- if(
182
- (isRealMsg || content?.reactionMessage?.key?.fromMe)
183
- && accountSettings?.unarchiveChats
184
- ) {
185
- chat.archived = false
186
- chat.readOnly = false
187
- }
188
-
189
- const protocolMsg = content?.protocolMessage
190
- if(protocolMsg) {
191
- switch (protocolMsg.type) {
192
- case proto.Message.ProtocolMessage.Type.HISTORY_SYNC_NOTIFICATION:
193
- const histNotification = protocolMsg!.historySyncNotification!
194
- const process = shouldProcessHistoryMsg
195
- const isLatest = !creds.processedHistoryMessages?.length
196
-
197
- logger?.info({
198
- histNotification,
199
- process,
200
- id: message.key.id,
201
- isLatest,
202
- }, 'got history notification')
203
-
204
- if(process) {
205
- ev.emit('creds.update', {
206
- processedHistoryMessages: [
207
- ...(creds.processedHistoryMessages || []),
208
- { key: message.key, messageTimestamp: message.messageTimestamp }
209
- ]
210
- })
211
-
212
- const data = await downloadAndProcessHistorySyncNotification(
213
- histNotification,
214
- options
215
- )
216
-
217
- ev.emit('messaging-history.set', { ...data, isLatest })
218
- }
219
-
220
- break
221
- case proto.Message.ProtocolMessage.Type.APP_STATE_SYNC_KEY_SHARE:
222
- const keys = protocolMsg.appStateSyncKeyShare!.keys
223
- if(keys?.length) {
224
- let newAppStateSyncKeyId = ''
225
- await keyStore.transaction(
226
- async() => {
227
- const newKeys: string[] = []
228
- for(const { keyData, keyId } of keys) {
229
- const strKeyId = Buffer.from(keyId!.keyId!).toString('base64')
230
- newKeys.push(strKeyId)
231
-
232
- await keyStore.set({ 'app-state-sync-key': { [strKeyId]: keyData! } })
233
-
234
- newAppStateSyncKeyId = strKeyId
235
- }
236
-
237
- logger?.info(
238
- { newAppStateSyncKeyId, newKeys },
239
- 'injecting new app state sync keys'
240
- )
241
- }
242
- )
243
-
244
- ev.emit('creds.update', { myAppStateKeyId: newAppStateSyncKeyId })
245
- } else {
246
- logger?.info({ protocolMsg }, 'recv app state sync with 0 keys')
247
- }
248
-
249
- break
250
- case proto.Message.ProtocolMessage.Type.REVOKE:
251
- ev.emit('messages.update', [
252
- {
253
- key: {
254
- ...message.key,
255
- id: protocolMsg.key!.id
256
- },
257
- update: { message: null, messageStubType: WAMessageStubType.REVOKE, key: message.key }
258
- }
259
- ])
260
- break
261
- case proto.Message.ProtocolMessage.Type.EPHEMERAL_SETTING:
262
- Object.assign(chat, {
263
- ephemeralSettingTimestamp: toNumber(message.messageTimestamp),
264
- ephemeralExpiration: protocolMsg.ephemeralExpiration || null
265
- })
266
- break
267
- case proto.Message.ProtocolMessage.Type.PEER_DATA_OPERATION_REQUEST_RESPONSE_MESSAGE:
268
- const response = protocolMsg.peerDataOperationRequestResponseMessage!
269
- if(response) {
270
- const { peerDataOperationResult } = response
271
- for(const result of peerDataOperationResult!) {
272
- const { placeholderMessageResendResponse: retryResponse } = result
273
- if(retryResponse) {
274
- const webMessageInfo = proto.WebMessageInfo.decode(retryResponse.webMessageInfoBytes!)
275
- ev.emit('messages.update', [
276
- { key: webMessageInfo.key, update: { message: webMessageInfo.message } }
277
- ])
278
- }
279
- }
280
- }
281
-
282
- break
283
- }
284
- } else if(content?.reactionMessage) {
285
- const reaction: proto.IReaction = {
286
- ...content.reactionMessage,
287
- key: message.key,
288
- }
289
- ev.emit('messages.reaction', [{
290
- reaction,
291
- key: content.reactionMessage!.key!,
292
- }])
293
- } else if(message.messageStubType) {
294
- const jid = message.key!.remoteJid!
295
- //let actor = whatsappID (message.participant)
296
- let participants: string[]
297
- const emitParticipantsUpdate = (action: ParticipantAction) => (
298
- ev.emit('group-participants.update', { id: jid, author: message.participant!, participants, action })
299
- )
300
- const emitGroupUpdate = (update: Partial<GroupMetadata>) => {
301
- ev.emit('groups.update', [{ id: jid, ...update, author: message.participant ?? undefined }])
302
- }
303
-
304
- const participantsIncludesMe = () => participants.find(jid => areJidsSameUser(meId, jid))
305
-
306
- switch (message.messageStubType) {
307
- case WAMessageStubType.GROUP_PARTICIPANT_LEAVE:
308
- case WAMessageStubType.GROUP_PARTICIPANT_REMOVE:
309
- participants = message.messageStubParameters || []
310
- emitParticipantsUpdate('remove')
311
- // mark the chat read only if you left the group
312
- if(participantsIncludesMe()) {
313
- chat.readOnly = true
314
- }
315
-
316
- break
317
- case WAMessageStubType.GROUP_PARTICIPANT_ADD:
318
- case WAMessageStubType.GROUP_PARTICIPANT_INVITE:
319
- case WAMessageStubType.GROUP_PARTICIPANT_ADD_REQUEST_JOIN:
320
- participants = message.messageStubParameters || []
321
- if(participantsIncludesMe()) {
322
- chat.readOnly = false
323
- }
324
-
325
- emitParticipantsUpdate('add')
326
- break
327
- case WAMessageStubType.GROUP_PARTICIPANT_DEMOTE:
328
- participants = message.messageStubParameters || []
329
- emitParticipantsUpdate('demote')
330
- break
331
- case WAMessageStubType.GROUP_PARTICIPANT_PROMOTE:
332
- participants = message.messageStubParameters || []
333
- emitParticipantsUpdate('promote')
334
- break
335
- case WAMessageStubType.GROUP_CHANGE_ANNOUNCE:
336
- const announceValue = message.messageStubParameters?.[0]
337
- emitGroupUpdate({ announce: announceValue === 'true' || announceValue === 'on' })
338
- break
339
- case WAMessageStubType.GROUP_CHANGE_RESTRICT:
340
- const restrictValue = message.messageStubParameters?.[0]
341
- emitGroupUpdate({ restrict: restrictValue === 'true' || restrictValue === 'on' })
342
- break
343
- case WAMessageStubType.GROUP_CHANGE_SUBJECT:
344
- const name = message.messageStubParameters?.[0]
345
- chat.name = name
346
- emitGroupUpdate({ subject: name })
347
- break
348
- case WAMessageStubType.GROUP_CHANGE_INVITE_LINK:
349
- const code = message.messageStubParameters?.[0]
350
- emitGroupUpdate({ inviteCode: code })
351
- break
352
- case WAMessageStubType.GROUP_MEMBER_ADD_MODE:
353
- const memberAddValue = message.messageStubParameters?.[0]
354
- emitGroupUpdate({ memberAddMode: memberAddValue === 'all_member_add' })
355
- break
356
- case WAMessageStubType.GROUP_MEMBERSHIP_JOIN_APPROVAL_MODE:
357
- const approvalMode = message.messageStubParameters?.[0]
358
- emitGroupUpdate({ joinApprovalMode: approvalMode === 'on' })
359
- break
360
- }
361
- } else if(content?.pollUpdateMessage) {
362
- const creationMsgKey = content.pollUpdateMessage.pollCreationMessageKey!
363
- // we need to fetch the poll creation message to get the poll enc key
364
- const pollMsg = await getMessage(creationMsgKey)
365
- if(pollMsg) {
366
- const meIdNormalised = jidNormalizedUser(meId)
367
- const pollCreatorJid = getKeyAuthor(creationMsgKey, meIdNormalised)
368
- const voterJid = getKeyAuthor(message.key!, meIdNormalised)
369
- const pollEncKey = pollMsg.messageContextInfo?.messageSecret!
370
-
371
- try {
372
- const voteMsg = decryptPollVote(
373
- content.pollUpdateMessage.vote!,
374
- {
375
- pollEncKey,
376
- pollCreatorJid,
377
- pollMsgId: creationMsgKey.id!,
378
- voterJid,
379
- }
380
- )
381
- ev.emit('messages.update', [
382
- {
383
- key: creationMsgKey,
384
- update: {
385
- pollUpdates: [
386
- {
387
- pollUpdateMessageKey: message.key,
388
- vote: voteMsg,
389
- senderTimestampMs: (content.pollUpdateMessage.senderTimestampMs! as Long).toNumber(),
390
- }
391
- ]
392
- }
393
- }
394
- ])
395
- } catch(err) {
396
- logger?.warn(
397
- { err, creationMsgKey },
398
- 'failed to decrypt poll vote'
399
- )
400
- }
401
- } else {
402
- logger?.warn(
403
- { creationMsgKey },
404
- 'poll creation message not found, cannot decrypt update'
405
- )
406
- }
407
- }
408
-
409
- if(Object.keys(chat).length > 1) {
410
- ev.emit('chats.update', [chat])
411
- }
412
- }
413
-
414
- export default processMessage