diff --git a/.eslintrc.json b/.eslintrc.json new file mode 100644 index 0000000..0942a32 --- /dev/null +++ b/.eslintrc.json @@ -0,0 +1,29 @@ +{ + "env": { + "commonjs": true, + "es2021": true, + "node": true + }, + "extends": "eslint:recommended", + "parserOptions": { + "ecmaVersion": "latest" + }, + "rules": { + "indent": [ + "error", + 4 + ], + "linebreak-style": [ + "error", + "unix" + ], + "quotes": [ + "error", + "single" + ], + "semi": [ + "error", + "always" + ] + } +} diff --git a/package.json b/package.json index 4146565..44adc60 100644 --- a/package.json +++ b/package.json @@ -1,12 +1,12 @@ { "name": "simply-xp", - "version": "1.3.5-beta-6", + "version": "1.3.5-beta-7", "description": "A Simple, Easy and Beginner Friendly XP System", "main": "simplyxp.js", "typings": "index.d.ts", "scripts": { "test": "echo \"Error: no test specified\" && exit 1", - "beta": "npm publish --tag beta" + "beta": "eslint . --fix && npm update && npm publish --tag beta" }, "author": "Rahuletto", "keywords": [ @@ -40,11 +40,14 @@ "url": "https://github.com/Rahuletto/simply-xp" }, "dependencies": { - "@napi-rs/canvas": "^0.1.33", + "@napi-rs/canvas": "^0.1.41", "chart.js": "^3.9.1", - "mongoose": "^6.8.3" + "mongoose": "^6.11.2" }, "peerDependencies": { "discord.js": ">=13.12.0" + }, + "devDependencies": { + "eslint": "^8.43.0" } } diff --git a/simplyxp.js b/simplyxp.js index c07f4ec..a9f3d3f 100644 --- a/simplyxp.js +++ b/simplyxp.js @@ -1,31 +1,31 @@ try { - require('discord.js') + require('discord.js'); } catch (e) { - console.warn('[XP] Discord.js is recommended for this package.') + console.warn('[XP] Discord.js is recommended for this package.'); } -module.exports.roleSetup = require('./src/roleSetup') +module.exports.roleSetup = require('./src/roleSetup'); -module.exports.addLevel = require('./src/addLevel') +module.exports.addLevel = require('./src/addLevel'); -module.exports.addXP = require('./src/addXP') +module.exports.addXP = require('./src/addXP'); -module.exports.charts = require('./src/charts') +module.exports.charts = require('./src/charts'); -module.exports.connect = require('./src/connect') +module.exports.connect = require('./src/connect'); -module.exports.create = require('./src/create') +module.exports.create = require('./src/create'); -module.exports.fetch = require('./src/fetch') +module.exports.fetch = require('./src/fetch'); -module.exports.leaderboard = require('./src/leaderboard') +module.exports.leaderboard = require('./src/leaderboard'); -module.exports.lvlRole = require('./src/lvlRole') +module.exports.lvlRole = require('./src/lvlRole'); -module.exports.rank = require('./src/rank') +module.exports.rank = require('./src/rank'); -module.exports.setLevel = require('./src/setLevel') +module.exports.setLevel = require('./src/setLevel'); -module.exports.setXP = require('./src/setXP') +module.exports.setXP = require('./src/setXP'); -module.exports.reset = require('./src/reset') +module.exports.reset = require('./src/reset'); diff --git a/src/addLevel.js b/src/addLevel.js index dba63be..e97d2ca 100644 --- a/src/addLevel.js +++ b/src/addLevel.js @@ -1,5 +1,5 @@ -const levels = require('../src/models/level.js') -let {roleSetup} = require('../simplyxp') +const levels = require('../src/models/level.js'); +let {roleSetup} = require('../simplyxp'); /** * @param {Discord.Message} message @@ -8,15 +8,15 @@ let {roleSetup} = require('../simplyxp') * @param {number} level */ async function addLevel(message, userID, guildID, level) { - if (!userID) throw new Error('[XP] User ID was not provided.') + if (!userID) throw new Error('[XP] User ID was not provided.'); - if (!guildID) throw new Error('[XP] Guild ID was not provided.') + if (!guildID) throw new Error('[XP] Guild ID was not provided.'); - if (!level) throw new Error('[XP] Level amount is not provided.') + if (!level) throw new Error('[XP] Level amount is not provided.'); - let {client} = message + let {client} = message; - const user = await levels.findOne({user: userID, guild: guildID}) + const user = await levels.findOne({user: userID, guild: guildID}); if (!user) { const newUser = new levels({ @@ -24,25 +24,25 @@ async function addLevel(message, userID, guildID, level) { guild: guildID, xp: 0, level: 0 - }) + }); - await newUser.save().catch(() => console.log(`[XP] Failed to save new user to database`)) + await newUser.save().catch(() => console.log('[XP] Failed to save new user to database')); - let xp = (level * 10) ** 2 + let xp = (level * 10) ** 2; return { level: level, exp: xp - } + }; } - let level1 = user.level + let level1 = user.level; - user.level += parseFloat(level) - user.xp = (user.level * 10) ** 2 + user.level += parseFloat(level); + user.xp = (user.level * 10) ** 2; await user.save().catch((e) => console.log(`[XP] Failed to add Level | User: ${userID} | Err: ${e}`) - ) + ); if (level1 !== level) { let data = { @@ -50,17 +50,17 @@ async function addLevel(message, userID, guildID, level) { level: user.level, userID, guildID - } + }; - let role = await roleSetup.find(client, guildID, level) + let role = await roleSetup.find(client, guildID, level); - client.emit('levelUp', message, data, role) + client.emit('levelUp', message, data, role); } return { level: user.level, xp: user.xp - } + }; } -module.exports = addLevel +module.exports = addLevel; diff --git a/src/addXP.js b/src/addXP.js index 0d476ee..2df7dc1 100644 --- a/src/addXP.js +++ b/src/addXP.js @@ -1,5 +1,5 @@ -const levels = require('../src/models/level.js') -let {roleSetup} = require('../simplyxp') +const levels = require('../src/models/level.js'); +let {roleSetup} = require('../simplyxp'); /** * @param {Discord.Message} message @@ -9,76 +9,77 @@ let {roleSetup} = require('../simplyxp') */ async function addXP(message, userID, guildID, xp) { - if (!userID) throw new Error('[XP] User ID was not provided.') + if (!userID) throw new Error('[XP] User ID was not provided.'); - if (!guildID) throw new Error('[XP] Guild ID was not provided.') + if (!guildID) throw new Error('[XP] Guild ID was not provided.'); - if (!xp) throw new Error('[XP] XP amount is not provided.') + if (!xp) throw new Error('[XP] XP amount is not provided.'); - let {client} = message + let {client} = message; - let min - let max + let min; + let max; if (xp.min) { if (!xp.max) throw new Error( '[XP] XP min amount is provided but max amount is not provided.' - ) + ); - min = Number(xp.min) + min = Number(xp.min); if (Number(xp.min).toString() === 'NaN') - throw new Error('[XP] XP amount (min) is not a number.') + throw new Error('[XP] XP amount (min) is not a number.'); } if (xp.max) { if (!xp.min) throw new Error( '[XP] XP max amount is provided but min amount is not provided.' - ) + ); - max = Number(xp.max) + max = Number(xp.max); if (Number(xp.max).toString() === 'NaN') - throw new Error('[XP] XP amount (max) is not a number.') + throw new Error('[XP] XP amount (max) is not a number.'); } if (xp.min && xp.max) { - xp = Math.floor(Math.random() * (max - min) + min) + xp = Math.floor(Math.random() * (max - min) + min); } - const user = await levels.findOne({user: userID, guild: guildID}) + const user = await levels.findOne({user: userID, guild: guildID}); - let lvl = Math.floor(0.1 * Math.sqrt(xp)) + let lvl = Math.floor(0.1 * Math.sqrt(xp)); + // TODO: FIX THIS xp = xp & level = lvl if (!user) { const newUser = new levels({ user: userID, guild: guildID, xp: xp, level: lvl - }) + }); - await newUser.save().catch(() => console.log(`[XP] Failed to save new user to database`)) + await newUser.save().catch(() => console.log('[XP] Failed to save new user to database')); return { level: 0, exp: 0 - } + }; } - let level1 = user.level + let level1 = user.level; - user.xp += parseInt(xp, 10) - user.level = Math.floor(0.1 * Math.sqrt(user.xp)) + user.xp += parseInt(xp, 10); + user.level = Math.floor(0.1 * Math.sqrt(user.xp)); - await user.save().catch((e) => console.log(`[XP] Failed to add XP | User: ${userID} | Err: ${e}`)) + await user.save().catch((e) => console.log(`[XP] Failed to add XP | User: ${userID} | Err: ${e}`)); - let level = user.level + let level = user.level; - xp = user.xp + xp = user.xp; if (user.xp === 0 || Math.sign(user.xp) === -1) { - xp = 0 + xp = 0; } if (level1 !== level) { @@ -87,17 +88,17 @@ async function addXP(message, userID, guildID, xp) { level, userID, guildID - } + }; - let role = await roleSetup.find(client, guildID, level) + let role = await roleSetup.find(client, guildID, level); - client.emit('levelUp', message, data, role) + client.emit('levelUp', message, data, role); } return { level, xp - } + }; } -module.exports = addXP +module.exports = addXP; diff --git a/src/charts.js b/src/charts.js index abd4418..26c1587 100644 --- a/src/charts.js +++ b/src/charts.js @@ -1,4 +1,4 @@ -let leaderboard = require('./leaderboard') +let leaderboard = require('./leaderboard'); /** * @param {Discord.Message} message @@ -7,27 +7,27 @@ let leaderboard = require('./leaderboard') async function charts(message, options) { try { - require('canvas') + require('canvas'); } catch { - throw '[XP] This requires canvas to be installed. \n"npm install canvas"' + throw '[XP] This requires canvas to be installed. \n"npm install canvas"'; } - const ChartJS = require('chart.js') - const Canvas = require('canvas') - let {client} = message + const ChartJS = require('chart.js'); + const Canvas = require('canvas'); + let {client} = message; - let data = [] - let pos = options?.position || 5 - let uzern = [] + let data = []; + let pos = options?.position || 5; + let uzern = []; - let ctx = Canvas.createCanvas(950, 526) + let ctx = Canvas.createCanvas(950, 526); await leaderboard(client, message.guild.id).then((e) => { e.forEach((m) => { if (m.position <= pos) { - data.push(m.xp) - uzern.push(m.tag) + data.push(m.xp); + uzern.push(m.tag); } - }) - }) + }); + }); new ChartJS(ctx, { type: options.type || 'bar', @@ -72,21 +72,21 @@ async function charts(message, options) { { id: 'simply-xp', beforeDraw: (chart) => { - const ctx = chart.canvas.getContext('2d') - ctx.save() - ctx.globalCompositeOperation = 'destination-over' - ctx.fillStyle = options.background || '#2F3136' - ctx.fillRect(0, 0, chart.width, chart.height) - ctx.restore() + const ctx = chart.canvas.getContext('2d'); + ctx.save(); + ctx.globalCompositeOperation = 'destination-over'; + ctx.fillStyle = options.background || '#2F3136'; + ctx.fillRect(0, 0, chart.width, chart.height); + ctx.restore(); } } ] - }).update() + }).update(); return { attachment: ctx.toBuffer('image/png'), name: 'chart.png' - } + }; } -module.exports = charts \ No newline at end of file +module.exports = charts; \ No newline at end of file diff --git a/src/connect.js b/src/connect.js index 09b68d8..0236ffd 100644 --- a/src/connect.js +++ b/src/connect.js @@ -1,4 +1,4 @@ -const mongoose = require('mongoose') +const mongoose = require('mongoose'); /** * @param {string} db @@ -6,17 +6,17 @@ const mongoose = require('mongoose') */ async function connect(db, options = []) { - if (!db) throw new Error('[XP] Database URL was not provided') - mongoose.set('strictQuery', true); + if (!db) throw new Error('[XP] Database URL was not provided'); + mongoose.set('strictQuery', true); - mongoose.connect(db, { - useNewUrlParser: true, - useUnifiedTopology: true - }) + mongoose.connect(db, { + useNewUrlParser: true, + useUnifiedTopology: true + }); - if (options.notify === false) return - else return console.log('{ XP } Database Connected') + if (options.notify === false) return; + else return console.log('{ XP } Database Connected'); } -module.exports = connect \ No newline at end of file +module.exports = connect; \ No newline at end of file diff --git a/src/create.js b/src/create.js index a9fcdb7..5698cd2 100644 --- a/src/create.js +++ b/src/create.js @@ -1,4 +1,4 @@ -const levels = require('../src/models/level.js') +const levels = require('../src/models/level.js'); /** * @param {string} userID @@ -6,23 +6,23 @@ const levels = require('../src/models/level.js') */ async function create(userID, guildID) { - if (!userID) throw new Error('[XP] User ID was not provided.') + if (!userID) throw new Error('[XP] User ID was not provided.'); - if (!guildID) throw new Error('[XP] User ID was not provided.') + if (!guildID) throw new Error('[XP] User ID was not provided.'); - let uzer = await levels.findOne({ user: userID, guild: guildID }) + let uzer = await levels.findOne({ user: userID, guild: guildID }); - if (uzer) return + if (uzer) return; - const newuser = new levels({ - user: userID, - guild: guildID - }) - await newuser - .save() - .catch((e) => console.log(`[XP] Failed to save new use to database`)) + const newuser = new levels({ + user: userID, + guild: guildID + }); + await newuser + .save() + .catch(() => console.log('[XP] Failed to save new use to database')); - return true + return true; } -module.exports = create +module.exports = create; diff --git a/src/fetch.js b/src/fetch.js index fffdd1c..4f56246 100644 --- a/src/fetch.js +++ b/src/fetch.js @@ -1,4 +1,4 @@ -const levels = require('../src/models/level.js') +const levels = require('../src/models/level.js'); /** * @param {string} userID @@ -6,69 +6,69 @@ const levels = require('../src/models/level.js') */ async function fetch(userID, guildID) { - if (!userID) throw new Error('[XP] User ID was not provided.') - - if (!guildID) throw new Error('[XP] Guild ID was not provided.') - - let user = await levels.findOne({ - user: userID, - guild: guildID - }) - if (!user) { - user = new levels({ - user: userID, - guild: guildID, - xp: 0, - level: 0 - }) - - await user.save() - } - - const leaderboard = await levels - .find({ - guild: guildID - }) - .sort([['xp', 'descending']]) - .exec() - - if (user === null) - return { - level: 0, - xp: 0, - reqxp: 100, - rank: leaderboard.findIndex((i) => i.user === userID) + 1, - shortxp: 0, - shortreq: 100 + if (!userID) throw new Error('[XP] User ID was not provided.'); + + if (!guildID) throw new Error('[XP] Guild ID was not provided.'); + + let user = await levels.findOne({ + user: userID, + guild: guildID + }); + if (!user) { + user = new levels({ + user: userID, + guild: guildID, + xp: 0, + level: 0 + }); + + await user.save(); } - user.position = leaderboard.findIndex((i) => i.user === userID) + 1 + const leaderboard = await levels + .find({ + guild: guildID + }) + .sort([['xp', 'descending']]) + .exec(); + + if (user === null) + return { + level: 0, + xp: 0, + reqxp: 100, + rank: leaderboard.findIndex((i) => i.user === userID) + 1, + shortxp: 0, + shortreq: 100 + }; - let targetxp = user.level + 1 + user.position = leaderboard.findIndex((i) => i.user === userID) + 1; - let target = targetxp * targetxp * 100 + let targetxp = user.level + 1; - function shortener(count) { - const COUNT_ABBRS = ['', 'k', 'M', 'T'] + let target = targetxp * targetxp * 100; - const i = 0 === count ? count : Math.floor(Math.log(count) / Math.log(1000)) - let result = parseFloat((count / Math.pow(1000, i)).toFixed(2)) - result += `${COUNT_ABBRS[i]}` - return result - } + function shortener(count) { + const COUNT_ABBRS = ['', 'k', 'M', 'T']; - let shortXP = shortener(user.xp) + const i = 0 === count ? count : Math.floor(Math.log(count) / Math.log(1000)); + let result = parseFloat((count / Math.pow(1000, i)).toFixed(2)); + result += `${COUNT_ABBRS[i]}`; + return result; + } - let shortReqXP = shortener(target) + let shortXP = shortener(user.xp); - return { - level: user.level, - xp: user.xp, - reqxp: target, - rank: user.position, - shortxp: shortXP, - shortreq: shortReqXP - } + let shortReqXP = shortener(target); + + return { + level: user.level, + xp: user.xp, + reqxp: target, + rank: user.position, + shortxp: shortXP, + shortreq: shortReqXP + }; } -module.exports = fetch +module.exports = fetch; diff --git a/src/leaderboard.js b/src/leaderboard.js index b0ce56b..f3d8ed2 100644 --- a/src/leaderboard.js +++ b/src/leaderboard.js @@ -1,4 +1,4 @@ -const levels = require('../src/models/level.js') +const levels = require('../src/models/level.js'); /** * @param {Discord.Client} client @@ -7,32 +7,32 @@ const levels = require('../src/models/level.js') */ async function leaderboard(client, guildID, limit) { - if (!guildID) throw new Error('[XP] Guild ID was not provided.') + if (!guildID) throw new Error('[XP] Guild ID was not provided.'); - let g = client.guilds.cache.get(guildID) - if (!g) throw new Error('[XP] Guild was not found.') + let g = client.guilds.cache.get(guildID); + if (!g) throw new Error('[XP] Guild was not found.'); - let leaderboard = await levels.find({guild: guildID}).sort([['xp', 'descending']]) + let leaderboard = await levels.find({guild: guildID}).sort([['xp', 'descending']]); - let led = [] + let led = []; function shortener(count) { - const COUNT_ABBRS = ['', 'k', 'M', 'T'] + const COUNT_ABBRS = ['', 'k', 'M', 'T']; - const i = 0 === count ? count : Math.floor(Math.log(count) / Math.log(1000)) - let result = parseFloat((count / Math.pow(1000, i)).toFixed(2)) - result += `${COUNT_ABBRS[i]}` - return result + const i = 0 === count ? count : Math.floor(Math.log(count) / Math.log(1000)); + let result = parseFloat((count / Math.pow(1000, i)).toFixed(2)); + result += `${COUNT_ABBRS[i]}`; + return result; } const led2 = leaderboard.map(async (key) => { - const user = await g.members.fetch(key.user).catch(() => null) - if (!user) return levels.deleteOne({user: key.user, guild: guildID}) + const user = await g.members.fetch(key.user).catch(() => null); + if (!user) return levels.deleteOne({user: key.user, guild: guildID}); if (key.xp === 0) return; - let pos = leaderboard.indexOf(key) + 1 + let pos = leaderboard.indexOf(key) + 1; if (limit) { - if (pos > Number(limit)) return + if (pos > Number(limit)) return; } led.push({ @@ -44,9 +44,9 @@ async function leaderboard(client, guildID, limit) { position: pos, username: user.user.username, tag: user.user.tag - }) - }) - return Promise.all(led2).then(() => led) + }); + }); + return Promise.all(led2).then(() => led); } -module.exports = leaderboard \ No newline at end of file +module.exports = leaderboard; \ No newline at end of file diff --git a/src/lvlRole.js b/src/lvlRole.js index 215e08d..39b48ff 100644 --- a/src/lvlRole.js +++ b/src/lvlRole.js @@ -1,5 +1,5 @@ -const levels = require('../src/models/level.js') -const lrole = require('../src/models/lvlrole.js') +const levels = require('../src/models/level.js'); +const lrole = require('../src/models/lvlrole.js'); /** * @param {Discord.Message} message @@ -8,46 +8,46 @@ const lrole = require('../src/models/lvlrole.js') */ async function lvlRole(message, userID, guildID) { - let e = await lrole.find({ - gid: guildID - }) - - if (!e) return - - let user = await levels.findOne({ - user: userID, - guild: guildID - }) - if (!user) { - const newuser = new levels({ - user: userID, - guild: guildID - }) - - await newuser - .save() - .catch((e) => console.log(`[XP] Failed to save new user to database`)) - } - - e.forEach((ee) => { - ee = ee.lvlrole - - ee.forEach((xd) => { - if (user && user.level >= Number(xd.lvl)) { - let u = message.guild.members.cache.get(userID) - - let real = message.guild.roles.cache.find((r) => r.id === xd.role) - if (!real) return - else { - u.roles.add(real).catch((err) => { - message.channel.send( - '[XP] ERROR: Role is higher than me. `MISSING_PERMISSIONS`' - ) - }) - } - } - }) - }) + let e = await lrole.find({ + gid: guildID + }); + + if (!e) return; + + let user = await levels.findOne({ + user: userID, + guild: guildID + }); + if (!user) { + const newuser = new levels({ + user: userID, + guild: guildID + }); + + await newuser + .save() + .catch(() => console.log('[XP] Failed to save new user to database')); + } + + e.forEach((ee) => { + ee = ee.lvlrole; + + ee.forEach((xd) => { + if (user && user.level >= Number(xd.lvl)) { + let u = message.guild.members.cache.get(userID); + + let real = message.guild.roles.cache.find((r) => r.id === xd.role); + if (!real) return; + else { + u.roles.add(real).catch(() => { + message.channel.send( + '[XP] ERROR: Role is higher than me. `MISSING_PERMISSIONS`' + ); + }); + } + } + }); + }); } -module.exports = lvlRole +module.exports = lvlRole; diff --git a/src/models/level.js b/src/models/level.js index 19cd89d..8b91907 100644 --- a/src/models/level.js +++ b/src/models/level.js @@ -1,10 +1,10 @@ -const mongoose = require('mongoose') +const mongoose = require('mongoose'); const Levelz = new mongoose.Schema({ - user: { type: String, unique: true }, - guild: { type: String }, - xp: { type: Number, default: 0 }, - level: { type: Number, default: 0 } -}) + user: { type: String, unique: true }, + guild: { type: String }, + xp: { type: Number, default: 0 }, + level: { type: Number, default: 0 } +}); -module.exports = mongoose.model('Simply-XP', Levelz) +module.exports = mongoose.model('Simply-XP', Levelz); diff --git a/src/models/lvlrole.js b/src/models/lvlrole.js index dbbd1a4..74492e8 100644 --- a/src/models/lvlrole.js +++ b/src/models/lvlrole.js @@ -1,8 +1,8 @@ -const mongoose = require('mongoose') +const mongoose = require('mongoose'); const rol = new mongoose.Schema({ - gid: { type: String }, - lvlrole: { type: Array } -}) + gid: { type: String }, + lvlrole: { type: Array } +}); -module.exports = mongoose.model('Simply-XP-LevelRole', rol) +module.exports = mongoose.model('Simply-XP-LevelRole', rol); diff --git a/src/rank.js b/src/rank.js index f650946..dcbd7cf 100644 --- a/src/rank.js +++ b/src/rank.js @@ -1,5 +1,5 @@ -const levels = require('../src/models/level.js') -const {join} = require('path') +const levels = require('../src/models/level.js'); +const {join} = require('path'); /** * @param {Discord.Message} message @@ -9,28 +9,28 @@ const {join} = require('path') */ async function rank(message, userID, guildID, options = []) { - if (!userID) throw new Error('[XP] User ID was not provided.') + if (!userID) throw new Error('[XP] User ID was not provided.'); - if (!guildID) throw new Error('[XP] Guild ID was not provided.') + if (!guildID) throw new Error('[XP] Guild ID was not provided.'); const user = await levels.findOne({ user: userID, guild: guildID - }) - if (!user) throw new Error('[XP] NO_DATA | User has no XP data.') + }); + if (!user) throw new Error('[XP] NO_DATA | User has no XP data.'); const leaderboard = await levels .find({ guild: guildID }) .sort([['xp', 'descending']]) - .exec() + .exec(); - user.position = leaderboard.findIndex((i) => i.user === userID) + 1 + user.position = leaderboard.findIndex((i) => i.user === userID) + 1; - let targetxp = user.level + 1 + let targetxp = user.level + 1; - let target = targetxp * targetxp * 100 + let target = targetxp * targetxp * 100; return rankCard(message, { level: user.level, @@ -42,56 +42,33 @@ async function rank(message, userID, guildID, options = []) { lvlbar: options.lvlbar, lvlbarBg: options.lvlbarBg, member: message.guild.members.cache.get(userID)?.user - }) + }); async function rankCard(message, options = []) { try { - const Canvas = require('@napi-rs/canvas') + const Canvas = require('@napi-rs/canvas'); Canvas.GlobalFonts.registerFromPath( join(__dirname, 'Fonts', 'Baloo-Regular.ttf'), 'Sans Serif' - ) - - function shortener(count) { - const COUNT_ABBRS = [ - '', - 'k', - 'M', - 'B', - 'T', - 'Q', - 'Q+', - 'S', - 'S+', - 'O', - 'N', - 'D', - 'U' - ] - - const i = 0 === count ? count : Math.floor(Math.log(count) / Math.log(1000)) - let result = parseFloat((count / Math.pow(1000, i)).toFixed(2)) - result += `${COUNT_ABBRS[i]}` - return result - } + ); - const member = options.member + const member = options.member; const canvas = Canvas.createCanvas(1080, 400), - ctx = canvas.getContext('2d') + ctx = canvas.getContext('2d'); - const name = member.tag - const noSymbols = (string) => string.replace(/[\u007f-\uffff]/g, '') + const name = member.tag; + const noSymbols = (string) => string.replace(/[\u007f-\uffff]/g, ''); - let fsiz = '45px' + let fsiz = '45px'; if (message.guild.name.length >= 23) { - fsiz = '38px' + fsiz = '38px'; } if (message.guild.name.length >= 40) { - fsiz = '28px' + fsiz = '28px'; } if (message.guild.name.length >= 63) { - fsiz = '22px' + fsiz = '22px'; } let BackgroundRadius = '20', @@ -113,182 +90,206 @@ async function rank(message, userID, guildID, options = []) { BarRadius = '20', TextXpNeded = '{current}/{needed}', CurrentXP = options.currentXP, - NeededXP = options.neededXP + NeededXP = options.neededXP; - ctx.beginPath() - ctx.moveTo(Number(BackgroundRadius), 0) - ctx.lineTo(1080 - Number(BackgroundRadius), 0) - ctx.quadraticCurveTo(1080, 0, 1080, Number(BackgroundRadius)) - ctx.lineTo(1080, 400 - Number(BackgroundRadius)) + ctx.beginPath(); + ctx.moveTo(Number(BackgroundRadius), 0); + ctx.lineTo(1080 - Number(BackgroundRadius), 0); + ctx.quadraticCurveTo(1080, 0, 1080, Number(BackgroundRadius)); + ctx.lineTo(1080, 400 - Number(BackgroundRadius)); ctx.quadraticCurveTo( 1080, 400, 1080 - Number(BackgroundRadius), 400 - ) - - ctx.lineTo(Number(BackgroundRadius), 400) - ctx.quadraticCurveTo(0, 400, 0, 400 - Number(BackgroundRadius)) - ctx.lineTo(0, Number(BackgroundRadius)) - ctx.quadraticCurveTo(0, 0, Number(BackgroundRadius), 0) - ctx.closePath() - ctx.clip() - ctx.fillStyle = '#000000' - ctx.fillRect(0, 0, 1080, 400) - let background = await Canvas.loadImage(BackGroundImg) - ctx.globalAlpha = 0.7 - ctx.drawImage(background, 0, 0, 1080, 400) - ctx.restore() - - ctx.fillStyle = DrawLayerColor - ctx.globalAlpha = DrawLayerOpacity - ctx.fillRect(40, 0, 240, canvas.height) - ctx.globalAlpha = 1 - - function RoundedBox(ctx, x, y, width, height, radius) { - ctx.beginPath() - ctx.moveTo(x + radius, y) - ctx.lineTo(x + width - radius, y) - ctx.quadraticCurveTo(x + width, y, x + width, y + radius) - ctx.lineTo(x + width, y + height - radius) - ctx.quadraticCurveTo( - x + width, - y + height, - x + width - radius, - y + height - ) - ctx.lineTo(x + radius, y + height) - ctx.quadraticCurveTo(x, y + height, x, y + height - radius) - ctx.lineTo(x, y + radius) - ctx.quadraticCurveTo(x, y, x + radius, y) - ctx.closePath() - } - - let avatar = await Canvas.loadImage(member.displayAvatarURL()) - ctx.save() - RoundedBox(ctx, 70, 30, 180, 180, Number(AvatarRoundRadius)) - ctx.strokeStyle = BoxColor - ctx.lineWidth = 15 - ctx.stroke() - ctx.clip() - ctx.drawImage(avatar, 70, 30, 180, 180) - ctx.restore() - - ctx.save() - RoundedBox(ctx, 70, 240 + 50 + 30, 180, 50, 20) - ctx.strokeStyle = '#BFC85A22' - ctx.stroke() - ctx.clip() - ctx.fillStyle = BoxColor - ctx.globalAlpha = 1 - ctx.fillRect(70, 320, 180, 50) - ctx.globalAlpha = 1 - ctx.fillStyle = '#ffffff' - ctx.font = '32px "Sans Serif"' - ctx.textAlign = 'center' - ctx.fillText(TextEXP, 160, 358) - ctx.restore() - - ctx.save() - RoundedBox(ctx, 70, 240, 180, 50, 20) - ctx.strokeStyle = '#BFC85A22' - ctx.stroke() - ctx.clip() - ctx.fillStyle = BoxColor - ctx.globalAlpha = 1 - ctx.fillRect(70, 240, 180, 50, 50) - ctx.globalAlpha = 1 - ctx.fillStyle = '#ffffff' - ctx.font = '32px "Sans Serif"' - ctx.textAlign = 'center' - ctx.fillText(LvlText, 70 + 180 / 2, 278) - ctx.restore() - - ctx.save() - ctx.textAlign = 'left' - ctx.fillStyle = '#ffffff' - ctx.shadowColor = '#000000' - ctx.shadowBlur = 15 - ctx.shadowOffsetX = 1 - ctx.shadowOffsetY = 1 - ctx.font = '39px "Sans Serif"' - ctx.fillText(Username, 390, 80) - ctx.restore() - - ctx.save() - ctx.textAlign = 'right' - ctx.fillStyle = '#ffffff' - ctx.shadowColor = '#000000' - ctx.shadowBlur = 15 - ctx.shadowOffsetX = 1 - ctx.shadowOffsetY = 1 - ctx.font = '55px "Sans Serif"' - ctx.fillText('#' + Rank, canvas.width - 55, 80) - ctx.restore() - - ctx.save() - RoundedBox(ctx, 390, 305, 660, 70, Number(20)) - ctx.strokeStyle = '#BFC85A22' - ctx.stroke() - ctx.clip() - ctx.fillStyle = '#ffffff' - ctx.font = `${fsiz} "Sans Serif"` - ctx.textAlign = 'center' - ctx.fillText(message.guild.name, 720, 355) - ctx.globalAlpha = 0.2 - ctx.fillRect(390, 305, 660, 70) - ctx.restore() - - ctx.save() - RoundedBox(ctx, 390, 145, 660, 50, Number(BarRadius)) - ctx.strokeStyle = '#BFC85A22' - ctx.stroke() - ctx.clip() - ctx.fillStyle = LevelBarBackground - ctx.globalAlpha = 0.2 - ctx.fillRect(390, 145, 660, 50, 50) - ctx.restore() - - const percent = (100 * CurrentXP) / NeededXP - const progress = (percent * 660) / 100 - - ctx.save() - RoundedBox(ctx, 390, 145, progress, 50, Number(BarRadius)) - ctx.strokeStyle = '#BFC85A22' - ctx.stroke() - ctx.clip() - ctx.fillStyle = LevelBarFill - ctx.globalAlpha = 0.5 - ctx.fillRect(390, 145, progress, 50, 50) - ctx.restore() - - ctx.save() - ctx.textAlign = 'left' - ctx.fillStyle = '#ffffff' - ctx.globalAlpha = 0.8 - ctx.font = '30px "Sans Serif"' - ctx.fillText('Next Level: ' + shortener(NeededXP) + ' XP', 390, 230) - ctx.restore() - - const latestXP = Number(CurrentXP) - Number(NeededXP) + ); + + ctx.lineTo(Number(BackgroundRadius), 400); + ctx.quadraticCurveTo(0, 400, 0, 400 - Number(BackgroundRadius)); + ctx.lineTo(0, Number(BackgroundRadius)); + ctx.quadraticCurveTo(0, 0, Number(BackgroundRadius), 0); + ctx.closePath(); + ctx.clip(); + ctx.fillStyle = '#000000'; + ctx.fillRect(0, 0, 1080, 400); + let background = await Canvas.loadImage(BackGroundImg); + ctx.globalAlpha = 0.7; + ctx.drawImage(background, 0, 0, 1080, 400); + ctx.restore(); + + ctx.fillStyle = DrawLayerColor; + ctx.globalAlpha = DrawLayerOpacity; + ctx.fillRect(40, 0, 240, canvas.height); + ctx.globalAlpha = 1; + + let avatar = await Canvas.loadImage(member.displayAvatarURL()); + ctx.save(); + RoundedBox(ctx, 70, 30, 180, 180, Number(AvatarRoundRadius)); + ctx.strokeStyle = BoxColor; + ctx.lineWidth = 15; + ctx.stroke(); + ctx.clip(); + ctx.drawImage(avatar, 70, 30, 180, 180); + ctx.restore(); + + ctx.save(); + RoundedBox(ctx, 70, 240 + 50 + 30, 180, 50, 20); + ctx.strokeStyle = '#BFC85A22'; + ctx.stroke(); + ctx.clip(); + ctx.fillStyle = BoxColor; + ctx.globalAlpha = 1; + ctx.fillRect(70, 320, 180, 50); + ctx.globalAlpha = 1; + ctx.fillStyle = '#ffffff'; + ctx.font = '32px "Sans Serif"'; + ctx.textAlign = 'center'; + ctx.fillText(TextEXP, 160, 358); + ctx.restore(); + + ctx.save(); + RoundedBox(ctx, 70, 240, 180, 50, 20); + ctx.strokeStyle = '#BFC85A22'; + ctx.stroke(); + ctx.clip(); + ctx.fillStyle = BoxColor; + ctx.globalAlpha = 1; + ctx.fillRect(70, 240, 180, 50, 50); + ctx.globalAlpha = 1; + ctx.fillStyle = '#ffffff'; + ctx.font = '32px "Sans Serif"'; + ctx.textAlign = 'center'; + ctx.fillText(LvlText, 70 + 180 / 2, 278); + ctx.restore(); + + ctx.save(); + ctx.textAlign = 'left'; + ctx.fillStyle = '#ffffff'; + ctx.shadowColor = '#000000'; + ctx.shadowBlur = 15; + ctx.shadowOffsetX = 1; + ctx.shadowOffsetY = 1; + ctx.font = '39px "Sans Serif"'; + ctx.fillText(Username, 390, 80); + ctx.restore(); + + ctx.save(); + ctx.textAlign = 'right'; + ctx.fillStyle = '#ffffff'; + ctx.shadowColor = '#000000'; + ctx.shadowBlur = 15; + ctx.shadowOffsetX = 1; + ctx.shadowOffsetY = 1; + ctx.font = '55px "Sans Serif"'; + ctx.fillText('#' + Rank, canvas.width - 55, 80); + ctx.restore(); + + ctx.save(); + RoundedBox(ctx, 390, 305, 660, 70, Number(20)); + ctx.strokeStyle = '#BFC85A22'; + ctx.stroke(); + ctx.clip(); + ctx.fillStyle = '#ffffff'; + ctx.font = `${fsiz} "Sans Serif"`; + ctx.textAlign = 'center'; + ctx.fillText(message.guild.name, 720, 355); + ctx.globalAlpha = 0.2; + ctx.fillRect(390, 305, 660, 70); + ctx.restore(); + + ctx.save(); + RoundedBox(ctx, 390, 145, 660, 50, Number(BarRadius)); + ctx.strokeStyle = '#BFC85A22'; + ctx.stroke(); + ctx.clip(); + ctx.fillStyle = LevelBarBackground; + ctx.globalAlpha = 0.2; + ctx.fillRect(390, 145, 660, 50, 50); + ctx.restore(); + + const percent = (100 * CurrentXP) / NeededXP; + const progress = (percent * 660) / 100; + + ctx.save(); + RoundedBox(ctx, 390, 145, progress, 50, Number(BarRadius)); + ctx.strokeStyle = '#BFC85A22'; + ctx.stroke(); + ctx.clip(); + ctx.fillStyle = LevelBarFill; + ctx.globalAlpha = 0.5; + ctx.fillRect(390, 145, progress, 50, 50); + ctx.restore(); + + ctx.save(); + ctx.textAlign = 'left'; + ctx.fillStyle = '#ffffff'; + ctx.globalAlpha = 0.8; + ctx.font = '30px "Sans Serif"'; + ctx.fillText('Next Level: ' + shortener(NeededXP) + ' XP', 390, 230); + ctx.restore(); + + const latestXP = Number(CurrentXP) - Number(NeededXP); const textXPEdited = TextXpNeded.replace(/{needed}/g, shortener(NeededXP).toString()) .replace(/{current}/g, shortener(CurrentXP).toString()) - .replace(/{latest}/g, latestXP.toString()) - ctx.textAlign = 'center' - ctx.fillStyle = '#474747' - ctx.globalAlpha = 1 - ctx.font = '30px "Sans Serif"' - ctx.fillText(textXPEdited, 730, 180) + .replace(/{latest}/g, latestXP.toString()); + ctx.textAlign = 'center'; + ctx.fillStyle = '#474747'; + ctx.globalAlpha = 1; + ctx.font = '30px "Sans Serif"'; + ctx.fillText(textXPEdited, 730, 180); return { attachment: canvas.toBuffer('image/webp'), description: AttachmentDesc, name: AttachmentName - } + }; } catch (err) { - console.log(`[XP] Error Occured. | rankCard | Error: ${err.stack}`) + console.log(`[XP] Error Occured. | rankCard | Error: ${err.stack}`); } } } -module.exports = rank \ No newline at end of file +function RoundedBox(ctx, x, y, width, height, radius) { + ctx.beginPath(); + ctx.moveTo(x + radius, y); + ctx.lineTo(x + width - radius, y); + ctx.quadraticCurveTo(x + width, y, x + width, y + radius); + ctx.lineTo(x + width, y + height - radius); + ctx.quadraticCurveTo( + x + width, + y + height, + x + width - radius, + y + height + ); + ctx.lineTo(x + radius, y + height); + ctx.quadraticCurveTo(x, y + height, x, y + height - radius); + ctx.lineTo(x, y + radius); + ctx.quadraticCurveTo(x, y, x + radius, y); + ctx.closePath(); +} + +function shortener(count) { + const COUNT_ABBRS = [ + '', + 'k', + 'M', + 'B', + 'T', + 'Q', + 'Q+', + 'S', + 'S+', + 'O', + 'N', + 'D', + 'U' + ]; + + const i = 0 === count ? count : Math.floor(Math.log(count) / Math.log(1000)); + let result = parseFloat((count / Math.pow(1000, i)).toFixed(2)); + result += `${COUNT_ABBRS[i]}`; + return result; +} + +module.exports = rank; + diff --git a/src/reset.js b/src/reset.js index abd0be7..7d0a40a 100644 --- a/src/reset.js +++ b/src/reset.js @@ -1,4 +1,4 @@ -const levels = require('../src/models/level.js') +const levels = require('../src/models/level.js'); /** * @param {string} userID @@ -6,17 +6,17 @@ const levels = require('../src/models/level.js') */ async function reset(userID, guildID) { - if (!userID) throw new Error('[XP] User ID was not provided.') + if (!userID) throw new Error('[XP] User ID was not provided.'); - if (!guildID) throw new Error('[XP] User ID was not provided.') + if (!guildID) throw new Error('[XP] User ID was not provided.'); - await levels - .findOneAndUpdate({ user: userID, guild: guildID }, { xp: 0, level: 0 }) - .catch((err) => { - throw new Error(err) - }) + await levels + .findOneAndUpdate({ user: userID, guild: guildID }, { xp: 0, level: 0 }) + .catch((err) => { + throw new Error(err); + }); - return { user: userID, guild: guildID, xp: 0, level: 0 } + return { user: userID, guild: guildID, xp: 0, level: 0 }; } -module.exports = reset +module.exports = reset; diff --git a/src/roleSetup.js b/src/roleSetup.js index 3efafa9..3fb24e2 100644 --- a/src/roleSetup.js +++ b/src/roleSetup.js @@ -1,121 +1,121 @@ -const lrole = require('../src/models/lvlrole.js') +const lrole = require('../src/models/lvlrole.js'); class roleSetup { - /** + /** * @param {Discord.Client} client * @param {string} guildID * @param {import('../index').lvladdOptions} options */ - static async add(client, guildID, options = []) { - let rol = await lrole.findOne({ - gid: guildID, - lvlrole: { - lvl: options.level, - role: options.role - } - }) - - let g = client.guilds.cache.get(guildID) - - let roll = g.roles.cache.find((r) => r.id === options.role) - - if (roll) { - if (rol) throw new Error('Level Already Exist. Use delete') - else if (!rol) { - let newrol = await lrole.findOne({ - gid: guildID - }) - - if (!newrol) { - newrol = new lrole({ + static async add(client, guildID, options = []) { + let rol = await lrole.findOne({ gid: guildID, - lvlrole: [] - }) - - await newrol.save() - } - - newrol.lvlrole.push({ lvl: options.level, role: options.role }) - - await newrol - .save() - .catch((e) => - console.log(`[XP] Failed to add lvlrole to database | ${e}`) - ) - - return true - } - } else { - throw new Error( - 'Role ID is invalid. | ' + + lvlrole: { + lvl: options.level, + role: options.role + } + }); + + let g = client.guilds.cache.get(guildID); + + let roll = g.roles.cache.find((r) => r.id === options.role); + + if (roll) { + if (rol) throw new Error('Level Already Exist. Use delete'); + else if (!rol) { + let newrol = await lrole.findOne({ + gid: guildID + }); + + if (!newrol) { + newrol = new lrole({ + gid: guildID, + lvlrole: [] + }); + + await newrol.save(); + } + + newrol.lvlrole.push({ lvl: options.level, role: options.role }); + + await newrol + .save() + .catch((e) => + console.log(`[XP] Failed to add lvlrole to database | ${e}`) + ); + + return true; + } + } else { + throw new Error( + 'Role ID is invalid. | ' + `Guild ID: ${guildID} | Role ID: ${options.role}` - ) + ); + } } - } - /** + /** * @param {Discord.Client} client * @param {string} guildID * @param {import('../index').lvlremoveOptions} options */ - static async remove(client, guildID, options = []) { - let rol = await lrole.find({ - gid: guildID - }) - - if (!rol || rol.length === 0) - throw new Error('Level role with this level does not exist') - rol = rol[0].lvlrole.find((item) => item.lvl === options.level) || undefined - - if (rol) { - let newrol = await lrole.findOneAndUpdate( - { - gid: guildID - }, - { - $pull: { lvlrole: { lvl: options.level } } - } - ) - - return true - } else throw new Error('Level role with this level does not exist') - } + static async remove(client, guildID, options = []) { + let rol = await lrole.find({ + gid: guildID + }); + + if (!rol || rol.length === 0) + throw new Error('Level role with this level does not exist'); + rol = rol[0].lvlrole.find((item) => item.lvl === options.level) || undefined; + + if (rol) { + await lrole.findOneAndUpdate( + { + gid: guildID + }, + { + $pull: { lvlrole: { lvl: options.level } } + } + ); + + return true; + } else throw new Error('Level role with this level does not exist'); + } - /** + /** * @param {Discord.Client} client * @param {string} guildID */ - static async fetch(client, guildID) { - let rol = await lrole.find({ - gid: guildID - }) + static async fetch(client, guildID) { + let rol = await lrole.find({ + gid: guildID + }); - if (!rol || rol.length === 0) return + if (!rol || rol.length === 0) return; - return rol[0].lvlrole - } + return rol[0].lvlrole; + } - /** + /** * @param {Discord.Client} client * @param {string} guildID * @param {string} level */ - static async find(client, guildID, level) { - let rol = await lrole.find({ - gid: guildID - }) + static async find(client, guildID, level) { + let rol = await lrole.find({ + gid: guildID + }); - if (!rol || !rol.length) return - rol = rol[0].lvlrole.filter((i) => i.lvl == level) || undefined + if (!rol || !rol.length) return; + rol = rol[0].lvlrole.filter((i) => i.lvl == level) || undefined; - if (rol) { - return rol + if (rol) { + return rol; + } } - } } -module.exports = roleSetup +module.exports = roleSetup; diff --git a/src/setLevel.js b/src/setLevel.js index 8cf09fd..56d57f0 100644 --- a/src/setLevel.js +++ b/src/setLevel.js @@ -1,5 +1,5 @@ -const levels = require('../src/models/level.js') -let { roleSetup } = require('../simplyxp') +const levels = require('../src/models/level.js'); +let { roleSetup } = require('../simplyxp'); /** * @param {Discord.Message} message @@ -8,63 +8,63 @@ let { roleSetup } = require('../simplyxp') * @param {string} level */ async function setLevel(message, userID, guildID, level) { - if (!userID) throw new Error('[XP] User ID was not provided.') + if (!userID) throw new Error('[XP] User ID was not provided.'); - if (!guildID) throw new Error('[XP] Guild ID was not provided.') + if (!guildID) throw new Error('[XP] Guild ID was not provided.'); - if (!level) throw new Error('[XP] Level amount is not provided.') + if (!level) throw new Error('[XP] Level amount is not provided.'); - let { client } = message + let { client } = message; - const user = await levels.findOne({ user: userID, guild: guildID }) + const user = await levels.findOne({ user: userID, guild: guildID }); - if (!user) { - const newUser = new levels({ - user: userID, - guild: guildID, - xp: 0, - level: 0 - }) + if (!user) { + const newUser = new levels({ + user: userID, + guild: guildID, + xp: 0, + level: 0 + }); - await newUser - .save() - .catch((e) => console.log(`[XP] Failed to save new user to database`)) + await newUser + .save() + .catch(() => console.log('[XP] Failed to save new user to database')); - let xp = (level * 10) ** 2 + let xp = (level * 10) ** 2; - return { - level: level, - exp: xp - } - } - let level1 = user.level - - user.xp = (level * 10) ** 2 - user.level = Math.floor(0.1 * Math.sqrt(user.xp)) - - await user - .save() - .catch((e) => - console.log(`[XP] Failed to set Level | User: ${userID} | Err: ${e}`) - ) - - if (level1 !== level) { - let data = { - xp: user.xp, - level: user.level, - userID, - guildID + return { + level: level, + exp: xp + }; } + let level1 = user.level; + + user.xp = (level * 10) ** 2; + user.level = Math.floor(0.1 * Math.sqrt(user.xp)); + + await user + .save() + .catch((e) => + console.log(`[XP] Failed to set Level | User: ${userID} | Err: ${e}`) + ); - let role = await roleSetup.find(client, guildID, level) + if (level1 !== level) { + let data = { + xp: user.xp, + level: user.level, + userID, + guildID + }; - client.emit('levelUp', message, data, role) - } + let role = await roleSetup.find(client, guildID, level); - return { - level: user.level, - xp: user.xp - } + client.emit('levelUp', message, data, role); + } + + return { + level: user.level, + xp: user.xp + }; } -module.exports = setLevel +module.exports = setLevel; diff --git a/src/setXP.js b/src/setXP.js index 65131b9..100d3e3 100644 --- a/src/setXP.js +++ b/src/setXP.js @@ -1,4 +1,4 @@ -const levels = require('../src/models/level.js') +const levels = require('../src/models/level.js'); /** * @param {string} userID @@ -7,45 +7,45 @@ const levels = require('../src/models/level.js') */ async function setXP(userID, guildID, xp) { - if (!userID) throw new Error('[XP] User ID was not provided.') + if (!userID) throw new Error('[XP] User ID was not provided.'); - if (!guildID) throw new Error('[XP] Guild ID was not provided.') + if (!guildID) throw new Error('[XP] Guild ID was not provided.'); - if (!xp) throw new Error('[XP] XP amount is not provided.') + if (!xp) throw new Error('[XP] XP amount is not provided.'); - if (Number(xp).toString() === 'NaN') - throw new Error('[XP] XP amount is not a number.') + if (Number(xp).toString() === 'NaN') + throw new Error('[XP] XP amount is not a number.'); - const user = await levels.findOne({ user: userID, guild: guildID }) + const user = await levels.findOne({ user: userID, guild: guildID }); - let lvl = Math.floor(0.1 * Math.sqrt(xp)) + let lvl = Math.floor(0.1 * Math.sqrt(xp)); - if (!user) { - const newUser = new levels({ - user: userID, - guild: guildID, - xp: xp, - level: lvl - }) + if (!user) { + const newUser = new levels({ + user: userID, + guild: guildID, + xp: xp, + level: lvl + }); - await newUser - .save() - .catch((e) => console.log(`[XP] Failed to save new use to database`)) + await newUser + .save() + .catch(() => console.log('[XP] Failed to save new use to database')); - return { - xp: 0 + return { + xp: 0 + }; } - } - user.xp = xp - user.level = Math.floor(0.1 * Math.sqrt(user.xp)) + user.xp = xp; + user.level = Math.floor(0.1 * Math.sqrt(user.xp)); - await user - .save() - .catch((e) => - console.log(`[XP] Failed to set XP | User: ${userID} | Err: ${e}`) - ) + await user + .save() + .catch((e) => + console.log(`[XP] Failed to set XP | User: ${userID} | Err: ${e}`) + ); - return { xp } + return { xp }; } -module.exports = setXP +module.exports = setXP;