diff --git a/src/client/Client.js b/src/client/Client.js index 92fc35c..4056a61 100644 --- a/src/client/Client.js +++ b/src/client/Client.js @@ -446,19 +446,12 @@ class Client extends BaseClient { return QR.connect(this); } - /** - * @typedef {Object} remoteAuthConfrim - * @property {function} yes Yes - * @property {function} no No - */ - /** * Implement `remoteAuth`, like using your phone to scan a QR code * @param {string} url URL from QR code - * @param {boolean} forceAccept Whether to force confirm `yes` - * @returns {Promise} + * @returns {Promise} */ - async remoteAuth(url, forceAccept = false) { + async remoteAuth(url) { if (!this.isReady()) throw new Error('CLIENT_NOT_READY', 'Remote Auth'); // Step 1: Parse URL url = new URL(url); @@ -478,17 +471,9 @@ class Client extends BaseClient { }); const handshake_token = res.handshake_token; // Step 3: Post - const yes = () => - this.api.users['@me']['remote-auth'].finish.post({ data: { handshake_token, temporary_token: false } }); - const no = () => this.api.users['@me']['remote-auth'].cancel.post({ data: { handshake_token } }); - if (forceAccept) { - return yes(); - } else { - return { - yes, - no, - }; - } + return this.api.users['@me']['remote-auth'].finish.post({ data: { handshake_token, temporary_token: false } }); + // Cancel + // this.api.users['@me']['remote-auth'].cancel.post({ data: { handshake_token } }); } /** @@ -947,10 +932,19 @@ class Client extends BaseClient { } /** - * Authorize an URL. + * @typedef {Object} OAuth2AuthorizeOptions + * @property {string} [guild_id] Guild ID + * @property {PermissionResolvable} [permissions] Permissions + * @property {boolean} [authorize] Whether to authorize or not + * @property {string} [code] 2FA Code + * @property {string} [webhook_channel_id] Webhook Channel ID + */ + + /** + * Authorize an application. * @param {string} url Discord Auth URL - * @param {Object} options Oauth2 options - * @returns {Promise} + * @param {OAuth2AuthorizeOptions} options Oauth2 options + * @returns {Promise} * @example * client.authorizeURL(`https://discord.com/api/oauth2/authorize?client_id=botID&permissions=8&scope=applications.commands%20bot`, { guild_id: "guildID", @@ -958,38 +952,23 @@ class Client extends BaseClient { authorize: true }) */ - async authorizeURL(url, options = {}) { - const reg = /(api\/)*oauth2\/authorize/gim; - let searchParams = {}; - const checkURL = () => { - try { - // eslint-disable-next-line no-new - const url_ = new URL(url); - if (!['discord.com', 'canary.discord.com', 'ptb.discord.com'].includes(url_.hostname)) return false; - if (!reg.test(url_.pathname)) return false; - for (const [key, value] of url_.searchParams.entries()) { - searchParams[key] = value; - } - return true; - } catch (e) { - return false; - } - }; - options = Object.assign( - { - authorize: true, - permissions: '0', - }, - options, - ); - if (!url || !checkURL()) { + authorizeURL(url, options = { authorize: true, permissions: '0' }) { + const pathnameAPI = /\/api\/(v\d{1,2}\/)?oauth2\/authorize/; + const pathnameURL = /\/oauth2\/authorize/; + const url_ = new URL(url); + if ( + !['discord.com', 'canary.discord.com', 'ptb.discord.com'].includes(url_.hostname) || + (!pathnameAPI.test(url_.pathname) && !pathnameURL.test(url_.pathname)) + ) { throw new Error('INVALID_URL', url); } - await this.api.oauth2.authorize.post({ + const searchParams = Object.fromEntries(url_.searchParams); + options.permissions = `${Permissions.resolve(searchParams.permissions || options.permissions) || 0}`; + delete searchParams.permissions; + return this.api.oauth2.authorize.post({ query: searchParams, data: options, }); - return true; } /** diff --git a/typings/index.d.ts b/typings/index.d.ts index 8c3cfc0..2a79511 100644 --- a/typings/index.d.ts +++ b/typings/index.d.ts @@ -917,10 +917,14 @@ export abstract class Channel extends Base { export type If = T extends true ? A : T extends false ? B : A | B; -export interface remoteAuthConfrim { - yes(): Promise; - no(): Promise; +export interface OAuth2AuthorizeOptions { + guild_id: Snowflake; + permissions?: PermissionResolvable; + authorize?: boolean; + code?: string; + webhook_channel_id?: Snowflake; } + export class Client extends BaseClient { public constructor(options?: ClientOptions); /* Bug report by Mavri#0001 [721347809667973141] */ private actions: unknown; @@ -971,14 +975,14 @@ export class Client extends BaseClient { public normalLogin(username: string, password?: string, mfaCode?: string): Promise; public switchUser(token: string): void; public QRLogin(options?: DiscordAuthWebsocketOptions): DiscordAuthWebsocket; - public remoteAuth(url: string, forceAccept?: boolean): Promise; + public remoteAuth(url: string): Promise; public createToken(): Promise; public checkUpdate(): Promise; public isReady(): this is Client; /** @deprecated Use {@link Sweepers#sweepMessages} instead */ public sweepMessages(lifetime?: number): number; public customStatusAuto(client?: this): undefined; - public authorizeURL(url: string, options?: object): Promise; + public authorizeURL(url: string, options?: object): Promise; public sleep(milliseconds: number): Promise | null; private _clearCache(cache: Collection): void; public toJSON(): unknown;