plogme 2.0.7 → 2.0.8

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.
package/README.md CHANGED
@@ -39,10 +39,10 @@ npm install plogme
39
39
 
40
40
  The package currently requires **Node.js 20 or newer**.
41
41
 
42
- To install the development branch directly from GitHub:
42
+ The published package is available from npm:
43
43
 
44
44
  ```bash
45
- npm install github:crysnovax/baileys
45
+ npm install plogme
46
46
  ```
47
47
 
48
48
  Plogme is an ES module package. Use `import` syntax in Node.js projects configured with `"type": "module"`.
@@ -1504,7 +1504,7 @@ Auto-greet new contacts with an interactive FAQ menu. Fires once per contact, ne
1504
1504
  ### Basic Setup
1505
1505
 
1506
1506
  ```javascript
1507
- import { createWelcomeFlow } from '@crysnovax/baileys'
1507
+ import { createWelcomeFlow } from 'plogme'
1508
1508
 
1509
1509
  const welcome = createWelcomeFlow(sock, {
1510
1510
  greeting: 'Welcome! How can I help you today?',
@@ -1580,7 +1580,7 @@ welcome.hasGreeted(jid) // check if greeted → boolean
1580
1580
  | Option | Type | Default | Description |
1581
1581
  |--------|------|---------|-------------|
1582
1582
  | greeting | string | 'Welcome!…' | Body text of welcome message |
1583
- | footer | string | 'Powered by @crysnovax/baileys' | Footer text |
1583
+ | footer | string | 'Powered by plogme' | Footer text |
1584
1584
  | buttonText | string | 'Choose an option' | List button label |
1585
1585
  | sectionTitle | string | 'How can we help?' | Section header |
1586
1586
  | faqs | Array | 4 defaults | { id, title, description } |
@@ -1703,7 +1703,7 @@ sock.sendMessage(jid, {
1703
1703
  text: 'Built manually',
1704
1704
  contextInfo: {
1705
1705
  externalAdReply: {
1706
- title: '@crysnovax/baileys',
1706
+ title: 'plogme',
1707
1707
  thumbnail: fs.readFileSync('./image.jpg'),
1708
1708
  sourceApp: 'whatsapp',
1709
1709
  showAdAttribution: true,
@@ -1885,7 +1885,7 @@ saveFavs(remaining)
1885
1885
 
1886
1886
  ```javascript
1887
1887
  // Create
1888
- sock.newsletterCreate('@crysnovax/baileys', 'Fresh updates weekly')
1888
+ sock.newsletterCreate('plogme', 'Fresh updates weekly')
1889
1889
 
1890
1890
  // Metadata
1891
1891
  const metadata = await sock.newsletterMetadata('1231111111111@newsletter')
@@ -1906,8 +1906,8 @@ sock.newsletterDemote('1231111111111@newsletter', '6281111111111@s.whatsapp.net'
1906
1906
  sock.newsletterChangeOwner('1231111111111@newsletter', '6281111111111@s.whatsapp.net')
1907
1907
 
1908
1908
  // Update
1909
- sock.newsletterUpdate('1231111111111@newsletter', { name: '@crysnovax/baileys' })
1910
- sock.newsletterUpdateName('1231111111111@newsletter', '@crysnovax/baileys')
1909
+ sock.newsletterUpdate('1231111111111@newsletter', { name: 'plogme' })
1910
+ sock.newsletterUpdateName('1231111111111@newsletter', 'plogme')
1911
1911
  sock.newsletterUpdateDescription('1231111111111@newsletter', 'Fresh updates weekly')
1912
1912
  sock.newsletterUpdatePicture('1231111111111@newsletter', { url: 'path/to/image.jpg' })
1913
1913
  sock.newsletterRemovePicture('1231111111111@newsletter')
@@ -1934,7 +1934,7 @@ sock.newsletterDelete('1231111111111@newsletter')
1934
1934
 
1935
1935
  ```javascript
1936
1936
  // Create
1937
- const group = await sock.groupCreate('@crysnovax/baileys', ['628123456789@s.whatsapp.net'])
1937
+ const group = await sock.groupCreate('plogme', ['628123456789@s.whatsapp.net'])
1938
1938
 
1939
1939
  // Metadata
1940
1940
  const metadata = await sock.groupMetadata(jid)
@@ -1957,7 +1957,7 @@ sock.groupParticipantsUpdate(jid, ['628123456789@s.whatsapp.net'], 'demote')
1957
1957
  sock.groupRequestParticipantsUpdate(jid, ['628123456789@s.whatsapp.net'], 'approve')
1958
1958
 
1959
1959
  // Info updates
1960
- sock.groupUpdateSubject(jid, '@crysnovax/baileys')
1960
+ sock.groupUpdateSubject(jid, 'plogme')
1961
1961
  sock.groupUpdateDescription(jid, 'Updated description')
1962
1962
  sock.updateProfilePicture(jid, { url: 'path/to/image.jpg' })
1963
1963
  sock.removeProfilePicture(jid)
@@ -1990,7 +1990,7 @@ const requests = await sock.groupRequestParticipantsList(jid)
1990
1990
  const group = await sock.groupGetInviteInfo('ABC123456789')
1991
1991
 
1992
1992
  // Member label
1993
- sock.updateMemberLabel(jid, '@crysnovax/baileys')
1993
+ sock.updateMemberLabel(jid, 'plogme')
1994
1994
  ```
1995
1995
 
1996
1996
  ---
@@ -1999,7 +1999,7 @@ sock.updateMemberLabel(jid, '@crysnovax/baileys')
1999
1999
 
2000
2000
  ```javascript
2001
2001
  // Create
2002
- const community = await sock.communityCreate('@crysnovax/baileys', 'Fresh updates weekly')
2002
+ const community = await sock.communityCreate('plogme', 'Fresh updates weekly')
2003
2003
 
2004
2004
  // Create subgroup
2005
2005
  const group = await sock.communityCreateGroup(
@@ -2027,7 +2027,7 @@ sock.communityLeave(jid)
2027
2027
  sock.communityRequestParticipantsUpdate(jid, ['628123456789@s.whatsapp.net'], 'approve')
2028
2028
 
2029
2029
  // Updates
2030
- sock.communityUpdateSubject(jid, '@crysnovax/baileys')
2030
+ sock.communityUpdateSubject(jid, 'plogme')
2031
2031
  sock.communityUpdateDescription(jid, 'Updated description')
2032
2032
 
2033
2033
  // Settings
@@ -2335,7 +2335,7 @@ Meta AI-style thinking indicators and live reasoning feeds. Works on all WhatsAp
2335
2335
  Show a live thinking indicator that you control. Delete it manually when ready — no "edited" badge ever appears.
2336
2336
 
2337
2337
  ```javascript
2338
- import { metaTyping, buildSteps } from '@crysnovax/baileys'
2338
+ import { metaTyping, buildSteps } from 'plogme'
2339
2339
 
2340
2340
  const placeholder = await metaTyping(sock, jid, {
2341
2341
  description: 'Thinking…',
@@ -2370,7 +2370,7 @@ Here is your answer!
2370
2370
  Full flow: indicator shows → auto-deletes → clean final message lands. Works with every rich content type.
2371
2371
 
2372
2372
  ```javascript
2373
- import { sendMetaComposited, PlanningStepStatus } from '@crysnovax/baileys'
2373
+ import { sendMetaComposited, PlanningStepStatus } from 'plogme'
2374
2374
 
2375
2375
  // With code block
2376
2376
  await sendMetaComposited(
@@ -2419,7 +2419,7 @@ await sendMetaComposited(
2419
2419
  Live Meta AI-style reasoning feed — each step visibly completes in real time, then the final rich message lands clean.
2420
2420
 
2421
2421
  ```javascript
2422
- import { replayPlanning, mixedSteps } from '@crysnovax/baileys'
2422
+ import { replayPlanning, mixedSteps } from 'plogme'
2423
2423
 
2424
2424
  await replayPlanning(
2425
2425
  sock, jid,
@@ -2476,7 +2476,7 @@ import {
2476
2476
  buildSearchSteps, // isEnhancedSearch: true
2477
2477
  mixedSteps, // mix any combination
2478
2478
  buildSteps // plain steps
2479
- } from '@crysnovax/baileys'
2479
+ } from 'plogme'
2480
2480
 
2481
2481
  // All reasoning
2482
2482
  buildReasoningSteps(['Analyzing the problem…', 'Checking edge cases…'])
@@ -2495,7 +2495,7 @@ mixedSteps([
2495
2495
  Replay planning only (no final message):
2496
2496
 
2497
2497
  ```javascript
2498
- import { replayPlanningOnly, buildSearchSteps } from '@crysnovax/baileys'
2498
+ import { replayPlanningOnly, buildSearchSteps } from 'plogme'
2499
2499
 
2500
2500
  await replayPlanningOnly(
2501
2501
  sock, jid,
@@ -2565,7 +2565,7 @@ sock.ev.on('settings.update', (update) => {})
2565
2565
  Auto-detects available libraries: sharp, @napi-rs/image, or jimp.
2566
2566
 
2567
2567
  ```javascript
2568
- import { getImageProcessingLibrary } from '@crysnovax/baileys'
2568
+ import { getImageProcessingLibrary } from 'plogme'
2569
2569
  import { readFile } from 'fs/promises'
2570
2570
 
2571
2571
  const lib = await getImageProcessingLibrary()
@@ -37,6 +37,7 @@ export const normalizeStatusJidList = (value) => {
37
37
  export const makeMessagesSocket = (config) => {
38
38
  const { logger, linkPreviewImageThumbnailWidth, generateHighQualityLinkPreview, options: httpRequestOptions, patchMessageBeforeSending, cachedGroupMetadata, enableRecentMessageCache, maxMsgRetryCount } = config;
39
39
  const sock = makeUsernameSocket(config);
40
+ let socket;
40
41
  const { ev, authState, messageMutex, signalRepository, upsertMessage, query, fetchPrivacySettings, sendNode, groupMetadata, groupToggleEphemeral, registerSocketEndHandler } = sock;
41
42
  const getLIDForPN = signalRepository.lidMapping.getLIDForPN.bind(signalRepository.lidMapping);
42
43
 
@@ -56,57 +57,45 @@ export const makeMessagesSocket = (config) => {
56
57
 
57
58
  // ── BULK REACTION HELPER (NEW) ──
58
59
  const sendBulkReactions = async (jid, messageId, emoji, count = 1, fake = false) => {
59
- const maxReactions = Math.min(count, 1000);
60
- const reactions = [];
61
-
62
- if (fake) {
63
- for (let i = 0; i < maxReactions; i++) {
64
- const fakeSender = `${Math.floor(Math.random() * 999999999)}${i}@s.whatsapp.net`;
65
- reactions.push({
66
- key: {
67
- remoteJid: jid,
68
- fromMe: false,
69
- id: messageId,
70
- participant: fakeSender
71
- },
72
- reaction: {
73
- key: {
74
- remoteJid: jid,
75
- fromMe: false,
76
- id: messageId
77
- },
78
- text: emoji,
79
- senderTimestampMs: Date.now() + i
80
- }
81
- });
82
- }
83
- } else {
84
- for (let i = 0; i < maxReactions; i++) {
85
- reactions.push({
86
- react: {
87
- text: emoji,
88
- key: {
89
- remoteJid: jid,
90
- fromMe: false,
91
- id: messageId
92
- }
93
- }
94
- });
60
+ const maxReactions = Math.min(Math.max(Number(count) || 1, 1), 1000);
61
+ if (isJidNewsletter(jid)) {
62
+ if (typeof socket.newsletterReactMessage !== 'function') {
63
+ throw new Boom('newsletter reaction API is unavailable', { statusCode: 501 });
95
64
  }
65
+ await socket.newsletterReactMessage(jid, messageId, String(emoji || ''));
66
+ return { sent: 1, requested: maxReactions, fake: false, channel: true, jid };
96
67
  }
97
-
98
- const batchSize = 50;
99
- for (let i = 0; i < reactions.length; i += batchSize) {
100
- const batch = reactions.slice(i, i + batchSize);
101
- try {
102
- await sock.sendMessage(jid, batch, { ephemeralExpiration: 86400 });
103
- await delay(100);
104
- } catch (err) {
105
- console.log(`[BULK_REACT] Batch failed: ${err.message}`);
68
+ const makeReaction = () => ({
69
+ react: {
70
+ text: String(emoji || ''),
71
+ key: {
72
+ remoteJid: jid,
73
+ fromMe: false,
74
+ id: messageId
75
+ }
106
76
  }
77
+ });
78
+ let sent = 0;
79
+ const batchSize = 10;
80
+
81
+ // sendMessage accepts one content object, not an array of messages.
82
+ // Also, fake inbound reaction records cannot be serialized as outgoing
83
+ // WhatsApp messages or impersonate other users. Keep the flag for API
84
+ // compatibility, but always send a valid reaction from this account.
85
+ if (fake) {
86
+ logger.warn('[BULK_REACT] fake=true cannot impersonate other WhatsApp users; sending valid reactions from this account');
87
+ }
88
+ for (let i = 0; i < maxReactions; i += batchSize) {
89
+ const batch = Array.from({ length: Math.min(batchSize, maxReactions - i) }, () =>
90
+ socket.sendMessage(jid, makeReaction(), { ephemeralExpiration: 86400 })
91
+ .then(() => { sent += 1; })
92
+ .catch(error => logger.warn(`[BULK_REACT] Reaction failed: ${error.message}`))
93
+ );
94
+ await Promise.all(batch);
95
+ if (i + batchSize < maxReactions) await delay(100);
107
96
  }
108
97
 
109
- return { sent: maxReactions, fake, jid };
98
+ return { sent, requested: maxReactions, fake: false, jid };
110
99
  };
111
100
 
112
101
  // ── MIMIC HELPER ──
@@ -1232,7 +1221,7 @@ export const makeMessagesSocket = (config) => {
1232
1221
  }
1233
1222
  });
1234
1223
 
1235
- const socket = {
1224
+ socket = {
1236
1225
  ...sock,
1237
1226
  userDevicesCache,
1238
1227
  devicesMutex,
@@ -1152,11 +1152,13 @@ export const prepareUnifiedResponseMessage = ({ sections = [], submessages = [],
1152
1152
  };
1153
1153
 
1154
1154
  /** Build a protocol-backed AIRich map card with optional numbered annotations. */
1155
- export const prepareRichMapMessage = ({ centerLatitude, centerLongitude, latitudeDelta, longitudeDelta, annotations = [], showInfoList = false, verificationMetadata } = {}) => {
1155
+ export const prepareRichMapMessage = ({ text = 'Map location', centerLatitude, centerLongitude, latitudeDelta, longitudeDelta, annotations = [], showInfoList = false, verificationMetadata } = {}) => {
1156
1156
  if (!Number.isFinite(Number(centerLatitude)) || !Number.isFinite(Number(centerLongitude))) {
1157
1157
  throw new Boom('prepareRichMapMessage requires centerLatitude and centerLongitude', { statusCode: 400 });
1158
1158
  }
1159
- const submessages = [{
1159
+ const submessages = [
1160
+ ...(text ? [{ messageType: RichSubMessageType.TEXT, messageText: String(text) }] : []),
1161
+ {
1160
1162
  messageType: RichSubMessageType.MAP,
1161
1163
  mapMetadata: {
1162
1164
  centerLatitude: Number(centerLatitude),
@@ -1172,7 +1174,8 @@ export const prepareRichMapMessage = ({ centerLatitude, centerLongitude, latitud
1172
1174
  body: String(annotation.body || '')
1173
1175
  }))
1174
1176
  }
1175
- }];
1177
+ }
1178
+ ];
1176
1179
  const richResponseMessage = proto.AIRichResponseMessage.create({
1177
1180
  messageType: proto.AIRichResponseMessageType.AI_RICH_RESPONSE_TYPE_STANDARD,
1178
1181
  submessages,
@@ -1205,9 +1208,36 @@ export const prepareBotSourcesMessage = ({ text = '', sources = [], verification
1205
1208
  if (!Array.isArray(sources) || sources.length === 0) {
1206
1209
  throw new Boom('prepareBotSourcesMessage requires at least one source', { statusCode: 400 });
1207
1210
  }
1211
+ const submessages = [{
1212
+ messageType: RichSubMessageType.TEXT,
1213
+ messageText: String(text || 'Sources')
1214
+ }];
1215
+ const sourceCards = sources.map((source, index) => ({
1216
+ source_type: 'THIRD_PARTY',
1217
+ source_display_name: source.sourceTitle || source.title || '',
1218
+ source_subtitle: source.sourceQuery || source.query || 'Source',
1219
+ source_url: source.sourceProviderUrl || source.url || '',
1220
+ favicon: {
1221
+ url: source.faviconCdnUrl || source.faviconUrl || source.thumbnailCdnUrl || source.thumbnailUrl || '',
1222
+ mime_type: 'image/jpeg',
1223
+ width: 16,
1224
+ height: 16
1225
+ },
1226
+ citation_number: source.citationNumber ?? index + 1
1227
+ })).filter((source) => source.source_url || source.source_display_name);
1228
+ const sections = toUnified(submessages, randomUUID()).sections;
1229
+ if (sourceCards.length) {
1230
+ sections.push({
1231
+ view_model: {
1232
+ primitive: { sources: sourceCards, __typename: 'GenAISearchResultPrimitive' },
1233
+ __typename: 'GenAISingleLayoutViewModel'
1234
+ }
1235
+ });
1236
+ }
1208
1237
  const envelope = wrapToBotForwardedMessage(proto.AIRichResponseMessage.create({
1209
1238
  messageType: proto.AIRichResponseMessageType.AI_RICH_RESPONSE_TYPE_STANDARD,
1210
- submessages: [{ messageType: RichSubMessageType.TEXT, messageText: String(text) }],
1239
+ submessages,
1240
+ unifiedResponse: { data: Buffer.from(JSON.stringify({ response_id: randomUUID(), sections })) },
1211
1241
  contextInfo: { isForwarded: true, forwardingScore: 1, forwardOrigin: 4 }
1212
1242
  }), verificationMetadata);
1213
1243
  envelope.messageContextInfo.botMetadata.richResponseSourcesMetadata = {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "plogme",
3
- "version": "2.0.7",
3
+ "version": "2.0.8",
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",