djs-builder 0.6.37 → 0.6.39

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 CHANGED
@@ -148,7 +148,7 @@ await starter(client, starterOptions);
148
148
 
149
149
  ## ⚙️ functions
150
150
 
151
- - **Easyest ✨** / **Fastest ⚡** /**Clear 🧵**
151
+ - **Easiest ✨** / **Fastest ⚡** /**Clear 🧵**
152
152
 
153
153
  **Than the discord.js**
154
154
 
@@ -552,6 +552,10 @@ module.exports = {
552
552
  The **Level System** module lets you track user experience points (XP) in **text** 💬 and **voice** 🎙️, handle **level-ups** ⬆️, and display **leaderboards** 🏅.
553
553
  Perfect for gamifying your Discord server! 🎮✨
554
554
 
555
+ > **Note**: To use this module, you **MUST** have **DATABASE** conection.
556
+
557
+ > **Note**: You can get all data by requiring the **Level** module.
558
+
555
559
  ---
556
560
 
557
561
  ### 📦 Module Exports
@@ -704,6 +708,10 @@ module.exports = {
704
708
 
705
709
  This module provides a robust and feature-rich suite of functions to effortlessly launch, monitor, manage, and conclude **Giveaways** on your Discord server. It fully supports both **Reactions** and **Buttons** for entry, featuring advanced controls like pausing, resuming, and rerolling winners. **It is highly recommended to read the Important Notes section below.** 🚨
706
710
 
711
+ > **Note**: To use this module, you **MUST** have **DATABASE** conection.
712
+
713
+ > **Note**: You can get all data by requiring the **giveaway** module.
714
+
707
715
  ---
708
716
 
709
717
  ### 📦 Module Exports
@@ -842,7 +850,7 @@ module.exports = {
842
850
  ---
843
851
 
844
852
  <details>
845
- <summary>⚠️ mportant Notes</summary>
853
+ <summary>⚠️ Important Notes</summary>
846
854
 
847
855
  ### ⚠️ **Important Notes** – _Read Before Use\!_ 🚨
848
856
 
@@ -1190,7 +1198,7 @@ if (giveawayData) {
1190
1198
 
1191
1199
  📊 **`Gdata(messageId)`** – Returned Object Structure
1192
1200
 
1193
- - it like :
1201
+ - Returns an object like:
1194
1202
 
1195
1203
  ```js
1196
1204
  {
@@ -1253,6 +1261,7 @@ const {
1253
1261
  SlashCommandBuilder,
1254
1262
  EmbedBuilder,
1255
1263
  AttachmentBuilder,
1264
+ PermissionFlagsBits,
1256
1265
  } = require("discord.js");
1257
1266
  const ms = require("ms");
1258
1267
 
@@ -1260,6 +1269,7 @@ module.exports = {
1260
1269
  data: new SlashCommandBuilder()
1261
1270
  .setName("giveaway")
1262
1271
  .setDescription("Comprehensive giveaway system management")
1272
+ .setDefaultMemberPermissions(PermissionFlagsBits.ManageGuild)
1263
1273
 
1264
1274
  // 🎬 /giveaway start
1265
1275
  .addSubcommand((subcommand) =>
@@ -1471,8 +1481,7 @@ module.exports = {
1471
1481
  const prize = interaction.options.getString("prize");
1472
1482
 
1473
1483
  const durationMs = ms(timeString);
1474
- const endTimeMs = Date.now() + durationMs;
1475
-
1484
+ const endTimeMs = Date.now() + durationMs;
1476
1485
 
1477
1486
  if (!durationMs) {
1478
1487
  return interaction.editReply(
@@ -1535,7 +1544,6 @@ const endTimeMs = Date.now() + durationMs;
1535
1544
  giveaways.length
1536
1545
  } found)`;
1537
1546
 
1538
-
1539
1547
  if (listContent.length <= MAX_MESSAGE_LENGTH) {
1540
1548
  // Output as a simple message (Under 2000 chars)
1541
1549
  return interaction.editReply({
@@ -1655,69 +1663,77 @@ const endTimeMs = Date.now() + durationMs;
1655
1663
  } else if (command === "data") {
1656
1664
  const id = interaction.options.getString("id");
1657
1665
  console.log(id);
1658
- const data = await Gdata(id);
1659
- if (data?.error)
1666
+ const data = await Gdata(id);
1667
+ if (data?.error)
1660
1668
  return interaction.editReply(`❌ **Error:** ${data.error}`);
1661
1669
 
1662
-
1663
- const giveawayEmbed = new EmbedBuilder()
1670
+ const giveawayEmbed = new EmbedBuilder()
1664
1671
  .setTitle(`📊 Giveaway Data: ${id}`)
1665
- .setColor(data.ended ? 0xFF0000 : data.paused ? 0xFFC0CB : 0x00FF00)
1666
- .setDescription(`**Jump to Message 🔗 ** : ${data.messageId ? `https://discord.com/channels/${data.guildId}/${data.channelId}/${data.messageId}` : 'N/A'}`)
1667
-
1668
-
1669
-
1670
- giveawayEmbed.addFields(
1671
- {
1672
- name: "✨ Status",
1673
- value: data.ended ? "ENDED 🛑" : data.paused ? "PAUSED ⏸️" : "ACTIVE ✅",
1674
- inline: true
1672
+ .setColor(data.ended ? 0xff0000 : data.paused ? 0xffc0cb : 0x00ff00)
1673
+ .setDescription(
1674
+ `**Jump to Message 🔗 ** : ${
1675
+ data.messageId
1676
+ ? `https://discord.com/channels/${data.guildId}/${data.channelId}/${data.messageId}`
1677
+ : "N/A"
1678
+ }`
1679
+ );
1680
+
1681
+ giveawayEmbed.addFields(
1682
+ {
1683
+ name: "✨ Status",
1684
+ value: data.ended
1685
+ ? "ENDED 🛑"
1686
+ : data.paused
1687
+ ? "PAUSED ⏸️"
1688
+ : "ACTIVE ✅",
1689
+ inline: true,
1675
1690
  },
1676
- {
1677
- name: "🏆 Winners",
1678
- value: data.winwesNumber.toString(),
1679
- inline: true
1691
+ {
1692
+ name: "🏆 Winners",
1693
+ value: data.winwesNumber.toString(),
1694
+ inline: true,
1680
1695
  },
1681
- {
1682
- name: "🙋‍♂️ Hoster",
1683
- value: `<@${data.hoster}>`,
1684
- inline: true
1696
+ {
1697
+ name: "🙋‍♂️ Hoster",
1698
+ value: `<@${data.hoster}>`,
1699
+ inline: true,
1685
1700
  },
1686
-
1687
- {
1688
- name: "⏳ Ends In",
1689
- value: `<t:${Math.floor(data.endTime / 1000)}:R>`,
1690
- inline: true
1701
+
1702
+ {
1703
+ name: "⏳ Ends In",
1704
+ value: `<t:${Math.floor(data.endTime / 1000)}:R>`,
1705
+ inline: true,
1691
1706
  },
1692
- {
1693
- name: "🎟️ Entries",
1694
- value: data.reaction === "button" ? data.users.length.toString() : "N/A (Reaction Type)",
1695
- inline: true
1707
+ {
1708
+ name: "🎟️ Entries",
1709
+ value:
1710
+ data.reaction === "button"
1711
+ ? data.users.length.toString()
1712
+ : "N/A (Reaction Type)",
1713
+ inline: true,
1696
1714
  },
1697
- {
1698
- name: "🖱️ Entry Type",
1699
- value: data.reaction.toUpperCase(),
1700
- inline: true
1715
+ {
1716
+ name: "🖱️ Entry Type",
1717
+ value: data.reaction.toUpperCase(),
1718
+ inline: true,
1701
1719
  }
1702
- );
1720
+ );
1703
1721
 
1704
-
1705
- if (data.ended && data.winers.length > 0) {
1722
+ if (data.ended && data.winers.length > 0) {
1706
1723
  giveawayEmbed.addFields({
1707
- name: "🏅 Past Winners",
1708
- value: data.winers.map(u => `<@${u}>`).join(', ') || "N/A",
1709
- inline: false
1724
+ name: "🏅 Past Winners",
1725
+ value: data.winers.map((u) => `<@${u}>`).join(", ") || "N/A",
1726
+ inline: false,
1710
1727
  });
1711
- }
1728
+ }
1712
1729
 
1713
- return interaction.editReply({
1714
- embeds: [giveawayEmbed],
1715
- content: `Data retrieved for giveaway \`${id}\`.`
1716
- });
1717
- }
1730
+ return interaction.editReply({
1731
+ embeds: [giveawayEmbed],
1732
+ content: `Data retrieved for giveaway \`${id}\`.`,
1733
+ });
1734
+ }
1718
1735
  },
1719
1736
  };
1720
-
1721
1737
  ```
1722
1738
 
1723
1739
  ---
@@ -1756,6 +1772,77 @@ const endTimeMs = Date.now() + durationMs;
1756
1772
 
1757
1773
  ---
1758
1774
 
1775
+ <details>
1776
+ <summary>Hot Reloading 🔄</summary>
1777
+
1778
+ **🔄 Hot Reloading – Update your bot without restarting!**
1779
+
1780
+ `djs-builder` allows you to reload your **commands** and **events** instantly while the bot is running. This is perfect for rapid development and fixing bugs on the fly.
1781
+
1782
+ ---
1783
+
1784
+ ### 📌 Features
1785
+
1786
+ - **Prefix Commands**: Reloads all prefix commands from disk.
1787
+ - **Slash Commands**: Reloads slash command logic (internal cache).
1788
+ - **Events**: Reloads event listeners (removes old ones, adds new ones).
1789
+ - **All**: Reloads everything at once.
1790
+
1791
+ ---
1792
+
1793
+ ### 📌 Example Usage (Slash Command)
1794
+
1795
+ ```js
1796
+ const { reload } = require("djs-builder");
1797
+ const { SlashCommandBuilder } = require("discord.js");
1798
+
1799
+ module.exports = {
1800
+ data: new SlashCommandBuilder()
1801
+ .setName("reload")
1802
+ .setDescription("Reload bot commands/events")
1803
+ .addStringOption((option) =>
1804
+ option
1805
+ .setName("type")
1806
+ .setDescription("What to reload?")
1807
+ .setRequired(true)
1808
+ .addChoices(
1809
+ { name: "Prefix Commands", value: "prefix" },
1810
+ { name: "Slash Commands", value: "slash" },
1811
+ { name: "Events", value: "events" },
1812
+ { name: "All", value: "all" }
1813
+ )
1814
+ ),
1815
+ ownerOnly: true,
1816
+ async run(interaction, client) {
1817
+ // Check for owner permission (Recommended)
1818
+
1819
+ const type = interaction.options.getString("type");
1820
+
1821
+ try {
1822
+ await interaction.deferReply();
1823
+ await reload(client, type);
1824
+ await interaction.editReply(`✅ Successfully reloaded **${type}**! 🚀`);
1825
+ } catch (error) {
1826
+ console.error(error);
1827
+ await interaction.editReply(
1828
+ "❌ Failed to reload. Check console for errors."
1829
+ );
1830
+ }
1831
+ },
1832
+ };
1833
+ ```
1834
+
1835
+ ---
1836
+
1837
+ ### 💡 Notes
1838
+
1839
+ - **Slash Commands**: Reloading only updates the **code execution**. If you change the command name, description, or options, you still need to restart the bot to update Discord's API.
1840
+ - **Events**: Old event listeners are automatically removed before adding new ones to prevent duplicates.
1841
+
1842
+ </details>
1843
+
1844
+ ---
1845
+
1759
1846
  ## ⚡ Commands & Events
1760
1847
 
1761
1848
  **💡 Commands & Events made easy!**
@@ -204,7 +204,7 @@ async function giveaway_end(client, g, type) {
204
204
  return;
205
205
  }
206
206
 
207
- const winners = pickWinners(users_id, g.winersNumber);
207
+ const winners = pickWinners(users_id, g.winwesNumber);
208
208
 
209
209
  await message.edit({
210
210
  embeds: [g.endEmbed],
@@ -255,7 +255,7 @@ async function Greroll(client, messageId) {
255
255
  );
256
256
  }
257
257
 
258
- const winners = pickWinners(users_id, g.winersNumber);
258
+ const winners = pickWinners(users_id, g.winwesNumber);
259
259
 
260
260
  await message.reply({
261
261
  content: `🔄️ **Giveaway Reroll!**\n> Winner(s):\n- <@${winners
package/function/level.js CHANGED
@@ -73,4 +73,4 @@ async function leaderboard(guildId, type = "totalXP", limit = 10) {
73
73
  .limit(limit);
74
74
  }
75
75
 
76
- module.exports = { addXP, UserLevel, leaderboard };
76
+ module.exports = { Level,addXP, UserLevel, leaderboard };
@@ -12,8 +12,135 @@ let termenal = {
12
12
  events: 0,
13
13
  };
14
14
 
15
+ async function loadPrefix(client, path) {
16
+ const prefix_files = await readFile(path);
17
+ client.prefixCommands = new Map();
18
+
19
+ for (const file of prefix_files) {
20
+ delete require.cache[require.resolve(file.path)];
21
+ const command = require(file.path);
22
+
23
+ if (!command.name) continue;
24
+
25
+ const commandWithMeta = {
26
+ ...command,
27
+ file_path: file.path,
28
+ };
29
+
30
+ client.prefixCommands.set(command.name, commandWithMeta);
31
+
32
+ if (Array.isArray(command.aliases)) {
33
+ for (const alias of command.aliases) {
34
+ client.prefixCommands.set(alias, commandWithMeta);
35
+ }
36
+ }
37
+ }
38
+ termenal.prefix = client.prefixCommands.size;
39
+ return client.prefixCommands.size;
40
+ }
41
+
42
+ async function loadSlash(client, path) {
43
+ const slash_files = await readFile(path);
44
+
45
+
46
+ for (const file of slash_files) {
47
+ delete require.cache[require.resolve(file.path)];
48
+ }
49
+
50
+ const validSlashCommands = slash_files
51
+ .map((f) => {
52
+ const cmd = require(f.path);
53
+ cmd.file_path = f.path;
54
+ return cmd;
55
+ })
56
+ .filter(
57
+ (cmd) =>
58
+ cmd.data &&
59
+ (typeof cmd.run === "function" || typeof cmd.execute === "function")
60
+ );
61
+
62
+ client.slashCommands = new Map(
63
+ validSlashCommands.map((cmd) => [cmd.data.name, cmd])
64
+ );
65
+ client.slashData = validSlashCommands.map((cmd) => cmd.data.toJSON());
66
+
67
+ termenal.slash = validSlashCommands.length;
68
+ return validSlashCommands.length;
69
+ }
70
+
71
+ async function loadEvents(client, path) {
72
+ const event_files = await readFile(path);
73
+
74
+
75
+ if (!client.djsEventListeners) {
76
+ client.djsEventListeners = new Map();
77
+ }
78
+
79
+
80
+ for (const file of event_files) {
81
+ if (client.djsEventListeners.has(file.path)) {
82
+ const { name, listener } = client.djsEventListeners.get(file.path);
83
+ client.removeListener(name, listener);
84
+ client.djsEventListeners.delete(file.path);
85
+ }
86
+ delete require.cache[require.resolve(file.path)];
87
+ }
88
+
89
+ for (const file of event_files) {
90
+ const event = require(file.path);
91
+
92
+ if (!event.name || typeof event.run !== "function") continue;
93
+
94
+ let listener;
95
+ if (event.once) {
96
+ listener = (...args) => {
97
+ if (typeof event.run === "function") {
98
+ event.run(...args);
99
+ } else if (typeof event.execute === "function") {
100
+ event.execute(...args);
101
+ }
102
+ };
103
+ client.once(event.name, listener);
104
+ } else {
105
+ listener = (...args) => {
106
+ if (typeof event.run === "function") {
107
+ event.run(...args, client);
108
+ } else if (typeof event.execute === "function") {
109
+ event.execute(...args, client);
110
+ }
111
+ };
112
+ client.on(event.name, listener);
113
+ }
114
+
115
+ client.djsEventListeners.set(file.path, { name: event.name, listener });
116
+ termenal.events++;
117
+ }
118
+ return termenal.events;
119
+ }
120
+
121
+ async function reload(client, type) {
122
+ if (!client.djsOptions) return console.error("❌ Options not found on client.");
123
+
124
+ if (type === "prefix" && client.djsOptions.prefix) {
125
+ await loadPrefix(client, client.djsOptions.prefix.path);
126
+ console.log("✅ Prefix commands reloaded.");
127
+ } else if (type === "slash" && client.djsOptions.slash) {
128
+ await loadSlash(client, client.djsOptions.slash.path);
129
+ console.log("✅ Slash commands reloaded (Internal Cache).");
130
+ } else if (type === "events" && client.djsOptions.events) {
131
+ await loadEvents(client, client.djsOptions.events.path);
132
+ console.log("✅ Events reloaded.");
133
+ } else if (type === "all") {
134
+ if (client.djsOptions.prefix) await loadPrefix(client, client.djsOptions.prefix.path);
135
+ if (client.djsOptions.slash) await loadSlash(client, client.djsOptions.slash.path);
136
+ if (client.djsOptions.events) await loadEvents(client, client.djsOptions.events.path);
137
+ console.log("✅ All systems reloaded.");
138
+ }
139
+ }
140
+
15
141
  async function starter(client, options) {
16
142
  //////////////////////////////////////////! mine data !////////////////////////////////////////////////////////
143
+ client.djsOptions = options;
17
144
  const token = options.bot.token;
18
145
  const ownerId = options.bot.ownerId;
19
146
  const Status = options.Status || null;
@@ -72,80 +199,19 @@ async function starter(client, options) {
72
199
  //////////////////////////////////////////? Prefix Loader ////////////////////////////////////////////////////////
73
200
 
74
201
  if (prefix) {
75
- const prefix_files = await readFile(prefix.path);
76
- client.prefixCommands = new Map();
77
-
78
- for (const file of prefix_files) {
79
- const command = require(file.path);
80
-
81
- if (!command.name) continue;
82
-
83
- const commandWithMeta = {
84
- ...command,
85
- file_path: file.path,
86
- };
87
-
88
- client.prefixCommands.set(command.name, commandWithMeta);
89
-
90
- if (Array.isArray(command.aliases)) {
91
- for (const alias of command.aliases) {
92
- client.prefixCommands.set(alias, commandWithMeta);
93
- }
94
- }
95
-
96
- termenal.prefix++;
97
- }
202
+ await loadPrefix(client, prefix.path);
98
203
  }
99
204
 
100
205
  //////////////////////////////////////////? Slash Loader ////////////////////////////////////////////////////////
101
206
 
102
207
  if (slash) {
103
- const slash_files = await readFile(slash.path);
104
- const validSlashCommands = slash_files
105
- .map((f) => require(f.path))
106
- .filter(
107
- (cmd) =>
108
- cmd.data &&
109
- (typeof cmd.run === "function" || typeof cmd.execute === "function")
110
- );
111
-
112
- client.slashCommands = new Map(
113
- validSlashCommands.map((cmd) => [cmd.data.name, cmd])
114
- );
115
- client.slashData = validSlashCommands.map((cmd) => cmd.data.toJSON());
116
-
117
- termenal.slash = validSlashCommands.length;
208
+ await loadSlash(client, slash.path);
118
209
  }
119
210
 
120
211
  //////////////////////////////////////////? Event Loader ////////////////////////////////////////////////////////
121
212
 
122
213
  if (events) {
123
- const event_files = await readFile(events.path);
124
- for (const file of event_files) {
125
- const event = require(file.path);
126
-
127
- if (!event.name || typeof event.run !== "function") continue;
128
-
129
- if (event.once) {
130
- client.once(event.name, (...args) => {
131
- if (typeof event.run === "function") {
132
- event.run(...args);
133
- } else if (typeof event.execute === "function") {
134
- event.execute(...args);
135
- }
136
- });
137
- } else {
138
- client.on(event.name, (...args) => {
139
- if (typeof event.run === "function") {
140
- event.run(...args, client);
141
- } else if (typeof event.execute === "function") {
142
- event.execute(...args, client);
143
- }
144
- });
145
- }
146
-
147
- termenal.events++;
148
- }
214
+ await loadEvents(client, events.path);
149
215
  }
150
216
 
151
217
  //////////////////////////////////////////* prefix run !////////////////////////////////////////////////////////
@@ -194,8 +260,7 @@ async function starter(client, options) {
194
260
  if (command.dmOnly && message.guild) return;
195
261
  if (
196
262
  command.devOnly &&
197
- client.ownerId &&
198
- message.author.id !== client.ownerId
263
+ message.author.id !== client.owner.id
199
264
  )
200
265
  return;
201
266
  if (
@@ -260,8 +325,7 @@ async function starter(client, options) {
260
325
 
261
326
  if (
262
327
  command.devOnly &&
263
- client.ownerId &&
264
- interaction.user.id !== client.ownerId
328
+ interaction.user.id !== client.owner.id
265
329
  ) {
266
330
  return interaction.reply({
267
331
  content: "`❌` هذا الأمر محصور لصاحب البوت فقط!",
@@ -350,10 +414,11 @@ async function starter(client, options) {
350
414
  }
351
415
 
352
416
  const { Wait, CreateBar, CreateRow, GetUser } = require("../function/function");
353
- const { addXP, UserLevel, leaderboard } = require("../function/level");
417
+ const { Level, addXP, UserLevel, leaderboard } = require("../function/level");
354
418
  const { log } = require("../function/log");
355
419
 
356
420
  const {
421
+ giveaway,
357
422
  Gstart,
358
423
  Gcheck,
359
424
  Greroll,
@@ -365,10 +430,14 @@ const {
365
430
  GremoveUser,
366
431
  GaddTime,
367
432
  GremoveTime,
433
+ Gdata
368
434
  } = require("../function/giveaway");
369
435
 
370
436
  module.exports = {
437
+ Level,
438
+ giveaway,
371
439
  starter,
440
+ reload,
372
441
  log,
373
442
  Wait,
374
443
  CreateBar,
@@ -388,4 +457,5 @@ module.exports = {
388
457
  GremoveUser,
389
458
  GaddTime,
390
459
  GremoveTime,
460
+ Gdata
391
461
  };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "djs-builder",
3
- "version": "0.6.37",
4
- "note": "🎉 Package Update! 🥏\n\n- Add Giveaway System 🎉 \n\n- 🛠 Fixes:\n- Minor bugs fixed\n- Improved stability and error handling\n\n🔗 Learn more on [NPM](https://www.npmjs.com/package/djs-builder)",
3
+ "version": "0.6.39",
4
+ "note": "🎉 Package Update! 🥏\n\n- 📚 Documentation: Added full guide for Giveaway System & Hot Reloading.\n- 🐛 Bug Fixes: Fixed critical issue in Giveaway winner selection.\n\n🔗 Learn more on [NPM](https://www.npmjs.com/package/djs-builder)",
5
5
  "description": "🎉 Package Update! 🥏",
6
6
  "main": "handler/starter.js",
7
7
  "dependencies": {