kage-baileys 3.0.6 → 3.2.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 (216) hide show
  1. package/Example/connection.cjs +4 -0
  2. package/README.MD +4726 -48
  3. package/WAProto/WAProto.proto +3395 -415
  4. package/WAProto/compat.cjs +12 -0
  5. package/WAProto/index.d.ts +47104 -19888
  6. package/WAProto/index.js +131979 -57361
  7. package/lib/Addon/http-error.js +43 -0
  8. package/lib/Addon/index.js +32 -0
  9. package/lib/Addon/keyed-db.js +250 -0
  10. package/lib/Addon/link-preview.js +82 -0
  11. package/lib/Defaults/baileys-version.json +3 -0
  12. package/lib/Defaults/connection.js +110 -0
  13. package/lib/Defaults/constants.js +156 -0
  14. package/lib/Defaults/history.js +46 -0
  15. package/lib/Defaults/index.js +230 -0
  16. package/lib/Defaults/media.js +104 -0
  17. package/lib/Defaults/phonenumber-mcc.json +223 -0
  18. package/lib/Defaults/prefix.js +44 -0
  19. package/lib/Extensions/business-advanced.js +382 -0
  20. package/lib/Extensions/business.js +159 -0
  21. package/lib/Extensions/chats-advanced.js +1106 -0
  22. package/lib/Extensions/chats.js +349 -0
  23. package/lib/Extensions/communities-advanced.js +430 -0
  24. package/lib/Extensions/community.js +94 -0
  25. package/lib/Extensions/groups-advanced.js +343 -0
  26. package/lib/Extensions/index.js +30 -0
  27. package/lib/Extensions/messages-recv-advanced.js +1690 -0
  28. package/lib/Extensions/messages-send-advanced.js +622 -0
  29. package/lib/Extensions/messages-send.js +1380 -0
  30. package/lib/Extensions/newsletter-advanced.js +228 -0
  31. package/lib/Extensions/newsletter.js +72 -0
  32. package/lib/Extensions/socket.js +389 -0
  33. package/lib/Modded/message_builder.js +2084 -4
  34. package/lib/Signal/Group/ciphertext-message.js +54 -0
  35. package/lib/Signal/Group/group-session-builder.js +124 -0
  36. package/lib/Signal/Group/group_cipher.js +216 -0
  37. package/lib/Signal/Group/index.js +124 -0
  38. package/lib/Signal/Group/keyhelper.js +108 -0
  39. package/lib/Signal/Group/sender-chain-key.js +83 -0
  40. package/lib/Signal/Group/sender-key-distribution-message.js +157 -0
  41. package/lib/Signal/Group/sender-key-message.js +166 -0
  42. package/lib/Signal/Group/sender-key-name.js +130 -0
  43. package/lib/Signal/Group/sender-key-record.js +113 -0
  44. package/lib/Signal/Group/sender-key-state.js +208 -0
  45. package/lib/Signal/Group/sender-message-key.js +82 -0
  46. package/lib/Signal/libsignal.js +935 -0
  47. package/lib/Signal/lid-mapping.js +545 -1
  48. package/lib/Socket/Client/index.js +60 -0
  49. package/lib/Socket/Client/types.js +51 -0
  50. package/lib/Socket/Client/websocket.js +152 -0
  51. package/lib/Socket/business.js +831 -0
  52. package/lib/Socket/chats.js +2535 -49
  53. package/lib/Socket/communities.js +450 -1
  54. package/lib/Socket/community.js +1022 -0
  55. package/lib/Socket/dugong.js +1 -1
  56. package/lib/Socket/groups.js +747 -0
  57. package/lib/Socket/index.js +60 -2
  58. package/lib/Socket/messages-recv.js +3450 -5
  59. package/lib/Socket/messages-send.js +3123 -0
  60. package/lib/Socket/mex.js +126 -1
  61. package/lib/Socket/newsletter.js +465 -0
  62. package/lib/Socket/socket.js +2217 -1
  63. package/lib/Store/index.js +79 -0
  64. package/lib/Store/make-cache-manager-store.js +186 -0
  65. package/lib/Store/make-in-memory-store.js +878 -0
  66. package/lib/Store/make-ordered-dictionary.js +187 -0
  67. package/lib/Store/object-repository.js +78 -0
  68. package/lib/Types/Auth.js +25 -0
  69. package/lib/Types/Bussines.js +25 -1
  70. package/lib/Types/Call.js +25 -0
  71. package/lib/Types/Chat.js +39 -0
  72. package/lib/Types/Contact.js +25 -0
  73. package/lib/Types/Events.js +25 -0
  74. package/lib/Types/GroupMetadata.js +25 -0
  75. package/lib/Types/Label.js +76 -0
  76. package/lib/Types/LabelAssociation.js +40 -0
  77. package/lib/Types/Message.js +57 -0
  78. package/lib/Types/Mex.js +56 -1
  79. package/lib/Types/MexUpdates.js +46 -0
  80. package/lib/Types/Newsletter.js +56 -0
  81. package/lib/Types/Product.js +25 -0
  82. package/lib/Types/RichType.js +23 -0
  83. package/lib/Types/Signal.js +25 -0
  84. package/lib/Types/Socket.js +25 -0
  85. package/lib/Types/State.js +92 -0
  86. package/lib/Types/USync.js +25 -0
  87. package/lib/Types/index.js +133 -0
  88. package/lib/Utils/auth-utils.js +703 -0
  89. package/lib/Utils/automation-tools.js +51 -16
  90. package/lib/Utils/baileys-event-stream.js +146 -0
  91. package/lib/Utils/browser-utils.js +95 -0
  92. package/lib/Utils/business.js +525 -0
  93. package/lib/Utils/chat-utils.js +1861 -0
  94. package/lib/Utils/companion-reg-client-utils.js +55 -1
  95. package/lib/Utils/crypto.js +355 -0
  96. package/lib/Utils/decode-wa-message.js +709 -0
  97. package/lib/Utils/event-buffer.js +1323 -8
  98. package/lib/Utils/generics.js +945 -1
  99. package/lib/Utils/history.js +266 -0
  100. package/lib/Utils/identity-change-handler.js +62 -1
  101. package/lib/Utils/index.js +114 -0
  102. package/lib/Utils/link-preview.js +179 -0
  103. package/lib/Utils/logger.js +42 -0
  104. package/lib/Utils/lt-hash.js +73 -0
  105. package/lib/Utils/make-mutex.js +104 -0
  106. package/lib/Utils/message-inspector.js +110 -0
  107. package/lib/Utils/message-retry-manager.js +507 -2
  108. package/lib/Utils/messages-media.js +1931 -1
  109. package/lib/Utils/messages.js +3748 -0
  110. package/lib/Utils/noise-handler.js +423 -0
  111. package/lib/Utils/offline-node-processor.js +53 -1
  112. package/lib/Utils/pre-key-manager.js +255 -1
  113. package/lib/Utils/process-message.js +1592 -0
  114. package/lib/Utils/reporting-utils.js +272 -1
  115. package/lib/Utils/rich-message-utils.js +377 -0
  116. package/lib/Utils/rich-messages.js +1 -1
  117. package/lib/Utils/signal.js +437 -0
  118. package/lib/Utils/stanza-ack.js +51 -1
  119. package/lib/Utils/status-refresh.js +37 -0
  120. package/lib/Utils/status-tools.js +4 -2
  121. package/lib/Utils/sync-action-utils.js +63 -1
  122. package/lib/Utils/tc-token-utils.js +185 -1
  123. package/lib/Utils/terminal-banner.js +31 -0
  124. package/lib/Utils/use-multi-file-auth-state.js +271 -0
  125. package/lib/Utils/use-single-file-auth-state.js +108 -0
  126. package/lib/Utils/use-sqlite-auth-state.js +142 -0
  127. package/lib/Utils/validate-connection.js +497 -1
  128. package/lib/Utils/view-once-compat.js +13 -5
  129. package/lib/VoIP/audio-feeder.js +150 -0
  130. package/lib/VoIP/index.js +289 -0
  131. package/lib/VoIP/relay-transport.js +608 -0
  132. package/lib/VoIP/signaling.js +583 -0
  133. package/lib/VoIP/types.js +30 -0
  134. package/lib/VoIP/wasm-engine.js +1261 -2
  135. package/lib/VoIP/worker-bootstrap.js +1090 -2
  136. package/lib/WABinary/constants.js +2805 -0
  137. package/lib/WABinary/decode.js +649 -2
  138. package/lib/WABinary/encode.js +564 -2
  139. package/lib/WABinary/generic-utils.js +401 -0
  140. package/lib/WABinary/index.js +82 -0
  141. package/lib/WABinary/jid-utils.js +290 -0
  142. package/lib/WABinary/types.js +25 -0
  143. package/lib/WAM/BinaryInfo.js +50 -0
  144. package/lib/WAM/constants.js +45747 -0
  145. package/lib/WAM/encode.js +393 -0
  146. package/lib/WAM/index.js +78 -0
  147. package/lib/WAUSync/Protocols/USyncBotProfileProtocol.js +135 -0
  148. package/lib/WAUSync/Protocols/USyncContactProtocol.js +110 -0
  149. package/lib/WAUSync/Protocols/USyncDeviceProtocol.js +142 -0
  150. package/lib/WAUSync/Protocols/USyncDisappearingModeProtocol.js +85 -0
  151. package/lib/WAUSync/Protocols/USyncLIDProtocol.js +69 -0
  152. package/lib/WAUSync/Protocols/USyncStatusProtocol.js +107 -0
  153. package/lib/WAUSync/Protocols/USyncUsernameProtocol.js +38 -1
  154. package/lib/WAUSync/Protocols/index.js +83 -0
  155. package/lib/WAUSync/USyncQuery.js +241 -2
  156. package/lib/WAUSync/USyncUser.js +86 -0
  157. package/lib/WAUSync/index.js +78 -0
  158. package/lib/assets/wasm/loader.js +1875 -1
  159. package/lib/assets/wasm/worker-modules.js +11047 -1
  160. package/lib/index.d.ts +126 -0
  161. package/lib/index.js +53 -21
  162. package/lib/index.mjs +437 -0
  163. package/licenses/upstream-MIT.txt +22 -0
  164. package/maintenance/api-coverage.json +1642 -0
  165. package/maintenance/archivos-sha256.json +207 -0
  166. package/maintenance/consumer-validation.log +3 -0
  167. package/maintenance/dependency-audit.json +4 -4
  168. package/maintenance/extension-inventory.json +57 -0
  169. package/maintenance/protocol-update.json +1101 -0
  170. package/maintenance/protocol-wire-audit.json +4 -0
  171. package/maintenance/reference-socket-surface.json +209 -0
  172. package/maintenance/resumen-validacion.json +50 -0
  173. package/maintenance/validation.log +2725 -0
  174. package/maintenance/verification.json +566 -0
  175. package/package.json +107 -9
  176. package/scripts/check-imports.cjs +10 -0
  177. package/scripts/check-package.cjs +40 -0
  178. package/scripts/check-syntax.cjs +1 -1
  179. package/scripts/generate-protobuf.cjs +6 -1
  180. package/scripts/generate-public-types.cjs +9 -0
  181. package/scripts/kage-base64-fix.cjs +45 -0
  182. package/scripts/maintenance.cjs +10 -0
  183. package/test/advanced.test.cjs +24 -0
  184. package/test/base64-fix.test.cjs +49 -0
  185. package/test/maintenance.test.cjs +1 -1
  186. package/test/npm-publication.test.cjs +141 -0
  187. package/test/recepcion-reparada.test.cjs +98 -0
  188. package/test/resilience-binary.test.cjs +69 -0
  189. package/test/resilience-transport.test.cjs +34 -0
  190. package/test/types.test.ts +5 -0
  191. package/test/upgrade.test.cjs +104 -0
  192. package/tsconfig.json +20 -0
  193. package/WAProto/p.html +0 -1
  194. package/lib/KageExtra/Modded/message_builder.js +0 -2330
  195. package/lib/KageExtra/VoIP/audio-feeder.js +0 -136
  196. package/lib/KageExtra/VoIP/index.js +0 -282
  197. package/lib/KageExtra/VoIP/relay-transport.js +0 -559
  198. package/lib/KageExtra/VoIP/signaling.js +0 -603
  199. package/lib/KageExtra/VoIP/types.js +0 -17
  200. package/lib/KageExtra/VoIP/wasm-engine.js +0 -1214
  201. package/lib/KageExtra/VoIP/worker-bootstrap.js +0 -1042
  202. package/lib/KageExtra/assets/wasm/loader.js +0 -5
  203. package/lib/KageExtra/assets/wasm/whatsapp.wasm +0 -0
  204. package/lib/KageExtra/assets/wasm/worker-modules.js +0 -273
  205. package/lib/KageExtra/index.js +0 -3
  206. package/lib/KageExtra/package.json +0 -1
  207. package/lib/WAUSync/Protocols/UsyncBotProfileProtocol.js +0 -53
  208. package/lib/WAUSync/Protocols/UsyncLIDProtocol.js +0 -24
  209. package/maintenance/revision-full-check.txt +0 -1097
  210. package/maintenance/revision-library-tests.tap +0 -1088
  211. package/maintenance/revision-protobuf.txt +0 -5
  212. package/maintenance/revision-syntax.txt +0 -5
  213. package/maintenance/schema-coverage.json +0 -23
  214. package/maintenance/schema-merge.json +0 -30
  215. package/maintenance/validation-node20.txt +0 -191
  216. package/maintenance/validation-node22.txt +0 -237
@@ -49,3 +49,76 @@ class d {
49
49
  }
50
50
  }
51
51
  exports.LT_HASH_ANTI_TAMPERING = new d('WhatsApp Patch Integrity');
52
+
53
+ // Kage: compatibilidad de API.
54
+ const __kageModule70 = (() => {
55
+ const module = { exports: {} }; const exports = module.exports;
56
+ "use strict"
57
+
58
+ Object.defineProperty(exports, "__esModule", { value: true })
59
+
60
+ const { hkdf } = require("./crypto")
61
+
62
+ /**
63
+ * LT Hash is a summation based hash algorithm that maintains the integrity of a piece of data
64
+ * over a series of mutations. You can add/remove mutations and it'll return a hash equal to
65
+ * if the same series of mutations was made sequentially.
66
+ */
67
+ const o = 128
68
+
69
+ class LTHash {
70
+ constructor(e) {
71
+ this.salt = e
72
+ }
73
+
74
+ async add(e, t) {
75
+ for (const item of t) {
76
+ e = await this._addSingle(e, item)
77
+ }
78
+ return e
79
+ }
80
+
81
+ async subtract(e, t) {
82
+ for (const item of t) {
83
+ e = await this._subtractSingle(e, item)
84
+ }
85
+ return e
86
+ }
87
+
88
+ async subtractThenAdd(e, addList, subtractList) {
89
+ const subtracted = await this.subtract(e, subtractList)
90
+ return this.add(subtracted, addList)
91
+ }
92
+
93
+ async _addSingle(e, t) {
94
+ const derived = new Uint8Array(await hkdf(Buffer.from(t), o, { info: this.salt })).buffer
95
+ return this.performPointwiseWithOverflow(e, derived, (a, b) => a + b)
96
+ }
97
+
98
+ async _subtractSingle(e, t) {
99
+ const derived = new Uint8Array(await hkdf(Buffer.from(t), o, { info: this.salt })).buffer
100
+ return this.performPointwiseWithOverflow(e, derived, (a, b) => a - b)
101
+ }
102
+
103
+ performPointwiseWithOverflow(e, t, op) {
104
+ const n = new DataView(e)
105
+ const i = new DataView(t)
106
+ const out = new ArrayBuffer(n.byteLength)
107
+ const s = new DataView(out)
108
+ for (let offset = 0; offset < n.byteLength; offset += 2) {
109
+ s.setUint16(offset, op(n.getUint16(offset, true), i.getUint16(offset, true)), true)
110
+ }
111
+ return out
112
+ }
113
+ }
114
+
115
+ const LT_HASH_ANTI_TAMPERING = new LTHash('WhatsApp Patch Integrity')
116
+
117
+ module.exports = {
118
+ LT_HASH_ANTI_TAMPERING
119
+ }
120
+ return module.exports;
121
+ })();
122
+ for (const key of Object.keys(__kageModule70)) {
123
+ if (key !== '__esModule' && !Object.prototype.hasOwnProperty.call(exports,key)) Object.defineProperty(exports,key,{enumerable:true,configurable:true,get:()=>__kageModule70[key]});
124
+ }
@@ -41,3 +41,107 @@ const makeKeyedMutex = () => {
41
41
  };
42
42
  };
43
43
  exports.makeKeyedMutex = makeKeyedMutex;
44
+
45
+ // Kage: compatibilidad de API.
46
+ const __kageModule71 = (() => {
47
+ const module = { exports: {} }; const exports = module.exports;
48
+ "use strict"
49
+
50
+ Object.defineProperty(exports, "__esModule", { value: true })
51
+
52
+ const { Mutex: AsyncMutex } = require("async-mutex")
53
+
54
+ const makeMutex = () => {
55
+ const mutex = new AsyncMutex()
56
+ return {
57
+ mutex(code) {
58
+ return mutex.runExclusive(code)
59
+ }
60
+ }
61
+ }
62
+
63
+ const makeKeyedMutex = () => {
64
+ const map = new Map()
65
+ return {
66
+ async mutex(key, task) {
67
+ let entry = map.get(key)
68
+
69
+ if (!entry) {
70
+ entry = { mutex: new AsyncMutex(), refCount: 0 }
71
+ map.set(key, entry)
72
+ }
73
+
74
+ entry.refCount++
75
+
76
+ try {
77
+ return await entry.mutex.runExclusive(task)
78
+ }
79
+ finally {
80
+ entry.refCount--
81
+
82
+ // only delete it if this is still the current entry
83
+ if (entry.refCount === 0 && map.get(key) === entry) {
84
+ map.delete(key)
85
+ }
86
+ }
87
+ }
88
+ }
89
+ }
90
+
91
+ module.exports = {
92
+ makeMutex,
93
+ makeKeyedMutex
94
+ }
95
+ return module.exports;
96
+ })();
97
+ for (const key of Object.keys(__kageModule71)) {
98
+ if (key !== '__esModule' && !Object.prototype.hasOwnProperty.call(exports,key)) Object.defineProperty(exports,key,{enumerable:true,configurable:true,get:()=>__kageModule71[key]});
99
+ }
100
+
101
+ // Kage: funciones avanzadas.
102
+ const __kageModule175 = (() => {
103
+ const module = { exports: {} }; const exports = module.exports;
104
+ "use strict";
105
+ Object.defineProperty(exports, "__esModule", { value: true });
106
+ exports.makeKeyedMutex = exports.makeMutex = void 0;
107
+ const index_js_1 = require("../Addon/index.js");
108
+ const makeMutex = () => {
109
+ const mutex = (0, index_js_1.createMutex)();
110
+ return {
111
+ mutex(code) {
112
+ return mutex.runExclusive(code);
113
+ }
114
+ };
115
+ };
116
+ exports.makeMutex = makeMutex;
117
+ const makeKeyedMutex = () => {
118
+ const map = new Map();
119
+ return {
120
+ async mutex(key, task) {
121
+ let entry = map.get(key);
122
+ if (!entry) {
123
+ entry = { mutex: (0, index_js_1.createMutex)(), refCount: 0 };
124
+ map.set(key, entry);
125
+ }
126
+ entry.refCount++;
127
+ try {
128
+ return await entry.mutex.runExclusive(task);
129
+ }
130
+ finally {
131
+ entry.refCount--;
132
+ // only delete it if this is still the current entry
133
+ if (entry.refCount === 0 && map.get(key) === entry) {
134
+ map.delete(key);
135
+ }
136
+ }
137
+ }
138
+ };
139
+ };
140
+ exports.makeKeyedMutex = makeKeyedMutex;
141
+
142
+ return module.exports;
143
+ })();
144
+ for (const key of Object.keys(__kageModule175)) {
145
+ if (key !== '__esModule' && !Object.prototype.hasOwnProperty.call(exports,key)) Object.defineProperty(exports,key,{enumerable:true,configurable:true,get:()=>__kageModule175[key]});
146
+ }
147
+ Object.defineProperty(exports, Symbol.for('kage.advanced'), {value:__kageModule175, configurable:true});
@@ -0,0 +1,110 @@
1
+ 'use strict';
2
+ const states = new WeakMap();
3
+ const wrappers = ['deviceSentMessage', 'ephemeralMessage', 'viewOnceMessage', 'viewOnceMessageV2', 'viewOnceMessageV2Extension', 'documentWithCaptionMessage', 'editedMessage', 'statusMentionMessage', 'groupStatusMentionMessage', 'groupStatusMessage', 'groupStatusMessageV2'];
4
+ const labels = { conversation:'Texto', extendedTextMessage:'Texto', imageMessage:'Imagen', videoMessage:'Video', audioMessage:'Audio', documentMessage:'Documento', stickerMessage:'Sticker', reactionMessage:'Reacción', encReactionMessage:'Reacción cifrada', contactMessage:'Contacto', contactsArrayMessage:'Contactos', locationMessage:'Ubicación', liveLocationMessage:'Ubicación en vivo', pollCreationMessage:'Encuesta', pollCreationMessageV2:'Encuesta', pollCreationMessageV3:'Encuesta', pollUpdateMessage:'Voto de encuesta', protocolMessage:'Protocolo', interactiveMessage:'Interactivo', interactiveResponseMessage:'Respuesta interactiva', buttonsResponseMessage:'Respuesta de botón', listResponseMessage:'Respuesta de lista', eventMessage:'Evento programado', call:'Llamada', scheduledCallCreationMessage:'Llamada programada' };
5
+ const clean = jid => (typeof jid === 'string' ? jid.slice(0,256) : '').replace(/:\d+@/, '@');
6
+ const numeric = n => { try { const value = Number(n?.toNumber?.() ?? n ?? 0); return Number.isFinite(value) ? value : 0; } catch { return 0; } };
7
+ function inspectMessage(raw = {}) {
8
+ raw = raw && typeof raw === 'object' ? raw : {};
9
+ let message = raw.message || raw.fakeObj?.message || {};
10
+ if (!message || typeof message !== 'object' || ArrayBuffer.isView(message)) message = {};
11
+ const visited = new WeakSet();
12
+ const layers = [];
13
+ for (let i=0; i<16; i++) {
14
+ if (!message || typeof message !== 'object' || visited.has(message)) { message = {}; break; }
15
+ visited.add(message);
16
+ const wrapper = wrappers.find(k => message[k]?.message);
17
+ if (!wrapper) break;
18
+ layers.push(wrapper); message = message[wrapper].message;
19
+ }
20
+ const keys = Object.keys(message).filter(k => message[k] != null && !['messageContextInfo','senderKeyDistributionMessage','fastRatchetKeySenderKeyDistributionMessage'].includes(k));
21
+ const type = keys.find(k => labels[k]) || keys[0] || '';
22
+ const value = typeof message[type] === 'object' ? message[type] : {};
23
+ const context = value?.contextInfo || {};
24
+ const key = raw.key || raw.fakeObj?.key || {};
25
+ const chat = clean(key.remoteJid || raw.chat);
26
+ const group = chat.endsWith('@g.us');
27
+ const stubType = numeric(raw.messageStubType);
28
+ const encrypted = stubType === 2 && !type;
29
+ const viewOnce = layers.some(k=>k.startsWith('viewOnce')) || value?.viewOnce === true;
30
+ const text = typeof message[type] === 'string' ? message[type] : value?.text || value?.caption || '';
31
+ return {
32
+ id: typeof (key.id || raw.id) === 'string' ? (key.id || raw.id).slice(0,256) : null, chat, chatAlt: clean(key.remoteJidAlt) || null,
33
+ sender: clean(key.participant || raw.participant || raw.sender || (!key.fromMe && !group && chat !== 'status@broadcast' ? chat : '')) || null,
34
+ senderAlt: clean(key.participantAlt) || null, fromMe: !!key.fromMe,
35
+ route: chat === 'status@broadcast' ? 'estado' : group ? 'grupo' : chat.endsWith('@newsletter') ? 'canal' : /@(s\.whatsapp\.net|lid)$/.test(chat) ? 'privado' : 'sistema',
36
+ type: type || (encrypted ? 'ciphertext' : stubType ? 'stub' : 'unknown'),
37
+ label: encrypted ? 'Mensaje cifrado pendiente de descifrar' : labels[type] || (stubType ? 'Aviso del sistema' : type || 'Sin contenido'),
38
+ wrappers: layers, viewOnce, ephemeral: layers.includes('ephemeralMessage') || numeric(context.expiration)>0,
39
+ ptt: !!value?.ptt, gif: !!value?.gifPlayback, mime: typeof value?.mimetype === 'string' ? value.mimetype.slice(0,256) : null,
40
+ bytes: numeric(value?.fileLength) || (typeof text === 'string' ? Buffer.byteLength(text) : 0),
41
+ width: numeric(value?.width), height: numeric(value?.height), seconds: numeric(value?.seconds),
42
+ timestamp: numeric(raw.messageTimestamp), stubType: stubType || null,
43
+ quotedId: typeof context.stanzaId === 'string' ? context.stanzaId.slice(0,256) : null, mentions: (Array.isArray(context.mentionedJid) ? context.mentionedJid : []).slice(0,100).filter(j => typeof j === 'string'),
44
+ forwarded: !!context.isForwarded, forwardingScore: numeric(context.forwardingScore),
45
+ downloadable: !!(value?.mediaKey && (value?.directPath || value?.url)), encrypted,
46
+ receivedAt: Date.now()
47
+ };
48
+ }
49
+ function stateFor(conn) {
50
+ let state=states.get(conn);
51
+ if(!state){state={events:[],messages:new Map(),counts:{},listeners:[],stopped:false};states.set(conn,state);}
52
+ return state;
53
+ }
54
+ function rememberMessage(conn, raw) {
55
+ const info=inspectMessage(raw); const state=stateFor(conn);
56
+ if(info.id){
57
+ const key=JSON.stringify([info.chat,info.sender,info.id,info.fromMe]);
58
+ const previous=state.messages.get(key) || [...state.messages.values()].find(item=>item.chat===info.chat&&item.id===info.id&&item.fromMe===info.fromMe);
59
+ if (!info.timestamp && previous) info.timestamp=previous.timestamp;
60
+ if (!info.sender && previous) info.sender=previous.sender;
61
+ state.messages.set(key,info);
62
+ }
63
+ for(const [key,info] of state.messages) if(Date.now()-info.receivedAt>86400000) state.messages.delete(key);
64
+ while(state.messages.size>1000) state.messages.delete(state.messages.keys().next().value);
65
+ return info;
66
+ }
67
+ function installMessageInspector(conn, options={}) {
68
+ const state=stateFor(conn);
69
+ if(state.stop && !state.stopped) return state.stop;
70
+ state.stopped=false;
71
+ const record=(kind,detail)=>{
72
+ const event={kind,time:Date.now(),...detail};
73
+ state.events.push(event); while(state.events.length>100) state.events.shift();
74
+ state.counts[kind]=(state.counts[kind]||0)+1;
75
+ conn.ev.emit('kage.event',event);
76
+ if(typeof options.onEvent==='function') { try{options.onEvent(event);}catch(error){conn.logger?.warn?.({error:error.message},'event monitor callback');} }
77
+ };
78
+ const bind=(name,callback)=>{conn.ev.on(name,callback);state.listeners.push([name,callback]);};
79
+ bind('messages.upsert',data=>{for(const raw of data?.messages||[]) record('message',rememberMessage(conn,raw));});
80
+ bind('messaging-history.set',data=>{for(const raw of data?.messages||[]) rememberMessage(conn,raw);record('history',{count:data?.messages?.length||0});});
81
+ bind('messages.update',items=>{for(const item of items||[]) {
82
+ if(item.update?.message) record('message.updated',rememberMessage(conn,{...item.update,key:item.key}));
83
+ else record('message.receipt',{id:item.key?.id,chat:clean(item.key?.remoteJid),status:item.update?.status ?? null,deleted:item.update?.message===null});
84
+ }});
85
+ bind('messages.delete',data=>record('message.deleted',{keys:(data?.keys||[]).slice(0,100).map(k=>({id:k.id,chat:clean(k.remoteJid)})),all:!!data?.all}));
86
+ bind('messages.reaction',items=>{for(const item of items||[]) record('reaction',{id:item.key?.id,chat:clean(item.key?.remoteJid),emoji:item.reaction?.text||''});});
87
+ bind('message-receipt.update',items=>{for(const item of items||[]) record('receipt',{id:item.key?.id,chat:clean(item.key?.remoteJid),user:clean(item.receipt?.userJid)});});
88
+ bind('call',calls=>{for(const call of calls||[]) record('call',{id:call.id,chat:clean(call.chatId||call.from),from:clean(call.from),status:call.status,isVideo:!!call.isVideo,isGroup:!!call.isGroup});});
89
+ bind('presence.update',data=>record('presence',{chat:clean(data?.id),users:Object.entries(data?.presences||{}).slice(0,30).map(([jid,p])=>({jid:clean(jid),state:p?.lastKnownPresence}))}));
90
+ bind('group-participants.update',data=>record('group.participants',{chat:clean(data?.id),action:data?.action,participants:(data?.participants||[]).slice(0,100).map(p=>typeof p==='string'?p:p.id)}));
91
+ bind('groups.update',items=>{for(const item of items||[])record('group.updated',{chat:clean(item.id),fields:Object.keys(item).filter(k=>k!=='id')});});
92
+ bind('chats.upsert',items=>record('chats.upsert',{chats:(items||[]).map(item=>clean(item.id)).slice(0,100)}));
93
+ bind('chats.update',items=>record('chats.update',{chats:(items||[]).map(item=>clean(item.id)).slice(0,100)}));
94
+ bind('contacts.upsert',items=>record('contacts.upsert',{count:items?.length||0}));
95
+ bind('contacts.update',items=>record('contacts.update',{count:items?.length||0}));
96
+ bind('kage.automation',data=>record('automation.'+String(data.kind||'media'),{id:data.id,chat:clean(data.chat),outcome:data.outcome,error:data.error||null}));
97
+ bind('kage.unsupported-message',data=>record('unsupported',{id:data?.id,chat:clean(data?.chat),encryption:data?.encryption,reason:data?.reason}));
98
+ bind('connection.update',data=>{record('connection',{connection:data.connection||null,receivedPendingNotifications:data.receivedPendingNotifications??null});if(data.connection==='close')state.stop();});
99
+ state.stop=()=>{if(state.stopped)return;state.stopped=true;for(const [name,fn]of state.listeners)conn.ev.off(name,fn);state.listeners=[];};
100
+ return state.stop;
101
+ }
102
+ function getMessageDiagnostics(conn) {
103
+ const state=stateFor(conn);
104
+ // Never expose references to internal mutable buffers or credentials.
105
+ return JSON.parse(JSON.stringify({active:!!state.stop&&!state.stopped,counts:state.counts,recent:state.events, messages:[...state.messages.values()]}));
106
+ }
107
+ exports.inspectMessage=inspectMessage;
108
+ exports.rememberMessage=rememberMessage;
109
+ exports.installMessageInspector=installMessageInspector;
110
+ exports.getMessageDiagnostics=getMessageDiagnostics;