fb-messenger-e2ee 0.1.1 → 0.1.2

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 (110) hide show
  1. package/README.md +27 -2
  2. package/dist/index.cjs +8811 -0
  3. package/dist/index.cjs.map +1 -0
  4. package/dist/index.d.cts +885 -0
  5. package/dist/index.d.ts +885 -0
  6. package/dist/index.js +8843 -0
  7. package/dist/index.js.map +1 -0
  8. package/package.json +19 -4
  9. package/bun.lock +0 -1014
  10. package/examples/basic-usage.ts +0 -52
  11. package/jest.config.ts +0 -18
  12. package/src/config/env.ts +0 -15
  13. package/src/controllers/client.controller.ts +0 -805
  14. package/src/controllers/dgw-handler.ts +0 -171
  15. package/src/controllers/e2ee-handler.ts +0 -832
  16. package/src/controllers/event-mapper.ts +0 -327
  17. package/src/core/client.ts +0 -151
  18. package/src/e2ee/application/e2ee-client.ts +0 -376
  19. package/src/e2ee/application/fanout-planner.ts +0 -79
  20. package/src/e2ee/application/outbound-message-cache.ts +0 -58
  21. package/src/e2ee/application/prekey-maintenance.ts +0 -55
  22. package/src/e2ee/application/retry-manager.ts +0 -156
  23. package/src/e2ee/facebook/facebook-protocol-utils.ts +0 -230
  24. package/src/e2ee/facebook/icdc-payload.ts +0 -31
  25. package/src/e2ee/index.ts +0 -76
  26. package/src/e2ee/internal.ts +0 -27
  27. package/src/e2ee/media/media-crypto.ts +0 -147
  28. package/src/e2ee/media/media-upload.ts +0 -90
  29. package/src/e2ee/message/builders/client-payload.ts +0 -54
  30. package/src/e2ee/message/builders/consumer-application.ts +0 -362
  31. package/src/e2ee/message/builders/message-application.ts +0 -64
  32. package/src/e2ee/message/builders/message-transport.ts +0 -84
  33. package/src/e2ee/message/codecs/protobuf-codecs.ts +0 -101
  34. package/src/e2ee/message/constants.ts +0 -4
  35. package/src/e2ee/message/message-builder.ts +0 -15
  36. package/src/e2ee/signal/prekey-manager.ts +0 -140
  37. package/src/e2ee/signal/signal-manager.ts +0 -365
  38. package/src/e2ee/store/device-json.ts +0 -47
  39. package/src/e2ee/store/device-repository.ts +0 -12
  40. package/src/e2ee/store/device-store.ts +0 -538
  41. package/src/e2ee/transport/binary/decoder.ts +0 -180
  42. package/src/e2ee/transport/binary/encoder.ts +0 -143
  43. package/src/e2ee/transport/binary/stanzas.ts +0 -97
  44. package/src/e2ee/transport/binary/tokens.ts +0 -64
  45. package/src/e2ee/transport/binary/wa-binary.ts +0 -8
  46. package/src/e2ee/transport/dgw/dgw-socket.ts +0 -345
  47. package/src/e2ee/transport/noise/noise-handshake.ts +0 -417
  48. package/src/e2ee/transport/noise/noise-socket.ts +0 -230
  49. package/src/index.ts +0 -34
  50. package/src/models/client.ts +0 -26
  51. package/src/models/config.ts +0 -14
  52. package/src/models/domain.ts +0 -299
  53. package/src/models/e2ee.ts +0 -295
  54. package/src/models/media.ts +0 -41
  55. package/src/models/messaging.ts +0 -88
  56. package/src/models/thread.ts +0 -69
  57. package/src/repositories/session.repository.ts +0 -20
  58. package/src/services/auth.service.ts +0 -55
  59. package/src/services/e2ee.service.ts +0 -174
  60. package/src/services/facebook-gateway.service.ts +0 -245
  61. package/src/services/icdc.service.ts +0 -177
  62. package/src/services/media.service.ts +0 -304
  63. package/src/services/messaging.service.ts +0 -28
  64. package/src/services/thread.service.ts +0 -199
  65. package/src/types/advanced-types.ts +0 -61
  66. package/src/types/fca-unofficial.d.ts +0 -212
  67. package/src/types/protocol-types.ts +0 -43
  68. package/src/utils/fca-utils.ts +0 -30
  69. package/src/utils/logger.ts +0 -24
  70. package/src/utils/mime.ts +0 -51
  71. package/tests/.env.example +0 -87
  72. package/tests/data/1x1.png +0 -0
  73. package/tests/data/example.txt +0 -1
  74. package/tests/data/file_example.mp3 +0 -0
  75. package/tests/data/file_example.mp4 +0 -0
  76. package/tests/integration.test.ts +0 -498
  77. package/tests/script/echo-e2ee.ts +0 -174
  78. package/tests/script/send-e2ee-media.ts +0 -227
  79. package/tests/script/send-e2ee-reaction.ts +0 -108
  80. package/tests/script/send-e2ee-unsend.ts +0 -115
  81. package/tests/script/send-typing.ts +0 -107
  82. package/tests/script/test-group-send.ts +0 -105
  83. package/tests/setup.ts +0 -3
  84. package/tests/types.test.ts +0 -57
  85. package/tests/unit/controllers/dgw-handler.test.ts +0 -60
  86. package/tests/unit/controllers/e2ee-handler.test.ts +0 -293
  87. package/tests/unit/controllers/event-mapper.test.ts +0 -252
  88. package/tests/unit/e2ee/application-helpers.test.ts +0 -418
  89. package/tests/unit/e2ee/device-store.test.ts +0 -126
  90. package/tests/unit/e2ee/facebook-protocol-utils.test.ts +0 -134
  91. package/tests/unit/e2ee/media-crypto.test.ts +0 -55
  92. package/tests/unit/e2ee/media-upload.test.ts +0 -60
  93. package/tests/unit/e2ee/message-builder.test.ts +0 -42
  94. package/tests/unit/e2ee/message-builders.test.ts +0 -230
  95. package/tests/unit/e2ee/noise-handshake.test.ts +0 -260
  96. package/tests/unit/e2ee/prekey-manager.test.ts +0 -55
  97. package/tests/unit/e2ee/wa-binary.test.ts +0 -127
  98. package/tests/unit/services/e2ee.service.test.ts +0 -101
  99. package/tests/unit/services/facebook-gateway.service.test.ts +0 -138
  100. package/tests/unit/services/media.service.test.ts +0 -169
  101. package/tests/unit/utils/fca-utils.test.ts +0 -48
  102. package/tsconfig.json +0 -19
  103. /package/{src/e2ee/message/proto → proto}/ArmadilloApplication.proto +0 -0
  104. /package/{src/e2ee/message/proto → proto}/ArmadilloICDC.proto +0 -0
  105. /package/{src/e2ee/message/proto → proto}/ConsumerApplication.proto +0 -0
  106. /package/{src/e2ee/message/proto → proto}/MessageApplication.proto +0 -0
  107. /package/{src/e2ee/message/proto → proto}/MessageTransport.proto +0 -0
  108. /package/{src/e2ee/message/proto → proto}/WACommon.proto +0 -0
  109. /package/{src/e2ee/message/proto → proto}/WAMediaTransport.proto +0 -0
  110. /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";