fb-messenger-e2ee 0.1.1 → 0.1.3

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.
Files changed (111) hide show
  1. package/DOCS.md +41 -3
  2. package/README.md +27 -2
  3. package/dist/index.cjs +9017 -0
  4. package/dist/index.cjs.map +1 -0
  5. package/dist/index.d.cts +910 -0
  6. package/dist/index.d.ts +910 -0
  7. package/dist/index.js +9049 -0
  8. package/dist/index.js.map +1 -0
  9. package/package.json +19 -4
  10. package/bun.lock +0 -1014
  11. package/examples/basic-usage.ts +0 -52
  12. package/jest.config.ts +0 -18
  13. package/src/config/env.ts +0 -15
  14. package/src/controllers/client.controller.ts +0 -805
  15. package/src/controllers/dgw-handler.ts +0 -171
  16. package/src/controllers/e2ee-handler.ts +0 -832
  17. package/src/controllers/event-mapper.ts +0 -327
  18. package/src/core/client.ts +0 -151
  19. package/src/e2ee/application/e2ee-client.ts +0 -376
  20. package/src/e2ee/application/fanout-planner.ts +0 -79
  21. package/src/e2ee/application/outbound-message-cache.ts +0 -58
  22. package/src/e2ee/application/prekey-maintenance.ts +0 -55
  23. package/src/e2ee/application/retry-manager.ts +0 -156
  24. package/src/e2ee/facebook/facebook-protocol-utils.ts +0 -230
  25. package/src/e2ee/facebook/icdc-payload.ts +0 -31
  26. package/src/e2ee/index.ts +0 -76
  27. package/src/e2ee/internal.ts +0 -27
  28. package/src/e2ee/media/media-crypto.ts +0 -147
  29. package/src/e2ee/media/media-upload.ts +0 -90
  30. package/src/e2ee/message/builders/client-payload.ts +0 -54
  31. package/src/e2ee/message/builders/consumer-application.ts +0 -362
  32. package/src/e2ee/message/builders/message-application.ts +0 -64
  33. package/src/e2ee/message/builders/message-transport.ts +0 -84
  34. package/src/e2ee/message/codecs/protobuf-codecs.ts +0 -101
  35. package/src/e2ee/message/constants.ts +0 -4
  36. package/src/e2ee/message/message-builder.ts +0 -15
  37. package/src/e2ee/signal/prekey-manager.ts +0 -140
  38. package/src/e2ee/signal/signal-manager.ts +0 -365
  39. package/src/e2ee/store/device-json.ts +0 -47
  40. package/src/e2ee/store/device-repository.ts +0 -12
  41. package/src/e2ee/store/device-store.ts +0 -538
  42. package/src/e2ee/transport/binary/decoder.ts +0 -180
  43. package/src/e2ee/transport/binary/encoder.ts +0 -143
  44. package/src/e2ee/transport/binary/stanzas.ts +0 -97
  45. package/src/e2ee/transport/binary/tokens.ts +0 -64
  46. package/src/e2ee/transport/binary/wa-binary.ts +0 -8
  47. package/src/e2ee/transport/dgw/dgw-socket.ts +0 -345
  48. package/src/e2ee/transport/noise/noise-handshake.ts +0 -417
  49. package/src/e2ee/transport/noise/noise-socket.ts +0 -230
  50. package/src/index.ts +0 -34
  51. package/src/models/client.ts +0 -26
  52. package/src/models/config.ts +0 -14
  53. package/src/models/domain.ts +0 -299
  54. package/src/models/e2ee.ts +0 -295
  55. package/src/models/media.ts +0 -41
  56. package/src/models/messaging.ts +0 -88
  57. package/src/models/thread.ts +0 -69
  58. package/src/repositories/session.repository.ts +0 -20
  59. package/src/services/auth.service.ts +0 -55
  60. package/src/services/e2ee.service.ts +0 -174
  61. package/src/services/facebook-gateway.service.ts +0 -245
  62. package/src/services/icdc.service.ts +0 -177
  63. package/src/services/media.service.ts +0 -304
  64. package/src/services/messaging.service.ts +0 -28
  65. package/src/services/thread.service.ts +0 -199
  66. package/src/types/advanced-types.ts +0 -61
  67. package/src/types/fca-unofficial.d.ts +0 -212
  68. package/src/types/protocol-types.ts +0 -43
  69. package/src/utils/fca-utils.ts +0 -30
  70. package/src/utils/logger.ts +0 -24
  71. package/src/utils/mime.ts +0 -51
  72. package/tests/.env.example +0 -87
  73. package/tests/data/1x1.png +0 -0
  74. package/tests/data/example.txt +0 -1
  75. package/tests/data/file_example.mp3 +0 -0
  76. package/tests/data/file_example.mp4 +0 -0
  77. package/tests/integration.test.ts +0 -498
  78. package/tests/script/echo-e2ee.ts +0 -174
  79. package/tests/script/send-e2ee-media.ts +0 -227
  80. package/tests/script/send-e2ee-reaction.ts +0 -108
  81. package/tests/script/send-e2ee-unsend.ts +0 -115
  82. package/tests/script/send-typing.ts +0 -107
  83. package/tests/script/test-group-send.ts +0 -105
  84. package/tests/setup.ts +0 -3
  85. package/tests/types.test.ts +0 -57
  86. package/tests/unit/controllers/dgw-handler.test.ts +0 -60
  87. package/tests/unit/controllers/e2ee-handler.test.ts +0 -293
  88. package/tests/unit/controllers/event-mapper.test.ts +0 -252
  89. package/tests/unit/e2ee/application-helpers.test.ts +0 -418
  90. package/tests/unit/e2ee/device-store.test.ts +0 -126
  91. package/tests/unit/e2ee/facebook-protocol-utils.test.ts +0 -134
  92. package/tests/unit/e2ee/media-crypto.test.ts +0 -55
  93. package/tests/unit/e2ee/media-upload.test.ts +0 -60
  94. package/tests/unit/e2ee/message-builder.test.ts +0 -42
  95. package/tests/unit/e2ee/message-builders.test.ts +0 -230
  96. package/tests/unit/e2ee/noise-handshake.test.ts +0 -260
  97. package/tests/unit/e2ee/prekey-manager.test.ts +0 -55
  98. package/tests/unit/e2ee/wa-binary.test.ts +0 -127
  99. package/tests/unit/services/e2ee.service.test.ts +0 -101
  100. package/tests/unit/services/facebook-gateway.service.test.ts +0 -138
  101. package/tests/unit/services/media.service.test.ts +0 -169
  102. package/tests/unit/utils/fca-utils.test.ts +0 -48
  103. package/tsconfig.json +0 -19
  104. /package/{src/e2ee/message/proto → proto}/ArmadilloApplication.proto +0 -0
  105. /package/{src/e2ee/message/proto → proto}/ArmadilloICDC.proto +0 -0
  106. /package/{src/e2ee/message/proto → proto}/ConsumerApplication.proto +0 -0
  107. /package/{src/e2ee/message/proto → proto}/MessageApplication.proto +0 -0
  108. /package/{src/e2ee/message/proto → proto}/MessageTransport.proto +0 -0
  109. /package/{src/e2ee/message/proto → proto}/WACommon.proto +0 -0
  110. /package/{src/e2ee/message/proto → proto}/WAMediaTransport.proto +0 -0
  111. /package/{src/e2ee/message/proto → proto}/proto-writer.ts +0 -0
@@ -1,180 +0,0 @@
1
- import { inflateSync } from "node:zlib";
2
- import { BinaryToken, DoubleByteTokens, SingleByteTokens } from "./tokens.ts";
3
-
4
- export interface Node {
5
- tag: string;
6
- attrs: Record<string, any>;
7
- content?: any;
8
- }
9
-
10
- export class BinaryDecoder {
11
- private data: Buffer;
12
- private index: number = 0;
13
-
14
- constructor(data: Buffer) {
15
- this.data = data;
16
- }
17
-
18
- readByte(): number {
19
- if (this.index >= this.data.length) throw new Error("EOF");
20
- const val = this.data[this.index++];
21
- if (val === undefined) throw new Error("EOF");
22
- return val;
23
- }
24
-
25
- readInt8(): number { return this.readByte(); }
26
-
27
- readInt16(): number {
28
- const val = this.data.readUInt16BE(this.index);
29
- this.index += 2;
30
- return val;
31
- }
32
-
33
- readInt20(): number {
34
- const b1 = this.data[this.index];
35
- const b2 = this.data[this.index + 1];
36
- const b3 = this.data[this.index + 2];
37
- if (b1 === undefined || b2 === undefined || b3 === undefined) throw new Error("EOF");
38
- const val = ((b1 & 15) << 16) + (b2 << 8) + b3;
39
- this.index += 3;
40
- return val;
41
- }
42
-
43
- readInt32(): number {
44
- const val = this.data.readUInt32BE(this.index);
45
- this.index += 4;
46
- return val;
47
- }
48
-
49
- readListSize(tag: number): number {
50
- switch (tag) {
51
- case BinaryToken.ListEmpty: return 0;
52
- case BinaryToken.List8: return this.readInt8();
53
- case BinaryToken.List16: return this.readInt16();
54
- default: throw new Error("Invalid list size tag: " + tag);
55
- }
56
- }
57
-
58
- readString(tag: number): string {
59
- if (tag >= 1 && tag < SingleByteTokens.length) {
60
- return SingleByteTokens[tag] || "";
61
- }
62
- switch (tag) {
63
- case BinaryToken.Dictionary0:
64
- case BinaryToken.Dictionary1:
65
- case BinaryToken.Dictionary2:
66
- case BinaryToken.Dictionary3:
67
- const dictIdx = tag - BinaryToken.Dictionary0;
68
- const innerIdx = this.readInt8();
69
- const dict = DoubleByteTokens[dictIdx];
70
- if (!dict) throw new Error("Invalid dictionary index: " + dictIdx);
71
- return dict[innerIdx] || "";
72
- case BinaryToken.Binary8: return this.readRaw(this.readInt8()).toString();
73
- case BinaryToken.Binary20: return this.readRaw(this.readInt20()).toString();
74
- case BinaryToken.Binary32: return this.readRaw(this.readInt32()).toString();
75
- case BinaryToken.Nibble8:
76
- case BinaryToken.Hex8:
77
- return this.readPacked8(tag);
78
- default: throw new Error("Invalid string tag: " + tag);
79
- }
80
- }
81
-
82
- readRaw(len: number): Buffer {
83
- if (this.index + len > this.data.length) {
84
- throw new Error(`BinaryReader: Read out of bounds (index=${this.index}, len=${len}, dataLen=${this.data.length})`);
85
- }
86
- const val = this.data.subarray(this.index, this.index + len);
87
- this.index += len;
88
- return val;
89
- }
90
-
91
- readPacked8(tag: number): string {
92
- const startByte = this.readByte();
93
- const len = startByte & 127;
94
- let res = "";
95
- for (let i = 0; i < len; i++) {
96
- const b = this.readByte();
97
- res += this.unpackByte(tag, (b & 0xF0) >> 4);
98
- res += this.unpackByte(tag, b & 0x0F);
99
- }
100
- if (startByte >> 7 !== 0 && tag === BinaryToken.Hex8) res = res.slice(0, -1);
101
- return res;
102
- }
103
-
104
- unpackByte(tag: number, val: number): string {
105
- if (tag === BinaryToken.Nibble8) {
106
- if (val < 10) return String.fromCharCode(48 + val);
107
- if (val === 10) return "-";
108
- if (val === 11) return ".";
109
- if (val === 15) return "";
110
- } else if (tag === BinaryToken.Hex8) {
111
- if (val < 10) return String.fromCharCode(48 + val);
112
- if (val < 16) return String.fromCharCode(65 + val - 10);
113
- }
114
- return "";
115
- }
116
-
117
- readNode(): Node {
118
- const listSize = this.readListSize(this.readByte());
119
- const tag = this.readString(this.readByte());
120
- const attrs: Record<string, any> = {};
121
- const attrCount = (listSize - 1) >> 1;
122
- for (let i = 0; i < attrCount; i++) {
123
- const key = this.readString(this.readByte());
124
- const val = this.read(true);
125
- attrs[key] = val;
126
- }
127
- let content: any;
128
- if (listSize % 2 === 0) {
129
- content = this.read(false);
130
- }
131
- return { tag, attrs, content };
132
- }
133
-
134
- read(asString: boolean): any {
135
- const tag = this.readByte();
136
- if (tag === BinaryToken.ListEmpty) return null;
137
- if (tag === BinaryToken.List8 || tag === BinaryToken.List16) {
138
- const size = this.readListSize(tag);
139
- const res: Node[] = [];
140
- for (let i = 0; i < size; i++) res.push(this.readNode());
141
- return res;
142
- }
143
- if (tag === BinaryToken.Binary8) return this.readBytesOrString(this.readInt8(), asString);
144
- if (tag === BinaryToken.Binary20) return this.readBytesOrString(this.readInt20(), asString);
145
- if (tag === BinaryToken.Binary32) return this.readBytesOrString(this.readInt32(), asString);
146
- if (tag === BinaryToken.JIDPair) {
147
- const user = this.read(true);
148
- const server = this.read(true);
149
- return (user ? user + "@" : "") + server;
150
- }
151
- if (tag === BinaryToken.FBJID) {
152
- const user = this.read(true);
153
- const device = this.readInt16();
154
- const server = this.read(true);
155
- return `${user}.${device}@${server}`;
156
- }
157
- if (tag === BinaryToken.ADJID) {
158
- const agent = this.readByte();
159
- const device = this.readByte();
160
- const user = this.read(true);
161
- return `${user}.${agent}:${device}@s.whatsapp.net`;
162
- }
163
- return this.readString(tag);
164
- }
165
-
166
- readBytesOrString(len: number, asString: boolean): any {
167
- const raw = this.readRaw(len);
168
- return asString ? raw.toString() : raw;
169
- }
170
- }
171
-
172
- export function unmarshal(data: Buffer): Node {
173
- if (data.length === 0) throw new Error("Empty data in unmarshal");
174
- const dataType = data[0];
175
- let body = data.subarray(1);
176
- if (dataType !== undefined && (dataType & 2)) {
177
- body = inflateSync(body);
178
- }
179
- return new BinaryDecoder(body).readNode();
180
- }
@@ -1,143 +0,0 @@
1
- import type { Node } from "./decoder.ts";
2
- import { BinaryToken, DoubleTokenToIndex, TokenToIndex } from "./tokens.ts";
3
-
4
- export function marshal(node: Node | Buffer): Buffer {
5
- const buf = Buffer.isBuffer(node) ? node : encodeNode(node.tag, node.attrs as Record<string, string>, node.content);
6
- return Buffer.concat([Buffer.from([0]), buf]); // dataType = 0 (not compressed)
7
- }
8
-
9
- export function encodeNode(tag: string, attrs: Record<string, string>, children?: any): Buffer {
10
- const hasContent = children !== undefined;
11
- const listSize = 1 + (Object.keys(attrs).length * 2) + (hasContent ? 1 : 0);
12
-
13
- const chunks: Buffer[] = [encodeListStart(listSize), encodeString(tag)];
14
-
15
- const JID_ATTRIBUTES = new Set(["to", "from", "jid", "participant", "recipient", "target"]);
16
-
17
- for (const [k, v] of Object.entries(attrs)) {
18
- chunks.push(encodeString(k));
19
- if (typeof v === "string" && (v.includes("@") || JID_ATTRIBUTES.has(k))) {
20
- chunks.push(encodeJID(v));
21
- } else {
22
- chunks.push(encodeString(String(v)));
23
- }
24
- }
25
-
26
- if (hasContent) {
27
- if (Array.isArray(children)) {
28
- chunks.push(encodeNodeList(children));
29
- } else if (Buffer.isBuffer(children)) {
30
- chunks.push(encodeStringRaw(children));
31
- } else {
32
- chunks.push(encodeString(String(children)));
33
- }
34
- }
35
-
36
- return Buffer.concat(chunks);
37
- }
38
-
39
- function encodeNodeList(nodes: Buffer[]): Buffer {
40
- return Buffer.concat([encodeListStart(nodes.length), ...nodes]);
41
- }
42
-
43
- function encodeListStart(size: number): Buffer {
44
- if (size === 0) return Buffer.from([BinaryToken.ListEmpty]);
45
- if (size < 256) return Buffer.from([BinaryToken.List8, size]);
46
- if (size < 65536) {
47
- const out = Buffer.alloc(3);
48
- out[0] = BinaryToken.List16;
49
- out.writeUInt16BE(size, 1);
50
- return out;
51
- }
52
- throw new Error("List too large");
53
- }
54
-
55
- function encodeString(val: string): Buffer {
56
- const token = TokenToIndex[val];
57
- if (typeof token === "number") return Buffer.from([token]);
58
-
59
- const doubleToken = DoubleTokenToIndex[val];
60
- if (doubleToken) {
61
- return Buffer.from([BinaryToken.Dictionary0 + doubleToken.dict, doubleToken.index]);
62
- }
63
-
64
- return encodeStringRaw(Buffer.from(val));
65
- }
66
-
67
- function encodeStringRaw(buf: Buffer): Buffer {
68
- if (buf.length < 256) return Buffer.concat([Buffer.from([BinaryToken.Binary8, buf.length]), buf]);
69
- if (buf.length < 1048576) {
70
- const header = Buffer.alloc(4);
71
- header[0] = BinaryToken.Binary20;
72
- header[1] = (buf.length >> 16) & 0xFF;
73
- header[2] = (buf.length >> 8) & 0xFF;
74
- header[3] = buf.length & 0xFF;
75
- return Buffer.concat([header, buf]);
76
- }
77
- const header = Buffer.alloc(5);
78
- header[0] = BinaryToken.Binary32;
79
- header.writeUInt32BE(buf.length, 1);
80
- return Buffer.concat([header, buf]);
81
- }
82
-
83
- function encodeJID(jid: string): Buffer {
84
- const atIdx = jid.indexOf("@");
85
- if (atIdx === -1) return encodeString(jid);
86
-
87
- const userFull = jid.slice(0, atIdx);
88
- const server = jid.slice(atIdx + 1);
89
-
90
- if (server === "msgr") {
91
- let user = userFull;
92
- let device = 0;
93
- const dotIdx = userFull.indexOf(".");
94
- const colonIdx = userFull.indexOf(":");
95
- const splitIdx = dotIdx !== -1 ? dotIdx : colonIdx;
96
-
97
- if (splitIdx !== -1) {
98
- user = userFull.slice(0, splitIdx);
99
- device = parseInt(userFull.slice(splitIdx + 1));
100
- }
101
-
102
- const chunks = [Buffer.from([BinaryToken.FBJID]), encodeString(user)];
103
- const devBuf = Buffer.alloc(2);
104
- devBuf.writeUInt16BE(device);
105
- chunks.push(devBuf);
106
- chunks.push(encodeString(server));
107
- return Buffer.concat(chunks);
108
- }
109
-
110
- // Handle ADJID (for @s.whatsapp.net with devices)
111
- if (server === "s.whatsapp.net" && (userFull.includes(".") || userFull.includes(":"))) {
112
- let user = userFull;
113
- let agent = 0;
114
- let device = 0;
115
-
116
- // Format: user.agent:device
117
- const dotIdx = userFull.indexOf(".");
118
- const colonIdx = userFull.indexOf(":");
119
- if (dotIdx !== -1 && colonIdx !== -1) {
120
- user = userFull.slice(0, dotIdx);
121
- agent = parseInt(userFull.slice(dotIdx + 1, colonIdx));
122
- device = parseInt(userFull.slice(colonIdx + 1));
123
- } else if (dotIdx !== -1) {
124
- user = userFull.slice(0, dotIdx);
125
- device = parseInt(userFull.slice(dotIdx + 1));
126
- }
127
-
128
- return Buffer.concat([
129
- Buffer.from([BinaryToken.ADJID, agent, device]),
130
- encodeString(user)
131
- ]);
132
- }
133
-
134
- // JIDPair: user@server (usually for g.us)
135
- const chunks: Uint8Array[] = [Buffer.from([BinaryToken.JIDPair])];
136
- if (userFull) {
137
- chunks.push(encodeString(userFull));
138
- } else {
139
- chunks.push(Buffer.from([BinaryToken.ListEmpty]));
140
- }
141
- chunks.push(encodeString(server));
142
- return Buffer.concat(chunks);
143
- }
@@ -1,97 +0,0 @@
1
- import { encodeNode, marshal } from "./encoder.ts";
2
-
3
- const UNIFIED_OFFSET_MS = 3 * 24 * 60 * 60 * 1000;
4
- const WEEK_MS = 7 * 24 * 60 * 60 * 1000;
5
-
6
- export function buildUnifiedSessionId(
7
- nowMs: number = Date.now(),
8
- serverOffsetMs: number = 0,
9
- ): string {
10
- const unifiedTs = nowMs + serverOffsetMs + UNIFIED_OFFSET_MS;
11
- return String(unifiedTs % WEEK_MS);
12
- }
13
-
14
- export function encodePresenceAvailable(passive?: string): Buffer {
15
- const attrs: Record<string, string> = { type: "available" };
16
- if (passive !== undefined) attrs.passive = passive;
17
- return marshal(encodeNode("presence", attrs));
18
- }
19
-
20
- export function encodePrimingNode(sessionId: string): Buffer {
21
- const unifiedSession = encodeNode("unified_session", { id: sessionId });
22
- const offlineNode = encodeNode("offline", {});
23
- const accountSync = encodeNode("dirty", { type: "account_sync" });
24
- return marshal(encodeNode("ib", {}, [unifiedSession, offlineNode, accountSync]));
25
- }
26
-
27
- export function encodeKeepAlive(id: string): Buffer {
28
- return marshal(encodeNode("iq", {
29
- id: id,
30
- to: "s.whatsapp.net",
31
- type: "get",
32
- xmlns: "w:p",
33
- }));
34
- }
35
-
36
- export function encodeSetPassive(id: string, passive: boolean): Buffer {
37
- return marshal(encodeNode("iq", {
38
- id: id,
39
- to: "s.whatsapp.net",
40
- type: "set",
41
- xmlns: "passive",
42
- }, [
43
- encodeNode(passive ? "passive" : "active", {})
44
- ]));
45
- }
46
-
47
-
48
- export function encodeIQ(attrs: Record<string, string>, children?: any): Buffer {
49
- return marshal(encodeNode("iq", attrs, children));
50
- }
51
-
52
- export interface PreKeyNodeData {
53
- id: number;
54
- pubKey: Buffer;
55
- signature?: Buffer;
56
- }
57
-
58
- export function encodePreKeyUpload(
59
- registrationId: number,
60
- identityPub: Buffer,
61
- signedPreKey: PreKeyNodeData,
62
- preKeys: PreKeyNodeData[]
63
- ): Buffer {
64
- const regBuf = Buffer.alloc(4);
65
- regBuf.writeUInt32BE(registrationId);
66
-
67
- const children = [
68
- encodeNode("registration", {}, regBuf),
69
- encodeNode("type", {}, Buffer.from([0x05])),
70
- encodeNode("identity", {}, identityPub),
71
- encodeNode("list", {}, preKeys.map(pk => encodePreKeyNode(pk, "key"))),
72
- encodePreKeyNode(signedPreKey, "skey")
73
- ];
74
-
75
- return encodeIQ({
76
- id: `pk-${Date.now()}`,
77
- to: "s.whatsapp.net",
78
- type: "set",
79
- xmlns: "encrypt",
80
- }, children);
81
- }
82
-
83
- function encodePreKeyNode(pk: PreKeyNodeData, tag: string): Buffer {
84
- const idBuf = Buffer.alloc(4);
85
- idBuf.writeUInt32BE(pk.id);
86
-
87
- const children = [
88
- encodeNode("id", {}, idBuf.subarray(1)), // 3-byte ID
89
- encodeNode("value", {}, pk.pubKey)
90
- ];
91
-
92
- if (pk.signature) {
93
- children.push(encodeNode("signature", {}, pk.signature));
94
- }
95
-
96
- return encodeNode(tag, {}, children);
97
- }
@@ -1,64 +0,0 @@
1
- export enum BinaryToken {
2
- ListEmpty = 0,
3
- Dictionary0 = 236,
4
- Dictionary1 = 237,
5
- Dictionary2 = 238,
6
- Dictionary3 = 239,
7
- InteropJID = 245,
8
- FBJID = 246,
9
- ADJID = 247,
10
- List8 = 248,
11
- List16 = 249,
12
- JIDPair = 250,
13
- Hex8 = 251,
14
- Binary8 = 252,
15
- Binary20 = 253,
16
- Binary32 = 254,
17
- Nibble8 = 255,
18
- }
19
-
20
- export const SingleByteTokens = [
21
- "", "xmlstreamstart", "xmlstreamend", "s.whatsapp.net", "type", "participant", "from", "receipt", "id", "notification",
22
- "disappearing_mode", "status", "jid", "broadcast", "user", "devices", "device_hash", "to", "offline", "message",
23
- "result", "class", "xmlns", "duration", "notify", "iq", "t", "ack", "g.us", "enc",
24
- "urn:xmpp:whatsapp:push", "presence", "config_value", "picture", "verified_name", "config_code", "key-index-list", "contact", "mediatype", "routing_info",
25
- "edge_routing", "get", "read", "urn:xmpp:ping", "fallback_hostname", "0", "chatstate", "business_hours_config", "unavailable", "download_buckets",
26
- "skmsg", "verified_level", "composing", "handshake", "device-list", "media", "text", "fallback_ip4", "media_conn", "device",
27
- "creation", "location", "config", "item", "fallback_ip6", "count", "w:profile:picture", "image", "business", "2",
28
- "hostname", "call-creator", "display_name", "relaylatency", "platform", "abprops", "success", "msg", "offline_preview", "prop",
29
- "key-index", "v", "day_of_week", "pkmsg", "version", "1", "ping", "w:p", "download", "video",
30
- "set", "specific_hours", "props", "primary", "unknown", "hash", "commerce_experience", "last", "subscribe", "max_buckets",
31
- "call", "profile", "member_since_text", "close_time", "call-id", "sticker", "mode", "participants", "value", "query",
32
- "profile_options", "open_time", "code", "list", "host", "ts", "contacts", "upload", "lid", "preview",
33
- "update", "usync", "w:stats", "delivery", "auth_ttl", "context", "fail", "cart_enabled", "appdata", "category",
34
- "atn", "direct_connection", "decrypt-fail", "relay_id", "mmg-fallback.whatsapp.net", "target", "available", "name", "last_id", "mmg.whatsapp.net",
35
- "categories", "401", "is_new", "index", "tctoken", "ip4", "token_id", "latency", "recipient", "edit",
36
- "ip6", "add", "thumbnail-document", "26", "paused", "true", "identity", "stream:error", "key", "sidelist",
37
- "background", "audio", "3", "thumbnail-image", "biz-cover-photo", "cat", "gcm", "thumbnail-video", "error", "auth",
38
- "deny", "serial", "in", "registration", "thumbnail-link", "remove", "00", "gif", "thumbnail-gif", "tag",
39
- "capability", "multicast", "item-not-found", "description", "business_hours", "config_expo_key", "md-app-state", "expiration", "fallback", "ttl",
40
- "300", "md-msg-hist", "device_orientation", "out", "w:m", "open_24h", "side_list", "token", "inactive", "01",
41
- "document", "te2", "played", "encrypt", "msgr", "hide", "direct_path", "12", "state", "not-authorized",
42
- "url", "terminate", "signature", "status-revoke-delay", "02", "te", "linked_accounts", "trusted_contact", "timezone", "ptt",
43
- "kyc-id", "privacy_token", "readreceipts", "appointment_only", "address", "expected_ts", "privacy", "7", "android", "interactive",
44
- "device-identity", "enabled", "attribute_padding", "1080", "03", "screen_height"
45
- ];
46
-
47
- export const DoubleByteTokens = [
48
- ["read-self", "active", "fbns", "protocol", "reaction", "screen_width", "heartbeat", "deviceid", "2:47DEQpj8", "uploadfieldstat", "voip_settings", "retry", "priority", "longitude", "conflict", "false", "ig_professional", "replaced", "preaccept", "cover_photo", "uncompressed", "encopt", "ppic", "04", "passive", "status-revoke-drop", "keygen", "540", "offer", "rate", "opus", "latitude", "w:gp2", "ver", "4", "business_profile", "medium", "sender", "prev_v_id", "email", "website", "invited", "sign_credential", "05", "transport", "skey", "reason", "peer_abtest_bucket", "America/Sao_Paulo", "appid", "refresh", "100", "06", "404", "101", "104", "107", "102", "109", "103", "member_add_mode", "105", "transaction-id", "110", "106", "outgoing", "108", "111", "tokens", "followers", "ig_handle", "self_pid", "tue", "dec", "thu", "joinable", "peer_pid", "mon", "features", "wed", "peer_device_presence", "pn", "delete", "07", "fri", "audio_duration", "admin", "connected", "delta", "rcat", "disable", "collection", "08", "480", "sat", "phash", "all", "invite", "accept", "critical_unblock_low", "group_update", "signed_credential", "blinded_credential", "eph_setting", "net", "09", "background_location", "refresh_id", "Asia/Kolkata", "privacy_mode_ts", "account_sync", "voip_payload_type", "service_areas", "acs_public_key", "v_id", "0a", "fallback_class", "relay", "actual_actors", "metadata", "w:biz", "5", "connected-limit", "notice", "0b", "host_storage", "fb_page", "subject", "privatestats", "invis", "groupadd", "010", "note.m4r", "uuid", "0c", "8000", "sun", "372", "1020", "stage", "1200", "720", "canonical", "fb", "011", "video_duration", "0d", "1140", "superadmin", "012", "Opening.m4r", "keystore_attestation", "dleq_proof", "013", "timestamp", "ab_key", "w:sync:app:state", "0e", "vertical", "600", "p_v_id", "6", "likes", "014", "500", "1260", "creator", "0f", "rte", "destination", "group", "group_info", "syncd_anti_tampering_fatal_exception_enabled", "015", "dl_bw", "Asia/Jakarta", "vp8/h.264", "online", "1320", "fb:multiway", "10", "timeout", "016", "nse_retry", "urn:xmpp:whatsapp:dirty", "017", "a_v_id", "web_shops_chat_header_button_enabled", "nse_call", "inactive-upgrade", "none", "web", "groups", "2250", "mms_hot_content_timespan_in_seconds", "contact_blacklist", "nse_read", "suspended_group_deletion_notification", "binary_version", "018", "https://www.whatsapp.com/otp/copy/", "reg_push", "shops_hide_catalog_attachment_entrypoint", "server_sync", ".", "ephemeral_messages_allowed_values", "019", "mms_vcache_aggregation_enabled", "iphone", "America/Argentina/Buenos_Aires", "01a", "mms_vcard_autodownload_size_kb", "nse_ver", "shops_header_dropdown_menu_item", "dhash", "catalog_status", "communities_mvp_new_iqs_serverprop", "blocklist", "default", "11", "ephemeral_messages_enabled", "01b", "original_dimensions", "8", "mms4_media_retry_notification_encryption_enabled", "mms4_server_error_receipt_encryption_enabled", "original_image_url", "sync", "multiway", "420", "companion_enc_static", "shops_profile_drawer_entrypoint", "01c", "vcard_as_document_size_kb", "status_video_max_duration", "request_image_url", "01d", "regular_high", "s_t", "abt", "share_ext_min_preliminary_image_quality", "01e", "32", "syncd_key_rotation_enabled", "data_namespace", "md_downgrade_read_receipts2", "patch", "polltype", "ephemeral_messages_setting", "userrate", "15", "partial_pjpeg_bw_threshold", "played-self", "catalog_exists", "01f", "mute_v2"],
49
- ["reject", "dirty", "announcement", "020", "13", "9", "status_video_max_bitrate", "fb:thrift_iq", "offline_batch", "022", "full", "ctwa_first_business_reply_logging", "h.264", "smax_id", "group_description_length", "https://www.whatsapp.com/otp/code", "status_image_max_edge", "smb_upsell_business_profile_enabled", "021", "web_upgrade_to_md_modal", "14", "023", "s_o", "smaller_video_thumbs_status_enabled", "media_max_autodownload", "960", "blocking_status", "peer_msg", "joinable_group_call_client_version", "group_call_video_maximization_enabled", "return_snapshot", "high", "America/Mexico_City", "entry_point_block_logging_enabled", "pop", "024", "1050", "16", "1380", "one_tap_calling_in_group_chat_size", "regular_low", "inline_joinable_education_enabled", "hq_image_max_edge", "locked", "America/Bogota", "smb_biztools_deeplink_enabled", "status_image_quality", "1088", "025", "payments_upi_intent_transaction_limit", "voip", "w:g2", "027", "md_pin_chat_enabled", "026", "multi_scan_pjpeg_download_enabled", "shops_product_grid", "transaction_id", "ctwa_context_enabled", "20", "fna", "hq_image_quality", "alt_jpeg_doc_detection_quality", "group_call_max_participants", "pkey", "America/Belem", "image_max_kbytes", "web_cart_v1_1_order_message_changes_enabled", "ctwa_context_enterprise_enabled", "urn:xmpp:whatsapp:account", "840", "Asia/Kuala_Lumpur", "max_participants", "video_remux_after_repair_enabled", "stella_addressbook_restriction_type", "660", "900", "780", "context_menu_ios13_enabled", "mute-state", "ref", "payments_request_messages", "029", "frskmsg", "vcard_max_size_kb", "sample_buffer_gif_player_enabled", "match_last_seen", "510", "4983", "video_max_bitrate", "028", "w:comms:chat", "17", "frequently_forwarded_max", "groups_privacy_blacklist", "Asia/Karachi", "02a", "web_download_document_thumb_mms_enabled", "02b", "hist_sync", "biz_block_reasons_version", "1024", "18", "web_is_direct_connection_for_plm_transparent", "view_once_write", "file_max_size", "paid_convo_id", "online_privacy_setting", "video_max_edge", "view_once_read", "enhanced_storage_management", "multi_scan_pjpeg_encoding_enabled", "ctwa_context_forward_enabled", "video_transcode_downgrade_enable", "template_doc_mime_types", "hq_image_bw_threshold", "30", "body", "u_aud_limit_sil_restarts_ctrl", "other", "participating", "w:biz:directory", "1110", "vp8", "4018", "meta", "doc_detection_image_max_edge", "image_quality", "1170", "02c", "smb_upsell_chat_banner_enabled", "key_expiry_time_second", "pid", "stella_interop_enabled", "19", "linked_device_max_count", "md_device_sync_enabled", "02d", "02e", "360", "enhanced_block_enabled", "ephemeral_icon_in_forwarding", "paid_convo_status", "gif_provider", "project_name", "server-error", "canonical_url_validation_enabled", "wallpapers_v2", "syncd_clear_chat_delete_chat_enabled", "medianotify", "02f", "shops_required_tos_version", "vote", "reset_skey_on_id_change", "030", "image_max_edge", "multicast_limit_global", "ul_bw", "21", "25", "5000", "poll", "570", "22", "031", "1280", "WhatsApp", "032", "bloks_shops_enabled", "50", "upload_host_switching_enabled", "web_ctwa_context_compose_enabled", "ptt_forwarded_features_enabled", "unblocked", "partial_pjpeg_enabled", "fbid:devices", "height", "ephemeral_group_query_ts", "group_join_permissions", "order", "033", "alt_jpeg_status_quality", "migrate", "popular-bank", "win_uwp_deprecation_killswitch_enabled", "web_download_status_thumb_mms_enabled", "blocking", "url_text", "035", "web_forwarding_limit_to_groups", "1600", "val", "1000", "syncd_msg_date_enabled", "bank-ref-id", "max_subject", "payments_web_enabled", "web_upload_document_thumb_mms_enabled", "size", "request", "ephemeral", "24", "receipt_agg", "ptt_remember_play_position", "sampling_weight", "enc_rekey", "mute_always", "037", "034", "23", "036", "action", "click_to_chat_qr_enabled", "width", "disabled", "038", "md_blocklist_v2", "played_self_enabled", "web_buttons_message_enabled", "flow_id", "clear", "450", "fbid:thread", "bloks_session_state", "America/Lima", "attachment_picker_refresh", "download_host_switching_enabled", "1792", "u_aud_limit_sil_restarts_test2", "custom_urls", "device_fanout", "optimistic_upload", "2000", "key_cipher_suite", "web_smb_upsell_in_biz_profile_enabled", "e", "039", "siri_post_status_shortcut", "pair-device", "lg", "lc", "stream_attribution_url", "model", "mspjpeg_phash_gen", "catalog_send_all", "new_multi_vcards_ui", "share_biz_vcard_enabled", "-", "clean", "200", "md_blocklist_v2_server", "03b", "03a", "web_md_migration_experience", "ptt_conversation_waveform", "u_aud_limit_sil_restarts_test1"],
50
- ["64", "ptt_playback_speed_enabled", "web_product_list_message_enabled", "paid_convo_ts", "27", "manufacturer", "psp-routing", "grp_uii_cleanup", "ptt_draft_enabled", "03c", "business_initiated", "web_catalog_products_onoff", "web_upload_link_thumb_mms_enabled", "03e", "mediaretry", "35", "hfm_string_changes", "28", "America/Fortaleza", "max_keys", "md_mhfs_days", "streaming_upload_chunk_size", "5541", "040", "03d", "2675", "03f", "...", "512", "mute", "48", "041", "alt_jpeg_quality", "60", "042", "md_smb_quick_reply", "5183", "c", "1343", "40", "1230", "043", "044", "mms_cat_v1_forward_hot_override_enabled", "user_notice", "ptt_waveform_send", "047", "Asia/Calcutta", "250", "md_privacy_v2", "31", "29", "128", "md_messaging_enabled", "046", "crypto", "690", "045", "enc_iv", "75", "failure", "ptt_oot_playback", "AIzaSyDR5yfaG7OG8sMTUj8kfQEb8T9pN8BM6Lk", "w", "048", "2201", "web_large_files_ui", "Asia/Makassar", "812", "status_collapse_muted", "1334", "257", "2HP4dm", "049", "patches", "1290", "43cY6T", "America/Caracas", "web_sticker_maker", "campaign", "ptt_pausable_enabled", "33", "42", "attestation", "biz", "04b", "query_linked", "s", "125", "04a", "810", "availability", "1411", "responsiveness_v2_m1", "catalog_not_created", "34", "America/Santiago", "1465", "enc_p", "04d", "status_info", "04f", "key_version", "..", "04c", "04e", "md_group_notification", "1598", "1215", "web_cart_enabled", "37", "630", "1920", "2394", "-1", "vcard", "38", "elapsed", "36", "828", "peer", "pricing_category", "1245", "invalid", "stella_ios_enabled", "2687", "45", "1528", "39", "u_is_redial_audio_1104_ctrl", "1025", "1455", "58", "2524", "2603", "054", "bsp_system_message_enabled", "web_pip_redesign", "051", "verify_apps", "1974", "1272", "1322", "1755", "052", "70", "050", "1063", "1135", "1361", "80", "1096", "1828", "1851", "1251", "1921", "key_config_id", "1254", "1566", "1252", "2525", "critical_block", "1669", "max_available", "w:auth:backup:token", "product", "2530", "870", "1022", "participant_uuid", "web_cart_on_off", "1255", "1432", "1867", "41", "1415", "1440", "240", "1204", "1608", "1690", "1846", "1483", "1687", "1749", "69", "url_number", "053", "1325", "1040", "365", "59", "Asia/Riyadh", "1177", "test_recommended", "057", "1612", "43", "1061", "1518", "1635", "055", "1034", "1375", "750", "1430", "event_code", "1682", "503", "55", "865", "78", "1309", "1365", "44", "America/Guayaquil", "535", "LIMITED", "1377", "1613", "1420", "1599", "1822", "05a", "1681", "password", "1111", "1214", "1376", "1478", "47", "1082", "4282", "Europe/Istanbul", "1307", "46", "058", "1124", "256", "rate-overlimit", "retail", "u_a_socket_err_fix_succ_test", "1292", "1370", "1388", "520", "861", "psa", "regular", "1181", "1766", "05b", "1183", "1213", "1304", "1537"],
51
- ["1724", "profile_picture", "1071", "1314", "1605", "407", "990", "1710", "746", "pricing_model", "056", "059", "061", "1119", "6027", "65", "877", "1607", "05d", "917", "seen", "1516", "49", "470", "973", "1037", "1350", "1394", "1480", "1796", "keys", "794", "1536", "1594", "2378", "1333", "1524", "1825", "116", "309", "52", "808", "827", "909", "495", "1660", "361", "957", "google", "1357", "1565", "1967", "996", "1775", "586", "736", "1052", "1670", "bank", "177", "1416", "2194", "2222", "1454", "1839", "1275", "53", "997", "1629", "6028", "smba", "1378", "1410", "05c", "1849", "727", "create", "1559", "536", "1106", "1310", "1944", "670", "1297", "1316", "1762", "en", "1148", "1295", "1551", "1853", "1890", "1208", "1784", "7200", "05f", "178", "1283", "1332", "381", "643", "1056", "1238", "2024", "2387", "179", "981", "1547", "1705", "05e", "290", "903", "1069", "1285", "2436", "062", "251", "560", "582", "719", "56", "1700", "2321", "325", "448", "613", "777", "791", "51", "488", "902", "Asia/Almaty", "is_hidden", "1398", "1527", "1893", "1999", "2367", "2642", "237", "busy", "065", "067", "233", "590", "993", "1511", "54", "723", "860", "363", "487", "522", "605", "995", "1321", "1691", "1865", "2447", "2462", "NON_TRANSACTIONAL", "433", "871", "432", "1004", "1207", "2032", "2050", "2379", "2446", "279", "636", "703", "904", "248", "370", "691", "700", "1068", "1655", "2334", "060", "063", "364", "533", "534", "567", "1191", "1210", "1473", "1827", "069", "701", "2531", "514", "prev_dhash", "064", "496", "790", "1046", "1139", "1505", "1521", "1108", "207", "544", "637", "final", "1173", "1293", "1694", "1939", "1951", "1993", "2353", "2515", "504", "601", "857", "modify", "spam_request", "p_121_aa_1101_test4", "866", "1427", "1502", "1638", "1744", "2153", "068", "382", "725", "1704", "1864", "1990", "2003", "Asia/Dubai", "508", "531", "1387", "1474", "1632", "2307", "2386", "819", "2014", "066", "387", "1468", "1706", "2186", "2261", "471", "728", "1147", "1372", "1961"]
52
- ];
53
-
54
- export const TokenToIndex: Record<string, number> = {};
55
- SingleByteTokens.forEach((token, idx) => {
56
- if (token) TokenToIndex[token] = idx;
57
- });
58
-
59
- export const DoubleTokenToIndex: Record<string, { dict: number; index: number }> = {};
60
- DoubleByteTokens.forEach((dict, dictIdx) => {
61
- dict.forEach((token, tokenIdx) => {
62
- if (token) DoubleTokenToIndex[token] = { dict: dictIdx, index: tokenIdx };
63
- });
64
- });
@@ -1,8 +0,0 @@
1
- /**
2
- * WA-binary public barrel for Messenger E2EE transport nodes.
3
- */
4
-
5
- export * from "./tokens.ts";
6
- export * from "./decoder.ts";
7
- export * from "./encoder.ts";
8
- export * from "./stanzas.ts";