feat: add badges

This commit is contained in:
2026-02-04 17:59:26 -08:00
parent e20be5f4e8
commit 054a55ff9c
17 changed files with 451 additions and 4 deletions
+1 -1
View File
@@ -65,7 +65,7 @@ const authPlugin: FastifyPluginAsync = async (app) => {
// Register Discord OAuth2
app.register(fastifyOauth2, {
name: "oauth2Discord",
scope: ["identify", "email"],
scope: ["identify", "email", "guilds", "guilds.members.read"],
credentials: {
client: {
id: process.env.DISCORD_CLIENT_ID || "",
+49 -1
View File
@@ -28,8 +28,56 @@ const authRoutes: FastifyPluginAsync = async (app) => {
const userData = await discordResponse.json();
// Check if user is in our Discord server and has special roles
let inDiscord = false;
let isVip = false;
let isMod = false;
let isStaff = false;
const guildId = process.env.DISCORD_GUILD_ID;
const sponsorRoleId = process.env.SPONSOR_ROLE_ID;
const modRoleId = process.env.MOD_ROLE_ID;
const staffRoleId = process.env.STAFF_ROLE_ID;
if (guildId) {
const guildsResponse = await fetch("https://discord.com/api/users/@me/guilds", {
headers: {
Authorization: `Bearer ${tokenResult.token.access_token}`,
},
});
if (guildsResponse.ok) {
const guilds = await guildsResponse.json() as Array<{ id: string }>;
inDiscord = guilds.some(guild => guild.id === guildId);
}
// If user is in Discord, check for special roles
if (inDiscord) {
const memberResponse = await fetch(
`https://discord.com/api/users/@me/guilds/${guildId}/member`,
{
headers: {
Authorization: `Bearer ${tokenResult.token.access_token}`,
},
}
);
if (memberResponse.ok) {
const memberData = await memberResponse.json() as { roles: string[] };
if (sponsorRoleId) {
isVip = memberData.roles.includes(sponsorRoleId);
}
if (modRoleId) {
isMod = memberData.roles.includes(modRoleId);
}
if (staffRoleId) {
isStaff = memberData.roles.includes(staffRoleId);
}
}
}
}
// Create or update user in database
const user = await authService.createOrUpdateUserFromDiscord(userData);
const user = await authService.createOrUpdateUserFromDiscord(userData, inDiscord, isVip, isMod, isStaff);
// Generate JWT
const jwt = await authService.generateToken(user);
+17 -1
View File
@@ -50,13 +50,17 @@ export class AuthService {
avatarUrl: dbUser.avatar || undefined,
isAdmin: dbUser.isAdmin,
isBanned: dbUser.isBanned,
inDiscord: dbUser.inDiscord,
isVip: dbUser.isVip,
isMod: dbUser.isMod,
isStaff: dbUser.isStaff,
};
}
/**
* Create or update user from Discord OAuth data.
*/
async createOrUpdateUserFromDiscord(discordData: DiscordUser): Promise<User> {
async createOrUpdateUserFromDiscord(discordData: DiscordUser, inDiscord: boolean, isVip: boolean, isMod: boolean, isStaff: boolean): Promise<User> {
const avatarUrl = discordData.avatar
? `https://cdn.discordapp.com/avatars/${discordData.id}/${discordData.avatar}.png`
: undefined;
@@ -72,11 +76,19 @@ export class AuthService {
email: discordData.email,
avatar: avatarUrl,
isAdmin: discordData.id === process.env.ADMIN_DISCORD_ID,
inDiscord,
isVip,
isMod,
isStaff,
},
update: {
username: discordData.username,
email: discordData.email,
avatar: avatarUrl,
inDiscord,
isVip,
isMod,
isStaff,
},
});
@@ -88,6 +100,10 @@ export class AuthService {
avatarUrl: dbUser.avatar || undefined,
isAdmin: dbUser.isAdmin,
isBanned: dbUser.isBanned,
inDiscord: dbUser.inDiscord,
isVip: dbUser.isVip,
isMod: dbUser.isMod,
isStaff: dbUser.isStaff,
};
}
}
+4
View File
@@ -60,6 +60,10 @@ export class CommentService {
id: comment.user.id,
username: comment.user.username,
avatar: comment.user.avatar || undefined,
inDiscord: comment.user.inDiscord,
isVip: comment.user.isVip,
isMod: comment.user.isMod,
isStaff: comment.user.isStaff,
},
gameId: comment.gameId || undefined,
bookId: comment.bookId || undefined,
+16
View File
@@ -23,6 +23,10 @@ export class UserService {
avatarUrl: user.avatar || undefined,
isAdmin: user.isAdmin,
isBanned: user.isBanned,
inDiscord: user.inDiscord,
isVip: user.isVip,
isMod: user.isMod,
isStaff: user.isStaff,
}));
}
@@ -43,6 +47,10 @@ export class UserService {
avatarUrl: user.avatar || undefined,
isAdmin: user.isAdmin,
isBanned: user.isBanned,
inDiscord: user.inDiscord,
isVip: user.isVip,
isMod: user.isMod,
isStaff: user.isStaff,
};
}
@@ -60,6 +68,10 @@ export class UserService {
avatarUrl: user.avatar || undefined,
isAdmin: user.isAdmin,
isBanned: user.isBanned,
inDiscord: user.inDiscord,
isVip: user.isVip,
isMod: user.isMod,
isStaff: user.isStaff,
};
}
@@ -77,6 +89,10 @@ export class UserService {
avatarUrl: user.avatar || undefined,
isAdmin: user.isAdmin,
isBanned: user.isBanned,
inDiscord: user.inDiscord,
isVip: user.isVip,
isMod: user.isMod,
isStaff: user.isStaff,
};
}