@hansaka02/baileys 7.3.2 → 7.3.6
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/lib/Defaults/baileys-version.json +2 -2
- package/lib/Defaults/connection.js +51 -0
- package/lib/Defaults/constants.js +74 -0
- package/lib/Defaults/history.js +19 -0
- package/lib/Defaults/index.js +36 -142
- package/lib/Defaults/media.js +48 -0
- package/lib/Defaults/prefix.js +18 -0
- package/lib/Signal/Group/group-session-builder.js +10 -42
- package/lib/Signal/Group/group_cipher.js +9 -6
- package/lib/Signal/Group/index.js +39 -53
- package/lib/Signal/Group/keyhelper.js +8 -41
- package/lib/Signal/Group/sender-chain-key.js +5 -18
- package/lib/Signal/Group/sender-key-distribution-message.js +7 -7
- package/lib/Signal/Group/sender-key-message.js +12 -8
- package/lib/Signal/Group/sender-key-record.js +7 -16
- package/lib/Signal/Group/sender-key-state.js +15 -61
- package/lib/Signal/Group/sender-message-key.js +2 -2
- package/lib/Signal/libsignal.js +237 -177
- package/lib/Signal/lid-mapping.js +128 -71
- package/lib/Socket/Client/types.js +2 -2
- package/lib/Socket/Client/websocket.js +25 -16
- package/lib/Socket/business.js +46 -33
- package/lib/Socket/chats.js +286 -170
- package/lib/Socket/community.js +215 -77
- package/lib/Socket/groups.js +77 -61
- package/lib/Socket/index.js +4 -4
- package/lib/Socket/messages-recv.js +629 -457
- package/lib/Socket/messages-send.js +645 -656
- package/lib/Socket/mex.js +61 -0
- package/lib/Socket/newsletter.js +166 -245
- package/lib/Socket/socket.js +396 -170
- package/lib/Store/index.js +27 -11
- package/lib/Store/make-cache-manager-store.js +14 -15
- package/lib/Store/make-in-memory-store.js +28 -24
- package/lib/Types/LabelAssociation.js +2 -2
- package/lib/Types/Message.js +6 -6
- package/lib/Types/MexUpdates.js +5 -5
- package/lib/Types/Newsletter.js +32 -25
- package/lib/Types/State.js +4 -4
- package/lib/Types/index.js +28 -12
- package/lib/Utils/auth-utils.js +212 -375
- package/lib/Utils/baileys-event-stream.js +68 -69
- package/lib/Utils/browser-utils.js +43 -0
- package/lib/Utils/business.js +63 -53
- package/lib/Utils/chat-utils.js +241 -106
- package/lib/Utils/crypto.js +25 -45
- package/lib/Utils/decode-wa-message.js +361 -311
- package/lib/Utils/event-buffer.js +97 -42
- package/lib/Utils/generics.js +90 -207
- package/lib/Utils/history.js +29 -27
- package/lib/Utils/index.js +28 -14
- package/lib/Utils/link-preview.js +24 -62
- package/lib/Utils/logger.js +5 -5
- package/lib/Utils/lt-hash.js +29 -23
- package/lib/Utils/make-mutex.js +26 -28
- package/lib/Utils/message-retry-manager.js +55 -7
- package/lib/Utils/messages-media.js +434 -247
- package/lib/Utils/messages.js +963 -917
- package/lib/Utils/noise-handler.js +60 -20
- package/lib/Utils/pre-key-manager.js +126 -0
- package/lib/Utils/process-message.js +216 -141
- package/lib/Utils/signal.js +75 -37
- package/lib/Utils/use-multi-file-auth-state.js +18 -22
- package/lib/Utils/validate-connection.js +96 -66
- package/lib/WABinary/constants.js +1268 -1268
- package/lib/WABinary/decode.js +62 -34
- package/lib/WABinary/encode.js +57 -36
- package/lib/WABinary/generic-utils.js +4 -4
- package/lib/WABinary/index.js +27 -11
- package/lib/WABinary/jid-utils.js +58 -11
- package/lib/WAM/constants.js +19064 -11563
- package/lib/WAM/encode.js +71 -14
- package/lib/WAM/index.js +27 -11
- package/lib/WAUSync/Protocols/USyncBotProfileProtocol.js +20 -16
- package/lib/WAUSync/Protocols/USyncContactProtocol.js +2 -2
- package/lib/WAUSync/Protocols/USyncDeviceProtocol.js +7 -4
- package/lib/WAUSync/Protocols/USyncDisappearingModeProtocol.js +2 -2
- package/lib/WAUSync/Protocols/USyncLIDProtocol.js +0 -2
- package/lib/WAUSync/Protocols/USyncStatusProtocol.js +2 -2
- package/lib/WAUSync/Protocols/index.js +27 -11
- package/lib/WAUSync/USyncQuery.js +51 -28
- package/lib/WAUSync/index.js +27 -11
- package/lib/index.js +60 -31
- package/package.json +12 -17
- package/WAProto/AICommon/AICommon.d.ts +0 -11702
- package/WAProto/Adv/Adv.d.ts +0 -643
- package/WAProto/BotMetadata/BotMetadata.d.ts +0 -5654
- package/WAProto/Cert/Cert.d.ts +0 -613
- package/WAProto/ChatLockSettings/ChatLockSettings.d.ts +0 -476
- package/WAProto/CompanionReg/CompanionReg.d.ts +0 -1361
- package/WAProto/DeviceCapabilities/DeviceCapabilities.d.ts +0 -577
- package/WAProto/E2E/E2E.d.ts +0 -41724
- package/WAProto/Ephemeral/Ephemeral.d.ts +0 -114
- package/WAProto/HistorySync/HistorySync.d.ts +0 -51700
- package/WAProto/LidMigrationSyncPayload/LidMigrationSyncPayload.d.ts +0 -229
- package/WAProto/MdStorageChatRowOpaqueData/MdStorageChatRowOpaqueData.d.ts +0 -583
- package/WAProto/MdStorageMsgRowOpaqueData/MdStorageMsgRowOpaqueData.d.ts +0 -42897
- package/WAProto/MmsRetry/MmsRetry.d.ts +0 -243
- package/WAProto/Protocol/Protocol.d.ts +0 -270
- package/WAProto/Reporting/Reporting.d.ts +0 -371
- package/WAProto/ServerSync/ServerSync.d.ts +0 -1285
- package/WAProto/SignalLocalStorageProtocol/SignalLocalStorageProtocol.d.ts +0 -1868
- package/WAProto/SignalWhisperTextProtocol/SignalWhisperTextProtocol.d.ts +0 -767
- package/WAProto/StatusAttributions/StatusAttributions.d.ts +0 -1027
- package/WAProto/SyncAction/SyncAction.d.ts +0 -11193
- package/WAProto/UserPassword/UserPassword.d.ts +0 -363
- package/WAProto/VnameCert/VnameCert.d.ts +0 -821
- package/WAProto/Wa6/Wa6.d.ts +0 -2128
- package/WAProto/Web/Web.d.ts +0 -46383
- package/WAProto/index.d.ts +0 -55
- package/lib/Defaults/index.d.ts +0 -77
- package/lib/Signal/Group/ciphertext-message.d.ts +0 -9
- package/lib/Signal/Group/group-session-builder.d.ts +0 -17
- package/lib/Signal/Group/group_cipher.d.ts +0 -19
- package/lib/Signal/Group/index.d.ts +0 -11
- package/lib/Signal/Group/keyhelper.d.ts +0 -16
- package/lib/Signal/Group/sender-chain-key.d.ts +0 -14
- package/lib/Signal/Group/sender-key-distribution-message.d.ts +0 -17
- package/lib/Signal/Group/sender-key-message.d.ts +0 -19
- package/lib/Signal/Group/sender-key-name.d.ts +0 -19
- package/lib/Signal/Group/sender-key-record.d.ts +0 -32
- package/lib/Signal/Group/sender-key-state.d.ts +0 -44
- package/lib/Signal/Group/sender-message-key.d.ts +0 -11
- package/lib/Signal/libsignal.d.ts +0 -8
- package/lib/Signal/lid-mapping.d.ts +0 -28
- package/lib/Socket/Client/index.d.ts +0 -2
- package/lib/Socket/Client/types.d.ts +0 -16
- package/lib/Socket/Client/websocket.d.ts +0 -13
- package/lib/Socket/business.d.ts +0 -187
- package/lib/Socket/chats.d.ts +0 -97
- package/lib/Socket/community.d.ts +0 -129
- package/lib/Socket/groups.d.ts +0 -129
- package/lib/Socket/index.d.ts +0 -191
- package/lib/Socket/messages-recv.d.ts +0 -174
- package/lib/Socket/messages-send.d.ts +0 -165
- package/lib/Socket/newsletter.d.ts +0 -145
- package/lib/Socket/socket.d.ts +0 -45
- package/lib/Socket/usync.d.ts +0 -37
- package/lib/Socket/usync.js +0 -83
- package/lib/Store/index.d.ts +0 -4
- package/lib/Store/make-cache-manager-store.d.ts +0 -14
- package/lib/Store/make-in-memory-store.d.ts +0 -123
- package/lib/Store/make-ordered-dictionary.d.ts +0 -12
- package/lib/Store/object-repository.d.ts +0 -10
- package/lib/Types/Auth.d.ts +0 -121
- package/lib/Types/Bussiness.d.ts +0 -28
- package/lib/Types/Call.d.ts +0 -14
- package/lib/Types/Chat.d.ts +0 -143
- package/lib/Types/Contact.d.ts +0 -23
- package/lib/Types/Events.d.ts +0 -226
- package/lib/Types/GroupMetadata.d.ts +0 -66
- package/lib/Types/Label.d.ts +0 -48
- package/lib/Types/LabelAssociation.d.ts +0 -35
- package/lib/Types/Message.d.ts +0 -484
- package/lib/Types/MexUpdates.d.ts +0 -9
- package/lib/Types/Newsletter.d.ts +0 -109
- package/lib/Types/Product.d.ts +0 -92
- package/lib/Types/Signal.d.ts +0 -98
- package/lib/Types/Socket.d.ts +0 -141
- package/lib/Types/State.d.ts +0 -41
- package/lib/Types/USync.d.ts +0 -26
- package/lib/Types/index.d.ts +0 -80
- package/lib/Utils/auth-utils.d.ts +0 -21
- package/lib/Utils/baileys-event-stream.d.ts +0 -18
- package/lib/Utils/business.d.ts +0 -29
- package/lib/Utils/chat-utils.d.ts +0 -82
- package/lib/Utils/crypto.d.ts +0 -56
- package/lib/Utils/decode-wa-message.d.ts +0 -53
- package/lib/Utils/event-buffer.d.ts +0 -39
- package/lib/Utils/generics.d.ts +0 -117
- package/lib/Utils/history.d.ts +0 -23
- package/lib/Utils/index.d.ts +0 -20
- package/lib/Utils/link-preview.d.ts +0 -23
- package/lib/Utils/logger.d.ts +0 -13
- package/lib/Utils/lt-hash.d.ts +0 -14
- package/lib/Utils/make-mutex.d.ts +0 -9
- package/lib/Utils/message-retry-manager.d.ts +0 -88
- package/lib/Utils/messages-media.d.ts +0 -135
- package/lib/Utils/messages.d.ts +0 -105
- package/lib/Utils/noise-handler.d.ts +0 -20
- package/lib/Utils/process-message.d.ts +0 -49
- package/lib/Utils/signal.d.ts +0 -42
- package/lib/Utils/use-mongo-file-auth-state.d.ts +0 -6
- package/lib/Utils/use-mongo-file-auth-state.js +0 -84
- package/lib/Utils/use-multi-file-auth-state.d.ts +0 -13
- package/lib/Utils/use-single-file-auth-state.d.ts +0 -13
- package/lib/Utils/use-single-file-auth-state.js +0 -80
- package/lib/Utils/validate-connection.d.ts +0 -13
- package/lib/WABinary/constants.d.ts +0 -30
- package/lib/WABinary/decode.d.ts +0 -9
- package/lib/WABinary/encode.d.ts +0 -3
- package/lib/WABinary/generic-utils.d.ts +0 -28
- package/lib/WABinary/index.d.ts +0 -5
- package/lib/WABinary/jid-utils.d.ts +0 -58
- package/lib/WABinary/types.d.ts +0 -22
- package/lib/WAM/BinaryInfo.d.ts +0 -16
- package/lib/WAM/constants.d.ts +0 -47
- package/lib/WAM/encode.d.ts +0 -3
- package/lib/WAM/index.d.ts +0 -3
- package/lib/WAUSync/Protocols/USyncBotProfileProtocol.d.ts +0 -28
- package/lib/WAUSync/Protocols/USyncContactProtocol.d.ts +0 -10
- package/lib/WAUSync/Protocols/USyncDeviceProtocol.d.ts +0 -26
- package/lib/WAUSync/Protocols/USyncDisappearingModeProtocol.d.ts +0 -14
- package/lib/WAUSync/Protocols/USyncLIDProtocol.d.ts +0 -10
- package/lib/WAUSync/Protocols/USyncStatusProtocol.d.ts +0 -14
- package/lib/WAUSync/Protocols/index.d.ts +0 -6
- package/lib/WAUSync/USyncQuery.d.ts +0 -31
- package/lib/WAUSync/USyncUser.d.ts +0 -12
- package/lib/WAUSync/index.d.ts +0 -3
- package/lib/index.d.ts +0 -13
package/lib/Signal/libsignal.js
CHANGED
|
@@ -1,99 +1,88 @@
|
|
|
1
1
|
"use strict"
|
|
2
2
|
|
|
3
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
4
|
-
if (k2 === undefined) k2 = k
|
|
5
|
-
var desc = Object.getOwnPropertyDescriptor(m, k)
|
|
6
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
7
|
-
desc = { enumerable: true, get: function() { return m[k] } }
|
|
8
|
-
}
|
|
9
|
-
Object.defineProperty(o, k2, desc)
|
|
10
|
-
}) : (function(o, m, k, k2) {
|
|
11
|
-
if (k2 === undefined) k2 = k
|
|
12
|
-
o[k2] = m[k]
|
|
13
|
-
}))
|
|
14
|
-
|
|
15
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
16
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v })
|
|
17
|
-
}) : function(o, v) {
|
|
18
|
-
o["default"] = v
|
|
19
|
-
})
|
|
20
|
-
|
|
21
|
-
var __importStar = (this && this.__importStar) || (function () {
|
|
22
|
-
var ownKeys = function(o) {
|
|
23
|
-
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
24
|
-
var ar = []
|
|
25
|
-
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k
|
|
26
|
-
return ar
|
|
27
|
-
}
|
|
28
|
-
return ownKeys(o)
|
|
29
|
-
}
|
|
30
|
-
return function (mod) {
|
|
31
|
-
if (mod && mod.__esModule) return mod
|
|
32
|
-
var result = {}
|
|
33
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i])
|
|
34
|
-
__setModuleDefault(result, mod)
|
|
35
|
-
return result
|
|
36
|
-
}
|
|
37
|
-
})()
|
|
38
|
-
|
|
39
3
|
Object.defineProperty(exports, "__esModule", { value: true })
|
|
40
4
|
|
|
41
|
-
const
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
const
|
|
5
|
+
const {
|
|
6
|
+
SessionCipher,
|
|
7
|
+
SessionBuilder,
|
|
8
|
+
SessionRecord,
|
|
9
|
+
ProtocolAddress
|
|
10
|
+
} = require("@itsukichan/libsignal-node")
|
|
11
|
+
const { generateSignalPubKey } = require("../Utils")
|
|
12
|
+
const {
|
|
13
|
+
isHostedLidUser,
|
|
14
|
+
isHostedPnUser,
|
|
15
|
+
isLidUser,
|
|
16
|
+
isPnUser,
|
|
17
|
+
jidDecode,
|
|
18
|
+
transferDevice,
|
|
19
|
+
WAJIDDomains
|
|
20
|
+
} = require("../WABinary")
|
|
21
|
+
const { SenderKeyName } = require("./Group/sender-key-name")
|
|
22
|
+
const { SenderKeyRecord } = require("./Group/sender-key-record")
|
|
23
|
+
const {
|
|
24
|
+
GroupCipher,
|
|
25
|
+
GroupSessionBuilder,
|
|
26
|
+
SenderKeyDistributionMessage
|
|
27
|
+
} = require("./Group")
|
|
28
|
+
const { LRUCache } = require("lru-cache")
|
|
29
|
+
const { LIDMappingStore } = require("./lid-mapping")
|
|
48
30
|
|
|
49
|
-
function makeLibSignalRepository(auth,
|
|
50
|
-
|
|
31
|
+
function makeLibSignalRepository(auth, logger, pnToLIDFunc) {
|
|
32
|
+
const lidMapping = new LIDMappingStore(auth.keys, logger, pnToLIDFunc)
|
|
51
33
|
const storage = signalStorage(auth, lidMapping)
|
|
52
34
|
const parsedKeys = auth.keys
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
return (key.includes('@lid.whatsapp.net') || // WhatsApp system messages
|
|
59
|
-
key.includes('@broadcast') || // Broadcast messages
|
|
60
|
-
key.includes('@newsletter'))
|
|
61
|
-
}
|
|
35
|
+
const migratedSessionCache = new LRUCache({
|
|
36
|
+
ttl: 3 * 24 * 60 * 60 * 1000, // 7 days
|
|
37
|
+
ttlAutopurge: true,
|
|
38
|
+
updateAgeOnGet: true
|
|
39
|
+
})
|
|
62
40
|
|
|
63
41
|
const repository = {
|
|
64
42
|
decryptGroupMessage({ group, authorJid, msg }) {
|
|
65
43
|
const senderName = jidToSignalSenderKeyName(group, authorJid)
|
|
66
|
-
const cipher = new
|
|
44
|
+
const cipher = new GroupCipher(storage, senderName)
|
|
45
|
+
|
|
67
46
|
// Use transaction to ensure atomicity
|
|
68
47
|
return parsedKeys.transaction(async () => {
|
|
69
48
|
return cipher.decrypt(msg)
|
|
70
49
|
}, group)
|
|
71
50
|
},
|
|
51
|
+
|
|
72
52
|
async processSenderKeyDistributionMessage({ item, authorJid }) {
|
|
73
|
-
const builder = new
|
|
53
|
+
const builder = new GroupSessionBuilder(storage)
|
|
54
|
+
|
|
74
55
|
if (!item.groupId) {
|
|
75
56
|
throw new Error('Group ID is required for sender key distribution message')
|
|
76
57
|
}
|
|
58
|
+
|
|
77
59
|
const senderName = jidToSignalSenderKeyName(item.groupId, authorJid)
|
|
78
|
-
const senderMsg = new
|
|
60
|
+
const senderMsg = new SenderKeyDistributionMessage(null, null, null, null, item.axolotlSenderKeyDistributionMessage)
|
|
79
61
|
const senderNameStr = senderName.toString()
|
|
80
62
|
const { [senderNameStr]: senderKey } = await auth.keys.get('sender-key', [senderNameStr])
|
|
63
|
+
|
|
81
64
|
if (!senderKey) {
|
|
82
|
-
await storage.storeSenderKey(senderName, new
|
|
65
|
+
await storage.storeSenderKey(senderName, new SenderKeyRecord())
|
|
83
66
|
}
|
|
67
|
+
|
|
84
68
|
return parsedKeys.transaction(async () => {
|
|
85
69
|
const { [senderNameStr]: senderKey } = await auth.keys.get('sender-key', [senderNameStr])
|
|
70
|
+
|
|
86
71
|
if (!senderKey) {
|
|
87
|
-
await storage.storeSenderKey(senderName, new
|
|
72
|
+
await storage.storeSenderKey(senderName, new SenderKeyRecord())
|
|
88
73
|
}
|
|
74
|
+
|
|
89
75
|
await builder.process(senderName, senderMsg)
|
|
90
76
|
}, item.groupId)
|
|
91
77
|
},
|
|
78
|
+
|
|
92
79
|
async decryptMessage({ jid, type, ciphertext }) {
|
|
93
80
|
const addr = jidToSignalProtocolAddress(jid)
|
|
94
|
-
const session = new
|
|
81
|
+
const session = new SessionCipher(storage, addr)
|
|
82
|
+
|
|
95
83
|
async function doDecrypt() {
|
|
96
84
|
let result
|
|
85
|
+
|
|
97
86
|
switch (type) {
|
|
98
87
|
case 'pkmsg':
|
|
99
88
|
result = await session.decryptPreKeyWhisperMessage(ciphertext)
|
|
@@ -102,98 +91,91 @@ function makeLibSignalRepository(auth, onWhatsAppFunc, logger) {
|
|
|
102
91
|
result = await session.decryptWhisperMessage(ciphertext)
|
|
103
92
|
break
|
|
104
93
|
}
|
|
94
|
+
|
|
105
95
|
return result
|
|
106
96
|
}
|
|
107
|
-
|
|
108
|
-
// If it's a sync message, we can skip the transaction
|
|
109
|
-
// as it is likely to be a system message that doesn't require strict atomicity
|
|
110
|
-
return await doDecrypt()
|
|
111
|
-
}
|
|
97
|
+
|
|
112
98
|
// If it's not a sync message, we need to ensure atomicity
|
|
113
99
|
// For regular messages, we use a transaction to ensure atomicity
|
|
114
100
|
return parsedKeys.transaction(async () => {
|
|
115
101
|
return await doDecrypt()
|
|
116
102
|
}, jid)
|
|
117
103
|
},
|
|
104
|
+
|
|
118
105
|
async encryptMessage({ jid, data }) {
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
if (jid.includes('@s.whatsapp.net')) {
|
|
123
|
-
const lidForPN = await lidMapping.getLIDForPN(jid)
|
|
124
|
-
if (lidForPN?.includes('@lid')) {
|
|
125
|
-
const lidAddr = jidToSignalProtocolAddress(lidForPN)
|
|
126
|
-
const { [lidAddr.toString()]: lidSession } = await auth.keys.get('session', [lidAddr.toString()])
|
|
127
|
-
if (lidSession) {
|
|
128
|
-
// LID session exists, use it
|
|
129
|
-
encryptionJid = lidForPN
|
|
130
|
-
}
|
|
131
|
-
else {
|
|
132
|
-
// Try to migrate if PN session exists
|
|
133
|
-
const pnAddr = jidToSignalProtocolAddress(jid)
|
|
134
|
-
const { [pnAddr.toString()]: pnSession } = await auth.keys.get('session', [pnAddr.toString()])
|
|
135
|
-
if (pnSession) {
|
|
136
|
-
// Migrate PN to LID
|
|
137
|
-
await repository.migrateSession([jid], lidForPN)
|
|
138
|
-
encryptionJid = lidForPN
|
|
139
|
-
}
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
const addr = jidToSignalProtocolAddress(encryptionJid)
|
|
144
|
-
const cipher = new libsignal.SessionCipher(storage, addr)
|
|
106
|
+
const addr = jidToSignalProtocolAddress(jid)
|
|
107
|
+
const cipher = new SessionCipher(storage, addr)
|
|
108
|
+
|
|
145
109
|
// Use transaction to ensure atomicity
|
|
146
110
|
return parsedKeys.transaction(async () => {
|
|
147
111
|
const { type: sigType, body } = await cipher.encrypt(data)
|
|
148
112
|
const type = sigType === 3 ? 'pkmsg' : 'msg'
|
|
113
|
+
|
|
149
114
|
return { type, ciphertext: Buffer.from(body, 'binary') }
|
|
150
115
|
}, jid)
|
|
151
116
|
},
|
|
117
|
+
|
|
152
118
|
async encryptGroupMessage({ group, meId, data }) {
|
|
153
119
|
const senderName = jidToSignalSenderKeyName(group, meId)
|
|
154
|
-
const builder = new
|
|
120
|
+
const builder = new GroupSessionBuilder(storage)
|
|
155
121
|
const senderNameStr = senderName.toString()
|
|
122
|
+
|
|
156
123
|
return parsedKeys.transaction(async () => {
|
|
157
124
|
const { [senderNameStr]: senderKey } = await auth.keys.get('sender-key', [senderNameStr])
|
|
125
|
+
|
|
158
126
|
if (!senderKey) {
|
|
159
|
-
await storage.storeSenderKey(senderName, new
|
|
127
|
+
await storage.storeSenderKey(senderName, new SenderKeyRecord())
|
|
160
128
|
}
|
|
129
|
+
|
|
161
130
|
const senderKeyDistributionMessage = await builder.create(senderName)
|
|
162
|
-
const session = new
|
|
131
|
+
const session = new GroupCipher(storage, senderName)
|
|
163
132
|
const ciphertext = await session.encrypt(data)
|
|
133
|
+
|
|
164
134
|
return {
|
|
165
135
|
ciphertext,
|
|
166
136
|
senderKeyDistributionMessage: senderKeyDistributionMessage.serialize()
|
|
167
137
|
}
|
|
168
138
|
}, group)
|
|
169
|
-
},
|
|
139
|
+
},
|
|
140
|
+
|
|
170
141
|
async injectE2ESession({ jid, session }) {
|
|
171
|
-
|
|
142
|
+
logger.trace({ jid }, 'injecting E2EE session')
|
|
143
|
+
|
|
144
|
+
const cipher = new SessionBuilder(storage, jidToSignalProtocolAddress(jid))
|
|
145
|
+
|
|
172
146
|
return parsedKeys.transaction(async () => {
|
|
173
147
|
await cipher.initOutgoing(session)
|
|
174
148
|
}, jid)
|
|
175
149
|
},
|
|
150
|
+
|
|
176
151
|
jidToSignalProtocolAddress(jid) {
|
|
177
152
|
return jidToSignalProtocolAddress(jid).toString()
|
|
178
153
|
},
|
|
154
|
+
|
|
179
155
|
// Optimized direct access to LID mapping store
|
|
180
156
|
lidMapping,
|
|
157
|
+
|
|
181
158
|
async validateSession(jid) {
|
|
182
159
|
try {
|
|
183
160
|
const addr = jidToSignalProtocolAddress(jid)
|
|
184
161
|
const session = await storage.loadSession(addr.toString())
|
|
162
|
+
|
|
185
163
|
if (!session) {
|
|
186
164
|
return { exists: false, reason: 'no session' }
|
|
187
165
|
}
|
|
166
|
+
|
|
188
167
|
if (!session.haveOpenSession()) {
|
|
189
168
|
return { exists: false, reason: 'no open session' }
|
|
190
169
|
}
|
|
170
|
+
|
|
191
171
|
return { exists: true }
|
|
192
172
|
}
|
|
173
|
+
|
|
193
174
|
catch (error) {
|
|
194
175
|
return { exists: false, reason: 'validation error' }
|
|
195
176
|
}
|
|
196
177
|
},
|
|
178
|
+
|
|
197
179
|
async deleteSession(jids) {
|
|
198
180
|
if (!jids.length) return
|
|
199
181
|
|
|
@@ -210,31 +192,81 @@ function makeLibSignalRepository(auth, onWhatsAppFunc, logger) {
|
|
|
210
192
|
await auth.keys.set({ session: sessionUpdates })
|
|
211
193
|
}, `delete-${jids.length}-sessions`)
|
|
212
194
|
},
|
|
213
|
-
|
|
214
|
-
|
|
195
|
+
|
|
196
|
+
async migrateSession(fromJid, toJid) {
|
|
197
|
+
// TODO: use usync to handle this entire mess
|
|
198
|
+
if (!fromJid || (!isLidUser(toJid) && !isHostedLidUser(toJid))) {
|
|
215
199
|
return { migrated: 0, skipped: 0, total: 0 }
|
|
216
|
-
|
|
217
|
-
// Filter valid PN JIDs
|
|
218
|
-
const validJids = fromJids.filter(jid => jid.includes('@s.whatsapp.net'))
|
|
200
|
+
}
|
|
219
201
|
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
202
|
+
// Only support PN to LID migration
|
|
203
|
+
if (!isPnUser(fromJid) && !isHostedPnUser(fromJid)) {
|
|
204
|
+
return { migrated: 0, skipped: 0, total: 1 }
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
const { user } = jidDecode(fromJid)
|
|
208
|
+
|
|
209
|
+
logger.debug({ fromJid }, 'bulk device migration - loading all user devices')
|
|
210
|
+
|
|
211
|
+
// Get user's device list from storage
|
|
212
|
+
const { [user]: userDevices } = await parsedKeys.get('device-list', [user])
|
|
213
|
+
|
|
214
|
+
if (!userDevices) {
|
|
215
|
+
return { migrated: 0, skipped: 0, total: 0 }
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
const { device: fromDevice } = jidDecode(fromJid)
|
|
219
|
+
const fromDeviceStr = fromDevice?.toString() || '0'
|
|
220
|
+
|
|
221
|
+
if (!userDevices.includes(fromDeviceStr)) {
|
|
222
|
+
userDevices.push(fromDeviceStr)
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
// Filter out cached devices before database fetch
|
|
226
|
+
const uncachedDevices = userDevices.filter(device => {
|
|
227
|
+
const deviceKey = `${user}.${device}`
|
|
228
|
+
return !migratedSessionCache.has(deviceKey)
|
|
229
|
+
})
|
|
230
|
+
|
|
231
|
+
// Bulk check session existence only for uncached devices
|
|
232
|
+
const deviceSessionKeys = uncachedDevices.map(device => `${user}.${device}`)
|
|
233
|
+
const existingSessions = await parsedKeys.get('session', deviceSessionKeys)
|
|
234
|
+
|
|
235
|
+
// Step 3: Convert existing sessions to JIDs (only migrate sessions that exist)
|
|
236
|
+
const deviceJids = []
|
|
237
|
+
|
|
238
|
+
for (const [sessionKey, sessionData] of Object.entries(existingSessions)) {
|
|
239
|
+
if (sessionData) {
|
|
240
|
+
// Session exists in storage
|
|
241
|
+
const deviceStr = sessionKey.split('.')[1]
|
|
242
|
+
|
|
243
|
+
if (!deviceStr) continue
|
|
244
|
+
|
|
245
|
+
const deviceNum = parseInt(deviceStr)
|
|
246
|
+
|
|
247
|
+
let jid = deviceNum === 0 ? `${user}@s.whatsapp.net` : `${user}:${deviceNum}@s.whatsapp.net`
|
|
248
|
+
|
|
249
|
+
if (deviceNum === 99) {
|
|
250
|
+
jid = `${user}:99@hosted`
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
deviceJids.push(jid)
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
logger.debug({
|
|
258
|
+
fromJid,
|
|
259
|
+
totalDevices: userDevices.length,
|
|
260
|
+
devicesWithSessions: deviceJids.length,
|
|
261
|
+
devices: deviceJids
|
|
262
|
+
}, 'bulk device migration complete - all user devices processed')
|
|
263
|
+
|
|
264
|
+
// Single transaction for all migrations
|
|
224
265
|
return parsedKeys.transaction(async () => {
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
}))
|
|
230
|
-
|
|
231
|
-
await lidMapping.storeLIDPNMappings(mappings)
|
|
232
|
-
|
|
233
|
-
// 2. Prepare migration operations
|
|
234
|
-
const migrationOps = validJids.map(jid => {
|
|
235
|
-
const lidWithDevice = WABinary_1.transferDevice(jid, toJid)
|
|
236
|
-
const fromDecoded = WABinary_1.jidDecode(jid)
|
|
237
|
-
const toDecoded = WABinary_1.jidDecode(lidWithDevice)
|
|
266
|
+
const migrationOps = deviceJids.map(jid => {
|
|
267
|
+
const lidWithDevice = transferDevice(jid, toJid)
|
|
268
|
+
const fromDecoded = jidDecode(jid)
|
|
269
|
+
const toDecoded = jidDecode(lidWithDevice)
|
|
238
270
|
|
|
239
271
|
return {
|
|
240
272
|
fromJid: jid,
|
|
@@ -247,106 +279,132 @@ function makeLibSignalRepository(auth, onWhatsAppFunc, logger) {
|
|
|
247
279
|
}
|
|
248
280
|
})
|
|
249
281
|
|
|
250
|
-
|
|
251
|
-
const lidAddrs = migrationOps.map(op => op.toAddr.toString())
|
|
252
|
-
const existingSessions = await auth.keys.get('session', lidAddrs)
|
|
282
|
+
const totalOps = migrationOps.length
|
|
253
283
|
|
|
254
|
-
|
|
255
|
-
const opsToMigrate = migrationOps.filter(op => !existingSessions[op.toAddr.toString()])
|
|
256
|
-
const skippedCount = migrationOps.length - opsToMigrate.length
|
|
284
|
+
let migratedCount = 0
|
|
257
285
|
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
286
|
+
// Bulk fetch PN sessions - already exist (verified during device discovery)
|
|
287
|
+
const pnAddrStrings = Array.from(new Set(migrationOps.map(op => op.fromAddr.toString())))
|
|
288
|
+
const pnSessions = await parsedKeys.get('session', pnAddrStrings)
|
|
289
|
+
|
|
290
|
+
// Prepare bulk session updates (PN → LID migration + deletion)
|
|
291
|
+
const sessionUpdates = {}
|
|
261
292
|
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
const
|
|
293
|
+
for (const op of migrationOps) {
|
|
294
|
+
const pnAddrStr = op.fromAddr.toString()
|
|
295
|
+
const lidAddrStr = op.toAddr.toString()
|
|
296
|
+
const pnSession = pnSessions[pnAddrStr]
|
|
265
297
|
|
|
266
|
-
if (
|
|
267
|
-
//
|
|
268
|
-
const
|
|
269
|
-
const copiedSession = libsignal.SessionRecord.deserialize(sessionBytes)
|
|
270
|
-
await storage.storeSession(op.toAddr.toString(), copiedSession)
|
|
298
|
+
if (pnSession) {
|
|
299
|
+
// Session exists (guaranteed from device discovery)
|
|
300
|
+
const fromSession = SessionRecord.deserialize(pnSession)
|
|
271
301
|
|
|
272
|
-
|
|
273
|
-
|
|
302
|
+
if (fromSession.haveOpenSession()) {
|
|
303
|
+
// Queue for bulk update: copy to LID, delete from PN
|
|
304
|
+
sessionUpdates[lidAddrStr] = fromSession.serialize()
|
|
305
|
+
sessionUpdates[pnAddrStr] = null
|
|
306
|
+
migratedCount++
|
|
307
|
+
}
|
|
274
308
|
}
|
|
275
|
-
}
|
|
309
|
+
}
|
|
276
310
|
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
311
|
+
// Single bulk session update for all migrations
|
|
312
|
+
if (Object.keys(sessionUpdates).length > 0) {
|
|
313
|
+
await parsedKeys.set({ session: sessionUpdates })
|
|
314
|
+
|
|
315
|
+
logger.debug({ migratedSessions: migratedCount }, 'bulk session migration complete')
|
|
316
|
+
|
|
317
|
+
// Cache device-level migrations
|
|
318
|
+
for (const op of migrationOps) {
|
|
319
|
+
if (sessionUpdates[op.toAddr.toString()]) {
|
|
320
|
+
const deviceKey = `${op.pnUser}.${op.deviceId}`
|
|
321
|
+
migratedSessionCache.set(deviceKey, true)
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
const skippedCount = totalOps - migratedCount
|
|
327
|
+
|
|
328
|
+
return { migrated: migratedCount, skipped: skippedCount, total: totalOps }
|
|
329
|
+
}, `migrate-${deviceJids.length}-sessions-${jidDecode(toJid)?.user}`)
|
|
283
330
|
}
|
|
284
331
|
}
|
|
332
|
+
|
|
285
333
|
return repository
|
|
286
334
|
}
|
|
287
335
|
|
|
288
336
|
const jidToSignalProtocolAddress = (jid) => {
|
|
289
|
-
const decoded =
|
|
290
|
-
const { user, device, server } = decoded
|
|
337
|
+
const decoded = jidDecode(jid)
|
|
338
|
+
const { user, device, server, domainType } = decoded
|
|
291
339
|
|
|
292
340
|
if (!user) {
|
|
293
341
|
throw new Error(`JID decoded but user is empty: "${jid}" -> user: "${user}", server: "${server}", device: ${device}`)
|
|
294
342
|
}
|
|
295
343
|
|
|
296
|
-
|
|
297
|
-
const signalUser = server === 'lid' ? `${user}_1` : user
|
|
344
|
+
const signalUser = domainType !== WAJIDDomains.WHATSAPP ? `${user}_${domainType}` : user
|
|
298
345
|
const finalDevice = device || 0
|
|
299
346
|
|
|
300
|
-
|
|
347
|
+
if (device === 99 && decoded.server !== 'hosted' && decoded.server !== 'hosted.lid') {
|
|
348
|
+
throw new Error('Unexpected non-hosted device JID with device 99. This ID seems invalid. ID:' + jid)
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
return new ProtocolAddress(signalUser, finalDevice)
|
|
301
352
|
}
|
|
302
353
|
|
|
303
354
|
const jidToSignalSenderKeyName = (group, user) => {
|
|
304
|
-
return new
|
|
355
|
+
return new SenderKeyName(group, jidToSignalProtocolAddress(user))
|
|
305
356
|
}
|
|
306
357
|
|
|
307
358
|
function signalStorage({ creds, keys }, lidMapping) {
|
|
359
|
+
// Shared function to resolve PN signal address to LID if mapping exists
|
|
360
|
+
const resolveLIDSignalAddress = async (id) => {
|
|
361
|
+
if (id.includes('.')) {
|
|
362
|
+
const [deviceId, device] = id.split('.')
|
|
363
|
+
const [user, domainType_] = deviceId.split('_')
|
|
364
|
+
const domainType = parseInt(domainType_ || '0')
|
|
365
|
+
|
|
366
|
+
if (domainType === WAJIDDomains.LID || domainType === WAJIDDomains.HOSTED_LID) return id
|
|
367
|
+
|
|
368
|
+
const pnJid = `${user}${device !== '0' ? `:${device}` : ''}@${domainType === WAJIDDomains.HOSTED ? 'hosted' : 's.whatsapp.net'}`
|
|
369
|
+
const lidForPN = await lidMapping.getLIDForPN(pnJid)
|
|
370
|
+
|
|
371
|
+
if (lidForPN) {
|
|
372
|
+
const lidAddr = jidToSignalProtocolAddress(lidForPN)
|
|
373
|
+
return lidAddr.toString()
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
return id
|
|
378
|
+
}
|
|
379
|
+
|
|
308
380
|
return {
|
|
309
381
|
loadSession: async (id) => {
|
|
310
382
|
try {
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
// This is a PN signal address format (e.g., "1234567890.0")
|
|
315
|
-
// Convert back to JID to check for LID mapping
|
|
316
|
-
const parts = id.split('.')
|
|
317
|
-
const device = parts[1] || '0'
|
|
318
|
-
const pnJid = device === '0' ? `${parts[0]}@s.whatsapp.net` : `${parts[0]}:${device}@s.whatsapp.net`
|
|
319
|
-
const lidForPN = await lidMapping.getLIDForPN(pnJid)
|
|
320
|
-
if (lidForPN?.includes('@lid')) {
|
|
321
|
-
const lidAddr = jidToSignalProtocolAddress(lidForPN)
|
|
322
|
-
const lidId = lidAddr.toString()
|
|
323
|
-
// Check if LID session exists
|
|
324
|
-
const { [lidId]: lidSession } = await keys.get('session', [lidId])
|
|
325
|
-
if (lidSession) {
|
|
326
|
-
actualId = lidId
|
|
327
|
-
}
|
|
328
|
-
}
|
|
329
|
-
}
|
|
330
|
-
const { [actualId]: sess } = await keys.get('session', [actualId])
|
|
383
|
+
const wireJid = await resolveLIDSignalAddress(id)
|
|
384
|
+
const { [wireJid]: sess } = await keys.get('session', [wireJid])
|
|
385
|
+
|
|
331
386
|
if (sess) {
|
|
332
|
-
return
|
|
387
|
+
return SessionRecord.deserialize(sess)
|
|
333
388
|
}
|
|
334
389
|
}
|
|
390
|
+
|
|
335
391
|
catch (e) {
|
|
336
392
|
return null
|
|
337
393
|
}
|
|
394
|
+
|
|
338
395
|
return null
|
|
339
396
|
},
|
|
340
|
-
// TODO: Replace with libsignal.SessionRecord when type exports are added to libsignal
|
|
341
397
|
storeSession: async (id, session) => {
|
|
342
|
-
|
|
398
|
+
const wireJid = await resolveLIDSignalAddress(id)
|
|
399
|
+
await keys.set({ session: { [wireJid]: session.serialize() } })
|
|
343
400
|
},
|
|
344
401
|
isTrustedIdentity: () => {
|
|
345
|
-
return true
|
|
402
|
+
return true // todo: implement
|
|
346
403
|
},
|
|
347
404
|
loadPreKey: async (id) => {
|
|
348
405
|
const keyId = id.toString()
|
|
349
406
|
const { [keyId]: key } = await keys.get('pre-key', [keyId])
|
|
407
|
+
|
|
350
408
|
if (key) {
|
|
351
409
|
return {
|
|
352
410
|
privKey: Buffer.from(key.private),
|
|
@@ -365,10 +423,12 @@ function signalStorage({ creds, keys }, lidMapping) {
|
|
|
365
423
|
loadSenderKey: async (senderKeyName) => {
|
|
366
424
|
const keyId = senderKeyName.toString()
|
|
367
425
|
const { [keyId]: key } = await keys.get('sender-key', [keyId])
|
|
426
|
+
|
|
368
427
|
if (key) {
|
|
369
|
-
return
|
|
428
|
+
return SenderKeyRecord.deserialize(key)
|
|
370
429
|
}
|
|
371
|
-
|
|
430
|
+
|
|
431
|
+
return new SenderKeyRecord()
|
|
372
432
|
},
|
|
373
433
|
storeSenderKey: async (senderKeyName, key) => {
|
|
374
434
|
const keyId = senderKeyName.toString()
|
|
@@ -380,7 +440,7 @@ function signalStorage({ creds, keys }, lidMapping) {
|
|
|
380
440
|
const { signedIdentityKey } = creds
|
|
381
441
|
return {
|
|
382
442
|
privKey: Buffer.from(signedIdentityKey.private),
|
|
383
|
-
pubKey: Buffer.from(
|
|
443
|
+
pubKey: Buffer.from(generateSignalPubKey(signedIdentityKey.public))
|
|
384
444
|
}
|
|
385
445
|
}
|
|
386
446
|
}
|