@sixcore/baileys 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.
Files changed (278) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +606 -0
  3. package/WAProto/GenerateStatics.sh +4 -0
  4. package/WAProto/WAProto.proto +4357 -0
  5. package/WAProto/index.d.ts +50383 -0
  6. package/WAProto/index.js +155693 -0
  7. package/WASignalGroup/GroupProtocol.js +1697 -0
  8. package/WASignalGroup/ciphertext_message.js +16 -0
  9. package/WASignalGroup/generate-proto.sh +1 -0
  10. package/WASignalGroup/group.proto +42 -0
  11. package/WASignalGroup/group_cipher.js +120 -0
  12. package/WASignalGroup/group_session_builder.js +46 -0
  13. package/WASignalGroup/index.js +5 -0
  14. package/WASignalGroup/keyhelper.js +21 -0
  15. package/WASignalGroup/protobufs.js +3 -0
  16. package/WASignalGroup/queue_job.js +69 -0
  17. package/WASignalGroup/sender_chain_key.js +50 -0
  18. package/WASignalGroup/sender_key_distribution_message.js +78 -0
  19. package/WASignalGroup/sender_key_message.js +92 -0
  20. package/WASignalGroup/sender_key_name.js +70 -0
  21. package/WASignalGroup/sender_key_record.js +56 -0
  22. package/WASignalGroup/sender_key_state.js +129 -0
  23. package/WASignalGroup/sender_message_key.js +39 -0
  24. package/lib/Defaults/baileys-version.json +3 -0
  25. package/lib/Defaults/index.d.ts +53 -0
  26. package/lib/Defaults/index.js +108 -0
  27. package/lib/Signal/libsignal.d.ts +3 -0
  28. package/lib/Signal/libsignal.js +152 -0
  29. package/lib/Socket/Client/abstract-socket-client.d.ts +17 -0
  30. package/lib/Socket/Client/abstract-socket-client.js +13 -0
  31. package/lib/Socket/Client/index.d.ts +3 -0
  32. package/lib/Socket/Client/index.js +19 -0
  33. package/lib/Socket/Client/mobile-socket-client.d.ts +13 -0
  34. package/lib/Socket/Client/mobile-socket-client.js +65 -0
  35. package/lib/Socket/Client/web-socket-client.d.ts +12 -0
  36. package/lib/Socket/Client/web-socket-client.js +62 -0
  37. package/lib/Socket/business.d.ts +170 -0
  38. package/lib/Socket/business.js +260 -0
  39. package/lib/Socket/chats.d.ts +81 -0
  40. package/lib/Socket/chats.js +950 -0
  41. package/lib/Socket/groups.d.ts +115 -0
  42. package/lib/Socket/groups.js +315 -0
  43. package/lib/Socket/index.d.ts +172 -0
  44. package/lib/Socket/index.js +10 -0
  45. package/lib/Socket/messages-recv.d.ts +158 -0
  46. package/lib/Socket/messages-recv.js +972 -0
  47. package/lib/Socket/messages-send.d.ts +155 -0
  48. package/lib/Socket/messages-send.js +1087 -0
  49. package/lib/Socket/newsletter.d.ts +132 -0
  50. package/lib/Socket/newsletter.js +236 -0
  51. package/lib/Socket/registration.d.ts +264 -0
  52. package/lib/Socket/registration.js +166 -0
  53. package/lib/Socket/socket.d.ts +44 -0
  54. package/lib/Socket/socket.js +643 -0
  55. package/lib/Socket/usync.d.ts +37 -0
  56. package/lib/Socket/usync.js +70 -0
  57. package/lib/Store/index.d.ts +3 -0
  58. package/lib/Store/index.js +10 -0
  59. package/lib/Store/make-cache-manager-store.d.ts +14 -0
  60. package/lib/Store/make-cache-manager-store.js +83 -0
  61. package/lib/Store/make-in-memory-store.d.ts +118 -0
  62. package/lib/Store/make-in-memory-store.js +431 -0
  63. package/lib/Store/make-ordered-dictionary.d.ts +13 -0
  64. package/lib/Store/make-ordered-dictionary.js +81 -0
  65. package/lib/Store/object-repository.d.ts +10 -0
  66. package/lib/Store/object-repository.js +27 -0
  67. package/lib/Types/Auth.d.ts +109 -0
  68. package/lib/Types/Auth.js +2 -0
  69. package/lib/Types/Call.d.ts +13 -0
  70. package/lib/Types/Call.js +2 -0
  71. package/lib/Types/Chat.d.ts +107 -0
  72. package/lib/Types/Chat.js +4 -0
  73. package/lib/Types/Contact.d.ts +19 -0
  74. package/lib/Types/Contact.js +2 -0
  75. package/lib/Types/Events.d.ts +172 -0
  76. package/lib/Types/Events.js +2 -0
  77. package/lib/Types/GroupMetadata.d.ts +56 -0
  78. package/lib/Types/GroupMetadata.js +2 -0
  79. package/lib/Types/Label.d.ts +46 -0
  80. package/lib/Types/Label.js +27 -0
  81. package/lib/Types/LabelAssociation.d.ts +29 -0
  82. package/lib/Types/LabelAssociation.js +9 -0
  83. package/lib/Types/Message.d.ts +433 -0
  84. package/lib/Types/Message.js +9 -0
  85. package/lib/Types/Newsletter.d.ts +92 -0
  86. package/lib/Types/Newsletter.js +32 -0
  87. package/lib/Types/Product.d.ts +78 -0
  88. package/lib/Types/Product.js +2 -0
  89. package/lib/Types/Signal.d.ts +57 -0
  90. package/lib/Types/Signal.js +2 -0
  91. package/lib/Types/Socket.d.ts +116 -0
  92. package/lib/Types/Socket.js +2 -0
  93. package/lib/Types/State.d.ts +27 -0
  94. package/lib/Types/State.js +2 -0
  95. package/lib/Types/USync.d.ts +25 -0
  96. package/lib/Types/USync.js +2 -0
  97. package/lib/Types/index.d.ts +66 -0
  98. package/lib/Types/index.js +42 -0
  99. package/lib/Utils/auth-utils.d.ts +18 -0
  100. package/lib/Utils/auth-utils.js +227 -0
  101. package/lib/Utils/baileys-event-stream.d.ts +16 -0
  102. package/lib/Utils/baileys-event-stream.js +63 -0
  103. package/lib/Utils/business.d.ts +22 -0
  104. package/lib/Utils/business.js +234 -0
  105. package/lib/Utils/chat-utils.d.ts +70 -0
  106. package/lib/Utils/chat-utils.js +745 -0
  107. package/lib/Utils/crypto.d.ts +40 -0
  108. package/lib/Utils/crypto.js +199 -0
  109. package/lib/Utils/decode-wa-message.d.ts +36 -0
  110. package/lib/Utils/decode-wa-message.js +234 -0
  111. package/lib/Utils/event-buffer.d.ts +35 -0
  112. package/lib/Utils/event-buffer.js +517 -0
  113. package/lib/Utils/generics.d.ts +88 -0
  114. package/lib/Utils/generics.js +402 -0
  115. package/lib/Utils/history.d.ts +19 -0
  116. package/lib/Utils/history.js +94 -0
  117. package/lib/Utils/index.d.ts +17 -0
  118. package/lib/Utils/index.js +33 -0
  119. package/lib/Utils/link-preview.d.ts +21 -0
  120. package/lib/Utils/link-preview.js +93 -0
  121. package/lib/Utils/logger.d.ts +2 -0
  122. package/lib/Utils/logger.js +7 -0
  123. package/lib/Utils/lt-hash.d.ts +12 -0
  124. package/lib/Utils/lt-hash.js +51 -0
  125. package/lib/Utils/make-mutex.d.ts +7 -0
  126. package/lib/Utils/make-mutex.js +43 -0
  127. package/lib/Utils/messages-media.d.ts +113 -0
  128. package/lib/Utils/messages-media.js +643 -0
  129. package/lib/Utils/messages.d.ts +77 -0
  130. package/lib/Utils/messages.js +1221 -0
  131. package/lib/Utils/noise-handler.d.ts +20 -0
  132. package/lib/Utils/noise-handler.js +160 -0
  133. package/lib/Utils/process-message.d.ts +41 -0
  134. package/lib/Utils/process-message.js +373 -0
  135. package/lib/Utils/signal.d.ts +33 -0
  136. package/lib/Utils/signal.js +159 -0
  137. package/lib/Utils/use-multi-file-auth-state.d.ts +12 -0
  138. package/lib/Utils/use-multi-file-auth-state.js +295 -0
  139. package/lib/Utils/use-single-file-auth-state.d.ts +12 -0
  140. package/lib/Utils/use-single-file-auth-state.js +75 -0
  141. package/lib/Utils/validate-connection.d.ts +11 -0
  142. package/lib/Utils/validate-connection.js +205 -0
  143. package/lib/WABinary/constants.d.ts +27 -0
  144. package/lib/WABinary/constants.js +40 -0
  145. package/lib/WABinary/decode.d.ts +6 -0
  146. package/lib/WABinary/decode.js +264 -0
  147. package/lib/WABinary/encode.d.ts +2 -0
  148. package/lib/WABinary/encode.js +252 -0
  149. package/lib/WABinary/generic-utils.d.ts +14 -0
  150. package/lib/WABinary/generic-utils.js +110 -0
  151. package/lib/WABinary/index.d.ts +5 -0
  152. package/lib/WABinary/index.js +21 -0
  153. package/lib/WABinary/jid-utils.d.ts +31 -0
  154. package/lib/WABinary/jid-utils.js +62 -0
  155. package/lib/WABinary/types.d.ts +18 -0
  156. package/lib/WABinary/types.js +2 -0
  157. package/lib/WAM/BinaryInfo.d.ts +8 -0
  158. package/lib/WAM/BinaryInfo.js +13 -0
  159. package/lib/WAM/constants.d.ts +38 -0
  160. package/lib/WAM/constants.js +15350 -0
  161. package/lib/WAM/encode.d.ts +2 -0
  162. package/lib/WAM/encode.js +155 -0
  163. package/lib/WAM/index.d.ts +3 -0
  164. package/lib/WAM/index.js +19 -0
  165. package/lib/WAUSync/Protocols/USyncContactProtocol.d.ts +9 -0
  166. package/lib/WAUSync/Protocols/USyncContactProtocol.js +32 -0
  167. package/lib/WAUSync/Protocols/USyncDeviceProtocol.d.ts +22 -0
  168. package/lib/WAUSync/Protocols/USyncDeviceProtocol.js +57 -0
  169. package/lib/WAUSync/Protocols/USyncDisappearingModeProtocol.d.ts +12 -0
  170. package/lib/WAUSync/Protocols/USyncDisappearingModeProtocol.js +30 -0
  171. package/lib/WAUSync/Protocols/USyncStatusProtocol.d.ts +12 -0
  172. package/lib/WAUSync/Protocols/USyncStatusProtocol.js +42 -0
  173. package/lib/WAUSync/Protocols/UsyncBotProfileProtocol.d.ts +25 -0
  174. package/lib/WAUSync/Protocols/UsyncBotProfileProtocol.js +53 -0
  175. package/lib/WAUSync/Protocols/UsyncLIDProtocol.d.ts +8 -0
  176. package/lib/WAUSync/Protocols/UsyncLIDProtocol.js +24 -0
  177. package/lib/WAUSync/Protocols/index.d.ts +4 -0
  178. package/lib/WAUSync/Protocols/index.js +20 -0
  179. package/lib/WAUSync/USyncQuery.d.ts +28 -0
  180. package/lib/WAUSync/USyncQuery.js +89 -0
  181. package/lib/WAUSync/USyncUser.d.ts +10 -0
  182. package/lib/WAUSync/USyncUser.js +26 -0
  183. package/lib/WAUSync/index.d.ts +3 -0
  184. package/lib/WAUSync/index.js +19 -0
  185. package/lib/index.js +31 -0
  186. package/package.json +51 -0
  187. package/src/Defaults/baileys-version.json +3 -0
  188. package/src/Defaults/index.ts +133 -0
  189. package/src/Signal/Group/ciphertext-message.ts +9 -0
  190. package/src/Signal/Group/group-session-builder.ts +56 -0
  191. package/src/Signal/Group/group_cipher.ts +117 -0
  192. package/src/Signal/Group/index.ts +11 -0
  193. package/src/Signal/Group/keyhelper.ts +28 -0
  194. package/src/Signal/Group/sender-chain-key.ts +34 -0
  195. package/src/Signal/Group/sender-key-distribution-message.ts +95 -0
  196. package/src/Signal/Group/sender-key-message.ts +96 -0
  197. package/src/Signal/Group/sender-key-name.ts +66 -0
  198. package/src/Signal/Group/sender-key-record.ts +69 -0
  199. package/src/Signal/Group/sender-key-state.ts +134 -0
  200. package/src/Signal/Group/sender-message-key.ts +36 -0
  201. package/src/Signal/libsignal.ts +447 -0
  202. package/src/Signal/lid-mapping.ts +209 -0
  203. package/src/Socket/Client/index.ts +2 -0
  204. package/src/Socket/Client/types.ts +22 -0
  205. package/src/Socket/Client/websocket.ts +56 -0
  206. package/src/Socket/business.ts +421 -0
  207. package/src/Socket/chats.ts +1223 -0
  208. package/src/Socket/communities.ts +477 -0
  209. package/src/Socket/groups.ts +361 -0
  210. package/src/Socket/index.ts +22 -0
  211. package/src/Socket/messages-recv.ts +1563 -0
  212. package/src/Socket/messages-send.ts +1210 -0
  213. package/src/Socket/mex.ts +58 -0
  214. package/src/Socket/newsletter.ts +229 -0
  215. package/src/Socket/socket.ts +1072 -0
  216. package/src/Types/Auth.ts +115 -0
  217. package/src/Types/Bussines.ts +20 -0
  218. package/src/Types/Call.ts +14 -0
  219. package/src/Types/Chat.ts +138 -0
  220. package/src/Types/Contact.ts +24 -0
  221. package/src/Types/Events.ts +132 -0
  222. package/src/Types/GroupMetadata.ts +70 -0
  223. package/src/Types/Label.ts +48 -0
  224. package/src/Types/LabelAssociation.ts +35 -0
  225. package/src/Types/Message.ts +424 -0
  226. package/src/Types/Newsletter.ts +98 -0
  227. package/src/Types/Product.ts +85 -0
  228. package/src/Types/Signal.ts +76 -0
  229. package/src/Types/Socket.ts +150 -0
  230. package/src/Types/State.ts +43 -0
  231. package/src/Types/USync.ts +27 -0
  232. package/src/Types/globals.d.ts +8 -0
  233. package/src/Types/index.ts +67 -0
  234. package/src/Utils/auth-utils.ts +331 -0
  235. package/src/Utils/browser-utils.ts +31 -0
  236. package/src/Utils/business.ts +286 -0
  237. package/src/Utils/chat-utils.ts +933 -0
  238. package/src/Utils/crypto.ts +184 -0
  239. package/src/Utils/decode-wa-message.ts +355 -0
  240. package/src/Utils/event-buffer.ts +662 -0
  241. package/src/Utils/generics.ts +470 -0
  242. package/src/Utils/history.ts +114 -0
  243. package/src/Utils/index.ts +18 -0
  244. package/src/Utils/link-preview.ts +111 -0
  245. package/src/Utils/logger.ts +13 -0
  246. package/src/Utils/lt-hash.ts +65 -0
  247. package/src/Utils/make-mutex.ts +45 -0
  248. package/src/Utils/message-retry-manager.ts +229 -0
  249. package/src/Utils/messages-media.ts +820 -0
  250. package/src/Utils/messages.ts +1137 -0
  251. package/src/Utils/noise-handler.ts +192 -0
  252. package/src/Utils/pre-key-manager.ts +126 -0
  253. package/src/Utils/process-message.ts +622 -0
  254. package/src/Utils/signal.ts +214 -0
  255. package/src/Utils/use-multi-file-auth-state.ts +136 -0
  256. package/src/Utils/validate-connection.ts +253 -0
  257. package/src/WABinary/constants.ts +1305 -0
  258. package/src/WABinary/decode.ts +281 -0
  259. package/src/WABinary/encode.ts +253 -0
  260. package/src/WABinary/generic-utils.ts +127 -0
  261. package/src/WABinary/index.ts +5 -0
  262. package/src/WABinary/jid-utils.ts +128 -0
  263. package/src/WABinary/types.ts +17 -0
  264. package/src/WAM/BinaryInfo.ts +12 -0
  265. package/src/WAM/constants.ts +22889 -0
  266. package/src/WAM/encode.ts +169 -0
  267. package/src/WAM/index.ts +3 -0
  268. package/src/WAUSync/Protocols/USyncContactProtocol.ts +32 -0
  269. package/src/WAUSync/Protocols/USyncDeviceProtocol.ts +78 -0
  270. package/src/WAUSync/Protocols/USyncDisappearingModeProtocol.ts +35 -0
  271. package/src/WAUSync/Protocols/USyncStatusProtocol.ts +44 -0
  272. package/src/WAUSync/Protocols/UsyncBotProfileProtocol.ts +76 -0
  273. package/src/WAUSync/Protocols/UsyncLIDProtocol.ts +33 -0
  274. package/src/WAUSync/Protocols/index.ts +4 -0
  275. package/src/WAUSync/USyncQuery.ts +133 -0
  276. package/src/WAUSync/USyncUser.ts +32 -0
  277. package/src/WAUSync/index.ts +3 -0
  278. package/src/index.ts +13 -0
@@ -0,0 +1,622 @@
1
+ import { proto } from '../../WAProto/index.js'
2
+ import type {
3
+ AuthenticationCreds,
4
+ BaileysEventEmitter,
5
+ CacheStore,
6
+ Chat,
7
+ GroupMetadata,
8
+ GroupParticipant,
9
+ LIDMapping,
10
+ ParticipantAction,
11
+ RequestJoinAction,
12
+ RequestJoinMethod,
13
+ SignalKeyStoreWithTransaction,
14
+ SignalRepositoryWithLIDStore,
15
+ SocketConfig,
16
+ WAMessage,
17
+ WAMessageKey
18
+ } from '../Types'
19
+ import { WAMessageStubType } from '../Types'
20
+ import { getContentType, normalizeMessageContent } from '../Utils/messages'
21
+ import {
22
+ areJidsSameUser,
23
+ isHostedLidUser,
24
+ isHostedPnUser,
25
+ isJidBroadcast,
26
+ isJidStatusBroadcast,
27
+ isLidUser,
28
+ jidDecode,
29
+ jidEncode,
30
+ jidNormalizedUser
31
+ } from '../WABinary'
32
+ import { aesDecryptGCM, hmacSign } from './crypto'
33
+ import { getKeyAuthor, toNumber } from './generics'
34
+ import { downloadAndProcessHistorySyncNotification } from './history'
35
+ import type { ILogger } from './logger'
36
+
37
+ type ProcessMessageContext = {
38
+ shouldProcessHistoryMsg: boolean
39
+ placeholderResendCache?: CacheStore
40
+ creds: AuthenticationCreds
41
+ keyStore: SignalKeyStoreWithTransaction
42
+ ev: BaileysEventEmitter
43
+ logger?: ILogger
44
+ options: RequestInit
45
+ signalRepository: SignalRepositoryWithLIDStore
46
+ getMessage: SocketConfig['getMessage']
47
+ }
48
+
49
+ const REAL_MSG_STUB_TYPES = new Set([
50
+ WAMessageStubType.CALL_MISSED_GROUP_VIDEO,
51
+ WAMessageStubType.CALL_MISSED_GROUP_VOICE,
52
+ WAMessageStubType.CALL_MISSED_VIDEO,
53
+ WAMessageStubType.CALL_MISSED_VOICE
54
+ ])
55
+
56
+ const REAL_MSG_REQ_ME_STUB_TYPES = new Set([WAMessageStubType.GROUP_PARTICIPANT_ADD])
57
+
58
+ /** Cleans a received message to further processing */
59
+ export const cleanMessage = (message: WAMessage, meId: string, meLid: string) => {
60
+ // ensure remoteJid and participant doesn't have device or agent in it
61
+ if (isHostedPnUser(message.key.remoteJid!) || isHostedLidUser(message.key.remoteJid!)) {
62
+ message.key.remoteJid = jidEncode(
63
+ jidDecode(message.key?.remoteJid!)?.user!,
64
+ isHostedPnUser(message.key.remoteJid!) ? 's.whatsapp.net' : 'lid'
65
+ )
66
+ } else {
67
+ message.key.remoteJid = jidNormalizedUser(message.key.remoteJid!)
68
+ }
69
+
70
+ if (isHostedPnUser(message.key.participant!) || isHostedLidUser(message.key.participant!)) {
71
+ message.key.participant = jidEncode(
72
+ jidDecode(message.key.participant!)?.user!,
73
+ isHostedPnUser(message.key.participant!) ? 's.whatsapp.net' : 'lid'
74
+ )
75
+ } else {
76
+ message.key.participant = jidNormalizedUser(message.key.participant!)
77
+ }
78
+
79
+ const content = normalizeMessageContent(message.message)
80
+ // if the message has a reaction, ensure fromMe & remoteJid are from our perspective
81
+ if (content?.reactionMessage) {
82
+ normaliseKey(content.reactionMessage.key!)
83
+ }
84
+
85
+ if (content?.pollUpdateMessage) {
86
+ normaliseKey(content.pollUpdateMessage.pollCreationMessageKey!)
87
+ }
88
+
89
+ function normaliseKey(msgKey: WAMessageKey) {
90
+ // if the reaction is from another user
91
+ // we've to correctly map the key to this user's perspective
92
+ if (!message.key.fromMe) {
93
+ // if the sender believed the message being reacted to is not from them
94
+ // we've to correct the key to be from them, or some other participant
95
+ msgKey.fromMe = !msgKey.fromMe
96
+ ? areJidsSameUser(msgKey.participant || msgKey.remoteJid!, meId) ||
97
+ areJidsSameUser(msgKey.participant || msgKey.remoteJid!, meLid)
98
+ : // if the message being reacted to, was from them
99
+ // fromMe automatically becomes false
100
+ false
101
+ // set the remoteJid to being the same as the chat the message came from
102
+ // TODO: investigate inconsistencies
103
+ msgKey.remoteJid = message.key.remoteJid
104
+ // set participant of the message
105
+ msgKey.participant = msgKey.participant || message.key.participant
106
+ }
107
+ }
108
+ }
109
+
110
+ // TODO: target:audit AUDIT THIS FUNCTION AGAIN
111
+ export const isRealMessage = (message: WAMessage) => {
112
+ const normalizedContent = normalizeMessageContent(message.message)
113
+ const hasSomeContent = !!getContentType(normalizedContent)
114
+ return (
115
+ (!!normalizedContent ||
116
+ REAL_MSG_STUB_TYPES.has(message.messageStubType!) ||
117
+ REAL_MSG_REQ_ME_STUB_TYPES.has(message.messageStubType!)) &&
118
+ hasSomeContent &&
119
+ !normalizedContent?.protocolMessage &&
120
+ !normalizedContent?.reactionMessage &&
121
+ !normalizedContent?.pollUpdateMessage
122
+ )
123
+ }
124
+
125
+ export const shouldIncrementChatUnread = (message: WAMessage) => !message.key.fromMe && !message.messageStubType
126
+
127
+ /**
128
+ * Get the ID of the chat from the given key.
129
+ * Typically -- that'll be the remoteJid, but for broadcasts, it'll be the participant
130
+ */
131
+ export const getChatId = ({ remoteJid, participant, fromMe }: WAMessageKey) => {
132
+ if (isJidBroadcast(remoteJid!) && !isJidStatusBroadcast(remoteJid!) && !fromMe) {
133
+ return participant!
134
+ }
135
+
136
+ return remoteJid!
137
+ }
138
+
139
+ type PollContext = {
140
+ /** normalised jid of the person that created the poll */
141
+ pollCreatorJid: string
142
+ /** ID of the poll creation message */
143
+ pollMsgId: string
144
+ /** poll creation message enc key */
145
+ pollEncKey: Uint8Array
146
+ /** jid of the person that voted */
147
+ voterJid: string
148
+ }
149
+
150
+ type EventContext = {
151
+ /** normalised jid of the person that created the event */
152
+ eventCreatorJid: string
153
+ /** ID of the event creation message */
154
+ eventMsgId: string
155
+ /** event creation message enc key */
156
+ eventEncKey: Uint8Array
157
+ /** jid of the person that responded */
158
+ responderJid: string
159
+ }
160
+
161
+ /**
162
+ * Decrypt a poll vote
163
+ * @param vote encrypted vote
164
+ * @param ctx additional info about the poll required for decryption
165
+ * @returns list of SHA256 options
166
+ */
167
+ export function decryptPollVote(
168
+ { encPayload, encIv }: proto.Message.IPollEncValue,
169
+ { pollCreatorJid, pollMsgId, pollEncKey, voterJid }: PollContext
170
+ ) {
171
+ const sign = Buffer.concat([
172
+ toBinary(pollMsgId),
173
+ toBinary(pollCreatorJid),
174
+ toBinary(voterJid),
175
+ toBinary('Poll Vote'),
176
+ new Uint8Array([1])
177
+ ])
178
+
179
+ const key0 = hmacSign(pollEncKey, new Uint8Array(32), 'sha256')
180
+ const decKey = hmacSign(sign, key0, 'sha256')
181
+ const aad = toBinary(`${pollMsgId}\u0000${voterJid}`)
182
+
183
+ const decrypted = aesDecryptGCM(encPayload!, decKey, encIv!, aad)
184
+ return proto.Message.PollVoteMessage.decode(decrypted)
185
+
186
+ function toBinary(txt: string) {
187
+ return Buffer.from(txt)
188
+ }
189
+ }
190
+
191
+ /**
192
+ * Decrypt an event response
193
+ * @param response encrypted event response
194
+ * @param ctx additional info about the event required for decryption
195
+ * @returns event response message
196
+ */
197
+ export function decryptEventResponse(
198
+ { encPayload, encIv }: proto.Message.IPollEncValue,
199
+ { eventCreatorJid, eventMsgId, eventEncKey, responderJid }: EventContext
200
+ ) {
201
+ const sign = Buffer.concat([
202
+ toBinary(eventMsgId),
203
+ toBinary(eventCreatorJid),
204
+ toBinary(responderJid),
205
+ toBinary('Event Response'),
206
+ new Uint8Array([1])
207
+ ])
208
+
209
+ const key0 = hmacSign(eventEncKey, new Uint8Array(32), 'sha256')
210
+ const decKey = hmacSign(sign, key0, 'sha256')
211
+ const aad = toBinary(`${eventMsgId}\u0000${responderJid}`)
212
+
213
+ const decrypted = aesDecryptGCM(encPayload!, decKey, encIv!, aad)
214
+ return proto.Message.EventResponseMessage.decode(decrypted)
215
+
216
+ function toBinary(txt: string) {
217
+ return Buffer.from(txt)
218
+ }
219
+ }
220
+
221
+ const processMessage = async (
222
+ message: WAMessage,
223
+ {
224
+ shouldProcessHistoryMsg,
225
+ placeholderResendCache,
226
+ ev,
227
+ creds,
228
+ signalRepository,
229
+ keyStore,
230
+ logger,
231
+ options,
232
+ getMessage
233
+ }: ProcessMessageContext
234
+ ) => {
235
+ const meId = creds.me!.id
236
+ const { accountSettings } = creds
237
+
238
+ const chat: Partial<Chat> = { id: jidNormalizedUser(getChatId(message.key)) }
239
+ const isRealMsg = isRealMessage(message)
240
+
241
+ if (isRealMsg) {
242
+ chat.messages = [{ message }]
243
+ chat.conversationTimestamp = toNumber(message.messageTimestamp)
244
+ // only increment unread count if not CIPHERTEXT and from another person
245
+ if (shouldIncrementChatUnread(message)) {
246
+ chat.unreadCount = (chat.unreadCount || 0) + 1
247
+ }
248
+ }
249
+
250
+ const content = normalizeMessageContent(message.message)
251
+
252
+ // unarchive chat if it's a real message, or someone reacted to our message
253
+ // and we've the unarchive chats setting on
254
+ if ((isRealMsg || content?.reactionMessage?.key?.fromMe) && accountSettings?.unarchiveChats) {
255
+ chat.archived = false
256
+ chat.readOnly = false
257
+ }
258
+
259
+ const protocolMsg = content?.protocolMessage
260
+ if (protocolMsg) {
261
+ switch (protocolMsg.type) {
262
+ case proto.Message.ProtocolMessage.Type.HISTORY_SYNC_NOTIFICATION:
263
+ const histNotification = protocolMsg.historySyncNotification!
264
+ const process = shouldProcessHistoryMsg
265
+ const isLatest = !creds.processedHistoryMessages?.length
266
+
267
+ logger?.info(
268
+ {
269
+ histNotification,
270
+ process,
271
+ id: message.key.id,
272
+ isLatest
273
+ },
274
+ 'got history notification'
275
+ )
276
+
277
+ if (process) {
278
+ // TODO: investigate
279
+ if (histNotification.syncType !== proto.HistorySync.HistorySyncType.ON_DEMAND) {
280
+ ev.emit('creds.update', {
281
+ processedHistoryMessages: [
282
+ ...(creds.processedHistoryMessages || []),
283
+ { key: message.key, messageTimestamp: message.messageTimestamp }
284
+ ]
285
+ })
286
+ }
287
+
288
+ const data = await downloadAndProcessHistorySyncNotification(histNotification, options)
289
+
290
+ ev.emit('messaging-history.set', {
291
+ ...data,
292
+ isLatest: histNotification.syncType !== proto.HistorySync.HistorySyncType.ON_DEMAND ? isLatest : undefined,
293
+ peerDataRequestSessionId: histNotification.peerDataRequestSessionId
294
+ })
295
+ }
296
+
297
+ break
298
+ case proto.Message.ProtocolMessage.Type.APP_STATE_SYNC_KEY_SHARE:
299
+ const keys = protocolMsg.appStateSyncKeyShare!.keys
300
+ if (keys?.length) {
301
+ let newAppStateSyncKeyId = ''
302
+ await keyStore.transaction(async () => {
303
+ const newKeys: string[] = []
304
+ for (const { keyData, keyId } of keys) {
305
+ const strKeyId = Buffer.from(keyId!.keyId!).toString('base64')
306
+ newKeys.push(strKeyId)
307
+
308
+ await keyStore.set({ 'app-state-sync-key': { [strKeyId]: keyData! } })
309
+
310
+ newAppStateSyncKeyId = strKeyId
311
+ }
312
+
313
+ logger?.info({ newAppStateSyncKeyId, newKeys }, 'injecting new app state sync keys')
314
+ }, meId)
315
+
316
+ ev.emit('creds.update', { myAppStateKeyId: newAppStateSyncKeyId })
317
+ } else {
318
+ logger?.info({ protocolMsg }, 'recv app state sync with 0 keys')
319
+ }
320
+
321
+ break
322
+ case proto.Message.ProtocolMessage.Type.REVOKE:
323
+ ev.emit('messages.update', [
324
+ {
325
+ key: {
326
+ ...message.key,
327
+ id: protocolMsg.key!.id
328
+ },
329
+ update: { message: null, messageStubType: WAMessageStubType.REVOKE, key: message.key }
330
+ }
331
+ ])
332
+ break
333
+ case proto.Message.ProtocolMessage.Type.EPHEMERAL_SETTING:
334
+ Object.assign(chat, {
335
+ ephemeralSettingTimestamp: toNumber(message.messageTimestamp),
336
+ ephemeralExpiration: protocolMsg.ephemeralExpiration || null
337
+ })
338
+ break
339
+ case proto.Message.ProtocolMessage.Type.PEER_DATA_OPERATION_REQUEST_RESPONSE_MESSAGE:
340
+ const response = protocolMsg.peerDataOperationRequestResponseMessage!
341
+ if (response) {
342
+ await placeholderResendCache?.del(response.stanzaId!)
343
+ // TODO: IMPLEMENT HISTORY SYNC ETC (sticker uploads etc.).
344
+ const { peerDataOperationResult } = response
345
+ for (const result of peerDataOperationResult!) {
346
+ const { placeholderMessageResendResponse: retryResponse } = result
347
+ //eslint-disable-next-line max-depth
348
+ if (retryResponse) {
349
+ const webMessageInfo = proto.WebMessageInfo.decode(retryResponse.webMessageInfoBytes!)
350
+ // wait till another upsert event is available, don't want it to be part of the PDO response message
351
+ // TODO: parse through proper message handling utilities (to add relevant key fields)
352
+ setTimeout(() => {
353
+ ev.emit('messages.upsert', {
354
+ messages: [webMessageInfo as WAMessage],
355
+ type: 'notify',
356
+ requestId: response.stanzaId!
357
+ })
358
+ }, 500)
359
+ }
360
+ }
361
+ }
362
+
363
+ break
364
+ case proto.Message.ProtocolMessage.Type.MESSAGE_EDIT:
365
+ ev.emit('messages.update', [
366
+ {
367
+ // flip the sender / fromMe properties because they're in the perspective of the sender
368
+ key: { ...message.key, id: protocolMsg.key?.id },
369
+ update: {
370
+ message: {
371
+ editedMessage: {
372
+ message: protocolMsg.editedMessage
373
+ }
374
+ },
375
+ messageTimestamp: protocolMsg.timestampMs
376
+ ? Math.floor(toNumber(protocolMsg.timestampMs) / 1000)
377
+ : message.messageTimestamp
378
+ }
379
+ }
380
+ ])
381
+ break
382
+ case proto.Message.ProtocolMessage.Type.LID_MIGRATION_MAPPING_SYNC:
383
+ const encodedPayload = protocolMsg.lidMigrationMappingSyncMessage?.encodedMappingPayload!
384
+ const { pnToLidMappings, chatDbMigrationTimestamp } =
385
+ proto.LIDMigrationMappingSyncPayload.decode(encodedPayload)
386
+ logger?.debug({ pnToLidMappings, chatDbMigrationTimestamp }, 'got lid mappings and chat db migration timestamp')
387
+ const pairs = []
388
+ for (const { pn, latestLid, assignedLid } of pnToLidMappings) {
389
+ const lid = latestLid || assignedLid
390
+ pairs.push({ lid: `${lid}@lid`, pn: `${pn}@s.whatsapp.net` })
391
+ }
392
+
393
+ await signalRepository.lidMapping.storeLIDPNMappings(pairs)
394
+ if (pairs.length) {
395
+ for (const { pn, lid } of pairs) {
396
+ await signalRepository.migrateSession(pn, lid)
397
+ }
398
+ }
399
+ }
400
+ } else if (content?.reactionMessage) {
401
+ const reaction: proto.IReaction = {
402
+ ...content.reactionMessage,
403
+ key: message.key
404
+ }
405
+ ev.emit('messages.reaction', [
406
+ {
407
+ reaction,
408
+ key: content.reactionMessage?.key!
409
+ }
410
+ ])
411
+ } else if (content?.encEventResponseMessage) {
412
+ const encEventResponse = content.encEventResponseMessage
413
+ const creationMsgKey = encEventResponse.eventCreationMessageKey!
414
+
415
+ // we need to fetch the event creation message to get the event enc key
416
+ const eventMsg = await getMessage(creationMsgKey)
417
+ if (eventMsg) {
418
+ try {
419
+ const meIdNormalised = jidNormalizedUser(meId)
420
+
421
+ // all jids need to be PN
422
+ const eventCreatorKey = creationMsgKey.participant || creationMsgKey.remoteJid!
423
+ const eventCreatorPn = isLidUser(eventCreatorKey)
424
+ ? await signalRepository.lidMapping.getPNForLID(eventCreatorKey)
425
+ : eventCreatorKey
426
+ const eventCreatorJid = getKeyAuthor(
427
+ { remoteJid: jidNormalizedUser(eventCreatorPn!), fromMe: meIdNormalised === eventCreatorPn },
428
+ meIdNormalised
429
+ )
430
+
431
+ const responderJid = getKeyAuthor(message.key, meIdNormalised)
432
+ const eventEncKey = eventMsg?.messageContextInfo?.messageSecret
433
+
434
+ if (!eventEncKey) {
435
+ logger?.warn({ creationMsgKey }, 'event response: missing messageSecret for decryption')
436
+ } else {
437
+ const responseMsg = decryptEventResponse(encEventResponse, {
438
+ eventEncKey,
439
+ eventCreatorJid,
440
+ eventMsgId: creationMsgKey.id!,
441
+ responderJid
442
+ })
443
+
444
+ const eventResponse = {
445
+ eventResponseMessageKey: message.key,
446
+ senderTimestampMs: responseMsg.timestampMs!,
447
+ response: responseMsg
448
+ }
449
+
450
+ ev.emit('messages.update', [
451
+ {
452
+ key: creationMsgKey,
453
+ update: {
454
+ eventResponses: [eventResponse]
455
+ }
456
+ }
457
+ ])
458
+ }
459
+ } catch (err) {
460
+ logger?.warn({ err, creationMsgKey }, 'failed to decrypt event response')
461
+ }
462
+ } else {
463
+ logger?.warn({ creationMsgKey }, 'event creation message not found, cannot decrypt response')
464
+ }
465
+ } else if (message.messageStubType) {
466
+ const jid = message.key?.remoteJid!
467
+ //let actor = whatsappID (message.participant)
468
+ let participants: GroupParticipant[]
469
+ const emitParticipantsUpdate = (action: ParticipantAction) =>
470
+ ev.emit('group-participants.update', {
471
+ id: jid,
472
+ author: message.key.participant!,
473
+ authorPn: message.key.participantAlt!,
474
+ participants,
475
+ action
476
+ })
477
+ const emitGroupUpdate = (update: Partial<GroupMetadata>) => {
478
+ ev.emit('groups.update', [
479
+ { id: jid, ...update, author: message.key.participant ?? undefined, authorPn: message.key.participantAlt }
480
+ ])
481
+ }
482
+
483
+ const emitGroupRequestJoin = (participant: LIDMapping, action: RequestJoinAction, method: RequestJoinMethod) => {
484
+ ev.emit('group.join-request', {
485
+ id: jid,
486
+ author: message.key.participant!,
487
+ authorPn: message.key.participantAlt!,
488
+ participant: participant.lid,
489
+ participantPn: participant.pn,
490
+ action,
491
+ method: method!
492
+ })
493
+ }
494
+
495
+ const participantsIncludesMe = () => participants.find(jid => areJidsSameUser(meId, jid.phoneNumber)) // ADD SUPPORT FOR LID
496
+
497
+ switch (message.messageStubType) {
498
+ case WAMessageStubType.GROUP_PARTICIPANT_CHANGE_NUMBER:
499
+ participants = message.messageStubParameters.map((a: any) => JSON.parse(a as string)) || []
500
+ emitParticipantsUpdate('modify')
501
+ break
502
+ case WAMessageStubType.GROUP_PARTICIPANT_LEAVE:
503
+ case WAMessageStubType.GROUP_PARTICIPANT_REMOVE:
504
+ participants = message.messageStubParameters.map((a: any) => JSON.parse(a as string)) || []
505
+ emitParticipantsUpdate('remove')
506
+ // mark the chat read only if you left the group
507
+ if (participantsIncludesMe()) {
508
+ chat.readOnly = true
509
+ }
510
+
511
+ break
512
+ case WAMessageStubType.GROUP_PARTICIPANT_ADD:
513
+ case WAMessageStubType.GROUP_PARTICIPANT_INVITE:
514
+ case WAMessageStubType.GROUP_PARTICIPANT_ADD_REQUEST_JOIN:
515
+ participants = message.messageStubParameters.map((a: any) => JSON.parse(a as string)) || []
516
+ if (participantsIncludesMe()) {
517
+ chat.readOnly = false
518
+ }
519
+
520
+ emitParticipantsUpdate('add')
521
+ break
522
+ case WAMessageStubType.GROUP_PARTICIPANT_DEMOTE:
523
+ participants = message.messageStubParameters.map((a: any) => JSON.parse(a as string)) || []
524
+ emitParticipantsUpdate('demote')
525
+ break
526
+ case WAMessageStubType.GROUP_PARTICIPANT_PROMOTE:
527
+ participants = message.messageStubParameters.map((a: any) => JSON.parse(a as string)) || []
528
+ emitParticipantsUpdate('promote')
529
+ break
530
+ case WAMessageStubType.GROUP_CHANGE_ANNOUNCE:
531
+ const announceValue = message.messageStubParameters?.[0]
532
+ emitGroupUpdate({ announce: announceValue === 'true' || announceValue === 'on' })
533
+ break
534
+ case WAMessageStubType.GROUP_CHANGE_RESTRICT:
535
+ const restrictValue = message.messageStubParameters?.[0]
536
+ emitGroupUpdate({ restrict: restrictValue === 'true' || restrictValue === 'on' })
537
+ break
538
+ case WAMessageStubType.GROUP_CHANGE_SUBJECT:
539
+ const name = message.messageStubParameters?.[0]
540
+ chat.name = name
541
+ emitGroupUpdate({ subject: name })
542
+ break
543
+ case WAMessageStubType.GROUP_CHANGE_DESCRIPTION:
544
+ const description = message.messageStubParameters?.[0]
545
+ chat.description = description
546
+ emitGroupUpdate({ desc: description })
547
+ break
548
+ case WAMessageStubType.GROUP_CHANGE_INVITE_LINK:
549
+ const code = message.messageStubParameters?.[0]
550
+ emitGroupUpdate({ inviteCode: code })
551
+ break
552
+ case WAMessageStubType.GROUP_MEMBER_ADD_MODE:
553
+ const memberAddValue = message.messageStubParameters?.[0]
554
+ emitGroupUpdate({ memberAddMode: memberAddValue === 'all_member_add' })
555
+ break
556
+ case WAMessageStubType.GROUP_MEMBERSHIP_JOIN_APPROVAL_MODE:
557
+ const approvalMode = message.messageStubParameters?.[0]
558
+ emitGroupUpdate({ joinApprovalMode: approvalMode === 'on' })
559
+ break
560
+ case WAMessageStubType.GROUP_MEMBERSHIP_JOIN_APPROVAL_REQUEST_NON_ADMIN_ADD: // TODO: Add other events
561
+ const participant = JSON.parse(message.messageStubParameters?.[0]) as LIDMapping
562
+ const action = message.messageStubParameters?.[1] as RequestJoinAction
563
+ const method = message.messageStubParameters?.[2] as RequestJoinMethod
564
+ emitGroupRequestJoin(participant, action, method)
565
+ break
566
+ }
567
+ } /* else if(content?.pollUpdateMessage) {
568
+ const creationMsgKey = content.pollUpdateMessage.pollCreationMessageKey!
569
+ // we need to fetch the poll creation message to get the poll enc key
570
+ // TODO: make standalone, remove getMessage reference
571
+ // TODO: Remove entirely
572
+ const pollMsg = await getMessage(creationMsgKey)
573
+ if(pollMsg) {
574
+ const meIdNormalised = jidNormalizedUser(meId)
575
+ const pollCreatorJid = getKeyAuthor(creationMsgKey, meIdNormalised)
576
+ const voterJid = getKeyAuthor(message.key, meIdNormalised)
577
+ const pollEncKey = pollMsg.messageContextInfo?.messageSecret!
578
+
579
+ try {
580
+ const voteMsg = decryptPollVote(
581
+ content.pollUpdateMessage.vote!,
582
+ {
583
+ pollEncKey,
584
+ pollCreatorJid,
585
+ pollMsgId: creationMsgKey.id!,
586
+ voterJid,
587
+ }
588
+ )
589
+ ev.emit('messages.update', [
590
+ {
591
+ key: creationMsgKey,
592
+ update: {
593
+ pollUpdates: [
594
+ {
595
+ pollUpdateMessageKey: message.key,
596
+ vote: voteMsg,
597
+ senderTimestampMs: (content.pollUpdateMessage.senderTimestampMs! as Long).toNumber(),
598
+ }
599
+ ]
600
+ }
601
+ }
602
+ ])
603
+ } catch(err) {
604
+ logger?.warn(
605
+ { err, creationMsgKey },
606
+ 'failed to decrypt poll vote'
607
+ )
608
+ }
609
+ } else {
610
+ logger?.warn(
611
+ { creationMsgKey },
612
+ 'poll creation message not found, cannot decrypt update'
613
+ )
614
+ }
615
+ } */
616
+
617
+ if (Object.keys(chat).length > 1) {
618
+ ev.emit('chats.update', [chat])
619
+ }
620
+ }
621
+
622
+ export default processMessage