Discord Giveaways is a powerful Node.js module that allows you to easily create giveaways!
npm install --save discord-giveaways
You can read this example bot on GitHub: discord-giveaways-bot
Required Discord Intents: Guilds and GuildMessageReactions.
Optional Discord Privileged Intent for better performance: GuildMembers.
const Discord = require('discord.js');
const client = new Discord.Client({
intents: [
Discord.IntentsBitField.Flags.Guilds,
Discord.IntentsBitField.Flags.GuildMessageReactions,
Discord.IntentsBitField.Flags.GuildMembers // Optional, for better performance
]
});
// Requires Manager from discord-giveaways
const { GiveawaysManager } = require('discord-giveaways');
const manager = new GiveawaysManager(client, {
storage: './giveaways.json',
default: {
botsCanWin: false,
embedColor: '#FF0000',
embedColorEnd: '#000000',
reaction: '🎉'
}
});
// We now have a giveawaysManager property to access the manager everywhere!
client.giveawaysManager = manager;
client.on('ready', () => {
console.log('Bot is ready!');
});
client.login(process.env.DISCORD_BOT_TOKEN);
After that, giveaways that are not yet completed will start to be updated again and new giveaways can be started. You can pass an options object to customize the giveaways. Here is a list of them:
client.on('interactionCreate', (interaction) => {
const ms = require('ms');
if (interaction.isChatInputCommand() && interaction.commandName === 'start') {
// /start 2d 1 Awesome prize!
// Will create a giveaway with a duration of two days, with one winner and the prize will be "Awesome prize!"
const duration = interaction.options.getString('duration');
const winnerCount = interaction.options.getInteger('winners');
const prize = interaction.options.getString('prize');
client.giveawaysManager
.start(interaction.channel, {
duration: ms(duration),
winnerCount,
prize
})
.then((data) => {
console.log(data); // {...} (messageId, end date and more)
});
// And the giveaway has started!
}
});
This allows you to start a new giveaway. Once the start() function is called, the giveaway starts, and you only have to observe the result, the package does the rest!
The command examples below (reroll, edit delete, end) can be executed on any server your bot is a member of if a person has the prize or the messageId of a giveaway. To prevent abuse we recommend to check if the prize or the messageId that was provided by the command user is for a giveaway on the same server, if it is not, then cancel the command execution.
const query = interaction.options.getString('query');
const giveaway =
// Search with giveaway prize
client.giveawaysManager.giveaways.find((g) => g.guildId === interaction.guildId && g.prize === query) ||
// Search with messageId
client.giveawaysManager.giveaways.find((g) => g.guildId === interaction.guildId && g.messageId === query);
// If no giveaway was found
if (!giveaway) return interaction.reply(`Unable to find a giveaway for \`${query}\`.`);
client.on('interactionCreate', (interaction) => {
if (interaction.isChatInputCommand() && interaction.commandName === 'reroll') {
const messageId = interaction.options.getString('message_id');
client.giveawaysManager
.reroll(messageId)
.then(() => {
interaction.reply('Success! Giveaway rerolled!');
})
.catch((err) => {
interaction.reply(`An error has occurred, please check and try again.\n\`${err}\``);
});
}
});
client.on('interactionCreate', (interaction) => {
if (interaction.isChatInputCommand() && interaction.commandName === 'edit') {
const messageId = interaction.options.getString('message_id');
client.giveawaysManager
.edit(messageId, {
addTime: 5000,
newWinnerCount: 3,
newPrize: 'New Prize!'
})
.then(() => {
interaction.reply('Success! Giveaway updated!');
})
.catch((err) => {
interaction.reply(`An error has occurred, please check and try again.\n\`${err}\``);
});
}
});
Date.now() + 60000).Note: to reduce giveaway duration, define addTime with a negative number! For example addTime: -5000 will reduce giveaway duration by 5 seconds!
client.on('interactionCreate', (interaction) => {
if (interaction.isChatInputCommand() && interaction.commandName === 'delete') {
const messageId = interaction.options.getString('message_id');
client.giveawaysManager
.delete(messageId)
.then(() => {
interaction.reply('Success! Giveaway deleted!');
})
.catch((err) => {
interaction.reply(`An error has occurred, please check and try again.\n\`${err}\``);
});
}
});
⚠️ Note: when you use the delete function, the giveaway data and the message of the giveaway are deleted (by default). You cannot restore a giveaway once you have deleted it!
client.on('interactionCreate', (interaction) => {
if (interaction.isChatInputCommand() && interaction.commandName === 'end') {
const messageId = interaction.options.getString('message_id');
client.giveawaysManager
.end(messageId)
.then(() => {
interaction.reply('Success! Giveaway ended!');
})
.catch((err) => {
interaction.reply(`An error has occurred, please check and try again.\n\`${err}\``);
});
}
});
client.on('interactionCreate', (interaction) => {
if (interaction.isChatInputCommand() && interaction.commandName === 'pause') {
const messageId = interaction.options.getString('message_id');
client.giveawaysManager
.pause(messageId)
.then(() => {
interaction.reply('Success! Giveaway paused!');
})
.catch((err) => {
interaction.reply(`An error has occurred, please check and try again.\n\`${err}\``);
});
}
});
GiveawayMessages#drawing in the paused embed, when there is no unpauseAfter.⚠️ Note: the pause function overwrites/edits the pauseOptions object property of a giveaway!
client.on('interactionCreate', (interaction) => {
if (interaction.isChatInputCommand() && interaction.commandName === 'unpause') {
const messageId = interaction.options.getString('message_id');
client.giveawaysManager
.unpause(messageId)
.then(() => {
interaction.reply('Success! Giveaway unpaused!');
})
.catch((err) => {
interaction.reply(`An error has occurred, please check and try again.\n\`${err}\``);
});
}
});
// A list of all the giveaways
const allGiveaways = client.giveawaysManager.giveaways; // [ {Giveaway}, {Giveaway} ]
// A list of all the giveaways on the server with Id "1909282092"
const onServer = client.giveawaysManager.giveaways.filter((g) => g.guildId === '1909282092');
// A list of the current active giveaways (not ended)
const notEnded = client.giveawaysManager.giveaways.filter((g) => !g.ended);
Function to filter members. If true is returned, the member will not be able to win the giveaway.
client.giveawaysManager.start(interaction.channel, {
duration: 60000,
winnerCount: 1,
prize: 'Free Steam Key',
// Only members who have the "Nitro Boost" role are able to win
exemptMembers: (member, giveaway) => !member.roles.cache.some((r) => r.name === 'Nitro Boost')
});
Note (only for proficients): if you want to use values of global variables inside of the function without using giveaway.extraData, you can use the Function constructor:
const roleName = 'Nitro Boost';
client.giveawaysManager.start(interaction.channel, {
duration: 60000,
winnerCount: 1,
prize: 'Free Steam Key',
// Only members who have the the role which is assigned to "roleName" are able to win
exemptMembers: new Function(
'member',
'giveaway',
`return !member.roles.cache.some((r) => r.name === '${roleName}')`
)
});
⚠ Note
this, instead of the giveaway parameter, inside of the function string to access anything of the giveaway instance.this.extraData, or this.client.giveaway.extraData for storing variables.```js client.giveawaysManager.start(interaction.channel, { duration: 60000, winnerCount: 1, prize: 'Discord Nitro!', lastChance: { enabled: true
$ claude mcp add discord-giveaways \
-- python -m otcore.mcp_server <graph>