djs-builder 0.6.36 → 0.6.38

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,11 +1544,6 @@ const endTimeMs = Date.now() + durationMs;
1535
1544
  giveaways.length
1536
1545
  } found)`;
1537
1546
 
1538
-
1539
- giveaways.forEach((g) => {
1540
- Gdelete(g.messageId);
1541
- })
1542
-
1543
1547
  if (listContent.length <= MAX_MESSAGE_LENGTH) {
1544
1548
  // Output as a simple message (Under 2000 chars)
1545
1549
  return interaction.editReply({
@@ -1659,69 +1663,77 @@ const endTimeMs = Date.now() + durationMs;
1659
1663
  } else if (command === "data") {
1660
1664
  const id = interaction.options.getString("id");
1661
1665
  console.log(id);
1662
- const data = await Gdata(id);
1663
- if (data?.error)
1666
+ const data = await Gdata(id);
1667
+ if (data?.error)
1664
1668
  return interaction.editReply(`❌ **Error:** ${data.error}`);
1665
1669
 
1666
-
1667
- const giveawayEmbed = new EmbedBuilder()
1670
+ const giveawayEmbed = new EmbedBuilder()
1668
1671
  .setTitle(`📊 Giveaway Data: ${id}`)
1669
- .setColor(data.ended ? 0xFF0000 : data.paused ? 0xFFC0CB : 0x00FF00)
1670
- .setDescription(`**Jump to Message 🔗 ** : ${data.messageId ? `https://discord.com/channels/${data.guildId}/${data.channelId}/${data.messageId}` : 'N/A'}`)
1671
-
1672
-
1673
-
1674
- giveawayEmbed.addFields(
1675
- {
1676
- name: "✨ Status",
1677
- value: data.ended ? "ENDED 🛑" : data.paused ? "PAUSED ⏸️" : "ACTIVE ✅",
1678
- 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,
1679
1690
  },
1680
- {
1681
- name: "🏆 Winners",
1682
- value: data.winwesNumber.toString(),
1683
- inline: true
1691
+ {
1692
+ name: "🏆 Winners",
1693
+ value: data.winwesNumber.toString(),
1694
+ inline: true,
1684
1695
  },
1685
- {
1686
- name: "🙋‍♂️ Hoster",
1687
- value: `<@${data.hoster}>`,
1688
- inline: true
1696
+ {
1697
+ name: "🙋‍♂️ Hoster",
1698
+ value: `<@${data.hoster}>`,
1699
+ inline: true,
1689
1700
  },
1690
-
1691
- {
1692
- name: "⏳ Ends In",
1693
- value: `<t:${Math.floor(data.endTime / 1000)}:R>`,
1694
- inline: true
1701
+
1702
+ {
1703
+ name: "⏳ Ends In",
1704
+ value: `<t:${Math.floor(data.endTime / 1000)}:R>`,
1705
+ inline: true,
1695
1706
  },
1696
- {
1697
- name: "🎟️ Entries",
1698
- value: data.reaction === "button" ? data.users.length.toString() : "N/A (Reaction Type)",
1699
- 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,
1700
1714
  },
1701
- {
1702
- name: "🖱️ Entry Type",
1703
- value: data.reaction.toUpperCase(),
1704
- inline: true
1715
+ {
1716
+ name: "🖱️ Entry Type",
1717
+ value: data.reaction.toUpperCase(),
1718
+ inline: true,
1705
1719
  }
1706
- );
1720
+ );
1707
1721
 
1708
-
1709
- if (data.ended && data.winers.length > 0) {
1722
+ if (data.ended && data.winers.length > 0) {
1710
1723
  giveawayEmbed.addFields({
1711
- name: "🏅 Past Winners",
1712
- value: data.winers.map(u => `<@${u}>`).join(', ') || "N/A",
1713
- inline: false
1724
+ name: "🏅 Past Winners",
1725
+ value: data.winers.map((u) => `<@${u}>`).join(", ") || "N/A",
1726
+ inline: false,
1714
1727
  });
1715
- }
1728
+ }
1716
1729
 
1717
- return interaction.editReply({
1718
- embeds: [giveawayEmbed],
1719
- content: `Data retrieved for giveaway \`${id}\`.`
1720
- });
1721
- }
1730
+ return interaction.editReply({
1731
+ embeds: [giveawayEmbed],
1732
+ content: `Data retrieved for giveaway \`${id}\`.`,
1733
+ });
1734
+ }
1722
1735
  },
1723
1736
  };
1724
-
1725
1737
  ```
1726
1738
 
1727
1739
  ---
@@ -1758,6 +1770,77 @@ const endTimeMs = Date.now() + durationMs;
1758
1770
 
1759
1771
  </details>
1760
1772
 
1773
+ ---
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.setName("type")
1805
+ .setDescription("What to reload?")
1806
+ .setRequired(true)
1807
+ .addChoices(
1808
+ { name: "Prefix Commands", value: "prefix" },
1809
+ { name: "Slash Commands", value: "slash" },
1810
+ { name: "Events", value: "events" },
1811
+ { name: "All", value: "all" }
1812
+ )
1813
+ ),
1814
+ async run(interaction, client) {
1815
+ // Check for owner permission (Recommended)
1816
+ if (interaction.user.id !== client.ownerId) {
1817
+ return interaction.reply({ content: "❌ Only the bot owner can use this!", ephemeral: true });
1818
+ }
1819
+
1820
+ const type = interaction.options.getString("type");
1821
+
1822
+ try {
1823
+ await interaction.deferReply();
1824
+ await reload(client, type);
1825
+ await interaction.editReply(`✅ Successfully reloaded **${type}**! 🚀`);
1826
+ } catch (error) {
1827
+ console.error(error);
1828
+ await interaction.editReply("❌ Failed to reload. Check console for errors.");
1829
+ }
1830
+ }
1831
+ };
1832
+ ```
1833
+
1834
+ ---
1835
+
1836
+ ### 💡 Notes
1837
+
1838
+ - **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.
1839
+ - **Events**: Old event listeners are automatically removed before adding new ones to prevent duplicates.
1840
+
1841
+ </details>
1842
+
1843
+
1761
1844
  ---
1762
1845
 
1763
1846
  ## ⚡ Commands & Events
@@ -53,6 +53,7 @@ async function Gstart({
53
53
  emoji: emoji = false,
54
54
  label: label = false,
55
55
  style: style = false,
56
+ id : id = false
56
57
  },
57
58
  }) {
58
59
  if (!winers) winers = 1;
@@ -67,7 +68,7 @@ async function Gstart({
67
68
  row = CreateRow([
68
69
  [
69
70
  {
70
- id: "djs-builder-giveaway",
71
+ id: id || "djs-builder-giveaway",
71
72
  style: style || 1,
72
73
  label: label,
73
74
  emoji: emoji,
@@ -203,7 +204,7 @@ async function giveaway_end(client, g, type) {
203
204
  return;
204
205
  }
205
206
 
206
- const winners = pickWinners(users_id, g.winersNumber);
207
+ const winners = pickWinners(users_id, g.winwesNumber);
207
208
 
208
209
  await message.edit({
209
210
  embeds: [g.endEmbed],
@@ -212,7 +213,7 @@ async function giveaway_end(client, g, type) {
212
213
  await message.reply({
213
214
  content: `🎉 **Giveaway Ended!**\n> Winner(s):\n- <@${winners
214
215
  .map((u) => `${u}`)
215
- .join(">\n- <@")}>`,
216
+ .join(">, <@")}>`,
216
217
  });
217
218
 
218
219
  await giveaway.findOneAndUpdate(
@@ -254,12 +255,12 @@ async function Greroll(client, messageId) {
254
255
  );
255
256
  }
256
257
 
257
- const winners = pickWinners(users_id, g.winersNumber);
258
+ const winners = pickWinners(users_id, g.winwesNumber);
258
259
 
259
260
  await message.reply({
260
- content: `🔄️ **Giveaway Reroll!**\n> Winners:\n- <@${winners
261
+ content: `🔄️ **Giveaway Reroll!**\n> Winner(s):\n- <@${winners
261
262
  .map((u) => `${u}`)
262
- .join(">\n- <@")}>`,
263
+ .join(">, <@")}>`,
263
264
  });
264
265
 
265
266
  let new_endType;
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 !////////////////////////////////////////////////////////
@@ -350,10 +416,11 @@ async function starter(client, options) {
350
416
  }
351
417
 
352
418
  const { Wait, CreateBar, CreateRow, GetUser } = require("../function/function");
353
- const { addXP, UserLevel, leaderboard } = require("../function/level");
419
+ const { Level, addXP, UserLevel, leaderboard } = require("../function/level");
354
420
  const { log } = require("../function/log");
355
421
 
356
422
  const {
423
+ giveaway,
357
424
  Gstart,
358
425
  Gcheck,
359
426
  Greroll,
@@ -365,10 +432,14 @@ const {
365
432
  GremoveUser,
366
433
  GaddTime,
367
434
  GremoveTime,
435
+ Gdata
368
436
  } = require("../function/giveaway");
369
437
 
370
438
  module.exports = {
439
+ Level,
440
+ giveaway,
371
441
  starter,
442
+ reload,
372
443
  log,
373
444
  Wait,
374
445
  CreateBar,
@@ -388,4 +459,5 @@ module.exports = {
388
459
  GremoveUser,
389
460
  GaddTime,
390
461
  GremoveTime,
462
+ Gdata
391
463
  };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "djs-builder",
3
- "version": "0.6.36",
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.38",
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": {