Skip to content

Commit f813e3d

Browse files
committed
feat(0.0.5): added new data
1 parent 5a9b4a8 commit f813e3d

File tree

6 files changed

+89
-30
lines changed

6 files changed

+89
-30
lines changed

api/index.ts

Lines changed: 41 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import express from 'express';
22
import cors from 'cors';
33
import mysql from 'mysql2';
4-
import ejs from 'ejs';
54
import path from 'path';
65

76
const app = express();
@@ -102,6 +101,9 @@ async function ensureGuildTableExists(guild, callback) {
102101
user_pfp TINYTEXT,
103102
user_name TINYTEXT,
104103
user_nickname TINYTEXT,
104+
user_level INT DEFAULT 0,
105+
user_xp_needed_next_level INT,
106+
user_progress_next_level DECIMAL(6, 2),
105107
PRIMARY KEY (user_id)
106108
)
107109
`;
@@ -166,23 +168,45 @@ app.post('/post/:guild/:user/:auth', (req, res) => {
166168
return res.status(500).json({ message: 'Internal server error' });
167169
}
168170

169-
const insertOrUpdateQuery = `
170-
INSERT INTO \`${guild}\` (user_id, xp, user_pfp, user_name, user_nickname)
171-
VALUES (?, ?, ?, ?, ?)
172-
ON DUPLICATE KEY UPDATE
173-
xp = xp + VALUES(xp),
174-
user_pfp = VALUES(user_pfp),
175-
user_name = VALUES(user_name),
176-
user_nickname = VALUES(user_nickname)
177-
`;
178-
pool.query(insertOrUpdateQuery, [user, xpValue, pfp, name, nickname], (err, results) => {
171+
const getXpQuery = `SELECT xp FROM \`${guild}\` WHERE user_id = ?`;
172+
173+
pool.query(getXpQuery, [user], (err, results) => {
179174
if (err) {
180-
console.error('Error updating XP:', err);
181-
res.status(500).json({ message: 'Internal server error' });
182-
}
183-
else {
184-
res.status(200).json(results);
175+
console.error('Error fetching XP:', err);
176+
return res.status(500).json({ message: 'Internal server error' });
185177
}
178+
179+
const currentXp = results.length ? results[0].xp : 0;
180+
const newXp = currentXp + xpValue;
181+
182+
const currentLevel = Math.floor(Math.sqrt(newXp / 100));
183+
const nextLevel = currentLevel + 1;
184+
const nextLevelXp = Math.pow(nextLevel, 2) * 100;
185+
const xpNeededForNextLevel = nextLevelXp - newXp;
186+
const currentLevelXp = Math.pow(currentLevel, 2) * 100;
187+
const progressToNextLevel = ((newXp - currentLevelXp) / (nextLevelXp - currentLevelXp)) * 100;
188+
189+
const updateQuery = `
190+
INSERT INTO \`${guild}\` (user_id, xp, user_pfp, user_name, user_nickname, user_level, user_xp_needed_next_level, user_progress_next_level)
191+
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
192+
ON DUPLICATE KEY UPDATE
193+
xp = VALUES(xp),
194+
user_pfp = VALUES(user_pfp),
195+
user_name = VALUES(user_name),
196+
user_nickname = VALUES(user_nickname),
197+
user_level = VALUES(user_level),
198+
user_xp_needed_next_level = VALUES(user_xp_needed_next_level),
199+
user_progress_next_level = VALUES(user_progress_next_level)
200+
`;
201+
202+
pool.query(updateQuery, [user, newXp, pfp, name, nickname, currentLevel, xpNeededForNextLevel, progressToNextLevel.toFixed(2)], (err, results) => {
203+
if (err) {
204+
console.error('Error updating XP:', err);
205+
return res.status(500).json({ message: 'Internal server error' });
206+
} else {
207+
res.status(200).json(results);
208+
}
209+
});
186210
});
187211
});
188212
});
@@ -276,7 +300,7 @@ app.get('/leaderboard/:guild', async (req, res) => {
276300
return res.status(404).json({ message: 'No guild was found with this ID' });
277301
}
278302
const data = await response.json();
279-
res.render('leaderboard', { guild: data.guild, leaderboard: data.leaderboard});
303+
res.render('leaderboard', { guild: data.guild, leaderboard: data.leaderboard });
280304
});
281305

282306
app.listen(PORT, () => {

api/public/styles.css

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,4 +84,5 @@ body {
8484

8585
.userXP {
8686
margin: 0;
87+
font-size: large;
8788
}

api/views/leaderboard.ejs

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
<meta name="viewport" content="width=device-width, initial-scale=1.0">
77
<title>Leaderboard for <%= guild.guild_name %>
88
</title>
9+
<meta name="description" content="Leaderboard for <%= guild.guild_name %>">
910
<link rel="stylesheet" href="/styles.css">
1011
</head>
1112

@@ -20,16 +21,22 @@
2021
</div>
2122
</div>
2223
<div class="leaderboard">
23-
<% leaderboard.forEach((user, index) => { %>
24+
<% leaderboard.forEach((user, index)=> { %>
2425
<div class="user">
25-
<p class="userPosition">#<%= index + 1 %></p>
26-
<img class="userImage" src="<%= user.user_pfp %>" alt="User Image">
26+
<h1 class="userPosition">#<%= index + 1 %>
27+
</h1>
28+
<img class="userImage" src="<%= user.user_pfp %>" alt="User image for <%= user.user_name %>">
2729
<div class="userInfo">
28-
<h2 class="userName"><%= user.user_nickname %> (@<%= user.user_name %>)</h2>
29-
<p class="userXP">XP: <%= user.xp %></p>
30+
<h2 class="userName">
31+
<%= user.user_nickname %> (@<%= user.user_name %>)
32+
</h2>
33+
<p class="userXP">XP: <%= user.xp %>
34+
</p>
35+
<p class="userXP">Level <%= user.user_level %> | <%= user.xp %>/<%= user.xp + user.user_xp_needed_next_level %> points to next level (<%= user.user_progress_next_level %>%)
36+
</p>
3037
</div>
3138
</div>
32-
<% }) %>
39+
<% }) %>
3340
</div>
3441
</main>
3542
</body>

bot/commands.ts

Lines changed: 31 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -133,11 +133,38 @@ const commands: Record<string, Command> = {
133133
const guild = interaction.guild?.id
134134
const user = interaction.user.id
135135
const xp = await makeGETRequest(guild as string, user)
136+
const progress = xp.user_progress_next_level;
137+
const progressBar = createProgressBar(progress);
138+
136139
await interaction.reply({
137140
embeds: [
138-
quickEmbed({color: 'Blurple', title: 'XP', description: `<@${user}> you have ${xp.xp} XP! (Level ${convertToLevels(xp.xp)})`}, interaction)
139-
]
140-
})
141+
quickEmbed(
142+
{
143+
color: 'Blurple',
144+
title: 'XP',
145+
description: `<@${user}> you have ${xp.xp} XP! (Level ${convertToLevels(xp.xp)})`,
146+
},
147+
interaction
148+
).addFields([
149+
{
150+
name: 'Progress To Next Level',
151+
value: `${progressBar} ${progress}%`,
152+
inline: true,
153+
},
154+
{
155+
name: 'XP Required',
156+
value: `${xp.user_xp_needed_next_level} XP`,
157+
inline: true,
158+
},
159+
]),
160+
],
161+
});
162+
163+
function createProgressBar(progress: number): string {
164+
const filled = Math.floor(progress / 10);
165+
const empty = 10 - filled;
166+
return '▰'.repeat(filled) + '▱'.repeat(empty);
167+
}
141168
}
142169
}
143170
},
@@ -169,7 +196,7 @@ const commands: Record<string, Command> = {
169196
}, interaction);
170197

171198
// Add a field for each user with a mention
172-
leaderboard.forEach((entry: { user_id: any; xp: any; }, index: number) => {
199+
leaderboard.leaderboard.forEach((entry: { user_id: any; xp: any; }, index: number) => {
173200
leaderboardEmbed.addFields([
174201
{
175202
name: `${index + 1}.`,

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "xpbot",
33
"type": "module",
4-
"version": "0.0.4",
4+
"version": "0.0.5",
55
"scripts": {
66
"api": "bun --watch api/index.ts",
77
"bot": "bun --watch bot/index.ts"

0 commit comments

Comments
 (0)