@kangwifi-pro/waliwa 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (144) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +600 -0
  3. package/dist/advanced/features.d.ts +211 -0
  4. package/dist/advanced/features.d.ts.map +1 -0
  5. package/dist/advanced/features.js +671 -0
  6. package/dist/advanced/features.js.map +1 -0
  7. package/dist/auth/auth-state.d.ts +89 -0
  8. package/dist/auth/auth-state.d.ts.map +1 -0
  9. package/dist/auth/auth-state.js +330 -0
  10. package/dist/auth/auth-state.js.map +1 -0
  11. package/dist/auth/pairing-code.d.ts +78 -0
  12. package/dist/auth/pairing-code.d.ts.map +1 -0
  13. package/dist/auth/pairing-code.js +191 -0
  14. package/dist/auth/pairing-code.js.map +1 -0
  15. package/dist/auth/qr-code.d.ts +60 -0
  16. package/dist/auth/qr-code.d.ts.map +1 -0
  17. package/dist/auth/qr-code.js +151 -0
  18. package/dist/auth/qr-code.js.map +1 -0
  19. package/dist/calls/handler.d.ts +61 -0
  20. package/dist/calls/handler.d.ts.map +1 -0
  21. package/dist/calls/handler.js +117 -0
  22. package/dist/calls/handler.js.map +1 -0
  23. package/dist/core/binary.d.ts +74 -0
  24. package/dist/core/binary.d.ts.map +1 -0
  25. package/dist/core/binary.js +448 -0
  26. package/dist/core/binary.js.map +1 -0
  27. package/dist/core/crypto.d.ts +60 -0
  28. package/dist/core/crypto.d.ts.map +1 -0
  29. package/dist/core/crypto.js +170 -0
  30. package/dist/core/crypto.js.map +1 -0
  31. package/dist/core/noise.d.ts +106 -0
  32. package/dist/core/noise.d.ts.map +1 -0
  33. package/dist/core/noise.js +307 -0
  34. package/dist/core/noise.js.map +1 -0
  35. package/dist/events/emitter.d.ts +44 -0
  36. package/dist/events/emitter.d.ts.map +1 -0
  37. package/dist/events/emitter.js +79 -0
  38. package/dist/events/emitter.js.map +1 -0
  39. package/dist/features/index.d.ts +342 -0
  40. package/dist/features/index.d.ts.map +1 -0
  41. package/dist/features/index.js +755 -0
  42. package/dist/features/index.js.map +1 -0
  43. package/dist/fixes/index.d.ts +333 -0
  44. package/dist/fixes/index.d.ts.map +1 -0
  45. package/dist/fixes/index.js +762 -0
  46. package/dist/fixes/index.js.map +1 -0
  47. package/dist/groups/management.d.ts +86 -0
  48. package/dist/groups/management.d.ts.map +1 -0
  49. package/dist/groups/management.js +443 -0
  50. package/dist/groups/management.js.map +1 -0
  51. package/dist/index.d.ts +65 -0
  52. package/dist/index.d.ts.map +1 -0
  53. package/dist/index.js +236 -0
  54. package/dist/index.js.map +1 -0
  55. package/dist/messages/media.d.ts +93 -0
  56. package/dist/messages/media.d.ts.map +1 -0
  57. package/dist/messages/media.js +252 -0
  58. package/dist/messages/media.js.map +1 -0
  59. package/dist/messages/message-encoder.d.ts +70 -0
  60. package/dist/messages/message-encoder.d.ts.map +1 -0
  61. package/dist/messages/message-encoder.js +453 -0
  62. package/dist/messages/message-encoder.js.map +1 -0
  63. package/dist/messages/send.d.ts +101 -0
  64. package/dist/messages/send.d.ts.map +1 -0
  65. package/dist/messages/send.js +409 -0
  66. package/dist/messages/send.js.map +1 -0
  67. package/dist/recovery/index.d.ts +125 -0
  68. package/dist/recovery/index.d.ts.map +1 -0
  69. package/dist/recovery/index.js +584 -0
  70. package/dist/recovery/index.js.map +1 -0
  71. package/dist/skdm/index.d.ts +220 -0
  72. package/dist/skdm/index.d.ts.map +1 -0
  73. package/dist/skdm/index.js +600 -0
  74. package/dist/skdm/index.js.map +1 -0
  75. package/dist/socket/hybrid.d.ts +118 -0
  76. package/dist/socket/hybrid.d.ts.map +1 -0
  77. package/dist/socket/hybrid.js +352 -0
  78. package/dist/socket/hybrid.js.map +1 -0
  79. package/dist/socket/wa-socket.d.ts +300 -0
  80. package/dist/socket/wa-socket.d.ts.map +1 -0
  81. package/dist/socket/wa-socket.js +1094 -0
  82. package/dist/socket/wa-socket.js.map +1 -0
  83. package/dist/socket/ws-socket.d.ts +96 -0
  84. package/dist/socket/ws-socket.d.ts.map +1 -0
  85. package/dist/socket/ws-socket.js +302 -0
  86. package/dist/socket/ws-socket.js.map +1 -0
  87. package/dist/types/index.d.ts +444 -0
  88. package/dist/types/index.d.ts.map +1 -0
  89. package/dist/types/index.js +7 -0
  90. package/dist/types/index.js.map +1 -0
  91. package/dist/utils/jid.d.ts +46 -0
  92. package/dist/utils/jid.d.ts.map +1 -0
  93. package/dist/utils/jid.js +152 -0
  94. package/dist/utils/jid.js.map +1 -0
  95. package/dist/utils/logger.d.ts +45 -0
  96. package/dist/utils/logger.d.ts.map +1 -0
  97. package/dist/utils/logger.js +79 -0
  98. package/dist/utils/logger.js.map +1 -0
  99. package/dist/utils/retry.d.ts +43 -0
  100. package/dist/utils/retry.d.ts.map +1 -0
  101. package/dist/utils/retry.js +175 -0
  102. package/dist/utils/retry.js.map +1 -0
  103. package/docs/API.md +745 -0
  104. package/docs/ARCHITECTURE.md +307 -0
  105. package/docs/BAILEYS_FIXES.md +360 -0
  106. package/docs/FEATURES.md +532 -0
  107. package/docs/PROTOCOL.md +489 -0
  108. package/docs/RECOVERY.md +409 -0
  109. package/docs/SKDM.md +233 -0
  110. package/examples/ai-bot/index.ts +479 -0
  111. package/examples/ai-bot/package.json +17 -0
  112. package/examples/echo-bot/index.ts +171 -0
  113. package/examples/echo-bot/package.json +18 -0
  114. package/examples/group-bot/index.ts +557 -0
  115. package/examples/group-bot/package.json +17 -0
  116. package/examples/rest-gateway/index.ts +499 -0
  117. package/examples/rest-gateway/package.json +19 -0
  118. package/package.json +75 -0
  119. package/src/advanced/features.ts +817 -0
  120. package/src/auth/auth-state.ts +342 -0
  121. package/src/auth/pairing-code.ts +246 -0
  122. package/src/auth/qr-code.ts +191 -0
  123. package/src/calls/handler.ts +153 -0
  124. package/src/core/binary.ts +464 -0
  125. package/src/core/crypto.ts +189 -0
  126. package/src/core/noise.ts +406 -0
  127. package/src/events/emitter.ts +88 -0
  128. package/src/features/index.ts +921 -0
  129. package/src/fixes/index.ts +882 -0
  130. package/src/groups/management.ts +497 -0
  131. package/src/index.ts +274 -0
  132. package/src/messages/media.ts +372 -0
  133. package/src/messages/message-encoder.ts +520 -0
  134. package/src/messages/send.ts +521 -0
  135. package/src/recovery/index.ts +704 -0
  136. package/src/skdm/index.ts +693 -0
  137. package/src/socket/hybrid.ts +414 -0
  138. package/src/socket/wa-socket.ts +1347 -0
  139. package/src/socket/ws-socket.ts +355 -0
  140. package/src/types/index.ts +457 -0
  141. package/src/utils/jid.ts +156 -0
  142. package/src/utils/logger.ts +84 -0
  143. package/src/utils/retry.ts +205 -0
  144. package/tsconfig.json +30 -0
@@ -0,0 +1,191 @@
1
+ "use strict";
2
+ /**
3
+ * Waliwa - Pairing code implementation (Mobile API style)
4
+ *
5
+ * Alternatif login tanpa scan QR - user input 8-character pairing code
6
+ * di WhatsApp mobile app. Mengikuti companion device registration flow.
7
+ *
8
+ * Format pairing code: "AB12-CD34" (8 alphanumeric, dash di tengah)
9
+ */
10
+ Object.defineProperty(exports, "__esModule", { value: true });
11
+ exports.PairingCodeExpiry = void 0;
12
+ exports.generatePairingCode = generatePairingCode;
13
+ exports.isValidPairingCodeFormat = isValidPairingCodeFormat;
14
+ exports.normalizePairingCode = normalizePairingCode;
15
+ exports.buildPairingRequestNode = buildPairingRequestNode;
16
+ exports.parsePairingResult = parsePairingResult;
17
+ exports.normalizePhoneNumber = normalizePhoneNumber;
18
+ exports.isValidPhoneNumber = isValidPhoneNumber;
19
+ const crypto_js_1 = require("../core/crypto.js");
20
+ const logger_js_1 = require("../utils/logger.js");
21
+ // ============== Pairing Code Generator ==============
22
+ /**
23
+ * Generate pairing code dari phone number + secret key
24
+ *
25
+ * Pairing code adalah 8 character alphanumeric yang derived dari:
26
+ * 1. Phone number user (target)
27
+ * 2. Server-side secret (sebagai HMAC key)
28
+ * 3. Random challenge untuk anti-replay
29
+ *
30
+ * User input code di WA mobile app, server verify dan pair device.
31
+ */
32
+ function generatePairingCode(phoneNumber, creds, logger) {
33
+ const log = logger ?? new logger_js_1.SilentLogger();
34
+ // Sanitize phone number
35
+ const cleanPhone = phoneNumber.replace(/[^0-9]/g, '');
36
+ if (cleanPhone.length < 8) {
37
+ throw new Error(`Invalid phone number: ${phoneNumber}`);
38
+ }
39
+ // Get pairing secret dari creds (atau generate)
40
+ const secretKey = creds.pairingKey?.private ?? (0, crypto_js_1.getRandomBytes)(32);
41
+ const publicKey = creds.pairingKey?.public ?? new Uint8Array(32);
42
+ // Compute pairing code via HKDF derive
43
+ // Code derived from phone number + public key fingerprint
44
+ const phoneBytes = new TextEncoder().encode(cleanPhone);
45
+ const derived = (0, crypto_js_1.hkdfDerive)(secretKey, phoneBytes, new TextEncoder().encode('pairing-code-v1'), 4 // 4 bytes = 8 hex chars
46
+ );
47
+ // Convert 4 bytes ke 8-character alphanumeric
48
+ // Mapping: each nibble (4 bits) -> 1 character dari "ABCDEFGHJKLMNPQRSTUVWXYZ23456789"
49
+ // (avoid ambiguous chars: 0/O, 1/I)
50
+ const charSet = 'ABCDEFGHJKLMNPQRSTUVWXYZ23456789';
51
+ let code = '';
52
+ for (let i = 0; i < 4; i++) {
53
+ const byte = derived[i];
54
+ code += charSet[byte >> 4]; // high nibble
55
+ code += charSet[byte & 0xf]; // low nibble
56
+ }
57
+ // Format: "XXXX-XXXX"
58
+ const formattedCode = `${code.substring(0, 4)}-${code.substring(4, 8)}`;
59
+ log.info(`Generated pairing code untuk ${cleanPhone}: ${formattedCode}`);
60
+ log.debug(`Pairing public key: ${Buffer.from(publicKey).toString('hex').substring(0, 32)}...`);
61
+ return {
62
+ code: formattedCode,
63
+ phoneNumber: cleanPhone,
64
+ expiresAt: Date.now() + 65 * 1000 // 65 detik expiry
65
+ };
66
+ }
67
+ // ============== Pairing Code Validation ==============
68
+ /**
69
+ * Validate pairing code format
70
+ */
71
+ function isValidPairingCodeFormat(code) {
72
+ return /^[A-Z0-9]{4}-[A-Z0-9]{4}$/.test(code.toUpperCase());
73
+ }
74
+ /**
75
+ * Normalize user input pairing code
76
+ * "ab12cd34" -> "AB12-CD34"
77
+ * "AB12 CD34" -> "AB12-CD34"
78
+ */
79
+ function normalizePairingCode(input) {
80
+ const cleaned = input.replace(/[^A-Za-z0-9]/g, '').toUpperCase();
81
+ if (cleaned.length !== 8) {
82
+ throw new Error(`Pairing code must be 8 alphanumeric chars, got: ${input}`);
83
+ }
84
+ return `${cleaned.substring(0, 4)}-${cleaned.substring(4, 8)}`;
85
+ }
86
+ // ============== Pairing Request Builder ==============
87
+ /**
88
+ * Build pairing request binary node untuk kirim ke server
89
+ *
90
+ * <iq type="get" to="s.whatsapp.net">
91
+ * <pair code="AB12-CD34" phone="6281234567890" />
92
+ * </iq>
93
+ */
94
+ function buildPairingRequestNode(code, phoneNumber, publicKey) {
95
+ const cleanPhone = phoneNumber.replace(/[^0-9]/g, '');
96
+ return {
97
+ tag: 'iq',
98
+ attrs: {
99
+ type: 'set',
100
+ to: 's.whatsapp.net',
101
+ id: `pair-${Date.now()}`
102
+ },
103
+ content: [
104
+ {
105
+ tag: 'pair',
106
+ attrs: {
107
+ code: code.replace('-', ''),
108
+ phone: cleanPhone,
109
+ pubkey: Buffer.from(publicKey).toString('base64')
110
+ }
111
+ }
112
+ ]
113
+ };
114
+ }
115
+ /**
116
+ * Parse pairing result dari binary node response
117
+ */
118
+ function parsePairingResult(node) {
119
+ if (!node || node.tag !== 'iq') {
120
+ return { success: false, error: 'Invalid response node' };
121
+ }
122
+ const type = node.attrs?.type;
123
+ if (type === 'error') {
124
+ const errorNode = Array.isArray(node.content) && node.content.find((c) => c.tag === 'error');
125
+ return {
126
+ success: false,
127
+ error: errorNode?.attrs?.text || 'Pairing failed'
128
+ };
129
+ }
130
+ const pairNode = Array.isArray(node.content) && node.content.find((c) => c.tag === 'pair');
131
+ if (!pairNode) {
132
+ return { success: false, error: 'Pair result not found' };
133
+ }
134
+ return {
135
+ success: true,
136
+ jid: pairNode.attrs?.jid,
137
+ platform: pairNode.attrs?.platform,
138
+ businessName: pairNode.attrs?.business_name,
139
+ identityKey: pairNode.attrs?.identity
140
+ ? new Uint8Array(Buffer.from(pairNode.attrs.identity, 'base64'))
141
+ : undefined
142
+ };
143
+ }
144
+ // ============== Phone Number Normalization ==============
145
+ /**
146
+ * Normalize phone number - hapus karakter non-digit
147
+ */
148
+ function normalizePhoneNumber(phone) {
149
+ return phone.replace(/[^0-9]/g, '');
150
+ }
151
+ /**
152
+ * Check apakah phone number valid (Indonesia: 10-15 digit)
153
+ */
154
+ function isValidPhoneNumber(phone) {
155
+ const clean = normalizePhoneNumber(phone);
156
+ return clean.length >= 8 && clean.length <= 15;
157
+ }
158
+ // ============== Code Expiry Tracker ==============
159
+ class PairingCodeExpiry {
160
+ expiresAt;
161
+ onExpiry;
162
+ timer = null;
163
+ constructor(expiresAt, onExpiry) {
164
+ this.expiresAt = expiresAt;
165
+ this.onExpiry = onExpiry;
166
+ }
167
+ start() {
168
+ const msUntilExpiry = this.expiresAt - Date.now();
169
+ if (msUntilExpiry <= 0) {
170
+ this.onExpiry();
171
+ return;
172
+ }
173
+ this.timer = setTimeout(() => {
174
+ this.onExpiry();
175
+ }, msUntilExpiry);
176
+ }
177
+ cancel() {
178
+ if (this.timer) {
179
+ clearTimeout(this.timer);
180
+ this.timer = null;
181
+ }
182
+ }
183
+ getRemainingMs() {
184
+ return Math.max(0, this.expiresAt - Date.now());
185
+ }
186
+ isExpired() {
187
+ return Date.now() >= this.expiresAt;
188
+ }
189
+ }
190
+ exports.PairingCodeExpiry = PairingCodeExpiry;
191
+ //# sourceMappingURL=pairing-code.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pairing-code.js","sourceRoot":"","sources":["../../src/auth/pairing-code.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,60 @@
1
+ /**
2
+ * Waliwa - QR code generation untuk WhatsApp Web Multi-Device pairing
3
+ *
4
+ * QR code berisi: ref + publicKey + pairingStaticKey (encoded sebagai comma-separated)
5
+ * User scan dengan WhatsApp mobile app untuk establish pairing
6
+ */
7
+ import type { QRGenerationData, AuthenticationCreds, WALogger } from '../types/index.js';
8
+ /**
9
+ * Generate new QR reference (server-side correlation ID)
10
+ * Format: 8-character alphanumeric
11
+ */
12
+ export declare function generateQRRef(): string;
13
+ /**
14
+ * Build QR code string untuk WA pairing
15
+ *
16
+ * Format:
17
+ * ref,publicKey(base64),pairingStaticKey(base64),clientDid,serverDid
18
+ *
19
+ * WhatsApp mobile app akan scan QR, kirim ke server, server pakai publicKey
20
+ * untuk encrypt pairing payload yang berisi identity keys.
21
+ */
22
+ export declare function buildQRString(ref: string, publicKey: Uint8Array, pairingStaticKey: Uint8Array,
23
+ /** Client device ID (noise static key fingerprint) */
24
+ clientDid?: Uint8Array): string;
25
+ export interface QRGenerationOptions {
26
+ creds: AuthenticationCreds;
27
+ logger?: WALogger;
28
+ /** Print QR ke terminal? */
29
+ printInTerminal?: boolean;
30
+ /** Small QR mode (lebih kompak di terminal) */
31
+ small?: boolean;
32
+ }
33
+ /**
34
+ * Generate QR code data dari auth creds
35
+ */
36
+ export declare function generateQRCodeData(opts: QRGenerationOptions): QRGenerationData;
37
+ /**
38
+ * QR refresh manager - auto-refresh QR setiap ~20 detik (sesuai WA server timeout)
39
+ * Untuk menghindari stale QR yang sudah expire
40
+ */
41
+ export declare class QRRefreshManager {
42
+ private timer;
43
+ private onRefresh;
44
+ private onTimeout;
45
+ private refreshIntervalMs;
46
+ private maxRefreshCount;
47
+ private refreshCount;
48
+ private isRunning;
49
+ constructor(onRefresh: (qr: QRGenerationData) => void, onTimeout: () => void, refreshIntervalMs?: number, maxRefreshCount?: number);
50
+ start(initialQR: QRGenerationData): void;
51
+ private generateNewQRPlaceholder;
52
+ stop(): void;
53
+ }
54
+ export declare function parseQRString(qrString: string): {
55
+ ref: string;
56
+ publicKey: Uint8Array;
57
+ pairingStaticKey: Uint8Array;
58
+ clientDid?: Uint8Array;
59
+ };
60
+ //# sourceMappingURL=qr-code.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"qr-code.d.ts","sourceRoot":"","sources":["../../src/auth/qr-code.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EACV,gBAAgB,EAChB,mBAAmB,EACnB,QAAQ,EACT,MAAM,mBAAmB,CAAC;AAQ3B;;;GAGG;AACH,wBAAgB,aAAa,IAAI,MAAM,CAStC;AAID;;;;;;;;GAQG;AACH,wBAAgB,aAAa,CAC3B,GAAG,EAAE,MAAM,EACX,SAAS,EAAE,UAAU,EACrB,gBAAgB,EAAE,UAAU;AAC5B,sDAAsD;AACtD,SAAS,CAAC,EAAE,UAAU,GACrB,MAAM,CAUR;AAID,MAAM,WAAW,mBAAmB;IAClC,KAAK,EAAE,mBAAmB,CAAC;IAC3B,MAAM,CAAC,EAAE,QAAQ,CAAC;IAClB,4BAA4B;IAC5B,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,+CAA+C;IAC/C,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,mBAAmB,GAAG,gBAAgB,CA2B9E;AAID;;;GAGG;AACH,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,KAAK,CAA+B;IAC5C,OAAO,CAAC,SAAS,CAAiC;IAClD,OAAO,CAAC,SAAS,CAAa;IAC9B,OAAO,CAAC,iBAAiB,CAAS;IAClC,OAAO,CAAC,eAAe,CAAS;IAChC,OAAO,CAAC,YAAY,CAAa;IACjC,OAAO,CAAC,SAAS,CAAkB;gBAGjC,SAAS,EAAE,CAAC,EAAE,EAAE,gBAAgB,KAAK,IAAI,EACzC,SAAS,EAAE,MAAM,IAAI,EACrB,iBAAiB,GAAE,MAAc,EACjC,eAAe,GAAE,MAAU;IAQ7B,KAAK,CAAC,SAAS,EAAE,gBAAgB,GAAG,IAAI;IAkBxC,OAAO,CAAC,wBAAwB;IAWhC,IAAI,IAAI,IAAI;CAOb;AAID,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG;IAC/C,GAAG,EAAE,MAAM,CAAC;IACZ,SAAS,EAAE,UAAU,CAAC;IACtB,gBAAgB,EAAE,UAAU,CAAC;IAC7B,SAAS,CAAC,EAAE,UAAU,CAAC;CACxB,CAWA"}
@@ -0,0 +1,151 @@
1
+ "use strict";
2
+ /**
3
+ * Waliwa - QR code generation untuk WhatsApp Web Multi-Device pairing
4
+ *
5
+ * QR code berisi: ref + publicKey + pairingStaticKey (encoded sebagai comma-separated)
6
+ * User scan dengan WhatsApp mobile app untuk establish pairing
7
+ */
8
+ var __importDefault = (this && this.__importDefault) || function (mod) {
9
+ return (mod && mod.__esModule) ? mod : { "default": mod };
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.QRRefreshManager = void 0;
13
+ exports.generateQRRef = generateQRRef;
14
+ exports.buildQRString = buildQRString;
15
+ exports.generateQRCodeData = generateQRCodeData;
16
+ exports.parseQRString = parseQRString;
17
+ const qrcode_terminal_1 = __importDefault(require("qrcode-terminal"));
18
+ const crypto_js_1 = require("../core/crypto.js");
19
+ const logger_js_1 = require("../utils/logger.js");
20
+ // ============== QR Reference Generator ==============
21
+ let qrRefCounter = 0;
22
+ /**
23
+ * Generate new QR reference (server-side correlation ID)
24
+ * Format: 8-character alphanumeric
25
+ */
26
+ function generateQRRef() {
27
+ const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
28
+ let ref = '';
29
+ const rand = (0, crypto_js_1.getRandomBytes)(8);
30
+ for (let i = 0; i < 8; i++) {
31
+ ref += chars[rand[i] % chars.length];
32
+ }
33
+ qrRefCounter++;
34
+ return ref + qrRefCounter.toString(36);
35
+ }
36
+ // ============== QR Encoder ==============
37
+ /**
38
+ * Build QR code string untuk WA pairing
39
+ *
40
+ * Format:
41
+ * ref,publicKey(base64),pairingStaticKey(base64),clientDid,serverDid
42
+ *
43
+ * WhatsApp mobile app akan scan QR, kirim ke server, server pakai publicKey
44
+ * untuk encrypt pairing payload yang berisi identity keys.
45
+ */
46
+ function buildQRString(ref, publicKey, pairingStaticKey,
47
+ /** Client device ID (noise static key fingerprint) */
48
+ clientDid) {
49
+ const pubKeyB64 = Buffer.from(publicKey).toString('base64');
50
+ const pairingB64 = Buffer.from(pairingStaticKey).toString('base64');
51
+ const didB64 = clientDid ? Buffer.from(clientDid).toString('base64') : '';
52
+ // Format: ref,publicKey,pairingStaticKey,clientDid
53
+ if (didB64) {
54
+ return `${ref},${pubKeyB64},${pairingB64},${didB64}`;
55
+ }
56
+ return `${ref},${pubKeyB64},${pairingB64}`;
57
+ }
58
+ /**
59
+ * Generate QR code data dari auth creds
60
+ */
61
+ function generateQRCodeData(opts) {
62
+ const logger = opts.logger ?? new logger_js_1.SilentLogger();
63
+ if (!opts.creds.noiseKey) {
64
+ throw new Error('noiseKey tidak tersedia di creds - generate creds baru');
65
+ }
66
+ const ref = generateQRRef();
67
+ const publicKey = opts.creds.noiseKey.public;
68
+ const pairingStaticKey = opts.creds.pairingKey?.public ?? new Uint8Array(32);
69
+ const qrString = buildQRString(ref, publicKey, pairingStaticKey);
70
+ if (opts.printInTerminal) {
71
+ logger.info('Scan QR code ini dengan WhatsApp mobile app:\n');
72
+ qrcode_terminal_1.default.generate(qrString, { small: opts.small ?? true }, (qr) => {
73
+ console.log(qr);
74
+ });
75
+ }
76
+ return {
77
+ ref,
78
+ publicKey,
79
+ pairingStaticKey,
80
+ qrString,
81
+ timeout: 60 // 60 seconds default
82
+ };
83
+ }
84
+ // ============== QR Refresh Manager ==============
85
+ /**
86
+ * QR refresh manager - auto-refresh QR setiap ~20 detik (sesuai WA server timeout)
87
+ * Untuk menghindari stale QR yang sudah expire
88
+ */
89
+ class QRRefreshManager {
90
+ timer = null;
91
+ onRefresh;
92
+ onTimeout;
93
+ refreshIntervalMs;
94
+ maxRefreshCount;
95
+ refreshCount = 0;
96
+ isRunning = false;
97
+ constructor(onRefresh, onTimeout, refreshIntervalMs = 20000, maxRefreshCount = 5) {
98
+ this.onRefresh = onRefresh;
99
+ this.onTimeout = onTimeout;
100
+ this.refreshIntervalMs = refreshIntervalMs;
101
+ this.maxRefreshCount = maxRefreshCount;
102
+ }
103
+ start(initialQR) {
104
+ if (this.isRunning)
105
+ return;
106
+ this.isRunning = true;
107
+ this.refreshCount = 0;
108
+ this.onRefresh(initialQR);
109
+ this.timer = setInterval(() => {
110
+ this.refreshCount++;
111
+ if (this.refreshCount >= this.maxRefreshCount) {
112
+ this.stop();
113
+ this.onTimeout();
114
+ return;
115
+ }
116
+ // Trigger refresh - caller akan generate new QR dan pass via update
117
+ this.onRefresh(this.generateNewQRPlaceholder());
118
+ }, this.refreshIntervalMs);
119
+ }
120
+ generateNewQRPlaceholder() {
121
+ // Placeholder - actual generation handled by caller
122
+ return {
123
+ ref: generateQRRef(),
124
+ publicKey: new Uint8Array(32),
125
+ pairingStaticKey: new Uint8Array(32),
126
+ qrString: '',
127
+ timeout: 20
128
+ };
129
+ }
130
+ stop() {
131
+ if (this.timer) {
132
+ clearInterval(this.timer);
133
+ this.timer = null;
134
+ }
135
+ this.isRunning = false;
136
+ }
137
+ }
138
+ exports.QRRefreshManager = QRRefreshManager;
139
+ // ============== QR Decoder (untuk reverse direction / debug) ==============
140
+ function parseQRString(qrString) {
141
+ const parts = qrString.split(',');
142
+ if (parts.length < 3) {
143
+ throw new Error('Invalid QR string format');
144
+ }
145
+ const [ref, pubKeyB64, pairingB64, didB64] = parts;
146
+ const publicKey = new Uint8Array(Buffer.from(pubKeyB64, 'base64'));
147
+ const pairingStaticKey = new Uint8Array(Buffer.from(pairingB64, 'base64'));
148
+ const clientDid = didB64 ? new Uint8Array(Buffer.from(didB64, 'base64')) : undefined;
149
+ return { ref, publicKey, pairingStaticKey, clientDid };
150
+ }
151
+ //# sourceMappingURL=qr-code.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"qr-code.js","sourceRoot":"","sources":["../../src/auth/qr-code.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,61 @@
1
+ /**
2
+ * Waliwa - Call handling
3
+ * Process incoming WhatsApp call events (offer, reject, terminate)
4
+ */
5
+ import type { WACallEvent, JIDLike, WALogger } from '../types/index.js';
6
+ import { BinaryNode } from '../core/binary.js';
7
+ export interface CallHandlerOptions {
8
+ send: (data: Uint8Array) => void;
9
+ logger?: WALogger;
10
+ onCall?: (event: WACallEvent) => void;
11
+ /** Auto reject incoming calls */
12
+ autoReject?: boolean;
13
+ }
14
+ /**
15
+ * Handle incoming WhatsApp call events
16
+ * Calls masuk sebagai binary node dengan tag "call"
17
+ */
18
+ export declare class CallHandler {
19
+ private send;
20
+ private logger;
21
+ private onCall?;
22
+ private autoReject;
23
+ constructor(opts: CallHandlerOptions);
24
+ /**
25
+ * Handle call node
26
+ */
27
+ handleCallNode(node: BinaryNode): Promise<void>;
28
+ /**
29
+ * Reject incoming call
30
+ */
31
+ rejectCall(callId: string, from: JIDLike): Promise<void>;
32
+ /**
33
+ * Accept incoming call (voice only, no WebRTC support)
34
+ */
35
+ acceptCall(callId: string, from: JIDLike): Promise<void>;
36
+ /**
37
+ * Set call handler
38
+ */
39
+ setHandler(handler: (event: WACallEvent) => void): void;
40
+ /**
41
+ * Enable/disable auto reject
42
+ */
43
+ setAutoReject(enabled: boolean): void;
44
+ }
45
+ /**
46
+ * Voice message transcription hook
47
+ * Note: WhatsApp punya transcription API tapi memerlukan server-side processing
48
+ */
49
+ export interface VoiceTranscriptionResult {
50
+ callId?: string;
51
+ messageId?: string;
52
+ text: string;
53
+ language?: string;
54
+ confidence?: number;
55
+ }
56
+ /**
57
+ * Transcribe voice message via external service (hook)
58
+ * User harus implement sendiri atau pakai service seperti Whisper
59
+ */
60
+ export type VoiceTranscriptionFn = (audioBuffer: Buffer) => Promise<VoiceTranscriptionResult | null>;
61
+ //# sourceMappingURL=handler.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"handler.d.ts","sourceRoot":"","sources":["../../src/calls/handler.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EACV,WAAW,EAEX,OAAO,EACP,QAAQ,EACT,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAoB,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAIjE,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,CAAC,IAAI,EAAE,UAAU,KAAK,IAAI,CAAC;IACjC,MAAM,CAAC,EAAE,QAAQ,CAAC;IAClB,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,WAAW,KAAK,IAAI,CAAC;IACtC,iCAAiC;IACjC,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED;;;GAGG;AACH,qBAAa,WAAW;IACtB,OAAO,CAAC,IAAI,CAA6B;IACzC,OAAO,CAAC,MAAM,CAAW;IACzB,OAAO,CAAC,MAAM,CAAC,CAA+B;IAC9C,OAAO,CAAC,UAAU,CAAU;gBAEhB,IAAI,EAAE,kBAAkB;IAOpC;;OAEG;IACG,cAAc,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IA4BrD;;OAEG;IACG,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAoB9D;;OAEG;IACG,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAkB9D;;OAEG;IACH,UAAU,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,WAAW,KAAK,IAAI,GAAG,IAAI;IAIvD;;OAEG;IACH,aAAa,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI;CAGtC;AAQD;;;GAGG;AACH,MAAM,WAAW,wBAAwB;IACvC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;;GAGG;AACH,MAAM,MAAM,oBAAoB,GAAG,CAAC,WAAW,EAAE,MAAM,KAAK,OAAO,CAAC,wBAAwB,GAAG,IAAI,CAAC,CAAC"}
@@ -0,0 +1,117 @@
1
+ "use strict";
2
+ /**
3
+ * Waliwa - Call handling
4
+ * Process incoming WhatsApp call events (offer, reject, terminate)
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.CallHandler = void 0;
8
+ const binary_js_1 = require("../core/binary.js");
9
+ const jid_js_1 = require("../utils/jid.js");
10
+ const logger_js_1 = require("../utils/logger.js");
11
+ /**
12
+ * Handle incoming WhatsApp call events
13
+ * Calls masuk sebagai binary node dengan tag "call"
14
+ */
15
+ class CallHandler {
16
+ send;
17
+ logger;
18
+ onCall;
19
+ autoReject;
20
+ constructor(opts) {
21
+ this.send = opts.send;
22
+ this.logger = opts.logger ?? new logger_js_1.SilentLogger();
23
+ this.onCall = opts.onCall;
24
+ this.autoReject = opts.autoReject ?? false;
25
+ }
26
+ /**
27
+ * Handle call node
28
+ */
29
+ async handleCallNode(node) {
30
+ const attrs = node.attrs || {};
31
+ const from = attrs.from;
32
+ const callId = attrs.id;
33
+ const isVideo = attrs.video === 'true';
34
+ const isGroup = attrs.group === 'true' || attrs.is_group === 'true';
35
+ const status = attrs.status || 'ringing';
36
+ const event = {
37
+ id: callId,
38
+ from,
39
+ to: attrs.to,
40
+ isVideo,
41
+ isGroup,
42
+ status,
43
+ timestamp: Date.now(),
44
+ offer: attrs.offer
45
+ };
46
+ this.logger.info(`Incoming ${isVideo ? 'video' : 'voice'} call from ${from} (id: ${callId})`);
47
+ if (this.onCall)
48
+ this.onCall(event);
49
+ // Auto reject jika enabled
50
+ if (this.autoReject && status === 'ringing') {
51
+ await this.rejectCall(callId, from);
52
+ }
53
+ }
54
+ /**
55
+ * Reject incoming call
56
+ */
57
+ async rejectCall(callId, from) {
58
+ const node = {
59
+ tag: 'call',
60
+ attrs: {
61
+ id: callId,
62
+ from: attrs_to_placeholder(),
63
+ to: (0, jid_js_1.jidToString)(from),
64
+ action: 'reject',
65
+ type: 'reject'
66
+ },
67
+ content: undefined
68
+ };
69
+ try {
70
+ this.send((0, binary_js_1.encodeBinaryNode)(node));
71
+ this.logger.info(`Rejected call ${callId}`);
72
+ }
73
+ catch (err) {
74
+ this.logger.error(`Failed to reject call: ${err.message}`);
75
+ }
76
+ }
77
+ /**
78
+ * Accept incoming call (voice only, no WebRTC support)
79
+ */
80
+ async acceptCall(callId, from) {
81
+ const node = {
82
+ tag: 'call',
83
+ attrs: {
84
+ id: callId,
85
+ to: (0, jid_js_1.jidToString)(from),
86
+ action: 'accept',
87
+ type: 'accept'
88
+ }
89
+ };
90
+ try {
91
+ this.send((0, binary_js_1.encodeBinaryNode)(node));
92
+ this.logger.info(`Accepted call ${callId}`);
93
+ }
94
+ catch (err) {
95
+ this.logger.error(`Failed to accept call: ${err.message}`);
96
+ }
97
+ }
98
+ /**
99
+ * Set call handler
100
+ */
101
+ setHandler(handler) {
102
+ this.onCall = handler;
103
+ }
104
+ /**
105
+ * Enable/disable auto reject
106
+ */
107
+ setAutoReject(enabled) {
108
+ this.autoReject = enabled;
109
+ }
110
+ }
111
+ exports.CallHandler = CallHandler;
112
+ // Helper placeholder for "to" field (own JID)
113
+ function attrs_to_placeholder() {
114
+ // Should be set to own JID
115
+ return '';
116
+ }
117
+ //# sourceMappingURL=handler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"handler.js","sourceRoot":"","sources":["../../src/calls/handler.ts"],"names":[],"mappings":"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"}