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,1030 +0,0 @@
1
- import { Boom } from '@hapi/boom'
2
- import { proto } from '../../WAProto'
3
- import { PROCESSABLE_HISTORY_TYPES } from '../Defaults'
4
- import { ALL_WA_PATCH_NAMES, ChatModification, ChatMutation, LTHashState, MessageUpsertType, PresenceData, SocketConfig, WABusinessHoursConfig, WABusinessProfile, WAMediaUpload, WAMessage, WAPatchCreate, WAPatchName, WAPresence, WAPrivacyOnlineValue, WAPrivacyValue, WAReadReceiptsValue } from '../Types'
5
- import { chatModificationToAppPatch, ChatMutationMap, decodePatches, decodeSyncdSnapshot, encodeSyncdPatch, extractSyncdPatches, generateProfilePicture, getHistoryMsg, newLTHashState, processSyncAction } from '../Utils'
6
- import { makeMutex } from '../Utils/make-mutex'
7
- import processMessage from '../Utils/process-message'
8
- import { BinaryNode, getBinaryNodeChild, getBinaryNodeChildren, jidNormalizedUser, reduceBinaryNodeToDictionary, S_WHATSAPP_NET } from '../WABinary'
9
- import { makeSocket } from './socket'
10
-
11
- const MAX_SYNC_ATTEMPTS = 2
12
-
13
- export const makeChatsSocket = (config: SocketConfig) => {
14
- const {
15
- logger,
16
- markOnlineOnConnect,
17
- fireInitQueries,
18
- appStateMacVerification,
19
- shouldIgnoreJid,
20
- shouldSyncHistoryMessage,
21
- } = config
22
- const sock = makeSocket(config)
23
- const {
24
- ev,
25
- ws,
26
- authState,
27
- generateMessageTag,
28
- sendNode,
29
- query,
30
- onUnexpectedError,
31
- } = sock
32
-
33
- let privacySettings: {
34
- [_: string]: string } | undefined
35
- let needToFlushWithAppStateSync = false
36
- let pendingAppStateSync = false
37
- /** this mutex ensures that the notifications (receipts, messages etc.) are processed in order */
38
- const processingMutex = makeMutex()
39
-
40
- /** helper function to fetch the given app state sync key */
41
- const getAppStateSyncKey = async (keyId: string) => {
42
- const {
43
- [keyId]: key } = await authState.keys.get('app-state-sync-key', [keyId])
44
- return key
45
- }
46
-
47
- const fetchPrivacySettings = async (force = false) => {
48
- if (!privacySettings || force) {
49
- const { content } = await query({
50
- tag: 'iq',
51
- attrs: {
52
- xmlns: 'privacy',
53
- to: S_WHATSAPP_NET,
54
- type: 'get'
55
- },
56
- content: [
57
- { tag: 'privacy', attrs: {} }
58
- ]
59
- })
60
- privacySettings = reduceBinaryNodeToDictionary(content?.[0] as BinaryNode, 'category')
61
- }
62
-
63
- return privacySettings
64
- }
65
-
66
- /** helper function to run a privacy IQ query */
67
- const privacyQuery = async (name: string, value: string) => {
68
- await query({
69
- tag: 'iq',
70
- attrs: {
71
- xmlns: 'privacy',
72
- to: S_WHATSAPP_NET,
73
- type: 'set'
74
- },
75
- content: [{
76
- tag: 'privacy',
77
- attrs: {},
78
- content: [
79
- {
80
- tag: 'category',
81
- attrs: { name, value }
82
- }
83
- ]
84
- }]
85
- })
86
- }
87
-
88
- const updateLastSeenPrivacy = async (value: WAPrivacyValue) => {
89
- await privacyQuery('last', value)
90
- }
91
-
92
- const updateOnlinePrivacy = async (value: WAPrivacyOnlineValue) => {
93
- await privacyQuery('online', value)
94
- }
95
-
96
- const updateProfilePicturePrivacy = async (value: WAPrivacyValue) => {
97
- await privacyQuery('profile', value)
98
- }
99
-
100
- const updateStatusPrivacy = async (value: WAPrivacyValue) => {
101
- await privacyQuery('status', value)
102
- }
103
-
104
- const updateReadReceiptsPrivacy = async (value: WAReadReceiptsValue) => {
105
- await privacyQuery('readreceipts', value)
106
- }
107
-
108
- const updateGroupsAddPrivacy = async (value: WAPrivacyValue) => {
109
- await privacyQuery('groupadd', value)
110
- }
111
-
112
- const updateDefaultDisappearingMode = async (duration: number) => {
113
- await query({
114
- tag: 'iq',
115
- attrs: {
116
- xmlns: 'disappearing_mode',
117
- to: S_WHATSAPP_NET,
118
- type: 'set'
119
- },
120
- content: [{
121
- tag: 'disappearing_mode',
122
- attrs: {
123
- duration: duration.toString()
124
- }
125
- }]
126
- })
127
- }
128
-
129
- /** helper function to run a generic IQ query */
130
- const interactiveQuery = async (userNodes: BinaryNode[], queryNode: BinaryNode) => {
131
- const result = await query({
132
- tag: 'iq',
133
- attrs: {
134
- to: S_WHATSAPP_NET,
135
- type: 'get',
136
- xmlns: 'usync',
137
- },
138
- content: [
139
- {
140
- tag: 'usync',
141
- attrs: {
142
- sid: generateMessageTag(),
143
- mode: 'query',
144
- last: 'true',
145
- index: '0',
146
- context: 'interactive',
147
- },
148
- content: [
149
- {
150
- tag: 'query',
151
- attrs: {},
152
- content: [queryNode]
153
- },
154
- {
155
- tag: 'list',
156
- attrs: {},
157
- content: userNodes
158
- }
159
- ]
160
- }
161
- ],
162
- })
163
-
164
- const usyncNode = getBinaryNodeChild(result, 'usync')
165
- const listNode = getBinaryNodeChild(usyncNode, 'list')
166
- const users = getBinaryNodeChildren(listNode, 'user')
167
-
168
- return users
169
- }
170
-
171
- const onWhatsApp = async (...jids: string[]) => {
172
- const query = { tag: 'contact', attrs: {} }
173
- const list = jids.map((jid) => {
174
- // insures only 1 + is there
175
- const content = `+${jid.replace('+', '')}`
176
-
177
- return {
178
- tag: 'user',
179
- attrs: {},
180
- content: [{
181
- tag: 'contact',
182
- attrs: {},
183
- content,
184
- }],
185
- }
186
- })
187
- const results = await interactiveQuery(list, query)
188
-
189
- return results.map(user => {
190
- const contact = getBinaryNodeChild(user, 'contact')
191
- return { exists: contact?.attrs.type === 'in', jid: user.attrs.jid }
192
- }).filter(item => item.exists)
193
- }
194
-
195
- const fetchStatus = async (jid: string) => {
196
- const [result] = await interactiveQuery(
197
- [{ tag: 'user', attrs: { jid } }], { tag: 'status', attrs: {} }
198
- )
199
- if (result) {
200
- const status = getBinaryNodeChild(result, 'status')
201
- return {
202
- status: status?.content!.toString(),
203
- setAt: new Date(+(status?.attrs.t || 0) * 1000)
204
- }
205
- }
206
- }
207
-
208
- /** update the profile picture for yourself or a group */
209
- const updateProfilePicture = async (jid: string, content: WAMediaUpload) => {
210
- let targetJid;
211
- if (!jid) {
212
- throw new Boom('Illegal no-jid profile update. Please specify either your ID or the ID of the chat you wish to update')
213
- }
214
-
215
- if (jidNormalizedUser(jid) !== jidNormalizedUser(authState.creds.me!.id)) {
216
- targetJid = jidNormalizedUser(jid) // in case it is someone other than us
217
- }
218
-
219
- const { img } = await generateProfilePicture(content)
220
- await query({
221
- tag: 'iq',
222
- attrs: {
223
- target: targetJid,
224
- to: S_WHATSAPP_NET,
225
- type: 'set',
226
- xmlns: 'w:profile:picture'
227
- },
228
- content: [
229
- {
230
- tag: 'picture',
231
- attrs: { type: 'image' },
232
- content: img
233
- }
234
- ]
235
- })
236
- }
237
-
238
- /** remove the profile picture for yourself or a group */
239
- const removeProfilePicture = async (jid: string) => {
240
- let targetJid;
241
- if (!jid) {
242
- throw new Boom('Illegal no-jid profile update. Please specify either your ID or the ID of the chat you wish to update')
243
- }
244
-
245
- if (jidNormalizedUser(jid) !== jidNormalizedUser(authState.creds.me!.id)) {
246
- targetJid = jidNormalizedUser(jid) // in case it is someone other than us
247
- }
248
-
249
- await query({
250
- tag: 'iq',
251
- attrs: {
252
- target: targetJid,
253
- to: S_WHATSAPP_NET,
254
- type: 'set',
255
- xmlns: 'w:profile:picture'
256
- }
257
- })
258
- }
259
-
260
- /** update the profile status for yourself */
261
- const updateProfileStatus = async (status: string) => {
262
- await query({
263
- tag: 'iq',
264
- attrs: {
265
- to: S_WHATSAPP_NET,
266
- type: 'set',
267
- xmlns: 'status'
268
- },
269
- content: [
270
- {
271
- tag: 'status',
272
- attrs: {},
273
- content: Buffer.from(status, 'utf-8')
274
- }
275
- ]
276
- })
277
- }
278
-
279
- const updateProfileName = async (name: string) => {
280
- await chatModify({ pushNameSetting: name }, '')
281
- }
282
-
283
- const fetchBlocklist = async () => {
284
- const result = await query({
285
- tag: 'iq',
286
- attrs: {
287
- xmlns: 'blocklist',
288
- to: S_WHATSAPP_NET,
289
- type: 'get'
290
- }
291
- })
292
-
293
- const listNode = getBinaryNodeChild(result, 'list')
294
- return getBinaryNodeChildren(listNode, 'item')
295
- .map(n => n.attrs.jid)
296
- }
297
-
298
- const updateBlockStatus = async (jid: string, action: 'block' | 'unblock') => {
299
- await query({
300
- tag: 'iq',
301
- attrs: {
302
- xmlns: 'blocklist',
303
- to: S_WHATSAPP_NET,
304
- type: 'set'
305
- },
306
- content: [
307
- {
308
- tag: 'item',
309
- attrs: {
310
- action,
311
- jid
312
- }
313
- }
314
- ]
315
- })
316
- }
317
-
318
- const getBusinessProfile = async (jid: string): Promise < WABusinessProfile | void > => {
319
- const results = await query({
320
- tag: 'iq',
321
- attrs: {
322
- to: 's.whatsapp.net',
323
- xmlns: 'w:biz',
324
- type: 'get'
325
- },
326
- content: [{
327
- tag: 'business_profile',
328
- attrs: { v: '244' },
329
- content: [{
330
- tag: 'profile',
331
- attrs: { jid }
332
- }]
333
- }]
334
- })
335
-
336
- const profileNode = getBinaryNodeChild(results, 'business_profile')
337
- const profiles = getBinaryNodeChild(profileNode, 'profile')
338
- if (profiles) {
339
- const address = getBinaryNodeChild(profiles, 'address')
340
- const description = getBinaryNodeChild(profiles, 'description')
341
- const website = getBinaryNodeChild(profiles, 'website')
342
- const email = getBinaryNodeChild(profiles, 'email')
343
- const category = getBinaryNodeChild(getBinaryNodeChild(profiles, 'categories'), 'category')
344
- const businessHours = getBinaryNodeChild(profiles, 'business_hours')
345
- const businessHoursConfig = businessHours ?
346
- getBinaryNodeChildren(businessHours, 'business_hours_config') :
347
- undefined
348
- const websiteStr = website?.content?.toString()
349
- return {
350
- wid: profiles.attrs?.jid,
351
- address: address?.content?.toString(),
352
- description: description?.content?.toString() || '',
353
- website: websiteStr ? [websiteStr] : [],
354
- email: email?.content?.toString(),
355
- category: category?.content?.toString(),
356
- 'business_hours': {
357
- timezone: businessHours?.attrs?.timezone,
358
- 'business_config': businessHoursConfig?.map(({ attrs }) => attrs as unknown as WABusinessHoursConfig)
359
- }
360
- }
361
- }
362
- }
363
-
364
- const cleanDirtyBits = async (type: 'account_sync' | 'groups', fromTimestamp ? : number | string) => {
365
- logger.info({ fromTimestamp }, 'clean dirty bits ' + type)
366
- await sendNode({
367
- tag: 'iq',
368
- attrs: {
369
- to: S_WHATSAPP_NET,
370
- type: 'set',
371
- xmlns: 'urn:xmpp:whatsapp:dirty',
372
- id: generateMessageTag(),
373
- },
374
- content: [
375
- {
376
- tag: 'clean',
377
- attrs: {
378
- type,
379
- ...(fromTimestamp ? { timestamp: fromTimestamp.toString() } : null),
380
- }
381
- }
382
- ]
383
- })
384
- }
385
-
386
- const newAppStateChunkHandler = (isInitialSync: boolean) => {
387
- return {
388
- onMutation(mutation: ChatMutation) {
389
- processSyncAction(
390
- mutation,
391
- ev,
392
- authState.creds.me!,
393
- isInitialSync ? { accountSettings: authState.creds.accountSettings } : undefined,
394
- logger
395
- )
396
- }
397
- }
398
- }
399
-
400
- const resyncAppState = ev.createBufferedFunction(async (collections: readonly WAPatchName[], isInitialSync: boolean) => {
401
- // we use this to determine which events to fire
402
- // otherwise when we resync from scratch -- all notifications will fire
403
- const initialVersionMap: {
404
- [T in WAPatchName] ? : number } = {}
405
- const globalMutationMap: ChatMutationMap = {}
406
-
407
- await authState.keys.transaction(
408
- async () => {
409
- const collectionsToHandle = new Set < string > (collections)
410
- // in case something goes wrong -- ensure we don't enter a loop that cannot be exited from
411
- const attemptsMap: {
412
- [T in WAPatchName] ? : number } = {}
413
- // keep executing till all collections are done
414
- // sometimes a single patch request will not return all the patches (God knows why)
415
- // so we fetch till they're all done (this is determined by the "has_more_patches" flag)
416
- while (collectionsToHandle.size) {
417
- const states = {} as {
418
- [T in WAPatchName]: LTHashState }
419
- const nodes: BinaryNode[] = []
420
-
421
- for (const name of collectionsToHandle) {
422
- const result = await authState.keys.get('app-state-sync-version', [name])
423
- let state = result[name]
424
-
425
- if (state) {
426
- if (typeof initialVersionMap[name] === 'undefined') {
427
- initialVersionMap[name] = state.version
428
- }
429
- } else {
430
- state = newLTHashState()
431
- }
432
-
433
- states[name] = state
434
-
435
- logger.info(`resyncing ${name} from v${state.version}`)
436
-
437
- nodes.push({
438
- tag: 'collection',
439
- attrs: {
440
- name,
441
- version: state.version.toString(),
442
- // return snapshot if being synced from scratch
443
- 'return_snapshot': (!state.version).toString()
444
- }
445
- })
446
- }
447
-
448
- const result = await query({
449
- tag: 'iq',
450
- attrs: {
451
- to: S_WHATSAPP_NET,
452
- xmlns: 'w:sync:app:state',
453
- type: 'set'
454
- },
455
- content: [
456
- {
457
- tag: 'sync',
458
- attrs: {},
459
- content: nodes
460
- }
461
- ]
462
- })
463
-
464
- // extract from binary node
465
- const decoded = await extractSyncdPatches(result, config?.options)
466
- for (const key in decoded) {
467
- const name = key as WAPatchName
468
- const { patches, hasMorePatches, snapshot } = decoded[name]
469
- try {
470
- if (snapshot) {
471
- const { state: newState, mutationMap } = await decodeSyncdSnapshot(
472
- name,
473
- snapshot,
474
- getAppStateSyncKey,
475
- initialVersionMap[name],
476
- appStateMacVerification.snapshot
477
- )
478
- states[name] = newState
479
- Object.assign(globalMutationMap, mutationMap)
480
-
481
- logger.info(`restored state of ${name} from snapshot to v${newState.version} with mutations`)
482
-
483
- await authState.keys.set({ 'app-state-sync-version': {
484
- [name]: newState } })
485
- }
486
-
487
- // only process if there are syncd patches
488
- if (patches.length) {
489
- const { state: newState, mutationMap } = await decodePatches(
490
- name,
491
- patches,
492
- states[name],
493
- getAppStateSyncKey,
494
- config.options,
495
- initialVersionMap[name],
496
- logger,
497
- appStateMacVerification.patch
498
- )
499
-
500
- await authState.keys.set({ 'app-state-sync-version': {
501
- [name]: newState } })
502
-
503
- logger.info(`synced ${name} to v${newState.version}`)
504
- initialVersionMap[name] = newState.version
505
-
506
- Object.assign(globalMutationMap, mutationMap)
507
- }
508
-
509
- if (hasMorePatches) {
510
- logger.info(`${name} has more patches...`)
511
- } else { // collection is done with sync
512
- collectionsToHandle.delete(name)
513
- }
514
- } catch (error) {
515
- // if retry attempts overshoot
516
- // or key not found
517
- const isIrrecoverableError = attemptsMap[name] ! >= MAX_SYNC_ATTEMPTS ||
518
- error.output?.statusCode === 404 ||
519
- error.name === 'TypeError'
520
- logger.info({ name, error: error.stack },
521
- `failed to sync state from version${isIrrecoverableError ? '' : ', removing and trying from scratch'}`
522
- )
523
- await authState.keys.set({ 'app-state-sync-version': {
524
- [name]: null } })
525
- // increment number of retries
526
- attemptsMap[name] = (attemptsMap[name] || 0) + 1
527
-
528
- if (isIrrecoverableError) {
529
- // stop retrying
530
- collectionsToHandle.delete(name)
531
- }
532
- }
533
- }
534
- }
535
- }
536
- )
537
-
538
- const { onMutation } = newAppStateChunkHandler(isInitialSync)
539
- for (const key in globalMutationMap) {
540
- onMutation(globalMutationMap[key])
541
- }
542
- })
543
-
544
- /**
545
- * fetch the profile picture of a user/group
546
- * type = "preview" for a low res picture
547
- * type = "image for the high res picture"
548
- */
549
- const profilePictureUrl = async (jid: string, type: 'preview' | 'image' = 'preview', timeoutMs ? : number) => {
550
- jid = jidNormalizedUser(jid)
551
- const result = await query({
552
- tag: 'iq',
553
- attrs: {
554
- target: jid,
555
- to: S_WHATSAPP_NET,
556
- type: 'get',
557
- xmlns: 'w:profile:picture'
558
- },
559
- content: [
560
- { tag: 'picture', attrs: { type, query: 'url' } }
561
- ]
562
- }, timeoutMs)
563
- const child = getBinaryNodeChild(result, 'picture')
564
- return child?.attrs?.url
565
- }
566
-
567
- const sendPresenceUpdate = async (type: WAPresence, toJid ? : string) => {
568
- const me = authState.creds.me!
569
- if (type === 'available' || type === 'unavailable') {
570
- if (!me.name) {
571
- logger.warn('no name present, ignoring presence update request...')
572
- return
573
- }
574
-
575
- ev.emit('connection.update', { isOnline: type === 'available' })
576
-
577
- await sendNode({
578
- tag: 'presence',
579
- attrs: {
580
- name: me.name,
581
- type
582
- }
583
- })
584
- } else {
585
- await sendNode({
586
- tag: 'chatstate',
587
- attrs: {
588
- from: me.id,
589
- to: toJid!,
590
- },
591
- content: [
592
- {
593
- tag: type === 'recording' ? 'composing' : type,
594
- attrs: type === 'recording' ? { media: 'audio' } : {}
595
- }
596
- ]
597
- })
598
- }
599
- }
600
-
601
- /**
602
- * @param toJid the jid to subscribe to
603
- * @param tcToken token for subscription, use if present
604
- */
605
- const presenceSubscribe = (toJid: string, tcToken ? : Buffer) => (
606
- sendNode({
607
- tag: 'presence',
608
- attrs: {
609
- to: toJid,
610
- id: generateMessageTag(),
611
- type: 'subscribe'
612
- },
613
- content: tcToken ?
614
- [
615
- {
616
- tag: 'tctoken',
617
- attrs: {},
618
- content: tcToken
619
- }
620
- ] :
621
- undefined
622
- })
623
- )
624
-
625
- const handlePresenceUpdate = ({ tag, attrs, content }: BinaryNode) => {
626
- let presence: PresenceData | undefined
627
- const jid = attrs.from
628
- const participant = attrs.participant || attrs.from
629
-
630
- if (shouldIgnoreJid(jid) && jid !== '@s.whatsapp.net') {
631
- return
632
- }
633
-
634
- if (tag === 'presence') {
635
- presence = {
636
- lastKnownPresence: attrs.type === 'unavailable' ? 'unavailable' : 'available',
637
- lastSeen: attrs.last && attrs.last !== 'deny' ? +attrs.last : undefined
638
- }
639
- } else if (Array.isArray(content)) {
640
- const [firstChild] = content
641
- let type = firstChild.tag as WAPresence
642
- if (type === 'paused') {
643
- type = 'available'
644
- }
645
-
646
- if (firstChild.attrs?.media === 'audio') {
647
- type = 'recording'
648
- }
649
-
650
- presence = { lastKnownPresence: type }
651
- } else {
652
- logger.error({ tag, attrs, content }, 'recv invalid presence node')
653
- }
654
-
655
- if (presence) {
656
- ev.emit('presence.update', { id: jid, presences: {
657
- [participant]: presence } })
658
- }
659
- }
660
-
661
- const appPatch = async (patchCreate: WAPatchCreate) => {
662
- const name = patchCreate.type
663
- const myAppStateKeyId = authState.creds.myAppStateKeyId
664
- if (!myAppStateKeyId) {
665
- throw new Boom('App state key not present!', { statusCode: 400 })
666
- }
667
-
668
- let initial: LTHashState
669
- let encodeResult: { patch: proto.ISyncdPatch, state: LTHashState }
670
-
671
- await processingMutex.mutex(
672
- async () => {
673
- await authState.keys.transaction(
674
- async () => {
675
- logger.debug({ patch: patchCreate }, 'applying app patch')
676
-
677
- await resyncAppState([name], false)
678
-
679
- const {
680
- [name]: currentSyncVersion } = await authState.keys.get('app-state-sync-version', [name])
681
- initial = currentSyncVersion || newLTHashState()
682
-
683
- encodeResult = await encodeSyncdPatch(
684
- patchCreate,
685
- myAppStateKeyId,
686
- initial,
687
- getAppStateSyncKey,
688
- )
689
- const { patch, state } = encodeResult
690
-
691
- const node: BinaryNode = {
692
- tag: 'iq',
693
- attrs: {
694
- to: S_WHATSAPP_NET,
695
- type: 'set',
696
- xmlns: 'w:sync:app:state'
697
- },
698
- content: [
699
- {
700
- tag: 'sync',
701
- attrs: {},
702
- content: [
703
- {
704
- tag: 'collection',
705
- attrs: {
706
- name,
707
- version: (state.version - 1).toString(),
708
- 'return_snapshot': 'false'
709
- },
710
- content: [
711
- {
712
- tag: 'patch',
713
- attrs: {},
714
- content: proto.SyncdPatch.encode(patch).finish()
715
- }
716
- ]
717
- }
718
- ]
719
- }
720
- ]
721
- }
722
- await query(node)
723
-
724
- await authState.keys.set({ 'app-state-sync-version': {
725
- [name]: state } })
726
- }
727
- )
728
- }
729
- )
730
-
731
- if (config.emitOwnEvents) {
732
- const { onMutation } = newAppStateChunkHandler(false)
733
- const { mutationMap } = await decodePatches(
734
- name,
735
- [{ ...encodeResult!.patch, version: { version: encodeResult!.state.version }, }],
736
- initial!,
737
- getAppStateSyncKey,
738
- config.options,
739
- undefined,
740
- logger,
741
- )
742
- for (const key in mutationMap) {
743
- onMutation(mutationMap[key])
744
- }
745
- }
746
- }
747
-
748
- /** sending non-abt props may fix QR scan fail if server expects */
749
- const fetchProps = async () => {
750
- const resultNode = await query({
751
- tag: 'iq',
752
- attrs: {
753
- to: S_WHATSAPP_NET,
754
- xmlns: 'w',
755
- type: 'get',
756
- },
757
- content: [
758
- {
759
- tag: 'props',
760
- attrs: {
761
- protocol: '2',
762
- hash: authState?.creds?.lastPropHash || ''
763
- }
764
- }
765
- ]
766
- })
767
-
768
- const propsNode = getBinaryNodeChild(resultNode, 'props')
769
-
770
-
771
- let props: {
772
- [_: string]: string } = {}
773
- if (propsNode) {
774
- authState.creds.lastPropHash = propsNode?.attrs?.hash
775
- ev.emit('creds.update', authState.creds)
776
- props = reduceBinaryNodeToDictionary(propsNode, 'prop')
777
- }
778
-
779
- logger.debug('fetched props')
780
-
781
- return props
782
- }
783
-
784
- /**
785
- * modify a chat -- mark unread, read etc.
786
- * lastMessages must be sorted in reverse chronologically
787
- * requires the last messages till the last message received; required for archive & unread
788
- */
789
- const chatModify = (mod: ChatModification, jid: string) => {
790
- const patch = chatModificationToAppPatch(mod, jid)
791
- return appPatch(patch)
792
- }
793
-
794
- /**
795
- * Star or Unstar a message
796
- */
797
- const star = (jid: string, messages: { id: string, fromMe ? : boolean } [], star: boolean) => {
798
- return chatModify({
799
- star: {
800
- messages,
801
- star
802
- }
803
- }, jid)
804
- }
805
-
806
- /**
807
- * Adds label for the chats
808
- */
809
- const addChatLabel = (jid: string, labelId: string) => {
810
- return chatModify({
811
- addChatLabel: {
812
- labelId
813
- }
814
- }, jid)
815
- }
816
-
817
- /**
818
- * Removes label for the chat
819
- */
820
- const removeChatLabel = (jid: string, labelId: string) => {
821
- return chatModify({
822
- removeChatLabel: {
823
- labelId
824
- }
825
- }, jid)
826
- }
827
-
828
- /**
829
- * Adds label for the message
830
- */
831
- const addMessageLabel = (jid: string, messageId: string, labelId: string) => {
832
- return chatModify({
833
- addMessageLabel: {
834
- messageId,
835
- labelId
836
- }
837
- }, jid)
838
- }
839
-
840
- /**
841
- * Removes label for the message
842
- */
843
- const removeMessageLabel = (jid: string, messageId: string, labelId: string) => {
844
- return chatModify({
845
- removeMessageLabel: {
846
- messageId,
847
- labelId
848
- }
849
- }, jid)
850
- }
851
-
852
- /**
853
- * queries need to be fired on connection open
854
- * help ensure parity with WA Web
855
- * */
856
- const executeInitQueries = async () => {
857
- await Promise.all([
858
- fetchProps(),
859
- fetchBlocklist(),
860
- fetchPrivacySettings(),
861
- ])
862
- }
863
-
864
- const upsertMessage = ev.createBufferedFunction(async (msg: WAMessage, type: MessageUpsertType) => {
865
- ev.emit('messages.upsert', { messages: [msg], type })
866
-
867
- if (!!msg.pushName) {
868
- let jid = msg.key.fromMe ? authState.creds.me!.id : (msg.key.participant || msg.key.remoteJid)
869
- jid = jidNormalizedUser(jid!)
870
-
871
- if (!msg.key.fromMe) {
872
- ev.emit('contacts.update', [{ id: jid, notify: msg.pushName, verifiedName: msg.verifiedBizName! }])
873
- }
874
-
875
- // update our pushname too
876
- if (msg.key.fromMe && msg.pushName && authState.creds.me?.name !== msg.pushName) {
877
- ev.emit('creds.update', { me: { ...authState.creds.me!, name: msg.pushName } })
878
- }
879
- }
880
-
881
- const historyMsg = getHistoryMsg(msg.message!)
882
- const shouldProcessHistoryMsg = historyMsg ?
883
- (
884
- shouldSyncHistoryMessage(historyMsg) &&
885
- PROCESSABLE_HISTORY_TYPES.includes(historyMsg.syncType!)
886
- ) :
887
- false
888
-
889
- if (historyMsg && !authState.creds.myAppStateKeyId) {
890
- logger.warn('skipping app state sync, as myAppStateKeyId is not set')
891
- pendingAppStateSync = true
892
- }
893
-
894
- await Promise.all([
895
- (async () => {
896
- if (
897
- historyMsg &&
898
- authState.creds.myAppStateKeyId
899
- ) {
900
- pendingAppStateSync = false
901
- await doAppStateSync()
902
- }
903
- })(),
904
- processMessage(
905
- msg,
906
- {
907
- shouldProcessHistoryMsg,
908
- ev,
909
- creds: authState.creds,
910
- keyStore: authState.keys,
911
- logger,
912
- options: config.options,
913
- getMessage: config.getMessage,
914
- }
915
- )
916
- ])
917
-
918
- if (
919
- msg.message?.protocolMessage?.appStateSyncKeyShare &&
920
- pendingAppStateSync
921
- ) {
922
- await doAppStateSync()
923
- pendingAppStateSync = false
924
- }
925
-
926
- async function doAppStateSync() {
927
- if (!authState.creds.accountSyncCounter) {
928
- logger.info('doing initial app state sync')
929
- await resyncAppState(ALL_WA_PATCH_NAMES, true)
930
-
931
- const accountSyncCounter = (authState.creds.accountSyncCounter || 0) + 1
932
- ev.emit('creds.update', { accountSyncCounter })
933
-
934
- if (needToFlushWithAppStateSync) {
935
- logger.debug('flushing with app state sync')
936
- ev.flush()
937
- }
938
- }
939
- }
940
- })
941
-
942
- ws.on('CB:presence', handlePresenceUpdate)
943
- ws.on('CB:chatstate', handlePresenceUpdate)
944
-
945
- ws.on('CB:ib,,dirty', async (node: BinaryNode) => {
946
- const { attrs } = getBinaryNodeChild(node, 'dirty') !
947
- const type = attrs.type
948
- switch (type) {
949
- case 'account_sync':
950
- if (attrs.timestamp) {
951
- let { lastAccountSyncTimestamp } = authState.creds
952
- if (lastAccountSyncTimestamp) {
953
- await cleanDirtyBits('account_sync', lastAccountSyncTimestamp)
954
- }
955
-
956
- lastAccountSyncTimestamp = +attrs.timestamp
957
- ev.emit('creds.update', { lastAccountSyncTimestamp })
958
- }
959
-
960
- break
961
- case 'groups':
962
- // handled in groups.ts
963
- break
964
- default:
965
- logger.info({ node }, 'received unknown sync')
966
- break
967
- }
968
- })
969
-
970
- ev.on('connection.update', ({ connection, receivedPendingNotifications }) => {
971
- if (connection === 'open') {
972
- if (fireInitQueries) {
973
- executeInitQueries()
974
- .catch(
975
- error => onUnexpectedError(error, 'init queries')
976
- )
977
- }
978
-
979
- sendPresenceUpdate(markOnlineOnConnect ? 'available' : 'unavailable')
980
- .catch(
981
- error => onUnexpectedError(error, 'presence update requests')
982
- )
983
- }
984
-
985
- if (receivedPendingNotifications) {
986
- // if we don't have the app state key
987
- // we keep buffering events until we finally have
988
- // the key and can sync the messages
989
- if (!authState.creds?.myAppStateKeyId && !config.mobile) {
990
- ev.buffer()
991
- needToFlushWithAppStateSync = true
992
- }
993
- }
994
- })
995
-
996
- return {
997
- ...sock,
998
- processingMutex,
999
- fetchPrivacySettings,
1000
- upsertMessage,
1001
- appPatch,
1002
- sendPresenceUpdate,
1003
- presenceSubscribe,
1004
- profilePictureUrl,
1005
- onWhatsApp,
1006
- fetchBlocklist,
1007
- fetchStatus,
1008
- updateProfilePicture,
1009
- removeProfilePicture,
1010
- updateProfileStatus,
1011
- updateProfileName,
1012
- updateBlockStatus,
1013
- updateLastSeenPrivacy,
1014
- updateOnlinePrivacy,
1015
- updateProfilePicturePrivacy,
1016
- updateStatusPrivacy,
1017
- updateReadReceiptsPrivacy,
1018
- updateGroupsAddPrivacy,
1019
- updateDefaultDisappearingMode,
1020
- getBusinessProfile,
1021
- resyncAppState,
1022
- chatModify,
1023
- cleanDirtyBits,
1024
- addChatLabel,
1025
- removeChatLabel,
1026
- addMessageLabel,
1027
- removeMessageLabel,
1028
- star
1029
- }
1030
- }