{"size": 2836, "ext": "js", "max_stars_repo_path": "src/methods/api/_callbacks/discord.js", "max_stars_repo_name": "Testausserveri/testausserveri-id", "max_stars_repo_stars_event_min_datetime": null, "max_stars_repo_stars_event_max_datetime": null, "max_issues_repo_path": "src/methods/api/_callbacks/discord.js", "max_issues_repo_name": "Testausserveri/testausserveri-id", "max_issues_repo_issues_event_min_datetime": null, "max_issues_repo_issues_event_max_datetime": null, "max_forks_repo_path": "src/methods/api/_callbacks/discord.js", "max_forks_repo_name": "Testausserveri/testausserveri-id", "max_forks_repo_forks_event_min_datetime": null, "max_forks_repo_forks_event_max_datetime": null}
{"max_stars_count": null, "max_issues_count": null, "max_forks_count": null, "avg_line_length": 44.3125, "max_line_length": 134, "alphanum_fraction": 0.6604372355}
const { updateAuthenticationSession } = require("../../../database/client")
const getCredentials = require("../../../util/getCredentials")
const redirectWithCode = require("../../../util/redirectWithCode")
const request = require("../../../util/request")

/**
 * Discord OAuth 2.0 callback
 * @param {import("http").IncomingMessage} req
 * @param {import("http").ServerResponse} res
 * @param {import("../../../typings/schemas").authenticationSession} session
 * @param {string} redirectURL
 */
module.exports = async (
    req, res, session, redirectURL
) => {
    // Get request params
    const url = new URL(req.url, `http://${req.headers.host ?? "local"}`)
    const code = url.searchParams.get("code")
    if (!code) throw new Error("safe: Missing code from query. The user might have rejected the login request.")

    // Construct access token request params
    const tokenExchangeParams = new URLSearchParams()
    tokenExchangeParams.append("client_id", getCredentials("Discord", "clientId"))
    tokenExchangeParams.append("client_secret", getCredentials("Discord", "secret"))
    tokenExchangeParams.append("grant_type", "authorization_code")
    tokenExchangeParams.append("code", code)
    tokenExchangeParams.append("redirect_uri", redirectURL)

    // Make the request for the access token
    const tokenExchange = await request(
        "POST", "https://discord.com/api/v9/oauth2/token", {
            "Content-Type": "application/x-www-form-urlencoded"
        }, tokenExchangeParams.toString()
    )
    if (tokenExchange.status !== 200) throw new Error("safe: Unable to request account access token. This is likely a Discord issue.")
    const token = JSON.parse(tokenExchange.data).access_token

    // Fetch data based on request scopes
    const info = await request("GET", "https://discord.com/api/v9/oauth2/@me", {
        Authorization: `Bearer ${token}`
    })
    if (info.status !== 200) throw new Error("safe: Unable to access account information. This is likely a Discord issue.")
    const userData = JSON.parse(info.data)

    // Update authentication session information based on scopes
    await updateAuthenticationSession({ internalState: session.internalState }, {
        user: {
            name: `${userData.user.username}#${userData.user.discriminator}`,
            id: userData.user.id,
            token: session.scopes.includes("token") ? token : null,
            contact: session.scopes.includes("contact") ? ({
                email: userData.user.email,
                phone: null
            }) : null,
            account: session.scopes.includes("account") ? ({
                avatar: `https://cdn.discordapp.com/avatars/${userData.user.id}/${userData.user.avatar}.webp`
            }) : null
        }
    })

    // Redirect to application
    redirectWithCode(session, res)
}
