@sapphire/plugin-api
Version:
Plugin for @sapphire/framework to expose a REST API
120 lines (118 loc) • 4.03 kB
JavaScript
import { __name, __publicField, __privateAdd, __privateSet, __privateGet } from '../../../chunk-S573YWRP.mjs';
import { isThenable } from '@sapphire/utilities';
import { randomBytes, createCipheriv, createDecipheriv } from 'crypto';
import { OAuth2Scopes, RouteBases, Routes } from 'discord.js';
import { fetch } from 'undici';
var _secret;
var _Auth = class _Auth {
constructor(options) {
/**
* The client's application id, this can be retrieved in Discord Developer Portal at https://discord.com/developers/applications.
* @since 1.0.0
*/
__publicField(this, "id");
/**
* The name for the cookie, this will be used to identify a Secure HttpOnly cookie.
* @since 1.0.0
*/
__publicField(this, "cookie");
/**
* The scopes defined at https://discord.com/developers/docs/topics/oauth2#shared-resources-oauth2-scopes.
* @since 1.0.0
*/
__publicField(this, "scopes");
/**
* The redirect uri.
* @since 1.0.0
*/
__publicField(this, "redirect");
/**
* The transformers used for {@link Auth.fetchData}.
* @since 1.4.0
*/
__publicField(this, "transformers");
__publicField(this, "domainOverwrite", null);
__privateAdd(this, _secret);
this.id = options.id;
this.cookie = options.cookie ?? "SAPPHIRE_AUTH";
this.scopes = options.scopes ?? [OAuth2Scopes.Identify];
this.redirect = options.redirect;
__privateSet(this, _secret, options.secret);
this.transformers = options.transformers ?? [];
this.domainOverwrite = options.domainOverwrite ?? null;
}
/**
* The client secret, this can be retrieved in Discord Developer Portal at https://discord.com/developers/applications.
* @since 1.0.0
*/
get secret() {
return __privateGet(this, _secret);
}
/**
* Encrypts an object with aes-256-cbc to use as a token.
* @since 1.0.0
* @param data An object to encrypt
*/
encrypt(data) {
const iv = randomBytes(16);
const cipher = createCipheriv("aes-256-cbc", __privateGet(this, _secret), iv);
return `${cipher.update(JSON.stringify(data), "utf8", "base64") + cipher.final("base64")}.${iv.toString("base64")}`;
}
/**
* Decrypts an object with aes-256-cbc to use as a token.
* @since 1.0.0
* @param token An data to decrypt
*/
decrypt(token) {
const [data, iv] = token.split(".");
const decipher = createDecipheriv("aes-256-cbc", __privateGet(this, _secret), Buffer.from(iv, "base64"));
try {
const parsed = JSON.parse(decipher.update(data, "base64", "utf8") + decipher.final("utf8"));
return parsed.expires >= Date.now() ? parsed : null;
} catch {
return null;
}
}
/**
* Retrieves the data for a specific user.
* @since 1.4.0
* @param token The access token from the user.
*/
async fetchData(token) {
const [user, guilds, connections] = await Promise.all([
this.fetchInformation(OAuth2Scopes.Identify, token, `${RouteBases.api}${Routes.user()}`),
this.fetchInformation(OAuth2Scopes.Guilds, token, `${RouteBases.api}${Routes.userGuilds()}`),
this.fetchInformation(
OAuth2Scopes.Connections,
token,
`${RouteBases.api}${Routes.userConnections()}`
)
]);
let data = { user, guilds, connections };
for (const transformer of this.transformers) {
const result = transformer(data);
if (isThenable(result)) data = await result;
else data = result;
}
return data;
}
async fetchInformation(scope, token, url) {
if (!this.scopes.includes(scope)) return void 0;
const result = await fetch(url, {
headers: {
authorization: `Bearer ${token}`
}
});
return result.ok ? await result.json() : null;
}
static create(options) {
if (!options?.secret || !options.id) return null;
return new _Auth(options);
}
};
_secret = new WeakMap();
__name(_Auth, "Auth");
var Auth = _Auth;
export { Auth };
//# sourceMappingURL=Auth.mjs.map
//# sourceMappingURL=Auth.mjs.map