levix-bot 3.3.0-rc.2 → 4.0.0-beta
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 +11 -7
- package/app.cjs +42 -45
- package/package.json +9 -1
- package/public/dashboard/assets/index-C1b7ijfu.js +391 -0
- package/public/dashboard/assets/index-pYaivHON.css +1 -0
- package/public/dashboard/index.html +19 -0
- package/public/dashboard.css +391 -66
- package/public/dashboard.js +593 -42
- package/scheduler.cjs +9 -14
- package/src/auth/use-database-auth-state.js +2 -4
- package/src/bootstrap/core.js +2 -5
- package/src/bootstrap/panel.js +10 -5
- package/src/cli.js +3 -5
- package/src/commands/autoschedule.cjs +1 -4
- package/src/commands/blacklist.cjs +22 -20
- package/src/commands/block.cjs +2 -4
- package/src/commands/calc.cjs +9 -16
- package/src/commands/digit.cjs +97 -0
- package/src/commands/gemini.cjs +147 -161
- package/src/commands/group/add.cjs +7 -16
- package/src/commands/group/antiSpam.cjs +5 -11
- package/src/commands/group/antilink.cjs +34 -28
- package/src/commands/group/approveall.cjs +3 -11
- package/src/commands/group/clearwarns.cjs +2 -5
- package/src/commands/group/demote.cjs +3 -8
- package/src/commands/group/kick.cjs +12 -15
- package/src/commands/group/media.cjs +17 -24
- package/src/commands/group/members.cjs +1 -2
- package/src/commands/group/promote.cjs +4 -12
- package/src/commands/group/removeall.cjs +2 -5
- package/src/commands/group/setpp.cjs +1 -1
- package/src/commands/group/setrules.cjs +2 -8
- package/src/commands/group/setwarn.cjs +4 -2
- package/src/commands/group/tagadmins.cjs +2 -5
- package/src/commands/group/warn.cjs +26 -24
- package/src/commands/group/warns.cjs +1 -2
- package/src/commands/group/welcome.cjs +13 -17
- package/src/commands/group.cjs +7 -10
- package/src/commands/help.cjs +6 -12
- package/src/commands/lang.cjs +104 -0
- package/src/commands/listschedules.cjs +2 -6
- package/src/commands/loop.cjs +6 -13
- package/src/commands/memory.cjs +19 -32
- package/src/commands/mod.cjs +97 -35
- package/src/commands/perm.cjs +18 -56
- package/src/commands/ping.cjs +1 -5
- package/src/commands/poll.cjs +1 -1
- package/src/commands/rand.cjs +2 -5
- package/src/commands/schedule.cjs +4 -8
- package/src/commands/score.cjs +8 -2
- package/src/commands/setprefix.cjs +2 -2
- package/src/commands/shortlink.cjs +7 -15
- package/src/commands/shutdown.cjs +1 -1
- package/src/commands/sticker.cjs +222 -0
- package/src/commands/stt.cjs +136 -68
- package/src/commands/todo.cjs +9 -15
- package/src/commands/tts.cjs +10 -16
- package/src/commands/unblock.cjs +2 -6
- package/src/commands/weather.cjs +5 -12
- package/src/config/ai-persona.md +5 -3
- package/src/config/available-models.json +1156 -0
- package/src/config/baileys.config.js +2 -1
- package/src/config/brand.esm.js +1 -10
- package/src/config/constants.js +1 -1
- package/src/config/defaults.cjs +66 -66
- package/src/config/lock.cjs +2 -2
- package/src/config/modelCapabilities.cjs +172 -0
- package/src/config/runtime-config.cjs +8 -13
- package/src/config/secrets.cjs +18 -10
- package/src/config/settings.cjs +94 -10
- package/src/config/vault.cjs +107 -0
- package/src/core/connection.js +13 -12
- package/src/core/events.js +41 -23
- package/src/core/proxy.js +7 -7
- package/src/core/session.js +91 -48
- package/src/core/socket.js +12 -15
- package/src/db/db.cjs +14 -6
- package/src/db/store.cjs +221 -87
- package/src/domain/caddy.js +1 -1
- package/src/domain/command.js +40 -19
- package/src/domain/detect.js +1 -1
- package/src/domain/system.js +2 -5
- package/src/handlers/command.handler.js +22 -43
- package/src/handlers/group.handler.js +13 -13
- package/src/handlers/message.handler.js +11 -21
- package/src/index.js +8 -4
- package/src/middleware/antispam.middleware.js +46 -23
- package/src/middleware/blacklist.middleware.js +14 -9
- package/src/middleware/forward-tracking.middleware.js +3 -2
- package/src/middleware/permissions.middleware.js +7 -10
- package/src/panel/login-throttle.cjs +43 -0
- package/src/panel/session-auth.cjs +17 -0
- package/src/routes/dashboard.api.esm.js +394 -72
- package/src/services/aiAgent.cjs +136 -49
- package/src/services/aiProviders.cjs +193 -47
- package/src/services/aiRouter.cjs +137 -0
- package/src/services/aiTools.cjs +305 -125
- package/src/services/llmDiscovery.cjs +481 -0
- package/src/services/modelRegistry.cjs +412 -0
- package/src/utils/datetime.cjs +2 -2
- package/src/utils/lid-helper.esm.js +7 -7
- package/src/utils/logger.cjs +1 -1
- package/src/utils/markdownParser.cjs +159 -0
- package/src/utils/memory.cjs +43 -13
- package/src/utils/messageContent.cjs +40 -0
- package/src/utils/normalizeJid.esm.js +7 -7
- package/src/utils/numerals.cjs +75 -0
- package/src/utils/permissions.esm.js +10 -15
- package/src/utils/providerUrl.cjs +281 -0
- package/src/utils/recurrence.cjs +7 -11
- package/src/utils/sendBotMessage.esm.js +4 -14
- package/src/utils/statusMessage.cjs +5 -13
- package/src/utils/storage.cjs +10 -0
- package/src/utils/storage.esm.js +11 -0
- package/src/utils/textDecode.cjs +4 -9
- package/src/utils/thumbnail.cjs +8 -14
- package/src/utils/typing.esm.js +12 -12
- package/views/dashboard.ejs +134 -106
|
@@ -47,38 +47,32 @@ async function handleAntiSpam(sock, msg) {
|
|
|
47
47
|
|
|
48
48
|
// 1. فلترة الرسائل القديمة
|
|
49
49
|
userData.messages = userData.messages.filter(
|
|
50
|
-
(m) => now - m.timestamp < SPAM_TIME_WINDOW_SECONDS
|
|
50
|
+
(m) => now - m.timestamp < SPAM_TIME_WINDOW_SECONDS,
|
|
51
51
|
);
|
|
52
52
|
|
|
53
53
|
// 2. إضافة الرسالة الجديدة
|
|
54
54
|
userData.messages.push({ content: messageContent, timestamp: now });
|
|
55
55
|
|
|
56
56
|
// 3. التحقق من وجود تكرار
|
|
57
|
-
const repeatedMessages = userData.messages.filter(
|
|
58
|
-
(m) => m.content === messageContent
|
|
59
|
-
);
|
|
57
|
+
const repeatedMessages = userData.messages.filter((m) => m.content === messageContent);
|
|
60
58
|
|
|
61
59
|
if (repeatedMessages.length >= SPAM_MESSAGE_COUNT) {
|
|
62
60
|
userData.warnCount += 1;
|
|
63
61
|
userData.messages = []; // مسح الرسائل بعد اكتشاف السبام لمنع التحذيرات المتتالية
|
|
64
62
|
|
|
65
63
|
if (userData.warnCount >= SPAM_WARN_LIMIT) {
|
|
66
|
-
logger.info(
|
|
67
|
-
`[AntiSpam] Kicking ${senderId} from ${groupId} for repeated spam.`
|
|
68
|
-
);
|
|
64
|
+
logger.info(`[AntiSpam] Kicking ${senderId} from ${groupId} for repeated spam.`);
|
|
69
65
|
// إعادة تعيين العداد بعد الطرد
|
|
70
66
|
antiSpamCache.delete(cacheKey);
|
|
71
67
|
|
|
72
68
|
await sock.sendMessage(groupId, {
|
|
73
|
-
text: `🚫 تم طرد المستخدم @${
|
|
74
|
-
senderId.split("@")[0]
|
|
75
|
-
} تلقائيًا بسبب الإزعاج.`,
|
|
69
|
+
text: `🚫 تم طرد المستخدم @${senderId.split("@")[0]} تلقائيًا بسبب الإزعاج.`,
|
|
76
70
|
mentions: [senderId],
|
|
77
71
|
});
|
|
78
72
|
await sock.groupParticipantsUpdate(groupId, [senderId], "remove");
|
|
79
73
|
} else {
|
|
80
74
|
logger.info(
|
|
81
|
-
`[AntiSpam] Warning ${senderId} in ${groupId}. Warn count: ${userData.warnCount}
|
|
75
|
+
`[AntiSpam] Warning ${senderId} in ${groupId}. Warn count: ${userData.warnCount}`,
|
|
82
76
|
);
|
|
83
77
|
await sock.sendMessage(groupId, {
|
|
84
78
|
text: `⚠️ تحذير للمستخدم @${
|
|
@@ -1,16 +1,15 @@
|
|
|
1
1
|
// file: /commands/group/antilink.js
|
|
2
2
|
const { getGroupSettings, saveGroupSettings } = require("../../utils/storage.cjs");
|
|
3
3
|
const logger = require("../../utils/logger.cjs");
|
|
4
|
-
const {
|
|
5
|
-
|
|
6
|
-
isAdminInGroupSync,
|
|
7
|
-
} = require("../../utils/permissions.cjs");
|
|
4
|
+
const { isOwnerJidSync, isAdminInGroupSync } = require("../../utils/permissions.cjs");
|
|
5
|
+
const { visibleText } = require("../../utils/messageContent.cjs");
|
|
8
6
|
|
|
9
7
|
// --- The Main Command Logic ---
|
|
10
8
|
const command = {
|
|
11
9
|
name: "antilink",
|
|
12
10
|
description: "Advanced control for the anti-link feature.",
|
|
13
|
-
usage:
|
|
11
|
+
usage:
|
|
12
|
+
"antilink [status]\nantilink <on|off>\nantilink mode <ALL|WHITELIST|BLACKLIST>\nantilink <allow|disallow> <دومين>",
|
|
14
13
|
chat: "group",
|
|
15
14
|
userAdminRequired: true,
|
|
16
15
|
|
|
@@ -44,7 +43,7 @@ const command = {
|
|
|
44
43
|
text: "☑️ تم تعطيل نظام منع الروابط.",
|
|
45
44
|
});
|
|
46
45
|
break;
|
|
47
|
-
case "mode":
|
|
46
|
+
case "mode": {
|
|
48
47
|
const mode = args[1] ? args[1].toUpperCase() : "";
|
|
49
48
|
if (!["ALL", "WHITELIST", "BLACKLIST"].includes(mode)) {
|
|
50
49
|
return await sock.sendMessage(groupId, {
|
|
@@ -56,7 +55,8 @@ const command = {
|
|
|
56
55
|
text: `✅ تم تغيير وضع منع الروابط إلى: ${mode}`,
|
|
57
56
|
});
|
|
58
57
|
break;
|
|
59
|
-
|
|
58
|
+
}
|
|
59
|
+
case "allow": {
|
|
60
60
|
const domainToAllow = args[1] ? args[1].toLowerCase() : "";
|
|
61
61
|
if (!domainToAllow)
|
|
62
62
|
return await sock.sendMessage(groupId, {
|
|
@@ -69,30 +69,31 @@ const command = {
|
|
|
69
69
|
text: `✅ تم إضافة '${domainToAllow}' إلى قائمة الدومينات المسموح بها.`,
|
|
70
70
|
});
|
|
71
71
|
break;
|
|
72
|
-
|
|
72
|
+
}
|
|
73
|
+
case "disallow": {
|
|
73
74
|
const domainToDisallow = args[1] ? args[1].toLowerCase() : "";
|
|
74
75
|
if (!domainToDisallow)
|
|
75
76
|
return await sock.sendMessage(groupId, {
|
|
76
77
|
text: "يرجى تحديد دومين لإزالته.",
|
|
77
78
|
});
|
|
78
79
|
antilinkConfig.allowed_domains = antilinkConfig.allowed_domains.filter(
|
|
79
|
-
(d) => d !== domainToDisallow
|
|
80
|
+
(d) => d !== domainToDisallow,
|
|
80
81
|
);
|
|
81
82
|
await sock.sendMessage(groupId, {
|
|
82
83
|
text: `☑️ تم إزالة '${domainToDisallow}' من قائمة الدومينات المسموح بها.`,
|
|
83
84
|
});
|
|
84
85
|
break;
|
|
85
|
-
|
|
86
|
+
}
|
|
87
|
+
default: {
|
|
86
88
|
// Display current status
|
|
87
89
|
let statusReply = `*حالة نظام منع الروابط:*\n\n`;
|
|
88
|
-
statusReply += `الحالة: ${
|
|
89
|
-
antilinkConfig.enabled ? "مفعل ✅" : "معطل ☑️"
|
|
90
|
-
}\n`;
|
|
90
|
+
statusReply += `الحالة: ${antilinkConfig.enabled ? "مفعل ✅" : "معطل ☑️"}\n`;
|
|
91
91
|
statusReply += `الوضع: ${antilinkConfig.mode}\n`;
|
|
92
92
|
statusReply += `الدومينات المسموح بها: ${
|
|
93
93
|
antilinkConfig.allowed_domains.join(", ") || "لا يوجد"
|
|
94
94
|
}\n`;
|
|
95
95
|
await sock.sendMessage(groupId, { text: statusReply });
|
|
96
|
+
}
|
|
96
97
|
}
|
|
97
98
|
|
|
98
99
|
saveGroupSettings(groupId, settings);
|
|
@@ -101,37 +102,42 @@ const command = {
|
|
|
101
102
|
|
|
102
103
|
// --- The Message Handler Logic ---
|
|
103
104
|
const linkRegex = new RegExp(
|
|
104
|
-
/(https?:\/\/(?:www\.|(?!www))[a-zA-Z0-9][a-zA-Z0-9-]+[a-zA-Z0-9]\.[^\s]{2,}|www\.[a-zA-Z0-9][a-zA-Z0-9-]+[a-zA-Z0-9]\.[^\s]{2,}|https?:\/\/[a-zA-Z0-9]+\.[^\s]{2,}|[a-zA-Z0-9]+\.[^\s]{2,})/i
|
|
105
|
+
/(https?:\/\/(?:www\.|(?!www))[a-zA-Z0-9][a-zA-Z0-9-]+[a-zA-Z0-9]\.[^\s]{2,}|www\.[a-zA-Z0-9][a-zA-Z0-9-]+[a-zA-Z0-9]\.[^\s]{2,}|https?:\/\/[a-zA-Z0-9]+\.[^\s]{2,}|[a-zA-Z0-9]+\.[^\s]{2,})/i,
|
|
105
106
|
);
|
|
106
107
|
|
|
107
108
|
async function handleAntiLink(sock, msg, _legacyConfig, _normalizeJid) {
|
|
108
109
|
const isGroup = msg.key.remoteJid.endsWith("@g.us");
|
|
109
|
-
if (!isGroup) return;
|
|
110
|
+
if (!isGroup) return false;
|
|
110
111
|
|
|
111
112
|
const groupId = msg.key.remoteJid;
|
|
112
113
|
const settings = getGroupSettings(groupId);
|
|
113
114
|
const antilinkConfig = settings.antilink;
|
|
114
115
|
|
|
115
|
-
if (!antilinkConfig || !antilinkConfig.enabled) return;
|
|
116
|
+
if (!antilinkConfig || !antilinkConfig.enabled) return false;
|
|
116
117
|
|
|
117
118
|
const senderId = msg.key.participant || msg.key.remoteJid;
|
|
118
119
|
|
|
119
120
|
const groupMetadata = await sock.groupMetadata(groupId);
|
|
120
121
|
// Centralized checks — handle LID/PN cross-format and bootstrap roster.
|
|
121
|
-
const
|
|
122
|
-
const
|
|
122
|
+
const senderIds = [senderId, msg.key.participantAlt, msg.key.participantPn].filter(Boolean);
|
|
123
|
+
const isOwner = msg.key.fromMe || senderIds.some(isOwnerJidSync);
|
|
124
|
+
const isSenderAdmin = senderIds.some((id) => isAdminInGroupSync(groupMetadata, id));
|
|
123
125
|
|
|
124
|
-
if (isOwner || isSenderAdmin) return;
|
|
126
|
+
if (isOwner || isSenderAdmin) return false;
|
|
125
127
|
|
|
126
|
-
const body =
|
|
127
|
-
|
|
128
|
-
if (!linkRegex.test(body)) return; // No link found
|
|
128
|
+
const body = visibleText(msg.message);
|
|
129
|
+
if (!linkRegex.test(body)) return false; // No link found
|
|
129
130
|
|
|
130
131
|
// --- Link Found, Apply Rules ---
|
|
131
132
|
const foundLinks = body.match(linkRegex);
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
133
|
+
let domain;
|
|
134
|
+
try {
|
|
135
|
+
domain = new URL(
|
|
136
|
+
foundLinks[0].startsWith("http") ? foundLinks[0] : `http://${foundLinks[0]}`,
|
|
137
|
+
).hostname.replace("www.", "");
|
|
138
|
+
} catch {
|
|
139
|
+
return false;
|
|
140
|
+
}
|
|
135
141
|
|
|
136
142
|
let shouldDelete = false;
|
|
137
143
|
|
|
@@ -152,15 +158,15 @@ async function handleAntiLink(sock, msg, _legacyConfig, _normalizeJid) {
|
|
|
152
158
|
}
|
|
153
159
|
|
|
154
160
|
if (shouldDelete) {
|
|
155
|
-
logger.info(
|
|
156
|
-
`[Anti-Link] Deleting link from ${senderId} in ${groupId}. Domain: ${domain}`
|
|
157
|
-
);
|
|
161
|
+
logger.info(`[Anti-Link] Deleting link from ${senderId} in ${groupId}. Domain: ${domain}`);
|
|
158
162
|
await sock.sendMessage(groupId, { delete: msg.key });
|
|
159
163
|
await sock.sendMessage(groupId, {
|
|
160
164
|
text: `ممنوع إرسال الروابط هنا يا @${senderId.split("@")[0]}!`,
|
|
161
165
|
mentions: [senderId],
|
|
162
166
|
});
|
|
167
|
+
return true;
|
|
163
168
|
}
|
|
169
|
+
return false;
|
|
164
170
|
}
|
|
165
171
|
|
|
166
172
|
// Export both the command and the handler
|
|
@@ -1,8 +1,5 @@
|
|
|
1
1
|
// file: /commands/group/approveall.js
|
|
2
|
-
const {
|
|
3
|
-
getGroupSettings,
|
|
4
|
-
saveGroupSettings,
|
|
5
|
-
} = require("../../utils/storage.cjs"); // Note the path is ../../
|
|
2
|
+
const { getGroupSettings, saveGroupSettings } = require("../../utils/storage.cjs"); // Note the path is ../../
|
|
6
3
|
const logger = require("../../utils/logger.cjs");
|
|
7
4
|
|
|
8
5
|
module.exports = {
|
|
@@ -36,18 +33,13 @@ module.exports = {
|
|
|
36
33
|
text: "☑️ تم تعطيل نظام الموافقة التلقائية.",
|
|
37
34
|
});
|
|
38
35
|
} else {
|
|
39
|
-
const status = settings.join_requests.auto_approve_enabled
|
|
40
|
-
? "مفعل ✅"
|
|
41
|
-
: "معطل ☑️";
|
|
36
|
+
const status = settings.join_requests.auto_approve_enabled ? "مفعل ✅" : "معطل ☑️";
|
|
42
37
|
return await sock.sendMessage(groupId, {
|
|
43
38
|
text: `حالة الموافقة التلقائية: ${status}.\nاستخدم 'on' أو 'off' للتغيير.`,
|
|
44
39
|
});
|
|
45
40
|
}
|
|
46
41
|
} catch (error) {
|
|
47
|
-
logger.error(
|
|
48
|
-
{ err: error, command: "approveall" },
|
|
49
|
-
"Error in !group approveall command"
|
|
50
|
-
);
|
|
42
|
+
logger.error({ err: error, command: "approveall" }, "Error in !group approveall command");
|
|
51
43
|
await sock.sendMessage(groupId, { text: "حدث خطأ." });
|
|
52
44
|
}
|
|
53
45
|
},
|
|
@@ -12,8 +12,7 @@ module.exports = {
|
|
|
12
12
|
async execute(sock, msg) {
|
|
13
13
|
try {
|
|
14
14
|
const groupId = msg.key.remoteJid;
|
|
15
|
-
const mentionedJid =
|
|
16
|
-
msg.message?.extendedTextMessage?.contextInfo?.mentionedJid?.[0];
|
|
15
|
+
const mentionedJid = msg.message?.extendedTextMessage?.contextInfo?.mentionedJid?.[0];
|
|
17
16
|
|
|
18
17
|
if (!mentionedJid) {
|
|
19
18
|
return await sock.sendMessage(groupId, {
|
|
@@ -24,9 +23,7 @@ module.exports = {
|
|
|
24
23
|
// Call the new function from storage.js to delete the record from the database
|
|
25
24
|
clearUserWarnings(groupId, mentionedJid);
|
|
26
25
|
|
|
27
|
-
const replyText = `✅ تم مسح جميع تحذيرات العضو @${
|
|
28
|
-
mentionedJid.split("@")[0]
|
|
29
|
-
} بنجاح.`;
|
|
26
|
+
const replyText = `✅ تم مسح جميع تحذيرات العضو @${mentionedJid.split("@")[0]} بنجاح.`;
|
|
30
27
|
await sock.sendMessage(groupId, {
|
|
31
28
|
text: replyText,
|
|
32
29
|
mentions: [mentionedJid],
|
|
@@ -24,9 +24,7 @@ module.exports = {
|
|
|
24
24
|
}
|
|
25
25
|
|
|
26
26
|
// Safety check: Is the target user NOT an admin?
|
|
27
|
-
const targetUser = groupMetadata.participants.find(
|
|
28
|
-
(p) => p.id === targetJid
|
|
29
|
-
);
|
|
27
|
+
const targetUser = groupMetadata.participants.find((p) => p.id === targetJid);
|
|
30
28
|
if (!targetUser || !targetUser.admin) {
|
|
31
29
|
return await sock.sendMessage(groupId, {
|
|
32
30
|
text: `⚠️ العضو @${targetJid.split("@")[0]} ليس مشرفًا أصلاً.`,
|
|
@@ -45,17 +43,14 @@ module.exports = {
|
|
|
45
43
|
await sock.groupParticipantsUpdate(
|
|
46
44
|
groupId,
|
|
47
45
|
[targetJid],
|
|
48
|
-
"demote" // The action is 'demote'
|
|
46
|
+
"demote", // The action is 'demote'
|
|
49
47
|
);
|
|
50
48
|
await sock.sendMessage(groupId, {
|
|
51
49
|
text: `👤 تم عزل @${targetJid.split("@")[0]} من الإشراف.`,
|
|
52
50
|
mentions: [targetJid],
|
|
53
51
|
});
|
|
54
52
|
} catch (error) {
|
|
55
|
-
logger.error(
|
|
56
|
-
{ err: error, command: "demote" },
|
|
57
|
-
"Error in !demote command"
|
|
58
|
-
);
|
|
53
|
+
logger.error({ err: error, command: "demote" }, "Error in !demote command");
|
|
59
54
|
await sock.sendMessage(groupId, { text: "حدث خطأ أثناء محاولة العزل." });
|
|
60
55
|
}
|
|
61
56
|
},
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
// file: /commands/kick.js
|
|
2
2
|
const logger = require("../../utils/logger.cjs");
|
|
3
|
-
const {
|
|
3
|
+
const {
|
|
4
|
+
hasBotPrivilegesSync,
|
|
5
|
+
isAdminInGroupSync,
|
|
6
|
+
sameUserSync,
|
|
7
|
+
} = require("../../utils/permissions.cjs");
|
|
4
8
|
|
|
5
9
|
module.exports = {
|
|
6
10
|
name: "kick",
|
|
@@ -16,9 +20,7 @@ module.exports = {
|
|
|
16
20
|
|
|
17
21
|
// --- Target Identification Logic ---
|
|
18
22
|
// 1. Check for mentions
|
|
19
|
-
if (
|
|
20
|
-
msg.message?.extendedTextMessage?.contextInfo?.mentionedJid?.length > 0
|
|
21
|
-
) {
|
|
23
|
+
if (msg.message?.extendedTextMessage?.contextInfo?.mentionedJid?.length > 0) {
|
|
22
24
|
targetJid = msg.message.extendedTextMessage.contextInfo.mentionedJid[0];
|
|
23
25
|
}
|
|
24
26
|
// 2. Check if it's a reply to another message
|
|
@@ -32,25 +34,20 @@ module.exports = {
|
|
|
32
34
|
|
|
33
35
|
// --- Safety Checks ---
|
|
34
36
|
// Can't kick the bot itself
|
|
35
|
-
if (
|
|
37
|
+
if ([sock.user?.id, sock.user?.lid].filter(Boolean).some((id) => sameUserSync(id, targetJid))) {
|
|
36
38
|
return await sock.sendMessage(groupId, { text: "لا يمكنني طرد نفسي." });
|
|
37
39
|
}
|
|
38
40
|
|
|
39
|
-
//
|
|
40
|
-
|
|
41
|
+
// Bot owners/admins are privileged across chats and cannot be removed by
|
|
42
|
+
// a group-only admin through an alternate LID/PN representation.
|
|
43
|
+
if (hasBotPrivilegesSync(targetJid)) {
|
|
41
44
|
return await sock.sendMessage(groupId, {
|
|
42
|
-
text: "لا يمكن طرد مالك البوت.",
|
|
45
|
+
text: "لا يمكن طرد مالك أو مشرف البوت.",
|
|
43
46
|
});
|
|
44
47
|
}
|
|
45
48
|
|
|
46
49
|
// Check if the target is also an admin
|
|
47
|
-
|
|
48
|
-
(p) => p.id === targetJid
|
|
49
|
-
);
|
|
50
|
-
if (
|
|
51
|
-
targetUser &&
|
|
52
|
-
(targetUser.admin === "admin" || targetUser.admin === "superadmin")
|
|
53
|
-
) {
|
|
50
|
+
if (isAdminInGroupSync(groupMetadata, targetJid)) {
|
|
54
51
|
return await sock.sendMessage(groupId, {
|
|
55
52
|
text: "لا يمكن للمشرف طرد مشرف آخر.",
|
|
56
53
|
});
|
|
@@ -1,10 +1,8 @@
|
|
|
1
1
|
// file: /commands/group/media.js
|
|
2
2
|
const { getGroupSettings, saveGroupSettings } = require("../../utils/storage.cjs");
|
|
3
3
|
const logger = require("../../utils/logger.cjs");
|
|
4
|
-
const {
|
|
5
|
-
|
|
6
|
-
isAdminInGroupSync,
|
|
7
|
-
} = require("../../utils/permissions.cjs");
|
|
4
|
+
const { isOwnerJidSync, isAdminInGroupSync } = require("../../utils/permissions.cjs");
|
|
5
|
+
const { mediaType } = require("../../utils/messageContent.cjs");
|
|
8
6
|
|
|
9
7
|
const VALID_TYPES = ["image", "video", "sticker", "audio"];
|
|
10
8
|
|
|
@@ -39,7 +37,7 @@ const command = {
|
|
|
39
37
|
text: "☑️ تم تعطيل نظام مراقبة الوسائط.",
|
|
40
38
|
});
|
|
41
39
|
break;
|
|
42
|
-
case "block":
|
|
40
|
+
case "block": {
|
|
43
41
|
const typeToBlock = args[1] ? args[1].toLowerCase() : "";
|
|
44
42
|
if (!VALID_TYPES.includes(typeToBlock))
|
|
45
43
|
return await sock.sendMessage(groupId, {
|
|
@@ -52,28 +50,26 @@ const command = {
|
|
|
52
50
|
text: `✅ تم إضافة '${typeToBlock}' للأنواع الممنوعة.`,
|
|
53
51
|
});
|
|
54
52
|
break;
|
|
55
|
-
|
|
53
|
+
}
|
|
54
|
+
case "unblock": {
|
|
56
55
|
const typeToUnblock = args[1] ? args[1].toLowerCase() : "";
|
|
57
56
|
if (!typeToUnblock)
|
|
58
57
|
return await sock.sendMessage(groupId, {
|
|
59
58
|
text: "يرجى تحديد نوع لإلغاء حظره.",
|
|
60
59
|
});
|
|
61
|
-
mediaConfig.blocked_types = mediaConfig.blocked_types.filter(
|
|
62
|
-
(t) => t !== typeToUnblock
|
|
63
|
-
);
|
|
60
|
+
mediaConfig.blocked_types = mediaConfig.blocked_types.filter((t) => t !== typeToUnblock);
|
|
64
61
|
await sock.sendMessage(groupId, {
|
|
65
62
|
text: `☑️ تم إزالة '${typeToUnblock}' من الأنواع الممنوعة.`,
|
|
66
63
|
});
|
|
67
64
|
break;
|
|
68
|
-
|
|
65
|
+
}
|
|
66
|
+
default: {
|
|
67
|
+
// 'status'
|
|
69
68
|
let statusReply = `*حالة نظام مراقبة الوسائط:*\n\n`;
|
|
70
|
-
statusReply += `الحالة: ${
|
|
71
|
-
|
|
72
|
-
}\n`;
|
|
73
|
-
statusReply += `الأنواع الممنوعة: ${
|
|
74
|
-
mediaConfig.blocked_types.join(", ") || "لا يوجد"
|
|
75
|
-
}`;
|
|
69
|
+
statusReply += `الحالة: ${mediaConfig.enabled ? "مفعل ✅" : "معطل ☑️"}\n`;
|
|
70
|
+
statusReply += `الأنواع الممنوعة: ${mediaConfig.blocked_types.join(", ") || "لا يوجد"}`;
|
|
76
71
|
await sock.sendMessage(groupId, { text: statusReply });
|
|
72
|
+
}
|
|
77
73
|
}
|
|
78
74
|
saveGroupSettings(groupId, settings);
|
|
79
75
|
},
|
|
@@ -93,19 +89,16 @@ async function handleMediaControl(sock, msg, _legacyConfig, _normalizeJid) {
|
|
|
93
89
|
const senderId = msg.key.participant || msg.key.remoteJid;
|
|
94
90
|
|
|
95
91
|
const groupMetadata = await sock.groupMetadata(groupId);
|
|
96
|
-
const
|
|
97
|
-
const
|
|
92
|
+
const senderIds = [senderId, msg.key.participantAlt, msg.key.participantPn].filter(Boolean);
|
|
93
|
+
const isOwner = msg.key.fromMe || senderIds.some(isOwnerJidSync);
|
|
94
|
+
const isSenderAdmin = senderIds.some((id) => isAdminInGroupSync(groupMetadata, id));
|
|
98
95
|
|
|
99
96
|
if (isOwner || isSenderAdmin) return false;
|
|
100
97
|
|
|
101
|
-
const messageType =
|
|
102
|
-
.replace("Message", "")
|
|
103
|
-
.toLowerCase();
|
|
98
|
+
const messageType = mediaType(msg.message);
|
|
104
99
|
|
|
105
100
|
if (mediaConfig.blocked_types.includes(messageType)) {
|
|
106
|
-
logger.info(
|
|
107
|
-
`[Media Control] Deleting ${messageType} from ${senderId} in ${groupId}.`
|
|
108
|
-
);
|
|
101
|
+
logger.info(`[Media Control] Deleting ${messageType} from ${senderId} in ${groupId}.`);
|
|
109
102
|
await sock.sendMessage(groupId, { delete: msg.key });
|
|
110
103
|
await sock.sendMessage(groupId, {
|
|
111
104
|
text: `يا @${senderId.split("@")[0]}، إرسال *${messageType}* ممنوع هنا.`,
|
|
@@ -33,8 +33,7 @@ module.exports = {
|
|
|
33
33
|
const phone = member.id.split("@")[0];
|
|
34
34
|
|
|
35
35
|
// Check if the member is an admin or superadmin
|
|
36
|
-
const isAdmin =
|
|
37
|
-
member.admin === "admin" || member.admin === "superadmin";
|
|
36
|
+
const isAdmin = member.admin === "admin" || member.admin === "superadmin";
|
|
38
37
|
|
|
39
38
|
// Add the formatted line to our reply text
|
|
40
39
|
// Using @ will create a "mention link" in the WhatsApp message
|
|
@@ -24,13 +24,8 @@ module.exports = {
|
|
|
24
24
|
}
|
|
25
25
|
|
|
26
26
|
// Safety check: Is the target user already an admin?
|
|
27
|
-
const targetUser = groupMetadata.participants.find(
|
|
28
|
-
|
|
29
|
-
);
|
|
30
|
-
if (
|
|
31
|
-
targetUser &&
|
|
32
|
-
(targetUser.admin === "admin" || targetUser.admin === "superadmin")
|
|
33
|
-
) {
|
|
27
|
+
const targetUser = groupMetadata.participants.find((p) => p.id === targetJid);
|
|
28
|
+
if (targetUser && (targetUser.admin === "admin" || targetUser.admin === "superadmin")) {
|
|
34
29
|
return await sock.sendMessage(groupId, {
|
|
35
30
|
text: `⚠️ العضو @${targetJid.split("@")[0]} مشرف بالفعل.`,
|
|
36
31
|
mentions: [targetJid],
|
|
@@ -41,17 +36,14 @@ module.exports = {
|
|
|
41
36
|
await sock.groupParticipantsUpdate(
|
|
42
37
|
groupId,
|
|
43
38
|
[targetJid],
|
|
44
|
-
"promote" // The action is 'promote'
|
|
39
|
+
"promote", // The action is 'promote'
|
|
45
40
|
);
|
|
46
41
|
await sock.sendMessage(groupId, {
|
|
47
42
|
text: `👑 تم ترقية @${targetJid.split("@")[0]} إلى مشرف بنجاح.`,
|
|
48
43
|
mentions: [targetJid],
|
|
49
44
|
});
|
|
50
45
|
} catch (error) {
|
|
51
|
-
logger.error(
|
|
52
|
-
{ err: error, command: "promote" },
|
|
53
|
-
"Error in !promote command"
|
|
54
|
-
);
|
|
46
|
+
logger.error({ err: error, command: "promote" }, "Error in !promote command");
|
|
55
47
|
await sock.sendMessage(groupId, {
|
|
56
48
|
text: "حدث خطأ أثناء محاولة الترقية.",
|
|
57
49
|
});
|
|
@@ -3,8 +3,7 @@ const logger = require("../../utils/logger.cjs");
|
|
|
3
3
|
|
|
4
4
|
module.exports = {
|
|
5
5
|
name: "removeall",
|
|
6
|
-
description:
|
|
7
|
-
"Removes all non-admin members from the group after confirmation.",
|
|
6
|
+
description: "Removes all non-admin members from the group after confirmation.",
|
|
8
7
|
usage: "removeall",
|
|
9
8
|
chat: "group",
|
|
10
9
|
userAdminRequired: true,
|
|
@@ -33,9 +32,7 @@ module.exports = {
|
|
|
33
32
|
setTimeout(() => {
|
|
34
33
|
if (confirmationSessions.has(senderId)) {
|
|
35
34
|
confirmationSessions.delete(senderId);
|
|
36
|
-
logger.info(
|
|
37
|
-
`[Confirmation] Timed out for ${senderId} on command removeall.`
|
|
38
|
-
);
|
|
35
|
+
logger.info(`[Confirmation] Timed out for ${senderId} on command removeall.`);
|
|
39
36
|
}
|
|
40
37
|
}, 30000); // 30 seconds
|
|
41
38
|
},
|
|
@@ -1,7 +1,4 @@
|
|
|
1
|
-
const {
|
|
2
|
-
getGroupSettings,
|
|
3
|
-
saveGroupSettings,
|
|
4
|
-
} = require("../../utils/storage.cjs");
|
|
1
|
+
const { getGroupSettings, saveGroupSettings } = require("../../utils/storage.cjs");
|
|
5
2
|
const logger = require("../../utils/logger.cjs");
|
|
6
3
|
|
|
7
4
|
module.exports = {
|
|
@@ -36,10 +33,7 @@ module.exports = {
|
|
|
36
33
|
});
|
|
37
34
|
} catch (error) {
|
|
38
35
|
// Improved logging for better debugging
|
|
39
|
-
logger.error(
|
|
40
|
-
{ err: error, groupId: groupId },
|
|
41
|
-
"Error in !setrules command"
|
|
42
|
-
);
|
|
36
|
+
logger.error({ err: error, groupId: groupId }, "Error in !setrules command");
|
|
43
37
|
await sock.sendMessage(groupId, { text: "حدث خطأ أثناء حفظ القواعد." });
|
|
44
38
|
}
|
|
45
39
|
},
|
|
@@ -21,7 +21,7 @@ module.exports = {
|
|
|
21
21
|
const warnConfig = settings.warn_system;
|
|
22
22
|
|
|
23
23
|
switch (subCommand) {
|
|
24
|
-
case "max":
|
|
24
|
+
case "max": {
|
|
25
25
|
const max = parseInt(value, 10);
|
|
26
26
|
if (isNaN(max) || max < 1) {
|
|
27
27
|
return await sock.sendMessage(groupId, {
|
|
@@ -33,8 +33,9 @@ module.exports = {
|
|
|
33
33
|
text: `✅ تم تعيين الحد الأقصى للتحذيرات إلى ${max}.`,
|
|
34
34
|
});
|
|
35
35
|
break;
|
|
36
|
+
}
|
|
36
37
|
|
|
37
|
-
case "action":
|
|
38
|
+
case "action": {
|
|
38
39
|
const action = value?.toUpperCase();
|
|
39
40
|
if (action !== "KICK" && action !== "NONE") {
|
|
40
41
|
return await sock.sendMessage(groupId, {
|
|
@@ -46,6 +47,7 @@ module.exports = {
|
|
|
46
47
|
text: `✅ تم تعيين الإجراء التلقائي إلى ${action}.`,
|
|
47
48
|
});
|
|
48
49
|
break;
|
|
50
|
+
}
|
|
49
51
|
|
|
50
52
|
default:
|
|
51
53
|
return await sock.sendMessage(groupId, {
|
|
@@ -13,7 +13,7 @@ module.exports = {
|
|
|
13
13
|
try {
|
|
14
14
|
// Filter the participants to get only admins and superadmins
|
|
15
15
|
const admins = groupMetadata.participants.filter(
|
|
16
|
-
(p) => p.admin === "admin" || p.admin === "superadmin"
|
|
16
|
+
(p) => p.admin === "admin" || p.admin === "superadmin",
|
|
17
17
|
);
|
|
18
18
|
|
|
19
19
|
if (admins.length === 0) {
|
|
@@ -40,10 +40,7 @@ module.exports = {
|
|
|
40
40
|
mentions: mentions,
|
|
41
41
|
});
|
|
42
42
|
} catch (error) {
|
|
43
|
-
logger.error(
|
|
44
|
-
{ err: error, command: "tagadmins" },
|
|
45
|
-
"Error in !tagadmins command"
|
|
46
|
-
);
|
|
43
|
+
logger.error({ err: error, command: "tagadmins" }, "Error in !tagadmins command");
|
|
47
44
|
await sock.sendMessage(groupId, { text: "حدث خطأ." });
|
|
48
45
|
}
|
|
49
46
|
},
|