124 lines
4.4 KiB
TypeScript
124 lines
4.4 KiB
TypeScript
import axios from 'axios';
|
|
import { prisma } from "~/db.server";
|
|
import { createUserSession } from '~/session.server';
|
|
|
|
export interface DiscordUser {
|
|
id: string;
|
|
username: string;
|
|
discriminator: string;
|
|
avatar: string;
|
|
bot?: boolean;
|
|
system?: boolean;
|
|
mfa_enabled?: boolean;
|
|
}
|
|
|
|
export interface AccessTokenResponse {
|
|
access_token: string;
|
|
expires: number;
|
|
refresh_token: string;
|
|
}
|
|
|
|
export function getAccessToken(code: string): Promise<AccessTokenResponse> {
|
|
return new Promise(
|
|
(resolve, reject) => {
|
|
const body = new FormData();
|
|
body.append("grant_type", "authorization_code");
|
|
body.append("code", code);
|
|
body.append("redirect_url", process.env.DISCORD_REDIRECT_URI || "");
|
|
|
|
axios.post("https://discord.com/api/oauth2/token", body)
|
|
.then((res) => {
|
|
const { access_token, refresh_token, expires_in } = res.data;
|
|
|
|
resolve({
|
|
access_token,
|
|
refresh_token,
|
|
expires: Date.now() + expires_in * 1000
|
|
});
|
|
})
|
|
.catch(reject);
|
|
}
|
|
)
|
|
}
|
|
|
|
export async function authorize(access_code: string): Promise<AccessTokenResponse | undefined> {
|
|
return new Promise(
|
|
(resolve, reject) => {
|
|
const formData = new FormData();
|
|
|
|
formData.append("client_id", process.env.DISCORD_CLIENT_ID || "");
|
|
formData.append("client_secret", process.env.DISCORD_CLIENT_SECRET || "");
|
|
formData.append("grant_type", "authorization_code");
|
|
formData.append("redirect_uri", process.env.DISCORD_REDIRECT_URI || "");
|
|
formData.append("scope", "identify");
|
|
formData.append("code", access_code);
|
|
|
|
axios.post("https://discord.com/api/oauth2/token", formData)
|
|
.then((res) => {
|
|
const { access_token, refresh_token, expires_in } = res.data;
|
|
|
|
resolve({
|
|
access_token,
|
|
refresh_token,
|
|
expires: Date.now() + expires_in * 1000
|
|
});
|
|
})
|
|
.catch(reject);
|
|
}
|
|
)
|
|
}
|
|
|
|
export function getDiscordUser(token: string): Promise<DiscordUser> {
|
|
return new Promise(
|
|
(resolve, reject) => {
|
|
axios.get("https://discord.com/api/users/@me", {
|
|
headers: {
|
|
Authorization: `Bearer ${token}`
|
|
}
|
|
})
|
|
.then(
|
|
(res) => {
|
|
resolve(res.data);
|
|
}
|
|
)
|
|
.catch(reject);
|
|
}
|
|
)
|
|
}
|
|
|
|
export async function discordLogin(request: Request, code: string): Promise<Response> {
|
|
return new Promise(
|
|
(resolve, reject) => {
|
|
getAccessToken(code)
|
|
.then((token) => {
|
|
getDiscordUser(token.access_token)
|
|
.then(async (user) => {
|
|
prisma.discordUser.upsert({
|
|
create: {
|
|
discord_id: user.id,
|
|
access_token: token.access_token,
|
|
refresh_token: token.refresh_token,
|
|
expires: new Date(token.expires),
|
|
username: user.username,
|
|
discriminator: user.discriminator,
|
|
},
|
|
update: {
|
|
discord_id: user.id,
|
|
access_token: token.access_token,
|
|
refresh_token: token.refresh_token,
|
|
expires: new Date(token.expires),
|
|
username: user.username,
|
|
discriminator: user.discriminator,
|
|
},
|
|
where: {
|
|
discord_id: user.id
|
|
}
|
|
})
|
|
.then(async () => {
|
|
resolve(await createUserSession({request, discord_id: user.id, redirectTo: '/'}));
|
|
})
|
|
})
|
|
})
|
|
}
|
|
)
|
|
} |