fb-messenger-e2ee 0.1.4 → 0.1.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/DOCS.md +2 -2
- package/README.md +2 -2
- package/dist/index.cjs +78 -27
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +44 -13
- package/dist/index.d.ts +44 -13
- package/dist/index.js +78 -27
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -225,6 +225,13 @@ interface SendMessageInput {
|
|
|
225
225
|
threadId: string;
|
|
226
226
|
text: string;
|
|
227
227
|
replyToMessageId?: string;
|
|
228
|
+
/**
|
|
229
|
+
* JID of the original message sender for E2EE reply (QuotedMessage.participant field).
|
|
230
|
+
* - For DM: the bare JID of the peer (e.g. "123456789.0@msgr"); if omitted, defaults to the peer's JID.
|
|
231
|
+
* - For group: the full member JID who sent the original message (e.g. "123456789.160@msgr"); required
|
|
232
|
+
* for the server to correctly thread the reply in the group conversation.
|
|
233
|
+
*/
|
|
234
|
+
replyToSenderJid?: string;
|
|
228
235
|
}
|
|
229
236
|
interface SendMediaInput {
|
|
230
237
|
threadId: string;
|
|
@@ -234,6 +241,11 @@ interface SendMediaInput {
|
|
|
234
241
|
mimeType?: string;
|
|
235
242
|
caption?: string;
|
|
236
243
|
replyToMessageId?: string;
|
|
244
|
+
/**
|
|
245
|
+
* JID of the original message sender for E2EE reply (QuotedMessage.participant field).
|
|
246
|
+
* See SendMessageInput.replyToSenderJid for details.
|
|
247
|
+
*/
|
|
248
|
+
replyToSenderJid?: string;
|
|
237
249
|
/** Optional media width in pixels for E2EE image/video/sticker payloads. */
|
|
238
250
|
width?: number;
|
|
239
251
|
/** Optional media height in pixels for E2EE image/video/sticker payloads. */
|
|
@@ -749,6 +761,38 @@ declare class DeviceStore implements IdentityKeyStore, SessionStore, PreKeyStore
|
|
|
749
761
|
getPreKeyCount(): number;
|
|
750
762
|
}
|
|
751
763
|
|
|
764
|
+
/**
|
|
765
|
+
* Reply-to (quoted message) metadata for MessageApplication.Metadata.QuotedMessage.
|
|
766
|
+
*
|
|
767
|
+
* Proto schema (WAMsgApplication.proto):
|
|
768
|
+
* message QuotedMessage {
|
|
769
|
+
* optional string stanzaID = 1; // message ID of the quoted message
|
|
770
|
+
* optional string remoteJID = 2; // chat JID (thread) that contains the quoted message
|
|
771
|
+
* optional string participant = 3; // sender JID of the quoted message (required for groups)
|
|
772
|
+
* }
|
|
773
|
+
*/
|
|
774
|
+
interface ReplyToMeta {
|
|
775
|
+
/** Message ID (stanzaID) of the quoted message. */
|
|
776
|
+
messageId: string;
|
|
777
|
+
/** Chat JID (remoteJID) — the thread where the quoted message lives. */
|
|
778
|
+
chatJid: string;
|
|
779
|
+
/**
|
|
780
|
+
* Sender JID (participant) of the quoted message.
|
|
781
|
+
* - For DM: same as chatJid (the peer's bare JID).
|
|
782
|
+
* - For group: the specific member JID who sent the original message.
|
|
783
|
+
*/
|
|
784
|
+
senderJid: string;
|
|
785
|
+
}
|
|
786
|
+
/**
|
|
787
|
+
* Wrap a ConsumerApplication payload into a MessageApplication.
|
|
788
|
+
* Returns (messageApp bytes, frankingKey, frankingTag).
|
|
789
|
+
*/
|
|
790
|
+
declare function encodeMessageApplication(consumerAppBytes: Buffer, replyTo?: ReplyToMeta): {
|
|
791
|
+
messageApp: Buffer;
|
|
792
|
+
frankingKey: Buffer;
|
|
793
|
+
frankingTag: Buffer;
|
|
794
|
+
};
|
|
795
|
+
|
|
752
796
|
/**
|
|
753
797
|
* Encode a ConsumerApplication text message.
|
|
754
798
|
* Field 1 = Payload { field 1 = Content { field 1 = MessageText { field 1 = text } } }
|
|
@@ -779,19 +823,6 @@ declare function encodeEditMessage(targetMessageId: string, newText: string): Bu
|
|
|
779
823
|
/** Encode a revoke (unsend) message. */
|
|
780
824
|
declare function encodeRevokeMessage(messageId: string, keyOptsOrFromMe?: MessageKeyOptions | boolean): Buffer;
|
|
781
825
|
|
|
782
|
-
/**
|
|
783
|
-
* Wrap a ConsumerApplication payload into a MessageApplication.
|
|
784
|
-
* Returns (messageApp bytes, frankingKey, frankingTag).
|
|
785
|
-
*/
|
|
786
|
-
declare function encodeMessageApplication(consumerAppBytes: Buffer, replyTo?: {
|
|
787
|
-
id: string;
|
|
788
|
-
senderJid: string;
|
|
789
|
-
}): {
|
|
790
|
-
messageApp: Buffer;
|
|
791
|
-
frankingKey: Buffer;
|
|
792
|
-
frankingTag: Buffer;
|
|
793
|
-
};
|
|
794
|
-
|
|
795
826
|
/**
|
|
796
827
|
* Encode the MessageTransport protobuf that will be fed into Signal cipher.
|
|
797
828
|
*/
|
package/dist/index.d.ts
CHANGED
|
@@ -225,6 +225,13 @@ interface SendMessageInput {
|
|
|
225
225
|
threadId: string;
|
|
226
226
|
text: string;
|
|
227
227
|
replyToMessageId?: string;
|
|
228
|
+
/**
|
|
229
|
+
* JID of the original message sender for E2EE reply (QuotedMessage.participant field).
|
|
230
|
+
* - For DM: the bare JID of the peer (e.g. "123456789.0@msgr"); if omitted, defaults to the peer's JID.
|
|
231
|
+
* - For group: the full member JID who sent the original message (e.g. "123456789.160@msgr"); required
|
|
232
|
+
* for the server to correctly thread the reply in the group conversation.
|
|
233
|
+
*/
|
|
234
|
+
replyToSenderJid?: string;
|
|
228
235
|
}
|
|
229
236
|
interface SendMediaInput {
|
|
230
237
|
threadId: string;
|
|
@@ -234,6 +241,11 @@ interface SendMediaInput {
|
|
|
234
241
|
mimeType?: string;
|
|
235
242
|
caption?: string;
|
|
236
243
|
replyToMessageId?: string;
|
|
244
|
+
/**
|
|
245
|
+
* JID of the original message sender for E2EE reply (QuotedMessage.participant field).
|
|
246
|
+
* See SendMessageInput.replyToSenderJid for details.
|
|
247
|
+
*/
|
|
248
|
+
replyToSenderJid?: string;
|
|
237
249
|
/** Optional media width in pixels for E2EE image/video/sticker payloads. */
|
|
238
250
|
width?: number;
|
|
239
251
|
/** Optional media height in pixels for E2EE image/video/sticker payloads. */
|
|
@@ -749,6 +761,38 @@ declare class DeviceStore implements IdentityKeyStore, SessionStore, PreKeyStore
|
|
|
749
761
|
getPreKeyCount(): number;
|
|
750
762
|
}
|
|
751
763
|
|
|
764
|
+
/**
|
|
765
|
+
* Reply-to (quoted message) metadata for MessageApplication.Metadata.QuotedMessage.
|
|
766
|
+
*
|
|
767
|
+
* Proto schema (WAMsgApplication.proto):
|
|
768
|
+
* message QuotedMessage {
|
|
769
|
+
* optional string stanzaID = 1; // message ID of the quoted message
|
|
770
|
+
* optional string remoteJID = 2; // chat JID (thread) that contains the quoted message
|
|
771
|
+
* optional string participant = 3; // sender JID of the quoted message (required for groups)
|
|
772
|
+
* }
|
|
773
|
+
*/
|
|
774
|
+
interface ReplyToMeta {
|
|
775
|
+
/** Message ID (stanzaID) of the quoted message. */
|
|
776
|
+
messageId: string;
|
|
777
|
+
/** Chat JID (remoteJID) — the thread where the quoted message lives. */
|
|
778
|
+
chatJid: string;
|
|
779
|
+
/**
|
|
780
|
+
* Sender JID (participant) of the quoted message.
|
|
781
|
+
* - For DM: same as chatJid (the peer's bare JID).
|
|
782
|
+
* - For group: the specific member JID who sent the original message.
|
|
783
|
+
*/
|
|
784
|
+
senderJid: string;
|
|
785
|
+
}
|
|
786
|
+
/**
|
|
787
|
+
* Wrap a ConsumerApplication payload into a MessageApplication.
|
|
788
|
+
* Returns (messageApp bytes, frankingKey, frankingTag).
|
|
789
|
+
*/
|
|
790
|
+
declare function encodeMessageApplication(consumerAppBytes: Buffer, replyTo?: ReplyToMeta): {
|
|
791
|
+
messageApp: Buffer;
|
|
792
|
+
frankingKey: Buffer;
|
|
793
|
+
frankingTag: Buffer;
|
|
794
|
+
};
|
|
795
|
+
|
|
752
796
|
/**
|
|
753
797
|
* Encode a ConsumerApplication text message.
|
|
754
798
|
* Field 1 = Payload { field 1 = Content { field 1 = MessageText { field 1 = text } } }
|
|
@@ -779,19 +823,6 @@ declare function encodeEditMessage(targetMessageId: string, newText: string): Bu
|
|
|
779
823
|
/** Encode a revoke (unsend) message. */
|
|
780
824
|
declare function encodeRevokeMessage(messageId: string, keyOptsOrFromMe?: MessageKeyOptions | boolean): Buffer;
|
|
781
825
|
|
|
782
|
-
/**
|
|
783
|
-
* Wrap a ConsumerApplication payload into a MessageApplication.
|
|
784
|
-
* Returns (messageApp bytes, frankingKey, frankingTag).
|
|
785
|
-
*/
|
|
786
|
-
declare function encodeMessageApplication(consumerAppBytes: Buffer, replyTo?: {
|
|
787
|
-
id: string;
|
|
788
|
-
senderJid: string;
|
|
789
|
-
}): {
|
|
790
|
-
messageApp: Buffer;
|
|
791
|
-
frankingKey: Buffer;
|
|
792
|
-
frankingTag: Buffer;
|
|
793
|
-
};
|
|
794
|
-
|
|
795
826
|
/**
|
|
796
827
|
* Encode the MessageTransport protobuf that will be fed into Signal cipher.
|
|
797
828
|
*/
|
package/dist/index.js
CHANGED
|
@@ -3969,8 +3969,8 @@ init_esm_shims();
|
|
|
3969
3969
|
var MessageBuilder = class {
|
|
3970
3970
|
content;
|
|
3971
3971
|
replyTo;
|
|
3972
|
-
setReply(
|
|
3973
|
-
this.replyTo =
|
|
3972
|
+
setReply(replyTo) {
|
|
3973
|
+
this.replyTo = replyTo;
|
|
3974
3974
|
return this;
|
|
3975
3975
|
}
|
|
3976
3976
|
getReply() {
|
|
@@ -4194,7 +4194,7 @@ function encodeMessageApplication(consumerAppBytes, replyTo) {
|
|
|
4194
4194
|
const appPayload = new ProtoWriter().bytes(4, payloadSubProto).build();
|
|
4195
4195
|
let metadataWriter = new ProtoWriter().bytes(8, frankingKey).varint(9, 0);
|
|
4196
4196
|
if (replyTo) {
|
|
4197
|
-
const quoted = new ProtoWriter().string(1, replyTo.
|
|
4197
|
+
const quoted = new ProtoWriter().string(1, replyTo.messageId).string(2, replyTo.chatJid).string(3, replyTo.senderJid).build();
|
|
4198
4198
|
metadataWriter = metadataWriter.bytes(10, quoted);
|
|
4199
4199
|
}
|
|
4200
4200
|
const metadata = metadataWriter.build();
|
|
@@ -5597,7 +5597,16 @@ var E2EEClient = class {
|
|
|
5597
5597
|
async buildDMTextFanoutPayloads(opts) {
|
|
5598
5598
|
const builder = new MessageBuilder().setText(opts.text);
|
|
5599
5599
|
if (opts.replyToId && opts.replyToSenderJid) {
|
|
5600
|
-
|
|
5600
|
+
const replyTo = {
|
|
5601
|
+
messageId: opts.replyToId,
|
|
5602
|
+
// chatJid = remoteJID: the thread/chat that holds the quoted message
|
|
5603
|
+
// For DM, this is the peer's bare JID (toJid).
|
|
5604
|
+
chatJid: opts.toJid,
|
|
5605
|
+
// senderJid = participant: who sent the original message.
|
|
5606
|
+
// Caller must supply the correct sender JID via replyToSenderJid.
|
|
5607
|
+
senderJid: opts.replyToSenderJid
|
|
5608
|
+
};
|
|
5609
|
+
builder.setReply(replyTo);
|
|
5601
5610
|
}
|
|
5602
5611
|
const consumerApp = builder.build();
|
|
5603
5612
|
const { messageApp, frankingTag } = encodeMessageApplication(consumerApp, builder.getReply());
|
|
@@ -5632,7 +5641,14 @@ var E2EEClient = class {
|
|
|
5632
5641
|
async encryptGroupText(groupJid, selfJid, text, messageId, replyToId, replyToSenderJid) {
|
|
5633
5642
|
const builder = new MessageBuilder().setText(text);
|
|
5634
5643
|
if (replyToId && replyToSenderJid) {
|
|
5635
|
-
|
|
5644
|
+
const replyTo = {
|
|
5645
|
+
messageId: replyToId,
|
|
5646
|
+
// chatJid = remoteJID: for a group message, this is the group JID
|
|
5647
|
+
chatJid: groupJid,
|
|
5648
|
+
// participant: the specific member who sent the original message
|
|
5649
|
+
senderJid: replyToSenderJid
|
|
5650
|
+
};
|
|
5651
|
+
builder.setReply(replyTo);
|
|
5636
5652
|
}
|
|
5637
5653
|
const consumerApp = builder.build();
|
|
5638
5654
|
const { messageApp, frankingTag } = encodeMessageApplication(consumerApp, builder.getReply());
|
|
@@ -5985,6 +6001,9 @@ var EncryptedFrameSocket = class {
|
|
|
5985
6001
|
const len = header.readUIntBE(0, 3);
|
|
5986
6002
|
logger.debug("FacebookE2EESocket", `RAW frame header: ${header.toString("hex")} (len=${len})`);
|
|
5987
6003
|
const payload = await this.ws.readRaw(len);
|
|
6004
|
+
if (!payload) {
|
|
6005
|
+
throw new Error("Socket closed while reading frame payload");
|
|
6006
|
+
}
|
|
5988
6007
|
try {
|
|
5989
6008
|
const decrypted = this.decryptFrame(payload);
|
|
5990
6009
|
logger.debug("FacebookE2EESocket", `Decrypt successful, result length: ${decrypted.length}`);
|
|
@@ -6124,11 +6143,12 @@ var FacebookE2EESocket = class extends EventEmitter2 {
|
|
|
6124
6143
|
url;
|
|
6125
6144
|
heartbeatInterval = null;
|
|
6126
6145
|
isConnected = false;
|
|
6146
|
+
cookieHeader = "";
|
|
6127
6147
|
constructor(endpoint) {
|
|
6128
6148
|
super();
|
|
6129
6149
|
this.url = endpoint;
|
|
6130
6150
|
}
|
|
6131
|
-
async connect(noisePrivKey, authPayload) {
|
|
6151
|
+
async connect(noisePrivKey, authPayload, cookies) {
|
|
6132
6152
|
return new Promise((resolve, reject) => {
|
|
6133
6153
|
try {
|
|
6134
6154
|
let readFromBuffer2 = function(len) {
|
|
@@ -6153,19 +6173,25 @@ var FacebookE2EESocket = class extends EventEmitter2 {
|
|
|
6153
6173
|
return res;
|
|
6154
6174
|
};
|
|
6155
6175
|
var readFromBuffer = readFromBuffer2;
|
|
6176
|
+
if (cookies) this.cookieHeader = cookies;
|
|
6156
6177
|
const wsUrl = new URL(this.url);
|
|
6157
6178
|
wsUrl.searchParams.set("cid", "client-" + Date.now());
|
|
6158
6179
|
const UserAgentStr = "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36";
|
|
6180
|
+
const wsHeaders = {
|
|
6181
|
+
"Origin": "https://www.facebook.com",
|
|
6182
|
+
"User-Agent": UserAgentStr
|
|
6183
|
+
};
|
|
6184
|
+
if (this.cookieHeader) {
|
|
6185
|
+
wsHeaders["Cookie"] = this.cookieHeader;
|
|
6186
|
+
}
|
|
6159
6187
|
this.ws = new WebSocket(wsUrl.toString(), void 0, {
|
|
6160
|
-
headers:
|
|
6161
|
-
"Origin": "https://www.facebook.com",
|
|
6162
|
-
"User-Agent": UserAgentStr
|
|
6163
|
-
}
|
|
6188
|
+
headers: wsHeaders
|
|
6164
6189
|
});
|
|
6165
6190
|
this.ws.binaryType = "arraybuffer";
|
|
6166
6191
|
let handshakeResolved = false;
|
|
6167
6192
|
let streamBuffer = [];
|
|
6168
6193
|
let streamLen = 0;
|
|
6194
|
+
let waitingRejectFn = null;
|
|
6169
6195
|
let waitingResolver = null;
|
|
6170
6196
|
let waitingLen = 0;
|
|
6171
6197
|
this.ws.addEventListener("message", (ev) => {
|
|
@@ -6190,8 +6216,9 @@ var FacebookE2EESocket = class extends EventEmitter2 {
|
|
|
6190
6216
|
const targetLen = len || 0;
|
|
6191
6217
|
if (targetLen === 0) {
|
|
6192
6218
|
if (streamLen > 0) return Promise.resolve(readFromBuffer2(streamLen));
|
|
6193
|
-
return new Promise((resolve2) => {
|
|
6219
|
+
return new Promise((resolve2, reject2) => {
|
|
6194
6220
|
waitingLen = 1;
|
|
6221
|
+
waitingRejectFn = reject2;
|
|
6195
6222
|
waitingResolver = () => resolve2(readFromBuffer2(streamLen));
|
|
6196
6223
|
});
|
|
6197
6224
|
}
|
|
@@ -6201,8 +6228,9 @@ var FacebookE2EESocket = class extends EventEmitter2 {
|
|
|
6201
6228
|
if (this.ws?.readyState !== WebSocket.OPEN) {
|
|
6202
6229
|
return Promise.reject(new Error("WebSocket not open"));
|
|
6203
6230
|
}
|
|
6204
|
-
return new Promise((resolve2) => {
|
|
6231
|
+
return new Promise((resolve2, reject2) => {
|
|
6205
6232
|
waitingLen = targetLen;
|
|
6233
|
+
waitingRejectFn = reject2;
|
|
6206
6234
|
waitingResolver = resolve2;
|
|
6207
6235
|
});
|
|
6208
6236
|
},
|
|
@@ -6211,10 +6239,11 @@ var FacebookE2EESocket = class extends EventEmitter2 {
|
|
|
6211
6239
|
this.ws.addEventListener("close", () => {
|
|
6212
6240
|
this.isConnected = false;
|
|
6213
6241
|
this.stopHeartbeat();
|
|
6214
|
-
if (
|
|
6215
|
-
|
|
6216
|
-
|
|
6242
|
+
if (waitingRejectFn) {
|
|
6243
|
+
waitingRejectFn(new Error("WebSocket closed while waiting for data"));
|
|
6244
|
+
waitingRejectFn = null;
|
|
6217
6245
|
}
|
|
6246
|
+
waitingResolver = null;
|
|
6218
6247
|
this.emit("disconnected");
|
|
6219
6248
|
});
|
|
6220
6249
|
this.ws.addEventListener("open", async () => {
|
|
@@ -8066,10 +8095,10 @@ var ClientController = class {
|
|
|
8066
8095
|
logger.debug("ClientController", "Fetching CAT...");
|
|
8067
8096
|
const fbCat = await this.gateway.fetchCAT(this.requireApi());
|
|
8068
8097
|
if (!ds.jidDevice) {
|
|
8069
|
-
const
|
|
8070
|
-
const
|
|
8071
|
-
const
|
|
8072
|
-
this.icdcService.setCookies(
|
|
8098
|
+
const api2 = this.requireApi();
|
|
8099
|
+
const appState2 = api2.getAppState?.() || [];
|
|
8100
|
+
const cookieStr2 = appState2.map((c) => `${c.key}=${c.value}`).join("; ");
|
|
8101
|
+
this.icdcService.setCookies(cookieStr2);
|
|
8073
8102
|
logger.info("ClientController", "Registering new device via ICDC...");
|
|
8074
8103
|
const waDeviceId = await this.icdcService.register(userId, fbCat, "2220391788200892", ds);
|
|
8075
8104
|
ds.jidDevice = waDeviceId;
|
|
@@ -8118,7 +8147,12 @@ var ClientController = class {
|
|
|
8118
8147
|
logger.error("E2EE", "Frame error:", err);
|
|
8119
8148
|
}
|
|
8120
8149
|
});
|
|
8121
|
-
|
|
8150
|
+
const api = this.requireApi();
|
|
8151
|
+
const appState = api.getAppState?.() || [];
|
|
8152
|
+
const cookieStr = appState.map((c) => `${c.key}=${c.value}`).join("; ");
|
|
8153
|
+
logger.info("ClientController", "FCA appState length:", appState.length);
|
|
8154
|
+
logger.info("ClientController", "Cookie string snippet:", cookieStr.substring(0, 100));
|
|
8155
|
+
await noiseSocket.connect(ds.noiseKeyPriv, clientPayload, cookieStr || void 0);
|
|
8122
8156
|
this.e2eeSocket = noiseSocket;
|
|
8123
8157
|
await new Promise((resolve, reject) => {
|
|
8124
8158
|
const timeout = setTimeout(() => reject(new Error("Handshake timeout")), 1e4);
|
|
@@ -8241,15 +8275,25 @@ var ClientController = class {
|
|
|
8241
8275
|
if (this.e2eeConnected && isE2EE) {
|
|
8242
8276
|
let messageId;
|
|
8243
8277
|
if (isGroup) {
|
|
8244
|
-
messageId = await this.sendE2EEGroupText(
|
|
8278
|
+
messageId = await this.sendE2EEGroupText(
|
|
8279
|
+
input.threadId,
|
|
8280
|
+
input.text,
|
|
8281
|
+
input.replyToMessageId,
|
|
8282
|
+
input.replyToSenderJid
|
|
8283
|
+
);
|
|
8245
8284
|
} else {
|
|
8246
|
-
messageId = await this.sendE2EEText(
|
|
8285
|
+
messageId = await this.sendE2EEText(
|
|
8286
|
+
input.threadId,
|
|
8287
|
+
input.text,
|
|
8288
|
+
input.replyToMessageId,
|
|
8289
|
+
input.replyToSenderJid
|
|
8290
|
+
);
|
|
8247
8291
|
}
|
|
8248
8292
|
return { messageId, timestampMs: now() };
|
|
8249
8293
|
}
|
|
8250
8294
|
return this.messagingService.sendText(this.requireApi(), input);
|
|
8251
8295
|
}
|
|
8252
|
-
async sendE2EEText(threadId, text, replyToMessageId) {
|
|
8296
|
+
async sendE2EEText(threadId, text, replyToMessageId, replyToSenderJid) {
|
|
8253
8297
|
if (!this.e2eeSocket) throw new Error("E2EE not connected");
|
|
8254
8298
|
const e2eeClient = this.e2eeService.getClient();
|
|
8255
8299
|
const selfJid = this.getSelfE2EEJid();
|
|
@@ -8261,7 +8305,9 @@ var ClientController = class {
|
|
|
8261
8305
|
text,
|
|
8262
8306
|
isGroup: false,
|
|
8263
8307
|
replyToId: replyToMessageId,
|
|
8264
|
-
|
|
8308
|
+
// For DM: participant = sender of original msg. If caller knows who sent it, use that;
|
|
8309
|
+
// otherwise fall back to the peer's JID (correct for messages they sent to us).
|
|
8310
|
+
replyToSenderJid: replyToMessageId ? replyToSenderJid ?? toJid : void 0
|
|
8265
8311
|
});
|
|
8266
8312
|
const participantNodes = [];
|
|
8267
8313
|
const deviceJids = uniqueJids(await this.e2eeHandler.getDeviceList([toJid, toBareMessengerJid(selfJid)]));
|
|
@@ -8307,7 +8353,7 @@ var ClientController = class {
|
|
|
8307
8353
|
logger.info("ClientController", `E2EE DM message sent to ${toJid} with ${participantNodes.length} devices`);
|
|
8308
8354
|
return messageId;
|
|
8309
8355
|
}
|
|
8310
|
-
async sendE2EEGroupText(groupJid, text, replyToMessageId) {
|
|
8356
|
+
async sendE2EEGroupText(groupJid, text, replyToMessageId, replyToSenderJid) {
|
|
8311
8357
|
if (!this.e2eeSocket) throw new Error("E2EE not connected");
|
|
8312
8358
|
const e2eeClient = this.e2eeService.getClient();
|
|
8313
8359
|
const selfJid = this.getSelfE2EEJid();
|
|
@@ -8323,7 +8369,8 @@ var ClientController = class {
|
|
|
8323
8369
|
text,
|
|
8324
8370
|
messageId,
|
|
8325
8371
|
replyToMessageId,
|
|
8326
|
-
|
|
8372
|
+
replyToSenderJid
|
|
8373
|
+
// pass through — undefined when not replying
|
|
8327
8374
|
);
|
|
8328
8375
|
const participantNodes = [];
|
|
8329
8376
|
for (const deviceJid of deviceJids) {
|
|
@@ -8663,7 +8710,11 @@ var ClientController = class {
|
|
|
8663
8710
|
const consumerApp = buildMessage(media.mediaFields);
|
|
8664
8711
|
const { messageApp, frankingTag } = e2eeClient.buildMessageApplication(
|
|
8665
8712
|
consumerApp,
|
|
8666
|
-
input.replyToMessageId ? {
|
|
8713
|
+
input.replyToMessageId ? {
|
|
8714
|
+
messageId: input.replyToMessageId,
|
|
8715
|
+
chatJid: toJid,
|
|
8716
|
+
senderJid: input.replyToSenderJid ?? toJid
|
|
8717
|
+
} : void 0
|
|
8667
8718
|
);
|
|
8668
8719
|
const devicePayload = e2eeClient.buildMessageTransport({ messageApp });
|
|
8669
8720
|
const selfDevicePayload = e2eeClient.buildMessageTransport({
|