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 +19 -19
- package/lib/Socket/messages-send.js +36 -47
- package/lib/Utils/rich-message-utils.js +34 -4
- package/package.json +1 -1
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
|
-
|
|
42
|
+
The published package is available from npm:
|
|
43
43
|
|
|
44
44
|
```bash
|
|
45
|
-
npm install
|
|
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 '
|
|
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
|
|
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: '
|
|
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('
|
|
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: '
|
|
1910
|
-
sock.newsletterUpdateName('1231111111111@newsletter', '
|
|
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('
|
|
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, '
|
|
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, '
|
|
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('
|
|
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, '
|
|
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 '
|
|
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 '
|
|
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 '
|
|
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 '
|
|
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 '
|
|
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 '
|
|
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
|
-
|
|
61
|
-
|
|
62
|
-
|
|
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
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
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
|
-
|
|
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
|
|
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.
|
|
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",
|