@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.
- package/lib/AntiBan/antiban.js +922 -0
- package/lib/AntiBan/banRecoveryOrchestrator.js +284 -0
- package/lib/AntiBan/cli.js +177 -0
- package/lib/AntiBan/contactGraph.js +236 -0
- package/lib/AntiBan/contentVariator.js +150 -0
- package/lib/AntiBan/credsSnapshot.js +121 -0
- package/lib/AntiBan/deliveryTracker.js +107 -0
- package/lib/AntiBan/deviceFingerprint.js +106 -0
- package/lib/AntiBan/fleetEventStore.js +157 -0
- package/lib/AntiBan/groupOperationGuard.js +116 -0
- package/lib/AntiBan/health.js +207 -0
- package/lib/AntiBan/humanEntropy.js +337 -0
- package/lib/AntiBan/index.js +77 -0
- package/lib/AntiBan/instanceCoordinator.js +175 -0
- package/lib/AntiBan/jidCanonicalizer.js +256 -0
- package/lib/AntiBan/jidCircuitBreaker.js +186 -0
- package/lib/AntiBan/legitimacySignalInjector.js +231 -0
- package/lib/AntiBan/lidFirstResolver.js +174 -0
- package/lib/AntiBan/lidResolver.js +324 -0
- package/lib/AntiBan/messageQueue.js +187 -0
- package/lib/AntiBan/messageRecovery.js +283 -0
- package/lib/AntiBan/messageTypeRegistry.js +369 -0
- package/lib/AntiBan/observability.js +145 -0
- package/lib/AntiBan/patch.js +302 -0
- package/lib/AntiBan/persist.js +87 -0
- package/lib/AntiBan/presenceChoreographer.js +430 -0
- package/lib/AntiBan/presets.js +105 -0
- package/lib/AntiBan/profiles.js +31 -0
- package/lib/AntiBan/proxyRotator.js +306 -0
- package/lib/AntiBan/rateLimiter.js +261 -0
- package/lib/AntiBan/readReceiptVariance.js +88 -0
- package/lib/AntiBan/reconnectThrottle.js +180 -0
- package/lib/AntiBan/replyRatio.js +161 -0
- package/lib/AntiBan/reputationVoucher.js +373 -0
- package/lib/AntiBan/retryReason.js +91 -0
- package/lib/AntiBan/retryTracker.js +172 -0
- package/lib/AntiBan/scheduler.js +111 -0
- package/lib/AntiBan/sessionFingerprint.js +248 -0
- package/lib/AntiBan/sessionStability.js +330 -0
- package/lib/AntiBan/stateAdapter.js +73 -0
- package/lib/AntiBan/stateExport.js +152 -0
- package/lib/AntiBan/stealthConnect.js +130 -0
- package/lib/AntiBan/timelockGuard.js +181 -0
- package/lib/AntiBan/topologyThrottler.js +339 -0
- package/lib/AntiBan/warmup.js +140 -0
- package/lib/AntiBan/webhooks.js +80 -0
- package/lib/AntiBan/wrapper.js +456 -0
- package/lib/Socket/groups.js +26 -21
- package/lib/Socket/index.js +139 -7
- package/lib/Socket/messages-send.js +68 -5
- package/lib/Utils/ai-rich-formatter.js +256 -0
- package/lib/Utils/index.js +1 -0
- package/lib/index.js +1 -1
- package/package.json +1 -1
package/lib/Socket/index.js
CHANGED
|
@@ -2,28 +2,160 @@ import { DEFAULT_CONNECTION_CONFIG } from "../Defaults/index.js";
|
|
|
2
2
|
import { makeCommunitiesSocket } from "./communities.js";
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
|
-
*
|
|
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
|
-
|
|
22
|
-
|
|
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
|
-
|
|
849
|
-
|
|
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
|
-
|
|
880
|
+
for (const s of statusJidList) addParticipantJid(s);
|
|
859
881
|
}
|
|
860
|
-
|
|
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
|
+
}
|
package/lib/Utils/index.js
CHANGED
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;
|