diff --git a/README.md b/README.md
index d43bf2fa..96d8feeb 100644
--- a/README.md
+++ b/README.md
@@ -21,7 +21,7 @@ Discord Giveaways is a powerful [Node.js](https://nodejs.org) module that allows
## Installation
-```js
+```bash
npm install --save discord-giveaways
```
@@ -59,7 +59,7 @@ const manager = new GiveawaysManager(client, {
client.giveawaysManager = manager;
client.on('ready', () => {
- console.log('I\'m ready!');
+ console.log('Bot is ready!');
});
client.login(process.env.DISCORD_BOT_TOKEN);
@@ -75,7 +75,6 @@ You can pass an options object to customize the giveaways. Here is a list of the
```js
client.on('interactionCreate', (interaction) => {
-
const ms = require('ms');
if (interaction.isCommand() && interaction.commandName === 'start') {
@@ -86,13 +85,15 @@ client.on('interactionCreate', (interaction) => {
const winnerCount = interaction.options.getInteger('winners');
const prize = interaction.options.getString('prize');
- client.giveawaysManager.start(interaction.channel, {
- duration: ms(duration),
- winnerCount,
- prize
- }).then((gData) => {
- console.log(gData); // {...} (messageId, end date and more)
- });
+ 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!
}
});
@@ -110,37 +111,42 @@ This allows you to start a new giveaway. Once the `start()` function is called,
#### ⚠ ATTENTION!
-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.
+
+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.
```js
-const giveaway =
-// Search with giveaway prize
-client.giveawaysManager.giveaways.find((g) => g.guildId === interaction.guildId && g.prize === interaction.options.getString('query')) ||
-// Search with messageId
-client.giveawaysManager.giveaways.find((g) => g.guildId === interaction.guildId && g.messageId === interaction.options.getString('query'));
+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.channel.send('Unable to find a giveaway for `'+ args.join(' ') +'`.');
+if (!giveaway) return interaction.reply(`Unable to find a giveaway for \`${query}\`.`);
```
### Reroll a giveaway
```js
client.on('interactionCreate', (interaction) => {
-
if (interaction.isCommand() && interaction.commandName === 'reroll') {
const messageId = interaction.options.getString('message_id');
- client.giveawaysManager.reroll(messageId).then(() => {
- interaction.channel.send('Success! Giveaway rerolled!');
- }).catch((err) => {
- interaction.channel.send(`An error has occurred, please check and try again.\n\`${err}\``);
- });
+ 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}\``);
+ });
}
});
```
- **options.winnerCount**: the number of winners to pick.
- **options.messages**: an object with the "congrat" and the "error" message. [Usage example](https://github.com/Androz2091/discord-giveaways#-translation).
+- **options.messages.replyWhenNoWinner**: Whether or not to send the "error" message when there is no winner.
@@ -150,18 +156,20 @@ client.on('interactionCreate', (interaction) => {
```js
client.on('interactionCreate', (interaction) => {
-
if (interaction.isCommand() && interaction.commandName === 'edit') {
const messageId = interaction.options.getString('message_id');
- client.giveawaysManager.edit(messageId, {
- addTime: 5000,
- newWinnerCount: 3,
- newPrize: 'New Prize!'
- }).then(() => {
- interaction.channel.send('Success! Giveaway updated!');
- }).catch((err) => {
- interaction.channel.send(`An error has occurred, please check and try again.\n\`${err}\``);
- });
+ 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}\``);
+ });
}
});
```
@@ -171,7 +179,7 @@ client.on('interactionCreate', (interaction) => {
- **options.addTime**: the number of milliseconds to add to the giveaway duration.
- **options.setEndTimestamp**: the timestamp of the new end date (for example, for the giveaway to be ended in 1 hour, set it to `Date.now() + 60000`).
- **options.newMessages**: the new giveaway messages. Will get merged with the existing object, if there.
-^^^ You can [access giveaway properties](https://github.com/Androz2091/discord-giveaways#access-giveaway-properties-in-messages).
+ ^^^ You can [access giveaway properties](https://github.com/Androz2091/discord-giveaways#access-giveaway-properties-in-messages).
- **options.newExtraData**: the new extra data value for the giveaway.
- **options.newBonusEntries**: the new BonusEntry objects (for example, to change the amount of entries).
- **options.newExemptMembers**: the new filter function to exempt members from winning the giveaway.
@@ -183,14 +191,16 @@ client.on('interactionCreate', (interaction) => {
```js
client.on('interactionCreate', (interaction) => {
-
if (interaction.isCommand() && interaction.commandName === 'delete') {
const messageId = interaction.options.getString('message_id');
- client.giveawaysManager.delete(messageId).then(() => {
- interaction.channel.send('Success! Giveaway deleted!');
- }).catch((err) => {
- interaction.channel.send(`An error has occurred, please check and try again.\n\`${err}\``);
- });
+ 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}\``);
+ });
}
});
```
@@ -203,32 +213,36 @@ client.on('interactionCreate', (interaction) => {
```js
client.on('interactionCreate', (interaction) => {
-
if (interaction.isCommand() && interaction.commandName === 'end') {
const messageId = interaction.options.getString('message_id');
- client.giveawaysManager.end(messageId).then(() => {
- interaction.channel.send('Success! Giveaway ended!');
- }).catch((err) => {
- interaction.channel.send(`An error has occurred, please check and try again.\n\`${err}\``);
- });
+ 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}\``);
+ });
}
});
```
-- **noWinnerMessage**: Sent in the channel if there is no valid winner for the giveaway. [Message Options](https://github.com/Androz2091/discord-giveaways#message-options)
+- **noWinnerMessage**: Sent in the channel if there is no valid winner for the giveaway. [Message Options](https://github.com/Androz2091/discord-giveaways#message-options)
### Pause a giveaway
```js
client.on('interactionCreate', (interaction) => {
-
if (interaction.isCommand() && interaction.commandName === 'pause') {
const messageId = interaction.options.getString('message_id');
- client.giveawaysManager.pause(messageId).then(() => {
- interaction.channel.send('Success! Giveaway paused!');
- }).catch((err) => {
- interaction.channel.send(`An error has occurred, please check and try again.\n\`${err}\``);
- });
+ 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}\``);
+ });
}
});
```
@@ -237,7 +251,7 @@ client.on('interactionCreate', (interaction) => {
- **options.unPauseAfter**: the number of milliseconds after which the giveaway will automatically unpause.
- **options.embedColor**: the color of the embed when the giveaway is paused.
- **options.infiniteDurationText**: The text that gets displayed next to `GiveawayMessages#drawing` in the paused embed, when there is no `unPauseAfter`.
-^^^ You can [access giveaway properties](https://github.com/Androz2091/discord-giveaways#access-giveaway-properties-in-messages).
+ ^^^ You can [access giveaway properties](https://github.com/Androz2091/discord-giveaways#access-giveaway-properties-in-messages).
⚠️ **Note**: the pause function overwrites/edits the [pauseOptions object property](https://github.com/Androz2091/discord-giveaways#pause-options) of a giveaway!
@@ -245,14 +259,16 @@ client.on('interactionCreate', (interaction) => {
```js
client.on('interactionCreate', (interaction) => {
-
if (interaction.isCommand() && interaction.commandName === 'unpause') {
const messageId = interaction.options.getString('message_id');
- client.giveawaysManager.unpause(messageId).then(() => {
- interaction.channel.send('Success! Giveaway unpaused!');
- }).catch((err) => {
- interaction.channel.send(`An error has occurred, please check and try again.\n\`${err}\``);
- });
+ 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}\``);
+ });
}
});
```
@@ -294,7 +310,7 @@ client.giveawaysManager.start(interaction.channel, {
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', `return !member.roles.cache.some((r) => r.name === \'${roleName}\')`),
+ exemptMembers: new Function('member', `return !member.roles.cache.some((r) => r.name === \'${roleName}\')`)
});
```
@@ -318,7 +334,7 @@ client.giveawaysManager.start(interaction.channel, {
- **lastChance.enabled**: if the last chance system is enabled.
- **lastChance.content**: the text of the embed when the last chance system is enabled.
-^^^ You can [access giveaway properties](https://github.com/Androz2091/discord-giveaways#access-giveaway-properties-in-messages).
+ ^^^ You can [access giveaway properties](https://github.com/Androz2091/discord-giveaways#access-giveaway-properties-in-messages).
- **lastChance.threshold**: the number of milliseconds before the giveaway ends when the last chance system will be enabled.
- **lastChance.embedColor**: the color of the embed when last chance is enabled.
@@ -345,11 +361,11 @@ client.giveawaysManager.start(interaction.channel, {
- **pauseOptions.isPaused**: if the giveaway is paused.
- **pauseOptions.content**: the text of the embed when the giveaway is paused.
-^^^ You can [access giveaway properties](https://github.com/Androz2091/discord-giveaways#access-giveaway-properties-in-messages).
+ ^^^ You can [access giveaway properties](https://github.com/Androz2091/discord-giveaways#access-giveaway-properties-in-messages).
- **pauseOptions.unPauseAfter**: the number of milliseconds, or a timestamp in milliseconds, after which the giveaway will automatically unpause.
- **pauseOptions.embedColor**: the color of the embed when the giveaway is paused.
- **pauseOptions.infiniteDurationText**: The text that gets displayed next to `GiveawayMessages#drawing` in the paused embed, when there is no `unPauseAfter`.
-^^^ You can [access giveaway properties](https://github.com/Androz2091/discord-giveaways#access-giveaway-properties-in-messages).
+ ^^^ You can [access giveaway properties](https://github.com/Androz2091/discord-giveaways#access-giveaway-properties-in-messages).
@@ -362,10 +378,10 @@ client.giveawaysManager.start(interaction.channel, {
duration: 60000,
winnerCount: 1,
prize: 'Free Steam Key',
- bonusEntries: [
+ bonusEntries: [
{
// Members who have the "Nitro Boost" role get 2 bonus entries
- bonus: (member) => member.roles.cache.some((r) => r.name === 'Nitro Boost') ? 2 : null,
+ bonus: (member) => (member.roles.cache.some((r) => r.name === 'Nitro Boost') ? 2 : null),
cumulative: false
}
]
@@ -386,10 +402,13 @@ client.giveawaysManager.start(interaction.channel, {
winnerCount: 1,
prize: 'Free Steam Key',
bonusEntries: [
- {
+ {
// Members who have the role which is assigned to "roleName" get the amount of bonus entries which is assigned to "roleBonusEntries"
- bonus: new Function('member', `return member.roles.cache.some((r) => r.name === \'${roleName}\') ? ${roleBonusEntries} : null`),
- cumulative: false
+ bonus: new Function(
+ 'member',
+ `return member.roles.cache.some((r) => r.name === \'${roleName}\') ? ${roleBonusEntries} : null`
+ ),
+ cumulative: false
}
]
});
@@ -422,13 +441,15 @@ message: {
You can access any giveaway property inside of giveaway messages with the format: `{this.}`.
For example:
+
```js
winMessage: 'Congratulations, {winners}! You won **{this.prize}**!\n{this.messageURL}'
```
-Also, you can write JavaScript code inside of the `{}`.
+Also, you can write JavaScript code inside of `{}`.
For example:
+
```js
winMessage: 'Congratulations, {winners}! You won **{this.prize.toUpperCase()}**!\n{this.messageURL}'
```
@@ -437,17 +458,17 @@ If you want to fill in strings that are not messages of a giveaway, or just cust
## 🇫🇷 Translation
-You can also pass a `messages` parameter for `start()` function, if you want to translate the bot text:
+You can also pass a `messages` parameter for the `start()` function, if you want to translate the giveaway texts:
- **options.messages.giveaway**: the message that will be displayed above the embeds.
- **options.messages.giveawayEnded**: the message that will be displayed above the embeds when the giveaway is ended.
- **options.messages.drawing**: the message that displays the drawing timestamp.
- **options.messages.dropMessage**: the message that will be displayed for drop giveaways.
- **options.messages.inviteToParticipate**: the message that invites users to participate.
-- **options.messages.winMessage**: the message that will be displayed to congratulate the winner(s) when the giveaway is ended.
-^^^ [Message options](https://github.com/Androz2091/discord-giveaways#message-options) are available in this message.
+- **options.messages.winMessage**: the message that will be displayed to congratulate the winner(s) when the giveaway is ended.
+ ^^^ [Message options](https://github.com/Androz2091/discord-giveaways#message-options) are available in this message.
- **options.messages.embedFooter**: the message displayed at the bottom of the main (not ended) embed.
-^^^ An empty string can be used for "deactivation", or [`iconURL` can be set](https://discord-giveaways.js.org/global.html#EmbedFooterObject).
+ ^^^ An empty string can be used for "deactivation", or [`iconURL` can be set](https://discord-giveaways.js.org/global.html#EmbedFooterObject).
- **options.messages.noWinner**: the message that is displayed if no winner can be drawn.
- **options.messages.hostedBy**: the message to display the host of the giveaway.
- **options.messages.winners**: simply the expression "Winner(s):" in your language.
@@ -475,7 +496,7 @@ client.giveawaysManager.start(interaction.channel, {
noWinner: 'Giveaway cancelled, no valid participations.',
hostedBy: 'Hosted by: {this.hostedBy}',
winners: 'Winner(s):',
- endedAt: 'Ended at',
+ endedAt: 'Ended at'
}
});
```
@@ -486,11 +507,11 @@ And for the `reroll()` function:
```js
client.giveawaysManager.reroll(messageId, {
- messages: {
- congrat: ':tada: New winner(s): {winners}! Congratulations, you won **{this.prize}**!\n{this.messageURL}',
- error: 'No valid participations, no new winner(s) can be chosen!'
- }
- });
+ messages: {
+ congrat: ':tada: New winner(s): {winners}! Congratulations, you won **{this.prize}**!\n{this.messageURL}',
+ error: 'No valid participations, no new winner(s) can be chosen!'
+ }
+});
```
- **options.messages.congrat**: the congratulatory message.
@@ -501,7 +522,9 @@ You can [access giveaway properties](https://github.com/Androz2091/discord-givea
## Custom Database
-You can use your custom database to save giveaways, instead of the json files (the "database" by default for `discord-giveaways`). For this, you will need to extend the `GiveawaysManager` class, and replace some methods with your custom ones. There are 4 methods you will need to replace:
+You can use your custom database to save giveaways, instead of the json files (the "database" by default for `discord-giveaways`).
+For this, you will need to extend the `GiveawaysManager` class, and replace some methods with your custom ones.
+There are 4 methods you will need to replace:
- `getAllGiveaways`: this method returns an array of stored giveaways.
- `saveGiveaway`: this method stores a new giveaway in the database.
@@ -511,16 +534,18 @@ You can use your custom database to save giveaways, instead of the json files (t
**⚠️ All the methods should be asynchronous to return a promise!**
**SQL examples**
-- [MySQL](https://github.com/Androz2091/discord-giveaways/blob/master/examples/custom-databases/mysql.js)
-- SQLite
- - [Quick.db](https://github.com/Androz2091/discord-giveaways/blob/master/examples/custom-databases/quick.db.js)
- - [Enmap](https://github.com/Androz2091/discord-giveaways/blob/master/examples/custom-databases/enmap.js)
+
+- [MySQL](https://github.com/Androz2091/discord-giveaways/blob/master/examples/custom-databases/mysql.js)
+- SQLite
+ - [Quick.db](https://github.com/Androz2091/discord-giveaways/blob/master/examples/custom-databases/quick.db.js)
+ - [Enmap](https://github.com/Androz2091/discord-giveaways/blob/master/examples/custom-databases/enmap.js)
**NoSQL examples**
-- MongoDB
- - [Mongoose](https://github.com/Androz2091/discord-giveaways/blob/master/examples/custom-databases/mongoose.js)
- - [QuickMongo](https://github.com/Androz2091/discord-giveaways/blob/master/examples/custom-databases/quickmongo.js) ⚠️ Not recommended for high giveaway usage, use the `mongoose` example instead
-- [Apache CouchDB - Nano](https://github.com/Androz2091/discord-giveaways/blob/master/examples/custom-databases/nano.js)
-- Replit Database ⚠️ Only usable if your bot is hosted on [Replit](https://replit.com/)
- - [@replit/database](https://github.com/Androz2091/discord-giveaways/blob/master/examples/custom-databases/replit.js)
- - [Quick.Replit](https://github.com/Androz2091/discord-giveaways/blob/master/examples/custom-databases/quick.replit.js)
\ No newline at end of file
+
+- MongoDB
+ - [Mongoose](https://github.com/Androz2091/discord-giveaways/blob/master/examples/custom-databases/mongoose.js)
+ - [QuickMongo](https://github.com/Androz2091/discord-giveaways/blob/master/examples/custom-databases/quickmongo.js) ⚠️ Not recommended for high giveaway usage, use the `mongoose` example instead
+- [Apache CouchDB - Nano](https://github.com/Androz2091/discord-giveaways/blob/master/examples/custom-databases/nano.js)
+- Replit Database ⚠️ Only usable if your bot is hosted on [Replit](https://replit.com/)
+ - [@replit/database](https://github.com/Androz2091/discord-giveaways/blob/master/examples/custom-databases/replit.js)
+ - [Quick.Replit](https://github.com/Androz2091/discord-giveaways/blob/master/examples/custom-databases/quick.replit.js)
diff --git a/src/Constants.js b/src/Constants.js
index 13f6eb41..dd531f5c 100644
--- a/src/Constants.js
+++ b/src/Constants.js
@@ -164,12 +164,14 @@ exports.GiveawaysManagerOptions = {
* @property {Object} [messages] The messages used in this method.
* @property {string|MessageObject} [messages.congrat=':tada: New winner(s): {winners}! Congratulations, you won **{this.prize}**!\n{this.messageURL}'] The message used if there are new winners.
* @property {string|MessageObject} [messages.error='No valid participations, no new winner(s) can be chosen!'] The message used if no new winner(s) could be chosen.
+ * @property {boolean} [messages.replyWhenNoWinner=true] Whether or not to send the "error" message when there is no winner.
*/
exports.GiveawayRerollOptions = {
winnerCount: null,
messages: {
congrat: ':tada: New winner(s): {winners}! Congratulations, you won **{this.prize}**!\n{this.messageURL}',
- error: 'No valid participations, no new winner(s) can be chosen!'
+ error: 'No valid participations, no new winner(s) can be chosen!',
+ replyWhenNoWinner: true
}
};
diff --git a/src/Giveaway.js b/src/Giveaway.js
index bd650d0c..a8e03bb3 100644
--- a/src/Giveaway.js
+++ b/src/Giveaway.js
@@ -962,18 +962,22 @@ class Giveaway extends EventEmitter {
}
resolve(winners);
} else {
- const embed = this.fillInEmbed(options.messages.error.embed);
- channel.send({
- content: this.fillInString(options.messages.error.content || options.messages.error),
- embeds: embed ? [embed] : null,
- components: this.fillInComponents(options.messages.error.components),
- allowedMentions: this.allowedMentions,
- reply: {
- messageReference:
- typeof options.messages.error.replyToGiveaway === 'boolean' ? this.messageId : undefined,
- failIfNotExists: false
- }
- });
+ if (options.messages.replyWhenNoWinner !== false) {
+ const embed = this.fillInEmbed(options.messages.error.embed);
+ channel.send({
+ content: this.fillInString(options.messages.error.content || options.messages.error),
+ embeds: embed ? [embed] : null,
+ components: this.fillInComponents(options.messages.error.components),
+ allowedMentions: this.allowedMentions,
+ reply: {
+ messageReference:
+ typeof options.messages.error.replyToGiveaway === 'boolean'
+ ? this.messageId
+ : undefined,
+ failIfNotExists: false
+ }
+ });
+ }
resolve([]);
}
});
diff --git a/typings/index.d.ts b/typings/index.d.ts
index ba58849b..e85d5309 100644
--- a/typings/index.d.ts
+++ b/typings/index.d.ts
@@ -214,6 +214,7 @@ export interface GiveawayRerollOptions {
messages?: {
congrat?: string | MessageObject;
error?: string | MessageObject;
+ replyWhenNoWinner?: boolean;
};
}
export interface GiveawayData {