gifted-baileys 1.5.5 → 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 (251) hide show
  1. package/README.md +6 -1642
  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/Signal/libsignal.js +0 -180
  136. package/src/Signal/libsignal.ts +0 -141
  137. package/src/Socket/Client/abstract-socket-client.ts +0 -19
  138. package/src/Socket/Client/index.ts +0 -3
  139. package/src/Socket/Client/mobile-socket-client.js +0 -78
  140. package/src/Socket/Client/mobile-socket-client.ts +0 -66
  141. package/src/Socket/Client/web-socket-client.js +0 -75
  142. package/src/Socket/Client/web-socket-client.ts +0 -57
  143. package/src/Socket/business.ts +0 -281
  144. package/src/Socket/chats.ts +0 -1030
  145. package/src/Socket/groups.ts +0 -356
  146. package/src/Socket/index.ts +0 -13
  147. package/src/Socket/messages-recv.ts +0 -985
  148. package/src/Socket/messages-send.ts +0 -871
  149. package/src/Socket/newsletter.ts +0 -282
  150. package/src/Socket/registration.ts +0 -250
  151. package/src/Socket/socket.ts +0 -777
  152. package/src/Store/index.ts +0 -3
  153. package/src/Store/make-cache-manager-store.ts +0 -100
  154. package/src/Store/make-in-memory-store.ts +0 -475
  155. package/src/Store/make-ordered-dictionary.ts +0 -86
  156. package/src/Store/object-repository.ts +0 -32
  157. package/src/Tests/test.app-state-sync.js +0 -204
  158. package/src/Tests/test.app-state-sync.ts +0 -207
  159. package/src/Tests/test.event-buffer.js +0 -270
  160. package/src/Tests/test.event-buffer.ts +0 -319
  161. package/src/Tests/test.key-store.js +0 -76
  162. package/src/Tests/test.key-store.ts +0 -92
  163. package/src/Tests/test.libsignal.js +0 -141
  164. package/src/Tests/test.libsignal.ts +0 -186
  165. package/src/Tests/test.media-download.js +0 -93
  166. package/src/Tests/test.media-download.ts +0 -76
  167. package/src/Tests/test.messages.js +0 -33
  168. package/src/Tests/test.messages.ts +0 -37
  169. package/src/Tests/utils.js +0 -34
  170. package/src/Tests/utils.ts +0 -36
  171. package/src/Types/Auth.ts +0 -113
  172. package/src/Types/Call.ts +0 -15
  173. package/src/Types/Chat.ts +0 -106
  174. package/src/Types/Events.ts +0 -93
  175. package/src/Types/GroupMetadata.ts +0 -53
  176. package/src/Types/Label.ts +0 -36
  177. package/src/Types/Message.ts +0 -288
  178. package/src/Types/Newsletter.ts +0 -98
  179. package/src/Types/Product.ts +0 -85
  180. package/src/Types/Signal.ts +0 -68
  181. package/src/Types/State.ts +0 -29
  182. package/src/Types/index.ts +0 -59
  183. package/src/Utils/auth-utils.ts +0 -222
  184. package/src/Utils/baileys-event-stream.js +0 -92
  185. package/src/Utils/baileys-event-stream.ts +0 -66
  186. package/src/Utils/business.ts +0 -275
  187. package/src/Utils/chat-utils.ts +0 -860
  188. package/src/Utils/crypto.ts +0 -131
  189. package/src/Utils/decode-wa-message.js +0 -211
  190. package/src/Utils/decode-wa-message.ts +0 -228
  191. package/src/Utils/event-buffer.ts +0 -613
  192. package/src/Utils/generics.ts +0 -434
  193. package/src/Utils/history.ts +0 -112
  194. package/src/Utils/index.ts +0 -17
  195. package/src/Utils/link-preview.ts +0 -122
  196. package/src/Utils/logger.ts +0 -3
  197. package/src/Utils/lt-hash.ts +0 -61
  198. package/src/Utils/make-mutex.ts +0 -44
  199. package/src/Utils/messages-media.ts +0 -847
  200. package/src/Utils/messages.ts +0 -956
  201. package/src/Utils/noise-handler.ts +0 -197
  202. package/src/Utils/process-message.ts +0 -414
  203. package/src/Utils/signal.ts +0 -177
  204. package/src/Utils/use-multi-file-auth-state.ts +0 -90
  205. package/src/Utils/validate-connection.ts +0 -238
  206. package/src/WABinary/constants.ts +0 -42
  207. package/src/WABinary/decode.ts +0 -265
  208. package/src/WABinary/encode.ts +0 -236
  209. package/src/WABinary/generic-utils.ts +0 -121
  210. package/src/WABinary/index.ts +0 -5
  211. package/src/WABinary/jid-utils.ts +0 -68
  212. package/src/WABinary/types.ts +0 -17
  213. package/src/WAM/BinaryInfo.ts +0 -12
  214. package/src/WAM/constants.ts +0 -15382
  215. package/src/WAM/encode.ts +0 -174
  216. package/src/WAM/index.ts +0 -3
  217. package/src/gifted +0 -1
  218. package/src/index.ts +0 -13
  219. /package/{src → lib}/Defaults/phonenumber-mcc.json +0 -0
  220. /package/{src → lib}/Socket/Client/abstract-socket-client.js +0 -0
  221. /package/{src → lib}/Store/index.js +0 -0
  222. /package/{src → lib}/Store/make-ordered-dictionary.js +0 -0
  223. /package/{src → lib}/Types/Auth.js +0 -0
  224. /package/{src → lib}/Types/Call.js +0 -0
  225. /package/{src → lib}/Types/Chat.js +0 -0
  226. /package/{src → lib}/Types/Contact.js +0 -0
  227. /package/{src → lib}/Types/Events.js +0 -0
  228. /package/{src → lib}/Types/GroupMetadata.js +0 -0
  229. /package/{src → lib}/Types/Label.js +0 -0
  230. /package/{src → lib}/Types/LabelAssociation.js +0 -0
  231. /package/{src → lib}/Types/Message.js +0 -0
  232. /package/{src → lib}/Types/Newsletter.js +0 -0
  233. /package/{src → lib}/Types/Product.js +0 -0
  234. /package/{src → lib}/Types/Signal.js +0 -0
  235. /package/{src → lib}/Types/Socket.js +0 -0
  236. /package/{src → lib}/Types/State.js +0 -0
  237. /package/{src/WABinary/types.js → lib/Types/USync.js} +0 -0
  238. /package/{src → lib}/Types/index.js +0 -0
  239. /package/{src → lib}/Utils/index.js +0 -0
  240. /package/{src → lib}/Utils/logger.js +0 -0
  241. /package/{src → lib}/Utils/lt-hash.js +0 -0
  242. /package/{src → lib}/Utils/noise-handler.js +0 -0
  243. /package/{src → lib}/WABinary/constants.js +0 -0
  244. /package/{src → lib}/WABinary/decode.js +0 -0
  245. /package/{src → lib}/WABinary/generic-utils.js +0 -0
  246. /package/{src → lib}/WABinary/index.js +0 -0
  247. /package/{src → lib}/WABinary/jid-utils.js +0 -0
  248. /package/{src → lib}/WAM/BinaryInfo.js +0 -0
  249. /package/{src → lib}/WAM/constants.js +0 -0
  250. /package/{src → lib}/WAM/encode.js +0 -0
  251. /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