discord-levels
Version:
A package that allows you to create a complete level system on your discord bot
186 lines (151 loc) • 8.29 kB
text/typescript
import * as db from 'quick.db'
import { MessageEmbed, MessageAttachment } from 'discord.js'
import * as canvas from 'canvas-constructor'
/**
* Adds experience to the user
* @param {any} message Parameter of your event message
* @param {string} userID ID of the user
* @param {number} XP The experience that will be added
* @returns {any}
*/
export function addXP (message: any, userID: string, XP: number) : any {
if(!message) throw new Error("You must enter a message parameter, referring to your 'message' event");
if(!userID) throw new Error("You must enter a userID parameter, corresponds to the ID of the user who will receive the experience");
if(typeof userID !== "string") throw new Error("The userID parameter must be a String");
if(!XP) throw new Error("You must enter an XP parameter, corresponds to the experience that will be added");
if(XP <= 0) throw new Error("The XP parameter must be greater than 0");
if(typeof XP !== "number") throw new Error("The XP parameter must be a Number");
db.add(`xp_${message.guild.id}_${userID}`, XP);
};
/**
* Remove experience to the user
* @param {any} message Parameter of your event message
* @param {string} userID ID of the user
* @param {number} XP The experience that will be removed
* @returns {any}
*/
export function removeXP (message: any, userID: string, XP: number) : any {
if(!message) throw new Error("You must enter a message parameter, referring to your 'message' event");
if(!userID) throw new Error("You must enter a userID parameter, corresponds to the ID of the user who will loose the experience");
if(typeof userID !== "string") throw new Error("The userID parameter must be a String");
if(!XP) throw new Error("You must enter an XP parameter, corresponds to the experience that will be remove");
if(XP <= 0) throw new Error("The XP parameter must be greater than 0");
if(typeof XP !== "number") throw new Error("The XP parameter must be a Number");
db.subtract(`xp_${message.guild.id}_${userID}`, XP);
};
/**
* Allows you to obtain a user's information
* @param {any} message Parameter of your event message
* @param {string} userID ID of the user
* @returns {any}
*/
export function fetch (message: any, userID: string) : any {
let embed;
if(!message) throw new Error("You must enter a message parameter, referring to your 'message' event");
if(!userID) throw new Error("You must enter a userID parameter, corresponds to the ID of the user");
if(typeof userID !== "string") throw new Error("The userID parameter must be a String");
const data = {
level: db.get(`level_${message.guild.id}_${userID}`) || 1,
xp: db.get(`xp_${message.guild.id}_${userID}`) || 0
};
message.guild.members.fetch(userID).then((m: any) => {
embed = new MessageEmbed()
.setColor("RANDOM")
.setAuthor(m.user.tag, m.user.displayAvatarURL({ dynamic: true }))
.setThumbnail(m.user.displayAvatarURL({ dynamic: true }))
.setDescription("**Level** : `" + data.level + "` \n**XP** : `" + data.xp + "`")
message.channel.send(embed);
}).catch(() => message.channel.send(":x: Unknown user ID."))
};
/**
* Returns a ranking of the experience in the server
* @param {any} client Discord.js Client
* @param {any} message Parameter of your event message
* @returns {any}
*/
export function leaderboard (client: any, message: any) : any {
if(!client) throw new Error("You must enter a client parameter (discord.js client)");
if(!message) throw new Error("You must enter a message parameter, referring to your 'message' event");
let data = db.all().filter(i => i.ID.startsWith("level_")).sort((a, b) => b.data - a.data);
if(data.length < 1) return message.channel.send("It seems that there is no data");
let authorRank = data.map(i => i.ID).indexOf(`level_${message.guild.id}_${message.author.id}`) + 1 || "N/A";
let leaderboard = [];
for (let i in data) {
let id = data[i].ID.split("_")[2];
let user = client.users.cache.get(id);
let level = db.get(`level_${message.guild.id}_${id}`);
leaderboard.push({
user: (user !== undefined || !user) ? user.tag : "Unknown#0000",
rank: data.indexOf(data[i]) + 1,
level: level !== null ? level : "Unknown",
xp: data[i].data ? data[i].data : "Unkown"
});
};
const embed = new MessageEmbed()
.setColor("RANDOM")
.setTitle("🙄 Leaderboard");
leaderboard.forEach(x => {
embed.addField(
`➔ \`${x.rank}\` • **${x.user}**`,
`__Level:__ **\`${x.level}\`** • __XP:__ **\`${x.xp}\`**`,
false
);
});
embed.setFooter("You are at the position " + authorRank, message.guild.iconURL({ dynamic: true }));
message.channel.send(embed);
};
/**
* Returns a rankcard
* @param {any} message Parameter of your event message
* @param {string} userID The ID of the user
* @returns {any}
*/
export function Rankcard (message: any, userID: string) : any {
if(!message) throw new Error("You must enter a message parameter, referring to your 'message' event");
if(!userID) throw new Error("You must enter a userID parameter, corresponds to the ID of the user");
if(typeof userID !== "string") throw new Error("The userID parameter must be a String");
message.guild.members.fetch(userID).then(async (m: any) => {
let avatar = await canvas.resolveImage(m.user.displayAvatarURL({ dynamic: false, format: "png" }));
const data = {
level: db.get(`level_${message.guild.id}_${userID}`) || 1,
xp: db.get(`xp_${message.guild.id}_${userID}`) || 1
};
let status = await canvas.resolveImage(`assets/status_${m.user.presence.status}.png`);
let black = await canvas.resolveImage('assets/black.png');
let userRank = db.all().filter(i => i.ID.startsWith("level_")).sort((a, b) => b.data - a.data).map(i => i.ID).indexOf(`level_${message.guild.id}_${userID}`) + 1 || "N/A";
let image = new canvas.Canvas(500, 200)
.setColor("#303133")
.printRectangle(0, 0, 500, 200)
.setColor("#fcfdff")
.setTextAlign("center")
.setTextSize(35)
.printText((m.displayName.length > 15 ? m.displayName.substring(0, 12) + "..." : m.displayName) + "#" + m.user.discriminator, 250, 45)
.printCircularImage(avatar, 70, 110, 50)
.printCircularImage(black, 100, 140, 15)
.printCircularImage(status, 100, 140, 20)
.setColor(String(m.user.presence.status).replace("online", "#43b581").replace("idle", "#faa61a").replace("dnd", "#f04747").replace("offline", "#747f8d"))
.printRoundedRectangle(130, 95, 350, 45, 15)
.setColor("#303133")
.printRoundedRectangle(132, 97, 346, 42, 15)
.setColor("#fcfdff")
.printRoundedRectangle(134, 99, ((data.xp/100)*340), 38, 15)
.setColor("#fcfdff")
.setTextAlign("left")
.setTextSize(19)
.printText(`Level : ${data.level} | XP : ${data.xp} / 100`, 10, 190);
let colorRanks = {
1: '#d1b94f',
2: '#adaca6',
3: '#96531d'
};
let color = (userRank === 1 || userRank === 2 || userRank === 3) ? colorRanks[userRank] : "#fcfdff"
let size = image.measureText(`Rank #${userRank}`).width;
await image.setColor(color).setTextAlign("left").setTextSize(21).printText(`Rank #${userRank}`, image.width-(size+20), 190)
if(userRank === 1 || userRank === 2 || userRank === 3) {
let userRank_img = await canvas.resolveImage(`assets/rank_${userRank}.png`);
await image.printImage(userRank_img, 435, 8);
};
let attachment = new MessageAttachment(image.toBuffer(), "rank.png");
message.channel.send(attachment)
}).catch(() => message.channel.send(":x: Unknown user ID."));
}