@neelegirl/baileys 2.1.8 → 2.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +75 -1586
- package/lib/Defaults/baileys-version.json +1 -1
- package/lib/Defaults/index.d.ts +18 -31
- package/lib/Signal/libsignal.d.ts +3 -8
- package/lib/Signal/libsignal.js +79 -288
- package/lib/Socket/chats.js +2 -3
- package/lib/Socket/socket.js +3 -3
- package/lib/Types/Auth.d.ts +2 -15
- package/lib/Types/Contact.d.ts +1 -2
- package/lib/Types/Events.d.ts +1 -4
- package/lib/Types/Message.d.ts +5 -1
- package/lib/Types/Signal.d.ts +1 -16
- package/lib/Types/Socket.d.ts +4 -10
- package/lib/Utils/decode-wa-message.d.ts +4 -4
- package/lib/Utils/decode-wa-message.js +36 -10
- package/lib/Utils/generics.d.ts +4 -3
- package/lib/Utils/generics.js +8 -6
- package/lib/Utils/history.d.ts +4 -11
- package/lib/Utils/history.js +38 -77
- package/lib/Utils/index.d.ts +1 -4
- package/lib/Utils/index.js +1 -2
- package/lib/Utils/message-retry-manager.js +4 -4
- package/lib/Utils/process-message.d.ts +2 -3
- package/lib/Utils/process-message.js +2 -28
- package/lib/WABinary/jid-utils.d.ts +4 -21
- package/lib/WABinary/jid-utils.js +8 -50
- package/package.json +44 -28
- package/WAProto/GenerateStatics.sh +0 -3
- package/WAProto/fix-imports.js +0 -81
- package/engine-requirements.js +0 -10
- package/lib/Signal/lid-mapping.d.ts +0 -23
- package/lib/Signal/lid-mapping.js +0 -278
- package/lib/Utils/browser-utils.d.ts +0 -1
- package/lib/Utils/browser-utils.js +0 -10
|
@@ -10,14 +10,7 @@ export declare const STORIES_JID = "status@broadcast"
|
|
|
10
10
|
|
|
11
11
|
export declare const META_AI_JID = '13135550002@c.us'
|
|
12
12
|
|
|
13
|
-
export type JidServer = 'c.us' | 'g.us' | 'broadcast' | 's.whatsapp.net' | 'call' | 'lid' | 'newsletter' | 'bot'
|
|
14
|
-
|
|
15
|
-
export declare enum WAJIDDomains {
|
|
16
|
-
WHATSAPP = 0,
|
|
17
|
-
LID = 1,
|
|
18
|
-
HOSTED = 128,
|
|
19
|
-
HOSTED_LID = 129
|
|
20
|
-
}
|
|
13
|
+
export type JidServer = 'c.us' | 'g.us' | 'broadcast' | 's.whatsapp.net' | 'call' | 'lid' | 'newsletter' | 'bot'
|
|
21
14
|
|
|
22
15
|
export type JidWithDevice = {
|
|
23
16
|
user: string
|
|
@@ -33,21 +26,13 @@ export declare const jidEncode: (user: string | number | null, server: JidServer
|
|
|
33
26
|
|
|
34
27
|
export declare const jidDecode: (jid: string | undefined) => FullJid | undefined
|
|
35
28
|
|
|
36
|
-
export declare const getServerFromDomainType: (initialServer: string, domainType?: WAJIDDomains) => JidServer
|
|
37
|
-
|
|
38
29
|
/** is the jid a user */
|
|
39
30
|
export declare const areJidsSameUser: (jid1: string | undefined, jid2: string | undefined) => boolean
|
|
40
31
|
|
|
41
|
-
/** is the
|
|
42
|
-
export declare const isJidMetaAI: (jid: string | undefined) => boolean | undefined
|
|
43
|
-
|
|
44
|
-
/** is the jid a PN user */
|
|
45
|
-
export declare const isPnUser: (jid: string | undefined) => boolean | undefined
|
|
46
|
-
|
|
47
|
-
/** backward-compatible alias */
|
|
32
|
+
/** is the lid a user */
|
|
48
33
|
export declare const isJidUser: (jid: string | undefined) => boolean | undefined
|
|
49
34
|
|
|
50
|
-
/** is the
|
|
35
|
+
/** is the jid a group */
|
|
51
36
|
export declare const isLidUser: (jid: string | undefined) => boolean | undefined
|
|
52
37
|
|
|
53
38
|
/** is the jid a broadcast */
|
|
@@ -71,6 +56,4 @@ export declare const isHostedLidUser: (jid: string | undefined) => boolean | und
|
|
|
71
56
|
/** is the jid a bot */
|
|
72
57
|
export declare const isJidBot: (jid: string | undefined) => boolean | undefined
|
|
73
58
|
|
|
74
|
-
export declare const jidNormalizedUser: (jid: string | undefined) => string
|
|
75
|
-
|
|
76
|
-
export declare const transferDevice: (fromJid: string, toJid: string) => string
|
|
59
|
+
export declare const jidNormalizedUser: (jid: string | undefined) => string
|
|
@@ -14,27 +14,6 @@ const STORIES_JID = 'status@broadcast'
|
|
|
14
14
|
|
|
15
15
|
const META_AI_JID = '13135550002@c.us'
|
|
16
16
|
|
|
17
|
-
const WAJIDDomains = {
|
|
18
|
-
WHATSAPP: 0,
|
|
19
|
-
LID: 1,
|
|
20
|
-
HOSTED: 128,
|
|
21
|
-
HOSTED_LID: 129
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
const getServerFromDomainType = (initialServer, domainType = WAJIDDomains.WHATSAPP) => {
|
|
25
|
-
switch (domainType) {
|
|
26
|
-
case WAJIDDomains.LID:
|
|
27
|
-
return 'lid'
|
|
28
|
-
case WAJIDDomains.HOSTED:
|
|
29
|
-
return 'hosted'
|
|
30
|
-
case WAJIDDomains.HOSTED_LID:
|
|
31
|
-
return 'hosted.lid'
|
|
32
|
-
case WAJIDDomains.WHATSAPP:
|
|
33
|
-
default:
|
|
34
|
-
return initialServer
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
|
|
38
17
|
const jidEncode = (user, server, device, agent) => {
|
|
39
18
|
return `${user || ''}${!!agent ? `_${agent}` : ''}${!!device ? `:${device}` : ''}@${server}`
|
|
40
19
|
}
|
|
@@ -48,10 +27,10 @@ const jidDecode = (jid) => {
|
|
|
48
27
|
const userCombined = jid.slice(0, sepIdx)
|
|
49
28
|
const [userAgent, device] = userCombined.split(':')
|
|
50
29
|
const [user, agent] = (userAgent || '').split('_')
|
|
51
|
-
let domainType =
|
|
52
|
-
if (server === 'lid') domainType =
|
|
53
|
-
else if (server === 'hosted') domainType =
|
|
54
|
-
else if (server === 'hosted.lid') domainType =
|
|
30
|
+
let domainType = 0
|
|
31
|
+
if (server === 'lid') domainType = 1
|
|
32
|
+
else if (server === 'hosted') domainType = 128
|
|
33
|
+
else if (server === 'hosted.lid') domainType = 129
|
|
55
34
|
else if (agent) domainType = parseInt(agent, 10)
|
|
56
35
|
return {
|
|
57
36
|
server,
|
|
@@ -66,14 +45,8 @@ const areJidsSameUser = (jid1, jid2) => {
|
|
|
66
45
|
return jidDecode(jid1)?.user === jidDecode(jid2)?.user
|
|
67
46
|
}
|
|
68
47
|
|
|
69
|
-
/** is the jid
|
|
70
|
-
const
|
|
71
|
-
|
|
72
|
-
/** is the jid a PN user */
|
|
73
|
-
const isPnUser = (jid) => jid?.endsWith('@s.whatsapp.net')
|
|
74
|
-
|
|
75
|
-
/** backward-compatible alias */
|
|
76
|
-
const isJidUser = isPnUser
|
|
48
|
+
/** is the jid a user */
|
|
49
|
+
const isJidUser = (jid) => jid?.endsWith('@s.whatsapp.net')
|
|
77
50
|
|
|
78
51
|
/** is the lid a user */
|
|
79
52
|
const isLidUser = (jid) => jid?.endsWith('@lid')
|
|
@@ -109,16 +82,6 @@ const jidNormalizedUser = (jid) => {
|
|
|
109
82
|
return jidEncode(user, server === 'c.us' ? 's.whatsapp.net' : server)
|
|
110
83
|
}
|
|
111
84
|
|
|
112
|
-
const transferDevice = (fromJid, toJid) => {
|
|
113
|
-
const fromDecoded = jidDecode(fromJid)
|
|
114
|
-
const deviceId = fromDecoded?.device || 0
|
|
115
|
-
const toDecoded = jidDecode(toJid)
|
|
116
|
-
if (!toDecoded) {
|
|
117
|
-
throw new Error(`invalid jid for device transfer: ${toJid}`)
|
|
118
|
-
}
|
|
119
|
-
return jidEncode(toDecoded.user, toDecoded.server, deviceId)
|
|
120
|
-
}
|
|
121
|
-
|
|
122
85
|
module.exports = {
|
|
123
86
|
S_WHATSAPP_NET,
|
|
124
87
|
OFFICIAL_BIZ_JID,
|
|
@@ -126,13 +89,9 @@ module.exports = {
|
|
|
126
89
|
PSA_WID,
|
|
127
90
|
STORIES_JID,
|
|
128
91
|
META_AI_JID,
|
|
129
|
-
WAJIDDomains,
|
|
130
|
-
getServerFromDomainType,
|
|
131
92
|
jidEncode,
|
|
132
93
|
jidDecode,
|
|
133
94
|
areJidsSameUser,
|
|
134
|
-
isJidMetaAI,
|
|
135
|
-
isPnUser,
|
|
136
95
|
isJidUser,
|
|
137
96
|
isLidUser,
|
|
138
97
|
isJidBroadcast,
|
|
@@ -142,6 +101,5 @@ module.exports = {
|
|
|
142
101
|
isHostedPnUser,
|
|
143
102
|
isHostedLidUser,
|
|
144
103
|
isJidBot,
|
|
145
|
-
jidNormalizedUser
|
|
146
|
-
|
|
147
|
-
}
|
|
104
|
+
jidNormalizedUser
|
|
105
|
+
}
|
package/package.json
CHANGED
|
@@ -1,57 +1,77 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@neelegirl/baileys",
|
|
3
|
-
"version": "2.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "2.2.0",
|
|
4
|
+
"description": "Conservative Neelegirl-maintained CommonJS WhatsApp Web client based on WhiskeySockets/Baileys with preserved QR, NEELE message IDs and device/LID handling.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"whatsapp",
|
|
7
|
+
"baileys",
|
|
8
|
+
"neelegirl",
|
|
7
9
|
"js-whatsapp",
|
|
8
10
|
"whatsapp-api",
|
|
9
11
|
"whatsapp-web",
|
|
10
12
|
"whatsapp-chat",
|
|
11
13
|
"whatsapp-group",
|
|
12
14
|
"automation",
|
|
13
|
-
"multi-device"
|
|
14
|
-
"commonjs",
|
|
15
|
-
"lid",
|
|
16
|
-
"neelegirl",
|
|
17
|
-
"baileys"
|
|
15
|
+
"multi-device"
|
|
18
16
|
],
|
|
19
|
-
"homepage": "https://
|
|
17
|
+
"homepage": "https://www.npmjs.com/package/@neelegirl/baileys",
|
|
20
18
|
"repository": {
|
|
21
19
|
"type": "git",
|
|
22
|
-
"url": "git+https://github.com/
|
|
23
|
-
},
|
|
24
|
-
"bugs": {
|
|
25
|
-
"url": "https://github.com/neelegirl/baileys/issues"
|
|
20
|
+
"url": "git+https://github.com/WhiskeySockets/Baileys.git"
|
|
26
21
|
},
|
|
27
22
|
"license": "MIT",
|
|
28
23
|
"author": "Neele",
|
|
29
24
|
"main": "lib/index.js",
|
|
30
25
|
"types": "lib/index.d.ts",
|
|
26
|
+
"exports": {
|
|
27
|
+
".": {
|
|
28
|
+
"types": "./lib/index.d.ts",
|
|
29
|
+
"require": "./lib/index.js",
|
|
30
|
+
"default": "./lib/index.js"
|
|
31
|
+
},
|
|
32
|
+
"./lib": {
|
|
33
|
+
"types": "./lib/index.d.ts",
|
|
34
|
+
"require": "./lib/index.js",
|
|
35
|
+
"default": "./lib/index.js"
|
|
36
|
+
},
|
|
37
|
+
"./lib/*": {
|
|
38
|
+
"types": "./lib/*.d.ts",
|
|
39
|
+
"require": "./lib/*.js",
|
|
40
|
+
"default": "./lib/*.js"
|
|
41
|
+
},
|
|
42
|
+
"./WAProto": {
|
|
43
|
+
"types": "./WAProto/index.d.ts",
|
|
44
|
+
"require": "./WAProto/index.js",
|
|
45
|
+
"default": "./WAProto/index.js"
|
|
46
|
+
},
|
|
47
|
+
"./WAProto/*": {
|
|
48
|
+
"types": "./WAProto/*.d.ts",
|
|
49
|
+
"require": "./WAProto/*.js",
|
|
50
|
+
"default": "./WAProto/*.js"
|
|
51
|
+
},
|
|
52
|
+
"./package.json": "./package.json"
|
|
53
|
+
},
|
|
31
54
|
"files": [
|
|
32
55
|
"lib/**/*",
|
|
33
56
|
"WAProto/**/*",
|
|
34
|
-
"
|
|
57
|
+
"LICENSE",
|
|
58
|
+
"README.md"
|
|
35
59
|
],
|
|
36
60
|
"scripts": {
|
|
37
|
-
"
|
|
38
|
-
"
|
|
39
|
-
"build:tsc": "tsc",
|
|
40
|
-
"preinstall": "node ./engine-requirements.js",
|
|
41
|
-
"test": "node -e \"console.log('No tests configured')\""
|
|
61
|
+
"smoke": "node -e \"require('./lib/index.js')\"",
|
|
62
|
+
"test": "node -e \"require('./lib/index.js')\""
|
|
42
63
|
},
|
|
43
64
|
"dependencies": {
|
|
44
65
|
"@adiwajshing/keyed-db": "^0.2.4",
|
|
45
66
|
"@cacheable/node-cache": "^1.5.4",
|
|
46
67
|
"@hapi/boom": "^9.1.3",
|
|
47
|
-
"@neelegirl/libsignal": "^1.0.
|
|
68
|
+
"@neelegirl/libsignal": "^1.0.2",
|
|
48
69
|
"async-mutex": "^0.5.0",
|
|
49
70
|
"audio-decode": "^2.1.3",
|
|
50
71
|
"axios": "^1.3.3",
|
|
51
72
|
"cache-manager": "4.0.1",
|
|
52
73
|
"futoin-hkdf": "^1.5.1",
|
|
53
74
|
"libphonenumber-js": "^1.10.20",
|
|
54
|
-
"lru-cache": "^11.1.0",
|
|
55
75
|
"music-metadata": "^7.12.3",
|
|
56
76
|
"node-cache": "^5.1.2",
|
|
57
77
|
"pino": "^7.0.0",
|
|
@@ -69,7 +89,7 @@
|
|
|
69
89
|
"conventional-changelog-cli": "^2.2.2",
|
|
70
90
|
"eslint": "^8.0.0",
|
|
71
91
|
"jest": "^27.0.6",
|
|
72
|
-
|
|
92
|
+
"jimp": "^0.16.13",
|
|
73
93
|
"json": "^11.0.0",
|
|
74
94
|
"link-preview-js": "^3.0.5",
|
|
75
95
|
"open": "^8.4.2",
|
|
@@ -82,16 +102,12 @@
|
|
|
82
102
|
"typescript": "^4.6.4"
|
|
83
103
|
},
|
|
84
104
|
"peerDependencies": {
|
|
85
|
-
"audio-decode": "^2.1.3",
|
|
86
105
|
"jimp": "^0.22.12",
|
|
87
106
|
"link-preview-js": "^3.0.0",
|
|
88
107
|
"qrcode-terminal": "^0.12.0",
|
|
89
108
|
"sharp": "^0.32.6"
|
|
90
109
|
},
|
|
91
110
|
"peerDependenciesMeta": {
|
|
92
|
-
"audio-decode": {
|
|
93
|
-
"optional": true
|
|
94
|
-
},
|
|
95
111
|
"jimp": {
|
|
96
112
|
"optional": true
|
|
97
113
|
},
|
|
@@ -105,8 +121,8 @@
|
|
|
105
121
|
"optional": true
|
|
106
122
|
}
|
|
107
123
|
},
|
|
108
|
-
"packageManager": "yarn@1.22.19",
|
|
109
124
|
"engines": {
|
|
110
|
-
"node": ">=
|
|
111
|
-
}
|
|
125
|
+
"node": ">=16.0.0"
|
|
126
|
+
},
|
|
127
|
+
"packageManager": "yarn@1.22.19"
|
|
112
128
|
}
|
|
@@ -1,3 +0,0 @@
|
|
|
1
|
-
yarn pbjs -t static-module --no-beautify -w es6 --no-bundle --no-delimited --no-verify --no-comments -o ./index.js ./WAProto.proto;
|
|
2
|
-
yarn pbjs -t static-module --no-beautify -w es6 --no-bundle --no-delimited --no-verify ./WAProto.proto | yarn pbts --no-comments -o ./index.d.ts -;
|
|
3
|
-
node ./fix-imports.js
|
package/WAProto/fix-imports.js
DELETED
|
@@ -1,81 +0,0 @@
|
|
|
1
|
-
import { readFileSync, writeFileSync } from 'fs';
|
|
2
|
-
import { exit } from 'process';
|
|
3
|
-
|
|
4
|
-
const filePath = './index.js'
|
|
5
|
-
|
|
6
|
-
try {
|
|
7
|
-
let content = readFileSync(filePath, 'utf8')
|
|
8
|
-
|
|
9
|
-
content = content.replace(/import \* as (\$protobuf) from/g, 'import $1 from')
|
|
10
|
-
content = content.replace(/(['"])protobufjs\/minimal(['"])/g, '$1protobufjs/minimal.js$2')
|
|
11
|
-
|
|
12
|
-
const marker = 'const $root = $protobuf.roots["default"] || ($protobuf.roots["default"] = {});\n\n'
|
|
13
|
-
const longToStringHelper =
|
|
14
|
-
'function longToString(value, unsigned) {\n' +
|
|
15
|
-
'\tif (typeof value === "string") {\n' +
|
|
16
|
-
'\t\treturn value;\n' +
|
|
17
|
-
'\t}\n' +
|
|
18
|
-
'\tif (typeof value === "number") {\n' +
|
|
19
|
-
'\t\treturn String(value);\n' +
|
|
20
|
-
'\t}\n' +
|
|
21
|
-
'\tif (!$util.Long) {\n' +
|
|
22
|
-
'\t\treturn String(value);\n' +
|
|
23
|
-
'\t}\n' +
|
|
24
|
-
'\tconst normalized = $util.Long.fromValue(value);\n' +
|
|
25
|
-
'\tconst prepared = unsigned && normalized && typeof normalized.toUnsigned === "function"\n' +
|
|
26
|
-
'\t\t? normalized.toUnsigned()\n' +
|
|
27
|
-
'\t\t: normalized;\n' +
|
|
28
|
-
'\treturn prepared.toString();\n' +
|
|
29
|
-
'}\n\n'
|
|
30
|
-
const longToNumberHelper =
|
|
31
|
-
'function longToNumber(value, unsigned) {\n' +
|
|
32
|
-
'\tif (typeof value === "number") {\n' +
|
|
33
|
-
'\t\treturn value;\n' +
|
|
34
|
-
'\t}\n' +
|
|
35
|
-
'\tif (typeof value === "string") {\n' +
|
|
36
|
-
'\t\tconst numeric = Number(value);\n' +
|
|
37
|
-
'\t\treturn numeric;\n' +
|
|
38
|
-
'\t}\n' +
|
|
39
|
-
'\tif (!$util.Long) {\n' +
|
|
40
|
-
'\t\treturn Number(value);\n' +
|
|
41
|
-
'\t}\n' +
|
|
42
|
-
'\tconst normalized = $util.Long.fromValue(value);\n' +
|
|
43
|
-
'\tconst prepared = unsigned && normalized && typeof normalized.toUnsigned === "function"\n' +
|
|
44
|
-
'\t\t? normalized.toUnsigned()\n' +
|
|
45
|
-
'\t\t: typeof normalized.toSigned === "function"\n' +
|
|
46
|
-
'\t\t\t? normalized.toSigned()\n' +
|
|
47
|
-
'\t\t\t: normalized;\n' +
|
|
48
|
-
'\treturn prepared.toNumber();\n' +
|
|
49
|
-
'}\n\n'
|
|
50
|
-
|
|
51
|
-
if (!content.includes('function longToString(')) {
|
|
52
|
-
const markerIndex = content.indexOf(marker)
|
|
53
|
-
if (markerIndex === -1) {
|
|
54
|
-
throw new Error('Unable to inject Long helpers: marker not found in WAProto index output')
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
content = content.replace(marker, `${marker}${longToStringHelper}${longToNumberHelper}`)
|
|
58
|
-
} else {
|
|
59
|
-
const longToStringRegex = /function longToString\(value, unsigned\) {\n[\s\S]*?\n}\n\n/
|
|
60
|
-
const longToNumberRegex = /function longToNumber\(value, unsigned\) {\n[\s\S]*?\n}\n\n/
|
|
61
|
-
|
|
62
|
-
if (!longToStringRegex.test(content) || !longToNumberRegex.test(content)) {
|
|
63
|
-
throw new Error('Unable to update Long helpers: existing definitions not found')
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
content = content.replace(longToStringRegex, longToStringHelper)
|
|
67
|
-
content = content.replace(longToNumberRegex, longToNumberHelper)
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
const longPattern = /([ \t]+d\.(\w+) = )o\.longs === String \? \$util\.Long\.prototype\.toString\.call\(m\.\2\) : o\.longs === Number \? new \$util\.LongBits\(m\.\2\.low >>> 0, m\.\2\.high >>> 0\)\.toNumber\((true)?\) : m\.\2;/g
|
|
71
|
-
content = content.replace(longPattern, (_match, prefix, field, unsignedFlag) => {
|
|
72
|
-
const unsignedArg = unsignedFlag ? ', true' : ''
|
|
73
|
-
return `${prefix}o.longs === String ? longToString(m.${field}${unsignedArg}) : o.longs === Number ? longToNumber(m.${field}${unsignedArg}) : m.${field};`
|
|
74
|
-
})
|
|
75
|
-
|
|
76
|
-
writeFileSync(filePath, content, 'utf8')
|
|
77
|
-
console.log(`✅ Fixed imports in ${filePath}`)
|
|
78
|
-
} catch (error) {
|
|
79
|
-
console.error(`❌ Error fixing imports: ${error.message}`)
|
|
80
|
-
exit(1)
|
|
81
|
-
}
|
package/engine-requirements.js
DELETED
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
const major = parseInt(process.versions.node.split('.')[0], 10);
|
|
2
|
-
|
|
3
|
-
if (major < 20) {
|
|
4
|
-
console.error(
|
|
5
|
-
`\n❌ This package requires Node.js 20+ to run reliably.\n` +
|
|
6
|
-
` You are using Node.js ${process.versions.node}.\n` +
|
|
7
|
-
` Please upgrade to Node.js 20+ to proceed.\n`
|
|
8
|
-
);
|
|
9
|
-
process.exit(1);
|
|
10
|
-
}
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
import type { LIDMapping, SignalKeyStoreWithTransaction } from '../Types'
|
|
2
|
-
import type { ILogger } from '../Utils/logger'
|
|
3
|
-
|
|
4
|
-
export declare class LIDMappingStore {
|
|
5
|
-
private readonly mappingCache
|
|
6
|
-
private readonly keys
|
|
7
|
-
private readonly logger
|
|
8
|
-
private readonly inflightLIDLookups
|
|
9
|
-
private readonly inflightPNLookups
|
|
10
|
-
private pnToLIDFunc?
|
|
11
|
-
constructor(
|
|
12
|
-
keys: SignalKeyStoreWithTransaction,
|
|
13
|
-
logger: ILogger,
|
|
14
|
-
pnToLIDFunc?: (jids: string[]) => Promise<LIDMapping[] | undefined>
|
|
15
|
-
)
|
|
16
|
-
storeLIDPNMappings(pairs: LIDMapping[]): Promise<void>
|
|
17
|
-
getLIDForPN(pn: string): Promise<string | null>
|
|
18
|
-
getLIDsForPNs(pns: string[]): Promise<LIDMapping[] | null>
|
|
19
|
-
getPNForLID(lid: string): Promise<string | null>
|
|
20
|
-
getPNsForLIDs(lids: string[]): Promise<LIDMapping[] | null>
|
|
21
|
-
private _getLIDsForPNsImpl
|
|
22
|
-
private _getPNsForLIDsImpl
|
|
23
|
-
}
|
|
@@ -1,278 +0,0 @@
|
|
|
1
|
-
"use strict"
|
|
2
|
-
|
|
3
|
-
Object.defineProperty(exports, "__esModule", { value: true })
|
|
4
|
-
|
|
5
|
-
const LRUCacheModule = require("lru-cache")
|
|
6
|
-
const LRUCache = LRUCacheModule.LRUCache || LRUCacheModule
|
|
7
|
-
const WABinary_1 = require("../WABinary")
|
|
8
|
-
|
|
9
|
-
class LIDMappingStore {
|
|
10
|
-
constructor(keys, logger, pnToLIDFunc) {
|
|
11
|
-
this.mappingCache = new LRUCache({
|
|
12
|
-
ttl: 3 * 24 * 60 * 60 * 1000,
|
|
13
|
-
ttlAutopurge: true,
|
|
14
|
-
updateAgeOnGet: true
|
|
15
|
-
})
|
|
16
|
-
this.inflightLIDLookups = new Map()
|
|
17
|
-
this.inflightPNLookups = new Map()
|
|
18
|
-
this.keys = keys
|
|
19
|
-
this.logger = logger
|
|
20
|
-
this.pnToLIDFunc = pnToLIDFunc
|
|
21
|
-
}
|
|
22
|
-
async storeLIDPNMappings(pairs) {
|
|
23
|
-
if (!pairs?.length) {
|
|
24
|
-
return
|
|
25
|
-
}
|
|
26
|
-
const validatedPairs = []
|
|
27
|
-
for (const { lid, pn } of pairs) {
|
|
28
|
-
const validDirection = ((0, WABinary_1.isLidUser)(lid) || (0, WABinary_1.isHostedLidUser)(lid))
|
|
29
|
-
&& ((0, WABinary_1.isPnUser)(pn) || (0, WABinary_1.isHostedPnUser)(pn))
|
|
30
|
-
const reverseDirection = ((0, WABinary_1.isPnUser)(lid) || (0, WABinary_1.isHostedPnUser)(lid))
|
|
31
|
-
&& ((0, WABinary_1.isLidUser)(pn) || (0, WABinary_1.isHostedLidUser)(pn))
|
|
32
|
-
if (!validDirection && !reverseDirection) {
|
|
33
|
-
this.logger?.warn?.({ lid, pn }, 'invalid LID-PN mapping')
|
|
34
|
-
continue
|
|
35
|
-
}
|
|
36
|
-
const lidJid = validDirection ? lid : pn
|
|
37
|
-
const pnJid = validDirection ? pn : lid
|
|
38
|
-
const lidDecoded = (0, WABinary_1.jidDecode)(lidJid)
|
|
39
|
-
const pnDecoded = (0, WABinary_1.jidDecode)(pnJid)
|
|
40
|
-
if (!lidDecoded?.user || !pnDecoded?.user) {
|
|
41
|
-
continue
|
|
42
|
-
}
|
|
43
|
-
validatedPairs.push({
|
|
44
|
-
pnUser: pnDecoded.user,
|
|
45
|
-
lidUser: lidDecoded.user
|
|
46
|
-
})
|
|
47
|
-
}
|
|
48
|
-
if (!validatedPairs.length) {
|
|
49
|
-
return
|
|
50
|
-
}
|
|
51
|
-
const cacheMissSet = new Set()
|
|
52
|
-
const existingMappings = new Map()
|
|
53
|
-
for (const { pnUser } of validatedPairs) {
|
|
54
|
-
const cached = this.mappingCache.get(`pn:${pnUser}`)
|
|
55
|
-
if (cached) {
|
|
56
|
-
existingMappings.set(pnUser, cached)
|
|
57
|
-
}
|
|
58
|
-
else {
|
|
59
|
-
cacheMissSet.add(pnUser)
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
if (cacheMissSet.size) {
|
|
63
|
-
const cacheMisses = [...cacheMissSet]
|
|
64
|
-
this.logger?.trace?.({ count: cacheMisses.length }, 'loading LID mappings from store')
|
|
65
|
-
const stored = await this.keys.get('lid-mapping', cacheMisses)
|
|
66
|
-
for (const pnUser of cacheMisses) {
|
|
67
|
-
const existingLidUser = stored[pnUser]
|
|
68
|
-
if (existingLidUser) {
|
|
69
|
-
existingMappings.set(pnUser, existingLidUser)
|
|
70
|
-
this.mappingCache.set(`pn:${pnUser}`, existingLidUser)
|
|
71
|
-
this.mappingCache.set(`lid:${existingLidUser}`, pnUser)
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
const pairMap = {}
|
|
76
|
-
for (const { pnUser, lidUser } of validatedPairs) {
|
|
77
|
-
const existingLidUser = existingMappings.get(pnUser)
|
|
78
|
-
if (existingLidUser === lidUser) {
|
|
79
|
-
continue
|
|
80
|
-
}
|
|
81
|
-
pairMap[pnUser] = lidUser
|
|
82
|
-
}
|
|
83
|
-
if (!Object.keys(pairMap).length) {
|
|
84
|
-
return
|
|
85
|
-
}
|
|
86
|
-
const batchData = {}
|
|
87
|
-
for (const [pnUser, lidUser] of Object.entries(pairMap)) {
|
|
88
|
-
batchData[pnUser] = lidUser
|
|
89
|
-
batchData[`${lidUser}_reverse`] = pnUser
|
|
90
|
-
}
|
|
91
|
-
await this.keys.transaction(async () => {
|
|
92
|
-
await this.keys.set({ 'lid-mapping': batchData })
|
|
93
|
-
}, 'lid-mapping')
|
|
94
|
-
for (const [pnUser, lidUser] of Object.entries(pairMap)) {
|
|
95
|
-
this.mappingCache.set(`pn:${pnUser}`, lidUser)
|
|
96
|
-
this.mappingCache.set(`lid:${lidUser}`, pnUser)
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
async getLIDForPN(pn) {
|
|
100
|
-
return (await this.getLIDsForPNs([pn]))?.[0]?.lid || null
|
|
101
|
-
}
|
|
102
|
-
async getLIDsForPNs(pns) {
|
|
103
|
-
if (!pns?.length) {
|
|
104
|
-
return null
|
|
105
|
-
}
|
|
106
|
-
const sortedPns = [...new Set(pns)].sort()
|
|
107
|
-
const cacheKey = sortedPns.join(',')
|
|
108
|
-
const inflight = this.inflightLIDLookups.get(cacheKey)
|
|
109
|
-
if (inflight) {
|
|
110
|
-
return inflight
|
|
111
|
-
}
|
|
112
|
-
const promise = this._getLIDsForPNsImpl(pns)
|
|
113
|
-
this.inflightLIDLookups.set(cacheKey, promise)
|
|
114
|
-
try {
|
|
115
|
-
return await promise
|
|
116
|
-
}
|
|
117
|
-
finally {
|
|
118
|
-
this.inflightLIDLookups.delete(cacheKey)
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
async _getLIDsForPNsImpl(pns) {
|
|
122
|
-
const usyncFetch = {}
|
|
123
|
-
const successfulPairs = {}
|
|
124
|
-
const pending = []
|
|
125
|
-
const addResolvedPair = (pn, decoded, lidUser) => {
|
|
126
|
-
if (!decoded || !lidUser) {
|
|
127
|
-
return false
|
|
128
|
-
}
|
|
129
|
-
const pnDevice = decoded.device !== undefined ? decoded.device : 0
|
|
130
|
-
const deviceSpecificLid = `${lidUser}${pnDevice ? `:${pnDevice}` : ''}@${decoded.server === 'hosted' ? 'hosted.lid' : 'lid'}`
|
|
131
|
-
successfulPairs[pn] = { lid: deviceSpecificLid, pn }
|
|
132
|
-
return true
|
|
133
|
-
}
|
|
134
|
-
for (const pn of pns) {
|
|
135
|
-
if (!(0, WABinary_1.isPnUser)(pn) && !(0, WABinary_1.isHostedPnUser)(pn)) {
|
|
136
|
-
continue
|
|
137
|
-
}
|
|
138
|
-
const decoded = (0, WABinary_1.jidDecode)(pn)
|
|
139
|
-
if (!decoded?.user) {
|
|
140
|
-
continue
|
|
141
|
-
}
|
|
142
|
-
const pnUser = decoded.user
|
|
143
|
-
const cached = this.mappingCache.get(`pn:${pnUser}`)
|
|
144
|
-
if (cached && typeof cached === 'string') {
|
|
145
|
-
addResolvedPair(pn, decoded, cached)
|
|
146
|
-
continue
|
|
147
|
-
}
|
|
148
|
-
pending.push({ pn, pnUser, decoded })
|
|
149
|
-
}
|
|
150
|
-
if (pending.length) {
|
|
151
|
-
const pnUsers = [...new Set(pending.map(item => item.pnUser))]
|
|
152
|
-
const stored = await this.keys.get('lid-mapping', pnUsers)
|
|
153
|
-
for (const pnUser of pnUsers) {
|
|
154
|
-
const lidUser = stored[pnUser]
|
|
155
|
-
if (lidUser && typeof lidUser === 'string') {
|
|
156
|
-
this.mappingCache.set(`pn:${pnUser}`, lidUser)
|
|
157
|
-
this.mappingCache.set(`lid:${lidUser}`, pnUser)
|
|
158
|
-
}
|
|
159
|
-
}
|
|
160
|
-
for (const { pn, pnUser, decoded } of pending) {
|
|
161
|
-
const cached = this.mappingCache.get(`pn:${pnUser}`)
|
|
162
|
-
if (cached && typeof cached === 'string') {
|
|
163
|
-
addResolvedPair(pn, decoded, cached)
|
|
164
|
-
continue
|
|
165
|
-
}
|
|
166
|
-
const device = decoded.device || 0
|
|
167
|
-
let normalizedPn = (0, WABinary_1.jidNormalizedUser)(pn)
|
|
168
|
-
if ((0, WABinary_1.isHostedPnUser)(normalizedPn)) {
|
|
169
|
-
normalizedPn = `${pnUser}@s.whatsapp.net`
|
|
170
|
-
}
|
|
171
|
-
if (!usyncFetch[normalizedPn]) {
|
|
172
|
-
usyncFetch[normalizedPn] = [device]
|
|
173
|
-
}
|
|
174
|
-
else {
|
|
175
|
-
usyncFetch[normalizedPn].push(device)
|
|
176
|
-
}
|
|
177
|
-
}
|
|
178
|
-
}
|
|
179
|
-
if (Object.keys(usyncFetch).length) {
|
|
180
|
-
const result = await this.pnToLIDFunc?.(Object.keys(usyncFetch))
|
|
181
|
-
if (result?.length) {
|
|
182
|
-
await this.storeLIDPNMappings(result)
|
|
183
|
-
for (const pair of result) {
|
|
184
|
-
const pnDecoded = (0, WABinary_1.jidDecode)(pair.pn)
|
|
185
|
-
const lidUser = (0, WABinary_1.jidDecode)(pair.lid)?.user
|
|
186
|
-
const pnUser = pnDecoded?.user
|
|
187
|
-
if (!pnUser || !lidUser) {
|
|
188
|
-
continue
|
|
189
|
-
}
|
|
190
|
-
for (const device of usyncFetch[pair.pn] || []) {
|
|
191
|
-
const deviceSpecificLid = `${lidUser}${device ? `:${device}` : ''}@${device === 99 ? 'hosted.lid' : 'lid'}`
|
|
192
|
-
const deviceSpecificPn = `${pnUser}${device ? `:${device}` : ''}@${device === 99 ? 'hosted' : 's.whatsapp.net'}`
|
|
193
|
-
successfulPairs[deviceSpecificPn] = { lid: deviceSpecificLid, pn: deviceSpecificPn }
|
|
194
|
-
}
|
|
195
|
-
}
|
|
196
|
-
}
|
|
197
|
-
else {
|
|
198
|
-
this.logger?.warn?.('USync did not return LID mappings for pending PN users')
|
|
199
|
-
}
|
|
200
|
-
}
|
|
201
|
-
const values = Object.values(successfulPairs)
|
|
202
|
-
return values.length ? values : null
|
|
203
|
-
}
|
|
204
|
-
async getPNForLID(lid) {
|
|
205
|
-
return (await this.getPNsForLIDs([lid]))?.[0]?.pn || null
|
|
206
|
-
}
|
|
207
|
-
async getPNsForLIDs(lids) {
|
|
208
|
-
if (!lids?.length) {
|
|
209
|
-
return null
|
|
210
|
-
}
|
|
211
|
-
const sortedLids = [...new Set(lids)].sort()
|
|
212
|
-
const cacheKey = sortedLids.join(',')
|
|
213
|
-
const inflight = this.inflightPNLookups.get(cacheKey)
|
|
214
|
-
if (inflight) {
|
|
215
|
-
return inflight
|
|
216
|
-
}
|
|
217
|
-
const promise = this._getPNsForLIDsImpl(lids)
|
|
218
|
-
this.inflightPNLookups.set(cacheKey, promise)
|
|
219
|
-
try {
|
|
220
|
-
return await promise
|
|
221
|
-
}
|
|
222
|
-
finally {
|
|
223
|
-
this.inflightPNLookups.delete(cacheKey)
|
|
224
|
-
}
|
|
225
|
-
}
|
|
226
|
-
async _getPNsForLIDsImpl(lids) {
|
|
227
|
-
const successfulPairs = {}
|
|
228
|
-
const pending = []
|
|
229
|
-
const addResolvedPair = (lid, decoded, pnUser) => {
|
|
230
|
-
if (!decoded || !pnUser || typeof pnUser !== 'string') {
|
|
231
|
-
return false
|
|
232
|
-
}
|
|
233
|
-
const lidDevice = decoded.device !== undefined ? decoded.device : 0
|
|
234
|
-
const pnJid = `${pnUser}${lidDevice ? `:${lidDevice}` : ''}@${decoded.domainType === WABinary_1.WAJIDDomains.HOSTED_LID ? 'hosted' : 's.whatsapp.net'}`
|
|
235
|
-
successfulPairs[lid] = { lid, pn: pnJid }
|
|
236
|
-
return true
|
|
237
|
-
}
|
|
238
|
-
for (const lid of lids) {
|
|
239
|
-
if (!(0, WABinary_1.isLidUser)(lid) && !(0, WABinary_1.isHostedLidUser)(lid)) {
|
|
240
|
-
continue
|
|
241
|
-
}
|
|
242
|
-
const decoded = (0, WABinary_1.jidDecode)(lid)
|
|
243
|
-
if (!decoded?.user) {
|
|
244
|
-
continue
|
|
245
|
-
}
|
|
246
|
-
const lidUser = decoded.user
|
|
247
|
-
const cached = this.mappingCache.get(`lid:${lidUser}`)
|
|
248
|
-
if (cached && typeof cached === 'string') {
|
|
249
|
-
addResolvedPair(lid, decoded, cached)
|
|
250
|
-
continue
|
|
251
|
-
}
|
|
252
|
-
pending.push({ lid, lidUser, decoded })
|
|
253
|
-
}
|
|
254
|
-
if (pending.length) {
|
|
255
|
-
const reverseKeys = [...new Set(pending.map(item => `${item.lidUser}_reverse`))]
|
|
256
|
-
const stored = await this.keys.get('lid-mapping', reverseKeys)
|
|
257
|
-
for (const { lid, lidUser, decoded } of pending) {
|
|
258
|
-
let pnUser = this.mappingCache.get(`lid:${lidUser}`)
|
|
259
|
-
if (!pnUser || typeof pnUser !== 'string') {
|
|
260
|
-
pnUser = stored[`${lidUser}_reverse`]
|
|
261
|
-
if (pnUser && typeof pnUser === 'string') {
|
|
262
|
-
this.mappingCache.set(`lid:${lidUser}`, pnUser)
|
|
263
|
-
this.mappingCache.set(`pn:${pnUser}`, lidUser)
|
|
264
|
-
}
|
|
265
|
-
}
|
|
266
|
-
if (pnUser && typeof pnUser === 'string') {
|
|
267
|
-
addResolvedPair(lid, decoded, pnUser)
|
|
268
|
-
}
|
|
269
|
-
}
|
|
270
|
-
}
|
|
271
|
-
const values = Object.values(successfulPairs)
|
|
272
|
-
return values.length ? values : null
|
|
273
|
-
}
|
|
274
|
-
}
|
|
275
|
-
|
|
276
|
-
module.exports = {
|
|
277
|
-
LIDMappingStore
|
|
278
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export { Browsers, getPlatformId } from './generics'
|