plogme 2.0.7 → 2.0.9

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.
@@ -65,10 +65,10 @@ const decodeDecryptedMsmsgMessage = (decrypted) => {
65
65
  const unpadded = Buffer.from(unpadRandomMax16(buf));
66
66
  const decoded = proto.Message.decode(unpadded);
67
67
  const hasContent = Object.keys(decoded).some(k => k !== 'messageContextInfo' && decoded[k] != null);
68
- if (hasContent) return decoded;
68
+ if (hasContent) return decodeUnifiedResponseInPlace(decoded);
69
69
  }
70
70
  catch {}
71
- return proto.Message.decode(buf);
71
+ return decodeUnifiedResponseInPlace(proto.Message.decode(buf));
72
72
  };
73
73
 
74
74
  /**
@@ -127,4 +127,77 @@ export const decryptMsmsgBotMessage = async (messageSecret, messageKey, msMsg) =
127
127
  throw err;
128
128
  };
129
129
 
130
+ // unifiedResponse.data is base64/bytes-wrapped JSON, not encrypted. Keep the
131
+ // original data and expose both the decoded object and flattened text.
132
+ export const parseUnifiedResponseData = (data) => {
133
+ if (!data)
134
+ return null;
135
+ try {
136
+ let buf;
137
+ if (Buffer.isBuffer(data))
138
+ buf = data;
139
+ else if (data instanceof Uint8Array)
140
+ buf = Buffer.from(data);
141
+ else if (typeof data === 'string')
142
+ buf = Buffer.from(data, 'base64');
143
+ else if (data.type === 'Buffer' && Array.isArray(data.data))
144
+ buf = Buffer.from(data.data);
145
+ else
146
+ return null;
147
+ return JSON.parse(buf.toString('utf8'));
148
+ }
149
+ catch {
150
+ return null;
151
+ }
152
+ };
153
+ export const textFromUnifiedResponse = (data) => {
154
+ const json = parseUnifiedResponseData(data);
155
+ if (!json)
156
+ return null;
157
+ const parts = [];
158
+ for (const section of json.sections || []) {
159
+ const text = section?.view_model?.primitive?.text;
160
+ if (text)
161
+ parts.push(text);
162
+ }
163
+ return parts.length ? parts.join('\n') : null;
164
+ };
165
+ export const textFromRichResponse = (richResponse) => {
166
+ if (!richResponse)
167
+ return null;
168
+ if (Array.isArray(richResponse.submessages)) {
169
+ const parts = richResponse.submessages
170
+ .map(submessage => submessage?.messageText)
171
+ .filter(text => typeof text === 'string' && text.length);
172
+ if (parts.length)
173
+ return parts.join('\n');
174
+ }
175
+ return textFromUnifiedResponse(richResponse.unifiedResponse?.data);
176
+ };
177
+ export const extractMetaAiText = (message) => {
178
+ if (!message)
179
+ return null;
180
+ const body = message.protocolMessage?.editedMessage || message;
181
+ return body.extendedTextMessage?.text ?? body.conversation ?? textFromRichResponse(body.richResponseMessage) ?? null;
182
+ };
183
+ export const decodeUnifiedResponseInPlace = (message) => {
184
+ if (!message || typeof message !== 'object')
185
+ return message;
186
+ const bodies = [
187
+ message,
188
+ message.protocolMessage?.editedMessage,
189
+ message.editedMessage
190
+ ].filter(Boolean);
191
+ for (const body of bodies) {
192
+ const unifiedResponse = body.richResponseMessage?.unifiedResponse;
193
+ if (unifiedResponse && unifiedResponse.data != null && unifiedResponse.decodedData === undefined) {
194
+ unifiedResponse.decodedData = parseUnifiedResponseData(unifiedResponse.data);
195
+ const text = textFromUnifiedResponse(unifiedResponse.data);
196
+ if (text != null)
197
+ unifiedResponse.text = text;
198
+ }
199
+ }
200
+ return message;
201
+ };
202
+
130
203
  export { decodeDecryptedMsmsgMessage };
@@ -7,7 +7,7 @@
7
7
  * - Plain text fallback is used unless the native payload can be authenticated
8
8
  *
9
9
  * metaTyping() — shows the "typing..." / planning steps indicator.
10
- * sendMetaComposited() — full flow: typing → delete → final message.
10
+ * sendMetaComposited() — full flow: initial message → streaming MESSAGE_EDIT frames → final edit.
11
11
  *
12
12
  * If you use or copy this code, please credit @crysnovax/bailey.
13
13
  */
@@ -161,12 +161,21 @@ export const metaTyping = async (sock, jid, {
161
161
  return sock.sendMessage(jid, placeholder);
162
162
  };
163
163
 
164
+ /** Send a streaming MESSAGE_EDIT frame without changing the original key. */
165
+ export const editMetaMessage = async (sock, jid, key, content, sendOptions = {}, streamContext) => {
166
+ if (!key)
167
+ return undefined;
168
+ const frame = streamContext
169
+ ? { ...content, messageContextInfo: { ...streamContext, ...content.messageContextInfo } }
170
+ : content;
171
+ return sock.sendMessage(jid, { ...frame, edit: key }, sendOptions);
172
+ };
173
+
164
174
  /**
165
- * sendMetaComposited — full Meta AI flow (UNIVERSAL).
166
- * 1. Send progress indicator
167
- * 2. Wait thinkingMs
168
- * 3. Delete placeholder
169
- * 4. Send final message fresh
175
+ * sendMetaComposited — full Meta AI-style flow (UNIVERSAL).
176
+ * 1. Send initial progress indicator
177
+ * 2. Optionally emit streamUpdates as MESSAGE_EDIT frames
178
+ * 3. Edit the same message into the final response
170
179
  */
171
180
  export const sendMetaComposited = async (sock, jid, content, {
172
181
  thinkingMs = 2000,
@@ -174,7 +183,10 @@ export const sendMetaComposited = async (sock, jid, content, {
174
183
  steps = [],
175
184
  placeholderText = '',
176
185
  sendOptions = {},
177
- useNativeMeta = false
186
+ useNativeMeta = false,
187
+ streamUpdates = [],
188
+ streamUpdateDelayMs = 0,
189
+ streamContext
178
190
  } = {}) => {
179
191
  const placeholder = await metaTyping(sock, jid, {
180
192
  description, steps, estimatedMs: thinkingMs, placeholderText, useNativeMeta
@@ -183,12 +195,29 @@ export const sendMetaComposited = async (sock, jid, content, {
183
195
  try {
184
196
  await delay(thinkingMs);
185
197
  if (placeholder?.key) {
186
- await sock.sendMessage(jid, { delete: placeholder.key });
198
+ for (const update of streamUpdates) {
199
+ const frame = typeof update === 'string' ? { text: update } : update;
200
+ try {
201
+ await editMetaMessage(sock, jid, placeholder.key, frame, sendOptions, streamContext);
202
+ }
203
+ catch (_) {}
204
+ if (streamUpdateDelayMs > 0)
205
+ await delay(streamUpdateDelayMs);
206
+ }
207
+ try {
208
+ await editMetaMessage(sock, jid, placeholder.key, content, sendOptions, streamContext);
209
+ }
210
+ catch (_) {
211
+ await sock.sendMessage(jid, content, sendOptions);
212
+ }
213
+ }
214
+ else {
215
+ await sock.sendMessage(jid, content, sendOptions);
187
216
  }
188
217
  } catch (_) {}
189
218
 
190
219
  await sock.sendPresenceUpdate('paused', jid);
191
- return sock.sendMessage(jid, content, sendOptions);
220
+ return placeholder;
192
221
  };
193
222
 
194
223
  /**
@@ -48,7 +48,7 @@ export const tokenizeCode = (code, language = 'javascript') => {
48
48
  const firstImageValue = (...values) => values.find(value => value !== undefined && value !== null && String(value).length > 0);
49
49
 
50
50
  /** Normalize album image variants without downgrading full-size URLs to previews. */
51
- const buildRichImagePrimitive = (image = {}, expiration = String(Date.now() + 30 * 24 * 60 * 60 * 1000)) => {
51
+ const buildRichImagePrimitive = (image = {}, expiration = String(Date.now() + 30 * 24 * 60 * 60 * 1000), { fullOnly = false } = {}) => {
52
52
  const previewUrl = firstImageValue(image.imagePreviewUrl, image.previewUrl, image.preview_url, image.sourceUrl, image.source_url, image.url) || '';
53
53
  const fullUrl = firstImageValue(image.imageHighResUrl, image.highResUrl, image.high_res_url, image.fullUrl, image.full_url, image.sourceUrl, image.source_url, image.url, previewUrl);
54
54
  const darkPreviewUrl = firstImageValue(image.darkModePreviewUrl, image.dark_mode_preview_url, previewUrl);
@@ -59,7 +59,13 @@ const buildRichImagePrimitive = (image = {}, expiration = String(Date.now() + 30
59
59
  const fullHeight = Number(image.fullHeight || image.full_height || image.highResHeight || image.high_res_height || image.height || height);
60
60
  const darkWidth = Number(image.darkWidth || image.dark_width || fullWidth);
61
61
  const darkHeight = Number(image.darkHeight || image.dark_height || fullHeight);
62
- const mimeType = image.mimeType || image.mime_type || 'image/png';
62
+ const mimeType = image.mimeType || image.mime_type || (() => {
63
+ const value = String(fullUrl || previewUrl).split('?')[0].toLowerCase();
64
+ if (value.endsWith('.jpg') || value.endsWith('.jpeg')) return 'image/jpeg';
65
+ if (value.endsWith('.webp')) return 'image/webp';
66
+ if (value.endsWith('.gif')) return 'image/gif';
67
+ return 'image/png';
68
+ })();
63
69
  const media = (url, mediaWidth, mediaHeight) => ({
64
70
  url,
65
71
  url_fallback: url,
@@ -68,14 +74,17 @@ const buildRichImagePrimitive = (image = {}, expiration = String(Date.now() + 30
68
74
  width: mediaWidth,
69
75
  height: mediaHeight
70
76
  });
71
- return {
72
- preview_image: media(previewUrl, width, height),
77
+ const primitive = {
73
78
  full_image: media(fullUrl, fullWidth, fullHeight),
74
- dark_mode_preview_image: media(darkPreviewUrl, darkWidth, darkHeight),
75
- dark_mode_full_image: media(darkFullUrl, darkWidth, darkHeight),
76
79
  asset_query_status: 'FETCHED',
77
80
  __typename: 'GenAIImagePrimitive'
78
81
  };
82
+ if (!fullOnly) {
83
+ primitive.preview_image = media(previewUrl, width, height);
84
+ primitive.dark_mode_preview_image = media(darkPreviewUrl, darkWidth, darkHeight);
85
+ primitive.dark_mode_full_image = media(darkFullUrl, darkWidth, darkHeight);
86
+ }
87
+ return primitive;
79
88
  };
80
89
  // Lia@Changes 09-04-26 --- Inject buffer into unifiedResponse.data to support proper rendering of rich messages (ex: tables and code blocks)
81
90
  export const toUnified = (submessages, uuid) => ({
@@ -974,13 +983,33 @@ export const prepareVerticalAlbumMessage = ({ items = [], verificationMetadata }
974
983
  if (!url) throw new Error('Each video album item requires a video URL');
975
984
  return buildImaginePrimitive({ mediaType: 'video', url, thumbnail: video?.thumbnail || video?.thumbnailUrl, mimeType: video?.mimeType || video?.mime_type || 'video/mp4', fileLength: video?.fileLength || video?.file_length || 0, duration: video?.duration || 0, status: 'READY' });
976
985
  }
977
- const image = item?.image || item?.data || item;
978
- const sourceUrl = typeof image === 'string' ? image : firstImageValue(
986
+ const rawImage = item?.image || item?.data || item;
987
+ const image = typeof rawImage === 'string' ? { url: rawImage } : (rawImage || {});
988
+ const sourceUrl = firstImageValue(
979
989
  image?.imageHighResUrl, image?.highResUrl, image?.fullUrl,
980
990
  image?.imagePreviewUrl, image?.previewUrl, image?.sourceUrl, image?.url
981
991
  ) || '';
982
992
  if (!sourceUrl) throw new Error('Each image album item requires an image URL');
983
- const primitive = buildRichImagePrimitive({ ...image, width: image?.width || item?.width, height: image?.height || item?.height }, expiration);
993
+ // Unlike a compact image grid, vertical albums are intended to render
994
+ // the actual media at full size. Some clients choose preview_image and
995
+ // never follow full_image, so expose the selected full URL/dimensions
996
+ // in both slots instead of allowing a thumbnail URL to win.
997
+ const fullUrl = firstImageValue(
998
+ image?.imageHighResUrl, image?.highResUrl, image?.high_res_url,
999
+ image?.fullUrl, image?.full_url, image?.sourceUrl, image?.source_url, image?.url
1000
+ ) || sourceUrl;
1001
+ const fullWidth = Number(image?.fullWidth || image?.full_width || image?.highResWidth || image?.high_res_width || image?.width || item?.width || 0);
1002
+ const fullHeight = Number(image?.fullHeight || image?.full_height || image?.highResHeight || image?.high_res_height || image?.height || item?.height || 0);
1003
+ const primitive = buildRichImagePrimitive({
1004
+ ...image,
1005
+ imagePreviewUrl: fullUrl,
1006
+ previewUrl: fullUrl,
1007
+ sourceUrl: fullUrl,
1008
+ imageHighResUrl: fullUrl,
1009
+ fullUrl,
1010
+ ...(fullWidth > 0 ? { width: fullWidth, fullWidth } : {}),
1011
+ ...(fullHeight > 0 ? { height: fullHeight, fullHeight } : {})
1012
+ }, expiration, { fullOnly: true });
984
1013
  return { ...primitive, display_mode: 'FULL_WIDTH', full_width: true };
985
1014
  });
986
1015
  const richResponseMessage = proto.AIRichResponseMessage.create({
@@ -1152,11 +1181,13 @@ export const prepareUnifiedResponseMessage = ({ sections = [], submessages = [],
1152
1181
  };
1153
1182
 
1154
1183
  /** Build a protocol-backed AIRich map card with optional numbered annotations. */
1155
- export const prepareRichMapMessage = ({ centerLatitude, centerLongitude, latitudeDelta, longitudeDelta, annotations = [], showInfoList = false, verificationMetadata } = {}) => {
1184
+ export const prepareRichMapMessage = ({ text = 'Map location', centerLatitude, centerLongitude, latitudeDelta, longitudeDelta, annotations = [], showInfoList = false, verificationMetadata } = {}) => {
1156
1185
  if (!Number.isFinite(Number(centerLatitude)) || !Number.isFinite(Number(centerLongitude))) {
1157
1186
  throw new Boom('prepareRichMapMessage requires centerLatitude and centerLongitude', { statusCode: 400 });
1158
1187
  }
1159
- const submessages = [{
1188
+ const submessages = [
1189
+ ...(text ? [{ messageType: RichSubMessageType.TEXT, messageText: String(text) }] : []),
1190
+ {
1160
1191
  messageType: RichSubMessageType.MAP,
1161
1192
  mapMetadata: {
1162
1193
  centerLatitude: Number(centerLatitude),
@@ -1172,7 +1203,8 @@ export const prepareRichMapMessage = ({ centerLatitude, centerLongitude, latitud
1172
1203
  body: String(annotation.body || '')
1173
1204
  }))
1174
1205
  }
1175
- }];
1206
+ }
1207
+ ];
1176
1208
  const richResponseMessage = proto.AIRichResponseMessage.create({
1177
1209
  messageType: proto.AIRichResponseMessageType.AI_RICH_RESPONSE_TYPE_STANDARD,
1178
1210
  submessages,
@@ -1205,9 +1237,36 @@ export const prepareBotSourcesMessage = ({ text = '', sources = [], verification
1205
1237
  if (!Array.isArray(sources) || sources.length === 0) {
1206
1238
  throw new Boom('prepareBotSourcesMessage requires at least one source', { statusCode: 400 });
1207
1239
  }
1240
+ const submessages = [{
1241
+ messageType: RichSubMessageType.TEXT,
1242
+ messageText: String(text || 'Sources')
1243
+ }];
1244
+ const sourceCards = sources.map((source, index) => ({
1245
+ source_type: 'THIRD_PARTY',
1246
+ source_display_name: source.sourceTitle || source.title || '',
1247
+ source_subtitle: source.sourceQuery || source.query || 'Source',
1248
+ source_url: source.sourceProviderUrl || source.url || '',
1249
+ favicon: {
1250
+ url: source.faviconCdnUrl || source.faviconUrl || source.thumbnailCdnUrl || source.thumbnailUrl || '',
1251
+ mime_type: 'image/jpeg',
1252
+ width: 16,
1253
+ height: 16
1254
+ },
1255
+ citation_number: source.citationNumber ?? index + 1
1256
+ })).filter((source) => source.source_url || source.source_display_name);
1257
+ const sections = toUnified(submessages, randomUUID()).sections;
1258
+ if (sourceCards.length) {
1259
+ sections.push({
1260
+ view_model: {
1261
+ primitive: { sources: sourceCards, __typename: 'GenAISearchResultPrimitive' },
1262
+ __typename: 'GenAISingleLayoutViewModel'
1263
+ }
1264
+ });
1265
+ }
1208
1266
  const envelope = wrapToBotForwardedMessage(proto.AIRichResponseMessage.create({
1209
1267
  messageType: proto.AIRichResponseMessageType.AI_RICH_RESPONSE_TYPE_STANDARD,
1210
- submessages: [{ messageType: RichSubMessageType.TEXT, messageText: String(text) }],
1268
+ submessages,
1269
+ unifiedResponse: { data: Buffer.from(JSON.stringify({ response_id: randomUUID(), sections })) },
1211
1270
  contextInfo: { isForwarded: true, forwardingScore: 1, forwardOrigin: 4 }
1212
1271
  }), verificationMetadata);
1213
1272
  envelope.messageContextInfo.botMetadata.richResponseSourcesMetadata = {
@@ -1758,6 +1817,57 @@ export const attachBotVerificationProofs = (envelope, verificationMetadata) => {
1758
1817
  return envelope;
1759
1818
  };
1760
1819
 
1820
+ /**
1821
+ * Build a forwarded AIRich label message.
1822
+ *
1823
+ * This is the small single-label surface used by WhatsApp clients for a
1824
+ * colored forwarded bubble. The unified response is intentionally serialized
1825
+ * as base64 text because that is the wire shape accepted by the raw
1826
+ * `relayMessage` API.
1827
+ */
1828
+ export const buildRichLabelMessage = ({
1829
+ text = '',
1830
+ variant = 'POSITIVE',
1831
+ backgroundColor = '#FF0000FF',
1832
+ textColor = '#000000FF',
1833
+ responseId = randomUUID(),
1834
+ } = {}) => {
1835
+ const unified = {
1836
+ __typename: 'GenAIUnifiedResponse',
1837
+ response_id: responseId,
1838
+ sections: [{
1839
+ __typename: 'GenAIUnifiedResponseSection',
1840
+ view_model: {
1841
+ __typename: 'GenAISingleLayoutViewModel',
1842
+ primitive: {
1843
+ __typename: 'GenAILabelPrimitive',
1844
+ text: String(text),
1845
+ variant,
1846
+ background_color_override: backgroundColor,
1847
+ text_color_override: textColor,
1848
+ },
1849
+ },
1850
+ }],
1851
+ };
1852
+
1853
+ return {
1854
+ botForwardedMessage: {
1855
+ message: {
1856
+ richResponseMessage: {
1857
+ messageType: 1,
1858
+ unifiedResponse: {
1859
+ data: Buffer.from(JSON.stringify(unified)).toString('base64'),
1860
+ },
1861
+ contextInfo: {
1862
+ isForwarded: true,
1863
+ forwardOrigin: 4,
1864
+ },
1865
+ },
1866
+ },
1867
+ },
1868
+ };
1869
+ };
1870
+
1761
1871
  /**
1762
1872
  * Wrap a rich response in the bot-forwarded envelope.
1763
1873
  *
@@ -96,7 +96,9 @@ export const generateRegistrationNode = ({ registrationId, signedPreKey, signedI
96
96
  supportMessageAssociation: true,
97
97
  supportGroupHistory: false,
98
98
  onDemandReady: undefined,
99
- supportGuestChat: undefined
99
+ supportGuestChat: undefined,
100
+ supportOmittedConversationIndex: true,
101
+ supportUniversalReachChat: true
100
102
  },
101
103
  version: {
102
104
  primary: 10,
@@ -203,4 +205,4 @@ export const encodeSignedDeviceIdentity = (account, includeSignatureKey) => {
203
205
  account.accountSignatureKey = null;
204
206
  }
205
207
  return proto.ADVSignedDeviceIdentity.encode(account).finish();
206
- };
208
+ };
package/lib/index.d.ts CHANGED
@@ -132,6 +132,25 @@ export interface AIPromptOptions {
132
132
  /** Extra options forwarded to `sendMessage` (quoted, linkPreview, ...). */
133
133
  [key: string]: unknown;
134
134
  }
135
+ /** Options for the verified Meta AI (Hatch) send path. */
136
+ export interface MetaAISendOptions {
137
+ /** Destination JID; defaults to `867051314767696@bot` for a direct prompt. */
138
+ jid?: string;
139
+ invokerJid?: string;
140
+ sessionId?: string;
141
+ messageSecret?: Buffer;
142
+ capabilities?: number[];
143
+ /** F-BID used when invoking Meta AI in a group. */
144
+ botFbid?: string;
145
+ /** Add a visible Meta AI mention to a group prompt. */
146
+ mention?: boolean;
147
+ personaType?: string;
148
+ agentEngagementType?: string;
149
+ modeSelected?: string;
150
+ conversationContext?: Uint8Array | Buffer;
151
+ quoted?: unknown;
152
+ links?: unknown;
153
+ }
135
154
 
136
155
  export interface RichMenuButton {
137
156
  id?: string;
@@ -351,6 +370,26 @@ export interface AIRichCommandMenuContent {
351
370
  footer?: string;
352
371
  }
353
372
 
373
+ export declare function parseUnifiedResponseData(data: unknown): Record<string, unknown> | null;
374
+ export declare function textFromUnifiedResponse(data: unknown): string | null;
375
+ export declare function textFromRichResponse(message: unknown): string | null;
376
+ export declare function extractMetaAiText(message: unknown): string | null;
377
+ export declare function decodeUnifiedResponseInPlace<T extends Record<string, unknown>>(message: T): T;
378
+ export interface MetaCompositedOptions {
379
+ thinkingMs?: number;
380
+ description?: string;
381
+ steps?: Array<Record<string, unknown>>;
382
+ estimatedMs?: number;
383
+ placeholderText?: string;
384
+ sendOptions?: Record<string, unknown>;
385
+ useNativeMeta?: boolean;
386
+ streamUpdates?: Array<string | Record<string, unknown>>;
387
+ streamUpdateDelayMs?: number;
388
+ streamContext?: Record<string, unknown>;
389
+ }
390
+ export declare function editMetaMessage(sock: WASocket, jid: string, key: WAMessageKey, content: Record<string, unknown>, sendOptions?: Record<string, unknown>, streamContext?: Record<string, unknown>): Promise<unknown>;
391
+ export declare function sendMetaComposited(sock: WASocket, jid: string, content: Record<string, unknown>, options?: MetaCompositedOptions): Promise<unknown>;
392
+
354
393
  export interface WASocket {
355
394
  sendMessage(jid: string | string[], content: StatusContent | GroupStatusContent | Record<string, unknown>, options?: Partial<StatusOptions> & Record<string, unknown>): Promise<unknown>;
356
395
  /** Send at least two image/video URL items as a full-width AIRich vertical album. */
@@ -427,6 +466,12 @@ export interface WASocket {
427
466
  sendBotToolResult(jid: string, content?: { text?: string; toolCallId?: string; resolutionData?: unknown; resolutionDataSerialized?: string; botJid?: string }, options?: Record<string, unknown>): Promise<unknown>;
428
467
  /** Send one tolerant AIRich response containing every supported section supplied in content. */
429
468
  sendPlogmeMessage(jid: string, content?: Record<string, unknown>, quoted?: unknown, options?: Record<string, unknown>): Promise<unknown>;
469
+ /** Send a compact forwarded AIRich label bubble with optional colors and variant. */
470
+ sendRichLabelMessage(jid: string, content?: { text?: string; variant?: string; backgroundColor?: string; textColor?: string; responseId?: string }, options?: Record<string, unknown>): Promise<Record<string, unknown>>;
471
+ /** Send a prompt through the verified Meta AI/Hatch route and return its message ID. */
472
+ sendMetaAI(text: string, options?: MetaAISendOptions): Promise<string>;
473
+ /** Backward-compatible destination-first signature. */
474
+ sendMetaAI(jid: string, text: string, options?: Omit<MetaAISendOptions, 'jid'>): Promise<string>;
430
475
  /** Resolve a WhatsApp Channel invite code or invite URL to channel metadata. */
431
476
  newsletterGetInviteInfo(inviteCodeOrUrl: string): Promise<Record<string, unknown> | null>;
432
477
  /** React to a Channel post; pass an empty string, null, or undefined to remove the reaction. */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "plogme",
3
- "version": "2.0.7",
3
+ "version": "2.0.9",
4
4
  "description": "Production-ready Baileys fork ⚉ with AI groups, Meta AI prompting, safe compositing fallbacks, rich responses, interactive messages, albums, newsletters, and communities — without antiban wrappers.",
5
5
  "main": "lib/index.js",
6
6
  "type": "module",