@neelegirl/baileys 2.1.5 → 2.1.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.
@@ -0,0 +1,277 @@
1
+ "use strict"
2
+
3
+ Object.defineProperty(exports, "__esModule", { value: true })
4
+
5
+ const { LRUCache } = require("lru-cache")
6
+ const WABinary_1 = require("../WABinary")
7
+
8
+ class LIDMappingStore {
9
+ constructor(keys, logger, pnToLIDFunc) {
10
+ this.mappingCache = new LRUCache({
11
+ ttl: 3 * 24 * 60 * 60 * 1000,
12
+ ttlAutopurge: true,
13
+ updateAgeOnGet: true
14
+ })
15
+ this.inflightLIDLookups = new Map()
16
+ this.inflightPNLookups = new Map()
17
+ this.keys = keys
18
+ this.logger = logger
19
+ this.pnToLIDFunc = pnToLIDFunc
20
+ }
21
+ async storeLIDPNMappings(pairs) {
22
+ if (!pairs?.length) {
23
+ return
24
+ }
25
+ const validatedPairs = []
26
+ for (const { lid, pn } of pairs) {
27
+ const validDirection = ((0, WABinary_1.isLidUser)(lid) || (0, WABinary_1.isHostedLidUser)(lid))
28
+ && ((0, WABinary_1.isPnUser)(pn) || (0, WABinary_1.isHostedPnUser)(pn))
29
+ const reverseDirection = ((0, WABinary_1.isPnUser)(lid) || (0, WABinary_1.isHostedPnUser)(lid))
30
+ && ((0, WABinary_1.isLidUser)(pn) || (0, WABinary_1.isHostedLidUser)(pn))
31
+ if (!validDirection && !reverseDirection) {
32
+ this.logger?.warn?.({ lid, pn }, 'invalid LID-PN mapping')
33
+ continue
34
+ }
35
+ const lidJid = validDirection ? lid : pn
36
+ const pnJid = validDirection ? pn : lid
37
+ const lidDecoded = (0, WABinary_1.jidDecode)(lidJid)
38
+ const pnDecoded = (0, WABinary_1.jidDecode)(pnJid)
39
+ if (!lidDecoded?.user || !pnDecoded?.user) {
40
+ continue
41
+ }
42
+ validatedPairs.push({
43
+ pnUser: pnDecoded.user,
44
+ lidUser: lidDecoded.user
45
+ })
46
+ }
47
+ if (!validatedPairs.length) {
48
+ return
49
+ }
50
+ const cacheMissSet = new Set()
51
+ const existingMappings = new Map()
52
+ for (const { pnUser } of validatedPairs) {
53
+ const cached = this.mappingCache.get(`pn:${pnUser}`)
54
+ if (cached) {
55
+ existingMappings.set(pnUser, cached)
56
+ }
57
+ else {
58
+ cacheMissSet.add(pnUser)
59
+ }
60
+ }
61
+ if (cacheMissSet.size) {
62
+ const cacheMisses = [...cacheMissSet]
63
+ this.logger?.trace?.({ count: cacheMisses.length }, 'loading LID mappings from store')
64
+ const stored = await this.keys.get('lid-mapping', cacheMisses)
65
+ for (const pnUser of cacheMisses) {
66
+ const existingLidUser = stored[pnUser]
67
+ if (existingLidUser) {
68
+ existingMappings.set(pnUser, existingLidUser)
69
+ this.mappingCache.set(`pn:${pnUser}`, existingLidUser)
70
+ this.mappingCache.set(`lid:${existingLidUser}`, pnUser)
71
+ }
72
+ }
73
+ }
74
+ const pairMap = {}
75
+ for (const { pnUser, lidUser } of validatedPairs) {
76
+ const existingLidUser = existingMappings.get(pnUser)
77
+ if (existingLidUser === lidUser) {
78
+ continue
79
+ }
80
+ pairMap[pnUser] = lidUser
81
+ }
82
+ if (!Object.keys(pairMap).length) {
83
+ return
84
+ }
85
+ const batchData = {}
86
+ for (const [pnUser, lidUser] of Object.entries(pairMap)) {
87
+ batchData[pnUser] = lidUser
88
+ batchData[`${lidUser}_reverse`] = pnUser
89
+ }
90
+ await this.keys.transaction(async () => {
91
+ await this.keys.set({ 'lid-mapping': batchData })
92
+ }, 'lid-mapping')
93
+ for (const [pnUser, lidUser] of Object.entries(pairMap)) {
94
+ this.mappingCache.set(`pn:${pnUser}`, lidUser)
95
+ this.mappingCache.set(`lid:${lidUser}`, pnUser)
96
+ }
97
+ }
98
+ async getLIDForPN(pn) {
99
+ return (await this.getLIDsForPNs([pn]))?.[0]?.lid || null
100
+ }
101
+ async getLIDsForPNs(pns) {
102
+ if (!pns?.length) {
103
+ return null
104
+ }
105
+ const sortedPns = [...new Set(pns)].sort()
106
+ const cacheKey = sortedPns.join(',')
107
+ const inflight = this.inflightLIDLookups.get(cacheKey)
108
+ if (inflight) {
109
+ return inflight
110
+ }
111
+ const promise = this._getLIDsForPNsImpl(pns)
112
+ this.inflightLIDLookups.set(cacheKey, promise)
113
+ try {
114
+ return await promise
115
+ }
116
+ finally {
117
+ this.inflightLIDLookups.delete(cacheKey)
118
+ }
119
+ }
120
+ async _getLIDsForPNsImpl(pns) {
121
+ const usyncFetch = {}
122
+ const successfulPairs = {}
123
+ const pending = []
124
+ const addResolvedPair = (pn, decoded, lidUser) => {
125
+ if (!decoded || !lidUser) {
126
+ return false
127
+ }
128
+ const pnDevice = decoded.device !== undefined ? decoded.device : 0
129
+ const deviceSpecificLid = `${lidUser}${pnDevice ? `:${pnDevice}` : ''}@${decoded.server === 'hosted' ? 'hosted.lid' : 'lid'}`
130
+ successfulPairs[pn] = { lid: deviceSpecificLid, pn }
131
+ return true
132
+ }
133
+ for (const pn of pns) {
134
+ if (!(0, WABinary_1.isPnUser)(pn) && !(0, WABinary_1.isHostedPnUser)(pn)) {
135
+ continue
136
+ }
137
+ const decoded = (0, WABinary_1.jidDecode)(pn)
138
+ if (!decoded?.user) {
139
+ continue
140
+ }
141
+ const pnUser = decoded.user
142
+ const cached = this.mappingCache.get(`pn:${pnUser}`)
143
+ if (cached && typeof cached === 'string') {
144
+ addResolvedPair(pn, decoded, cached)
145
+ continue
146
+ }
147
+ pending.push({ pn, pnUser, decoded })
148
+ }
149
+ if (pending.length) {
150
+ const pnUsers = [...new Set(pending.map(item => item.pnUser))]
151
+ const stored = await this.keys.get('lid-mapping', pnUsers)
152
+ for (const pnUser of pnUsers) {
153
+ const lidUser = stored[pnUser]
154
+ if (lidUser && typeof lidUser === 'string') {
155
+ this.mappingCache.set(`pn:${pnUser}`, lidUser)
156
+ this.mappingCache.set(`lid:${lidUser}`, pnUser)
157
+ }
158
+ }
159
+ for (const { pn, pnUser, decoded } of pending) {
160
+ const cached = this.mappingCache.get(`pn:${pnUser}`)
161
+ if (cached && typeof cached === 'string') {
162
+ addResolvedPair(pn, decoded, cached)
163
+ continue
164
+ }
165
+ const device = decoded.device || 0
166
+ let normalizedPn = (0, WABinary_1.jidNormalizedUser)(pn)
167
+ if ((0, WABinary_1.isHostedPnUser)(normalizedPn)) {
168
+ normalizedPn = `${pnUser}@s.whatsapp.net`
169
+ }
170
+ if (!usyncFetch[normalizedPn]) {
171
+ usyncFetch[normalizedPn] = [device]
172
+ }
173
+ else {
174
+ usyncFetch[normalizedPn].push(device)
175
+ }
176
+ }
177
+ }
178
+ if (Object.keys(usyncFetch).length) {
179
+ const result = await this.pnToLIDFunc?.(Object.keys(usyncFetch))
180
+ if (result?.length) {
181
+ await this.storeLIDPNMappings(result)
182
+ for (const pair of result) {
183
+ const pnDecoded = (0, WABinary_1.jidDecode)(pair.pn)
184
+ const lidUser = (0, WABinary_1.jidDecode)(pair.lid)?.user
185
+ const pnUser = pnDecoded?.user
186
+ if (!pnUser || !lidUser) {
187
+ continue
188
+ }
189
+ for (const device of usyncFetch[pair.pn] || []) {
190
+ const deviceSpecificLid = `${lidUser}${device ? `:${device}` : ''}@${device === 99 ? 'hosted.lid' : 'lid'}`
191
+ const deviceSpecificPn = `${pnUser}${device ? `:${device}` : ''}@${device === 99 ? 'hosted' : 's.whatsapp.net'}`
192
+ successfulPairs[deviceSpecificPn] = { lid: deviceSpecificLid, pn: deviceSpecificPn }
193
+ }
194
+ }
195
+ }
196
+ else {
197
+ this.logger?.warn?.('USync did not return LID mappings for pending PN users')
198
+ }
199
+ }
200
+ const values = Object.values(successfulPairs)
201
+ return values.length ? values : null
202
+ }
203
+ async getPNForLID(lid) {
204
+ return (await this.getPNsForLIDs([lid]))?.[0]?.pn || null
205
+ }
206
+ async getPNsForLIDs(lids) {
207
+ if (!lids?.length) {
208
+ return null
209
+ }
210
+ const sortedLids = [...new Set(lids)].sort()
211
+ const cacheKey = sortedLids.join(',')
212
+ const inflight = this.inflightPNLookups.get(cacheKey)
213
+ if (inflight) {
214
+ return inflight
215
+ }
216
+ const promise = this._getPNsForLIDsImpl(lids)
217
+ this.inflightPNLookups.set(cacheKey, promise)
218
+ try {
219
+ return await promise
220
+ }
221
+ finally {
222
+ this.inflightPNLookups.delete(cacheKey)
223
+ }
224
+ }
225
+ async _getPNsForLIDsImpl(lids) {
226
+ const successfulPairs = {}
227
+ const pending = []
228
+ const addResolvedPair = (lid, decoded, pnUser) => {
229
+ if (!decoded || !pnUser || typeof pnUser !== 'string') {
230
+ return false
231
+ }
232
+ const lidDevice = decoded.device !== undefined ? decoded.device : 0
233
+ const pnJid = `${pnUser}${lidDevice ? `:${lidDevice}` : ''}@${decoded.domainType === WABinary_1.WAJIDDomains.HOSTED_LID ? 'hosted' : 's.whatsapp.net'}`
234
+ successfulPairs[lid] = { lid, pn: pnJid }
235
+ return true
236
+ }
237
+ for (const lid of lids) {
238
+ if (!(0, WABinary_1.isLidUser)(lid) && !(0, WABinary_1.isHostedLidUser)(lid)) {
239
+ continue
240
+ }
241
+ const decoded = (0, WABinary_1.jidDecode)(lid)
242
+ if (!decoded?.user) {
243
+ continue
244
+ }
245
+ const lidUser = decoded.user
246
+ const cached = this.mappingCache.get(`lid:${lidUser}`)
247
+ if (cached && typeof cached === 'string') {
248
+ addResolvedPair(lid, decoded, cached)
249
+ continue
250
+ }
251
+ pending.push({ lid, lidUser, decoded })
252
+ }
253
+ if (pending.length) {
254
+ const reverseKeys = [...new Set(pending.map(item => `${item.lidUser}_reverse`))]
255
+ const stored = await this.keys.get('lid-mapping', reverseKeys)
256
+ for (const { lid, lidUser, decoded } of pending) {
257
+ let pnUser = this.mappingCache.get(`lid:${lidUser}`)
258
+ if (!pnUser || typeof pnUser !== 'string') {
259
+ pnUser = stored[`${lidUser}_reverse`]
260
+ if (pnUser && typeof pnUser === 'string') {
261
+ this.mappingCache.set(`lid:${lidUser}`, pnUser)
262
+ this.mappingCache.set(`pn:${pnUser}`, lidUser)
263
+ }
264
+ }
265
+ if (pnUser && typeof pnUser === 'string') {
266
+ addResolvedPair(lid, decoded, pnUser)
267
+ }
268
+ }
269
+ }
270
+ const values = Object.values(successfulPairs)
271
+ return values.length ? values : null
272
+ }
273
+ }
274
+
275
+ module.exports = {
276
+ LIDMappingStore
277
+ }
@@ -21,7 +21,7 @@ const MAX_SYNC_ATTEMPTS = 2
21
21
  const makeChatsSocket = (config) => {
22
22
  const { logger, markOnlineOnConnect, fireInitQueries, appStateMacVerification, shouldIgnoreJid, shouldSyncHistoryMessage, } = config
23
23
  const Neele = usync_1.makeUSyncSocket(config)
24
- const { ev, ws, authState, generateMessageTag, sendNode, query, onUnexpectedError, groupFetchAllParticipating } = Neele
24
+ const { ev, ws, authState, generateMessageTag, sendNode, query, onUnexpectedError, groupFetchAllParticipating, signalRepository } = Neele
25
25
 
26
26
  let privacySettings
27
27
  let syncState = Types_1.SyncState.Connecting
@@ -1000,6 +1000,7 @@ const makeChatsSocket = (config) => {
1000
1000
  logger,
1001
1001
  options: config.options,
1002
1002
  getMessage: config.getMessage,
1003
+ signalRepository,
1003
1004
  })
1004
1005
  ])
1005
1006
 
@@ -1130,4 +1131,4 @@ const makeChatsSocket = (config) => {
1130
1131
 
1131
1132
  module.exports = {
1132
1133
  makeChatsSocket
1133
- }
1134
+ }
@@ -24,6 +24,11 @@ export type SignalIdentity = {
24
24
  identifierKey: Uint8Array
25
25
  }
26
26
 
27
+ export type LIDMapping = {
28
+ pn: string
29
+ lid: string
30
+ }
31
+
27
32
  export type LTHashState = {
28
33
  version: number
29
34
  hash: Buffer
@@ -67,6 +72,7 @@ export type AuthenticationCreds = SignalCreds & {
67
72
  pairingCode: string | undefined
68
73
  lastPropHash: string | undefined
69
74
  routingInfo: Buffer | undefined
75
+ additionalData?: any | undefined
70
76
  }
71
77
 
72
78
  export type SignalDataTypeMap = {
@@ -78,6 +84,13 @@ export type SignalDataTypeMap = {
78
84
  }
79
85
  'app-state-sync-key': proto.Message.IAppStateSyncKeyData
80
86
  'app-state-sync-version': LTHashState
87
+ 'lid-mapping': string
88
+ 'device-list': string[]
89
+ 'tctoken': {
90
+ token: Buffer
91
+ timestamp?: string
92
+ }
93
+ 'identity-key': Uint8Array
81
94
  }
82
95
 
83
96
  export type SignalDataSet = {
@@ -99,7 +112,7 @@ export type SignalKeyStore = {
99
112
 
100
113
  export type SignalKeyStoreWithTransaction = SignalKeyStore & {
101
114
  isInTransaction: () => boolean
102
- transaction<T>(exec: () => Promise<T>): Promise<T>
115
+ transaction<T>(exec: () => Promise<T>, key?: string): Promise<T>
103
116
  }
104
117
 
105
118
  export type TransactionCapabilityOptions = {
@@ -117,4 +130,4 @@ export type AuthenticationState = {
117
130
  keys: SignalKeyStore
118
131
  }
119
132
 
120
- export {}
133
+ export {}
@@ -2,6 +2,7 @@ export interface Contact {
2
2
  id: string
3
3
  lid?: string
4
4
  jid?: string
5
+ phoneNumber?: string
5
6
  /** name of the contact, you have saved on your WA */
6
7
  name?: string
7
8
  /** name of the contact, the contact has set on their own on WA */
@@ -17,4 +18,4 @@ export interface Contact {
17
18
  */
18
19
  imgUrl?: string | null
19
20
  status?: string
20
- }
21
+ }
@@ -10,6 +10,7 @@ import { LabelAssociation } from './LabelAssociation'
10
10
  import { MessageUpsertType, MessageUserReceiptUpdate, WAMessage, WAMessageKey, WAMessageUpdate } from './Message'
11
11
  import { NewsletterViewRole, SubscriberAction, NewsletterSettingsUpdate } from './Newsletter'
12
12
  import { ConnectionState } from './State'
13
+ import { LIDMapping } from './Auth'
13
14
 
14
15
  export type BaileysEventMap = {
15
16
  /** connection state has been updated -- WS closed, opened, connecting etc. */
@@ -21,6 +22,7 @@ export type BaileysEventMap = {
21
22
  chats: Chat[]
22
23
  contacts: Contact[]
23
24
  messages: WAMessage[]
25
+ lidPnMappings?: LIDMapping[]
24
26
  isLatest?: boolean
25
27
  progress?: number | null
26
28
  syncType?: proto.HistorySync.HistorySyncType
@@ -82,6 +84,7 @@ export type BaileysEventMap = {
82
84
  'message-receipt.update': MessageUserReceiptUpdate[]
83
85
  'groups.upsert': GroupMetadata[]
84
86
  'groups.update': Partial<GroupMetadata>[]
87
+ 'communities.update': Partial<GroupMetadata>[]
85
88
  /** apply an action to participants in a group */
86
89
  'group-participants.update': {
87
90
  id: string
@@ -234,4 +237,4 @@ export interface BaileysEventEmitter {
234
237
  off<T extends keyof BaileysEventMap>(event: T, listener: (arg: BaileysEventMap[T]) => void): void
235
238
  removeAllListeners<T extends keyof BaileysEventMap>(event: T): void
236
239
  emit<T extends keyof BaileysEventMap>(event: T, arg: BaileysEventMap[T]): boolean
237
- }
240
+ }
@@ -1,4 +1,5 @@
1
1
  import { proto } from '../../WAProto'
2
+ import type { LIDMappingStore } from '../Signal/lid-mapping'
2
3
 
3
4
  type DecryptGroupSignalOpts = {
4
5
  group: string
@@ -62,7 +63,21 @@ export type SignalRepository = {
62
63
  ciphertext: Uint8Array
63
64
  }>
64
65
  injectE2ESession(opts: E2ESessionOpts): Promise<void>
66
+ validateSession(jid: string): Promise<{
67
+ exists: boolean
68
+ reason?: string
69
+ }>
65
70
  jidToSignalProtocolAddress(jid: string): string
71
+ migrateSession(fromJid: string, toJid: string): Promise<{
72
+ migrated: number
73
+ skipped: number
74
+ total: number
75
+ }>
76
+ deleteSession(jids: string[]): Promise<void>
77
+ }
78
+
79
+ export interface SignalRepositoryWithLIDStore extends SignalRepository {
80
+ lidMapping: LIDMappingStore
66
81
  }
67
82
 
68
- export {}
83
+ export {}
@@ -3,10 +3,10 @@ import type { Agent } from 'https'
3
3
  import { ILogger } from '../Utils/logger'
4
4
  import type { URL } from 'url'
5
5
  import { proto } from '../../WAProto'
6
- import { AuthenticationState, SignalAuthState, TransactionCapabilityOptions } from './Auth'
6
+ import { AuthenticationState, LIDMapping, SignalAuthState, TransactionCapabilityOptions } from './Auth'
7
7
  import { GroupMetadata } from './GroupMetadata'
8
8
  import { MediaConnInfo } from './Message'
9
- import { SignalRepository } from './Signal'
9
+ import { SignalRepositoryWithLIDStore } from './Signal'
10
10
 
11
11
  export type WAVersion = [number, number, number]
12
12
 
@@ -91,6 +91,8 @@ export type SocketConfig = {
91
91
  * entails uploading the jpegThumbnail to WA
92
92
  * */
93
93
  generateHighQualityLinkPreview: boolean
94
+ /** Enable automatic session recreation for failed messages */
95
+ enableAutoSessionRecreation: boolean
94
96
  /** Enable recent message caching for retry handling */
95
97
  enableRecentMessageCache: boolean
96
98
  /**
@@ -118,5 +120,9 @@ export type SocketConfig = {
118
120
  getMessage: (key: proto.IMessageKey) => Promise<proto.IMessage | undefined>
119
121
  /** cached group metadata, use to prevent redundant requests to WA & speed up msg sending */
120
122
  cachedGroupMetadata: (jid: string) => Promise<GroupMetadata | undefined>
121
- makeSignalRepository: (auth: SignalAuthState) => SignalRepository
122
- }
123
+ makeSignalRepository: (
124
+ auth: SignalAuthState,
125
+ logger: ILogger,
126
+ pnToLIDFunc?: (jids: string[]) => Promise<LIDMapping[] | undefined>
127
+ ) => SignalRepositoryWithLIDStore
128
+ }
@@ -0,0 +1 @@
1
+ export { Browsers, getPlatformId } from './generics'
@@ -0,0 +1,10 @@
1
+ "use strict"
2
+
3
+ Object.defineProperty(exports, "__esModule", { value: true })
4
+
5
+ const generics_1 = require("./generics")
6
+
7
+ module.exports = {
8
+ Browsers: generics_1.Browsers,
9
+ getPlatformId: generics_1.getPlatformId
10
+ }
@@ -1,23 +1,30 @@
1
1
  import { AxiosRequestConfig } from 'axios'
2
2
  import { proto } from '../../WAProto'
3
- import { Chat, Contact } from '../Types'
3
+ import { Chat, Contact, LIDMapping } from '../Types'
4
+ import { ILogger } from './logger'
4
5
 
5
6
  export declare const downloadHistory: (msg: proto.Message.IHistorySyncNotification, options: AxiosRequestConfig<{}>) => Promise<proto.HistorySync>
6
7
 
7
- export declare const processHistoryMessage: (item: proto.IHistorySync) => {
8
+ export declare const processHistoryMessage: (item: proto.IHistorySync, logger?: ILogger) => {
8
9
  chats: Chat[]
9
10
  contacts: Contact[]
10
11
  messages: proto.IWebMessageInfo[]
12
+ lidPnMappings: LIDMapping[]
11
13
  syncType: proto.HistorySync.HistorySyncType
12
14
  progress: number | null | undefined
13
15
  }
14
16
 
15
- export declare const downloadAndProcessHistorySyncNotification: (msg: proto.Message.IHistorySyncNotification, options: AxiosRequestConfig<{}>) => Promise<{
17
+ export declare const downloadAndProcessHistorySyncNotification: (
18
+ msg: proto.Message.IHistorySyncNotification,
19
+ options: AxiosRequestConfig<{}>,
20
+ logger?: ILogger
21
+ ) => Promise<{
16
22
  chats: Chat[]
17
23
  contacts: Contact[]
18
24
  messages: proto.IWebMessageInfo[]
25
+ lidPnMappings: LIDMapping[]
19
26
  syncType: proto.HistorySync.HistorySyncType
20
27
  progress: number | null | undefined
21
28
  }>
22
29
 
23
- export declare const getHistoryMsg: (message: proto.IMessage) => proto.Message.IHistorySyncNotification | null | undefined
30
+ export declare const getHistoryMsg: (message: proto.IMessage) => proto.Message.IHistorySyncNotification | null | undefined