djs-builder 0.7.3 → 0.7.5

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/function/dash.js CHANGED
@@ -31,6 +31,7 @@ const {
31
31
  Gresume,
32
32
  Gdelete
33
33
  } = require("./giveaway");
34
+ const { Log, getLogConfigData } = require("./log");
34
35
 
35
36
  /**
36
37
  * دالة لإنشاء وتشغيل لوحة التحكم
@@ -40,17 +41,16 @@ const {
40
41
  function dashboard(client, options) {
41
42
  const app = express();
42
43
  const {
43
- clientID,
44
44
  clientSecret,
45
- callbackURL,
46
- sessionSecret,
45
+ callbackURL = "http://localhost:3000/auth/discord/callback",
46
+ sessionSecret ,
47
47
  port = 3000,
48
48
  } = options;
49
49
 
50
+ clientID = client.user.id;
50
51
  // إعداد المسارات
51
52
  app.set("view engine", "ejs");
52
- app.set("views", path.join(__dirname, "..", "views")); // تم تصحيح المسار
53
- app.use(express.static(path.join(__dirname, "..", "public"))); // تم تصحيح المسار
53
+ app.set("views", path.join(__dirname, "..", "views"));
54
54
  app.use(express.json());
55
55
  app.use(express.urlencoded({ extended: true }));
56
56
 
@@ -356,6 +356,213 @@ function dashboard(client, options) {
356
356
  }
357
357
  });
358
358
 
359
+ // ==================== نظام السجلات (Logs) ====================
360
+ // قائمة أنواع الأحداث المدعومة
361
+ const LOG_EVENT_TYPES = [
362
+ { name: "حذف رسالة", value: "messageDelete", icon: "ri-delete-bin-line" },
363
+ { name: "تعديل رسالة", value: "messageUpdate", icon: "ri-edit-line" },
364
+ { name: "إنشاء قناة", value: "channelCreate", icon: "ri-add-circle-line" },
365
+ { name: "حذف قناة", value: "channelDelete", icon: "ri-close-circle-line" },
366
+ { name: "تعديل قناة", value: "channelUpdate", icon: "ri-settings-3-line" },
367
+ { name: "انضمام عضو", value: "guildMemberAdd", icon: "ri-user-add-line" },
368
+ { name: "مغادرة عضو", value: "guildMemberRemove", icon: "ri-user-unfollow-line" },
369
+ { name: "حظر عضو", value: "guildBanAdd", icon: "ri-forbid-line" },
370
+ { name: "رفع الحظر", value: "guildBanRemove", icon: "ri-checkbox-circle-line" },
371
+ { name: "إنشاء رتبة", value: "roleCreate", icon: "ri-shield-star-line" },
372
+ { name: "حذف رتبة", value: "roleDelete", icon: "ri-shield-cross-line" },
373
+ { name: "تعديل رتبة", value: "roleUpdate", icon: "ri-shield-line" },
374
+ { name: "تغيير رتب العضو", value: "guildMemberUpdate", icon: "ri-user-settings-line" },
375
+ { name: "نشاط صوتي", value: "voiceStateUpdate", icon: "ri-mic-line" },
376
+ { name: "إنشاء دعوة", value: "inviteCreate", icon: "ri-links-line" },
377
+ { name: "إضافة إيموجي", value: "emojiCreate", icon: "ri-emotion-happy-line" },
378
+ { name: "حذف إيموجي", value: "emojiDelete", icon: "ri-emotion-unhappy-line" },
379
+ { name: "تعديل إيموجي", value: "emojiUpdate", icon: "ri-emotion-line" },
380
+ { name: "إضافة ستيكر", value: "stickerCreate", icon: "ri-sticky-note-line" },
381
+ { name: "حذف ستيكر", value: "stickerDelete", icon: "ri-sticky-note-2-line" },
382
+ { name: "تعديل ستيكر", value: "stickerUpdate", icon: "ri-file-edit-line" },
383
+ ];
384
+
385
+ // صفحة السجلات
386
+ app.get("/dashboard/:guildId/logs", isAuthenticated, async (req, res) => {
387
+ const guild = client.guilds.cache.get(req.params.guildId);
388
+ if (!guild) return res.redirect("/dashboard");
389
+
390
+ const userGuild = req.user.guilds.find((g) => g.id === req.params.guildId);
391
+ if (!userGuild || (userGuild.permissions & 0x20) !== 0x20) {
392
+ return res.redirect("/dashboard");
393
+ }
394
+
395
+ // الحصول على بيانات الـ log
396
+ const logData = getLogConfigData();
397
+ const databaseEnabled = logData.databaseEnabled;
398
+ let logConfig = null;
399
+ let configSource = null; // "database" أو "code" أو null
400
+
401
+ if (databaseEnabled) {
402
+ // وضع Database - قراءة من قاعدة البيانات
403
+ try {
404
+ logConfig = await Log.findOne({ guildId: guild.id });
405
+ if (logConfig) configSource = "database";
406
+ } catch (e) {
407
+ console.error("Error fetching log config:", e);
408
+ }
409
+ } else {
410
+ // وضع Code - قراءة من الكود المكتوب
411
+ const codeConfig = logData.configs.find(c => c.guildId === guild.id);
412
+ if (codeConfig) {
413
+ logConfig = codeConfig;
414
+ configSource = "code";
415
+ }
416
+ }
417
+
418
+ // الحصول على قنوات السيرفر النصية
419
+ const channels = guild.channels.cache
420
+ .filter(c => c.type === 0) // GuildText
421
+ .map(c => ({ id: c.id, name: c.name }))
422
+ .sort((a, b) => a.name.localeCompare(b.name));
423
+
424
+ // حساب الإحصائيات
425
+ const disabledEvents = logConfig?.disable?.length || 0;
426
+ const enabledEvents = LOG_EVENT_TYPES.length - disabledEvents;
427
+ const customColors = logConfig?.colors ? Object.keys(logConfig.colors).length : 0;
428
+ const customChannels = logConfig?.channels ? Object.keys(logConfig.channels).length : 0;
429
+
430
+ res.render("logs", {
431
+ guild,
432
+ page: "logs",
433
+ botStats: getBotStats(),
434
+ databaseEnabled,
435
+ configSource,
436
+ logConfig,
437
+ channels,
438
+ eventTypes: LOG_EVENT_TYPES,
439
+ enabledEvents,
440
+ disabledEvents,
441
+ customColors,
442
+ customChannels
443
+ });
444
+ });
445
+
446
+ // API - تحديث القناة الافتراضية
447
+ app.post("/api/:guildId/logs/channel", isAuthenticated, async (req, res) => {
448
+ const logData = getLogConfigData();
449
+ if (!logData.databaseEnabled) return res.json({ error: "يجب تفعيل وضع Database لتعديل الإعدادات" });
450
+
451
+ const { channelId } = req.body;
452
+ const guildId = req.params.guildId;
453
+
454
+ try {
455
+ await Log.findOneAndUpdate(
456
+ { guildId },
457
+ { guildId, channelId },
458
+ { upsert: true, new: true }
459
+ );
460
+ // تنظيف الـ cache
461
+ if (logData.clearCache) logData.clearCache(guildId);
462
+ res.json({ success: true });
463
+ } catch (e) {
464
+ res.json({ success: false, error: e.message });
465
+ }
466
+ });
467
+
468
+ // API - تفعيل/تعطيل حدث
469
+ app.post("/api/:guildId/logs/toggle", isAuthenticated, async (req, res) => {
470
+ const logData = getLogConfigData();
471
+ if (!logData.databaseEnabled) return res.json({ error: "يجب تفعيل وضع Database لتعديل الإعدادات" });
472
+
473
+ const { eventType, enable } = req.body;
474
+ const guildId = req.params.guildId;
475
+
476
+ try {
477
+ if (enable) {
478
+ // تفعيل (إزالة من قائمة المعطل)
479
+ await Log.findOneAndUpdate(
480
+ { guildId },
481
+ { $pull: { disable: eventType } },
482
+ { upsert: true }
483
+ );
484
+ } else {
485
+ // تعطيل (إضافة لقائمة المعطل)
486
+ await Log.findOneAndUpdate(
487
+ { guildId },
488
+ { $addToSet: { disable: eventType } },
489
+ { upsert: true }
490
+ );
491
+ }
492
+ // تنظيف الـ cache
493
+ const logData = getLogConfigData();
494
+ if (logData.clearCache) logData.clearCache(guildId);
495
+ res.json({ success: true });
496
+ } catch (e) {
497
+ res.json({ success: false, error: e.message });
498
+ }
499
+ });
500
+
501
+ // API - تحديث إعدادات حدث معين
502
+ app.post("/api/:guildId/logs/event", isAuthenticated, async (req, res) => {
503
+ const logData = getLogConfigData();
504
+ if (!logData.databaseEnabled) return res.json({ error: "يجب تفعيل وضع Database لتعديل الإعدادات" });
505
+
506
+ const { eventType, channel, color } = req.body;
507
+ const guildId = req.params.guildId;
508
+
509
+ try {
510
+ const updateObj = {};
511
+
512
+ if (channel) {
513
+ updateObj[`channels.${eventType}`] = channel;
514
+ } else {
515
+ // إذا كانت فارغة، نحذف القناة المخصصة
516
+ await Log.findOneAndUpdate(
517
+ { guildId },
518
+ { $unset: { [`channels.${eventType}`]: "" } }
519
+ );
520
+ }
521
+
522
+ if (color) {
523
+ updateObj[`colors.${eventType}`] = color;
524
+ } else {
525
+ // إذا كان فارغاً، نحذف اللون المخصص
526
+ await Log.findOneAndUpdate(
527
+ { guildId },
528
+ { $unset: { [`colors.${eventType}`]: "" } }
529
+ );
530
+ }
531
+
532
+ if (Object.keys(updateObj).length > 0) {
533
+ await Log.findOneAndUpdate(
534
+ { guildId },
535
+ { $set: updateObj },
536
+ { upsert: true }
537
+ );
538
+ }
539
+
540
+ // تنظيف الـ cache
541
+ const logData2 = getLogConfigData();
542
+ if (logData2.clearCache) logData2.clearCache(guildId);
543
+ res.json({ success: true });
544
+ } catch (e) {
545
+ res.json({ success: false, error: e.message });
546
+ }
547
+ });
548
+
549
+ // API - إعادة تعيين إعدادات السجلات
550
+ app.post("/api/:guildId/logs/reset", isAuthenticated, async (req, res) => {
551
+ const logData = getLogConfigData();
552
+ if (!logData.databaseEnabled) return res.json({ error: "يجب تفعيل وضع Database لتعديل الإعدادات" });
553
+
554
+ const guildId = req.params.guildId;
555
+
556
+ try {
557
+ await Log.findOneAndDelete({ guildId });
558
+ // تنظيف الـ cache
559
+ if (logData.clearCache) logData.clearCache(guildId);
560
+ res.json({ success: true });
561
+ } catch (e) {
562
+ res.json({ success: false, error: e.message });
563
+ }
564
+ });
565
+
359
566
  // ==================== نظام البلاك ليست ====================
360
567
  // API لإضافة للبلاك ليست
361
568
  app.post("/api/guild/:guildId/blacklist", isAuthenticated, async (req, res) => {
@@ -617,8 +824,7 @@ function dashboard(client, options) {
617
824
  });
618
825
 
619
826
  // تشغيل الخادم
620
- app.listen();
621
-
827
+ app.listen( port, () => {});
622
828
 
623
829
  return app;
624
830
  }
@@ -7,7 +7,23 @@ const {
7
7
  ButtonBuilder,
8
8
  } = require("discord.js");
9
9
 
10
- const axios = require("axios");
10
+ const {
11
+ ModalBuilder,
12
+ TextInputBuilder,
13
+ LabelBuilder,
14
+ FileUploadBuilder,
15
+ } = require("discord.js");
16
+
17
+ const {
18
+ TextDisplayBuilder,
19
+ ContainerBuilder,
20
+ SectionBuilder,
21
+ FileBuilder,
22
+ SeparatorBuilder,
23
+ MediaGalleryBuilder,
24
+ ThumbnailBuilder,
25
+ MediaGalleryItemBuilder,
26
+ } = require("discord.js");
11
27
 
12
28
  //////////////////////////////////* Bar 🔄
13
29
 
@@ -214,11 +230,11 @@ function CreateRow(components) {
214
230
  }
215
231
 
216
232
  if (type === "channel" && Array.isArray(channelTypes)) {
217
- selectMenu.setChannelTypes(channelTypes); // جديد
233
+ selectMenu.setChannelTypes(channelTypes);
218
234
  }
219
235
 
220
236
  if (defaultValues && Array.isArray(defaultValues)) {
221
- selectMenu.setDefaultValues(defaultValues); // جديد
237
+ selectMenu.setDefaultValues(defaultValues);
222
238
  }
223
239
 
224
240
  if (options.hasOwnProperty("disabled")) {
@@ -234,6 +250,305 @@ function CreateRow(components) {
234
250
  return actionRows;
235
251
  }
236
252
 
253
+ //////////////////////////////////* MODAL creat 🔩
254
+
255
+ async function CreateModal(options) {
256
+ const { id, title, components } = options;
257
+ const modal = new ModalBuilder().setCustomId(id).setTitle(title);
258
+
259
+ components.forEach((com) => {
260
+ if (com.type === "textInput") {
261
+ com.components.forEach((component) => {
262
+ const {
263
+ label,
264
+ description,
265
+ id,
266
+ style,
267
+ placeholder,
268
+ minLength,
269
+ maxLength,
270
+ required,
271
+ value,
272
+ } = component;
273
+ const input = new TextInputBuilder()
274
+ .setCustomId(id)
275
+ .setPlaceholder(placeholder)
276
+ .setStyle(style);
277
+ if (required !== undefined) input.setRequired(required);
278
+ if (minLength) input.setMinLength(minLength);
279
+ if (maxLength) input.setMaxLength(maxLength);
280
+ if (value) input.setValue(value);
281
+ const actionRow = new LabelBuilder()
282
+ .setLabel(label)
283
+ .setTextInputComponent(input);
284
+ if (description) actionRow.setDescription(description);
285
+
286
+ modal.addLabelComponents(actionRow);
287
+ });
288
+ } else if (com.type === "menu") {
289
+ const { type, options } = com.components;
290
+ const {
291
+ mine_label = false,
292
+ placeholder = "Choose an option",
293
+ description = false,
294
+ data = [],
295
+ label = false,
296
+ emoji = false,
297
+ value = false,
298
+ id = "selectMenu",
299
+ max = false,
300
+ min = false,
301
+ channelTypes = false,
302
+ defaultValues = false,
303
+ } = options;
304
+
305
+ let selectMenu;
306
+ if (type === "string") selectMenu = new StringSelectMenuBuilder();
307
+ else if (type === "user") selectMenu = new UserSelectMenuBuilder();
308
+ else if (type === "role") selectMenu = new RoleSelectMenuBuilder();
309
+ else if (type === "channel") selectMenu = new ChannelSelectMenuBuilder();
310
+
311
+ selectMenu.setCustomId(id);
312
+ selectMenu.setPlaceholder(placeholder);
313
+
314
+ if (min) {
315
+ selectMenu.setMinValues(Math.min(min, data.length));
316
+ }
317
+ if (max) {
318
+ selectMenu.setMaxValues(max);
319
+ } else if (min) {
320
+ selectMenu.setMaxValues(data.length);
321
+ }
322
+
323
+ if (type === "string" && Array.isArray(data)) {
324
+ const selectOptions = data.map((item, index) => ({
325
+ label: item[label] || `Option ${index + 1}`,
326
+ description: item[description]?.slice(0, 100) || undefined,
327
+ emoji: item[emoji] || undefined,
328
+ value: item[value] || `${index}`,
329
+ default: item.default || false,
330
+ }));
331
+ selectMenu.addOptions(selectOptions);
332
+ }
333
+
334
+ if (type === "channel" && Array.isArray(channelTypes)) {
335
+ selectMenu.setChannelTypes(channelTypes);
336
+ }
337
+
338
+ if (defaultValues && Array.isArray(defaultValues)) {
339
+ selectMenu.setDefaultValues(defaultValues);
340
+ }
341
+
342
+ const menu = new LabelBuilder()
343
+ .setLabel(mine_label || "Select an option")
344
+ .setStringSelectMenuComponent(selectMenu);
345
+
346
+ modal.addLabelComponents(menu);
347
+ } else if (com.type === "file") {
348
+ const { id, label, description } = com.components;
349
+
350
+ const fileUpload = new LabelBuilder().setLabel(label);
351
+ if (description) fileUpload.setDescription(description);
352
+ fileUpload.setFileUploadComponent(
353
+ new FileUploadBuilder().setCustomId(id)
354
+ );
355
+
356
+ modal.addLabelComponents(fileUpload);
357
+ } else if (com.type === "label") {
358
+ const { label } = com.components;
359
+ const text = new TextDisplayBuilder().setContent(label);
360
+
361
+ modal.addTextDisplayComponents(text);
362
+ }
363
+ });
364
+ return modal;
365
+ }
366
+
367
+ //////////////////////////////////* components creat 🔩
368
+
369
+ async function CreateComponents(type, components) {
370
+ let result;
371
+ if (type === "container") {
372
+ result = new ContainerBuilder();
373
+ } else {
374
+ result = [];
375
+ }
376
+
377
+ components.forEach((item) => {
378
+ if (item.type === "text") {
379
+ const text = new TextDisplayBuilder().setContent(item.content);
380
+
381
+ if (type !== "container") {
382
+ result.push(text);
383
+ } else {
384
+ result.addTextDisplayComponents(text);
385
+ }
386
+ } else if (item.type === "separator") {
387
+ const separator = new SeparatorBuilder().setDivider(
388
+ item.divider || false
389
+ );
390
+ if (item.spacing) separator.setSpacing(item.spacing);
391
+
392
+ if (type === "container") {
393
+ result.addSeparatorComponents(separator);
394
+ } else {
395
+ result.push(separator);
396
+ }
397
+ } else if (item.type === "media") {
398
+ let items = [];
399
+ item.links.forEach((link) => {
400
+ if (typeof link === "string") {
401
+ items.push(new MediaGalleryItemBuilder().setURL(link));
402
+ } else {
403
+ const mediaItem = new MediaGalleryItemBuilder().setURL(link.url);
404
+ if (link.description) mediaItem.setDescription(link.description);
405
+ if (link.spoiler) mediaItem.setSpoiler(true);
406
+ items.push(mediaItem);
407
+ }
408
+ });
409
+ const media = new MediaGalleryBuilder().addItems(items);
410
+ if (type === "container") {
411
+ result.addMediaGalleryComponents(media);
412
+ } else {
413
+ result.push(media);
414
+ }
415
+ } else if (item.type === "file") {
416
+ const file = new FileBuilder().setURL(item.url);
417
+ if (item.spoiler) file.setSpoiler(true);
418
+ if (type === "container") {
419
+ result.addFileComponents(file);
420
+ } else {
421
+ result.push(file);
422
+ }
423
+ } else if (item.type === "button") {
424
+ const buttons = [];
425
+
426
+ item.components.forEach((item) => {
427
+ const button = new ButtonBuilder().setStyle(item.style || 2);
428
+ if (item.label) button.setLabel(item.label);
429
+ if (item.emoji) button.setEmoji(item.emoji);
430
+ if (item.style !== 5) {
431
+ if (!item.id)
432
+ throw new Error("Button id is required for non-link buttons.");
433
+ button.setCustomId(item.id);
434
+ }
435
+ if (item.hasOwnProperty("disabled")) button.setDisabled(item.disabled);
436
+ if (item.style === 5 && item.url) button.setURL(item.url);
437
+ buttons.push(button);
438
+ });
439
+ const but = new ActionRowBuilder().addComponents(...buttons);
440
+
441
+ if (type === "container") {
442
+ result.addActionRowComponents(but);
443
+ } else {
444
+ result.push(but);
445
+ }
446
+ } else if (item.type === "menu") {
447
+ const menu_type = item.components.type;
448
+ const {
449
+ placeholder = "Choose an option",
450
+ description = false,
451
+ data = [],
452
+ label = false,
453
+ emoji = false,
454
+ value = false,
455
+ id = "selectMenu",
456
+ max = false,
457
+ min = false,
458
+ channelTypes = false,
459
+ defaultValues = false,
460
+ } = item.components.options;
461
+
462
+ let selectMenu;
463
+ if (menu_type === "string") selectMenu = new StringSelectMenuBuilder();
464
+ else if (menu_type === "user") selectMenu = new UserSelectMenuBuilder();
465
+ else if (menu_type === "role") selectMenu = new RoleSelectMenuBuilder();
466
+ else if (menu_type === "channel")
467
+ selectMenu = new ChannelSelectMenuBuilder();
468
+
469
+ console.log(menu_type, selectMenu, id);
470
+ selectMenu.setCustomId(id);
471
+ selectMenu.setPlaceholder(placeholder);
472
+
473
+ if (min) {
474
+ selectMenu.setMinValues(Math.min(min, data.length));
475
+ }
476
+ if (max) {
477
+ selectMenu.setMaxValues(max);
478
+ } else if (min) {
479
+ selectMenu.setMaxValues(data.length);
480
+ }
481
+
482
+ if (menu_type === "string" && Array.isArray(data)) {
483
+ const selectOptions = data.map((item, index) => ({
484
+ label: item[label] || `Option ${index + 1}`,
485
+ description: item[description]?.slice(0, 100) || undefined,
486
+ emoji: item[emoji] || undefined,
487
+ value: item[value] || `${index}`,
488
+ default: item.default || false,
489
+ }));
490
+ selectMenu.addOptions(selectOptions);
491
+ }
492
+
493
+ if (type === "channel" && Array.isArray(channelTypes)) {
494
+ selectMenu.setChannelTypes(channelTypes);
495
+ }
496
+
497
+ if (defaultValues && Array.isArray(defaultValues)) {
498
+ selectMenu.setDefaultValues(defaultValues);
499
+ }
500
+
501
+ const menu = new ActionRowBuilder().addComponents(selectMenu);
502
+
503
+ if (type === "container") {
504
+ result.addActionRowComponents(menu);
505
+ } else {
506
+ result.push(selectMenu);
507
+ }
508
+ } else if (item.type === "section") {
509
+ const section = new SectionBuilder();
510
+
511
+ if (item.content) {
512
+ section.addTextDisplayComponents(
513
+ new TextDisplayBuilder().setContent(item.content)
514
+ );
515
+ }
516
+
517
+ if (item.accessory) {
518
+ if (item.accessory.type === "button") {
519
+ const btn = new ButtonBuilder().setStyle(item.accessory.style || 2);
520
+ if (item.accessory.label) btn.setLabel(item.accessory.label);
521
+ if (item.accessory.emoji) btn.setEmoji(item.accessory.emoji);
522
+ if (item.accessory.style !== 5) {
523
+ btn.setCustomId(item.accessory.id);
524
+ } else if (item.accessory.url) {
525
+ btn.setURL(item.accessory.url);
526
+ }
527
+
528
+ section.setButtonAccessory(btn);
529
+ } else if (item.accessory.type === "thumbnail") {
530
+ const thumb = new ThumbnailBuilder().setURL(item.accessory.url);
531
+ if (item.accessory.description)
532
+ thumb.setDescription(item.accessory.description);
533
+ section.setThumbnailAccessory(thumb);
534
+ }
535
+ }
536
+
537
+ if (type === "container") {
538
+ result.addSectionComponents(section);
539
+ } else {
540
+ result.push(section);
541
+ }
542
+ }
543
+ });
544
+
545
+ if (type === "container") {
546
+ return [result];
547
+ } else {
548
+ return [...result];
549
+ }
550
+ }
551
+
237
552
  //////////////////////////////////* Get User 👀
238
553
 
239
554
  async function GetUser(message) {
@@ -267,4 +582,11 @@ async function GetUser(message) {
267
582
  };
268
583
  }
269
584
 
270
- module.exports = { Wait, CreateBar, CreateRow, GetUser };
585
+ module.exports = {
586
+ Wait,
587
+ CreateBar,
588
+ CreateRow,
589
+ GetUser,
590
+ CreateModal,
591
+ CreateComponents,
592
+ };