trixxy-leveling
Version:
A Discord leveling system with image generation for Trixxy projects.
108 lines (83 loc) • 3.82 kB
JavaScript
const { AttachmentBuilder } = require('discord.js');
const { createCanvas, loadImage } = require('canvas');
class TrixxyLeveling {
constructor(options) {
this.client = options.client;
this.background = options.background || 'https://i.imgur.com/2g0QY0q.png'; // Default background
this.fontColor = options.fontColor || '#ffffff';
this.progressBarColor = options.progressBarColor || '#00ff00';
this.levelUpMessage = options.levelUpMessage || 'Congratulations, {user}! You leveled up to level {level}!';
this.xpPerMessage = options.xpPerMessage || 10;
this.levelFormula = options.levelFormula || ((level) => 5 * Math.pow(level, 2) + 50 * level + 100);
this.usersData = new Map(); // Store user XP and level data
if (this.client) {
this.client.on('messageCreate', this.handleMessage.bind(this));
}
}
async handleMessage(message) {
if (message.author.bot) return;
const userId = message.author.id;
const guildId = message.guild.id;
const userKey = `${guildId}-${userId}`;
if (!this.usersData.has(userKey)) {
this.usersData.set(userKey, { xp: 0, level: 0 });
}
const userData = this.usersData.get(userKey);
userData.xp += this.xpPerMessage;
const requiredXp = this.levelFormula(userData.level);
if (userData.xp >= requiredXp) {
userData.level++;
userData.xp -= requiredXp; // Carry over remaining XP
const channel = message.channel;
const levelUpMsg = this.levelUpMessage
.replace('{user}', message.author.username)
.replace('{level}', userData.level);
channel.send(levelUpMsg);
}
this.usersData.set(userKey, userData);
}
async generateLevelCard(user, currentXp, currentLevel) {
const canvas = createCanvas(934, 282);
const ctx = canvas.getContext('2d');
// Load background image
const background = await loadImage(this.background);
ctx.drawImage(background, 0, 0, canvas.width, canvas.height);
// Draw user avatar
const avatar = await loadImage(user.displayAvatarURL({ extension: 'png', size: 128 }));
ctx.beginPath();
ctx.arc(140, 140, 80, 0, Math.PI * 2, true);
ctx.closePath();
ctx.clip();
ctx.drawImage(avatar, 60, 60, 160, 160);
// Reset clip
ctx.restore();
// Draw text
ctx.fillStyle = this.fontColor;
ctx.font = 'bold 36px Arial';
ctx.fillText(user.username, 280, 120);
ctx.font = 'bold 28px Arial';
ctx.fillText(`Level: ${currentLevel}`, 280, 170);
const requiredXp = this.levelFormula(currentLevel);
ctx.fillText(`XP: ${currentXp}/${requiredXp}`, 280, 220);
// Draw progress bar
const progressBarWidth = 600;
const progressBarHeight = 30;
const progressBarX = 280;
const progressBarY = 240;
ctx.fillStyle = '#555555'; // Background of progress bar
ctx.fillRect(progressBarX, progressBarY, progressBarWidth, progressBarHeight);
const progress = (currentXp / requiredXp) * progressBarWidth;
ctx.fillStyle = this.progressBarColor;
ctx.fillRect(progressBarX, progressBarY, progress, progressBarHeight);
return new AttachmentBuilder(canvas.toBuffer(), { name: 'level-card.png' });
}
getUserData(userId, guildId) {
const userKey = `${guildId}-${userId}`;
return this.usersData.get(userKey) || { xp: 0, level: 0 };
}
setUserData(userId, guildId, data) {
const userKey = `${guildId}-${userId}`;
this.usersData.set(userKey, data);
}
}
module.exports = TrixxyLeveling;