djs-builder 0.7.2 → 0.7.4
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 +915 -154
- package/function/dash.js +214 -5
- package/function/log.js +407 -332
- package/handler/starter.js +3 -1
- package/package.json +3 -3
- package/views/giveaways.ejs +1 -0
- package/views/guild.ejs +4 -0
- package/views/levels.ejs +1 -0
- package/views/logs.ejs +589 -0
package/README.md
CHANGED
|
@@ -73,11 +73,10 @@ const starterOptions = {
|
|
|
73
73
|
|
|
74
74
|
// 🌐 Dashboard Configuration (Full docs at the end of this page)
|
|
75
75
|
dashboard: {
|
|
76
|
-
clientID: "YOUR_DISCORD_CLIENT_ID", // 🔑 Discord Application Client ID
|
|
77
76
|
clientSecret: "YOUR_DISCORD_CLIENT_SECRET", // 🔐 Discord Application Client Secret
|
|
78
|
-
callbackURL: "http://localhost:3000/auth/discord/callback", // 🔗 OAuth2 Callback URL
|
|
79
|
-
sessionSecret: "your-super-secret-key",
|
|
80
|
-
port: 3000,
|
|
77
|
+
callbackURL: "http://localhost:3000/auth/discord/callback", // 🔗 OAuth2 Callback URL (OPTINAL)
|
|
78
|
+
sessionSecret: "your-super-secret-key", // 🔒 Session encryption secret
|
|
79
|
+
port: 3000, // 🌍 Dashboard port (OPTINAL / default: 3000)
|
|
81
80
|
},
|
|
82
81
|
};
|
|
83
82
|
|
|
@@ -507,11 +506,26 @@ message.reply(`🚫 ${member.user.tag} was banned for: ${reason}`);
|
|
|
507
506
|
---
|
|
508
507
|
|
|
509
508
|
<details>
|
|
510
|
-
|
|
509
|
+
<summary>Logging System 🛡️</summary>
|
|
510
|
+
|
|
511
|
+
## 🛡️ Logging System – Track Everything in Your Server
|
|
511
512
|
|
|
512
513
|
The **Logging System** is a powerful feature that keeps track of almost everything happening inside your Discord server 🔍.
|
|
513
514
|
From **messages** 📝 to **channels** 📂, **roles** 🎭, **invites** 🔗, and even **voice state changes** 🎙️ – nothing goes unnoticed!
|
|
514
515
|
|
|
516
|
+
> **Note 1**: Using `database: true` requires a **MongoDB** connection. | **Note 2**: You can import the **Log** model for direct database access 💾.
|
|
517
|
+
|
|
518
|
+
---
|
|
519
|
+
|
|
520
|
+
### 📦 Module Exports
|
|
521
|
+
|
|
522
|
+
```js
|
|
523
|
+
const { log, Log } = require("djs-builder");
|
|
524
|
+
```
|
|
525
|
+
|
|
526
|
+
- `log(client, options)` → Start the logging system with your configuration 🚀.
|
|
527
|
+
- `Log` → The Mongoose model for direct database access and custom modifications 💾.
|
|
528
|
+
|
|
515
529
|
---
|
|
516
530
|
|
|
517
531
|
### ✨ Features
|
|
@@ -522,15 +536,70 @@ From **messages** 📝 to **channels** 📂, **roles** 🎭, **invites** 🔗, a
|
|
|
522
536
|
- 🎙️ **Voice State** – Joins, leaves, and moves between channels.
|
|
523
537
|
- 🔗 **Invites** – Created invites & usage tracking.
|
|
524
538
|
- 😀 **Emojis & Stickers** – Added, removed, or updated.
|
|
539
|
+
- 👤 **Members** – Join, leave, kick, ban, and unban events.
|
|
525
540
|
- 🚨 **Audit Log Integration** – Fetches the executor (who did what).
|
|
526
541
|
- 🎨 **Beautiful Embeds** – Every log is shown in a clean, styled embed with timestamps.
|
|
542
|
+
- 🗄️ **Caching System** – Fast performance with built-in data caching.
|
|
543
|
+
|
|
544
|
+
---
|
|
545
|
+
|
|
546
|
+
### 📊 Database Schema
|
|
547
|
+
|
|
548
|
+
The logging system uses the following data structure:
|
|
549
|
+
|
|
550
|
+
```js
|
|
551
|
+
{
|
|
552
|
+
guildId: String, // 🏠 Server ID (required)
|
|
553
|
+
channelId: String, // 📢 Default log channel ID
|
|
554
|
+
channels: Object, // 📂 Custom channels per event type (optional)
|
|
555
|
+
colors: Object, // 🎨 Custom colors per event type (optional)
|
|
556
|
+
disable: Array, // 🚫 Array of disabled event types (optional)
|
|
557
|
+
}
|
|
558
|
+
```
|
|
527
559
|
|
|
528
560
|
---
|
|
529
561
|
|
|
530
|
-
|
|
562
|
+
<details>
|
|
563
|
+
<summary>📋 Supported Event Types</summary>
|
|
564
|
+
|
|
565
|
+
### 📋 Supported Event Types
|
|
566
|
+
|
|
567
|
+
| Event Type | Description |
|
|
568
|
+
| ------------------- | ------------------------- |
|
|
569
|
+
| `messageDelete` | Message deleted 📝 |
|
|
570
|
+
| `messageUpdate` | Message edited ✏️ |
|
|
571
|
+
| `channelCreate` | Channel created 📁 |
|
|
572
|
+
| `channelDelete` | Channel deleted 🗑️ |
|
|
573
|
+
| `channelUpdate` | Channel updated ⚙️ |
|
|
574
|
+
| `guildMemberAdd` | Member joined 🎉 |
|
|
575
|
+
| `guildMemberRemove` | Member left/kicked 🚪 |
|
|
576
|
+
| `guildBanAdd` | Member banned 🔨 |
|
|
577
|
+
| `guildBanRemove` | Member unbanned 🤗 |
|
|
578
|
+
| `roleCreate` | Role created 🏅 |
|
|
579
|
+
| `roleDelete` | Role deleted ❌ |
|
|
580
|
+
| `roleUpdate` | Role updated 🔄 |
|
|
581
|
+
| `guildMemberUpdate` | Member roles changed 👤 |
|
|
582
|
+
| `voiceStateUpdate` | Voice channel activity 🎤 |
|
|
583
|
+
| `inviteCreate` | Invite created 🔗 |
|
|
584
|
+
| `emojiCreate` | Emoji added 😀 |
|
|
585
|
+
| `emojiDelete` | Emoji removed 🚫 |
|
|
586
|
+
| `emojiUpdate` | Emoji updated 🔄 |
|
|
587
|
+
| `stickerCreate` | Sticker added ✨ |
|
|
588
|
+
| `stickerDelete` | Sticker removed 🗑️ |
|
|
589
|
+
| `stickerUpdate` | Sticker updated 🌀 |
|
|
590
|
+
|
|
591
|
+
</details>
|
|
592
|
+
|
|
593
|
+
---
|
|
531
594
|
|
|
532
|
-
|
|
533
|
-
|
|
595
|
+
<details>
|
|
596
|
+
<summary>⚡ Method Using Database (Recommended) 🗄️</summary>
|
|
597
|
+
|
|
598
|
+
### 🗄️ Using MongoDB Database
|
|
599
|
+
|
|
600
|
+
This method stores log configuration in MongoDB, allowing dynamic management via commands.
|
|
601
|
+
|
|
602
|
+
**⚡ Setup in `clientReady` Event:**
|
|
534
603
|
|
|
535
604
|
```js
|
|
536
605
|
const { log } = require("djs-builder");
|
|
@@ -538,11 +607,12 @@ const { log } = require("djs-builder");
|
|
|
538
607
|
module.exports = {
|
|
539
608
|
name: "clientReady",
|
|
540
609
|
async run(client) {
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
610
|
+
// Start logging with database mode
|
|
611
|
+
await log(client, {
|
|
612
|
+
database: true, // 🗄️ Uses MongoDB to store/fetch config
|
|
613
|
+
});
|
|
614
|
+
|
|
615
|
+
console.log("✅ Logging system started with database mode!");
|
|
546
616
|
},
|
|
547
617
|
};
|
|
548
618
|
```
|
|
@@ -551,9 +621,601 @@ module.exports = {
|
|
|
551
621
|
|
|
552
622
|
### 💡 How It Works
|
|
553
623
|
|
|
554
|
-
- ✅
|
|
555
|
-
-
|
|
556
|
-
-
|
|
624
|
+
- ✅ The system automatically fetches log configuration for each guild from MongoDB.
|
|
625
|
+
- 🛠️ You can manage settings via slash commands (see management command below).
|
|
626
|
+
- 🎨 Supports per-guild customization for channels, colors, and disabled events.
|
|
627
|
+
- 📖 **Important**: If you use database mode, see the [Log Management Command](#-slash-command-for-log-management-) below to edit data.
|
|
628
|
+
|
|
629
|
+
</details>
|
|
630
|
+
|
|
631
|
+
---
|
|
632
|
+
|
|
633
|
+
<details>
|
|
634
|
+
<summary>⚡ Method Using Custom Data Array 📋</summary>
|
|
635
|
+
|
|
636
|
+
### 📋 Using Custom Data Array
|
|
637
|
+
|
|
638
|
+
This method uses a predefined array of configurations – perfect for simple setups or testing.
|
|
639
|
+
|
|
640
|
+
**⚡ Setup in `clientReady` Event:**
|
|
641
|
+
|
|
642
|
+
```js
|
|
643
|
+
const { log } = require("djs-builder");
|
|
644
|
+
|
|
645
|
+
module.exports = {
|
|
646
|
+
name: "clientReady",
|
|
647
|
+
async run(client) {
|
|
648
|
+
// Define your log configurations
|
|
649
|
+
const logData = [
|
|
650
|
+
{
|
|
651
|
+
guildId: "123456789012345678", // 🏠 Server ID
|
|
652
|
+
channelId: "987654321098765432", // 📢 Default log channel
|
|
653
|
+
channels: {
|
|
654
|
+
// 📂 Custom channels (optional)
|
|
655
|
+
messageDelete: "111111111111111111",
|
|
656
|
+
voiceStateUpdate: "222222222222222222",
|
|
657
|
+
},
|
|
658
|
+
colors: {
|
|
659
|
+
// 🎨 Custom colors (optional)
|
|
660
|
+
messageDelete: "DarkRed",
|
|
661
|
+
channelCreate: "DarkGreen",
|
|
662
|
+
},
|
|
663
|
+
disable: ["inviteCreate"], // 🚫 Disabled events (optional)
|
|
664
|
+
},
|
|
665
|
+
// Add more guild configurations...
|
|
666
|
+
{
|
|
667
|
+
guildId: "999888777666555444",
|
|
668
|
+
channelId: "444555666777888999",
|
|
669
|
+
},
|
|
670
|
+
];
|
|
671
|
+
|
|
672
|
+
// Start logging with custom data
|
|
673
|
+
await log(client, {
|
|
674
|
+
database: false, // 📋 Uses custom array
|
|
675
|
+
Data: logData, // 📊 Your configurations
|
|
676
|
+
});
|
|
677
|
+
|
|
678
|
+
console.log("✅ Logging system started with custom data!");
|
|
679
|
+
},
|
|
680
|
+
};
|
|
681
|
+
```
|
|
682
|
+
|
|
683
|
+
---
|
|
684
|
+
|
|
685
|
+
### 🎨 Supported Colors
|
|
686
|
+
|
|
687
|
+
`Default`, `White`, `Aqua`, `Green`, `Blue`, `Yellow`, `Purple`, `LuminousVividPink`, `Fuchsia`, `Gold`, `Orange`, `Red`, `Grey`, `Navy`, `DarkAqua`, `DarkGreen`, `DarkBlue`, `DarkPurple`, `DarkVividPink`, `DarkGold`, `DarkOrange`, `DarkRed`, `DarkGrey`, `DarkerGrey`, `LightGrey`, `DarkNavy`, `Blurple`, `Greyple`, `DarkButNotBlack`, `NotQuiteBlack`, `Random`, or any **Hex Color** like `#FF5733`.
|
|
688
|
+
|
|
689
|
+
---
|
|
690
|
+
|
|
691
|
+
### 🌐 Multi-Guild Support
|
|
692
|
+
|
|
693
|
+
> 💡 **Tip:** You can add configurations for multiple guilds in the same array. Each guild can have its own unique settings for channels, colors, and disabled events!
|
|
694
|
+
|
|
695
|
+
</details>
|
|
696
|
+
|
|
697
|
+
---
|
|
698
|
+
|
|
699
|
+
<details>
|
|
700
|
+
<summary>🔧 Direct Database Access with Log Model 💾</summary>
|
|
701
|
+
|
|
702
|
+
### 💾 Using the Log Model Directly
|
|
703
|
+
|
|
704
|
+
You can import the `Log` Mongoose model to create, update, or delete log configurations programmatically.
|
|
705
|
+
|
|
706
|
+
**📥 Import the Model:**
|
|
707
|
+
|
|
708
|
+
```js
|
|
709
|
+
const { Log } = require("djs-builder");
|
|
710
|
+
```
|
|
711
|
+
|
|
712
|
+
**➕ Create New Configuration:**
|
|
713
|
+
|
|
714
|
+
```js
|
|
715
|
+
const { Log } = require("djs-builder");
|
|
716
|
+
|
|
717
|
+
// Create a new log configuration for a guild
|
|
718
|
+
const newConfig = await Log.create({
|
|
719
|
+
guildId: "123456789012345678",
|
|
720
|
+
channelId: "987654321098765432",
|
|
721
|
+
channels: {
|
|
722
|
+
messageDelete: "111111111111111111",
|
|
723
|
+
},
|
|
724
|
+
colors: {
|
|
725
|
+
messageDelete: "Red",
|
|
726
|
+
},
|
|
727
|
+
disable: [],
|
|
728
|
+
});
|
|
729
|
+
|
|
730
|
+
console.log("✅ Log configuration created!", newConfig);
|
|
731
|
+
```
|
|
732
|
+
|
|
733
|
+
**✏️ Update Existing Configuration:**
|
|
734
|
+
|
|
735
|
+
```js
|
|
736
|
+
const { Log } = require("djs-builder");
|
|
737
|
+
|
|
738
|
+
// Update log channel
|
|
739
|
+
await Log.findOneAndUpdate(
|
|
740
|
+
{ guildId: "123456789012345678" },
|
|
741
|
+
{ channelId: "NEW_CHANNEL_ID" },
|
|
742
|
+
{ upsert: true } // Create if doesn't exist
|
|
743
|
+
);
|
|
744
|
+
|
|
745
|
+
// Add event to disable list
|
|
746
|
+
await Log.findOneAndUpdate(
|
|
747
|
+
{ guildId: "123456789012345678" },
|
|
748
|
+
{ $push: { disable: "voiceStateUpdate" } }
|
|
749
|
+
);
|
|
750
|
+
|
|
751
|
+
// Remove event from disable list
|
|
752
|
+
await Log.findOneAndUpdate(
|
|
753
|
+
{ guildId: "123456789012345678" },
|
|
754
|
+
{ $pull: { disable: "voiceStateUpdate" } }
|
|
755
|
+
);
|
|
756
|
+
|
|
757
|
+
// Update specific channel for an event
|
|
758
|
+
await Log.findOneAndUpdate(
|
|
759
|
+
{ guildId: "123456789012345678" },
|
|
760
|
+
{ $set: { "channels.messageDelete": "NEW_CHANNEL_ID" } }
|
|
761
|
+
);
|
|
762
|
+
|
|
763
|
+
// Update specific color for an event
|
|
764
|
+
await Log.findOneAndUpdate(
|
|
765
|
+
{ guildId: "123456789012345678" },
|
|
766
|
+
{ $set: { "colors.messageDelete": "DarkRed" } }
|
|
767
|
+
);
|
|
768
|
+
```
|
|
769
|
+
|
|
770
|
+
**🗑️ Delete Configuration:**
|
|
771
|
+
|
|
772
|
+
```js
|
|
773
|
+
const { Log } = require("djs-builder");
|
|
774
|
+
|
|
775
|
+
await Log.findOneAndDelete({ guildId: "123456789012345678" });
|
|
776
|
+
console.log("🗑️ Log configuration deleted!");
|
|
777
|
+
```
|
|
778
|
+
|
|
779
|
+
**📊 Fetch Configuration:**
|
|
780
|
+
|
|
781
|
+
```js
|
|
782
|
+
const { Log } = require("djs-builder");
|
|
783
|
+
|
|
784
|
+
const config = await Log.findOne({ guildId: "123456789012345678" });
|
|
785
|
+
if (config) {
|
|
786
|
+
console.log("📢 Log Channel:", config.channelId);
|
|
787
|
+
console.log("📂 Custom Channels:", config.channels);
|
|
788
|
+
console.log("🎨 Custom Colors:", config.colors);
|
|
789
|
+
console.log("🚫 Disabled Events:", config.disable);
|
|
790
|
+
}
|
|
791
|
+
```
|
|
792
|
+
|
|
793
|
+
</details>
|
|
794
|
+
|
|
795
|
+
---
|
|
796
|
+
|
|
797
|
+
<details>
|
|
798
|
+
<summary>🌐 Dashboard Integration – Manage Logs from Web Panel 🖥️</summary>
|
|
799
|
+
|
|
800
|
+
### 🖥️ Web Dashboard for Log Management
|
|
801
|
+
|
|
802
|
+
When you use **database mode** (`database: true`), you can manage the logging system directly from the **djs-builder Dashboard**! 🎛️
|
|
803
|
+
|
|
804
|
+
---
|
|
805
|
+
|
|
806
|
+
#### ✨ Dashboard Features for Logs
|
|
807
|
+
|
|
808
|
+
| Feature | Description |
|
|
809
|
+
| ---------------------- | -------------------------------------------- |
|
|
810
|
+
| 📢 **Default Channel** | Set the main channel for all logs |
|
|
811
|
+
| 📂 **Custom Channels** | Assign specific channels for each event type |
|
|
812
|
+
| 🎨 **Custom Colors** | Choose embed colors for each event type |
|
|
813
|
+
| 🔄 **Toggle Events** | Enable/Disable specific event types |
|
|
814
|
+
| 📊 **Statistics** | View enabled/disabled events count |
|
|
815
|
+
| 🗑️ **Reset** | Clear all log settings with one click |
|
|
816
|
+
|
|
817
|
+
---
|
|
818
|
+
|
|
819
|
+
#### 🚀 How to Access
|
|
820
|
+
|
|
821
|
+
1. Navigate to your dashboard (e.g., `http://localhost:3000`)
|
|
822
|
+
2. Log in with Discord OAuth2
|
|
823
|
+
3. Select a server
|
|
824
|
+
4. Click on **"سجلات المراقبة"** (Logs) in the sidebar
|
|
825
|
+
|
|
826
|
+
---
|
|
827
|
+
|
|
828
|
+
#### ⚠️ Important Notes
|
|
829
|
+
|
|
830
|
+
**When `database: true`:**
|
|
831
|
+
|
|
832
|
+
- ✅ Full editing capabilities from dashboard
|
|
833
|
+
- ✅ Changes are saved automatically to MongoDB
|
|
834
|
+
- ✅ Real-time updates
|
|
835
|
+
|
|
836
|
+
**When `database: false` (Custom Data Array):**
|
|
837
|
+
|
|
838
|
+
- ⚠️ Dashboard shows **read-only** mode
|
|
839
|
+
- ⚠️ A warning banner appears at the top
|
|
840
|
+
- ⚠️ You must edit settings in your code
|
|
841
|
+
|
|
842
|
+
</details>
|
|
843
|
+
|
|
844
|
+
---
|
|
845
|
+
|
|
846
|
+
<details>
|
|
847
|
+
<summary>🎮 Slash Command for Log Management 🛠️</summary>
|
|
848
|
+
|
|
849
|
+
### 🛠️ Complete Log Management Slash Command
|
|
850
|
+
|
|
851
|
+
This command allows server administrators to manage the logging system via Discord.
|
|
852
|
+
|
|
853
|
+
> ⚠️ **Important**: This command requires `database: true` mode to work properly.
|
|
854
|
+
|
|
855
|
+
```js
|
|
856
|
+
const { Log, getLogConfigData } = require("djs-builder");
|
|
857
|
+
const {
|
|
858
|
+
SlashCommandBuilder,
|
|
859
|
+
PermissionFlagsBits,
|
|
860
|
+
EmbedBuilder,
|
|
861
|
+
ChannelType,
|
|
862
|
+
} = require("discord.js");
|
|
863
|
+
|
|
864
|
+
// All supported event types (21 events)
|
|
865
|
+
const EVENT_TYPES = [
|
|
866
|
+
{ name: "Message Delete", value: "messageDelete" },
|
|
867
|
+
{ name: "Message Update", value: "messageUpdate" },
|
|
868
|
+
{ name: "Channel Create", value: "channelCreate" },
|
|
869
|
+
{ name: "Channel Delete", value: "channelDelete" },
|
|
870
|
+
{ name: "Channel Update", value: "channelUpdate" },
|
|
871
|
+
{ name: "Member Join", value: "guildMemberAdd" },
|
|
872
|
+
{ name: "Member Leave", value: "guildMemberRemove" },
|
|
873
|
+
{ name: "Member Ban", value: "guildBanAdd" },
|
|
874
|
+
{ name: "Member Unban", value: "guildBanRemove" },
|
|
875
|
+
{ name: "Role Create", value: "roleCreate" },
|
|
876
|
+
{ name: "Role Delete", value: "roleDelete" },
|
|
877
|
+
{ name: "Role Update", value: "roleUpdate" },
|
|
878
|
+
{ name: "Member Role Update", value: "guildMemberUpdate" },
|
|
879
|
+
{ name: "Voice State", value: "voiceStateUpdate" },
|
|
880
|
+
{ name: "Invite Create", value: "inviteCreate" },
|
|
881
|
+
{ name: "Emoji Create", value: "emojiCreate" },
|
|
882
|
+
{ name: "Emoji Delete", value: "emojiDelete" },
|
|
883
|
+
{ name: "Emoji Update", value: "emojiUpdate" },
|
|
884
|
+
{ name: "Sticker Create", value: "stickerCreate" },
|
|
885
|
+
{ name: "Sticker Delete", value: "stickerDelete" },
|
|
886
|
+
{ name: "Sticker Update", value: "stickerUpdate" },
|
|
887
|
+
];
|
|
888
|
+
|
|
889
|
+
// Helper function to clear cache after updates
|
|
890
|
+
function clearLogCache(guildId) {
|
|
891
|
+
const logData = getLogConfigData();
|
|
892
|
+
if (logData.clearCache) logData.clearCache(guildId);
|
|
893
|
+
}
|
|
894
|
+
|
|
895
|
+
module.exports = {
|
|
896
|
+
data: new SlashCommandBuilder()
|
|
897
|
+
.setName("logs")
|
|
898
|
+
.setDescription("🛡️ Manage the server logging system")
|
|
899
|
+
.setDefaultMemberPermissions(PermissionFlagsBits.Administrator)
|
|
900
|
+
.addSubcommand((sub) =>
|
|
901
|
+
sub
|
|
902
|
+
.setName("setup")
|
|
903
|
+
.setDescription("📢 Set up the default log channel")
|
|
904
|
+
.addChannelOption((opt) =>
|
|
905
|
+
opt
|
|
906
|
+
.setName("channel")
|
|
907
|
+
.setDescription("The channel to send logs to")
|
|
908
|
+
.addChannelTypes(ChannelType.GuildText)
|
|
909
|
+
.setRequired(true)
|
|
910
|
+
)
|
|
911
|
+
)
|
|
912
|
+
.addSubcommand((sub) =>
|
|
913
|
+
sub
|
|
914
|
+
.setName("channel")
|
|
915
|
+
.setDescription("📂 Set a specific channel for an event type")
|
|
916
|
+
.addStringOption((opt) =>
|
|
917
|
+
opt
|
|
918
|
+
.setName("event")
|
|
919
|
+
.setDescription("The event type")
|
|
920
|
+
.setRequired(true)
|
|
921
|
+
.addChoices(...EVENT_TYPES)
|
|
922
|
+
)
|
|
923
|
+
.addChannelOption((opt) =>
|
|
924
|
+
opt
|
|
925
|
+
.setName("channel")
|
|
926
|
+
.setDescription("The channel for this event")
|
|
927
|
+
.addChannelTypes(ChannelType.GuildText)
|
|
928
|
+
.setRequired(true)
|
|
929
|
+
)
|
|
930
|
+
)
|
|
931
|
+
.addSubcommand((sub) =>
|
|
932
|
+
sub
|
|
933
|
+
.setName("color")
|
|
934
|
+
.setDescription("🎨 Set a custom color for an event type")
|
|
935
|
+
.addStringOption((opt) =>
|
|
936
|
+
opt
|
|
937
|
+
.setName("event")
|
|
938
|
+
.setDescription("The event type")
|
|
939
|
+
.setRequired(true)
|
|
940
|
+
.addChoices(...EVENT_TYPES)
|
|
941
|
+
)
|
|
942
|
+
.addStringOption((opt) =>
|
|
943
|
+
opt
|
|
944
|
+
.setName("color")
|
|
945
|
+
.setDescription("Color name or hex code (e.g., Red, #FF5733)")
|
|
946
|
+
.setRequired(true)
|
|
947
|
+
)
|
|
948
|
+
)
|
|
949
|
+
.addSubcommand((sub) =>
|
|
950
|
+
sub
|
|
951
|
+
.setName("toggle")
|
|
952
|
+
.setDescription("🔄 Enable or disable an event type")
|
|
953
|
+
.addStringOption((opt) =>
|
|
954
|
+
opt
|
|
955
|
+
.setName("event")
|
|
956
|
+
.setDescription("The event type")
|
|
957
|
+
.setRequired(true)
|
|
958
|
+
.addChoices(...EVENT_TYPES)
|
|
959
|
+
)
|
|
960
|
+
.addStringOption((opt) =>
|
|
961
|
+
opt
|
|
962
|
+
.setName("action")
|
|
963
|
+
.setDescription("Enable or disable")
|
|
964
|
+
.setRequired(true)
|
|
965
|
+
.addChoices(
|
|
966
|
+
{ name: "Enable", value: "enable" },
|
|
967
|
+
{ name: "Disable", value: "disable" }
|
|
968
|
+
)
|
|
969
|
+
)
|
|
970
|
+
)
|
|
971
|
+
.addSubcommand((sub) =>
|
|
972
|
+
sub.setName("view").setDescription("📊 View current log configuration")
|
|
973
|
+
)
|
|
974
|
+
.addSubcommand((sub) =>
|
|
975
|
+
sub
|
|
976
|
+
.setName("reset")
|
|
977
|
+
.setDescription("🗑️ Reset all log settings for this server")
|
|
978
|
+
),
|
|
979
|
+
|
|
980
|
+
async run(client, interaction) {
|
|
981
|
+
await interaction.deferReply({ ephemeral: true });
|
|
982
|
+
|
|
983
|
+
const subcommand = interaction.options.getSubcommand();
|
|
984
|
+
const guildId = interaction.guild.id;
|
|
985
|
+
|
|
986
|
+
// ═══════════════════════════════════════════════════════
|
|
987
|
+
// 📢 SETUP - Set default log channel
|
|
988
|
+
// ═══════════════════════════════════════════════════════
|
|
989
|
+
if (subcommand === "setup") {
|
|
990
|
+
const channel = interaction.options.getChannel("channel");
|
|
991
|
+
|
|
992
|
+
await Log.findOneAndUpdate(
|
|
993
|
+
{ guildId },
|
|
994
|
+
{ guildId, channelId: channel.id },
|
|
995
|
+
{ upsert: true, new: true }
|
|
996
|
+
);
|
|
997
|
+
|
|
998
|
+
clearLogCache(guildId); // Clear cache to apply changes immediately
|
|
999
|
+
|
|
1000
|
+
const embed = new EmbedBuilder()
|
|
1001
|
+
.setTitle("✅ Logging System Setup")
|
|
1002
|
+
.setDescription(`Logs will now be sent to ${channel}`)
|
|
1003
|
+
.setColor("Green")
|
|
1004
|
+
.setTimestamp();
|
|
1005
|
+
|
|
1006
|
+
return interaction.editReply({ embeds: [embed] });
|
|
1007
|
+
}
|
|
1008
|
+
|
|
1009
|
+
// ═══════════════════════════════════════════════════════
|
|
1010
|
+
// 📂 CHANNEL - Set specific channel for event
|
|
1011
|
+
// ═══════════════════════════════════════════════════════
|
|
1012
|
+
if (subcommand === "channel") {
|
|
1013
|
+
const event = interaction.options.getString("event");
|
|
1014
|
+
const channel = interaction.options.getChannel("channel");
|
|
1015
|
+
|
|
1016
|
+
await Log.findOneAndUpdate(
|
|
1017
|
+
{ guildId },
|
|
1018
|
+
{ $set: { [`channels.${event}`]: channel.id } },
|
|
1019
|
+
{ upsert: true }
|
|
1020
|
+
);
|
|
1021
|
+
|
|
1022
|
+
clearLogCache(guildId);
|
|
1023
|
+
|
|
1024
|
+
const eventName =
|
|
1025
|
+
EVENT_TYPES.find((e) => e.value === event)?.name || event;
|
|
1026
|
+
const embed = new EmbedBuilder()
|
|
1027
|
+
.setTitle("📂 Event Channel Updated")
|
|
1028
|
+
.setDescription(`**${eventName}** logs will now be sent to ${channel}`)
|
|
1029
|
+
.setColor("Blue")
|
|
1030
|
+
.setTimestamp();
|
|
1031
|
+
|
|
1032
|
+
return interaction.editReply({ embeds: [embed] });
|
|
1033
|
+
}
|
|
1034
|
+
|
|
1035
|
+
// ═══════════════════════════════════════════════════════
|
|
1036
|
+
// 🎨 COLOR - Set custom color for event
|
|
1037
|
+
// ═══════════════════════════════════════════════════════
|
|
1038
|
+
if (subcommand === "color") {
|
|
1039
|
+
const event = interaction.options.getString("event");
|
|
1040
|
+
const color = interaction.options.getString("color");
|
|
1041
|
+
|
|
1042
|
+
await Log.findOneAndUpdate(
|
|
1043
|
+
{ guildId },
|
|
1044
|
+
{ $set: { [`colors.${event}`]: color } },
|
|
1045
|
+
{ upsert: true }
|
|
1046
|
+
);
|
|
1047
|
+
|
|
1048
|
+
clearLogCache(guildId);
|
|
1049
|
+
|
|
1050
|
+
const eventName =
|
|
1051
|
+
EVENT_TYPES.find((e) => e.value === event)?.name || event;
|
|
1052
|
+
|
|
1053
|
+
// Try to use the color, fallback to Blue if invalid
|
|
1054
|
+
let embedColor;
|
|
1055
|
+
try {
|
|
1056
|
+
embedColor = color;
|
|
1057
|
+
} catch {
|
|
1058
|
+
embedColor = "Blue";
|
|
1059
|
+
}
|
|
1060
|
+
|
|
1061
|
+
const embed = new EmbedBuilder()
|
|
1062
|
+
.setTitle("🎨 Event Color Updated")
|
|
1063
|
+
.setDescription(
|
|
1064
|
+
`**${eventName}** embeds will now use color: \`${color}\``
|
|
1065
|
+
)
|
|
1066
|
+
.setColor(embedColor)
|
|
1067
|
+
.setTimestamp();
|
|
1068
|
+
|
|
1069
|
+
return interaction.editReply({ embeds: [embed] });
|
|
1070
|
+
}
|
|
1071
|
+
|
|
1072
|
+
// ═══════════════════════════════════════════════════════
|
|
1073
|
+
// 🔄 TOGGLE - Enable/Disable event
|
|
1074
|
+
// ═══════════════════════════════════════════════════════
|
|
1075
|
+
if (subcommand === "toggle") {
|
|
1076
|
+
const event = interaction.options.getString("event");
|
|
1077
|
+
const action = interaction.options.getString("action");
|
|
1078
|
+
|
|
1079
|
+
if (action === "disable") {
|
|
1080
|
+
await Log.findOneAndUpdate(
|
|
1081
|
+
{ guildId },
|
|
1082
|
+
{ $addToSet: { disable: event } },
|
|
1083
|
+
{ upsert: true }
|
|
1084
|
+
);
|
|
1085
|
+
} else {
|
|
1086
|
+
await Log.findOneAndUpdate(
|
|
1087
|
+
{ guildId },
|
|
1088
|
+
{ $pull: { disable: event } },
|
|
1089
|
+
{ upsert: true }
|
|
1090
|
+
);
|
|
1091
|
+
}
|
|
1092
|
+
|
|
1093
|
+
clearLogCache(guildId);
|
|
1094
|
+
|
|
1095
|
+
const eventName =
|
|
1096
|
+
EVENT_TYPES.find((e) => e.value === event)?.name || event;
|
|
1097
|
+
const embed = new EmbedBuilder()
|
|
1098
|
+
.setTitle(
|
|
1099
|
+
action === "disable" ? "🚫 Event Disabled" : "✅ Event Enabled"
|
|
1100
|
+
)
|
|
1101
|
+
.setDescription(`**${eventName}** logging has been ${action}d`)
|
|
1102
|
+
.setColor(action === "disable" ? "Red" : "Green")
|
|
1103
|
+
.setTimestamp();
|
|
1104
|
+
|
|
1105
|
+
return interaction.editReply({ embeds: [embed] });
|
|
1106
|
+
}
|
|
1107
|
+
|
|
1108
|
+
// ═══════════════════════════════════════════════════════
|
|
1109
|
+
// 📊 VIEW - Show current configuration
|
|
1110
|
+
// ═══════════════════════════════════════════════════════
|
|
1111
|
+
if (subcommand === "view") {
|
|
1112
|
+
const config = await Log.findOne({ guildId });
|
|
1113
|
+
|
|
1114
|
+
if (!config) {
|
|
1115
|
+
return interaction.editReply({
|
|
1116
|
+
content:
|
|
1117
|
+
"❌ No logging configuration found for this server. Use `/logs setup` first!",
|
|
1118
|
+
});
|
|
1119
|
+
}
|
|
1120
|
+
|
|
1121
|
+
const channelsList = config.channels
|
|
1122
|
+
? Object.entries(config.channels)
|
|
1123
|
+
.map(([k, v]) => {
|
|
1124
|
+
const eventName = EVENT_TYPES.find((e) => e.value === k)?.name || k;
|
|
1125
|
+
return `• **${eventName}**: <#${v}>`;
|
|
1126
|
+
})
|
|
1127
|
+
.join("\n") || "None"
|
|
1128
|
+
: "None";
|
|
1129
|
+
|
|
1130
|
+
const colorsList = config.colors
|
|
1131
|
+
? Object.entries(config.colors)
|
|
1132
|
+
.map(([k, v]) => {
|
|
1133
|
+
const eventName = EVENT_TYPES.find((e) => e.value === k)?.name || k;
|
|
1134
|
+
return `• **${eventName}**: \`${v}\``;
|
|
1135
|
+
})
|
|
1136
|
+
.join("\n") || "None"
|
|
1137
|
+
: "None";
|
|
1138
|
+
|
|
1139
|
+
const disabledList =
|
|
1140
|
+
config.disable?.length > 0
|
|
1141
|
+
? config.disable.map((e) => {
|
|
1142
|
+
const eventName = EVENT_TYPES.find((ev) => ev.value === e)?.name || e;
|
|
1143
|
+
return `• ${eventName}`;
|
|
1144
|
+
}).join("\n")
|
|
1145
|
+
: "None";
|
|
1146
|
+
|
|
1147
|
+
const enabledCount = EVENT_TYPES.length - (config.disable?.length || 0);
|
|
1148
|
+
|
|
1149
|
+
const embed = new EmbedBuilder()
|
|
1150
|
+
.setTitle("📊 Log Configuration")
|
|
1151
|
+
.setDescription(`**${enabledCount}/${EVENT_TYPES.length}** events are enabled`)
|
|
1152
|
+
.setColor("Blue")
|
|
1153
|
+
.addFields(
|
|
1154
|
+
{
|
|
1155
|
+
name: "📢 Default Channel",
|
|
1156
|
+
value: config.channelId ? `<#${config.channelId}>` : "Not set",
|
|
1157
|
+
inline: true,
|
|
1158
|
+
},
|
|
1159
|
+
{
|
|
1160
|
+
name: "📂 Custom Channels",
|
|
1161
|
+
value: channelsList.slice(0, 1024) || "None",
|
|
1162
|
+
inline: false,
|
|
1163
|
+
},
|
|
1164
|
+
{
|
|
1165
|
+
name: "🎨 Custom Colors",
|
|
1166
|
+
value: colorsList.slice(0, 1024) || "None",
|
|
1167
|
+
inline: false,
|
|
1168
|
+
},
|
|
1169
|
+
{
|
|
1170
|
+
name: "🚫 Disabled Events",
|
|
1171
|
+
value: disabledList.slice(0, 1024) || "None",
|
|
1172
|
+
inline: false,
|
|
1173
|
+
}
|
|
1174
|
+
)
|
|
1175
|
+
.setFooter({ text: `Guild ID: ${guildId}` })
|
|
1176
|
+
.setTimestamp();
|
|
1177
|
+
|
|
1178
|
+
return interaction.editReply({ embeds: [embed] });
|
|
1179
|
+
}
|
|
1180
|
+
|
|
1181
|
+
// ═══════════════════════════════════════════════════════
|
|
1182
|
+
// 🗑️ RESET - Delete all configuration
|
|
1183
|
+
// ═══════════════════════════════════════════════════════
|
|
1184
|
+
if (subcommand === "reset") {
|
|
1185
|
+
await Log.findOneAndDelete({ guildId });
|
|
1186
|
+
|
|
1187
|
+
clearLogCache(guildId);
|
|
1188
|
+
|
|
1189
|
+
const embed = new EmbedBuilder()
|
|
1190
|
+
.setTitle("🗑️ Configuration Reset")
|
|
1191
|
+
.setDescription(
|
|
1192
|
+
"All logging settings have been deleted for this server."
|
|
1193
|
+
)
|
|
1194
|
+
.setColor("Red")
|
|
1195
|
+
.setTimestamp();
|
|
1196
|
+
|
|
1197
|
+
return interaction.editReply({ embeds: [embed] });
|
|
1198
|
+
}
|
|
1199
|
+
},
|
|
1200
|
+
};
|
|
1201
|
+
```
|
|
1202
|
+
|
|
1203
|
+
</details>
|
|
1204
|
+
|
|
1205
|
+
---
|
|
1206
|
+
|
|
1207
|
+
### 💡 Tips & Notes
|
|
1208
|
+
|
|
1209
|
+
- 🔄 **Caching**: The system caches guild configurations for better performance.
|
|
1210
|
+
- 🔐 **Permissions**: Make sure your bot has `View Audit Log` permission for full functionality.
|
|
1211
|
+
- 📢 **Invite Tracking**: Uses `discord-inviter` package for accurate invite tracking.
|
|
1212
|
+
- 🎨 **Default Colors**: Each event type has sensible default colors if not customized.
|
|
1213
|
+
- 🚫 **Disabled Events**: Events in the `disable` array will be completely ignored.
|
|
1214
|
+
- 📂 **Channel Fallback**: If no specific channel is set for an event, it uses `channelId`.
|
|
1215
|
+
- 💾 **Database Mode**: Recommended for multi-server bots with dynamic configuration needs.
|
|
1216
|
+
- 🌐 **Dashboard Integration**: When using database mode, you can manage logs via the web dashboard!
|
|
1217
|
+
|
|
1218
|
+
---
|
|
557
1219
|
|
|
558
1220
|
</details>
|
|
559
1221
|
|
|
@@ -809,55 +1471,54 @@ const { Gstart } = require("djs-builder");
|
|
|
809
1471
|
const { EmbedBuilder } = require("discord.js");
|
|
810
1472
|
|
|
811
1473
|
module.exports = {
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
const twoDays = Date.now() +
|
|
817
|
-
const channelId =
|
|
818
|
-
|
|
819
|
-
await Gstart({
|
|
820
|
-
context: message,
|
|
821
|
-
endTime: twoDays,
|
|
822
|
-
winers: 5, // 5 lucky winners! 🏆
|
|
823
|
-
channelId: channelId,
|
|
1474
|
+
name: "gstart",
|
|
1475
|
+
description: "Starts a new highly-customized giveaway.",
|
|
1476
|
+
run: async (client, message, args) => {
|
|
1477
|
+
// ⏰ Giveaway ends in 48 hours
|
|
1478
|
+
const twoDays = Date.now() + 48 * 60 * 60 * 1000;
|
|
1479
|
+
const channelId = "YOUR_GIVEAWAY_CHANNEL_ID"; // 📢 Target Channel
|
|
824
1480
|
|
|
825
|
-
|
|
826
|
-
|
|
1481
|
+
await Gstart({
|
|
1482
|
+
context: message,
|
|
1483
|
+
endTime: twoDays,
|
|
1484
|
+
winers: 5, // 5 lucky winners! 🏆
|
|
1485
|
+
channelId: channelId,
|
|
827
1486
|
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
1487
|
+
// 🎨 Customization for the STARTING EMBED
|
|
1488
|
+
embed: {
|
|
1489
|
+
custom: new EmbedBuilder().setTitle("Raw Embed"), // 💡 You can use 'custom' to pass a raw Discord.js EmbedBuilder JSON
|
|
1490
|
+
title: "🎉 **HUGE SERVER BOOST GIVEAWAY!**",
|
|
1491
|
+
description:
|
|
1492
|
+
"Click the button below to enter for a chance to win a free server boost!",
|
|
1493
|
+
color: "Blue", // Any valid Discord color
|
|
1494
|
+
image: "https://yourimage.com/banner.png", // image URL
|
|
1495
|
+
thumbnail: message.guild.iconURL(),
|
|
1496
|
+
},
|
|
835
1497
|
|
|
836
1498
|
// 🛑 Customization for the ENDED EMBED
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
},
|
|
1499
|
+
endEmbed: {
|
|
1500
|
+
custom: new EmbedBuilder().setTitle("Raw Embed"), // 💡 You can use 'custom' to pass a raw Discord.js EmbedBuilder JSON
|
|
1501
|
+
title: "🛑 Giveaway Has Concluded!",
|
|
1502
|
+
description: "Congratulations to the winners! Check the message below.",
|
|
1503
|
+
color: "Green", // Eimage and Ethumbnail can also be set here
|
|
1504
|
+
},
|
|
844
1505
|
|
|
845
1506
|
// 🖱️ Button Entry Method
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
1507
|
+
reaction: {
|
|
1508
|
+
type: "button", // Use 'reaction' for an emoji reaction
|
|
1509
|
+
emoji: "✅", // The emoji displayed on the button
|
|
1510
|
+
label: "Enter Giveaway!", // The text label
|
|
1511
|
+
style: 3, // Button style: Primary(1), Secondary(2), Success(3), Danger(4)
|
|
1512
|
+
id: "djs-builder-giveaway", // Custom ID for the button
|
|
1513
|
+
},
|
|
853
1514
|
|
|
854
1515
|
// 🔒 Requirements (Optional)
|
|
855
1516
|
requirements: {
|
|
856
1517
|
requiredRoles: ["123456789012345678"], // 🛡️ User MUST have this role to join (Button Only)
|
|
857
1518
|
},
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
1519
|
+
});
|
|
1520
|
+
message.reply("🎉 Giveaway started successfully!");
|
|
1521
|
+
},
|
|
861
1522
|
};
|
|
862
1523
|
```
|
|
863
1524
|
|
|
@@ -1103,14 +1764,14 @@ module.exports = {
|
|
|
1103
1764
|
const result = await GaddUser(
|
|
1104
1765
|
interaction.message.id,
|
|
1105
1766
|
interaction.user.id,
|
|
1106
|
-
interaction.guild
|
|
1767
|
+
interaction.guild
|
|
1107
1768
|
);
|
|
1108
1769
|
|
|
1109
1770
|
if (result?.error) {
|
|
1110
1771
|
// Handles both "User Already Joined" and "Missing Roles" errors
|
|
1111
1772
|
if (result.error === "❌ User Already Joined") {
|
|
1112
|
-
|
|
1113
|
-
|
|
1773
|
+
// ... (Leave button logic)
|
|
1774
|
+
const row = await CreateRow([
|
|
1114
1775
|
[
|
|
1115
1776
|
{
|
|
1116
1777
|
label: "Leave Giveaway",
|
|
@@ -1120,16 +1781,17 @@ module.exports = {
|
|
|
1120
1781
|
],
|
|
1121
1782
|
]);
|
|
1122
1783
|
return interaction.reply({
|
|
1123
|
-
content:
|
|
1784
|
+
content:
|
|
1785
|
+
"⚠️ You have **already joined** this giveaway! You can **leave** by clicking the button below.",
|
|
1124
1786
|
components: row,
|
|
1125
|
-
flags: 64,
|
|
1787
|
+
flags: 64,
|
|
1126
1788
|
});
|
|
1127
1789
|
}
|
|
1128
|
-
|
|
1790
|
+
|
|
1129
1791
|
// Show error (e.g. Missing Role)
|
|
1130
1792
|
return interaction.reply({
|
|
1131
|
-
|
|
1132
|
-
|
|
1793
|
+
content: result.error,
|
|
1794
|
+
flags: 64,
|
|
1133
1795
|
});
|
|
1134
1796
|
}
|
|
1135
1797
|
|
|
@@ -1139,7 +1801,6 @@ module.exports = {
|
|
|
1139
1801
|
});
|
|
1140
1802
|
}
|
|
1141
1803
|
|
|
1142
|
-
|
|
1143
1804
|
// 2. Handle Leave Button Click (Dynamically Generated ID)
|
|
1144
1805
|
if (
|
|
1145
1806
|
interaction.customId &&
|
|
@@ -1534,7 +2195,7 @@ module.exports = {
|
|
|
1534
2195
|
channelId: channel.id,
|
|
1535
2196
|
winers: winnerCount,
|
|
1536
2197
|
endTime: endTimeMs,
|
|
1537
|
-
prize
|
|
2198
|
+
prize: prize,
|
|
1538
2199
|
embed: {
|
|
1539
2200
|
title: `🎉 ${prize} Giveaway!`,
|
|
1540
2201
|
image: image,
|
|
@@ -1810,7 +2471,6 @@ module.exports = {
|
|
|
1810
2471
|
|
|
1811
2472
|
---
|
|
1812
2473
|
|
|
1813
|
-
|
|
1814
2474
|
<details>
|
|
1815
2475
|
<summary>Blacklist System 🚫</summary>
|
|
1816
2476
|
|
|
@@ -1882,10 +2542,12 @@ console.log("Role unblacklisted! 🔓");
|
|
|
1882
2542
|
Returns an array of blacklisted items for a guild. You can optionally filter by type (`user`, `role`, `channel`).
|
|
1883
2543
|
|
|
1884
2544
|
**Parameters:**
|
|
2545
|
+
|
|
1885
2546
|
- `guildId` (String): The ID of the guild.
|
|
1886
2547
|
- `type` (String, optional): The type to filter by (`user`, `role`, `channel`).
|
|
1887
2548
|
|
|
1888
2549
|
**Example:**
|
|
2550
|
+
|
|
1889
2551
|
```js
|
|
1890
2552
|
// Get all blacklisted items
|
|
1891
2553
|
const allBlacklisted = await getBlacklist("GUILD_ID");
|
|
@@ -1910,35 +2572,80 @@ Output:
|
|
|
1910
2572
|
You can create a slash command to manage the blacklist easily.
|
|
1911
2573
|
|
|
1912
2574
|
```js
|
|
1913
|
-
const {
|
|
1914
|
-
|
|
2575
|
+
const {
|
|
2576
|
+
addToBlacklist,
|
|
2577
|
+
removeFromBlacklist,
|
|
2578
|
+
isBlacklisted,
|
|
2579
|
+
getBlacklist,
|
|
2580
|
+
} = require("djs-builder");
|
|
2581
|
+
const {
|
|
2582
|
+
SlashCommandBuilder,
|
|
2583
|
+
PermissionFlagsBits,
|
|
2584
|
+
EmbedBuilder,
|
|
2585
|
+
} = require("discord.js");
|
|
1915
2586
|
|
|
1916
2587
|
module.exports = {
|
|
1917
2588
|
data: new SlashCommandBuilder()
|
|
1918
2589
|
.setName("blacklist")
|
|
1919
2590
|
.setDescription("Manage the blacklist")
|
|
1920
2591
|
.setDefaultMemberPermissions(PermissionFlagsBits.Administrator)
|
|
1921
|
-
.addSubcommand(sub =>
|
|
1922
|
-
sub
|
|
1923
|
-
.
|
|
1924
|
-
.
|
|
1925
|
-
.
|
|
2592
|
+
.addSubcommand((sub) =>
|
|
2593
|
+
sub
|
|
2594
|
+
.setName("add")
|
|
2595
|
+
.setDescription("Add to blacklist")
|
|
2596
|
+
.addUserOption((opt) =>
|
|
2597
|
+
opt.setName("user").setDescription("User to blacklist")
|
|
2598
|
+
)
|
|
2599
|
+
.addRoleOption((opt) =>
|
|
2600
|
+
opt.setName("role").setDescription("Role to blacklist")
|
|
2601
|
+
)
|
|
2602
|
+
.addChannelOption((opt) =>
|
|
2603
|
+
opt.setName("channel").setDescription("Channel to blacklist")
|
|
2604
|
+
)
|
|
1926
2605
|
)
|
|
1927
|
-
.addSubcommand(sub =>
|
|
1928
|
-
sub
|
|
1929
|
-
.
|
|
1930
|
-
.
|
|
1931
|
-
.
|
|
2606
|
+
.addSubcommand((sub) =>
|
|
2607
|
+
sub
|
|
2608
|
+
.setName("remove")
|
|
2609
|
+
.setDescription("Remove from blacklist")
|
|
2610
|
+
.addUserOption((opt) =>
|
|
2611
|
+
opt.setName("user").setDescription("User to remove")
|
|
2612
|
+
)
|
|
2613
|
+
.addRoleOption((opt) =>
|
|
2614
|
+
opt.setName("role").setDescription("Role to remove")
|
|
2615
|
+
)
|
|
2616
|
+
.addChannelOption((opt) =>
|
|
2617
|
+
opt.setName("channel").setDescription("Channel to remove")
|
|
2618
|
+
)
|
|
1932
2619
|
)
|
|
1933
|
-
.addSubcommand(sub =>
|
|
1934
|
-
sub
|
|
1935
|
-
.
|
|
1936
|
-
.
|
|
1937
|
-
.
|
|
2620
|
+
.addSubcommand((sub) =>
|
|
2621
|
+
sub
|
|
2622
|
+
.setName("check")
|
|
2623
|
+
.setDescription("Check if a target is blacklisted")
|
|
2624
|
+
.addUserOption((opt) =>
|
|
2625
|
+
opt.setName("user").setDescription("User to check")
|
|
2626
|
+
)
|
|
2627
|
+
.addRoleOption((opt) =>
|
|
2628
|
+
opt.setName("role").setDescription("Role to check")
|
|
2629
|
+
)
|
|
2630
|
+
.addChannelOption((opt) =>
|
|
2631
|
+
opt.setName("channel").setDescription("Channel to check")
|
|
2632
|
+
)
|
|
1938
2633
|
)
|
|
1939
|
-
.addSubcommand(sub =>
|
|
1940
|
-
sub
|
|
1941
|
-
.
|
|
2634
|
+
.addSubcommand((sub) =>
|
|
2635
|
+
sub
|
|
2636
|
+
.setName("list")
|
|
2637
|
+
.setDescription("List all blacklisted items")
|
|
2638
|
+
.addStringOption((opt) =>
|
|
2639
|
+
opt
|
|
2640
|
+
.setName("type")
|
|
2641
|
+
.setDescription("Filter by type")
|
|
2642
|
+
.addChoices(
|
|
2643
|
+
{ name: "User", value: "user" },
|
|
2644
|
+
{ name: "Role", value: "role" },
|
|
2645
|
+
{ name: "Channel", value: "channel" },
|
|
2646
|
+
{ name: "All", value: "all" }
|
|
2647
|
+
)
|
|
2648
|
+
)
|
|
1942
2649
|
),
|
|
1943
2650
|
async run(interaction) {
|
|
1944
2651
|
const sub = interaction.options.getSubcommand();
|
|
@@ -1948,54 +2655,95 @@ module.exports = {
|
|
|
1948
2655
|
const guildId = interaction.guild.id;
|
|
1949
2656
|
|
|
1950
2657
|
if (sub === "list") {
|
|
1951
|
-
|
|
1952
|
-
|
|
2658
|
+
const type = interaction.options.getString("type");
|
|
2659
|
+
if (type !== "all") {
|
|
1953
2660
|
const list = await getBlacklist(guildId, type);
|
|
1954
2661
|
|
|
1955
|
-
if (!list.length)
|
|
2662
|
+
if (!list.length)
|
|
2663
|
+
return interaction.reply({
|
|
2664
|
+
content: "✅ No blacklisted items found.",
|
|
2665
|
+
flags: 64,
|
|
2666
|
+
});
|
|
1956
2667
|
|
|
1957
2668
|
const embed = new EmbedBuilder()
|
|
1958
|
-
|
|
1959
|
-
|
|
1960
|
-
|
|
1961
|
-
|
|
1962
|
-
|
|
1963
|
-
|
|
2669
|
+
.setTitle("🚫 Blacklist")
|
|
2670
|
+
.setColor("Red")
|
|
2671
|
+
.setDescription(
|
|
2672
|
+
list
|
|
2673
|
+
.map(
|
|
2674
|
+
(item) =>
|
|
2675
|
+
`• **${item.type.toUpperCase()}**: <${
|
|
2676
|
+
item.type === "channel"
|
|
2677
|
+
? "#"
|
|
2678
|
+
: item.type === "role"
|
|
2679
|
+
? "@&"
|
|
2680
|
+
: "@"
|
|
2681
|
+
}${item.id}> (\`${item.id}\`)`
|
|
2682
|
+
)
|
|
2683
|
+
.join("\n")
|
|
2684
|
+
.slice(0, 4000)
|
|
2685
|
+
);
|
|
2686
|
+
|
|
2687
|
+
return interaction.reply({ embeds: [embed], flags: 64 });
|
|
2688
|
+
} else {
|
|
1964
2689
|
const list = await getBlacklist(guildId);
|
|
1965
|
-
if (!list.length)
|
|
2690
|
+
if (!list.length)
|
|
2691
|
+
return interaction.reply({
|
|
2692
|
+
content: "✅ No blacklisted items found.",
|
|
2693
|
+
flags: 64,
|
|
2694
|
+
});
|
|
1966
2695
|
|
|
1967
2696
|
const embeds = [];
|
|
1968
|
-
const roles = list.filter(i => i.type === "role");
|
|
1969
|
-
const users = list.filter(i => i.type === "user");
|
|
1970
|
-
const channels = list.filter(i => i.type === "channel");
|
|
2697
|
+
const roles = list.filter((i) => i.type === "role");
|
|
2698
|
+
const users = list.filter((i) => i.type === "user");
|
|
2699
|
+
const channels = list.filter((i) => i.type === "channel");
|
|
1971
2700
|
|
|
1972
2701
|
if (users.length) {
|
|
1973
|
-
|
|
2702
|
+
const userEmbed = new EmbedBuilder()
|
|
1974
2703
|
.setTitle("🚫 Blacklisted Users")
|
|
1975
2704
|
.setColor("Red")
|
|
1976
|
-
.setDescription(
|
|
1977
|
-
|
|
2705
|
+
.setDescription(
|
|
2706
|
+
users
|
|
2707
|
+
.map((item) => `• <@${item.id}> (\`${item.id}\`)`)
|
|
2708
|
+
.join("\n")
|
|
2709
|
+
.slice(0, 4000)
|
|
2710
|
+
);
|
|
2711
|
+
embeds.push(userEmbed);
|
|
1978
2712
|
}
|
|
1979
|
-
if(
|
|
1980
|
-
|
|
2713
|
+
if (roles.length) {
|
|
2714
|
+
const roleEmbed = new EmbedBuilder()
|
|
1981
2715
|
.setTitle("🚫 Blacklisted Roles")
|
|
1982
2716
|
.setColor("Red")
|
|
1983
|
-
.setDescription(
|
|
1984
|
-
|
|
2717
|
+
.setDescription(
|
|
2718
|
+
roles
|
|
2719
|
+
.map((item) => `• <@&${item.id}> (\`${item.id}\`)`)
|
|
2720
|
+
.join("\n")
|
|
2721
|
+
.slice(0, 4000)
|
|
2722
|
+
);
|
|
2723
|
+
embeds.push(roleEmbed);
|
|
1985
2724
|
}
|
|
1986
|
-
if(
|
|
1987
|
-
|
|
2725
|
+
if (channels.length) {
|
|
2726
|
+
const channelEmbed = new EmbedBuilder()
|
|
1988
2727
|
.setTitle("🚫 Blacklisted Channels")
|
|
1989
2728
|
.setColor("Red")
|
|
1990
|
-
.setDescription(
|
|
1991
|
-
|
|
2729
|
+
.setDescription(
|
|
2730
|
+
channels
|
|
2731
|
+
.map((item) => `• <#${item.id}> (\`${item.id}\`)`)
|
|
2732
|
+
.join("\n")
|
|
2733
|
+
.slice(0, 4000)
|
|
2734
|
+
);
|
|
2735
|
+
embeds.push(channelEmbed);
|
|
1992
2736
|
}
|
|
1993
|
-
return interaction.reply({ embeds, flags
|
|
2737
|
+
return interaction.reply({ embeds, flags: 64 });
|
|
2738
|
+
}
|
|
1994
2739
|
}
|
|
1995
|
-
|
|
1996
|
-
|
|
2740
|
+
|
|
1997
2741
|
if (!user && !role && !channel) {
|
|
1998
|
-
return interaction.reply({
|
|
2742
|
+
return interaction.reply({
|
|
2743
|
+
content:
|
|
2744
|
+
"⚠️ You must provide at least one option (User, Role, or Channel).",
|
|
2745
|
+
flags: 64,
|
|
2746
|
+
});
|
|
1999
2747
|
}
|
|
2000
2748
|
const target = user || role || channel;
|
|
2001
2749
|
const type = user ? "user" : role ? "role" : "channel";
|
|
@@ -2003,18 +2751,25 @@ module.exports = {
|
|
|
2003
2751
|
|
|
2004
2752
|
if (sub === "add") {
|
|
2005
2753
|
const success = await addToBlacklist(guildId, type, id);
|
|
2006
|
-
if (success)
|
|
2007
|
-
|
|
2754
|
+
if (success)
|
|
2755
|
+
interaction.reply(`✅ Added **${type}** ${target} to blacklist.`);
|
|
2756
|
+
else
|
|
2757
|
+
interaction.reply(`⚠️ **${type}** ${target} is already blacklisted.`);
|
|
2008
2758
|
} else if (sub === "remove") {
|
|
2009
2759
|
const success = await removeFromBlacklist(guildId, type, id);
|
|
2010
|
-
if (success)
|
|
2760
|
+
if (success)
|
|
2761
|
+
interaction.reply(`✅ Removed **${type}** ${target} from blacklist.`);
|
|
2011
2762
|
else interaction.reply(`⚠️ **${type}** ${target} is not blacklisted.`);
|
|
2012
2763
|
} else if (sub === "check") {
|
|
2013
2764
|
const isBlocked = await isBlacklisted(guildId, type, id);
|
|
2014
|
-
if (isBlocked)
|
|
2015
|
-
|
|
2765
|
+
if (isBlocked)
|
|
2766
|
+
interaction.reply(
|
|
2767
|
+
`🚫 **${type}** ${target} is currently **blacklisted**.`
|
|
2768
|
+
);
|
|
2769
|
+
else
|
|
2770
|
+
interaction.reply(`✅ **${type}** ${target} is **not** blacklisted.`);
|
|
2016
2771
|
}
|
|
2017
|
-
}
|
|
2772
|
+
},
|
|
2018
2773
|
};
|
|
2019
2774
|
```
|
|
2020
2775
|
|
|
@@ -2160,6 +2915,7 @@ The **Dashboard System** is a modern, lightweight web-based control panel for yo
|
|
|
2160
2915
|
- 📜 **Commands Viewer** – Browse all slash and prefix commands.
|
|
2161
2916
|
- 🏆 **Level System Management** – View leaderboards, manage user XP and levels.
|
|
2162
2917
|
- 🎉 **Giveaway Control** – Pause, resume, end, reroll, or delete giveaways.
|
|
2918
|
+
- 🦾 **Logging System Control** – Manage log channels, colors, and event toggles.
|
|
2163
2919
|
- 🚫 **Blacklist Management** – Add/remove users, roles, or channels from blacklist.
|
|
2164
2920
|
- 🎨 **Modern UI** – Beautiful, responsive design with dark mode support.
|
|
2165
2921
|
|
|
@@ -2191,11 +2947,10 @@ const starterOptions = {
|
|
|
2191
2947
|
|
|
2192
2948
|
// 🌐 Dashboard Configuration
|
|
2193
2949
|
dashboard: {
|
|
2194
|
-
clientID: "YOUR_DISCORD_CLIENT_ID", // 🔑 Discord Application Client ID
|
|
2195
2950
|
clientSecret: "YOUR_DISCORD_CLIENT_SECRET", // 🔐 Discord Application Client Secret
|
|
2196
|
-
callbackURL: "http://localhost:3000/auth/discord/callback", // 🔗 OAuth2 Callback URL
|
|
2197
|
-
sessionSecret: "your-super-secret-key",
|
|
2198
|
-
port: 3000,
|
|
2951
|
+
callbackURL: "http://localhost:3000/auth/discord/callback", // 🔗 OAuth2 Callback URL (OPTINAL)
|
|
2952
|
+
sessionSecret: "your-super-secret-key", // 🔒 Session encryption secret
|
|
2953
|
+
port: 3000, // 🌍 Dashboard port (OPTINAL / default: 3000)
|
|
2199
2954
|
},
|
|
2200
2955
|
|
|
2201
2956
|
// ... other options (Status, database, anticrash, etc.)
|
|
@@ -2229,11 +2984,10 @@ client.once("ready", () => {
|
|
|
2229
2984
|
|
|
2230
2985
|
// 🌐 Start the Dashboard
|
|
2231
2986
|
dashboard(client, {
|
|
2232
|
-
clientID: "YOUR_DISCORD_CLIENT_ID", // 🔑 Discord Application Client ID
|
|
2233
2987
|
clientSecret: "YOUR_DISCORD_CLIENT_SECRET", // 🔐 Discord Application Client Secret
|
|
2234
|
-
callbackURL: "http://localhost:3000/auth/discord/callback", // 🔗 OAuth2 Callback URL
|
|
2235
|
-
sessionSecret: "your-super-secret-key",
|
|
2236
|
-
port: 3000,
|
|
2988
|
+
callbackURL: "http://localhost:3000/auth/discord/callback", // 🔗 OAuth2 Callback URL (OPTINAL)
|
|
2989
|
+
sessionSecret: "your-super-secret-key", // 🔒 Session encryption secret
|
|
2990
|
+
port: 3000, // 🌍 Dashboard port (OPTINAL / default: 3000)
|
|
2237
2991
|
});
|
|
2238
2992
|
});
|
|
2239
2993
|
```
|
|
@@ -2249,15 +3003,16 @@ client.once("ready", () => {
|
|
|
2249
3003
|
|
|
2250
3004
|
### 📌 Dashboard Routes
|
|
2251
3005
|
|
|
2252
|
-
| Route
|
|
2253
|
-
|
|
2254
|
-
| `/`
|
|
2255
|
-
| `/login`
|
|
2256
|
-
| `/dashboard`
|
|
2257
|
-
| `/dashboard/:guildId`
|
|
2258
|
-
| `/dashboard/:guildId/commands`
|
|
2259
|
-
| `/dashboard/:guildId/levels`
|
|
2260
|
-
| `/dashboard/:guildId/giveaways` | 🎉 Giveaway management
|
|
3006
|
+
| Route | Description |
|
|
3007
|
+
| ------------------------------- | ---------------------------- |
|
|
3008
|
+
| `/` | 🏠 Homepage with bot stats |
|
|
3009
|
+
| `/login` | 🔐 Login page |
|
|
3010
|
+
| `/dashboard` | 📊 Server selection |
|
|
3011
|
+
| `/dashboard/:guildId` | 🏠 Server overview |
|
|
3012
|
+
| `/dashboard/:guildId/commands` | 📜 Commands list |
|
|
3013
|
+
| `/dashboard/:guildId/levels` | 🏆 Level leaderboard |
|
|
3014
|
+
| `/dashboard/:guildId/giveaways` | 🎉 Giveaway management |
|
|
3015
|
+
| `/dashboard/:guildId/logs` | 🛡️ Logging system management |
|
|
2261
3016
|
|
|
2262
3017
|
---
|
|
2263
3018
|
|
|
@@ -2290,7 +3045,13 @@ POST /api/:guildId/giveaway/end
|
|
|
2290
3045
|
POST /api/:guildId/giveaway/reroll
|
|
2291
3046
|
POST /api/:guildId/giveaway/delete
|
|
2292
3047
|
|
|
2293
|
-
//
|
|
3048
|
+
// �️ Logging system management
|
|
3049
|
+
POST /api/:guildId/logs/channel // Set default log channel
|
|
3050
|
+
POST /api/:guildId/logs/toggle // Enable/disable event type
|
|
3051
|
+
POST /api/:guildId/logs/event // Update event settings (channel, color)
|
|
3052
|
+
POST /api/:guildId/logs/reset // Reset all log settings
|
|
3053
|
+
|
|
3054
|
+
// �🚫 Blacklist management
|
|
2294
3055
|
POST /api/guild/:guildId/blacklist // Add to blacklist
|
|
2295
3056
|
DELETE /api/guild/:guildId/blacklist // Remove from blacklist
|
|
2296
3057
|
```
|
|
@@ -2304,13 +3065,12 @@ DELETE /api/guild/:guildId/blacklist // Remove from blacklist
|
|
|
2304
3065
|
|
|
2305
3066
|
### 🔧 Configuration Options
|
|
2306
3067
|
|
|
2307
|
-
| Option
|
|
2308
|
-
|
|
2309
|
-
| `
|
|
2310
|
-
| `
|
|
2311
|
-
| `
|
|
2312
|
-
| `
|
|
2313
|
-
| `port` | `number` | ❌ | 🌍 Port to run the dashboard (default: 3000) |
|
|
3068
|
+
| Option | Type | Required | Description |
|
|
3069
|
+
| --------------- | -------- | -------- | ---------------------------------------------------- |
|
|
3070
|
+
| `clientSecret` | `string` | ✅ | 🔐 Your Discord Application Client Secret |
|
|
3071
|
+
| `callbackURL` | `string` | ✅ | 🔗 OAuth2 redirect URL (must match Discord settings) |
|
|
3072
|
+
| `sessionSecret` | `string` | ✅ | 🔒 Secret key for session encryption |
|
|
3073
|
+
| `port` | `number` | ❌ | 🌍 Port to run the dashboard (default: 3000) |
|
|
2314
3074
|
|
|
2315
3075
|
---
|
|
2316
3076
|
|
|
@@ -2318,16 +3078,17 @@ DELETE /api/guild/:guildId/blacklist // Remove from blacklist
|
|
|
2318
3078
|
|
|
2319
3079
|
The dashboard uses **EJS** templates located in the `views` folder:
|
|
2320
3080
|
|
|
2321
|
-
| File
|
|
2322
|
-
|
|
2323
|
-
| `index.ejs`
|
|
2324
|
-
| `login.ejs`
|
|
2325
|
-
| `dashboard.ejs` | 📊 Server selection
|
|
2326
|
-
| `guild.ejs`
|
|
2327
|
-
| `commands.ejs`
|
|
2328
|
-
| `levels.ejs`
|
|
2329
|
-
| `giveaways.ejs` | 🎉 Giveaway management
|
|
2330
|
-
| `
|
|
3081
|
+
| File | Description |
|
|
3082
|
+
| --------------- | ---------------------------- |
|
|
3083
|
+
| `index.ejs` | 🏠 Homepage |
|
|
3084
|
+
| `login.ejs` | 🔐 Login page |
|
|
3085
|
+
| `dashboard.ejs` | 📊 Server selection |
|
|
3086
|
+
| `guild.ejs` | 🏠 Server overview |
|
|
3087
|
+
| `commands.ejs` | 📜 Commands list |
|
|
3088
|
+
| `levels.ejs` | 🏆 Level management |
|
|
3089
|
+
| `giveaways.ejs` | 🎉 Giveaway management |
|
|
3090
|
+
| `logs.ejs` | 🛡️ Logging system management |
|
|
3091
|
+
| `404.ejs` | ❌ Not found page |
|
|
2331
3092
|
|
|
2332
3093
|
</details>
|
|
2333
3094
|
|