@prototypevip/baileys 0.0.8 → 0.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.
Files changed (54) hide show
  1. package/lib/AntiBan/antiban.js +922 -0
  2. package/lib/AntiBan/banRecoveryOrchestrator.js +284 -0
  3. package/lib/AntiBan/cli.js +177 -0
  4. package/lib/AntiBan/contactGraph.js +236 -0
  5. package/lib/AntiBan/contentVariator.js +150 -0
  6. package/lib/AntiBan/credsSnapshot.js +121 -0
  7. package/lib/AntiBan/deliveryTracker.js +107 -0
  8. package/lib/AntiBan/deviceFingerprint.js +106 -0
  9. package/lib/AntiBan/fleetEventStore.js +157 -0
  10. package/lib/AntiBan/groupOperationGuard.js +116 -0
  11. package/lib/AntiBan/health.js +207 -0
  12. package/lib/AntiBan/humanEntropy.js +337 -0
  13. package/lib/AntiBan/index.js +77 -0
  14. package/lib/AntiBan/instanceCoordinator.js +175 -0
  15. package/lib/AntiBan/jidCanonicalizer.js +256 -0
  16. package/lib/AntiBan/jidCircuitBreaker.js +186 -0
  17. package/lib/AntiBan/legitimacySignalInjector.js +231 -0
  18. package/lib/AntiBan/lidFirstResolver.js +174 -0
  19. package/lib/AntiBan/lidResolver.js +324 -0
  20. package/lib/AntiBan/messageQueue.js +187 -0
  21. package/lib/AntiBan/messageRecovery.js +283 -0
  22. package/lib/AntiBan/messageTypeRegistry.js +369 -0
  23. package/lib/AntiBan/observability.js +145 -0
  24. package/lib/AntiBan/patch.js +302 -0
  25. package/lib/AntiBan/persist.js +87 -0
  26. package/lib/AntiBan/presenceChoreographer.js +430 -0
  27. package/lib/AntiBan/presets.js +105 -0
  28. package/lib/AntiBan/profiles.js +31 -0
  29. package/lib/AntiBan/proxyRotator.js +306 -0
  30. package/lib/AntiBan/rateLimiter.js +261 -0
  31. package/lib/AntiBan/readReceiptVariance.js +88 -0
  32. package/lib/AntiBan/reconnectThrottle.js +180 -0
  33. package/lib/AntiBan/replyRatio.js +161 -0
  34. package/lib/AntiBan/reputationVoucher.js +373 -0
  35. package/lib/AntiBan/retryReason.js +91 -0
  36. package/lib/AntiBan/retryTracker.js +172 -0
  37. package/lib/AntiBan/scheduler.js +111 -0
  38. package/lib/AntiBan/sessionFingerprint.js +248 -0
  39. package/lib/AntiBan/sessionStability.js +330 -0
  40. package/lib/AntiBan/stateAdapter.js +73 -0
  41. package/lib/AntiBan/stateExport.js +152 -0
  42. package/lib/AntiBan/stealthConnect.js +130 -0
  43. package/lib/AntiBan/timelockGuard.js +181 -0
  44. package/lib/AntiBan/topologyThrottler.js +339 -0
  45. package/lib/AntiBan/warmup.js +140 -0
  46. package/lib/AntiBan/webhooks.js +80 -0
  47. package/lib/AntiBan/wrapper.js +456 -0
  48. package/lib/Socket/groups.js +26 -21
  49. package/lib/Socket/index.js +139 -7
  50. package/lib/Socket/messages-send.js +68 -5
  51. package/lib/Utils/ai-rich-formatter.js +256 -0
  52. package/lib/Utils/index.js +1 -0
  53. package/lib/index.js +1 -1
  54. package/package.json +1 -1
@@ -2,28 +2,160 @@ import { DEFAULT_CONNECTION_CONFIG } from "../Defaults/index.js";
2
2
  import { makeCommunitiesSocket } from "./communities.js";
3
3
 
4
4
  /**
5
- * Create a WhatsApp socket (clean — no anti-ban wrapper).
5
+ * Optional AntiBan — مقفول افتراضياً.
6
+ * لتفعيله مرّر في إعدادات makeWASocket:
7
+ * makeWASocket({ antiBan: true }) // moderate preset
8
+ * makeWASocket({ antiBan: 'conservative' }) // preset name
9
+ * makeWASocket({ antiBan: { maxPerMinute: 8, ... } }) // config مخصص
10
+ * makeWASocket({ antiBan: false }) // صراحة مقفول (الافتراضي)
11
+ *
12
+ * الحالة الاختيارية:
13
+ * antiBanWarmUpState — حالة الـ warmup المحفوظة
14
+ * antiBanWrapOptions — خيارات إضافية لـ wrapSocket
15
+ */
16
+
17
+ let _wrapSocket = null;
18
+ let _wrapSocketWithFingerprint = null;
19
+ let _PRESETS = {};
20
+ let _antiBanLoadError = null;
21
+
22
+ async function loadAntiBan() {
23
+ if (_wrapSocket) return true;
24
+ if (_antiBanLoadError) return false;
25
+ try {
26
+ const mod = await import("../AntiBan/index.js");
27
+ _wrapSocket = mod.wrapSocket;
28
+ _wrapSocketWithFingerprint = mod.wrapSocketWithFingerprint;
29
+ _PRESETS = mod.PRESETS || {};
30
+ return true;
31
+ } catch (e) {
32
+ // fallback: try wrapper export path
33
+ try {
34
+ const wrap = await import("../AntiBan/wrapper.js");
35
+ const presets = await import("../AntiBan/presets.js").catch(() => ({}));
36
+ _wrapSocket = wrap.wrapSocket;
37
+ _wrapSocketWithFingerprint = wrap.wrapSocketWithFingerprint;
38
+ _PRESETS = presets.PRESETS || {};
39
+ return true;
40
+ } catch (e2) {
41
+ _antiBanLoadError = e2;
42
+ console.warn(
43
+ "[@prototypevip/baileys] AntiBan module failed to load — continuing without it:",
44
+ e2?.message || e2
45
+ );
46
+ return false;
47
+ }
48
+ }
49
+ }
50
+
51
+ // Sync load attempt for ESM top-level (best-effort)
52
+ try {
53
+ const wrap = await import("../AntiBan/wrapper.js");
54
+ _wrapSocket = wrap.wrapSocket;
55
+ _wrapSocketWithFingerprint = wrap.wrapSocketWithFingerprint;
56
+ try {
57
+ const presets = await import("../AntiBan/presets.js");
58
+ _PRESETS = presets.PRESETS || {};
59
+ } catch {}
60
+ } catch (e) {
61
+ _antiBanLoadError = e;
62
+ }
63
+
64
+ /**
65
+ * Create a WhatsApp socket.
66
+ * AntiBan مقفول افتراضياً — فعّله عبر config.antiBan
6
67
  */
7
68
  const makeWASocket = (config = {}) => {
8
- // strip antiBan options if present so they don't leak into internal config
9
69
  const {
10
- antiBan,
70
+ antiBan = false, // مقفول افتراضياً
11
71
  antiBanWarmUpState,
12
72
  antiBanWrapOptions,
13
73
  ...restConfig
14
- } = config;
74
+ } = config || {};
15
75
 
16
76
  delete restConfig.userDevicesCache;
17
77
  const newConfig = { ...DEFAULT_CONNECTION_CONFIG, ...restConfig };
18
78
 
19
79
  let sock;
20
80
  const originalGetMessage = newConfig.getMessage;
21
- newConfig.getMessage = async function (key) {
22
- return originalGetMessage.call(sock || this, key);
23
- };
81
+ if (typeof originalGetMessage === "function") {
82
+ newConfig.getMessage = async function (key) {
83
+ return originalGetMessage.call(sock || this, key);
84
+ };
85
+ }
24
86
 
25
87
  sock = makeCommunitiesSocket(newConfig);
88
+
89
+ // ── AntiBan (اختياري) ──
90
+ const enabled =
91
+ antiBan === true ||
92
+ (typeof antiBan === "string" && antiBan.length > 0) ||
93
+ (antiBan && typeof antiBan === "object");
94
+
95
+ if (enabled) {
96
+ if (typeof _wrapSocket !== "function") {
97
+ console.warn(
98
+ "[@prototypevip/baileys] antiBan requested but module not available — socket without protection"
99
+ );
100
+ return sock;
101
+ }
102
+
103
+ const antiBanConfig =
104
+ antiBan === true
105
+ ? "moderate"
106
+ : antiBan; // string preset or object config
107
+
108
+ try {
109
+ sock = _wrapSocket(
110
+ sock,
111
+ antiBanConfig,
112
+ antiBanWarmUpState,
113
+ antiBanWrapOptions || {}
114
+ );
115
+ if (newConfig.logger?.info) {
116
+ newConfig.logger.info(
117
+ { antiBan: typeof antiBanConfig === "string" ? antiBanConfig : "custom" },
118
+ "AntiBan protection enabled"
119
+ );
120
+ }
121
+ } catch (e) {
122
+ console.warn(
123
+ "[@prototypevip/baileys] AntiBan wrap failed — continuing without it:",
124
+ e?.message || e
125
+ );
126
+ }
127
+ }
128
+
26
129
  return sock;
27
130
  };
28
131
 
132
+ /** Pass-through stubs when antiban is not loaded; real functions when loaded */
133
+ const wrapSocket = (sock, ...args) =>
134
+ typeof _wrapSocket === "function" ? _wrapSocket(sock, ...args) : sock;
135
+
136
+ const wrapSocketWithFingerprint = (makeSock, opts, wrapOpts) => {
137
+ if (typeof _wrapSocketWithFingerprint === "function") {
138
+ return _wrapSocketWithFingerprint(makeSock, opts, wrapOpts);
139
+ }
140
+ return typeof makeSock === "function" ? makeSock(opts || {}) : makeSock;
141
+ };
142
+
143
+ const PRESETS = new Proxy(
144
+ {},
145
+ {
146
+ get(_, prop) {
147
+ return _PRESETS[prop];
148
+ },
149
+ ownKeys() {
150
+ return Reflect.ownKeys(_PRESETS);
151
+ },
152
+ getOwnPropertyDescriptor(_, prop) {
153
+ if (prop in _PRESETS) {
154
+ return { enumerable: true, configurable: true, value: _PRESETS[prop] };
155
+ }
156
+ },
157
+ }
158
+ );
159
+
29
160
  export default makeWASocket;
161
+ export { makeWASocket, wrapSocket, wrapSocketWithFingerprint, PRESETS };
@@ -845,9 +845,31 @@ export const makeMessagesSocket = (config) => {
845
845
  return {};
846
846
  })(),
847
847
  ]);
848
- const participantsList = groupData?.participants
849
- ? groupData.participants.map((p) => p.id)
850
- : [];
848
+ // نبني قائمة المشاركين + بدائل LID/PN عشان حسابات اليوزرنيم
849
+ // (اللي أحياناً USync بيرجع فاضي لو استعلمنا بصيغة واحدة بس)
850
+ const participantsList = [];
851
+ const seenParticipantUsers = new Set();
852
+ const addParticipantJid = (jid) => {
853
+ if (!jid || typeof jid !== "string") return;
854
+ const normalized = jidNormalizedUser(jid);
855
+ const user = jidDecode(normalized)?.user;
856
+ if (!user || seenParticipantUsers.has(user + ":" + (normalized.split("@")[1] || ""))) {
857
+ // نسمح بنفس الـ user بصيغتين مختلفتين (pn + lid) بس نمنع التكرار الحرفي
858
+ }
859
+ if (participantsList.includes(normalized) || participantsList.includes(jid)) return;
860
+ participantsList.push(normalized);
861
+ if (user) seenParticipantUsers.add(user);
862
+ };
863
+ if (groupData?.participants) {
864
+ for (const p of groupData.participants) {
865
+ addParticipantJid(p.id);
866
+ // بديل LID لو الـ id رقم (PN) — مهم لحسابات اليوزرنيم
867
+ if (p.lid) addParticipantJid(p.lid);
868
+ // بديل الرقم لو الـ id LID
869
+ if (p.phoneNumber) addParticipantJid(p.phoneNumber);
870
+ if (p.jid && p.jid !== p.id) addParticipantJid(p.jid);
871
+ }
872
+ }
851
873
  if (groupData?.ephemeralDuration && groupData.ephemeralDuration > 0) {
852
874
  additionalAttributes = {
853
875
  ...additionalAttributes,
@@ -855,13 +877,54 @@ export const makeMessagesSocket = (config) => {
855
877
  };
856
878
  }
857
879
  if (isStatus && statusJidList) {
858
- participantsList.push(...statusJidList);
880
+ for (const s of statusJidList) addParticipantJid(s);
859
881
  }
860
- const additionalDevices = await getUSyncDevices(
882
+ let additionalDevices = await getUSyncDevices(
861
883
  participantsList,
862
884
  !!useUserDevicesCache,
863
885
  false,
864
886
  );
887
+ // لو في مشاركين معرفين في الميتاداتا ومفيش أي device ليهم في النتيجة
888
+ // (شائع مع username/LID)، نعيد الاستعلام من غير كاش وبمهلة أطول
889
+ // على الـ JIDs الناقصة فقط — من غير ما نأثر على باقي الجروب
890
+ if (groupData?.participants?.length) {
891
+ const coveredUsers = new Set(
892
+ additionalDevices
893
+ .map((d) => d.user || jidDecode(d.jid)?.user)
894
+ .filter(Boolean),
895
+ );
896
+ const missingJids = [];
897
+ for (const p of groupData.participants) {
898
+ const candidates = [p.id, p.lid, p.phoneNumber, p.jid].filter(Boolean);
899
+ const userIds = candidates
900
+ .map((j) => jidDecode(jidNormalizedUser(j))?.user)
901
+ .filter(Boolean);
902
+ if (userIds.some((u) => coveredUsers.has(u))) continue;
903
+ // جرب LID أولاً لو موجود (أحسن لليوزرنيم)، وإلا id الأصلي
904
+ if (p.lid) missingJids.push(jidNormalizedUser(p.lid));
905
+ else if (p.id) missingJids.push(jidNormalizedUser(p.id));
906
+ else if (p.phoneNumber) missingJids.push(jidNormalizedUser(p.phoneNumber));
907
+ }
908
+ if (missingJids.length > 0) {
909
+ logger.debug(
910
+ { missing: missingJids.length, jids: missingJids.slice(0, 5) },
911
+ "retrying USync for participants with no devices (likely username/LID)",
912
+ );
913
+ try {
914
+ const retryDevices = await getUSyncDevices(
915
+ missingJids,
916
+ false, // no cache
917
+ false,
918
+ 8000, // longer timeout
919
+ );
920
+ if (retryDevices?.length) {
921
+ additionalDevices = [...additionalDevices, ...retryDevices];
922
+ }
923
+ } catch (e) {
924
+ logger.warn({ e }, "USync retry for missing participants failed");
925
+ }
926
+ }
927
+ }
865
928
  devices.push(...additionalDevices);
866
929
  if (isGroup) {
867
930
  additionalAttributes = {
@@ -0,0 +1,256 @@
1
+ /**
2
+ * AI Rich Formatter helpers
3
+ * Extracted helpers for parsing AI responses and sending unified rich messages
4
+ * via AIRich (message-builder).
5
+ *
6
+ * Used by AI bot commands (Claude, Gemini, etc.)
7
+ */
8
+
9
+ import { AIRich } from './message-builder.js';
10
+
11
+ /**
12
+ * Parse a markdown table string into rows (string[][])
13
+ * First row is typically the header.
14
+ */
15
+ export function parseMarkdownTable(tableString) {
16
+ const lines = tableString.trim().split('\n');
17
+ const rows = [];
18
+
19
+ for (let line of lines) {
20
+ line = line.trim();
21
+ if (line.replace(/[\s|:-]/g, '') === '') continue;
22
+
23
+ let items = line.split('|').map((c) => c.trim());
24
+ if (items[0] === '') items.shift();
25
+ if (items[items.length - 1] === '') items.pop();
26
+
27
+ if (items.length > 0) rows.push(items);
28
+ }
29
+ return rows;
30
+ }
31
+
32
+ /**
33
+ * Extract code blocks, tables, sources, and special action tags
34
+ * (exec / group / commands / db) from an AI response text.
35
+ */
36
+ export function extractElements(text) {
37
+ const blocks = [];
38
+ const execBlocks = [];
39
+ const groupBlocks = [];
40
+ const commandsBlocks = [];
41
+ const dbBlocks = [];
42
+ const tables = [];
43
+ const sources = [];
44
+ let clean = text;
45
+
46
+ const codeRegex = /```(\w*)\n?([\s\S]*?)```/g;
47
+ let codeMatch;
48
+ while ((codeMatch = codeRegex.exec(text)) !== null) {
49
+ const lang = codeMatch[1].trim().toLowerCase() || 'javascript';
50
+ const code = codeMatch[2].trim();
51
+ if (code) {
52
+ if (lang === 'exec') execBlocks.push(code);
53
+ else if (lang === 'group') groupBlocks.push(code);
54
+ else if (lang === 'commands') commandsBlocks.push(code);
55
+ else if (lang === 'db') dbBlocks.push(code);
56
+ else blocks.push({ lang, code });
57
+ }
58
+ clean = clean.replace(codeMatch[0], '');
59
+ }
60
+
61
+ // Safety net: model wrote [group]/[db]/[commands]/[exec] without real code fences
62
+ const looseTagRegex =
63
+ /\[(group|db|commands|exec)(?:\s+\w+)?\]\s*\n?([\s\S]*?)(?=\n\[(?:group|db|commands|exec)(?:\s+\w+)?\]|$)/gi;
64
+ let looseMatch;
65
+ while ((looseMatch = looseTagRegex.exec(clean)) !== null) {
66
+ const tag = looseMatch[1].toLowerCase();
67
+ const payload = looseMatch[2].trim();
68
+ if (!payload) continue;
69
+ if (tag === 'exec') execBlocks.push(payload);
70
+ else if (tag === 'group') groupBlocks.push(payload);
71
+ else if (tag === 'commands') commandsBlocks.push(payload);
72
+ else if (tag === 'db') dbBlocks.push(payload);
73
+ clean = clean.replace(looseMatch[0], '');
74
+ }
75
+
76
+ const linkRegex = /\[([^\]]+)\]\((https?:\/\/[^\s)]+)\)/g;
77
+ let linkMatch;
78
+ const seenUrls = new Set();
79
+ while ((linkMatch = linkRegex.exec(clean)) !== null) {
80
+ const label = linkMatch[1].trim();
81
+ const url = linkMatch[2].trim();
82
+ if (!seenUrls.has(url)) {
83
+ seenUrls.add(url);
84
+ sources.push({ label, url });
85
+ }
86
+ }
87
+
88
+ linkRegex.lastIndex = 0;
89
+ clean = clean.replace(linkRegex, '$1');
90
+
91
+ const lines = clean.split('\n');
92
+ let currentTableLines = [];
93
+ let newCleanLines = [];
94
+ let inTable = false;
95
+
96
+ for (let line of lines) {
97
+ if (line.trim().startsWith('|') && line.trim().endsWith('|')) {
98
+ inTable = true;
99
+ currentTableLines.push(line);
100
+ } else {
101
+ if (inTable) {
102
+ const parsed = parseMarkdownTable(currentTableLines.join('\n'));
103
+ if (parsed.length > 0) tables.push(parsed);
104
+ currentTableLines = [];
105
+ inTable = false;
106
+ }
107
+ newCleanLines.push(line);
108
+ }
109
+ }
110
+ if (inTable && currentTableLines.length > 0) {
111
+ const parsed = parseMarkdownTable(currentTableLines.join('\n'));
112
+ if (parsed.length > 0) tables.push(parsed);
113
+ }
114
+
115
+ clean = newCleanLines.join('\n').trim();
116
+ const finalMergedCode = blocks
117
+ .map((b) => b.code)
118
+ .join('\n\n// ──────────────────────────────────────────\n\n');
119
+ const primaryLang = blocks.length > 0 ? blocks[0].lang : 'javascript';
120
+
121
+ return {
122
+ clean,
123
+ finalMergedCode,
124
+ primaryLang,
125
+ hasCode: blocks.length > 0,
126
+ tables,
127
+ sources,
128
+ execBlocks,
129
+ groupBlocks,
130
+ commandsBlocks,
131
+ dbBlocks,
132
+ };
133
+ }
134
+
135
+ /**
136
+ * Build and send a unified rich AI message (text + tables + code + sources + action results).
137
+ * Falls back to plain text if the rich send fails.
138
+ */
139
+ export async function sendUnifiedMetaMessage(
140
+ prototype,
141
+ chatId,
142
+ m,
143
+ {
144
+ textOnly,
145
+ tables,
146
+ hasCode,
147
+ finalMergedCode,
148
+ primaryLang,
149
+ sources,
150
+ sig,
151
+ execResults,
152
+ groupResults,
153
+ commandsResults,
154
+ dbResults,
155
+ }
156
+ ) {
157
+ try {
158
+ const rich = new AIRich(prototype);
159
+
160
+ // 1. Text
161
+ rich.addText((textOnly || '🤖 تم إنشاء الرد بنجاح') + (sig || ''));
162
+
163
+ // 2. Tables
164
+ if (tables && tables.length > 0) {
165
+ for (const tableRows of tables) {
166
+ if (Array.isArray(tableRows) && tableRows.length > 0) {
167
+ rich.addTable(tableRows);
168
+ }
169
+ }
170
+ }
171
+
172
+ // 3. Colored code
173
+ if (hasCode && finalMergedCode) {
174
+ rich.addCode(primaryLang, finalMergedCode);
175
+ }
176
+
177
+ // 4. Exec results (file edit/create/delete)
178
+ if (Array.isArray(execResults) && execResults.length > 0) {
179
+ for (const r of execResults) {
180
+ rich.addText(`${r.ok ? '✅' : '❌'} تنفيذ: ${r.command}`);
181
+ rich.addCode('bash', r.output);
182
+ }
183
+ }
184
+
185
+ // 5. Group action results
186
+ if (Array.isArray(groupResults) && groupResults.length > 0) {
187
+ for (const r of groupResults) {
188
+ rich.addText(`${r.ok ? '✅' : '❌'} ${r.output}`);
189
+ }
190
+ }
191
+
192
+ // 6. Commands list/count results
193
+ if (Array.isArray(commandsResults) && commandsResults.length > 0) {
194
+ for (const r of commandsResults) {
195
+ rich.addText(`${r.ok ? '✅' : '❌'} ${r.output}`);
196
+ }
197
+ }
198
+
199
+ // 7. Database results
200
+ if (Array.isArray(dbResults) && dbResults.length > 0) {
201
+ for (const r of dbResults) {
202
+ rich.addText(`${r.ok ? '✅' : '❌'} نتيجة قاعدة البيانات:`);
203
+ rich.addCode('json', r.output);
204
+ }
205
+ }
206
+
207
+ // 8. Sources ("See details")
208
+ if (Array.isArray(sources) && sources.length > 0) {
209
+ const defaultIcon = 'https://files.catbox.moe/9qffq1.jpg';
210
+ rich.addSource(sources.slice(0, 10).map((s) => [defaultIcon, s.url, s.label]));
211
+ }
212
+
213
+ await rich.send(chatId, { quoted: m });
214
+ } catch (sendErr) {
215
+ console.warn('⚠️ فشل إرسال الرسالة الغنية، إرسال نسخة نصية بديلة:', sendErr.message);
216
+
217
+ let fallbackText = textOnly || '🤖 تم إنشاء الرد بنجاح';
218
+ if (hasCode && finalMergedCode) {
219
+ fallbackText += `\n\n\`\`\`${primaryLang}\n${finalMergedCode}\n\`\`\``;
220
+ }
221
+ if (Array.isArray(execResults) && execResults.length > 0) {
222
+ fallbackText +=
223
+ '\n\n' +
224
+ execResults
225
+ .map(
226
+ (r) =>
227
+ `${r.ok ? '✅' : '❌'} ${r.command}\n\`\`\`bash\n${r.output}\n\`\`\``
228
+ )
229
+ .join('\n\n');
230
+ }
231
+ if (Array.isArray(groupResults) && groupResults.length > 0) {
232
+ fallbackText +=
233
+ '\n\n' + groupResults.map((r) => `${r.ok ? '✅' : '❌'} ${r.output}`).join('\n');
234
+ }
235
+ if (Array.isArray(commandsResults) && commandsResults.length > 0) {
236
+ fallbackText +=
237
+ '\n\n' +
238
+ commandsResults.map((r) => `${r.ok ? '✅' : '❌'} ${r.output}`).join('\n');
239
+ }
240
+ if (Array.isArray(dbResults) && dbResults.length > 0) {
241
+ fallbackText +=
242
+ '\n\n' +
243
+ dbResults
244
+ .map((r) => `${r.ok ? '✅' : '❌'} \`\`\`json\n${r.output}\n\`\`\``)
245
+ .join('\n');
246
+ }
247
+ if (Array.isArray(sources) && sources.length > 0) {
248
+ fallbackText +=
249
+ `\n\n🔗 *مصادر:*\n` +
250
+ sources.slice(0, 10).map((s) => `• ${s.label}: ${s.url}`).join('\n');
251
+ }
252
+ fallbackText += sig || '';
253
+
254
+ await prototype.sendMessage(chatId, { text: fallbackText }, { quoted: m });
255
+ }
256
+ }
@@ -27,4 +27,5 @@ export * from "./use-prototype-auth-state.js";
27
27
  export * from "./sticker-utils.js";
28
28
  export * from "./rich-message-utils.js";
29
29
  export * from "./message-builder.js";
30
+ export * from "./ai-rich-formatter.js";
30
31
  export * from "./constants.js";
package/lib/index.js CHANGED
@@ -9,7 +9,7 @@ export * from "./WAM/index.js";
9
9
  export * from "./WAUSync/index.js";
10
10
  export * from "./Store/cache-factory.js";
11
11
 
12
- export { wrapSocket, wrapSocketWithFingerprint } from "./Socket/index.js";
12
+ export { wrapSocket, wrapSocketWithFingerprint, PRESETS } from "./Socket/index.js";
13
13
 
14
14
  export { makeWASocket };
15
15
  export default makeWASocket;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@prototypevip/baileys",
3
- "version": "0.0.8",
3
+ "version": "0.0.9",
4
4
  "description": "Baileys fork (@prototypevip/baileys) — clean, without anti-ban",
5
5
  "main": "lib/index.js",
6
6
  "type": "module",