@sixcore/baileys 1.0.0 → 1.0.2

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 (228) hide show
  1. package/WAProto/index.js +14270 -302
  2. package/jessica.js +91 -0
  3. package/lib/Defaults/baileys-version.json +1 -1
  4. package/lib/Defaults/index.js +117 -79
  5. package/lib/Defaults/phonenumber-mcc.json +223 -0
  6. package/lib/Signal/Group/ciphertext-message.d.ts +9 -0
  7. package/lib/Signal/Group/ciphertext-message.js +15 -0
  8. package/lib/Signal/Group/group-session-builder.d.ts +14 -0
  9. package/lib/Signal/Group/group-session-builder.js +64 -0
  10. package/lib/Signal/Group/group_cipher.d.ts +17 -0
  11. package/lib/Signal/Group/group_cipher.js +96 -0
  12. package/lib/Signal/Group/index.d.ts +11 -0
  13. package/lib/Signal/Group/index.js +57 -0
  14. package/lib/Signal/Group/keyhelper.d.ts +10 -0
  15. package/lib/Signal/Group/keyhelper.js +55 -0
  16. package/lib/Signal/Group/queue-job.d.ts +1 -0
  17. package/lib/Signal/Group/queue-job.js +57 -0
  18. package/lib/Signal/Group/sender-chain-key.d.ts +13 -0
  19. package/lib/Signal/Group/sender-chain-key.js +34 -0
  20. package/lib/Signal/Group/sender-key-distribution-message.d.ts +16 -0
  21. package/lib/Signal/Group/sender-key-distribution-message.js +66 -0
  22. package/lib/Signal/Group/sender-key-message.d.ts +18 -0
  23. package/lib/Signal/Group/sender-key-message.js +69 -0
  24. package/lib/Signal/Group/sender-key-name.d.ts +17 -0
  25. package/lib/Signal/Group/sender-key-name.js +51 -0
  26. package/lib/Signal/Group/sender-key-record.d.ts +30 -0
  27. package/lib/Signal/Group/sender-key-record.js +53 -0
  28. package/lib/Signal/Group/sender-key-state.d.ts +38 -0
  29. package/lib/Signal/Group/sender-key-state.js +99 -0
  30. package/lib/Signal/Group/sender-message-key.d.ts +11 -0
  31. package/{WASignalGroup/sender_message_key.js → lib/Signal/Group/sender-message-key.js} +6 -16
  32. package/lib/Signal/libsignal.js +51 -29
  33. package/lib/Socket/business.d.ts +43 -42
  34. package/lib/Socket/chats.d.ts +222 -36
  35. package/lib/Socket/chats.js +173 -153
  36. package/lib/Socket/dugong.d.ts +254 -0
  37. package/lib/Socket/dugong.js +484 -0
  38. package/lib/Socket/groups.d.ts +7 -7
  39. package/lib/Socket/groups.js +37 -35
  40. package/lib/Socket/index.d.ts +52 -51
  41. package/lib/Socket/index.js +1 -0
  42. package/lib/Socket/messages-recv.d.ts +37 -34
  43. package/lib/Socket/messages-recv.js +175 -37
  44. package/lib/Socket/messages-send.d.ts +12 -18
  45. package/lib/Socket/messages-send.js +396 -574
  46. package/lib/Socket/newsletter.d.ts +28 -26
  47. package/lib/Socket/newsletter.js +132 -121
  48. package/lib/Socket/registration.d.ts +52 -49
  49. package/lib/Socket/registration.js +7 -7
  50. package/lib/Socket/socket.d.ts +0 -1
  51. package/lib/Socket/socket.js +49 -27
  52. package/lib/Socket/usync.d.ts +10 -11
  53. package/lib/Store/make-cache-manager-store.d.ts +1 -2
  54. package/lib/Store/make-in-memory-store.d.ts +2 -2
  55. package/lib/Store/make-in-memory-store.js +1 -5
  56. package/lib/Store/make-ordered-dictionary.js +2 -2
  57. package/lib/Types/Auth.d.ts +1 -0
  58. package/lib/Types/Call.d.ts +1 -1
  59. package/lib/Types/Chat.d.ts +7 -12
  60. package/lib/Types/Events.d.ts +2 -17
  61. package/lib/Types/GroupMetadata.d.ts +2 -3
  62. package/lib/Types/Label.d.ts +0 -11
  63. package/lib/Types/Label.js +1 -1
  64. package/lib/Types/LabelAssociation.js +1 -1
  65. package/lib/Types/Message.d.ts +10 -170
  66. package/lib/Types/Newsletter.d.ts +97 -86
  67. package/lib/Types/Newsletter.js +38 -32
  68. package/lib/Types/Socket.d.ts +2 -7
  69. package/lib/Types/index.d.ts +0 -9
  70. package/lib/Types/index.js +1 -1
  71. package/lib/Utils/auth-utils.js +14 -35
  72. package/lib/Utils/business.d.ts +1 -1
  73. package/lib/Utils/business.js +2 -2
  74. package/lib/Utils/chat-utils.d.ts +12 -11
  75. package/lib/Utils/chat-utils.js +36 -52
  76. package/lib/Utils/crypto.d.ts +16 -15
  77. package/lib/Utils/crypto.js +26 -74
  78. package/lib/Utils/decode-wa-message.d.ts +0 -17
  79. package/lib/Utils/decode-wa-message.js +17 -53
  80. package/lib/Utils/event-buffer.js +7 -10
  81. package/lib/Utils/generics.d.ts +17 -13
  82. package/lib/Utils/generics.js +79 -58
  83. package/lib/Utils/history.d.ts +2 -6
  84. package/lib/Utils/history.js +6 -4
  85. package/lib/Utils/logger.d.ts +3 -1
  86. package/lib/Utils/lt-hash.js +12 -12
  87. package/lib/Utils/make-mutex.d.ts +2 -2
  88. package/lib/Utils/messages-media.d.ts +28 -25
  89. package/lib/Utils/messages-media.js +733 -557
  90. package/lib/Utils/messages.js +68 -473
  91. package/lib/Utils/noise-handler.d.ts +5 -4
  92. package/lib/Utils/noise-handler.js +14 -19
  93. package/lib/Utils/process-message.d.ts +5 -5
  94. package/lib/Utils/process-message.js +23 -75
  95. package/lib/Utils/signal.d.ts +1 -2
  96. package/lib/Utils/signal.js +26 -32
  97. package/lib/Utils/use-multi-file-auth-state.d.ts +1 -0
  98. package/lib/Utils/use-multi-file-auth-state.js +66 -242
  99. package/lib/Utils/validate-connection.d.ts +1 -1
  100. package/lib/Utils/validate-connection.js +88 -64
  101. package/lib/WABinary/constants.d.ts +27 -24
  102. package/lib/WABinary/decode.d.ts +2 -1
  103. package/lib/WABinary/decode.js +11 -23
  104. package/lib/WABinary/encode.d.ts +2 -1
  105. package/lib/WABinary/encode.js +147 -134
  106. package/lib/WABinary/generic-utils.d.ts +5 -2
  107. package/lib/WABinary/generic-utils.js +125 -37
  108. package/lib/WABinary/jid-utils.d.ts +1 -1
  109. package/lib/WAM/BinaryInfo.d.ts +11 -2
  110. package/lib/WAM/encode.d.ts +2 -1
  111. package/lib/WAUSync/Protocols/USyncStatusProtocol.js +3 -3
  112. package/lib/WAUSync/USyncUser.d.ts +2 -0
  113. package/lib/index.d.ts +12 -0
  114. package/lib/index.js +64 -1
  115. package/package.json +113 -51
  116. package/WAProto/GenerateStatics.sh +0 -4
  117. package/WAProto/WAProto.proto +0 -4357
  118. package/WAProto/index.d.ts +0 -50383
  119. package/WASignalGroup/GroupProtocol.js +0 -1697
  120. package/WASignalGroup/ciphertext_message.js +0 -16
  121. package/WASignalGroup/generate-proto.sh +0 -1
  122. package/WASignalGroup/group.proto +0 -42
  123. package/WASignalGroup/group_cipher.js +0 -120
  124. package/WASignalGroup/group_session_builder.js +0 -46
  125. package/WASignalGroup/index.js +0 -5
  126. package/WASignalGroup/keyhelper.js +0 -21
  127. package/WASignalGroup/protobufs.js +0 -3
  128. package/WASignalGroup/queue_job.js +0 -69
  129. package/WASignalGroup/sender_chain_key.js +0 -50
  130. package/WASignalGroup/sender_key_distribution_message.js +0 -78
  131. package/WASignalGroup/sender_key_message.js +0 -92
  132. package/WASignalGroup/sender_key_name.js +0 -70
  133. package/WASignalGroup/sender_key_record.js +0 -56
  134. package/WASignalGroup/sender_key_state.js +0 -129
  135. package/lib/Utils/use-single-file-auth-state.d.ts +0 -12
  136. package/lib/Utils/use-single-file-auth-state.js +0 -75
  137. package/src/Defaults/baileys-version.json +0 -3
  138. package/src/Defaults/index.ts +0 -133
  139. package/src/Signal/Group/ciphertext-message.ts +0 -9
  140. package/src/Signal/Group/group-session-builder.ts +0 -56
  141. package/src/Signal/Group/group_cipher.ts +0 -117
  142. package/src/Signal/Group/index.ts +0 -11
  143. package/src/Signal/Group/keyhelper.ts +0 -28
  144. package/src/Signal/Group/sender-chain-key.ts +0 -34
  145. package/src/Signal/Group/sender-key-distribution-message.ts +0 -95
  146. package/src/Signal/Group/sender-key-message.ts +0 -96
  147. package/src/Signal/Group/sender-key-name.ts +0 -66
  148. package/src/Signal/Group/sender-key-record.ts +0 -69
  149. package/src/Signal/Group/sender-key-state.ts +0 -134
  150. package/src/Signal/Group/sender-message-key.ts +0 -36
  151. package/src/Signal/libsignal.ts +0 -447
  152. package/src/Signal/lid-mapping.ts +0 -209
  153. package/src/Socket/Client/index.ts +0 -2
  154. package/src/Socket/Client/types.ts +0 -22
  155. package/src/Socket/Client/websocket.ts +0 -56
  156. package/src/Socket/business.ts +0 -421
  157. package/src/Socket/chats.ts +0 -1223
  158. package/src/Socket/communities.ts +0 -477
  159. package/src/Socket/groups.ts +0 -361
  160. package/src/Socket/index.ts +0 -22
  161. package/src/Socket/messages-recv.ts +0 -1563
  162. package/src/Socket/messages-send.ts +0 -1210
  163. package/src/Socket/mex.ts +0 -58
  164. package/src/Socket/newsletter.ts +0 -229
  165. package/src/Socket/socket.ts +0 -1072
  166. package/src/Types/Auth.ts +0 -115
  167. package/src/Types/Bussines.ts +0 -20
  168. package/src/Types/Call.ts +0 -14
  169. package/src/Types/Chat.ts +0 -138
  170. package/src/Types/Contact.ts +0 -24
  171. package/src/Types/Events.ts +0 -132
  172. package/src/Types/GroupMetadata.ts +0 -70
  173. package/src/Types/Label.ts +0 -48
  174. package/src/Types/LabelAssociation.ts +0 -35
  175. package/src/Types/Message.ts +0 -424
  176. package/src/Types/Newsletter.ts +0 -98
  177. package/src/Types/Product.ts +0 -85
  178. package/src/Types/Signal.ts +0 -76
  179. package/src/Types/Socket.ts +0 -150
  180. package/src/Types/State.ts +0 -43
  181. package/src/Types/USync.ts +0 -27
  182. package/src/Types/globals.d.ts +0 -8
  183. package/src/Types/index.ts +0 -67
  184. package/src/Utils/auth-utils.ts +0 -331
  185. package/src/Utils/browser-utils.ts +0 -31
  186. package/src/Utils/business.ts +0 -286
  187. package/src/Utils/chat-utils.ts +0 -933
  188. package/src/Utils/crypto.ts +0 -184
  189. package/src/Utils/decode-wa-message.ts +0 -355
  190. package/src/Utils/event-buffer.ts +0 -662
  191. package/src/Utils/generics.ts +0 -470
  192. package/src/Utils/history.ts +0 -114
  193. package/src/Utils/index.ts +0 -18
  194. package/src/Utils/link-preview.ts +0 -111
  195. package/src/Utils/logger.ts +0 -13
  196. package/src/Utils/lt-hash.ts +0 -65
  197. package/src/Utils/make-mutex.ts +0 -45
  198. package/src/Utils/message-retry-manager.ts +0 -229
  199. package/src/Utils/messages-media.ts +0 -820
  200. package/src/Utils/messages.ts +0 -1137
  201. package/src/Utils/noise-handler.ts +0 -192
  202. package/src/Utils/pre-key-manager.ts +0 -126
  203. package/src/Utils/process-message.ts +0 -622
  204. package/src/Utils/signal.ts +0 -214
  205. package/src/Utils/use-multi-file-auth-state.ts +0 -136
  206. package/src/Utils/validate-connection.ts +0 -253
  207. package/src/WABinary/constants.ts +0 -1305
  208. package/src/WABinary/decode.ts +0 -281
  209. package/src/WABinary/encode.ts +0 -253
  210. package/src/WABinary/generic-utils.ts +0 -127
  211. package/src/WABinary/index.ts +0 -5
  212. package/src/WABinary/jid-utils.ts +0 -128
  213. package/src/WABinary/types.ts +0 -17
  214. package/src/WAM/BinaryInfo.ts +0 -12
  215. package/src/WAM/constants.ts +0 -22889
  216. package/src/WAM/encode.ts +0 -169
  217. package/src/WAM/index.ts +0 -3
  218. package/src/WAUSync/Protocols/USyncContactProtocol.ts +0 -32
  219. package/src/WAUSync/Protocols/USyncDeviceProtocol.ts +0 -78
  220. package/src/WAUSync/Protocols/USyncDisappearingModeProtocol.ts +0 -35
  221. package/src/WAUSync/Protocols/USyncStatusProtocol.ts +0 -44
  222. package/src/WAUSync/Protocols/UsyncBotProfileProtocol.ts +0 -76
  223. package/src/WAUSync/Protocols/UsyncLIDProtocol.ts +0 -33
  224. package/src/WAUSync/Protocols/index.ts +0 -4
  225. package/src/WAUSync/USyncQuery.ts +0 -133
  226. package/src/WAUSync/USyncUser.ts +0 -32
  227. package/src/WAUSync/index.ts +0 -3
  228. package/src/index.ts +0 -13
@@ -1,214 +0,0 @@
1
- import { KEY_BUNDLE_TYPE } from '../Defaults'
2
- import type { SignalRepositoryWithLIDStore } from '../Types'
3
- import type {
4
- AuthenticationCreds,
5
- AuthenticationState,
6
- KeyPair,
7
- SignalIdentity,
8
- SignalKeyStore,
9
- SignedKeyPair
10
- } from '../Types/Auth'
11
- import {
12
- assertNodeErrorFree,
13
- type BinaryNode,
14
- type FullJid,
15
- getBinaryNodeChild,
16
- getBinaryNodeChildBuffer,
17
- getBinaryNodeChildren,
18
- getBinaryNodeChildUInt,
19
- getServerFromDomainType,
20
- jidDecode,
21
- S_WHATSAPP_NET,
22
- WAJIDDomains
23
- } from '../WABinary'
24
- import type { DeviceListData, ParsedDeviceInfo, USyncQueryResultList } from '../WAUSync'
25
- import { Curve, generateSignalPubKey } from './crypto'
26
- import { encodeBigEndian } from './generics'
27
-
28
- function chunk<T>(array: T[], size: number): T[][] {
29
- const chunks: T[][] = []
30
- for (let i = 0; i < array.length; i += size) {
31
- chunks.push(array.slice(i, i + size))
32
- }
33
-
34
- return chunks
35
- }
36
-
37
- export const createSignalIdentity = (wid: string, accountSignatureKey: Uint8Array): SignalIdentity => {
38
- return {
39
- identifier: { name: wid, deviceId: 0 },
40
- identifierKey: generateSignalPubKey(accountSignatureKey)
41
- }
42
- }
43
-
44
- export const getPreKeys = async ({ get }: SignalKeyStore, min: number, limit: number) => {
45
- const idList: string[] = []
46
- for (let id = min; id < limit; id++) {
47
- idList.push(id.toString())
48
- }
49
-
50
- return get('pre-key', idList)
51
- }
52
-
53
- export const generateOrGetPreKeys = (creds: AuthenticationCreds, range: number) => {
54
- const avaliable = creds.nextPreKeyId - creds.firstUnuploadedPreKeyId
55
- const remaining = range - avaliable
56
- const lastPreKeyId = creds.nextPreKeyId + remaining - 1
57
- const newPreKeys: { [id: number]: KeyPair } = {}
58
- if (remaining > 0) {
59
- for (let i = creds.nextPreKeyId; i <= lastPreKeyId; i++) {
60
- newPreKeys[i] = Curve.generateKeyPair()
61
- }
62
- }
63
-
64
- return {
65
- newPreKeys,
66
- lastPreKeyId,
67
- preKeysRange: [creds.firstUnuploadedPreKeyId, range] as const
68
- }
69
- }
70
-
71
- export const xmppSignedPreKey = (key: SignedKeyPair): BinaryNode => ({
72
- tag: 'skey',
73
- attrs: {},
74
- content: [
75
- { tag: 'id', attrs: {}, content: encodeBigEndian(key.keyId, 3) },
76
- { tag: 'value', attrs: {}, content: key.keyPair.public },
77
- { tag: 'signature', attrs: {}, content: key.signature }
78
- ]
79
- })
80
-
81
- export const xmppPreKey = (pair: KeyPair, id: number): BinaryNode => ({
82
- tag: 'key',
83
- attrs: {},
84
- content: [
85
- { tag: 'id', attrs: {}, content: encodeBigEndian(id, 3) },
86
- { tag: 'value', attrs: {}, content: pair.public }
87
- ]
88
- })
89
-
90
- export const parseAndInjectE2ESessions = async (node: BinaryNode, repository: SignalRepositoryWithLIDStore) => {
91
- const extractKey = (key: BinaryNode) =>
92
- key
93
- ? {
94
- keyId: getBinaryNodeChildUInt(key, 'id', 3)!,
95
- publicKey: generateSignalPubKey(getBinaryNodeChildBuffer(key, 'value')!),
96
- signature: getBinaryNodeChildBuffer(key, 'signature')!
97
- }
98
- : undefined
99
- const nodes = getBinaryNodeChildren(getBinaryNodeChild(node, 'list'), 'user')
100
- for (const node of nodes) {
101
- assertNodeErrorFree(node)
102
- }
103
-
104
- // Most of the work in repository.injectE2ESession is CPU intensive, not IO
105
- // So Promise.all doesn't really help here,
106
- // but blocks even loop if we're using it inside keys.transaction, and it makes it "sync" actually
107
- // This way we chunk it in smaller parts and between those parts we can yield to the event loop
108
- // It's rare case when you need to E2E sessions for so many users, but it's possible
109
- const chunkSize = 100
110
- const chunks = chunk(nodes, chunkSize)
111
-
112
- for (const nodesChunk of chunks) {
113
- for (const node of nodesChunk) {
114
- const signedKey = getBinaryNodeChild(node, 'skey')!
115
- const key = getBinaryNodeChild(node, 'key')!
116
- const identity = getBinaryNodeChildBuffer(node, 'identity')!
117
- const jid = node.attrs.jid!
118
-
119
- const registrationId = getBinaryNodeChildUInt(node, 'registration', 4)
120
-
121
- await repository.injectE2ESession({
122
- jid,
123
- session: {
124
- registrationId: registrationId!,
125
- identityKey: generateSignalPubKey(identity),
126
- signedPreKey: extractKey(signedKey)!,
127
- preKey: extractKey(key)!
128
- }
129
- })
130
- }
131
- }
132
- }
133
-
134
- export const extractDeviceJids = (
135
- result: USyncQueryResultList[],
136
- myJid: string,
137
- myLid: string,
138
- excludeZeroDevices: boolean
139
- ) => {
140
- const { user: myUser, device: myDevice } = jidDecode(myJid)!
141
-
142
- const extracted: FullJid[] = []
143
-
144
- for (const userResult of result) {
145
- const { devices, id } = userResult as { devices: ParsedDeviceInfo; id: string }
146
- const decoded = jidDecode(id)!,
147
- { user, server } = decoded
148
- let { domainType } = decoded
149
- const deviceList = devices?.deviceList as DeviceListData[]
150
- if (!Array.isArray(deviceList)) continue
151
- for (const { id: device, keyIndex, isHosted } of deviceList) {
152
- if (
153
- (!excludeZeroDevices || device !== 0) && // if zero devices are not-excluded, or device is non zero
154
- ((myUser !== user && myLid !== user) || myDevice !== device) && // either different user or if me user, not this device
155
- (device === 0 || !!keyIndex) // ensure that "key-index" is specified for "non-zero" devices, produces a bad req otherwise
156
- ) {
157
- if (isHosted) {
158
- domainType = domainType === WAJIDDomains.LID ? WAJIDDomains.HOSTED_LID : WAJIDDomains.HOSTED
159
- }
160
-
161
- extracted.push({
162
- user,
163
- device,
164
- domainType,
165
- server: getServerFromDomainType(server, domainType)
166
- })
167
- }
168
- }
169
- }
170
-
171
- return extracted
172
- }
173
-
174
- /**
175
- * get the next N keys for upload or processing
176
- * @param count number of pre-keys to get or generate
177
- */
178
- export const getNextPreKeys = async ({ creds, keys }: AuthenticationState, count: number) => {
179
- const { newPreKeys, lastPreKeyId, preKeysRange } = generateOrGetPreKeys(creds, count)
180
-
181
- const update: Partial<AuthenticationCreds> = {
182
- nextPreKeyId: Math.max(lastPreKeyId + 1, creds.nextPreKeyId),
183
- firstUnuploadedPreKeyId: Math.max(creds.firstUnuploadedPreKeyId, lastPreKeyId + 1)
184
- }
185
-
186
- await keys.set({ 'pre-key': newPreKeys })
187
-
188
- const preKeys = await getPreKeys(keys, preKeysRange[0], preKeysRange[0] + preKeysRange[1])
189
-
190
- return { update, preKeys }
191
- }
192
-
193
- export const getNextPreKeysNode = async (state: AuthenticationState, count: number) => {
194
- const { creds } = state
195
- const { update, preKeys } = await getNextPreKeys(state, count)
196
-
197
- const node: BinaryNode = {
198
- tag: 'iq',
199
- attrs: {
200
- xmlns: 'encrypt',
201
- type: 'set',
202
- to: S_WHATSAPP_NET
203
- },
204
- content: [
205
- { tag: 'registration', attrs: {}, content: encodeBigEndian(creds.registrationId) },
206
- { tag: 'type', attrs: {}, content: KEY_BUNDLE_TYPE },
207
- { tag: 'identity', attrs: {}, content: creds.signedIdentityKey.public },
208
- { tag: 'list', attrs: {}, content: Object.keys(preKeys).map(k => xmppPreKey(preKeys[+k]!, +k)) },
209
- xmppSignedPreKey(creds.signedPreKey)
210
- ]
211
- }
212
-
213
- return { update, node }
214
- }
@@ -1,136 +0,0 @@
1
- import { Mutex } from 'async-mutex'
2
- import { mkdir, readFile, stat, unlink, writeFile } from 'fs/promises'
3
- import { join } from 'path'
4
- import { proto } from '../../WAProto/index.js'
5
- import type { AuthenticationCreds, AuthenticationState, SignalDataTypeMap } from '../Types'
6
- import { initAuthCreds } from './auth-utils'
7
- import { BufferJSON } from './generics'
8
-
9
- // We need to lock files due to the fact that we are using async functions to read and write files
10
- // https://github.com/WhiskeySockets/Baileys/issues/794
11
- // https://github.com/nodejs/node/issues/26338
12
- // Use a Map to store mutexes for each file path
13
- const fileLocks = new Map<string, Mutex>()
14
-
15
- // Get or create a mutex for a specific file path
16
- const getFileLock = (path: string): Mutex => {
17
- let mutex = fileLocks.get(path)
18
- if (!mutex) {
19
- mutex = new Mutex()
20
- fileLocks.set(path, mutex)
21
- }
22
-
23
- return mutex
24
- }
25
-
26
- /**
27
- * stores the full authentication state in a single folder.
28
- * Far more efficient than singlefileauthstate
29
- *
30
- * Again, I wouldn't endorse this for any production level use other than perhaps a bot.
31
- * Would recommend writing an auth state for use with a proper SQL or No-SQL DB
32
- * */
33
- export const useMultiFileAuthState = async (
34
- folder: string
35
- ): Promise<{ state: AuthenticationState; saveCreds: () => Promise<void> }> => {
36
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
37
- const writeData = async (data: any, file: string) => {
38
- const filePath = join(folder, fixFileName(file)!)
39
- const mutex = getFileLock(filePath)
40
-
41
- return mutex.acquire().then(async release => {
42
- try {
43
- await writeFile(filePath, JSON.stringify(data, BufferJSON.replacer))
44
- } finally {
45
- release()
46
- }
47
- })
48
- }
49
-
50
- const readData = async (file: string) => {
51
- try {
52
- const filePath = join(folder, fixFileName(file)!)
53
- const mutex = getFileLock(filePath)
54
-
55
- return await mutex.acquire().then(async release => {
56
- try {
57
- const data = await readFile(filePath, { encoding: 'utf-8' })
58
- return JSON.parse(data, BufferJSON.reviver)
59
- } finally {
60
- release()
61
- }
62
- })
63
- } catch (error) {
64
- return null
65
- }
66
- }
67
-
68
- const removeData = async (file: string) => {
69
- try {
70
- const filePath = join(folder, fixFileName(file)!)
71
- const mutex = getFileLock(filePath)
72
-
73
- return mutex.acquire().then(async release => {
74
- try {
75
- await unlink(filePath)
76
- } catch {
77
- } finally {
78
- release()
79
- }
80
- })
81
- } catch {}
82
- }
83
-
84
- const folderInfo = await stat(folder).catch(() => {})
85
- if (folderInfo) {
86
- if (!folderInfo.isDirectory()) {
87
- throw new Error(
88
- `found something that is not a directory at ${folder}, either delete it or specify a different location`
89
- )
90
- }
91
- } else {
92
- await mkdir(folder, { recursive: true })
93
- }
94
-
95
- const fixFileName = (file?: string) => file?.replace(/\//g, '__')?.replace(/:/g, '-')
96
-
97
- const creds: AuthenticationCreds = (await readData('creds.json')) || initAuthCreds()
98
-
99
- return {
100
- state: {
101
- creds,
102
- keys: {
103
- get: async (type, ids) => {
104
- const data: { [_: string]: SignalDataTypeMap[typeof type] } = {}
105
- await Promise.all(
106
- ids.map(async id => {
107
- let value = await readData(`${type}-${id}.json`)
108
- if (type === 'app-state-sync-key' && value) {
109
- value = proto.Message.AppStateSyncKeyData.fromObject(value)
110
- }
111
-
112
- data[id] = value
113
- })
114
- )
115
-
116
- return data
117
- },
118
- set: async data => {
119
- const tasks: Promise<void>[] = []
120
- for (const category in data) {
121
- for (const id in data[category as keyof SignalDataTypeMap]) {
122
- const value = data[category as keyof SignalDataTypeMap]![id]
123
- const file = `${category}-${id}.json`
124
- tasks.push(value ? writeData(value, file) : removeData(file))
125
- }
126
- }
127
-
128
- await Promise.all(tasks)
129
- }
130
- }
131
- },
132
- saveCreds: async () => {
133
- return writeData(creds, 'creds.json')
134
- }
135
- }
136
- }
@@ -1,253 +0,0 @@
1
- import { Boom } from '@hapi/boom'
2
- import { createHash } from 'crypto'
3
- import { proto } from '../../WAProto/index.js'
4
- import {
5
- KEY_BUNDLE_TYPE,
6
- WA_ADV_ACCOUNT_SIG_PREFIX,
7
- WA_ADV_DEVICE_SIG_PREFIX,
8
- WA_ADV_HOSTED_ACCOUNT_SIG_PREFIX
9
- } from '../Defaults'
10
- import type { AuthenticationCreds, SignalCreds, SocketConfig } from '../Types'
11
- import { type BinaryNode, getBinaryNodeChild, jidDecode, S_WHATSAPP_NET } from '../WABinary'
12
- import { Curve, hmacSign } from './crypto'
13
- import { encodeBigEndian } from './generics'
14
- import { createSignalIdentity } from './signal'
15
-
16
- const getUserAgent = (config: SocketConfig): proto.ClientPayload.IUserAgent => {
17
- return {
18
- appVersion: {
19
- primary: config.version[0],
20
- secondary: config.version[1],
21
- tertiary: config.version[2]
22
- },
23
- platform: proto.ClientPayload.UserAgent.Platform.WEB,
24
- releaseChannel: proto.ClientPayload.UserAgent.ReleaseChannel.RELEASE,
25
- osVersion: '0.1',
26
- device: 'Desktop',
27
- osBuildNumber: '0.1',
28
- localeLanguageIso6391: 'en',
29
-
30
- mnc: '000',
31
- mcc: '000',
32
- localeCountryIso31661Alpha2: config.countryCode
33
- }
34
- }
35
-
36
- const PLATFORM_MAP = {
37
- 'Mac OS': proto.ClientPayload.WebInfo.WebSubPlatform.DARWIN,
38
- Windows: proto.ClientPayload.WebInfo.WebSubPlatform.WIN32
39
- }
40
-
41
- const getWebInfo = (config: SocketConfig): proto.ClientPayload.IWebInfo => {
42
- let webSubPlatform = proto.ClientPayload.WebInfo.WebSubPlatform.WEB_BROWSER
43
- if (
44
- config.syncFullHistory &&
45
- PLATFORM_MAP[config.browser[0] as keyof typeof PLATFORM_MAP] &&
46
- config.browser[1] === 'Desktop'
47
- ) {
48
- webSubPlatform = PLATFORM_MAP[config.browser[0] as keyof typeof PLATFORM_MAP]
49
- }
50
-
51
- return { webSubPlatform }
52
- }
53
-
54
- const getClientPayload = (config: SocketConfig) => {
55
- const payload: proto.IClientPayload = {
56
- connectType: proto.ClientPayload.ConnectType.WIFI_UNKNOWN,
57
- connectReason: proto.ClientPayload.ConnectReason.USER_ACTIVATED,
58
- userAgent: getUserAgent(config)
59
- }
60
-
61
- payload.webInfo = getWebInfo(config)
62
-
63
- return payload
64
- }
65
-
66
- export const generateLoginNode = (userJid: string, config: SocketConfig): proto.IClientPayload => {
67
- const { user, device } = jidDecode(userJid)!
68
- const payload: proto.IClientPayload = {
69
- ...getClientPayload(config),
70
- passive: true,
71
- pull: true,
72
- username: +user,
73
- device: device,
74
- // TODO: investigate (hard set as false atm)
75
- lidDbMigrated: false
76
- }
77
- return proto.ClientPayload.fromObject(payload)
78
- }
79
-
80
- const getPlatformType = (platform: string): proto.DeviceProps.PlatformType => {
81
- const platformType = platform.toUpperCase()
82
- return (
83
- proto.DeviceProps.PlatformType[platformType as keyof typeof proto.DeviceProps.PlatformType] ||
84
- proto.DeviceProps.PlatformType.CHROME
85
- )
86
- }
87
-
88
- export const generateRegistrationNode = (
89
- { registrationId, signedPreKey, signedIdentityKey }: SignalCreds,
90
- config: SocketConfig
91
- ) => {
92
- // the app version needs to be md5 hashed
93
- // and passed in
94
- const appVersionBuf = createHash('md5')
95
- .update(config.version.join('.')) // join as string
96
- .digest()
97
-
98
- const companion: proto.IDeviceProps = {
99
- os: config.browser[0],
100
- platformType: getPlatformType(config.browser[1]),
101
- requireFullSync: config.syncFullHistory,
102
- historySyncConfig: {
103
- storageQuotaMb: 10240,
104
- inlineInitialPayloadInE2EeMsg: true,
105
- recentSyncDaysLimit: undefined,
106
- supportCallLogHistory: false,
107
- supportBotUserAgentChatHistory: true,
108
- supportCagReactionsAndPolls: true,
109
- supportBizHostedMsg: true,
110
- supportRecentSyncChunkMessageCountTuning: true,
111
- supportHostedGroupMsg: true,
112
- supportFbidBotChatHistory: true,
113
- supportAddOnHistorySyncMigration: undefined,
114
- supportMessageAssociation: true,
115
- supportGroupHistory: false,
116
- onDemandReady: undefined,
117
- supportGuestChat: undefined
118
- },
119
- version: {
120
- primary: 10,
121
- secondary: 15,
122
- tertiary: 7
123
- }
124
- }
125
-
126
- const companionProto = proto.DeviceProps.encode(companion).finish()
127
-
128
- const registerPayload: proto.IClientPayload = {
129
- ...getClientPayload(config),
130
- passive: false,
131
- pull: false,
132
- devicePairingData: {
133
- buildHash: appVersionBuf,
134
- deviceProps: companionProto,
135
- eRegid: encodeBigEndian(registrationId),
136
- eKeytype: KEY_BUNDLE_TYPE,
137
- eIdent: signedIdentityKey.public,
138
- eSkeyId: encodeBigEndian(signedPreKey.keyId, 3),
139
- eSkeyVal: signedPreKey.keyPair.public,
140
- eSkeySig: signedPreKey.signature
141
- }
142
- }
143
-
144
- return proto.ClientPayload.fromObject(registerPayload)
145
- }
146
-
147
- export const configureSuccessfulPairing = (
148
- stanza: BinaryNode,
149
- {
150
- advSecretKey,
151
- signedIdentityKey,
152
- signalIdentities
153
- }: Pick<AuthenticationCreds, 'advSecretKey' | 'signedIdentityKey' | 'signalIdentities'>
154
- ) => {
155
- const msgId = stanza.attrs.id
156
-
157
- const pairSuccessNode = getBinaryNodeChild(stanza, 'pair-success')
158
-
159
- const deviceIdentityNode = getBinaryNodeChild(pairSuccessNode, 'device-identity')
160
- const platformNode = getBinaryNodeChild(pairSuccessNode, 'platform')
161
- const deviceNode = getBinaryNodeChild(pairSuccessNode, 'device')
162
- const businessNode = getBinaryNodeChild(pairSuccessNode, 'biz')
163
-
164
- if (!deviceIdentityNode || !deviceNode) {
165
- throw new Boom('Missing device-identity or device in pair success node', { data: stanza })
166
- }
167
-
168
- const bizName = businessNode?.attrs.name
169
- const jid = deviceNode.attrs.jid
170
- const lid = deviceNode.attrs.lid
171
-
172
- const { details, hmac, accountType } = proto.ADVSignedDeviceIdentityHMAC.decode(deviceIdentityNode.content as Buffer)
173
-
174
- let hmacPrefix = Buffer.from([])
175
- if (accountType !== undefined && accountType === proto.ADVEncryptionType.HOSTED) {
176
- hmacPrefix = WA_ADV_HOSTED_ACCOUNT_SIG_PREFIX
177
- }
178
-
179
- const advSign = hmacSign(Buffer.concat([hmacPrefix, details!]), Buffer.from(advSecretKey, 'base64'))
180
- if (Buffer.compare(hmac!, advSign) !== 0) {
181
- throw new Boom('Invalid account signature')
182
- }
183
-
184
- const account = proto.ADVSignedDeviceIdentity.decode(details!)
185
- const { accountSignatureKey, accountSignature, details: deviceDetails } = account
186
-
187
- const deviceIdentity = proto.ADVDeviceIdentity.decode(deviceDetails!)
188
-
189
- const accountSignaturePrefix =
190
- deviceIdentity.deviceType === proto.ADVEncryptionType.HOSTED
191
- ? WA_ADV_HOSTED_ACCOUNT_SIG_PREFIX
192
- : WA_ADV_ACCOUNT_SIG_PREFIX
193
- const accountMsg = Buffer.concat([accountSignaturePrefix, deviceDetails!, signedIdentityKey.public])
194
- if (!Curve.verify(accountSignatureKey!, accountMsg, accountSignature!)) {
195
- throw new Boom('Failed to verify account signature')
196
- }
197
-
198
- const deviceMsg = Buffer.concat([
199
- WA_ADV_DEVICE_SIG_PREFIX,
200
- deviceDetails!,
201
- signedIdentityKey.public,
202
- accountSignatureKey!
203
- ])
204
- account.deviceSignature = Curve.sign(signedIdentityKey.private, deviceMsg)
205
-
206
- const identity = createSignalIdentity(lid!, accountSignatureKey!)
207
- const accountEnc = encodeSignedDeviceIdentity(account, false)
208
-
209
- const reply: BinaryNode = {
210
- tag: 'iq',
211
- attrs: {
212
- to: S_WHATSAPP_NET,
213
- type: 'result',
214
- id: msgId!
215
- },
216
- content: [
217
- {
218
- tag: 'pair-device-sign',
219
- attrs: {},
220
- content: [
221
- {
222
- tag: 'device-identity',
223
- attrs: { 'key-index': deviceIdentity.keyIndex!.toString() },
224
- content: accountEnc
225
- }
226
- ]
227
- }
228
- ]
229
- }
230
-
231
- const authUpdate: Partial<AuthenticationCreds> = {
232
- account,
233
- me: { id: jid!, name: bizName, lid },
234
- signalIdentities: [...(signalIdentities || []), identity],
235
- platform: platformNode?.attrs.name
236
- }
237
-
238
- return {
239
- creds: authUpdate,
240
- reply
241
- }
242
- }
243
-
244
- export const encodeSignedDeviceIdentity = (account: proto.IADVSignedDeviceIdentity, includeSignatureKey: boolean) => {
245
- account = { ...account }
246
- // set to null if we are not to include the signature key
247
- // or if we are including the signature key but it is empty
248
- if (!includeSignatureKey || !account.accountSignatureKey?.length) {
249
- account.accountSignatureKey = null
250
- }
251
-
252
- return proto.ADVSignedDeviceIdentity.encode(account).finish()
253
- }