-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathindex.js
More file actions
112 lines (93 loc) · 3.98 KB
/
Copy pathindex.js
File metadata and controls
112 lines (93 loc) · 3.98 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
const cron = require("node-cron");
const { ActionRowBuilder, ButtonBuilder, ButtonStyle, EmbedBuilder } = require("discord.js");
const { createGiveawayCommand, pickWinners } = require("./commands/giveaway");
const giveawaySchema = require("./models/giveaway");
async function load(ctx) {
const GiveawayModel = ctx.defineModel("giveaway", giveawaySchema);
// Correctly require the command factory function
const giveawayCommand = createGiveawayCommand(GiveawayModel);
ctx.registerCommand(giveawayCommand);
// Button interaction handler for entering giveaways
ctx.registerEvent("interactionCreate", async (interaction, client) => {
if (!interaction.isButton() || interaction.customId !== "giveaway_enter") return;
const giveaway = await GiveawayModel.findOne({
guildId: interaction.guildId,
messageId: interaction.message.id,
ended: false,
});
if (!giveaway) {
return interaction.reply({ content: "This giveaway is over.", ephemeral: true });
}
// Role check
if (giveaway.requiredRole) {
const member = await interaction.guild.members.fetch(interaction.user.id).catch(() => null);
if (!member || !member.roles.cache.has(giveaway.requiredRole)) {
return interaction.reply({
content: `You need the <@&${giveaway.requiredRole}> role to enter.`,
ephemeral: true,
});
}
}
// Account age check (disabled by default)
if (giveaway.minAccountAge > 0) {
const age = (Date.now() - interaction.user.createdAt.getTime()) / 86400000;
if (age < giveaway.minAccountAge) {
return interaction.reply({
content: `Your account must be at least ${giveaway.minAccountAge} days old.`,
ephemeral: true,
});
}
}
if (giveaway.entrants.includes(interaction.user.id)) {
giveaway.entrants = giveaway.entrants.filter((id) => id !== interaction.user.id);
await giveaway.save();
return interaction.reply({ content: "You left the giveaway.", ephemeral: true });
}
giveaway.entrants.push(interaction.user.id);
await giveaway.save();
await interaction.reply({ content: "You entered the giveaway! 🎉", ephemeral: true });
});
// Check every 30s for ended giveaways
const task = cron.schedule("*/30 * * * * *", async () => {
const due = await GiveawayModel.find({
ended: false,
endsAt: { $lte: new Date() },
}).limit(20);
for (const giveaway of due) {
try {
await pickWinners(giveaway, ctx.client);
await giveaway.save();
const channel = await ctx.client.channels.fetch(giveaway.channelId).catch(() => null);
if (!channel) continue;
const msg = await channel.messages.fetch(giveaway.messageId).catch(() => null);
const winText =
giveaway.winners.length > 0
? `Congratulations ${giveaway.winners.map((id) => `<@${id}>`).join(", ")}! You won **${giveaway.prize}**!`
: "No eligible entrants.";
// Edit the original message
if (msg) {
const endedEmbed = EmbedBuilder.from(msg.embeds[0] || {})
.setColor(0x57f287)
.setFooter({ text: "Giveaway ended" });
const disabledRow = new ActionRowBuilder().addComponents(
new ButtonBuilder()
.setCustomId("giveaway_enter_disabled")
.setLabel("🎉 Ended")
.setStyle(ButtonStyle.Secondary)
.setDisabled(true)
);
await msg.edit({ embeds: [endedEmbed], components: [disabledRow] }).catch(() => {});
}
await channel.send(winText);
ctx.logger.info(`Giveaway "${giveaway.prize}" ended with ${giveaway.winners.length} winner(s)`);
} catch (error) {
ctx.logger.error(`Failed to end giveaway ${giveaway._id}`, error);
}
}
});
ctx.hooks.on("onPluginUnload", async ({ pluginName }) => {
if (pluginName === "adb-plugin-giveaways") task.stop();
});
ctx.logger.info("Giveaways plugin loaded");
}
module.exports = { load };