shadowx-fca 8.0.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 +1066 -0
- package/build/messagix.dll +0 -0
- package/build/messagix.so +0 -0
- package/checkUpdate.js +393 -0
- package/config.json +17 -0
- package/e2ee.js +563 -0
- package/e2eetest.js +356 -0
- package/index.js +611 -0
- package/lib/index.mjs +1412 -0
- package/logger.js +500 -0
- package/package.json +65 -0
- package/src/GetBotInfo.js +66 -0
- package/src/OldMessage.js +182 -0
- package/src/Screenshot.js +83 -0
- package/src/addExternalModule.js +13 -0
- package/src/addUserToGroup.js +33 -0
- package/src/approveGroupJoinRequests.js +18 -0
- package/src/changeAdminStatus.js +16 -0
- package/src/changeArchivedStatus.js +17 -0
- package/src/changeAvatar.js +136 -0
- package/src/changeAvatarV2.js +86 -0
- package/src/changeAvt.js +85 -0
- package/src/changeBio.js +76 -0
- package/src/changeBlockedStatus.js +20 -0
- package/src/changeBlockedStatusMqtt.js +80 -0
- package/src/changeCover.js +72 -0
- package/src/changeGroupImage.js +16 -0
- package/src/changeName.js +79 -0
- package/src/changeNickname.js +16 -0
- package/src/changeThreadColor.js +15 -0
- package/src/changeThreadEmoji.js +15 -0
- package/src/changeThreadMemberNickname.js +6 -0
- package/src/changeUsername.js +59 -0
- package/src/createCommentPost.js +230 -0
- package/src/createNewGroup.js +38 -0
- package/src/createNote.js +35 -0
- package/src/createPoll.js +27 -0
- package/src/createPost.js +276 -0
- package/src/createThemeAI.js +129 -0
- package/src/data/cache/system/data.json +4 -0
- package/src/data/cache/system/datahandle.js +21 -0
- package/src/data/getThreadInfo.json +1 -0
- package/src/deleteComment.js +23 -0
- package/src/deleteMessage.js +15 -0
- package/src/deleteThread.js +15 -0
- package/src/denyGroupJoinRequests.js +18 -0
- package/src/e2ee/crypto.js +173 -0
- package/src/e2ee/index.js +144 -0
- package/src/e2ee/proto/ArmadilloApplication.proto +281 -0
- package/src/e2ee/proto/ArmadilloICDC.proto +14 -0
- package/src/e2ee/proto/ConsumerApplication.proto +232 -0
- package/src/e2ee/proto/MessageApplication.proto +82 -0
- package/src/e2ee/proto/MessageTransport.proto +77 -0
- package/src/e2ee/proto/WACommon.proto +66 -0
- package/src/e2ee/proto/WAMediaTransport.proto +176 -0
- package/src/e2ee/proto/proto-writer.ts +76 -0
- package/src/e2ee/protocol.js +196 -0
- package/src/e2ee/ratchet.js +219 -0
- package/src/e2ee/store.js +182 -0
- package/src/e2ee.js +8 -0
- package/src/editMessage.js +56 -0
- package/src/editMessageOld.js +67 -0
- package/src/enableReactions.js +24 -0
- package/src/follow.js +74 -0
- package/src/followUser.js +23 -0
- package/src/forwardAttachment.js +16 -0
- package/src/friendList.js +98 -0
- package/src/getAccess.js +112 -0
- package/src/getAppState.js +13 -0
- package/src/getAvatarUser.js +11 -0
- package/src/getBio.js +24 -0
- package/src/getBotInitialData.js +42 -0
- package/src/getCtx.js +5 -0
- package/src/getCurrentUserID.js +6 -0
- package/src/getEmojiUrl.js +29 -0
- package/src/getFriendsList.js +36 -0
- package/src/getMessage.js +37 -0
- package/src/getNotes.js +17 -0
- package/src/getOptions.js +5 -0
- package/src/getPinnedMessages.js +33 -0
- package/src/getPostInfo.js +17 -0
- package/src/getProfileInfo.js +17 -0
- package/src/getPublicData.js +25 -0
- package/src/getRegion.js +7 -0
- package/src/getRepInfo.js +17 -0
- package/src/getStickerPacks.js +25 -0
- package/src/getStickers.js +39 -0
- package/src/getStoryReactions.js +18 -0
- package/src/getThreadHistory.js +45 -0
- package/src/getThreadHistoryDeprecated.js +71 -0
- package/src/getThreadInfo.js +73 -0
- package/src/getThreadInfoDeprecated.js +56 -0
- package/src/getThreadList.js +76 -0
- package/src/getThreadListDeprecated.js +46 -0
- package/src/getThreadPictures.js +59 -0
- package/src/getThreadTheme.js +77 -0
- package/src/getUID.js +17 -0
- package/src/getUserID.js +17 -0
- package/src/getUserInfo.js +28 -0
- package/src/handleFriendRequest.js +21 -0
- package/src/handleMessageRequest.js +15 -0
- package/src/httpGet.js +13 -0
- package/src/httpPost.js +12 -0
- package/src/httpPostFormData.js +12 -0
- package/src/listenE2EE.js +75 -0
- package/src/listenMqtt.js +802 -0
- package/src/listenNotification.js +85 -0
- package/src/logout.js +22 -0
- package/src/markAsDelivered.js +17 -0
- package/src/markAsRead.js +14 -0
- package/src/markAsReadAll.js +15 -0
- package/src/markAsSeen.js +15 -0
- package/src/metaTheme.js +185 -0
- package/src/muteThread.js +52 -0
- package/src/note.js +228 -0
- package/src/pin.js +53 -0
- package/src/pinMessage.js +6 -0
- package/src/postComment.js +29 -0
- package/src/postFormData.js +46 -0
- package/src/reactToComment.js +31 -0
- package/src/reactToPost.js +32 -0
- package/src/refreshFb_dtsg.js +31 -0
- package/src/removeSuspiciousAccount.js +74 -0
- package/src/removeUserFromGroup.js +15 -0
- package/src/reply.js +442 -0
- package/src/resolvePhotoUrl.js +15 -0
- package/src/searchForThread.js +20 -0
- package/src/searchFriends.js +28 -0
- package/src/searchStickers.js +53 -0
- package/src/send.js +46 -0
- package/src/sendAudio.js +8 -0
- package/src/sendBroadcast.js +93 -0
- package/src/sendButtons.js +161 -0
- package/src/sendComment.js +159 -0
- package/src/sendEmoji.js +10 -0
- package/src/sendFile.js +9 -0
- package/src/sendFriendRequest.js +33 -0
- package/src/sendGif.js +24 -0
- package/src/sendImage.js +9 -0
- package/src/sendLocation.js +9 -0
- package/src/sendMessage.js +487 -0
- package/src/sendMessage1.js +309 -0
- package/src/sendMessageMqtt.js +68 -0
- package/src/sendSticker.js +8 -0
- package/src/sendTypingIndicator.js +36 -0
- package/src/sendTypingIndicatorV2.js +28 -0
- package/src/sendVideo.js +9 -0
- package/src/sessionGuard.js +130 -0
- package/src/setActiveStatus.js +16 -0
- package/src/setMessageReaction.js +61 -0
- package/src/setMessageReactionMqtt.js +62 -0
- package/src/setOptions.js +22 -0
- package/src/setPollVote.js +17 -0
- package/src/setPostReaction.js +112 -0
- package/src/setProfileGuard.js +44 -0
- package/src/setProfileLock.js +93 -0
- package/src/setStoryReaction.js +129 -0
- package/src/setStorySeen.js +99 -0
- package/src/setThreadTheme.js +17 -0
- package/src/setTitle.js +15 -0
- package/src/shareContact.js +33 -0
- package/src/shareLink.js +8 -0
- package/src/sharePost.js +31 -0
- package/src/stopListenMqtt.js +23 -0
- package/src/storyManager.js +353 -0
- package/src/suggestFriend.js +128 -0
- package/src/threadColors.js +131 -0
- package/src/unfollowUser.js +23 -0
- package/src/unfriend.js +15 -0
- package/src/unpinMessage.js +6 -0
- package/src/unsendMessage.js +14 -0
- package/src/uploadAttachment.js +58 -0
- package/src/uploadImageToImgbb.js +29 -0
- package/utils.js +2945 -0
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* SHADOWX E2EE Crypto — All primitives using Node.js built-in crypto only.
|
|
5
|
+
* Implements: X25519 DH, HKDF-SHA256, AES-256-GCM, HMAC-SHA256
|
|
6
|
+
* Node.js >= 15 required (crypto.hkdfSync, crypto.generateKeyPairSync x25519).
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
const crypto = require("crypto");
|
|
10
|
+
|
|
11
|
+
// ─────────────────────────────────────────────────────────
|
|
12
|
+
// X25519 Key Management
|
|
13
|
+
// ─────────────────────────────────────────────────────────
|
|
14
|
+
|
|
15
|
+
function generateKeyPair() {
|
|
16
|
+
const { privateKey, publicKey } = crypto.generateKeyPairSync("x25519", {
|
|
17
|
+
privateKeyEncoding: { type: "pkcs8", format: "der" },
|
|
18
|
+
publicKeyEncoding: { type: "spki", format: "der" }
|
|
19
|
+
});
|
|
20
|
+
return {
|
|
21
|
+
privateKey,
|
|
22
|
+
publicKey,
|
|
23
|
+
publicKeyRaw: exportRawPublicKey(publicKey)
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function exportRawPublicKey(spkiDer) {
|
|
28
|
+
// X25519 SPKI DER: 12 bytes header + 32 bytes key
|
|
29
|
+
return Buffer.from(spkiDer).slice(-32);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function importPublicKey(raw32bytes) {
|
|
33
|
+
if (raw32bytes.length !== 32) throw new Error("X25519 public key must be 32 bytes");
|
|
34
|
+
// Build minimal SPKI wrapper for X25519
|
|
35
|
+
const header = Buffer.from("302a300506032b656e032100", "hex");
|
|
36
|
+
return Buffer.concat([header, raw32bytes]);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function dh(privateKeyPkcs8Der, peerPublicRaw32) {
|
|
40
|
+
const privKey = crypto.createPrivateKey({ key: Buffer.from(privateKeyPkcs8Der), format: "der", type: "pkcs8" });
|
|
41
|
+
const pubKeyDer = importPublicKey(Buffer.from(peerPublicRaw32));
|
|
42
|
+
const pubKey = crypto.createPublicKey({ key: pubKeyDer, format: "der", type: "spki" });
|
|
43
|
+
return crypto.diffieHellman({ privateKey: privKey, publicKey: pubKey });
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// ─────────────────────────────────────────────────────────
|
|
47
|
+
// HKDF-SHA256
|
|
48
|
+
// ─────────────────────────────────────────────────────────
|
|
49
|
+
|
|
50
|
+
function hkdf(ikm, length, salt, info) {
|
|
51
|
+
if (!salt) salt = Buffer.alloc(32, 0);
|
|
52
|
+
if (!info) info = Buffer.alloc(0);
|
|
53
|
+
if (typeof info === "string") info = Buffer.from(info, "utf8");
|
|
54
|
+
return Buffer.from(crypto.hkdfSync("sha256", ikm, salt, info, length));
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function hkdfExtract(salt, ikm) {
|
|
58
|
+
return crypto.createHmac("sha256", salt).update(ikm).digest();
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function hkdfExpand(prk, info, length) {
|
|
62
|
+
const results = [];
|
|
63
|
+
let t = Buffer.alloc(0);
|
|
64
|
+
let i = 0;
|
|
65
|
+
while (results.reduce((s, b) => s + b.length, 0) < length) {
|
|
66
|
+
i++;
|
|
67
|
+
const hmac = crypto.createHmac("sha256", prk);
|
|
68
|
+
hmac.update(t);
|
|
69
|
+
if (info) hmac.update(info);
|
|
70
|
+
hmac.update(Buffer.from([i]));
|
|
71
|
+
t = hmac.digest();
|
|
72
|
+
results.push(t);
|
|
73
|
+
}
|
|
74
|
+
return Buffer.concat(results).slice(0, length);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// ─────────────────────────────────────────────────────────
|
|
78
|
+
// AES-256-GCM
|
|
79
|
+
// ─────────────────────────────────────────────────────────
|
|
80
|
+
|
|
81
|
+
function encrypt(key32, plaintext, aad) {
|
|
82
|
+
if (key32.length !== 32) throw new Error("AES-GCM key must be 32 bytes");
|
|
83
|
+
const iv = crypto.randomBytes(12);
|
|
84
|
+
const cipher = crypto.createCipheriv("aes-256-gcm", key32, iv);
|
|
85
|
+
if (aad) cipher.setAAD(aad);
|
|
86
|
+
const encrypted = Buffer.concat([cipher.update(plaintext), cipher.final()]);
|
|
87
|
+
const authTag = cipher.getAuthTag();
|
|
88
|
+
return Buffer.concat([iv, authTag, encrypted]);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
function decrypt(key32, ciphertext, aad) {
|
|
92
|
+
if (key32.length !== 32) throw new Error("AES-GCM key must be 32 bytes");
|
|
93
|
+
if (ciphertext.length < 28) throw new Error("Ciphertext too short");
|
|
94
|
+
const iv = ciphertext.slice(0, 12);
|
|
95
|
+
const authTag = ciphertext.slice(12, 28);
|
|
96
|
+
const data = ciphertext.slice(28);
|
|
97
|
+
const decipher = crypto.createDecipheriv("aes-256-gcm", key32, iv);
|
|
98
|
+
decipher.setAuthTag(authTag);
|
|
99
|
+
if (aad) decipher.setAAD(aad);
|
|
100
|
+
return Buffer.concat([decipher.update(data), decipher.final()]);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// ─────────────────────────────────────────────────────────
|
|
104
|
+
// HMAC-SHA256
|
|
105
|
+
// ─────────────────────────────────────────────────────────
|
|
106
|
+
|
|
107
|
+
function hmacSha256(key, data) {
|
|
108
|
+
return crypto.createHmac("sha256", key).update(data).digest();
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
function constantTimeEqual(a, b) {
|
|
112
|
+
if (a.length !== b.length) return false;
|
|
113
|
+
return crypto.timingSafeEqual(a, b);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// ─────────────────────────────────────────────────────────
|
|
117
|
+
// X3DH Key Agreement (Extended Triple Diffie-Hellman)
|
|
118
|
+
// ─────────────────────────────────────────────────────────
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Sender side of X3DH.
|
|
122
|
+
* @param {object} senderIdKey - { privateKey, publicKey, publicKeyRaw } of sender identity key
|
|
123
|
+
* @param {object} ephemeralKey - { privateKey, publicKey, publicKeyRaw } of ephemeral key
|
|
124
|
+
* @param {Buffer} recipientIdPub - recipient's identity public key (raw 32 bytes)
|
|
125
|
+
* @param {Buffer} recipientSpkPub - recipient's signed pre-key (raw 32 bytes)
|
|
126
|
+
* @param {Buffer} [recipientOpkPub] - recipient's one-time pre-key (raw 32 bytes), optional
|
|
127
|
+
* @returns {Buffer} 32-byte shared master secret
|
|
128
|
+
*/
|
|
129
|
+
function x3dhSend(senderIdKey, ephemeralKey, recipientIdPub, recipientSpkPub, recipientOpkPub) {
|
|
130
|
+
const dh1 = dh(senderIdKey.privateKey, recipientSpkPub);
|
|
131
|
+
const dh2 = dh(ephemeralKey.privateKey, recipientIdPub);
|
|
132
|
+
const dh3 = dh(ephemeralKey.privateKey, recipientSpkPub);
|
|
133
|
+
const parts = recipientOpkPub
|
|
134
|
+
? [dh1, dh2, dh3, dh(ephemeralKey.privateKey, recipientOpkPub)]
|
|
135
|
+
: [dh1, dh2, dh3];
|
|
136
|
+
const ikm = Buffer.concat(parts);
|
|
137
|
+
const F = Buffer.alloc(32, 0xFF);
|
|
138
|
+
const salt = Buffer.alloc(32, 0);
|
|
139
|
+
return hkdf(Buffer.concat([F, ikm]), 32, salt, Buffer.from("WhisperText", "utf8"));
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* Receiver side of X3DH.
|
|
144
|
+
*/
|
|
145
|
+
function x3dhReceive(recipientIdKey, recipientSpkKey, recipientOpkKey, senderIdPub, senderEphemeralPub) {
|
|
146
|
+
const dh1 = dh(recipientSpkKey.privateKey, senderIdPub);
|
|
147
|
+
const dh2 = dh(recipientIdKey.privateKey, senderEphemeralPub);
|
|
148
|
+
const dh3 = dh(recipientSpkKey.privateKey, senderEphemeralPub);
|
|
149
|
+
const parts = recipientOpkKey
|
|
150
|
+
? [dh1, dh2, dh3, dh(recipientOpkKey.privateKey, senderEphemeralPub)]
|
|
151
|
+
: [dh1, dh2, dh3];
|
|
152
|
+
const ikm = Buffer.concat(parts);
|
|
153
|
+
const F = Buffer.alloc(32, 0xFF);
|
|
154
|
+
const salt = Buffer.alloc(32, 0);
|
|
155
|
+
return hkdf(Buffer.concat([F, ikm]), 32, salt, Buffer.from("WhisperText", "utf8"));
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
module.exports = {
|
|
159
|
+
generateKeyPair,
|
|
160
|
+
exportRawPublicKey,
|
|
161
|
+
importPublicKey,
|
|
162
|
+
dh,
|
|
163
|
+
hkdf,
|
|
164
|
+
hkdfExtract,
|
|
165
|
+
hkdfExpand,
|
|
166
|
+
encrypt,
|
|
167
|
+
decrypt,
|
|
168
|
+
hmacSha256,
|
|
169
|
+
constantTimeEqual,
|
|
170
|
+
x3dhSend,
|
|
171
|
+
x3dhReceive,
|
|
172
|
+
randomBytes: crypto.randomBytes.bind(crypto)
|
|
173
|
+
};
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* SHADOWX E2EE Bridge — delegates to root e2ee.js (lib/index.mjs + messagix.so)
|
|
5
|
+
*
|
|
6
|
+
* The original vendor/fb-e2ee.cjs path is replaced by the root-level e2ee.js
|
|
7
|
+
* which uses the bundled messagix native binary via lib/index.mjs.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
const path = require("path");
|
|
11
|
+
const logger = require("../../logger");
|
|
12
|
+
|
|
13
|
+
// Root e2ee.js — contains createBridge + patchApiForE2EE
|
|
14
|
+
const rootE2EE = require("../../e2ee");
|
|
15
|
+
|
|
16
|
+
class E2EEBridge {
|
|
17
|
+
constructor(ctx, api, defaultFuncs) {
|
|
18
|
+
this.ctx = ctx;
|
|
19
|
+
this.api = api;
|
|
20
|
+
this.defaultFuncs = defaultFuncs || null;
|
|
21
|
+
this.connected = false;
|
|
22
|
+
this._bridge = null;
|
|
23
|
+
this._messageCallback = null;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
27
|
+
// Setup
|
|
28
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
29
|
+
|
|
30
|
+
async connect(deviceStorePath, userId) {
|
|
31
|
+
const fs = require("fs");
|
|
32
|
+
|
|
33
|
+
userId = userId || this.ctx.userID;
|
|
34
|
+
|
|
35
|
+
// Mirror the device-store path logic from the original bridge
|
|
36
|
+
if (!deviceStorePath) {
|
|
37
|
+
deviceStorePath = path.join(process.cwd(), ".shadowx-fca", "e2ee_device.json");
|
|
38
|
+
}
|
|
39
|
+
try { fs.mkdirSync(path.dirname(deviceStorePath), { recursive: true }); } catch (_) {}
|
|
40
|
+
|
|
41
|
+
logger.info("E2EE", "Device store: " + deviceStorePath);
|
|
42
|
+
|
|
43
|
+
// Propagate options into ctx.globalOptions so createBridge picks them up
|
|
44
|
+
const opts = this.ctx.globalOptions || {};
|
|
45
|
+
opts.enableE2EE = true;
|
|
46
|
+
opts.e2eeMemoryOnly = opts.e2eeMemoryOnly !== false;
|
|
47
|
+
opts.e2eeDevicePath = opts.e2eeDevicePath || deviceStorePath;
|
|
48
|
+
this.ctx.globalOptions = opts;
|
|
49
|
+
|
|
50
|
+
// Patch the api object with E2EE helpers (sendMessage routing etc.)
|
|
51
|
+
rootE2EE.patchApiForE2EE(this.api, this.ctx);
|
|
52
|
+
|
|
53
|
+
// Obtain the bridge singleton for this ctx
|
|
54
|
+
this._bridge = rootE2EE.createBridge(this.ctx);
|
|
55
|
+
|
|
56
|
+
logger.info("E2EE", "Bootstrapping E2EE via lib/index.mjs + messagix native binary...");
|
|
57
|
+
|
|
58
|
+
// connect() returns the native Client; pass a callback to capture events
|
|
59
|
+
await this._bridge.connect((err, event) => {
|
|
60
|
+
if (err) {
|
|
61
|
+
logger.error("E2EE", "E2EE event error: " + (err && err.message ? err.message : String(err)));
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
if (!event) return;
|
|
65
|
+
|
|
66
|
+
// Forward e2eeMessage events to the registered callback
|
|
67
|
+
if (event.type === "e2ee_message" && this._messageCallback) {
|
|
68
|
+
this._messageCallback(null, event);
|
|
69
|
+
}
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
this.connected = true;
|
|
73
|
+
logger.success("E2EE", "E2EE active — lib/index.mjs + messagix (Signal Protocol / Noise WebSocket)");
|
|
74
|
+
return this;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
ensureConnected() {
|
|
78
|
+
if (!this.connected || !this._bridge) {
|
|
79
|
+
throw new Error("E2EE not connected. Call api.connectE2EE() first.");
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
isConnected() {
|
|
84
|
+
return this.connected && !!(this._bridge && this._bridge.isConnected());
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
88
|
+
// Send API
|
|
89
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
90
|
+
|
|
91
|
+
async sendMessage(threadId, msg, replyToMessageId) {
|
|
92
|
+
this.ensureConnected();
|
|
93
|
+
return this._bridge.sendMessage(threadId, msg, replyToMessageId);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
async sendReaction(threadId, messageId, reaction, senderJid) {
|
|
97
|
+
this.ensureConnected();
|
|
98
|
+
return this._bridge.sendReaction(threadId, messageId, reaction, senderJid);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
async sendTyping(threadId, isTyping) {
|
|
102
|
+
this.ensureConnected();
|
|
103
|
+
return this._bridge.sendTyping(threadId, isTyping);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
async unsendMessage(messageId, threadId) {
|
|
107
|
+
this.ensureConnected();
|
|
108
|
+
return this._bridge.unsendMessage(messageId, threadId);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
async editMessage(threadId, messageId, newText) {
|
|
112
|
+
this.ensureConnected();
|
|
113
|
+
return this._bridge.editMessage(threadId, messageId, newText);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
117
|
+
// Receive API
|
|
118
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
119
|
+
|
|
120
|
+
onMessage(callback) {
|
|
121
|
+
this._messageCallback = callback;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
125
|
+
// Info / lifecycle
|
|
126
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
127
|
+
|
|
128
|
+
getPublicKeys() {
|
|
129
|
+
return {
|
|
130
|
+
info: "Keys managed by lib/index.mjs + messagix native E2EE engine.",
|
|
131
|
+
note: "Device keys are stored in the device-store file. Do NOT delete it.",
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
async disconnect() {
|
|
136
|
+
if (this._bridge) {
|
|
137
|
+
try { await this._bridge.disconnect(); } catch (_) {}
|
|
138
|
+
}
|
|
139
|
+
this.connected = false;
|
|
140
|
+
logger.info("E2EE", "E2EE disconnected.");
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
module.exports = { E2EEBridge };
|
|
@@ -0,0 +1,281 @@
|
|
|
1
|
+
syntax = "proto2";
|
|
2
|
+
package waArmadilloApplication;
|
|
3
|
+
|
|
4
|
+
import "WACommon.proto";
|
|
5
|
+
|
|
6
|
+
message Armadillo {
|
|
7
|
+
message Metadata {
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
message Payload {
|
|
11
|
+
oneof payload {
|
|
12
|
+
Content content = 1;
|
|
13
|
+
ApplicationData applicationData = 2;
|
|
14
|
+
Signal signal = 3;
|
|
15
|
+
SubProtocolPayload subProtocol = 4;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
message SubProtocolPayload {
|
|
20
|
+
optional WACommon.FutureProofBehavior futureProof = 1;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
message Signal {
|
|
24
|
+
message EncryptedBackupsSecrets {
|
|
25
|
+
message Epoch {
|
|
26
|
+
enum EpochStatus {
|
|
27
|
+
ES_OPEN = 1;
|
|
28
|
+
ES_CLOSE = 2;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
optional uint64 ID = 1;
|
|
32
|
+
optional bytes anonID = 2;
|
|
33
|
+
optional bytes rootKey = 3;
|
|
34
|
+
optional EpochStatus status = 4;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
optional uint64 backupID = 1;
|
|
38
|
+
optional uint64 serverDataID = 2;
|
|
39
|
+
repeated Epoch epoch = 3;
|
|
40
|
+
optional bytes tempOcmfClientState = 4;
|
|
41
|
+
optional bytes mailboxRootKey = 5;
|
|
42
|
+
optional bytes obliviousValidationToken = 6;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
oneof signal {
|
|
46
|
+
EncryptedBackupsSecrets encryptedBackupsSecrets = 1;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
message ApplicationData {
|
|
51
|
+
message MessageHistoryDocumentMessage {
|
|
52
|
+
optional WACommon.SubProtocol document = 1;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
message AIBotResponseMessage {
|
|
56
|
+
optional string summonToken = 1;
|
|
57
|
+
optional string messageText = 2;
|
|
58
|
+
optional string serializedExtras = 3;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
message MetadataSyncAction {
|
|
62
|
+
message SyncAttachmentInterventionAction {
|
|
63
|
+
enum InterventionType {
|
|
64
|
+
UNKNOWN = 0;
|
|
65
|
+
NUDE = 1;
|
|
66
|
+
NOT_NUDE = 2;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
optional WACommon.MessageKey messageKey = 1;
|
|
70
|
+
optional InterventionType interventionType = 2;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
message SyncSpectraAction {
|
|
74
|
+
enum SpectraActionType {
|
|
75
|
+
TAKEDOWN = 0;
|
|
76
|
+
RESTORE = 1;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
optional WACommon.MessageKey key = 1;
|
|
80
|
+
optional SpectraActionType actionType = 2;
|
|
81
|
+
optional int64 takedownActionID = 3;
|
|
82
|
+
optional string config = 4;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
message SyncMessageAction {
|
|
86
|
+
message ActionMessageDelete {
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
oneof action {
|
|
90
|
+
ActionMessageDelete messageDelete = 101;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
optional WACommon.MessageKey key = 1;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
message SyncChatAction {
|
|
97
|
+
message ActionChatRead {
|
|
98
|
+
optional SyncActionMessageRange messageRange = 1;
|
|
99
|
+
optional bool read = 2;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
message ActionChatDelete {
|
|
103
|
+
optional SyncActionMessageRange messageRange = 1;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
message ActionChatArchive {
|
|
107
|
+
optional SyncActionMessageRange messageRange = 1;
|
|
108
|
+
optional bool archived = 2;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
oneof action {
|
|
112
|
+
ActionChatArchive chatArchive = 101;
|
|
113
|
+
ActionChatDelete chatDelete = 102;
|
|
114
|
+
ActionChatRead chatRead = 103;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
optional string chatID = 1;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
message SyncActionMessage {
|
|
121
|
+
optional WACommon.MessageKey key = 1;
|
|
122
|
+
optional int64 timestamp = 2;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
message SyncActionMessageRange {
|
|
126
|
+
optional int64 lastMessageTimestamp = 1;
|
|
127
|
+
optional int64 lastSystemMessageTimestamp = 2;
|
|
128
|
+
repeated SyncActionMessage messages = 3;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
oneof actionType {
|
|
132
|
+
SyncChatAction chatAction = 101;
|
|
133
|
+
SyncMessageAction messageAction = 102;
|
|
134
|
+
SyncSpectraAction spectraAction = 103;
|
|
135
|
+
SyncAttachmentInterventionAction attachmentInterventionAction = 104;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
optional int64 actionTimestamp = 1;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
message MetadataSyncNotification {
|
|
142
|
+
repeated MetadataSyncAction actions = 2;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
oneof applicationData {
|
|
146
|
+
MetadataSyncNotification metadataSync = 1;
|
|
147
|
+
AIBotResponseMessage aiBotResponse = 2;
|
|
148
|
+
MessageHistoryDocumentMessage messageHistoryDocumentMessage = 3;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
message Content {
|
|
153
|
+
message PaymentsTransactionMessage {
|
|
154
|
+
enum PaymentStatus {
|
|
155
|
+
PAYMENT_UNKNOWN = 0;
|
|
156
|
+
REQUEST_INITED = 4;
|
|
157
|
+
REQUEST_DECLINED = 5;
|
|
158
|
+
REQUEST_TRANSFER_INITED = 6;
|
|
159
|
+
REQUEST_TRANSFER_COMPLETED = 7;
|
|
160
|
+
REQUEST_TRANSFER_FAILED = 8;
|
|
161
|
+
REQUEST_CANCELED = 9;
|
|
162
|
+
REQUEST_EXPIRED = 10;
|
|
163
|
+
TRANSFER_INITED = 11;
|
|
164
|
+
TRANSFER_PENDING = 12;
|
|
165
|
+
TRANSFER_PENDING_RECIPIENT_VERIFICATION = 13;
|
|
166
|
+
TRANSFER_CANCELED = 14;
|
|
167
|
+
TRANSFER_COMPLETED = 15;
|
|
168
|
+
TRANSFER_NO_RECEIVER_CREDENTIAL_NO_RTS_PENDING_CANCELED = 16;
|
|
169
|
+
TRANSFER_NO_RECEIVER_CREDENTIAL_NO_RTS_PENDING_OTHER = 17;
|
|
170
|
+
TRANSFER_REFUNDED = 18;
|
|
171
|
+
TRANSFER_PARTIAL_REFUND = 19;
|
|
172
|
+
TRANSFER_CHARGED_BACK = 20;
|
|
173
|
+
TRANSFER_EXPIRED = 21;
|
|
174
|
+
TRANSFER_DECLINED = 22;
|
|
175
|
+
TRANSFER_UNAVAILABLE = 23;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
optional uint64 transactionID = 1;
|
|
179
|
+
optional string amount = 2;
|
|
180
|
+
optional string currency = 3;
|
|
181
|
+
optional PaymentStatus paymentStatus = 4;
|
|
182
|
+
// optional waArmadilloXMA.ExtendedContentMessage extendedContentMessage = 5;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
message NetworkVerificationMessage {
|
|
186
|
+
optional string codeText = 1;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
message NoteReplyMessage {
|
|
190
|
+
oneof noteReplyContent {
|
|
191
|
+
WACommon.MessageText textContent = 4;
|
|
192
|
+
WACommon.SubProtocol stickerContent = 5;
|
|
193
|
+
WACommon.SubProtocol videoContent = 6;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
optional string noteID = 1;
|
|
197
|
+
optional WACommon.MessageText noteText = 2;
|
|
198
|
+
optional int64 noteTimestampMS = 3;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
message BumpExistingMessage {
|
|
202
|
+
optional WACommon.MessageKey key = 1;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
message ImageGalleryMessage {
|
|
206
|
+
repeated WACommon.SubProtocol images = 1;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
message ScreenshotAction {
|
|
210
|
+
enum ScreenshotType {
|
|
211
|
+
SCREENSHOT_IMAGE = 1;
|
|
212
|
+
SCREEN_RECORDING = 2;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
optional ScreenshotType screenshotType = 1;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
message ExtendedContentMessageWithSear {
|
|
219
|
+
optional string searID = 1;
|
|
220
|
+
optional bytes payload = 2;
|
|
221
|
+
optional string nativeURL = 3;
|
|
222
|
+
optional WACommon.SubProtocol searAssociatedMessage = 4;
|
|
223
|
+
optional string searSentWithMessageID = 5;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
message RavenActionNotifMessage {
|
|
227
|
+
enum ActionType {
|
|
228
|
+
PLAYED = 0;
|
|
229
|
+
SCREENSHOT = 1;
|
|
230
|
+
FORCE_DISABLE = 2;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
optional WACommon.MessageKey key = 1;
|
|
234
|
+
optional int64 actionTimestamp = 2;
|
|
235
|
+
optional ActionType actionType = 3;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
message RavenMessage {
|
|
239
|
+
enum EphemeralType {
|
|
240
|
+
VIEW_ONCE = 0;
|
|
241
|
+
ALLOW_REPLAY = 1;
|
|
242
|
+
KEEP_IN_CHAT = 2;
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
oneof mediaContent {
|
|
246
|
+
WACommon.SubProtocol imageMessage = 2;
|
|
247
|
+
WACommon.SubProtocol videoMessage = 3;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
optional EphemeralType ephemeralType = 1;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
message CommonSticker {
|
|
254
|
+
enum StickerType {
|
|
255
|
+
SMALL_LIKE = 1;
|
|
256
|
+
MEDIUM_LIKE = 2;
|
|
257
|
+
LARGE_LIKE = 3;
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
optional StickerType stickerType = 1;
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
oneof content {
|
|
264
|
+
CommonSticker commonSticker = 1;
|
|
265
|
+
ScreenshotAction screenshotAction = 3;
|
|
266
|
+
// waArmadilloXMA.ExtendedContentMessage extendedContentMessage = 4;
|
|
267
|
+
RavenMessage ravenMessage = 5;
|
|
268
|
+
RavenActionNotifMessage ravenActionNotifMessage = 6;
|
|
269
|
+
ExtendedContentMessageWithSear extendedMessageContentWithSear = 7;
|
|
270
|
+
ImageGalleryMessage imageGalleryMessage = 8;
|
|
271
|
+
PaymentsTransactionMessage paymentsTransactionMessage = 10;
|
|
272
|
+
BumpExistingMessage bumpExistingMessage = 11;
|
|
273
|
+
NoteReplyMessage noteReplyMessage = 13;
|
|
274
|
+
RavenMessage ravenMessageMsgr = 14;
|
|
275
|
+
NetworkVerificationMessage networkVerificationMessage = 15;
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
optional Payload payload = 1;
|
|
280
|
+
optional Metadata metadata = 2;
|
|
281
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
syntax = "proto2";
|
|
2
|
+
package waArmadilloICDC;
|
|
3
|
+
|
|
4
|
+
message ICDCIdentityList {
|
|
5
|
+
optional int32 seq = 1;
|
|
6
|
+
optional int64 timestamp = 2;
|
|
7
|
+
repeated bytes devices = 3;
|
|
8
|
+
optional int32 signingDeviceIndex = 4;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
message SignedICDCIdentityList {
|
|
12
|
+
optional bytes details = 1;
|
|
13
|
+
optional bytes signature = 2;
|
|
14
|
+
}
|