import DiscordOauth2 from 'discord-oauth2'; import {User} from "../models/User"; import {redisClient} from "../app"; const oauth = new DiscordOauth2(); /** * Retrieves an access & refresh token from the discord api * @param code The authorization code from the callback */ export const createTokenByCode = (code: string) => oauth.tokenRequest({ grantType: "authorization_code", scope: "identify guilds", clientId: process.env.DC_CLIENT, clientSecret: process.env.DC_SECRET, redirectUri: process.env.DC_REDIRECT_URI, code }); /** * Generate a new access token from the refresh token * @param refreshToken The token to refresh the access token */ export const generateToken = (refreshToken: string) => oauth.tokenRequest({ grantType: "refresh_token", scope: "identify guilds", clientId: process.env.DC_CLIENT, clientSecret: process.env.DC_SECRET, redirectUri: process.env.DC_REDIRECT_URI, refreshToken }); /** * Updates a user's access token if it is expired * @param refreshDate The date of when to renew the provided access token * @param refreshToken The token to refresh the access token * @param accessToken The token to access the discord api */ export const updateToken = async (refreshDate: Date, refreshToken: string, accessToken: string) => { let token = accessToken; if (refreshDate.valueOf() < Date.now()) { const newToken = await generateToken(refreshToken); token = newToken.access_token; User.update({ accessToken: token, refreshDate: new Date(Date.now() + newToken.expires_in), refreshToken: newToken.refresh_token }, {where: {refreshToken: refreshToken}}); } return token; } /** * Gets the guilds from the access token. * This function also automatically renews the access token if it expires * @param refreshDate The date of when to renew the provided access token * @param refreshToken The token to refresh the access token * @param accessToken The token to access the discord api */ export const getGuilds = async (refreshDate: Date, refreshToken: string, accessToken: string) => { const cacheResults = await redisClient.get(`guilds:${accessToken}`); if (cacheResults) { return JSON.parse(cacheResults) as DiscordOauth2.PartialGuild[]; } else { const guilds = await oauth.getUserGuilds(await updateToken(refreshDate, refreshToken, accessToken)); await redisClient.setEx(`guilds:${accessToken}`, 60 * 60 * 24, JSON.stringify(guilds)); return guilds; } } /** * Checks if the user is the owner of the guild or has the manage server permission * @param refreshDate The date of when to renew the provided access token * @param refreshToken The token to refresh the access token * @param accessToken The token to access the discord api * @param guildId The id of the guild */ export const canEditGuild = async (refreshDate: Date, refreshToken: string, accessToken: string, guildId: string) => { const guilds = await getGuilds(refreshDate, refreshToken, accessToken); return guilds.some(guild => guild.id === guildId && (guild.owner || (guild.permissions && (guild.permissions & 0x8)))); } /** * Gets user information from the discord api * @param token The access token of the user */ export const getUser = (token: string) => oauth.getUser(token);