@fer2809fl/baileys 7.0.4 → 7.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. package/README.md +347 -50
  2. package/lib/Defaults/index.js +1 -1
  3. package/lib/Modded/message_builder.js +2356 -0
  4. package/lib/Socket/chats.d.ts +14 -0
  5. package/lib/Socket/chats.js +48 -0
  6. package/lib/Socket/index.d.ts +17 -0
  7. package/lib/Socket/messages-send.d.ts +18 -0
  8. package/lib/Socket/messages-send.js +50 -2
  9. package/lib/Utils/anti-ban.d.ts +41 -0
  10. package/lib/Utils/anti-ban.js +182 -0
  11. package/lib/Utils/banner.d.ts +8 -0
  12. package/lib/Utils/banner.js +76 -0
  13. package/lib/Utils/bot-utils.d.ts +57 -0
  14. package/lib/Utils/bot-utils.js +241 -0
  15. package/lib/Utils/enhanced-cache.d.ts +40 -0
  16. package/lib/Utils/enhanced-cache.js +242 -0
  17. package/lib/Utils/enhanced-logger.d.ts +41 -0
  18. package/lib/Utils/enhanced-logger.js +185 -0
  19. package/lib/Utils/index.d.ts +14 -0
  20. package/lib/Utils/index.js +13 -0
  21. package/lib/Utils/lid-utils.d.ts +139 -0
  22. package/lib/Utils/lid-utils.js +503 -0
  23. package/lib/Utils/message-queue.d.ts +47 -0
  24. package/lib/Utils/message-queue.js +226 -0
  25. package/lib/Utils/rich-message-utils.d.ts +21 -0
  26. package/lib/Utils/rich-message-utils.js +229 -0
  27. package/lib/Utils/rich-messages.d.ts +52 -0
  28. package/lib/Utils/rich-messages.js +185 -0
  29. package/lib/Utils/scheduled-messages.d.ts +122 -0
  30. package/lib/Utils/scheduled-messages.js +289 -0
  31. package/lib/Utils/smart-reconnect.d.ts +48 -0
  32. package/lib/Utils/smart-reconnect.js +207 -0
  33. package/lib/Utils/use-sqlite-auth-state.d.ts +11 -0
  34. package/lib/Utils/use-sqlite-auth-state.js +95 -0
  35. package/lib/VoIP/audio-feeder.d.ts +15 -0
  36. package/lib/VoIP/audio-feeder.js +132 -0
  37. package/lib/VoIP/index.js +277 -0
  38. package/lib/VoIP/relay-transport.d.ts +43 -0
  39. package/lib/VoIP/relay-transport.js +559 -0
  40. package/lib/VoIP/signaling.js +594 -0
  41. package/lib/VoIP/types.d.ts +69 -0
  42. package/lib/VoIP/types.js +17 -0
  43. package/lib/VoIP/wasm-engine.d.ts +103 -0
  44. package/lib/VoIP/wasm-engine.js +1214 -0
  45. package/lib/VoIP/worker-bootstrap.js +1042 -0
  46. package/lib/assets/wasm/loader.js +5 -0
  47. package/lib/assets/wasm/whatsapp.wasm +0 -0
  48. package/lib/assets/wasm/worker-modules.js +273 -0
  49. package/lib/index.d.ts +41 -0
  50. package/lib/index.js +3 -0
  51. package/package.json +10 -2
@@ -0,0 +1,226 @@
1
+ import { LRUCache } from 'lru-cache';
2
+
3
+ const PRIORITY = {
4
+ CRITICAL: 0,
5
+ HIGH: 1,
6
+ NORMAL: 2,
7
+ LOW: 3,
8
+ BACKGROUND: 4
9
+ };
10
+
11
+ const QUEUE_CONFIG = {
12
+ MAX_QUEUE_SIZE: 1000,
13
+ PROCESS_INTERVAL: 50,
14
+ RATE_LIMITS: {
15
+ message: { count: 100, window: 60000 },
16
+ group: { count: 40, window: 60000 },
17
+ media: { count: 50, window: 60000 },
18
+ broadcast: { count: 200, window: 3600000 }
19
+ },
20
+ DELAYS: {
21
+ message: 300,
22
+ group: 500,
23
+ media: 800,
24
+ broadcast: 1500
25
+ }
26
+ };
27
+
28
+ class QueueItem {
29
+ constructor(task, priority = PRIORITY.NORMAL, metadata = {}) {
30
+ this.id = `${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
31
+ this.task = task;
32
+ this.priority = priority;
33
+ this.metadata = metadata;
34
+ this.createdAt = Date.now();
35
+ this.attempts = 0;
36
+ this.maxAttempts = metadata.maxAttempts || 3;
37
+ this.status = 'pending';
38
+ }
39
+ }
40
+
41
+ class MessageQueue {
42
+ constructor(logger, config = {}) {
43
+ this.logger = logger;
44
+ this.config = { ...QUEUE_CONFIG, ...config };
45
+ this.queue = [];
46
+ this.processing = false;
47
+ this.paused = false;
48
+ this.rateLimiters = new Map();
49
+ this.processTimer = null;
50
+ this.stats = {
51
+ totalQueued: 0,
52
+ totalProcessed: 0,
53
+ totalFailed: 0,
54
+ averageWaitTime: 0
55
+ };
56
+ this.recentMessages = new LRUCache({ max: 500, ttl: 300000 });
57
+ }
58
+
59
+ enqueue(task, priority = PRIORITY.NORMAL, metadata = {}) {
60
+ if (this.queue.length >= this.config.MAX_QUEUE_SIZE) {
61
+ this.logger?.warn('Queue is full, dropping oldest low priority items');
62
+ this._dropLowPriority();
63
+ }
64
+ const item = new QueueItem(task, priority, metadata);
65
+ const hash = this._hashTask(task, metadata);
66
+ if (this.recentMessages.has(hash) && !metadata.allowDuplicate) {
67
+ this.logger?.debug({ hash }, 'Duplicate message detected, skipping');
68
+ return null;
69
+ }
70
+ let inserted = false;
71
+ for (let i = 0; i < this.queue.length; i++) {
72
+ if (this.queue[i].priority > priority) {
73
+ this.queue.splice(i, 0, item);
74
+ inserted = true;
75
+ break;
76
+ }
77
+ }
78
+ if (!inserted) this.queue.push(item);
79
+ this.stats.totalQueued++;
80
+ this.recentMessages.set(hash, true);
81
+ this.logger?.debug({ id: item.id, priority, queueSize: this.queue.length }, 'Task enqueued');
82
+ if (!this.processing && !this.paused) this._startProcessing();
83
+ return item.id;
84
+ }
85
+
86
+ _hashTask(task, metadata) {
87
+ const data = JSON.stringify({ jid: metadata.jid, content: typeof task === 'function' ? metadata.contentHash : task });
88
+ return Buffer.from(data).toString('base64').substr(0, 32);
89
+ }
90
+
91
+ _dropLowPriority() {
92
+ this.queue.sort((a, b) => b.priority - a.priority);
93
+ const toDrop = Math.ceil(this.queue.length * 0.1);
94
+ const dropped = this.queue.splice(0, toDrop);
95
+ this.logger?.warn({ dropped: dropped.length }, 'Dropped low priority items');
96
+ }
97
+
98
+ _startProcessing() {
99
+ if (this.processTimer) return;
100
+ this.processing = true;
101
+ this.processTimer = setInterval(() => this._processNext(), this.config.PROCESS_INTERVAL);
102
+ }
103
+
104
+ _stopProcessing() {
105
+ if (this.processTimer) {
106
+ clearInterval(this.processTimer);
107
+ this.processTimer = null;
108
+ }
109
+ this.processing = false;
110
+ }
111
+
112
+ async _processNext() {
113
+ if (this.paused || this.queue.length === 0) {
114
+ if (this.queue.length === 0) this._stopProcessing();
115
+ return;
116
+ }
117
+ const item = this.queue.shift();
118
+ if (!item) return;
119
+ item.status = 'processing';
120
+ item.attempts++;
121
+ const waitTime = Date.now() - item.createdAt;
122
+ this._updateAverageWaitTime(waitTime);
123
+ try {
124
+ const type = item.metadata.type || 'message';
125
+ await this._checkRateLimit(type, item.metadata.jid);
126
+ const result = typeof item.task === 'function' ? await item.task() : item.task;
127
+ item.status = 'completed';
128
+ this.stats.totalProcessed++;
129
+ this.logger?.debug({ id: item.id, waitTime }, 'Task completed');
130
+ const delay = this.config.DELAYS[type] || this.config.DELAYS.message;
131
+ await this._delay(delay);
132
+ return result;
133
+ } catch (error) {
134
+ this.logger?.error({ id: item.id, error: error.message }, 'Task failed');
135
+ if (item.attempts < item.maxAttempts) {
136
+ item.priority = Math.min(item.priority + 1, PRIORITY.BACKGROUND);
137
+ item.status = 'pending';
138
+ this.queue.push(item);
139
+ this.logger?.debug({ id: item.id, attempts: item.attempts }, 'Task re-queued');
140
+ } else {
141
+ item.status = 'failed';
142
+ this.stats.totalFailed++;
143
+ this.logger?.warn({ id: item.id }, 'Task permanently failed');
144
+ }
145
+ }
146
+ }
147
+
148
+ async _checkRateLimit(type, jid) {
149
+ const limit = this.config.RATE_LIMITS[type] || this.config.RATE_LIMITS.message;
150
+ const key = jid ? `${type}:${jid}` : type;
151
+ if (!this.rateLimiters.has(key)) this.rateLimiters.set(key, []);
152
+ const timestamps = this.rateLimiters.get(key);
153
+ const now = Date.now();
154
+ const valid = timestamps.filter(ts => now - ts < limit.window);
155
+ this.rateLimiters.set(key, valid);
156
+ if (valid.length >= limit.count) {
157
+ const oldestValid = valid[valid.length - limit.count];
158
+ const waitTime = limit.window - (now - oldestValid);
159
+ if (waitTime > 0) {
160
+ this.logger?.debug({ key, waitTime }, 'Rate limited, waiting');
161
+ await this._delay(waitTime);
162
+ }
163
+ }
164
+ valid.push(now);
165
+ }
166
+
167
+ _updateAverageWaitTime(newTime) {
168
+ const total = this.stats.totalProcessed;
169
+ this.stats.averageWaitTime = (this.stats.averageWaitTime * total + newTime) / (total + 1);
170
+ }
171
+
172
+ _delay(ms) {
173
+ return new Promise(resolve => setTimeout(resolve, ms));
174
+ }
175
+
176
+ pause() {
177
+ this.paused = true;
178
+ this.logger?.info('Queue paused');
179
+ }
180
+
181
+ resume() {
182
+ this.paused = false;
183
+ if (this.queue.length > 0 && !this.processing) this._startProcessing();
184
+ this.logger?.info('Queue resumed');
185
+ }
186
+
187
+ clear(priority = null) {
188
+ if (priority !== null) this.queue = this.queue.filter(item => item.priority !== priority);
189
+ else this.queue = [];
190
+ this.logger?.info({ cleared: true, remaining: this.queue.length }, 'Queue cleared');
191
+ }
192
+
193
+ getStats() {
194
+ return {
195
+ ...this.stats,
196
+ currentQueueSize: this.queue.length,
197
+ isProcessing: this.processing,
198
+ isPaused: this.paused,
199
+ pendingByPriority: {
200
+ critical: this.queue.filter(i => i.priority === PRIORITY.CRITICAL).length,
201
+ high: this.queue.filter(i => i.priority === PRIORITY.HIGH).length,
202
+ normal: this.queue.filter(i => i.priority === PRIORITY.NORMAL).length,
203
+ low: this.queue.filter(i => i.priority === PRIORITY.LOW).length,
204
+ background: this.queue.filter(i => i.priority === PRIORITY.BACKGROUND).length
205
+ }
206
+ };
207
+ }
208
+
209
+ cleanup() {
210
+ this._stopProcessing();
211
+ this.queue = [];
212
+ this.rateLimiters.clear();
213
+ }
214
+ }
215
+
216
+ function createMessageQueue(logger, customConfig = {}) {
217
+ return new MessageQueue(logger, customConfig);
218
+ }
219
+
220
+ export {
221
+ PRIORITY,
222
+ QUEUE_CONFIG,
223
+ QueueItem,
224
+ MessageQueue,
225
+ createMessageQueue
226
+ };
@@ -0,0 +1,21 @@
1
+ export declare function toUnified(submessages: any[], uuid?: string): { response_id: string; sections: any[] };
2
+
3
+ export interface RichResponseContent {
4
+ headerText?: string;
5
+ contentText?: string;
6
+ footerText?: string;
7
+ disclaimerText?: string;
8
+ code?: string;
9
+ language?: string;
10
+ table?: any[][];
11
+ title?: string;
12
+ noHeading?: boolean;
13
+ links?: Array<{ text: string; url?: string; title?: string; displayName?: string }>;
14
+ richResponse?: any[];
15
+ [key: string]: any;
16
+ }
17
+
18
+ export declare function prepareRichResponseMessage(content: RichResponseContent): any;
19
+ export declare function botMetadataSignature(): Uint8Array;
20
+ export declare function botMetadataCertificate(length?: number): Uint8Array;
21
+ export declare function wrapToBotForwardedMessage(richResponseMessage: any): any;
@@ -0,0 +1,229 @@
1
+ import { randomUUID, getRandomValues } from 'crypto';
2
+ import { proto } from '../../WAProto/index.js';
3
+ import { CodeHighlightType, RichSubMessageType, LANGUAGE_KEYWORDS } from './rich-messages.js';
4
+
5
+ const LEXER_REGEX = /(\/\/[^\n]*|\/\*[\s\S]*?\*\/|"(?:[^"\\]|\\.)*"|'(?:[^'\\]|\\.)*'|`(?:[^`\\]|\\.)*`|\b\d+\.?\d*\b|\b[a-zA-Z_$][\w$]*\b|\s+|[^\s\w$]+)/g;
6
+ const NOOP = new Set([]);
7
+
8
+ const tokenizeCode = (code, language = 'javascript') => {
9
+ const keywords = LANGUAGE_KEYWORDS[language] || NOOP;
10
+ const blocks = [];
11
+ LEXER_REGEX.lastIndex = 0;
12
+ let match;
13
+ while ((match = LEXER_REGEX.exec(code)) !== null) {
14
+ if (match[1]) {
15
+ blocks.push({ highlightType: CodeHighlightType.COMMENT, codeContent: match[1] });
16
+ } else if (match[2]) {
17
+ blocks.push({ highlightType: CodeHighlightType.STRING, codeContent: match[2] });
18
+ } else if (match[3]) {
19
+ blocks.push({
20
+ highlightType: keywords.has(match[3]) ? CodeHighlightType.KEYWORD : CodeHighlightType.METHOD,
21
+ codeContent: match[3]
22
+ });
23
+ } else if (match[4]) {
24
+ blocks.push({
25
+ highlightType: keywords.has(match[4]) ? CodeHighlightType.KEYWORD : CodeHighlightType.DEFAULT,
26
+ codeContent: match[4]
27
+ });
28
+ } else if (match[5]) {
29
+ blocks.push({ highlightType: CodeHighlightType.NUMBER, codeContent: match[5] });
30
+ } else {
31
+ blocks.push({ highlightType: CodeHighlightType.DEFAULT, codeContent: match[6] });
32
+ }
33
+ }
34
+ return blocks;
35
+ };
36
+
37
+ const toUnified = (submessages, uuid) => ({
38
+ response_id: uuid || randomUUID(),
39
+ sections: submessages.map(submessage => {
40
+ switch (submessage.messageType) {
41
+ case RichSubMessageType.CODE: {
42
+ const codeMetadata = submessage.codeMetadata;
43
+ return {
44
+ view_model: {
45
+ primitive: {
46
+ language: codeMetadata.codeLanguage,
47
+ code_blocks: codeMetadata.codeBlocks.map(block => ({
48
+ content: block.codeContent,
49
+ type: CodeHighlightType[block.highlightType]
50
+ })),
51
+ __typename: 'GenAICodeUXPrimitive'
52
+ },
53
+ __typename: 'GenAISingleLayoutViewModel'
54
+ }
55
+ };
56
+ }
57
+ case RichSubMessageType.TABLE: {
58
+ const tableMetadata = submessage.tableMetadata;
59
+ return {
60
+ view_model: {
61
+ primitive: {
62
+ title: tableMetadata.title,
63
+ rows: tableMetadata.rows.map(row => ({
64
+ is_header: row.isHeading,
65
+ cells: row.items,
66
+ markdown_cells: row.items.map(item => ({ text: item }))
67
+ })),
68
+ __typename: 'GenATableUXPrimitive'
69
+ },
70
+ __typename: 'GenAISingleLayoutViewModel'
71
+ }
72
+ };
73
+ }
74
+ case RichSubMessageType.TEXT:
75
+ return {
76
+ view_model: {
77
+ primitive: {
78
+ text: submessage.messageText,
79
+ inline_entities: submessage.inlineEntities || [],
80
+ __typename: 'GenAIMarkdownTextUXPrimitive'
81
+ },
82
+ __typename: 'GenAISingleLayoutViewModel'
83
+ }
84
+ };
85
+ }
86
+ return submessage;
87
+ })
88
+ });
89
+
90
+ const botMetadataSignature = () => {
91
+ const signature = new Uint8Array(64);
92
+ getRandomValues(signature);
93
+ return signature;
94
+ };
95
+
96
+ const botMetadataCertificate = (length = 685) => {
97
+ const certificate = new Uint8Array(length);
98
+ certificate[0] = 48;
99
+ certificate[1] = 130;
100
+ getRandomValues(certificate.subarray(2));
101
+ return certificate;
102
+ };
103
+
104
+ const wrapToBotForwardedMessage = richResponseMessage => ({
105
+ messageContextInfo: {
106
+ botMetadata: {
107
+ verificationMetadata: {
108
+ proofs: [
109
+ {
110
+ certificateChain: [
111
+ botMetadataCertificate(),
112
+ botMetadataCertificate(892)
113
+ ],
114
+ version: 1,
115
+ useCase: 1,
116
+ signature: botMetadataSignature()
117
+ }
118
+ ]
119
+ }
120
+ }
121
+ },
122
+ botForwardedMessage: {
123
+ message: { richResponseMessage }
124
+ }
125
+ });
126
+
127
+ const prepareRichResponseMessage = content => {
128
+ const {
129
+ alignment, code, contentText, disclaimerText, footerText, headerText,
130
+ imageText, inlineImage, inlineVideo, items, language, latex, links,
131
+ noHeading, posts, products, suggested, richResponse, table, tapLinkUrl, title
132
+ } = content;
133
+
134
+ let submessages = [];
135
+
136
+ if (Array.isArray(richResponse)) {
137
+ submessages = richResponse.map(submessage => {
138
+ if (submessage.text) {
139
+ return { messageType: RichSubMessageType.TEXT, messageText: submessage.text, inlineEntities: submessage.inlineEntities };
140
+ } else if (submessage.code) {
141
+ return {
142
+ messageType: RichSubMessageType.CODE,
143
+ codeMetadata: {
144
+ codeLanguage: submessage.language || 'javascript',
145
+ codeBlocks: typeof submessage.code === 'string'
146
+ ? tokenizeCode(submessage.code, submessage.language || 'javascript')
147
+ : submessage.code
148
+ }
149
+ };
150
+ } else if (submessage.table) {
151
+ return {
152
+ messageType: RichSubMessageType.TABLE,
153
+ tableMetadata: { title: submessage.title, rows: submessage.table }
154
+ };
155
+ }
156
+ return submessage;
157
+ });
158
+ } else {
159
+ if (headerText) submessages.push({ messageType: RichSubMessageType.TEXT, messageText: headerText });
160
+ if (contentText) submessages.push({ messageType: RichSubMessageType.TEXT, messageText: contentText });
161
+ if (code) {
162
+ const lang = language || 'javascript';
163
+ submessages.push({
164
+ messageType: RichSubMessageType.CODE,
165
+ codeMetadata: { codeLanguage: lang, codeBlocks: tokenizeCode(code, lang) }
166
+ });
167
+ }
168
+ if (links) {
169
+ links.forEach((linkField, index) => {
170
+ const prefix = 'SS_' + index;
171
+ submessages.push({
172
+ messageType: RichSubMessageType.TEXT,
173
+ messageText: linkField.text + ` {{${prefix}}}1{{/${prefix}}} `,
174
+ inlineEntities: [{
175
+ key: prefix,
176
+ metadata: {
177
+ reference_id: index + 1,
178
+ reference_url: linkField.url || '',
179
+ reference_title: linkField.title || 'Reference',
180
+ reference_display_name: linkField.displayName || 'Source',
181
+ sources: [],
182
+ __typename: 'GenAISearchCitationItem'
183
+ }
184
+ }]
185
+ });
186
+ });
187
+ }
188
+ if (table) {
189
+ submessages.push({
190
+ messageType: RichSubMessageType.TABLE,
191
+ tableMetadata: {
192
+ title,
193
+ rows: table.map((items, index) => ({ isHeading: !noHeading && index === 0, items }))
194
+ }
195
+ });
196
+ }
197
+ if (footerText) submessages.push({ messageType: RichSubMessageType.TEXT, messageText: footerText });
198
+ }
199
+
200
+ const uuid = randomUUID();
201
+ const unified = toUnified(submessages, uuid);
202
+
203
+ const richResponseMessage = proto.AIRichResponseMessage.create({
204
+ submessages,
205
+ messageType: proto.AIRichResponseMessageType.AI_RICH_RESPONSE_TYPE_STANDARD,
206
+ unifiedResponse: { data: Buffer.from(JSON.stringify(unified)) },
207
+ contextInfo: {
208
+ isForwarded: true,
209
+ forwardingScore: 1,
210
+ forwardedAiBotMessageInfo: { botJid: '867051314767696@bot' },
211
+ forwardOrigin: 4
212
+ }
213
+ });
214
+
215
+ const message = wrapToBotForwardedMessage(richResponseMessage);
216
+ const botMetadata = message.messageContextInfo.botMetadata;
217
+ if (disclaimerText) botMetadata.messageDisclaimerText = disclaimerText;
218
+ botMetadata.botResponseId = uuid;
219
+
220
+ return message;
221
+ };
222
+
223
+ export {
224
+ toUnified,
225
+ prepareRichResponseMessage,
226
+ botMetadataSignature,
227
+ botMetadataCertificate,
228
+ wrapToBotForwardedMessage
229
+ };
@@ -273,5 +273,57 @@ export declare const generateLinkContentV2: (
273
273
  message: any;
274
274
  messageId: string;
275
275
  };
276
+
277
+ /**
278
+ * Opciones para generar un mensaje HTML embebido en WhatsApp.
279
+ *
280
+ * El mensaje resultante es renderizado por el cliente de WhatsApp como un
281
+ * WebView sandboxed dentro del bocadillo del mensaje, usando el campo interno
282
+ * `GenAIaeacdsnwHtmlPrimitive` del protocolo AIRichResponseMessage.
283
+ */
284
+ export interface HtmlContentOptions extends RichMessageOptions {
285
+ /**
286
+ * Dominios que el WebView puede contactar (fetch, imágenes, fuentes, etc.).
287
+ * Sin esquema (ej: `["api.tuyo.com", "cdn.tuyo.com"]`).
288
+ * Default: `[]` (sin red).
289
+ */
290
+ trustedSources?: string[];
291
+ /** Cabecera opcional arriba del HTML (markdown). */
292
+ headerText?: string;
293
+ /** Pie opcional debajo del HTML (markdown). */
294
+ footer?: string;
295
+ /**
296
+ * Texto mostrado en el submessage de respaldo si el cliente no soporta
297
+ * HTML. Default: `"Contenido interactivo"`.
298
+ */
299
+ fallbackText?: string;
300
+ }
301
+
302
+ /**
303
+ * Construye un mensaje que el cliente de WhatsApp renderiza como un WebView
304
+ * embebido dentro del bocadillo del mensaje.
305
+ *
306
+ * Ver `HtmlContentOptions` para las limitaciones estructurales conocidas y
307
+ * el patrón recomendado (backend + inyección de estado + JWT).
308
+ *
309
+ * @example
310
+ * ```ts
311
+ * const html = `<body><h1>Hola ${jid}</h1></body>`;
312
+ * const { message, messageId } = generateHtmlContent(html, quoted, {
313
+ * trustedSources: ["api.tuyo.com"],
314
+ * headerText: "Demo HTML",
315
+ * });
316
+ * await sock.relayMessage(jid, message, { messageId });
317
+ * ```
318
+ */
319
+ export declare const generateHtmlContent: (
320
+ html: string,
321
+ quoted?: QuotedMessage | null,
322
+ options?: HtmlContentOptions,
323
+ ) => {
324
+ message: any;
325
+ messageId: string;
326
+ };
327
+
276
328
  export {};
277
329
  //# sourceMappingURL=rich-messages.d.ts.map