UNPKG

trixxy-leveling

Version:

A Discord leveling system with image generation for Trixxy projects.

108 lines (83 loc) 3.82 kB
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;