Security News
New Python Packaging Proposal Aims to Solve Phantom Dependency Problem with SBOMs
PEP 770 proposes adding SBOM support to Python packages to improve transparency and catch hidden non-Python dependencies that security tools often miss.
discord-giveaways-v13
Advanced tools
This package functions just like the normal discord-giveaways, but it only works on discord.js v13! So you can use it if you are using discord.js v13.
Discord Giveaways is a powerful Node.js module that allows you to easily create giveaways!
if you need support, Join Our Support Server
npm install --save discord-giveaways-v13
You can read this example bot on GitHub: giveaways-bot
const Discord = require('discord.js'),
client = new Discord.Client(),
settings = {
prefix: 'g!',
token: 'Your Discord Bot Token'
};
// Requires Manager from discord-giveaways-v13
const { GiveawaysManager } = require('discord-giveaways-v13');
// Starts updating currents giveaways
const manager = new GiveawaysManager(client, {
storage: './giveaways.json',
updateCountdownEvery: 10000,
hasGuildMembersIntent: false,
default: {
botsCanWin: false,
exemptPermissions: ['MANAGE_MESSAGES', 'ADMINISTRATOR'],
embedColor: '#FF0000',
embedColorEnd: '#000000',
reaction: '🎉'
}
});
// We now have a giveawaysManager property to access the manager everywhere!
client.giveawaysManager = manager;
client.on('ready', () => {
console.log('I\'m ready!');
});
client.login(settings.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('message', (message) => {
const ms = require('ms'); // npm install ms
const args = message.content.slice(settings.prefix.length).trim().split(/ +/g);
const command = args.shift().toLowerCase();
if (command === 'start-giveaway') {
// g!start-giveaway 2d 1 Awesome prize!
// Will create a giveaway with a duration of two days, with one winner and the prize will be "Awesome prize!"
client.giveawaysManager.start(message.channel, {
time: ms(args[0]),
winnerCount: parseInt(args[1]),
prize: args.slice(2).join(' ')
}).then((gData) => {
console.log(gData); // {...} (messageID, end date and more)
});
// And the giveaway has started!
}
});
giveaway.extraData
.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.
let giveaway =
// Search with giveaway prize
client.giveawaysManager.giveaways.find((g) => g.guildID === message.guild.id && g.prize === args.join(' ')) ||
// Search with messageID
client.giveawaysManager.giveaways.find((g) => g.guildID === message.guild.id && g.messageID === args[0]);
// If no giveaway was found
if (!giveaway) return message.channel.send('Unable to find a giveaway for `'+ args.join(' ') +'`.');
client.on('message', (message) => {
const args = message.content.slice(settings.prefix.length).trim().split(/ +/g);
const command = args.shift().toLowerCase();
if (command === 'reroll') {
const messageID = args[0];
client.giveawaysManager.reroll(messageID).then(() => {
message.channel.send('Success! Giveaway rerolled!');
}).catch((err) => {
message.channel.send('No giveaway found for ' + messageID + ', please check and try again');
});
}
});
client.on('message', (message) => {
const args = message.content.slice(settings.prefix.length).trim().split(/ +/g);
const command = args.shift().toLowerCase();
if (command === 'edit') {
const messageID = args[0];
client.giveawaysManager.edit(messageID, {
addTime: 5000,
newWinnerCount: 3,
newPrize: 'New Prize!'
}).then(() => {
// Here, we can calculate the time after which we are sure that the lib will update the giveaway
const numberOfSecondsMax = client.giveawaysManager.options.updateCountdownEvery / 1000;
message.channel.send('Success! Giveaway will updated in less than ' + numberOfSecondsMax + ' seconds.');
}).catch((err) => {
message.channel.send('No giveaway found for ' + messageID + ', please check and try again');
});
}
});
Date.now() + 60000
).⚠️ Note: to reduce giveaway time, define addTime
with a negative number! For example addTime: -5000
will reduce giveaway time by 5 seconds!
client.on('message', (message) => {
const args = message.content.slice(settings.prefix.length).trim().split(/ +/g);
const command = args.shift().toLowerCase();
if (command === 'delete') {
const messageID = args[0];
client.giveawaysManager.delete(messageID).then(() => {
message.channel.send('Success! Giveaway deleted!');
}).catch((err) => {
message.channel.send('No giveaway found for ' + messageID + ', please check and try again');
});
}
});
⚠️ Note: when you use the delete function, the giveaway data and per default the message of the giveaway are deleted. You cannot restore a giveaway once you have deleted it!
client.on('message', (message) => {
const args = message.content.slice(settings.prefix.length).trim().split(/ +/g);
const command = args.shift().toLowerCase();
if (command === 'end') {
const messageID = args[0];
client.giveawaysManager.end(messageID).then(() => {
message.channel.send('Success! Giveaway ended!');
}).catch((err) => {
message.channel.send('No giveaway found for ' + messageID + ', please check and try again');
});
}
});
// 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);
client.giveawaysManager.start(message.channel, {
time: 60000,
winnerCount: 1,
prize: 'Free Steam Key',
// Only members who have the "Nitro Boost" role are able to win
exemptMembers: (member) => !member.roles.cache.some((r) => r.name === 'Nitro Boost')
})
⚠️ Note: If the function should be customizable
const roleName = 'Nitro Boost';
client.giveawaysManager.start(message.channel, {
time: 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', `return !member.roles.cache.some((r) => r.name === \'${roleName}\')`),
})
client.giveawaysManager.start(message.channel, {
time: 60000,
winnerCount: 1,
prize: 'Discord Nitro!',
lastChance: {
enabled: true,
content: '⚠️ **LAST CHANCE TO ENTER !** ⚠️',
threshold: 5000,
embedColor: '#FF0000'
}
})
client.giveawaysManager.start(message.channel, {
time: 60000,
winnerCount: 1,
prize: 'Free Steam Key',
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,
cumulative: false
}
]
})
⚠️ Note: If the bonus
function should be customizable
const roleName = 'Nitro Boost';
const roleBonusEntries = 2;
client.giveawaysManager.start(message.channel, {
time: 60000,
winnerCount: 1,
prize: 'Free Steam Key',
bonusEntries: [
// Members who have the role which is assigned to "roleName" get the amount of bonus entries which are assigned to "roleBonusEntries"
{
bonus: new Function('member', `return member.roles.cache.some((r) => r.name === \'${roleName}\') ? ${roleBonusEntries} : null`),
cumulative: false
}
]
})
You can also pass a messages
parameter for start()
function, if you want to translate the bot text:
Note: units should be in the plural.
For example:
client.giveawaysManager.start(message.channel, {
time: ms(args[0]),
winnerCount: parseInt(args[1]),
prize: args.slice(2).join(' '),
messages: {
giveaway: '@everyone\n\n🎉🎉 **GIVEAWAY** 🎉🎉',
giveawayEnded: '@everyone\n\n🎉🎉 **GIVEAWAY ENDED** 🎉🎉',
timeRemaining: 'Time remaining: **{duration}**',
inviteToParticipate: 'React with 🎉 to participate!',
winMessage: 'Congratulations, {winners}! You won **{prize}**!\n{messageURL}',
embedFooter: 'Powered by the discord-giveaways-v13 package',
noWinner: 'Giveaway cancelled, no valid participations.',
hostedBy: 'Hosted by: {user}',
winners: 'winner(s)',
endedAt: 'Ended at',
units: {
seconds: 'seconds',
minutes: 'minutes',
hours: 'hours',
days: 'days',
pluralS: false // Not needed, because units end with a S so it will automatically removed if the unit value is lower than 2
}
}
});
And for the reroll()
function:
client.giveawaysManager.reroll(messageID, {
messages: {
congrat: ':tada: New winner(s): {winners}! Congratulations, you won **{prize}**!\n{messageURL}',
error: 'No valid participations, no new winner(s) can be chosen!'
}
}).catch((err) => {
message.channel.send('No giveaway found for ' + messageID + ', please check and try again');
});
You can use your custom database to save giveaways, instead of the json files (the "database" by default for discord-giveaways-v13
). 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.editGiveaway
: this method edits a giveaway already stored in the database.deleteGiveaway
: this method deletes a giveaway from the database (permanently).⚠️ All the methods should be asynchronous to return a promise!
Here is an example, using quick.db
, a SQLite database. The comments in the code below are very important to understand how it works!
Other examples:
mongoose
example insteadconst Discord = require('discord.js'),
client = new Discord.Client(),
settings = {
prefix: 'g!',
token: 'Your Discord Bot Token'
};
// Load quick.db - it's an example of custom database, you can use MySQL, PostgreSQL, etc...
const db = require('quick.db');
if (!Array.isArray(db.get('giveaways'))) db.set('giveaways', []);
const { GiveawaysManager } = require('discord-giveaways-v13');
const GiveawayManagerWithOwnDatabase = class extends GiveawaysManager {
// This function is called when the manager needs to get all giveaways which are stored in the database.
async getAllGiveaways() {
// Get all giveaways from the database
return db.get('giveaways');
}
// This function is called when a giveaway needs to be saved in the database.
async saveGiveaway(messageID, giveawayData) {
// Add the new giveaway to the database
db.push('giveaways', giveawayData);
// Don't forget to return something!
return true;
}
// This function is called when a giveaway needs to be edited in the database.
async editGiveaway(messageID, giveawayData) {
// Get all giveaways from the database
const giveaways = db.get('giveaways');
// Remove the unedited giveaway from the array
const newGiveawaysArray = giveaways.filter((giveaway) => giveaway.messageID !== messageID);
// Push the edited giveaway into the array
newGiveawaysArray.push(giveawayData);
// Save the updated array
db.set('giveaways', newGiveawaysArray);
// Don't forget to return something!
return true;
}
// This function is called when a giveaway needs to be deleted from the database.
async deleteGiveaway(messageID) {
// Get all giveaways from the database
const giveaways = db.get('giveaways');
// Remove the giveaway from the array
const newGiveawaysArray = giveaways.filter((giveaway) => giveaway.messageID !== messageID);
// Save the updated array
db.set('giveaways', newGiveawaysArray);
// Don't forget to return something!
return true;
}
};
// Create a new instance of your new class
const manager = new GiveawayManagerWithOwnDatabase(client, {
updateCountdownEvery: 10000,
default: {
botsCanWin: false,
exemptPermissions: ['MANAGE_MESSAGES', 'ADMINISTRATOR'],
embedColor: '#FF0000',
embedColorEnd: '#000000',
reaction: '🎉'
}
});
// We now have a giveawaysManager property to access the manager everywhere!
client.giveawaysManager = manager;
client.on('ready', () => {
console.log('I\'m ready!');
});
client.login(settings.token);
To make discord-giveaways-v13
working with shards, you will need to extend the GiveawaysManager
class and update the refreshStorage()
method. This method should call the getAllGiveaways()
method for every shard, so all GiveawaysManager
synchronize their cache with the updated database.
const Discord = require('discord.js'),
client = new Discord.Client(),
settings = {
prefix: 'g!',
token: 'Your Discord Bot Token'
};
// Extends the GiveawaysManager class and update the refreshStorage method
const { GiveawaysManager } = require('discord-giveaways-v13');
const GiveawayManagerWithShardSupport = class extends GiveawaysManager {
// Refresh storage method is called when the database is updated on one of the shards
async refreshStorage() {
// This should make all shard refreshing their cache with the updated database
return client.shard.broadcastEval(() => this.giveawaysManager.getAllGiveaways());
}
};
// Create a new instance of your new class
const manager = new GiveawayManagerWithShardSupport(client, {
storage: './storage.json',
updateCountdownEvery: 10000,
default: {
botsCanWin: false,
exemptPermissions: ['MANAGE_MESSAGES', 'ADMINISTRATOR'],
embedColor: '#FF0000',
embedColorEnd: '#000000',
reaction: '🎉'
}
});
// We now have a giveawaysManager property to access the manager everywhere!
client.giveawaysManager = manager;
client.on('ready', () => {
console.log('I\'m ready!');
});
client.login(settings.token);
FAQs
This package functions just like the normal discord-giveaways, but it only works on discord.js v13! So you can use it if you are using discord.js v13.
The npm package discord-giveaways-v13 receives a total of 1 weekly downloads. As such, discord-giveaways-v13 popularity was classified as not popular.
We found that discord-giveaways-v13 demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
PEP 770 proposes adding SBOM support to Python packages to improve transparency and catch hidden non-Python dependencies that security tools often miss.
Security News
Socket CEO Feross Aboukhadijeh discusses open source security challenges, including zero-day attacks and supply chain risks, on the Cyber Security Council podcast.
Security News
Research
Socket researchers uncover how threat actors weaponize Out-of-Band Application Security Testing (OAST) techniques across the npm, PyPI, and RubyGems ecosystems to exfiltrate sensitive data.