fb-messenger-e2ee 0.1.4 → 0.1.5
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/dist/index.cjs +45 -12
- 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 +45 -12
- 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());
|
|
@@ -8241,15 +8257,25 @@ var ClientController = class {
|
|
|
8241
8257
|
if (this.e2eeConnected && isE2EE) {
|
|
8242
8258
|
let messageId;
|
|
8243
8259
|
if (isGroup) {
|
|
8244
|
-
messageId = await this.sendE2EEGroupText(
|
|
8260
|
+
messageId = await this.sendE2EEGroupText(
|
|
8261
|
+
input.threadId,
|
|
8262
|
+
input.text,
|
|
8263
|
+
input.replyToMessageId,
|
|
8264
|
+
input.replyToSenderJid
|
|
8265
|
+
);
|
|
8245
8266
|
} else {
|
|
8246
|
-
messageId = await this.sendE2EEText(
|
|
8267
|
+
messageId = await this.sendE2EEText(
|
|
8268
|
+
input.threadId,
|
|
8269
|
+
input.text,
|
|
8270
|
+
input.replyToMessageId,
|
|
8271
|
+
input.replyToSenderJid
|
|
8272
|
+
);
|
|
8247
8273
|
}
|
|
8248
8274
|
return { messageId, timestampMs: now() };
|
|
8249
8275
|
}
|
|
8250
8276
|
return this.messagingService.sendText(this.requireApi(), input);
|
|
8251
8277
|
}
|
|
8252
|
-
async sendE2EEText(threadId, text, replyToMessageId) {
|
|
8278
|
+
async sendE2EEText(threadId, text, replyToMessageId, replyToSenderJid) {
|
|
8253
8279
|
if (!this.e2eeSocket) throw new Error("E2EE not connected");
|
|
8254
8280
|
const e2eeClient = this.e2eeService.getClient();
|
|
8255
8281
|
const selfJid = this.getSelfE2EEJid();
|
|
@@ -8261,7 +8287,9 @@ var ClientController = class {
|
|
|
8261
8287
|
text,
|
|
8262
8288
|
isGroup: false,
|
|
8263
8289
|
replyToId: replyToMessageId,
|
|
8264
|
-
|
|
8290
|
+
// For DM: participant = sender of original msg. If caller knows who sent it, use that;
|
|
8291
|
+
// otherwise fall back to the peer's JID (correct for messages they sent to us).
|
|
8292
|
+
replyToSenderJid: replyToMessageId ? replyToSenderJid ?? toJid : void 0
|
|
8265
8293
|
});
|
|
8266
8294
|
const participantNodes = [];
|
|
8267
8295
|
const deviceJids = uniqueJids(await this.e2eeHandler.getDeviceList([toJid, toBareMessengerJid(selfJid)]));
|
|
@@ -8307,7 +8335,7 @@ var ClientController = class {
|
|
|
8307
8335
|
logger.info("ClientController", `E2EE DM message sent to ${toJid} with ${participantNodes.length} devices`);
|
|
8308
8336
|
return messageId;
|
|
8309
8337
|
}
|
|
8310
|
-
async sendE2EEGroupText(groupJid, text, replyToMessageId) {
|
|
8338
|
+
async sendE2EEGroupText(groupJid, text, replyToMessageId, replyToSenderJid) {
|
|
8311
8339
|
if (!this.e2eeSocket) throw new Error("E2EE not connected");
|
|
8312
8340
|
const e2eeClient = this.e2eeService.getClient();
|
|
8313
8341
|
const selfJid = this.getSelfE2EEJid();
|
|
@@ -8323,7 +8351,8 @@ var ClientController = class {
|
|
|
8323
8351
|
text,
|
|
8324
8352
|
messageId,
|
|
8325
8353
|
replyToMessageId,
|
|
8326
|
-
|
|
8354
|
+
replyToSenderJid
|
|
8355
|
+
// pass through — undefined when not replying
|
|
8327
8356
|
);
|
|
8328
8357
|
const participantNodes = [];
|
|
8329
8358
|
for (const deviceJid of deviceJids) {
|
|
@@ -8663,7 +8692,11 @@ var ClientController = class {
|
|
|
8663
8692
|
const consumerApp = buildMessage(media.mediaFields);
|
|
8664
8693
|
const { messageApp, frankingTag } = e2eeClient.buildMessageApplication(
|
|
8665
8694
|
consumerApp,
|
|
8666
|
-
input.replyToMessageId ? {
|
|
8695
|
+
input.replyToMessageId ? {
|
|
8696
|
+
messageId: input.replyToMessageId,
|
|
8697
|
+
chatJid: toJid,
|
|
8698
|
+
senderJid: input.replyToSenderJid ?? toJid
|
|
8699
|
+
} : void 0
|
|
8667
8700
|
);
|
|
8668
8701
|
const devicePayload = e2eeClient.buildMessageTransport({ messageApp });
|
|
8669
8702
|
const selfDevicePayload = e2eeClient.buildMessageTransport({
|