ertu-giveaways
v3.5.9
Published
A powerful and customizable giveaway system built for Discord.js v14
Maintainers
Readme
ertu-giveaways
A powerful and customizable giveaway system built for Discord.js v14.
Features
- 🎉 Start, end, pause, unpause, edit, and reroll giveaways
- 🎁 Drop giveaways (first click wins)
- 🏆 Bonus entries support
- 🔒 Exempt members or permissions from entering
- 🌍 Multi-language support (English, Turkish, French, Spanish, Portuguese, German)
- 💾 JSON-based persistent storage (easily replaceable with a database)
- 🎨 Fully customizable container colors and button styles
- ⏳ Last-chance mode with custom color and message
- ⏸️ Pause & resume giveaways
- 📋 Paginated participant list with alphabetical or chronological sorting
Requirements
- Node.js
v16.9.0or higher discord.jsv14
Installation
npm install ertu-giveawaysNote:
discord.jsmust also be installed in your project.npm install discord.js
Getting Started
Basic Setup
const { Client, GatewayIntentBits } = require('discord.js');
const { GiveawaysManager } = require('ertu-giveaways');
const client = new Client({
intents: [
GatewayIntentBits.Guilds,
GatewayIntentBits.GuildMessages,
GatewayIntentBits.GuildMembers,
]
});
const manager = new GiveawaysManager(client, {
storage: './giveaways.json',
default: {
containerColor: '#FF0000',
containerColorEnd: '#000000',
buttonEmoji: '🎉',
}
});
client.giveawaysManager = manager;
client.once('ready', () => {
console.log(`Logged in as ${client.user.tag}`);
});
client.login('YOUR_BOT_TOKEN');Manager Options
| Option | Type | Default | Description |
|---|---|---|---|
| storage | string | ./giveaways.json | Path to the JSON file where giveaways are stored |
| forceUpdateEvery | number \| null | null | Interval (ms) to force-check giveaways. Defaults to 10 seconds |
| endedGiveawaysLifetime | number \| null | null | How long (ms) to keep ended giveaways in storage before deleting |
| language | string | en | Language for giveaway messages. Supported: en, tr, fr, es, pt, de |
| default.containerColor | ColorResolvable | #FF0000 | Default container accent color while giveaway is active |
| default.containerColorEnd | ColorResolvable | #000000 | Default container accent color when giveaway ends |
| default.buttonEmoji | string | 🎉 | Emoji shown on the join button |
| default.buttonStyle | ButtonStyle | Secondary | Style of the join button |
| default.exemptPermissions | PermissionResolvable[] | [] | Members with these permissions cannot enter giveaways |
| default.exemptMembers | Function | () => false | A function to determine if a member should be excluded |
| default.lastChance | LastChanceOptions | See below | Last-chance configuration |
Starting a Giveaway
const channel = client.channels.cache.get('CHANNEL_ID');
client.giveawaysManager.start(channel, {
duration: 60000, // 60 seconds
winnerCount: 1,
prize: 'Discord Nitro',
hostedBy: interaction.user,
});Start Options
| Option | Type | Required | Description |
|---|---|---|---|
| duration | number | ✅ | Duration of the giveaway in milliseconds |
| winnerCount | number | ✅ | Number of winners |
| prize | string | ✅ | Prize name |
| hostedBy | User | ❌ | The user who is hosting the giveaway |
| containerColor | ColorResolvable | ❌ | Accent color for the active giveaway container |
| containerColorEnd | ColorResolvable | ❌ | Accent color after the giveaway ends |
| thumbnail | string | ❌ | URL of a thumbnail image shown in the giveaway |
| image | string | ❌ | URL of an image shown in the giveaway |
| exemptPermissions | PermissionResolvable[] | ❌ | Permissions that block entry |
| exemptMembers | Function | ❌ | Custom function to exclude specific members |
| bonusEntries | BonusEntry[] | ❌ | Array of bonus entry rules |
| lastChance | LastChanceOptions | ❌ | Last-chance configuration |
| pauseOptions | PauseOptions | ❌ | Pause configuration |
| isDrop | boolean | ❌ | If true, the first person to click wins immediately |
| extraData | any | ❌ | Any extra data you want to store with the giveaway |
| allowedMentions | MessageMentionOptions | ❌ | Controls which mentions are allowed in giveaway messages |
Ending a Giveaway
client.giveawaysManager.end('MESSAGE_ID');
// With a custom no-winner message
client.giveawaysManager.end('MESSAGE_ID', 'No valid participants!');Rerolling a Giveaway
client.giveawaysManager.reroll('MESSAGE_ID', {
winnerCount: 2,
messages: {
congrat: '🎉 New winners: {winners}! You won **{this.prize}**!',
error: 'No valid participants to reroll!',
replyWhenNoWinner: true,
}
});Editing a Giveaway
client.giveawaysManager.edit('MESSAGE_ID', {
newPrize: 'Steam Gift Card',
newWinnerCount: 3,
addTime: 30000, // add 30 seconds
setEndTimestamp: Date.now() + 300000, // or set a specific end time
newThumbnail: 'https://example.com/image.png',
newLastChance: { enabled: true, threshold: 5000, containerColor: '#FF0000' },
});Deleting a Giveaway
// Delete the giveaway and its message
client.giveawaysManager.delete('MESSAGE_ID');
// Delete only from storage (keep the Discord message)
client.giveawaysManager.delete('MESSAGE_ID', true);Pausing & Resuming
// Pause
client.giveawaysManager.pause('MESSAGE_ID', {
content: '⏸️ This giveaway is paused.',
containerColor: '#FFFF00',
});
// Resume
client.giveawaysManager.unpause('MESSAGE_ID');Bonus Entries
Bonus entries allow specific members to get additional chances to win.
client.giveawaysManager.start(channel, {
duration: 60000,
winnerCount: 1,
prize: 'Nitro',
bonusEntries: [
{
// Members with the MANAGE_MESSAGES permission get +2 entries
bonus: (member) => member.permissions.has('ManageMessages') ? 2 : 0,
cumulative: false,
}
]
});Exempt Members
Prevent specific members from entering a giveaway.
client.giveawaysManager.start(channel, {
duration: 60000,
winnerCount: 1,
prize: 'Nitro',
exemptMembers: (member) => member.roles.cache.has('ROLE_ID'), // excluded if they have this role
});Last Chance Mode
When the remaining time drops below the threshold, the container color changes to signal urgency.
client.giveawaysManager.start(channel, {
duration: 60000,
winnerCount: 1,
prize: 'Nitro',
lastChance: {
enabled: true,
threshold: 10000, // activate when 10 seconds remain
containerColor: '#FF6600',
content: '⚠️ Last chance to enter!',
}
});Drop Giveaways
The first person to click the button wins immediately.
client.giveawaysManager.start(channel, {
duration: 60000,
winnerCount: 1,
prize: 'Nitro',
isDrop: true,
});Events
Listen to giveaway events on the manager.
// Fired when a giveaway ends
manager.on('giveawayEnded', (giveaway, winners) => {
console.log(`Giveaway ended! Winners: ${winners.map(w => w.user.tag).join(', ')}`);
});
// Fired when a user joins a giveaway
manager.on('giveawayJoined', (giveaway, member, interaction) => {
console.log(`${member.user.tag} joined the giveaway for ${giveaway.prize}`);
});
// Fired when a user leaves a giveaway
manager.on('giveawayLeaved', (giveaway, member, interaction) => {
console.log(`${member.user.tag} left the giveaway`);
});
// Fired when a giveaway is rerolled
manager.on('giveawayRerolled', (giveaway, winners) => {
console.log(`Giveaway rerolled! New winners: ${winners.map(w => w.user.tag).join(', ')}`);
});
// Fired when a giveaway is deleted
manager.on('giveawayDeleted', (giveaway) => {
console.log(`Giveaway for ${giveaway.prize} was deleted`);
});Multi-Language Support
Set the language when creating the manager:
const manager = new GiveawaysManager(client, {
language: 'tr', // Turkish
default: { ... }
});Supported languages:
| Code | Language |
|---|---|
| en | English |
| tr | Turkish |
| fr | French |
| es | Spanish |
| pt | Portuguese |
| de | German |
Giveaway Properties
Once a giveaway is started, you can access these properties:
| Property | Type | Description |
|---|---|---|
| prize | string | The prize name |
| winnerCount | number | Number of winners |
| winnerIds | string[] | IDs of the winners (after end) |
| participants | string[] | IDs of all participants |
| startAt | number | Start timestamp (ms) |
| endAt | number | End timestamp (ms) |
| ended | boolean | Whether the giveaway has ended |
| remainingTime | number | Milliseconds remaining |
| duration | number | Total duration in ms |
| messageURL | string | Direct link to the giveaway message |
| isDrop | boolean | Whether it's a drop giveaway |
| hostedBy | string | Mention string of the host |
| extraData | any | Custom data attached to the giveaway |
Links
License
GPL-3.0 © Ertuğrul 'Ertu' Karahanlı
