simply-xp 1.1.5-beta → 1.1.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/README.md +16 -10
  2. package/package.json +1 -1
  3. package/src/rank.js +287 -285
package/README.md CHANGED
@@ -1,4 +1,4 @@
1
- <p align="center"><img align="center" style="margin-bottom:-6px" src="https://i.imgur.com/BiaHJA7.png?maxwidth=128&fidelity=grand"></p>
1
+ <p align="center"><img align="center" style="width: 128px" src="https://user-images.githubusercontent.com/71836991/173240203-ca92976f-2e5e-4a85-ba5e-155796eac889.png"></p>
2
2
 
3
3
  <h2 style="font-size:2.5rem;" align="center">Simply-XP</h2>
4
4
 
@@ -28,7 +28,12 @@ yarn add simply-xp
28
28
 
29
29
  <br>
30
30
 
31
- # 🎉 What's New 🎉
31
+ # 👋 Goodbye XP 👋
32
+
33
+
34
+ > We are deprecating, Because making an XP system is already easy. And working on a package which not much people uses is an time waste. We are not deleting the package whatsoever !
35
+
36
+ # 👋 Last Update log
32
37
 
33
38
  - Fixed bugs
34
39
  - New `addLevel(), setLevel(), reset()`
@@ -38,15 +43,16 @@ yarn add simply-xp
38
43
  - Re-coded to squeeze bugs
39
44
  - Bug Fixes
40
45
 
41
- # But Why ?
46
+ # ~~But Why ?~~
47
+ ## We do not recommend using this package as you can encounter bugs.
42
48
 
43
- - Easiest XP System in Discord.js
44
- - Fastest Support ever
45
- - Rank Card Maker
46
- - Beginner Friendly
47
- - Easier than other XP Systems
48
- - Inbuilt Auto Roles system
49
- - Flexible and simple at the same time
49
+ - ~~Easiest XP System in Discord.js~~
50
+ - ~~Fastest Support ever~~
51
+ - ~~Rank Card Maker~~
52
+ - ~~Beginner Friendly~~
53
+ - ~~Easier than other XP Systems~~
54
+ - ~~Inbuilt Auto Roles system~~
55
+ - ~~Flexible and simple at the same time~~
50
56
 
51
57
  `Reconstructed discord-xp to give you things simpler ;)`
52
58
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "simply-xp",
3
- "version": "1.1.5-beta",
3
+ "version": "1.1.5",
4
4
  "description": "A Simple, Easy and Beginner Friendly XP System",
5
5
  "main": "simplyxp.js",
6
6
  "typings": "index.d.ts",
package/src/rank.js CHANGED
@@ -1,285 +1,287 @@
1
- let Discord = require('discord.js')
2
- const levels = require('../src/models/level.js')
3
- const { join } = require('path')
4
-
5
- /**
6
- * @param {Discord.Message} message
7
- * @param {string} userID
8
- * @param {string} guildID
9
- * @param {import('../index').rankOptions} options
10
- */
11
-
12
- async function rank(message, userID, guildID, options = []) {
13
- if (!userID) throw new Error('[XP] User ID was not provided.')
14
-
15
- if (!guildID) throw new Error('[XP] Guild ID was not provided.')
16
-
17
- const user = await levels.findOne({
18
- user: userID,
19
- guild: guildID
20
- })
21
- if (!user) console.error('[XP] NO_DATA | User has no XP data.')
22
-
23
- const leaderboard = await levels
24
- .find({
25
- guild: guildID
26
- })
27
- .sort([['xp', 'descending']])
28
- .exec()
29
-
30
- user.position = leaderboard.findIndex((i) => i.user === userID) + 1
31
-
32
- let targetxp = user.level + 1
33
-
34
- let target = targetxp * targetxp * 100
35
-
36
- return rankCard(message, {
37
- level: user.level,
38
- currentXP: user.xp,
39
- neededXP: target,
40
- rank: user.position,
41
- background: options.background,
42
- color: options.color,
43
- member: message.guild.members.cache.get(userID)?.user
44
- })
45
-
46
- async function rankCard(message, options = []) {
47
- try {
48
- const Canvas = require('canvas')
49
- const { registerFont } = require('canvas')
50
- registerFont(join(__dirname, 'Fonts', 'Poppins-SemiBold.ttf'), {
51
- family: 'Poppins-Regular'
52
- })
53
- registerFont(join(__dirname, 'Fonts', 'Poppins-SemiBold.ttf'), {
54
- family: 'Poppins-Bold'
55
- })
56
-
57
- function shortener(count) {
58
- const COUNT_ABBRS = ['', 'k', 'M', 'T']
59
-
60
- const i =
61
- 0 === count ? count : Math.floor(Math.log(count) / Math.log(1000))
62
- let result = parseFloat((count / Math.pow(1000, i)).toFixed(2))
63
- result += `${COUNT_ABBRS[i]}`
64
- return result
65
- }
66
-
67
- const member = options.member
68
-
69
- const canvas = Canvas.createCanvas(1080, 400),
70
- ctx = canvas.getContext('2d')
71
-
72
- const name = member.tag
73
- const noSymbols = (string) => string.replace(/[\u007f-\uffff]/g, '')
74
-
75
- let fsiz = '45px'
76
- if (message.guild.name.length >= 23) {
77
- fsiz = '38px'
78
- }
79
- if (message.guild.name.length >= 40) {
80
- fsiz = '28px'
81
- }
82
- if (message.guild.name.length >= 63) {
83
- fsiz = '22px'
84
- }
85
-
86
- let BackgroundRadius = '20',
87
- BackGroundImg =
88
- options.background ||
89
- 'https://media.discordapp.net/attachments/868506665102762034/876750913866461185/photo-1579546929518-9e396f3cc809.png?width=640&height=427',
90
- AttachmentName = 'rank.png',
91
- Username = noSymbols(name),
92
- AvatarRoundRadius = '50',
93
- DrawLayerColor = '#000000',
94
- DrawLayerOpacity = '0.4',
95
- BoxColor = options.color || '#096DD1',
96
- LevelBarFill = options.lvlbar || '#ffffff',
97
- LevelBarBackground = options.lvlbarBg || '#ffffff',
98
- Rank = options.rank,
99
- TextEXP = shortener(options.currentXP) + ' xp',
100
- LvlText = `Level ${shortener(options.level)}`,
101
- BarRadius = '20',
102
- TextXpNeded = '{current}/{needed}',
103
- CurrentXP = options.currentXP,
104
- NeededXP = options.neededXP
105
-
106
- ctx.beginPath()
107
- ctx.moveTo(0 + Number(BackgroundRadius), 0)
108
- ctx.lineTo(0 + 1080 - Number(BackgroundRadius), 0)
109
- ctx.quadraticCurveTo(0 + 1080, 0, 0 + 1080, 0 + Number(BackgroundRadius))
110
- ctx.lineTo(0 + 1080, 0 + 400 - Number(BackgroundRadius))
111
- ctx.quadraticCurveTo(
112
- 0 + 1080,
113
- 0 + 400,
114
- 0 + 1080 - Number(BackgroundRadius),
115
- 0 + 400
116
- )
117
-
118
- ctx.lineTo(0 + Number(BackgroundRadius), 0 + 400)
119
- ctx.quadraticCurveTo(0, 0 + 400, 0, 0 + 400 - Number(BackgroundRadius))
120
- ctx.lineTo(0, 0 + Number(BackgroundRadius))
121
- ctx.quadraticCurveTo(0, 0, 0 + Number(BackgroundRadius), 0)
122
- ctx.closePath()
123
- ctx.clip()
124
- ctx.fillStyle = '#000000'
125
- ctx.fillRect(0, 0, 1080, 400)
126
- let background = await Canvas.loadImage(BackGroundImg)
127
- ctx.globalAlpha = 0.7
128
- ctx.drawImage(background, 0, 0, 1080, 400)
129
- ctx.restore()
130
-
131
- ctx.fillStyle = DrawLayerColor
132
- ctx.globalAlpha = DrawLayerOpacity
133
- ctx.fillRect(40, 0, 240, canvas.height)
134
- ctx.globalAlpha = 1
135
-
136
- function RoundedBox(ctx, x, y, width, height, radius) {
137
- ctx.beginPath()
138
- ctx.moveTo(x + radius, y)
139
- ctx.lineTo(x + width - radius, y)
140
- ctx.quadraticCurveTo(x + width, y, x + width, y + radius)
141
- ctx.lineTo(x + width, y + height - radius)
142
- ctx.quadraticCurveTo(
143
- x + width,
144
- y + height,
145
- x + width - radius,
146
- y + height
147
- )
148
- ctx.lineTo(x + radius, y + height)
149
- ctx.quadraticCurveTo(x, y + height, x, y + height - radius)
150
- ctx.lineTo(x, y + radius)
151
- ctx.quadraticCurveTo(x, y, x + radius, y)
152
- ctx.closePath()
153
- }
154
-
155
- let avatar = await Canvas.loadImage(
156
- member.displayAvatarURL({ dynamic: true, format: 'png' })
157
- )
158
- ctx.save()
159
- RoundedBox(ctx, 40 + 30, 30, 180, 180, Number(AvatarRoundRadius))
160
- ctx.strokeStyle = BoxColor
161
- ctx.lineWidth = '10'
162
- ctx.stroke()
163
- ctx.clip()
164
- ctx.drawImage(avatar, 40 + 30, 30, 180, 180)
165
- ctx.restore()
166
-
167
- ctx.save()
168
- RoundedBox(ctx, 40 + 30, 30 + 180 + 30 + 50 + 30, 180, 50, 20)
169
- ctx.strokeStyle = '#BFC85A22'
170
- ctx.stroke()
171
- ctx.clip()
172
- ctx.fillStyle = BoxColor
173
- ctx.globalAlpha = '1'
174
- ctx.fillRect(40 + 30, 30 + 180 + 30 + 50 + 30, 180, 50)
175
- ctx.globalAlpha = 1
176
- ctx.fillStyle = '#ffffff'
177
- ctx.font = '32px "Poppins-Bold"'
178
- ctx.textAlign = 'center'
179
- ctx.fillText(TextEXP, 40 + 30 + 180 / 2, 30 + 180 + 30 + 30 + 50 + 38)
180
- ctx.restore()
181
-
182
- ctx.save()
183
- RoundedBox(ctx, 40 + 30, 30 + 180 + 30, 180, 50, 20)
184
- ctx.strokeStyle = '#BFC85A22'
185
- ctx.stroke()
186
- ctx.clip()
187
- ctx.fillStyle = BoxColor
188
- ctx.globalAlpha = '1'
189
- ctx.fillRect(40 + 30, 30 + 180 + 30, 180, 50, 50)
190
- ctx.globalAlpha = 1
191
- ctx.fillStyle = '#ffffff'
192
- ctx.font = '32px "Poppins-Bold"'
193
- ctx.textAlign = 'center'
194
- ctx.fillText(LvlText, 40 + 30 + 180 / 2, 30 + 180 + 30 + 38)
195
- ctx.restore()
196
-
197
- ctx.save()
198
- ctx.textAlign = 'left'
199
- ctx.fillStyle = '#ffffff'
200
- ctx.shadowColor = '#000000'
201
- ctx.shadowBlur = 15
202
- ctx.shadowOffsetX = 1
203
- ctx.shadowOffsetY = 1
204
- ctx.font = '39px "Poppins-Bold"'
205
- ctx.fillText(Username, 390, 80)
206
- ctx.restore()
207
-
208
- ctx.save()
209
- ctx.textAlign = 'right'
210
- ctx.fillStyle = '#ffffff'
211
- ctx.shadowColor = '#000000'
212
- ctx.shadowBlur = 15
213
- ctx.shadowOffsetX = 1
214
- ctx.shadowOffsetY = 1
215
- ctx.font = '55px "Poppins-Bold"'
216
- ctx.fillText('#' + Rank, canvas.width - 50 - 5, 80)
217
- ctx.restore()
218
-
219
- ctx.save()
220
- RoundedBox(ctx, 390, 305, 660, 70, Number(20))
221
- ctx.strokeStyle = '#BFC85A22'
222
- ctx.stroke()
223
- ctx.clip()
224
- ctx.fillStyle = '#ffffff'
225
- ctx.font = `${fsiz} "Poppins-Bold"`
226
- ctx.textAlign = 'center'
227
- ctx.fillText(message.guild.name, 60 + 660, 355)
228
- ctx.globalAlpha = '0.2'
229
- ctx.fillRect(390, 305, 660, 70)
230
- ctx.restore()
231
-
232
- ctx.save()
233
- RoundedBox(ctx, 390, 145, 660, 50, Number(BarRadius))
234
- ctx.strokeStyle = '#BFC85A22'
235
- ctx.stroke()
236
- ctx.clip()
237
- ctx.fillStyle = LevelBarBackground
238
- ctx.globalAlpha = '0.2'
239
- ctx.fillRect(390, 145, 660, 50, 50)
240
- ctx.restore()
241
-
242
- const percent = (100 * CurrentXP) / NeededXP
243
- const progress = (percent * 660) / 100
244
-
245
- ctx.save()
246
- RoundedBox(ctx, 390, 145, progress, 50, Number(BarRadius))
247
- ctx.strokeStyle = '#BFC85A22'
248
- ctx.stroke()
249
- ctx.clip()
250
- ctx.fillStyle = LevelBarFill
251
- ctx.globalAlpha = '0.5'
252
- ctx.fillRect(390, 145, progress, 50, 50)
253
- ctx.restore()
254
-
255
- ctx.save()
256
- ctx.textAlign = 'left'
257
- ctx.fillStyle = '#ffffff'
258
- ctx.globalAlpha = '0.8'
259
- ctx.font = '30px "Poppins-Bold"'
260
- ctx.fillText('Next Level: ' + shortener(NeededXP) + ' xp', 390, 230)
261
- ctx.restore()
262
-
263
- const latestXP = Number(CurrentXP) - Number(NeededXP)
264
- const textXPEdited = TextXpNeded.replace(/{needed}/g, shortener(NeededXP))
265
- .replace(/{current}/g, shortener(CurrentXP))
266
- .replace(/{latest}/g, latestXP)
267
- ctx.textAlign = 'center'
268
- ctx.fillStyle = '#474747'
269
- ctx.globalAlpha = 1
270
- ctx.font = '30px "Poppins-Bold"'
271
- ctx.fillText(textXPEdited, 730, 180)
272
-
273
- const attachment = new Discord.MessageAttachment(
274
- canvas.toBuffer(),
275
- AttachmentName
276
- )
277
-
278
- return attachment
279
- } catch (err) {
280
- console.log(`[XP] Error Occured. | rankCard | Error: ${err.stack}`)
281
- }
282
- }
283
- }
284
-
285
- module.exports = rank
1
+ let Discord = require('discord.js')
2
+ const levels = require('../src/models/level.js')
3
+ const { join } = require('path')
4
+
5
+ /**
6
+ * @param {Discord.Message} message
7
+ * @param {string} userID
8
+ * @param {string} guildID
9
+ * @param {import('../index').rankOptions} options
10
+ */
11
+
12
+ async function rank(message, userID, guildID, options = []) {
13
+ if (!userID) throw new Error('[XP] User ID was not provided.')
14
+
15
+ if (!guildID) throw new Error('[XP] Guild ID was not provided.')
16
+
17
+ const user = await levels.findOne({
18
+ user: userID,
19
+ guild: guildID
20
+ })
21
+ if (!user) console.error('[XP] NO_DATA | User has no XP data.')
22
+
23
+ const leaderboard = await levels
24
+ .find({
25
+ guild: guildID
26
+ })
27
+ .sort([['xp', 'descending']])
28
+ .exec()
29
+
30
+ user.position = leaderboard.findIndex((i) => i.user === userID) + 1
31
+
32
+ let targetxp = user.level + 1
33
+
34
+ let target = targetxp * targetxp * 100
35
+
36
+ return rankCard(message, {
37
+ level: user.level,
38
+ currentXP: user.xp,
39
+ neededXP: target,
40
+ rank: user.position,
41
+ background: options.background,
42
+ color: options.color,
43
+ lvlbar: options.lvlbar,
44
+ lvlbarBg: options.lvlbarBg,
45
+ member: message.guild.members.cache.get(userID)?.user
46
+ })
47
+
48
+ async function rankCard(message, options = []) {
49
+ try {
50
+ const Canvas = require('canvas')
51
+ const { registerFont } = require('canvas')
52
+ registerFont(join(__dirname, 'Fonts', 'Poppins-SemiBold.ttf'), {
53
+ family: 'Poppins-Regular'
54
+ })
55
+ registerFont(join(__dirname, 'Fonts', 'Poppins-SemiBold.ttf'), {
56
+ family: 'Poppins-Bold'
57
+ })
58
+
59
+ function shortener(count) {
60
+ const COUNT_ABBRS = ['', 'k', 'M', 'T']
61
+
62
+ const i =
63
+ 0 === count ? count : Math.floor(Math.log(count) / Math.log(1000))
64
+ let result = parseFloat((count / Math.pow(1000, i)).toFixed(2))
65
+ result += `${COUNT_ABBRS[i]}`
66
+ return result
67
+ }
68
+
69
+ const member = options.member
70
+
71
+ const canvas = Canvas.createCanvas(1080, 400),
72
+ ctx = canvas.getContext('2d')
73
+
74
+ const name = member.tag
75
+ const noSymbols = (string) => string.replace(/[\u007f-\uffff]/g, '')
76
+
77
+ let fsiz = '45px'
78
+ if (message.guild.name.length >= 23) {
79
+ fsiz = '38px'
80
+ }
81
+ if (message.guild.name.length >= 40) {
82
+ fsiz = '28px'
83
+ }
84
+ if (message.guild.name.length >= 63) {
85
+ fsiz = '22px'
86
+ }
87
+
88
+ let BackgroundRadius = '20',
89
+ BackGroundImg =
90
+ options.background ||
91
+ 'https://media.discordapp.net/attachments/868506665102762034/876750913866461185/photo-1579546929518-9e396f3cc809.png?width=640&height=427',
92
+ AttachmentName = 'rank.png',
93
+ Username = noSymbols(name),
94
+ AvatarRoundRadius = '50',
95
+ DrawLayerColor = '#000000',
96
+ DrawLayerOpacity = '0.4',
97
+ BoxColor = options.color || '#096DD1',
98
+ LevelBarFill = options.lvlbar || '#ffffff',
99
+ LevelBarBackground = options.lvlbarBg || '#ffffff',
100
+ Rank = options.rank,
101
+ TextEXP = shortener(options.currentXP) + ' xp',
102
+ LvlText = `Level ${shortener(options.level)}`,
103
+ BarRadius = '20',
104
+ TextXpNeded = '{current}/{needed}',
105
+ CurrentXP = options.currentXP,
106
+ NeededXP = options.neededXP
107
+
108
+ ctx.beginPath()
109
+ ctx.moveTo(0 + Number(BackgroundRadius), 0)
110
+ ctx.lineTo(0 + 1080 - Number(BackgroundRadius), 0)
111
+ ctx.quadraticCurveTo(0 + 1080, 0, 0 + 1080, 0 + Number(BackgroundRadius))
112
+ ctx.lineTo(0 + 1080, 0 + 400 - Number(BackgroundRadius))
113
+ ctx.quadraticCurveTo(
114
+ 0 + 1080,
115
+ 0 + 400,
116
+ 0 + 1080 - Number(BackgroundRadius),
117
+ 0 + 400
118
+ )
119
+
120
+ ctx.lineTo(0 + Number(BackgroundRadius), 0 + 400)
121
+ ctx.quadraticCurveTo(0, 0 + 400, 0, 0 + 400 - Number(BackgroundRadius))
122
+ ctx.lineTo(0, 0 + Number(BackgroundRadius))
123
+ ctx.quadraticCurveTo(0, 0, 0 + Number(BackgroundRadius), 0)
124
+ ctx.closePath()
125
+ ctx.clip()
126
+ ctx.fillStyle = '#000000'
127
+ ctx.fillRect(0, 0, 1080, 400)
128
+ let background = await Canvas.loadImage(BackGroundImg)
129
+ ctx.globalAlpha = 0.7
130
+ ctx.drawImage(background, 0, 0, 1080, 400)
131
+ ctx.restore()
132
+
133
+ ctx.fillStyle = DrawLayerColor
134
+ ctx.globalAlpha = DrawLayerOpacity
135
+ ctx.fillRect(40, 0, 240, canvas.height)
136
+ ctx.globalAlpha = 1
137
+
138
+ function RoundedBox(ctx, x, y, width, height, radius) {
139
+ ctx.beginPath()
140
+ ctx.moveTo(x + radius, y)
141
+ ctx.lineTo(x + width - radius, y)
142
+ ctx.quadraticCurveTo(x + width, y, x + width, y + radius)
143
+ ctx.lineTo(x + width, y + height - radius)
144
+ ctx.quadraticCurveTo(
145
+ x + width,
146
+ y + height,
147
+ x + width - radius,
148
+ y + height
149
+ )
150
+ ctx.lineTo(x + radius, y + height)
151
+ ctx.quadraticCurveTo(x, y + height, x, y + height - radius)
152
+ ctx.lineTo(x, y + radius)
153
+ ctx.quadraticCurveTo(x, y, x + radius, y)
154
+ ctx.closePath()
155
+ }
156
+
157
+ let avatar = await Canvas.loadImage(
158
+ member.displayAvatarURL({ dynamic: true, format: 'png' })
159
+ )
160
+ ctx.save()
161
+ RoundedBox(ctx, 40 + 30, 30, 180, 180, Number(AvatarRoundRadius))
162
+ ctx.strokeStyle = BoxColor
163
+ ctx.lineWidth = '10'
164
+ ctx.stroke()
165
+ ctx.clip()
166
+ ctx.drawImage(avatar, 40 + 30, 30, 180, 180)
167
+ ctx.restore()
168
+
169
+ ctx.save()
170
+ RoundedBox(ctx, 40 + 30, 30 + 180 + 30 + 50 + 30, 180, 50, 20)
171
+ ctx.strokeStyle = '#BFC85A22'
172
+ ctx.stroke()
173
+ ctx.clip()
174
+ ctx.fillStyle = BoxColor
175
+ ctx.globalAlpha = '1'
176
+ ctx.fillRect(40 + 30, 30 + 180 + 30 + 50 + 30, 180, 50)
177
+ ctx.globalAlpha = 1
178
+ ctx.fillStyle = '#ffffff'
179
+ ctx.font = '32px "Poppins-Bold"'
180
+ ctx.textAlign = 'center'
181
+ ctx.fillText(TextEXP, 40 + 30 + 180 / 2, 30 + 180 + 30 + 30 + 50 + 38)
182
+ ctx.restore()
183
+
184
+ ctx.save()
185
+ RoundedBox(ctx, 40 + 30, 30 + 180 + 30, 180, 50, 20)
186
+ ctx.strokeStyle = '#BFC85A22'
187
+ ctx.stroke()
188
+ ctx.clip()
189
+ ctx.fillStyle = BoxColor
190
+ ctx.globalAlpha = '1'
191
+ ctx.fillRect(40 + 30, 30 + 180 + 30, 180, 50, 50)
192
+ ctx.globalAlpha = 1
193
+ ctx.fillStyle = '#ffffff'
194
+ ctx.font = '32px "Poppins-Bold"'
195
+ ctx.textAlign = 'center'
196
+ ctx.fillText(LvlText, 40 + 30 + 180 / 2, 30 + 180 + 30 + 38)
197
+ ctx.restore()
198
+
199
+ ctx.save()
200
+ ctx.textAlign = 'left'
201
+ ctx.fillStyle = '#ffffff'
202
+ ctx.shadowColor = '#000000'
203
+ ctx.shadowBlur = 15
204
+ ctx.shadowOffsetX = 1
205
+ ctx.shadowOffsetY = 1
206
+ ctx.font = '39px "Poppins-Bold"'
207
+ ctx.fillText(Username, 390, 80)
208
+ ctx.restore()
209
+
210
+ ctx.save()
211
+ ctx.textAlign = 'right'
212
+ ctx.fillStyle = '#ffffff'
213
+ ctx.shadowColor = '#000000'
214
+ ctx.shadowBlur = 15
215
+ ctx.shadowOffsetX = 1
216
+ ctx.shadowOffsetY = 1
217
+ ctx.font = '55px "Poppins-Bold"'
218
+ ctx.fillText('#' + Rank, canvas.width - 50 - 5, 80)
219
+ ctx.restore()
220
+
221
+ ctx.save()
222
+ RoundedBox(ctx, 390, 305, 660, 70, Number(20))
223
+ ctx.strokeStyle = '#BFC85A22'
224
+ ctx.stroke()
225
+ ctx.clip()
226
+ ctx.fillStyle = '#ffffff'
227
+ ctx.font = `${fsiz} "Poppins-Bold"`
228
+ ctx.textAlign = 'center'
229
+ ctx.fillText(message.guild.name, 60 + 660, 355)
230
+ ctx.globalAlpha = '0.2'
231
+ ctx.fillRect(390, 305, 660, 70)
232
+ ctx.restore()
233
+
234
+ ctx.save()
235
+ RoundedBox(ctx, 390, 145, 660, 50, Number(BarRadius))
236
+ ctx.strokeStyle = '#BFC85A22'
237
+ ctx.stroke()
238
+ ctx.clip()
239
+ ctx.fillStyle = LevelBarBackground
240
+ ctx.globalAlpha = '0.2'
241
+ ctx.fillRect(390, 145, 660, 50, 50)
242
+ ctx.restore()
243
+
244
+ const percent = (100 * CurrentXP) / NeededXP
245
+ const progress = (percent * 660) / 100
246
+
247
+ ctx.save()
248
+ RoundedBox(ctx, 390, 145, progress, 50, Number(BarRadius))
249
+ ctx.strokeStyle = '#BFC85A22'
250
+ ctx.stroke()
251
+ ctx.clip()
252
+ ctx.fillStyle = LevelBarFill
253
+ ctx.globalAlpha = '0.5'
254
+ ctx.fillRect(390, 145, progress, 50, 50)
255
+ ctx.restore()
256
+
257
+ ctx.save()
258
+ ctx.textAlign = 'left'
259
+ ctx.fillStyle = '#ffffff'
260
+ ctx.globalAlpha = '0.8'
261
+ ctx.font = '30px "Poppins-Bold"'
262
+ ctx.fillText('Next Level: ' + shortener(NeededXP) + ' xp', 390, 230)
263
+ ctx.restore()
264
+
265
+ const latestXP = Number(CurrentXP) - Number(NeededXP)
266
+ const textXPEdited = TextXpNeded.replace(/{needed}/g, shortener(NeededXP))
267
+ .replace(/{current}/g, shortener(CurrentXP))
268
+ .replace(/{latest}/g, latestXP)
269
+ ctx.textAlign = 'center'
270
+ ctx.fillStyle = '#474747'
271
+ ctx.globalAlpha = 1
272
+ ctx.font = '30px "Poppins-Bold"'
273
+ ctx.fillText(textXPEdited, 730, 180)
274
+
275
+ const attachment = new Discord.MessageAttachment(
276
+ canvas.toBuffer(),
277
+ AttachmentName
278
+ )
279
+
280
+ return attachment
281
+ } catch (err) {
282
+ console.log(`[XP] Error Occured. | rankCard | Error: ${err.stack}`)
283
+ }
284
+ }
285
+ }
286
+
287
+ module.exports = rank