import { NextApiRequest } from 'next' import fetch from 'node-fetch' import { serialize } from 'cookie' import { DiscordEnpoints } from '@utils/Constants' import { formData } from '@utils/Tools' import { OauthCallbackSchema } from '@utils/Yup' import ResponseWrapper from '@utils/ResponseWrapper' import { DiscordTokenInfo, DiscordUserInfo } from '@types' import { update } from '@utils/Query' import { verify } from '@utils/Jwt' import RequestHandler from '@utils/RequestHandler' const Callback = RequestHandler().get(async (req: ApiRequest, res) => { const validate = await OauthCallbackSchema.validate(req.query) .then((r) => r) .catch((e) => { ResponseWrapper(res, { code: 400, errors: e.errors }) return null }) if (!validate) return res.statusCode = 200 const token: DiscordTokenInfo = await fetch(DiscordEnpoints.Token, { method: 'POST', body: formData({ client_id: process.env.DISCORD_CLIENT_ID, redirect_uri: process.env.KOREANBOTS_URL + '/api/auth/discord/callback', client_secret: process.env.DISCORD_CLIENT_SECRET, scope: process.env.DISCORD_SCOPE, grant_type: 'authorization_code', code: req.query.code, }), headers: { 'Content-Type': 'application/x-www-form-urlencoded', }, }).then((r) => r.json()) if (token.error) return ResponseWrapper(res, { code: 400, errors: ['올바르지 않은 코드입니다.'] }) const user: DiscordUserInfo = await fetch(DiscordEnpoints.Me, { method: 'GET', headers: { Authorization: `${token.token_type} ${token.access_token}`, }, }).then((r) => r.json()) const userToken = await update.assignToken({ id: user.id, access_token: token.access_token, expires_in: token.expires_in, refresh_token: token.refresh_token, email: user.email, username: user.username, discriminator: user.discriminator, verified: user.verified, }) if (userToken === 1) return res.redirect(301, 'https://docs.koreanbots.dev/bots/account/unverified') else if (userToken === 2) return res.redirect(301, 'https://docs.koreanbots.dev/bots/account/blocked') const info = verify(userToken) res.setHeader( 'set-cookie', serialize('token', userToken, { expires: new Date(info.exp * 1000), secure: process.env.NODE_ENV === 'production', httpOnly: true, sameSite: 'lax', path: '/', }) ) res.redirect(301, '/callback/discord') }) interface ApiRequest extends NextApiRequest { query: { code: string } } export default Callback