djs-builder 0.6.401 → 0.7.1
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 +292 -43
- package/function/dash.js +638 -0
- package/function/giveaway.js +47 -10
- package/function/security.js +0 -0
- package/handler/starter.js +73 -38
- package/package.json +9 -4
- package/views/404.ejs +40 -0
- package/views/dashboard.ejs +894 -0
- package/views/giveaways.ejs +306 -0
- package/views/guild.ejs +576 -0
- package/views/index.ejs +419 -0
- package/views/levels.ejs +326 -0
- package/views/login.ejs +437 -0
package/function/dash.js
ADDED
|
@@ -0,0 +1,638 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DJS-Builder Dashboard
|
|
3
|
+
* لوحة تحكم عصرية وخفيفة متوافقة مع حزمة djs-builder
|
|
4
|
+
* @version 2.0.0
|
|
5
|
+
* @author DJS-Builder Team
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
const express = require("express");
|
|
9
|
+
const session = require("express-session");
|
|
10
|
+
const passport = require("passport");
|
|
11
|
+
const DiscordStrategy = require("passport-discord").Strategy;
|
|
12
|
+
const path = require("path");
|
|
13
|
+
|
|
14
|
+
// استيراد موديلات djs-builder
|
|
15
|
+
let Level, giveaway, Blacklist, leaderboard, addXP, UserLevel;
|
|
16
|
+
let Gstart, Gcheck, Greroll, Glist, Gpause, Gresume, Gdelete, Gdata;
|
|
17
|
+
let isBlacklisted, addToBlacklist, removeFromBlacklist, getBlacklist;
|
|
18
|
+
|
|
19
|
+
try {
|
|
20
|
+
const djsBuilder = require("djs-builder");
|
|
21
|
+
Level = djsBuilder.Level;
|
|
22
|
+
giveaway = djsBuilder.giveaway;
|
|
23
|
+
Blacklist = djsBuilder.Blacklist;
|
|
24
|
+
leaderboard = djsBuilder.leaderboard;
|
|
25
|
+
addXP = djsBuilder.addXP;
|
|
26
|
+
UserLevel = djsBuilder.UserLevel;
|
|
27
|
+
Gstart = djsBuilder.Gstart;
|
|
28
|
+
Gcheck = djsBuilder.Gcheck;
|
|
29
|
+
Greroll = djsBuilder.Greroll;
|
|
30
|
+
Glist = djsBuilder.Glist;
|
|
31
|
+
Gpause = djsBuilder.Gpause;
|
|
32
|
+
Gresume = djsBuilder.Gresume;
|
|
33
|
+
Gdelete = djsBuilder.Gdelete;
|
|
34
|
+
Gdata = djsBuilder.Gdata;
|
|
35
|
+
isBlacklisted = djsBuilder.isBlacklisted;
|
|
36
|
+
addToBlacklist = djsBuilder.addToBlacklist;
|
|
37
|
+
removeFromBlacklist = djsBuilder.removeFromBlacklist;
|
|
38
|
+
getBlacklist = djsBuilder.getBlacklist;
|
|
39
|
+
} catch (e) {
|
|
40
|
+
console.log("⚠️ djs-builder models not fully loaded:", e.message);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* دالة لإنشاء وتشغيل لوحة التحكم
|
|
45
|
+
* @param {Client} client - كائن البوت
|
|
46
|
+
* @param {Object} options - خيارات اللوحة
|
|
47
|
+
*/
|
|
48
|
+
function dashboard(client, options) {
|
|
49
|
+
const app = express();
|
|
50
|
+
const {
|
|
51
|
+
clientID,
|
|
52
|
+
clientSecret,
|
|
53
|
+
callbackURL,
|
|
54
|
+
sessionSecret,
|
|
55
|
+
port = 3000,
|
|
56
|
+
} = options;
|
|
57
|
+
|
|
58
|
+
// إعداد المسارات
|
|
59
|
+
app.set("view engine", "ejs");
|
|
60
|
+
app.set("views", path.join(__dirname, "views"));
|
|
61
|
+
app.use(express.static(path.join(__dirname, "public")));
|
|
62
|
+
app.use(express.json());
|
|
63
|
+
app.use(express.urlencoded({ extended: true }));
|
|
64
|
+
|
|
65
|
+
// إعداد الجلسات
|
|
66
|
+
app.use(
|
|
67
|
+
session({
|
|
68
|
+
secret: sessionSecret,
|
|
69
|
+
resave: false,
|
|
70
|
+
saveUninitialized: false,
|
|
71
|
+
cookie: {
|
|
72
|
+
maxAge: 1000 * 60 * 60 * 24 * 7,
|
|
73
|
+
},
|
|
74
|
+
})
|
|
75
|
+
);
|
|
76
|
+
|
|
77
|
+
// إعداد Passport
|
|
78
|
+
app.use(passport.initialize());
|
|
79
|
+
app.use(passport.session());
|
|
80
|
+
|
|
81
|
+
passport.serializeUser((user, done) => done(null, user));
|
|
82
|
+
passport.deserializeUser((obj, done) => done(null, obj));
|
|
83
|
+
|
|
84
|
+
passport.use(
|
|
85
|
+
new DiscordStrategy(
|
|
86
|
+
{
|
|
87
|
+
clientID,
|
|
88
|
+
clientSecret,
|
|
89
|
+
callbackURL,
|
|
90
|
+
scope: ["identify", "guilds"],
|
|
91
|
+
},
|
|
92
|
+
(accessToken, refreshToken, profile, done) => {
|
|
93
|
+
return done(null, profile);
|
|
94
|
+
}
|
|
95
|
+
)
|
|
96
|
+
);
|
|
97
|
+
|
|
98
|
+
// Middleware للتحقق من تسجيل الدخول
|
|
99
|
+
function isAuthenticated(req, res, next) {
|
|
100
|
+
if (req.isAuthenticated()) return next();
|
|
101
|
+
res.redirect("/login");
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// تمرير بيانات المستخدم والبوت لكل الصفحات
|
|
105
|
+
app.use((req, res, next) => {
|
|
106
|
+
res.locals.user = req.user || null;
|
|
107
|
+
res.locals.client = client;
|
|
108
|
+
res.locals.path = req.path;
|
|
109
|
+
next();
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
// ==================== دالة مساعدة للإحصائيات ====================
|
|
113
|
+
function getBotStats() {
|
|
114
|
+
const uniquePrefixCommands = new Set();
|
|
115
|
+
if (client.prefixCommands) {
|
|
116
|
+
client.prefixCommands.forEach((cmd) => {
|
|
117
|
+
uniquePrefixCommands.add(cmd.name);
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// محاولة الحصول على البادئة من client
|
|
122
|
+
const prefix = client.prefix || options.prefix || '-';
|
|
123
|
+
|
|
124
|
+
return {
|
|
125
|
+
guilds: client.guilds?.cache?.size || 0,
|
|
126
|
+
users: client.guilds?.cache?.reduce((acc, g) => acc + g.memberCount, 0) || 0,
|
|
127
|
+
channels: client.channels?.cache?.size || 0,
|
|
128
|
+
slashCommands: client.slashCommands?.size || 0,
|
|
129
|
+
prefixCommands: uniquePrefixCommands.size,
|
|
130
|
+
events: client.djsEventListeners?.size || 0,
|
|
131
|
+
uptime: client.uptime || 0,
|
|
132
|
+
ping: client.ws?.ping || 0,
|
|
133
|
+
botName: client.user?.username || "Bot",
|
|
134
|
+
botAvatar: client.user?.displayAvatarURL({ size: 256 }) || "",
|
|
135
|
+
botId: client.user?.id || "",
|
|
136
|
+
botTag: client.user?.tag || "",
|
|
137
|
+
prefix: prefix,
|
|
138
|
+
startedAt: Date.now() - (client.uptime || 0),
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
// ==================== المسارات الرئيسية ====================
|
|
143
|
+
|
|
144
|
+
// الصفحة الرئيسية
|
|
145
|
+
app.get("/", (req, res) => {
|
|
146
|
+
res.render("index", {
|
|
147
|
+
botStats: getBotStats(),
|
|
148
|
+
});
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
// صفحة تسجيل الدخول
|
|
152
|
+
app.get("/login", (req, res) => {
|
|
153
|
+
if (req.isAuthenticated()) return res.redirect("/dashboard");
|
|
154
|
+
res.render("login", { botStats: getBotStats() });
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
// OAuth2 مع Discord
|
|
158
|
+
app.get("/auth/discord", passport.authenticate("discord"));
|
|
159
|
+
|
|
160
|
+
app.get(
|
|
161
|
+
"/auth/discord/callback",
|
|
162
|
+
passport.authenticate("discord", {
|
|
163
|
+
failureRedirect: "/login",
|
|
164
|
+
}),
|
|
165
|
+
(req, res) => {
|
|
166
|
+
res.redirect("/dashboard");
|
|
167
|
+
}
|
|
168
|
+
);
|
|
169
|
+
|
|
170
|
+
// تسجيل الخروج
|
|
171
|
+
app.get("/logout", (req, res) => {
|
|
172
|
+
req.logout(() => {
|
|
173
|
+
res.redirect("/");
|
|
174
|
+
});
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
// ==================== لوحة التحكم ====================
|
|
178
|
+
|
|
179
|
+
// لوحة التحكم الرئيسية
|
|
180
|
+
app.get("/dashboard", isAuthenticated, (req, res) => {
|
|
181
|
+
const userGuilds = req.user.guilds.filter(
|
|
182
|
+
(g) =>
|
|
183
|
+
(g.permissions & 0x20) === 0x20 && client.guilds.cache.has(g.id)
|
|
184
|
+
);
|
|
185
|
+
res.render("dashboard", {
|
|
186
|
+
guilds: userGuilds,
|
|
187
|
+
botStats: getBotStats()
|
|
188
|
+
});
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
// إدارة سيرفر معين - نظرة عامة
|
|
192
|
+
app.get("/dashboard/:guildId", isAuthenticated, async (req, res) => {
|
|
193
|
+
const guild = client.guilds.cache.get(req.params.guildId);
|
|
194
|
+
if (!guild) return res.redirect("/dashboard");
|
|
195
|
+
|
|
196
|
+
const userGuild = req.user.guilds.find((g) => g.id === req.params.guildId);
|
|
197
|
+
if (!userGuild || (userGuild.permissions & 0x20) !== 0x20) {
|
|
198
|
+
return res.redirect("/dashboard");
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
// جمع إحصائيات السيرفر
|
|
202
|
+
let levelCount = 0;
|
|
203
|
+
let giveawayCount = 0;
|
|
204
|
+
let blacklistCount = 0;
|
|
205
|
+
|
|
206
|
+
try {
|
|
207
|
+
if (Level) levelCount = await Level.countDocuments({ guildId: guild.id });
|
|
208
|
+
if (giveaway) giveawayCount = await giveaway.countDocuments({ guildId: guild.id, ended: false });
|
|
209
|
+
if (Blacklist) blacklistCount = await Blacklist.countDocuments({ guild: guild.id });
|
|
210
|
+
} catch (e) {
|
|
211
|
+
console.error("Stats error:", e);
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
res.render("guild", {
|
|
215
|
+
guild,
|
|
216
|
+
page: "overview",
|
|
217
|
+
stats: {
|
|
218
|
+
members: guild.memberCount,
|
|
219
|
+
channels: guild.channels.cache.size,
|
|
220
|
+
roles: guild.roles.cache.size,
|
|
221
|
+
emojis: guild.emojis.cache.size,
|
|
222
|
+
levelUsers: levelCount,
|
|
223
|
+
activeGiveaways: giveawayCount,
|
|
224
|
+
blacklisted: blacklistCount,
|
|
225
|
+
},
|
|
226
|
+
botStats: getBotStats()
|
|
227
|
+
});
|
|
228
|
+
});
|
|
229
|
+
|
|
230
|
+
// ==================== صفحة الأوامر ====================
|
|
231
|
+
app.get("/dashboard/:guildId/commands", isAuthenticated, async (req, res) => {
|
|
232
|
+
const guild = client.guilds.cache.get(req.params.guildId);
|
|
233
|
+
if (!guild) return res.redirect("/dashboard");
|
|
234
|
+
|
|
235
|
+
const slashCommands = client.slashCommands
|
|
236
|
+
? Array.from(client.slashCommands.values())
|
|
237
|
+
: [];
|
|
238
|
+
|
|
239
|
+
// إزالة التكرارات من prefix commands
|
|
240
|
+
const uniquePrefixCommands = [];
|
|
241
|
+
const seen = new Set();
|
|
242
|
+
if (client.prefixCommands) {
|
|
243
|
+
client.prefixCommands.forEach((cmd) => {
|
|
244
|
+
if (!seen.has(cmd.name)) {
|
|
245
|
+
seen.add(cmd.name);
|
|
246
|
+
uniquePrefixCommands.push(cmd);
|
|
247
|
+
}
|
|
248
|
+
});
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
res.render("commands", {
|
|
252
|
+
guild,
|
|
253
|
+
slashCommands,
|
|
254
|
+
prefixCommands: uniquePrefixCommands,
|
|
255
|
+
page: "commands",
|
|
256
|
+
botStats: getBotStats()
|
|
257
|
+
});
|
|
258
|
+
});
|
|
259
|
+
|
|
260
|
+
// ==================== نظام اللفل ====================
|
|
261
|
+
app.get("/dashboard/:guildId/levels", isAuthenticated, async (req, res) => {
|
|
262
|
+
const guild = client.guilds.cache.get(req.params.guildId);
|
|
263
|
+
if (!guild) return res.redirect("/dashboard");
|
|
264
|
+
|
|
265
|
+
let leaderboardData = [];
|
|
266
|
+
if (Level) {
|
|
267
|
+
try {
|
|
268
|
+
leaderboardData = await Level.find({ guildId: guild.id })
|
|
269
|
+
.sort({ totalXP: -1 })
|
|
270
|
+
.limit(100);
|
|
271
|
+
} catch (e) {
|
|
272
|
+
console.error("Error fetching levels:", e);
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
res.render("levels", {
|
|
277
|
+
guild,
|
|
278
|
+
leaderboard: leaderboardData,
|
|
279
|
+
page: "levels",
|
|
280
|
+
botStats: getBotStats()
|
|
281
|
+
});
|
|
282
|
+
});
|
|
283
|
+
|
|
284
|
+
// API للحصول على بيانات مستخدم
|
|
285
|
+
app.get("/api/:guildId/user/:userId", isAuthenticated, async (req, res) => {
|
|
286
|
+
if (!Level) return res.json({ error: "Level system not available" });
|
|
287
|
+
|
|
288
|
+
try {
|
|
289
|
+
const userData = await Level.findOne({
|
|
290
|
+
guildId: req.params.guildId,
|
|
291
|
+
userId: req.params.userId,
|
|
292
|
+
});
|
|
293
|
+
res.json(userData || { level: 0, totalXP: 0, text: 0, voice: 0 });
|
|
294
|
+
} catch (e) {
|
|
295
|
+
res.json({ error: e.message });
|
|
296
|
+
}
|
|
297
|
+
});
|
|
298
|
+
|
|
299
|
+
// ==================== نظام الجيف اوي ====================
|
|
300
|
+
app.get("/dashboard/:guildId/giveaways", isAuthenticated, async (req, res) => {
|
|
301
|
+
const guild = client.guilds.cache.get(req.params.guildId);
|
|
302
|
+
if (!guild) return res.redirect("/dashboard");
|
|
303
|
+
|
|
304
|
+
let giveaways = [];
|
|
305
|
+
if (giveaway) {
|
|
306
|
+
try {
|
|
307
|
+
giveaways = await giveaway.find({ guildId: guild.id }).sort({ endTime: -1 });
|
|
308
|
+
} catch (e) {
|
|
309
|
+
console.error("Error fetching giveaways:", e);
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
res.render("giveaways", {
|
|
314
|
+
guild,
|
|
315
|
+
giveaways,
|
|
316
|
+
page: "giveaways",
|
|
317
|
+
botStats: getBotStats()
|
|
318
|
+
});
|
|
319
|
+
});
|
|
320
|
+
|
|
321
|
+
// API للجيف اوي
|
|
322
|
+
app.post("/api/:guildId/giveaway/:action", isAuthenticated, async (req, res) => {
|
|
323
|
+
const { guildId, action } = req.params;
|
|
324
|
+
const { messageId } = req.body;
|
|
325
|
+
|
|
326
|
+
try {
|
|
327
|
+
let result = { success: true };
|
|
328
|
+
switch (action) {
|
|
329
|
+
case "pause":
|
|
330
|
+
if (Gpause) await Gpause(client, messageId);
|
|
331
|
+
break;
|
|
332
|
+
case "resume":
|
|
333
|
+
// تنفيذ يدوي للاستئناف لأن Gresume في djs-builder يحتوي على خطأ
|
|
334
|
+
if (Gresume) await Gresume(client, messageId);
|
|
335
|
+
break;
|
|
336
|
+
case "end":
|
|
337
|
+
// إنهاء الجيف اوي فوراً بتعديل وقت الانتهاء للوقت الحالي
|
|
338
|
+
if (giveaway) {
|
|
339
|
+
const g = await giveaway.findOne({ messageId });
|
|
340
|
+
if (g && !g.ended) {
|
|
341
|
+
// إذا كان متوقفاً مؤقتاً، نلغي الإيقاف أولاً
|
|
342
|
+
await giveaway.findOneAndUpdate(
|
|
343
|
+
{ messageId },
|
|
344
|
+
{ paused: false, endTime: Date.now().toString() }
|
|
345
|
+
);
|
|
346
|
+
// إعطاء Gcheck فرصة للتشغيل
|
|
347
|
+
setTimeout(() => Gcheck && Gcheck(client), 1000);
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
break;
|
|
351
|
+
case "reroll":
|
|
352
|
+
if (Greroll) await Greroll(client, messageId);
|
|
353
|
+
break;
|
|
354
|
+
case "delete":
|
|
355
|
+
if (Gdelete) await Gdelete(messageId);
|
|
356
|
+
break;
|
|
357
|
+
default:
|
|
358
|
+
return res.json({ success: false, error: "Invalid action" });
|
|
359
|
+
}
|
|
360
|
+
res.json({ success: true, message: `تم تنفيذ ${action} بنجاح` });
|
|
361
|
+
} catch (e) {
|
|
362
|
+
console.error("Giveaway action error:", e);
|
|
363
|
+
res.json({ success: false, error: e.message });
|
|
364
|
+
}
|
|
365
|
+
});
|
|
366
|
+
|
|
367
|
+
// ==================== نظام البلاك ليست ====================
|
|
368
|
+
// API لإضافة للبلاك ليست
|
|
369
|
+
app.post("/api/guild/:guildId/blacklist", isAuthenticated, async (req, res) => {
|
|
370
|
+
const { type, id } = req.body;
|
|
371
|
+
const guildId = req.params.guildId;
|
|
372
|
+
|
|
373
|
+
try {
|
|
374
|
+
if (addToBlacklist) {
|
|
375
|
+
const result = await addToBlacklist(guildId, type, id);
|
|
376
|
+
return res.json({ success: result });
|
|
377
|
+
} else if (Blacklist) {
|
|
378
|
+
const exists = await Blacklist.findOne({ guild: guildId, type, id });
|
|
379
|
+
if (!exists) {
|
|
380
|
+
await Blacklist.create({ guild: guildId, type, id });
|
|
381
|
+
}
|
|
382
|
+
return res.json({ success: true });
|
|
383
|
+
}
|
|
384
|
+
res.json({ error: "Blacklist system not available" });
|
|
385
|
+
} catch (e) {
|
|
386
|
+
res.json({ success: false, error: e.message });
|
|
387
|
+
}
|
|
388
|
+
});
|
|
389
|
+
|
|
390
|
+
// API لحذف من البلاك ليست
|
|
391
|
+
app.delete("/api/guild/:guildId/blacklist", isAuthenticated, async (req, res) => {
|
|
392
|
+
const { type, id } = req.body;
|
|
393
|
+
const guildId = req.params.guildId;
|
|
394
|
+
|
|
395
|
+
try {
|
|
396
|
+
if (removeFromBlacklist) {
|
|
397
|
+
const result = await removeFromBlacklist(guildId, type, id);
|
|
398
|
+
return res.json({ success: result });
|
|
399
|
+
} else if (Blacklist) {
|
|
400
|
+
await Blacklist.deleteOne({ guild: guildId, type, id });
|
|
401
|
+
return res.json({ success: true });
|
|
402
|
+
}
|
|
403
|
+
res.json({ error: "Blacklist system not available" });
|
|
404
|
+
} catch (e) {
|
|
405
|
+
res.json({ success: false, error: e.message });
|
|
406
|
+
}
|
|
407
|
+
});
|
|
408
|
+
|
|
409
|
+
// ==================== API القائمة السوداء العامة ====================
|
|
410
|
+
app.get("/api/blacklist/:type", isAuthenticated, async (req, res) => {
|
|
411
|
+
const { type } = req.params;
|
|
412
|
+
try {
|
|
413
|
+
if (Blacklist) {
|
|
414
|
+
const typeMap = { users: 'user', roles: 'role', channels: 'channel' };
|
|
415
|
+
const items = await Blacklist.find({ type: typeMap[type] || type });
|
|
416
|
+
return res.json({ items });
|
|
417
|
+
}
|
|
418
|
+
res.json({ items: [] });
|
|
419
|
+
} catch (e) {
|
|
420
|
+
res.json({ items: [], error: e.message });
|
|
421
|
+
}
|
|
422
|
+
});
|
|
423
|
+
|
|
424
|
+
app.post("/api/blacklist", isAuthenticated, async (req, res) => {
|
|
425
|
+
const { type, id } = req.body;
|
|
426
|
+
try {
|
|
427
|
+
if (Blacklist) {
|
|
428
|
+
const exists = await Blacklist.findOne({ type, id });
|
|
429
|
+
if (!exists) {
|
|
430
|
+
await Blacklist.create({ type, id, guild: 'global' });
|
|
431
|
+
}
|
|
432
|
+
return res.json({ success: true });
|
|
433
|
+
}
|
|
434
|
+
res.json({ error: "Blacklist not available" });
|
|
435
|
+
} catch (e) {
|
|
436
|
+
res.json({ success: false, error: e.message });
|
|
437
|
+
}
|
|
438
|
+
});
|
|
439
|
+
|
|
440
|
+
app.delete("/api/blacklist", isAuthenticated, async (req, res) => {
|
|
441
|
+
const { type, id } = req.body;
|
|
442
|
+
try {
|
|
443
|
+
if (Blacklist) {
|
|
444
|
+
await Blacklist.deleteOne({ type, id });
|
|
445
|
+
return res.json({ success: true });
|
|
446
|
+
}
|
|
447
|
+
res.json({ error: "Blacklist not available" });
|
|
448
|
+
} catch (e) {
|
|
449
|
+
res.json({ success: false, error: e.message });
|
|
450
|
+
}
|
|
451
|
+
});
|
|
452
|
+
|
|
453
|
+
// API لجلب بيانات مستخدم (عام)
|
|
454
|
+
app.get("/api/user/:userId", isAuthenticated, async (req, res) => {
|
|
455
|
+
try {
|
|
456
|
+
const user = await client.users.fetch(req.params.userId).catch(() => null);
|
|
457
|
+
if (user) {
|
|
458
|
+
return res.json({
|
|
459
|
+
id: user.id,
|
|
460
|
+
username: user.username,
|
|
461
|
+
global_name: user.globalName,
|
|
462
|
+
avatar: user.avatar,
|
|
463
|
+
discriminator: user.discriminator
|
|
464
|
+
});
|
|
465
|
+
}
|
|
466
|
+
res.json({ error: "User not found" });
|
|
467
|
+
} catch (e) {
|
|
468
|
+
res.json({ error: e.message });
|
|
469
|
+
}
|
|
470
|
+
});
|
|
471
|
+
|
|
472
|
+
// ==================== API للأعضاء ====================
|
|
473
|
+
// الحصول على معلومات عضو
|
|
474
|
+
app.get("/api/:guildId/member/:userId", isAuthenticated, async (req, res) => {
|
|
475
|
+
const guild = client.guilds.cache.get(req.params.guildId);
|
|
476
|
+
if (!guild) return res.json({ error: "Guild not found" });
|
|
477
|
+
|
|
478
|
+
try {
|
|
479
|
+
const member = await guild.members.fetch(req.params.userId).catch(() => null);
|
|
480
|
+
if (member) {
|
|
481
|
+
return res.json({
|
|
482
|
+
user: {
|
|
483
|
+
id: member.user.id,
|
|
484
|
+
username: member.user.username,
|
|
485
|
+
global_name: member.user.globalName,
|
|
486
|
+
avatar: member.user.avatar,
|
|
487
|
+
discriminator: member.user.discriminator
|
|
488
|
+
},
|
|
489
|
+
displayName: member.displayName
|
|
490
|
+
});
|
|
491
|
+
}
|
|
492
|
+
res.json({ error: "Member not found" });
|
|
493
|
+
} catch (e) {
|
|
494
|
+
res.json({ error: e.message });
|
|
495
|
+
}
|
|
496
|
+
});
|
|
497
|
+
|
|
498
|
+
// البحث عن أعضاء
|
|
499
|
+
app.get("/api/:guildId/members/search", isAuthenticated, async (req, res) => {
|
|
500
|
+
const guild = client.guilds.cache.get(req.params.guildId);
|
|
501
|
+
if (!guild) return res.json({ members: [] });
|
|
502
|
+
|
|
503
|
+
const query = (req.query.q || '').toLowerCase();
|
|
504
|
+
if (query.length < 2) return res.json({ members: [] });
|
|
505
|
+
|
|
506
|
+
try {
|
|
507
|
+
// جلب الأعضاء من الكاش
|
|
508
|
+
const members = guild.members.cache
|
|
509
|
+
.filter(m =>
|
|
510
|
+
m.user.username.toLowerCase().includes(query) ||
|
|
511
|
+
m.displayName.toLowerCase().includes(query) ||
|
|
512
|
+
m.user.id.includes(query)
|
|
513
|
+
)
|
|
514
|
+
.first(20)
|
|
515
|
+
.map(m => ({
|
|
516
|
+
id: m.user.id,
|
|
517
|
+
username: m.user.username,
|
|
518
|
+
displayName: m.displayName,
|
|
519
|
+
avatar: m.user.avatar,
|
|
520
|
+
discriminator: m.user.discriminator
|
|
521
|
+
}));
|
|
522
|
+
|
|
523
|
+
res.json({ members });
|
|
524
|
+
} catch (e) {
|
|
525
|
+
res.json({ members: [], error: e.message });
|
|
526
|
+
}
|
|
527
|
+
});
|
|
528
|
+
|
|
529
|
+
// ==================== API للمستويات ====================
|
|
530
|
+
// تحديث مستوى مستخدم
|
|
531
|
+
app.post("/api/:guildId/level/update", isAuthenticated, async (req, res) => {
|
|
532
|
+
const { userId, xp, level } = req.body;
|
|
533
|
+
const guildId = req.params.guildId;
|
|
534
|
+
|
|
535
|
+
try {
|
|
536
|
+
if (Level) {
|
|
537
|
+
await Level.findOneAndUpdate(
|
|
538
|
+
{ guildId, userId },
|
|
539
|
+
{ totalXP: xp, level, $setOnInsert: { text: 0, voice: 0 } },
|
|
540
|
+
{ upsert: true, new: true }
|
|
541
|
+
);
|
|
542
|
+
return res.json({ success: true });
|
|
543
|
+
}
|
|
544
|
+
res.json({ error: "Level system not available" });
|
|
545
|
+
} catch (e) {
|
|
546
|
+
res.json({ success: false, error: e.message });
|
|
547
|
+
}
|
|
548
|
+
});
|
|
549
|
+
|
|
550
|
+
// إضافة XP لمستخدم
|
|
551
|
+
app.post("/api/:guildId/level/add", isAuthenticated, async (req, res) => {
|
|
552
|
+
const { userId, xp, level } = req.body;
|
|
553
|
+
const guildId = req.params.guildId;
|
|
554
|
+
|
|
555
|
+
try {
|
|
556
|
+
if (Level) {
|
|
557
|
+
const existing = await Level.findOne({ guildId, userId });
|
|
558
|
+
if (existing) {
|
|
559
|
+
existing.totalXP += xp;
|
|
560
|
+
if (level > 0) existing.level = level;
|
|
561
|
+
await existing.save();
|
|
562
|
+
} else {
|
|
563
|
+
await Level.create({ guildId, userId, totalXP: xp, level: level || 0, text: 0, voice: 0 });
|
|
564
|
+
}
|
|
565
|
+
return res.json({ success: true });
|
|
566
|
+
}
|
|
567
|
+
res.json({ error: "Level system not available" });
|
|
568
|
+
} catch (e) {
|
|
569
|
+
res.json({ success: false, error: e.message });
|
|
570
|
+
}
|
|
571
|
+
});
|
|
572
|
+
|
|
573
|
+
// إعادة تعيين مستوى مستخدم
|
|
574
|
+
app.post("/api/:guildId/level/reset", isAuthenticated, async (req, res) => {
|
|
575
|
+
const { userId } = req.body;
|
|
576
|
+
const guildId = req.params.guildId;
|
|
577
|
+
|
|
578
|
+
try {
|
|
579
|
+
if (Level) {
|
|
580
|
+
await Level.deleteOne({ guildId, userId });
|
|
581
|
+
return res.json({ success: true });
|
|
582
|
+
}
|
|
583
|
+
res.json({ error: "Level system not available" });
|
|
584
|
+
} catch (e) {
|
|
585
|
+
res.json({ success: false, error: e.message });
|
|
586
|
+
}
|
|
587
|
+
});
|
|
588
|
+
|
|
589
|
+
// ==================== API للإحصائيات ====================
|
|
590
|
+
app.get("/api/stats", (req, res) => {
|
|
591
|
+
res.json(getBotStats());
|
|
592
|
+
});
|
|
593
|
+
|
|
594
|
+
// API لإحصائيات السيرفر
|
|
595
|
+
app.get("/api/:guildId/stats", isAuthenticated, async (req, res) => {
|
|
596
|
+
const guild = client.guilds.cache.get(req.params.guildId);
|
|
597
|
+
if (!guild) return res.json({ error: "Guild not found" });
|
|
598
|
+
|
|
599
|
+
let levelCount = 0;
|
|
600
|
+
let giveawayCount = 0;
|
|
601
|
+
let blacklistCount = 0;
|
|
602
|
+
|
|
603
|
+
try {
|
|
604
|
+
if (Level) levelCount = await Level.countDocuments({ guildId: guild.id });
|
|
605
|
+
if (giveaway) giveawayCount = await giveaway.countDocuments({ guildId: guild.id, ended: false });
|
|
606
|
+
if (Blacklist) blacklistCount = await Blacklist.countDocuments({ guild: guild.id });
|
|
607
|
+
} catch (e) {
|
|
608
|
+
console.error("Stats error:", e);
|
|
609
|
+
}
|
|
610
|
+
|
|
611
|
+
res.json({
|
|
612
|
+
members: guild.memberCount,
|
|
613
|
+
channels: guild.channels.cache.size,
|
|
614
|
+
roles: guild.roles.cache.size,
|
|
615
|
+
emojis: guild.emojis.cache.size,
|
|
616
|
+
levelUsers: levelCount,
|
|
617
|
+
activeGiveaways: giveawayCount,
|
|
618
|
+
blacklisted: blacklistCount,
|
|
619
|
+
});
|
|
620
|
+
});
|
|
621
|
+
|
|
622
|
+
// ==================== صفحة 404 ====================
|
|
623
|
+
app.use((req, res) => {
|
|
624
|
+
res.status(404).render("404", { botStats: getBotStats() });
|
|
625
|
+
});
|
|
626
|
+
|
|
627
|
+
// تشغيل الخادم
|
|
628
|
+
app.listen(port, () => {
|
|
629
|
+
console.log(`\n🌐 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━`);
|
|
630
|
+
console.log(` DJS-Builder Dashboard v2.0`);
|
|
631
|
+
console.log(` 🔗 http://localhost:${port}`);
|
|
632
|
+
console.log(`━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n`);
|
|
633
|
+
});
|
|
634
|
+
|
|
635
|
+
return app;
|
|
636
|
+
}
|
|
637
|
+
|
|
638
|
+
module.exports = { dashboard };
|