feat: implement discord role syncing

This commit is contained in:
mrjvs
2026-08-09 19:30:25 +02:00
parent 735a723328
commit 87d2b6357b
5 changed files with 54 additions and 3 deletions

View File

@@ -1,3 +1,5 @@
import { removeDiscordMemberSupporterRole, removeDiscordMemberTesterRole } from "~~/server/utils/discord";
export default defineEventHandler(async (event): Promise<void> => {
const auth = enforceLoggedIn(event);
const discord = useDiscord(event);
@@ -7,9 +9,26 @@ export default defineEventHandler(async (event): Promise<void> => {
})
const grpc = useApiGrpcWithToken(event, auth.token);
const oldUserData = await grpc.getUserData({});
const oldDiscordId = oldUserData.connections?.discord?.id;
await grpc.setDiscordConnectionData({
id: '',
});
// TODO set roles based on stripe info
const priceId = oldUserData.connections?.stripe?.priceId;
const stripe = useStripe(event);
if (stripe) {
if (priceId && oldDiscordId) {
const price = await stripe.prices.retrieve(priceId);
const product = await stripe.products.retrieve(price.product as string);
const discordRoleId = product.metadata.discord_role_id;
if (discordRoleId) {
await removeDiscordMemberSupporterRole(discord, oldDiscordId, discordRoleId);
}
if (product.metadata.beta === 'true') {
await removeDiscordMemberTesterRole(discord, oldDiscordId);
}
}
}
});

View File

@@ -17,6 +17,8 @@ export default defineEventHandler(async (event) => {
pid: userData.pid,
username: userData.username,
token: token,
accessLevel: userData.accessLevel,
email: userData.emailAddress,
})
} catch (err) {
console.error('Failed to request user data: ', err);

View File

@@ -1,3 +1,5 @@
import { assignDiscordMemberSupporterRole, assignDiscordMemberTesterRole } from "~~/server/utils/discord";
type DiscordTokenResponse = {
"access_token": string,
"token_type": string,
@@ -15,6 +17,10 @@ type DiscordUserResponse = {
// Discord oauth callback
export default defineEventHandler(async (event) => {
const discord = useDiscord(event);
if (!discord) {
return sendRedirect(event, '/');
}
const discordFetch = $fetch.create({
baseURL: discord.baseUrl,
});
@@ -42,12 +48,29 @@ export default defineEventHandler(async (event) => {
return sendRedirect(event, '/'); // No identify scope
}
const discordId = authInfo.user.id;
const grpc = useApiGrpcWithToken(event, accessTokenCookie ?? '');
await grpc.setDiscordConnectionData({
id: authInfo.user.id
id: discordId
});
// TODO set roles based on stripe info
const userData = await grpc.getUserData({});
const priceId = userData.connections?.stripe?.priceId;
const stripe = useStripe(event);
if (stripe && priceId) {
if (priceId) {
const price = await stripe.prices.retrieve(priceId);
const product = await stripe.products.retrieve(price.product as string);
const discordRoleId = product.metadata.discord_role_id;
if (discordRoleId) {
await assignDiscordMemberSupporterRole(discord, discordId, discordRoleId);
}
if (product.metadata.beta === 'true') {
await assignDiscordMemberTesterRole(discord, discordId);
}
}
}
return sendRedirect(event, '/account');
});

View File

@@ -4,6 +4,8 @@ export type AuthContext = {
pid: number;
username: string;
token: string;
email: string;
accessLevel: number;
};
export function setAuthContext(event: H3Event, context: AuthContext | null): void {

View File

@@ -64,3 +64,8 @@ export const ForgotPasswordSchema = z.object({
emailOrPassword: z.string(),
});
export type ApiAuthForgotPasswordRequest = z.infer<typeof ForgotPasswordSchema>;
export const CheckoutSchema = z.object({
priceId: z.string(),
});
export type ApiAccountCheckoutRequest = z.infer<typeof CheckoutSchema>;