1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192 |
- /* eslint-disable camelcase */
- import * as querystring from "querystring";
- import { Option, tryDo, isHttpError } from "@shared/common/async_utils";
- import got, { HTTPError } from "got";
- import { logger } from "./logging";
- const DISCORD_API = "https://discord.com/api";
- export interface AccessTokenResponse {
- access_token: string;
- token_type: string;
- expires_in: number;
- refresh_token: string;
- scope: string;
- }
- type GrantType = "authorization_code";
- type TokenType = "code" | "token";
- export interface AccessTokenRequest {
- client_id: string;
- client_secret: string;
- grant_type: GrantType;
- code: string;
- scope: string;
- redirect_uri: string;
- }
- export type AuthorizeRequest = {
- client_id: string,
- redirect_url: string,
- response_type: TokenType,
- scope: string,
- }
- export interface DiscordUser {
- id: string;
- username: string;
- discriminator: string;
- avatar?: string;
- bot?: boolean;
- mfa_enabled?: boolean;
- locale?: string;
- verified?: boolean;
- email?: string;
- flags?: number;
- premium_type?: number;
- }
- export class DiscordAPI {
- static getAuthUrl(opts: AuthorizeRequest): string {
- return `${DISCORD_API}/oauth2/authorize?${querystring.stringify(opts)}`;
- }
- static async getToken(opts: AccessTokenRequest):
- Promise<Option<AccessTokenResponse, { error: string }>> {
- const result = await tryDo(got<AccessTokenResponse>("oauth2/token", {
- responseType: "json",
- method: "post",
- form: opts,
- prefixUrl: DISCORD_API,
- }));
- if (!result.ok) {
- if (isHttpError<HTTPError>(result.error)) {
- logger.warn("WEB: Failed to authenticate a user: %s", result.error);
- return { error: "Couldn't authenticate a user (the session might be old). Please try logging in again.", ok: false };
- }
- logger.error("WEB: failed to fetch access token: %s", result.error);
- return { error: "Unexpected error", ok: false };
- }
- return { ok: true, ...result.result.body };
- }
- static async getCurrentUser(token: string): Promise<Option<DiscordUser, {error: string}>> {
- const result = await tryDo(got<DiscordUser>("users/@me", {
- responseType: "json",
- headers: {
- Authorization: `Bearer ${token}`,
- },
- prefixUrl: DISCORD_API,
- }));
- if (!result.ok) {
- if (isHttpError<HTTPError>(result.error)) {
- return { error: `Failed to check used ID. Error: ${result.error.message}`, ok: false };
- }
- return { error: "Unexpected error", ok: false };
- }
- return { ok: true, ...result.result.body };
- }
- }
|