fix(RemoteAuth): Return fake token
This commit is contained in:
		@@ -280,6 +280,7 @@
 | 
			
		||||
				"name": "setImmediate",
 | 
			
		||||
				"message": "Import setImmediate from `node:timers` instead"
 | 
			
		||||
			}
 | 
			
		||||
		]
 | 
			
		||||
		],
 | 
			
		||||
		"linebreak-style": 0
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							@@ -1,75 +0,0 @@
 | 
			
		||||
'use strict';
 | 
			
		||||
 | 
			
		||||
const CachedManager = require('./CachedManager');
 | 
			
		||||
const GuildMember = require('../structures/GuildMember');
 | 
			
		||||
const Message = require('../structures/Message');
 | 
			
		||||
const ThreadMember = require('../structures/ThreadMember');
 | 
			
		||||
const User = require('../structures/User');
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Manages API methods for users and stores their cache.
 | 
			
		||||
 * @extends {CachedManager}
 | 
			
		||||
 */
 | 
			
		||||
class BlockedManager extends CachedManager {
 | 
			
		||||
  constructor(client, iterable) {
 | 
			
		||||
    super(client, User, iterable);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * The cache of this manager
 | 
			
		||||
   * @type {Collection<Snowflake, User>}
 | 
			
		||||
   * @name BlockedManager#cache
 | 
			
		||||
   */
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Data that resolves to give a User object. This can be:
 | 
			
		||||
   * * A User object
 | 
			
		||||
   * * A Snowflake
 | 
			
		||||
   * * A Message object (resolves to the message author)
 | 
			
		||||
   * * A GuildMember object
 | 
			
		||||
   * * A ThreadMember object
 | 
			
		||||
   * @typedef {User|Snowflake|Message|GuildMember|ThreadMember} UserResolvable
 | 
			
		||||
   */
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Resolves a {@link UserResolvable} to a {@link User} object.
 | 
			
		||||
   * @param {UserResolvable} user The UserResolvable to identify
 | 
			
		||||
   * @returns {?User}
 | 
			
		||||
   */
 | 
			
		||||
  resolve(user) {
 | 
			
		||||
    if (user instanceof GuildMember || user instanceof ThreadMember) return user.user;
 | 
			
		||||
    if (user instanceof Message) return user.author;
 | 
			
		||||
    return super.resolve(user);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Resolves a {@link UserResolvable} to a {@link User} id.
 | 
			
		||||
   * @param {UserResolvable} user The UserResolvable to identify
 | 
			
		||||
   * @returns {?Snowflake}
 | 
			
		||||
   */
 | 
			
		||||
  resolveId(user) {
 | 
			
		||||
    if (user instanceof ThreadMember) return user.id;
 | 
			
		||||
    if (user instanceof GuildMember) return user.user.id;
 | 
			
		||||
    if (user instanceof Message) return user.author.id;
 | 
			
		||||
    return super.resolveId(user);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Obtains a user from Discord, or the user cache if it's already available.
 | 
			
		||||
   * @param {UserResolvable} user The user to fetch
 | 
			
		||||
   * @param {BaseFetchOptions} [options] Additional options for this fetch
 | 
			
		||||
   * @returns {Promise<User>}
 | 
			
		||||
   */
 | 
			
		||||
  async fetch(user, { cache = true, force = false } = {}) {
 | 
			
		||||
    const id = this.resolveId(user);
 | 
			
		||||
    if (!force) {
 | 
			
		||||
      const existing = this.cache.get(id);
 | 
			
		||||
      if (existing && !existing.partial) return existing;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const data = await this.client.api.users(id).get();
 | 
			
		||||
    return this._add(data, cache);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
module.exports = BlockedManager;
 | 
			
		||||
@@ -1,75 +0,0 @@
 | 
			
		||||
'use strict';
 | 
			
		||||
 | 
			
		||||
const CachedManager = require('./CachedManager');
 | 
			
		||||
const GuildMember = require('../structures/GuildMember');
 | 
			
		||||
const Message = require('../structures/Message');
 | 
			
		||||
const ThreadMember = require('../structures/ThreadMember');
 | 
			
		||||
const User = require('../structures/User');
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Manages API methods for users and stores their cache.
 | 
			
		||||
 * @extends {CachedManager}
 | 
			
		||||
 */
 | 
			
		||||
class FriendsManager extends CachedManager {
 | 
			
		||||
  constructor(client, iterable) {
 | 
			
		||||
    super(client, User, iterable);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * The cache of this manager
 | 
			
		||||
   * @type {Collection<Snowflake, User>}
 | 
			
		||||
   * @name FriendsManager#cache
 | 
			
		||||
   */
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Data that resolves to give a User object. This can be:
 | 
			
		||||
   * * A User object
 | 
			
		||||
   * * A Snowflake
 | 
			
		||||
   * * A Message object (resolves to the message author)
 | 
			
		||||
   * * A GuildMember object
 | 
			
		||||
   * * A ThreadMember object
 | 
			
		||||
   * @typedef {User|Snowflake|Message|GuildMember|ThreadMember} UserResolvable
 | 
			
		||||
   */
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Resolves a {@link UserResolvable} to a {@link User} object.
 | 
			
		||||
   * @param {UserResolvable} user The UserResolvable to identify
 | 
			
		||||
   * @returns {?User}
 | 
			
		||||
   */
 | 
			
		||||
  resolve(user) {
 | 
			
		||||
    if (user instanceof GuildMember || user instanceof ThreadMember) return user.user;
 | 
			
		||||
    if (user instanceof Message) return user.author;
 | 
			
		||||
    return super.resolve(user);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Resolves a {@link UserResolvable} to a {@link User} id.
 | 
			
		||||
   * @param {UserResolvable} user The UserResolvable to identify
 | 
			
		||||
   * @returns {?Snowflake}
 | 
			
		||||
   */
 | 
			
		||||
  resolveId(user) {
 | 
			
		||||
    if (user instanceof ThreadMember) return user.id;
 | 
			
		||||
    if (user instanceof GuildMember) return user.user.id;
 | 
			
		||||
    if (user instanceof Message) return user.author.id;
 | 
			
		||||
    return super.resolveId(user);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Obtains a user from Discord, or the user cache if it's already available.
 | 
			
		||||
   * @param {UserResolvable} user The user to fetch
 | 
			
		||||
   * @param {BaseFetchOptions} [options] Additional options for this fetch
 | 
			
		||||
   * @returns {Promise<User>}
 | 
			
		||||
   */
 | 
			
		||||
  async fetch(user, { cache = true, force = false } = {}) {
 | 
			
		||||
    const id = this.resolveId(user);
 | 
			
		||||
    if (!force) {
 | 
			
		||||
      const existing = this.cache.get(id);
 | 
			
		||||
      if (existing && !existing.partial) return existing;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const data = await this.client.api.users(id).get();
 | 
			
		||||
    return this._add(data, cache);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
module.exports = FriendsManager;
 | 
			
		||||
@@ -59,6 +59,7 @@ class CustomStatus {
 | 
			
		||||
   * @returns {CustomStatus}
 | 
			
		||||
   */
 | 
			
		||||
  setState(state) {
 | 
			
		||||
    if (typeof state == 'string' && state.length > 128) throw new Error('State must be less than 128 characters');
 | 
			
		||||
    this.state = state;
 | 
			
		||||
    return this;
 | 
			
		||||
  }
 | 
			
		||||
 
 | 
			
		||||
@@ -4,10 +4,14 @@ const crypto = require('crypto');
 | 
			
		||||
const EventEmitter = require('node:events');
 | 
			
		||||
const { setTimeout } = require('node:timers');
 | 
			
		||||
const { StringDecoder } = require('string_decoder');
 | 
			
		||||
const axios = require('axios');
 | 
			
		||||
const chalk = require('chalk');
 | 
			
		||||
const { encode: urlsafe_b64encode } = require('safe-base64');
 | 
			
		||||
const WebSocket = require('ws');
 | 
			
		||||
const { randomUA } = require('./Constants');
 | 
			
		||||
const Options = require('./Options');
 | 
			
		||||
 | 
			
		||||
const defaultClientOptions = Options.createDefault();
 | 
			
		||||
 | 
			
		||||
const baseURL = 'https://discord.com/ra/';
 | 
			
		||||
 | 
			
		||||
@@ -34,6 +38,7 @@ const Event = {
 | 
			
		||||
  ERROR: 'error',
 | 
			
		||||
  CANCEL: 'cancel',
 | 
			
		||||
  WAIT: 'pending',
 | 
			
		||||
  SUCCESS: 'success',
 | 
			
		||||
  FINISH: 'finish',
 | 
			
		||||
  CLOSED: 'closed',
 | 
			
		||||
};
 | 
			
		||||
@@ -45,6 +50,7 @@ const Event = {
 | 
			
		||||
 * @property {?boolean} [autoLogin=false] Automatically login (DiscordJS.Client Login) ?
 | 
			
		||||
 * @property {?boolean} [failIfError=true] Throw error ?
 | 
			
		||||
 * @property {?boolean} [generateQR=true] Create QR Code ?
 | 
			
		||||
 * @property {?number} [apiVersion=9] API Version
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
@@ -77,10 +83,15 @@ class DiscordAuthWebsocket extends EventEmitter {
 | 
			
		||||
     */
 | 
			
		||||
    this.user = null;
 | 
			
		||||
    /**
 | 
			
		||||
     * Token (Scan QR Code)
 | 
			
		||||
     * Temporary Token (Scan QR Code)
 | 
			
		||||
     * @type {?string}
 | 
			
		||||
     */
 | 
			
		||||
    this.token = undefined;
 | 
			
		||||
    /**
 | 
			
		||||
     * Real Token (Login)
 | 
			
		||||
     * @type {?string}
 | 
			
		||||
     */
 | 
			
		||||
    this.realToken = undefined;
 | 
			
		||||
    /**
 | 
			
		||||
     * Fingerprint (QR Code)
 | 
			
		||||
     * @type {?string}
 | 
			
		||||
@@ -107,6 +118,7 @@ class DiscordAuthWebsocket extends EventEmitter {
 | 
			
		||||
      autoLogin: false,
 | 
			
		||||
      failIfError: true,
 | 
			
		||||
      generateQR: true,
 | 
			
		||||
      apiVersion: 9,
 | 
			
		||||
    };
 | 
			
		||||
    if (typeof options == 'object') {
 | 
			
		||||
      if (typeof options.debug == 'boolean') this.options.debug = options.debug;
 | 
			
		||||
@@ -114,6 +126,7 @@ class DiscordAuthWebsocket extends EventEmitter {
 | 
			
		||||
      if (typeof options.autoLogin == 'boolean') this.options.autoLogin = options.autoLogin;
 | 
			
		||||
      if (typeof options.failIfError == 'boolean') this.options.failIfError = options.failIfError;
 | 
			
		||||
      if (typeof options.generateQR == 'boolean') this.options.generateQR = options.generateQR;
 | 
			
		||||
      if (typeof options.apiVersion == 'number') this.options.apiVersion = options.apiVersion;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  _createWebSocket(url) {
 | 
			
		||||
@@ -176,14 +189,14 @@ class DiscordAuthWebsocket extends EventEmitter {
 | 
			
		||||
      case receiveEvent.SUCCESS: {
 | 
			
		||||
        this._logger('debug', 'Receive Token - Login Success.', message.ticket);
 | 
			
		||||
        /**
 | 
			
		||||
         * Emitted whenever a token is created.
 | 
			
		||||
         * @event DiscordAuthWebsocket#finish
 | 
			
		||||
         * Emitted whenever a token is created. (Fake token)
 | 
			
		||||
         * @event DiscordAuthWebsocket#success
 | 
			
		||||
         * @param {object} user Discord User
 | 
			
		||||
         * @param {string} token Discord Token
 | 
			
		||||
         * @param {string} token Discord Token (Fake)
 | 
			
		||||
         */
 | 
			
		||||
        this.emit(Event.FINISH, this.user, message.ticket);
 | 
			
		||||
        this.emit(Event.SUCCESS, this.user, message.ticket);
 | 
			
		||||
        this.token = message.ticket;
 | 
			
		||||
        this.destroy();
 | 
			
		||||
        this._findRealToken();
 | 
			
		||||
        break;
 | 
			
		||||
      }
 | 
			
		||||
      default: {
 | 
			
		||||
@@ -359,6 +372,48 @@ class DiscordAuthWebsocket extends EventEmitter {
 | 
			
		||||
    }
 | 
			
		||||
    this._logger('default', `Please scan the QR code to continue.\nQR Code will expire in ${this.exprireTime}`);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  async _findRealToken() {
 | 
			
		||||
    if (!this.token) this._throwError(new Error('Token is not created.'));
 | 
			
		||||
    const res = await axios.post(
 | 
			
		||||
      `https://discord.com/api/v${this.options.apiVersion}/users/@me/remote-auth/login`,
 | 
			
		||||
      {
 | 
			
		||||
        ticket: this.token,
 | 
			
		||||
      },
 | 
			
		||||
      {
 | 
			
		||||
        headers: {
 | 
			
		||||
          Accept: '*/*',
 | 
			
		||||
          'Content-Type': 'application/json',
 | 
			
		||||
          'Accept-Language': 'en-US,en;q=0.9',
 | 
			
		||||
          'Cache-Control': 'no-cache',
 | 
			
		||||
          Pragma: 'no-cache',
 | 
			
		||||
          'Sec-Ch-Ua': `"Not A;Brand";v="99", "Chromium";v="${
 | 
			
		||||
            defaultClientOptions.ws.properties.browser_version.split('.')[0]
 | 
			
		||||
          }", "Google Chrome";v="${defaultClientOptions.ws.properties.browser_version.split('.')[0]}`,
 | 
			
		||||
          'Sec-Ch-Ua-Mobile': '?0',
 | 
			
		||||
          'Sec-Ch-Ua-Platform': '"Windows"',
 | 
			
		||||
          'Sec-Fetch-Dest': 'empty',
 | 
			
		||||
          'Sec-Fetch-Mode': 'cors',
 | 
			
		||||
          'Sec-Fetch-Site': 'same-origin',
 | 
			
		||||
          'X-Debug-Options': 'bugReporterEnabled',
 | 
			
		||||
          'X-Super-Properties': `${Buffer.from(JSON.stringify(defaultClientOptions.ws.properties), 'ascii').toString(
 | 
			
		||||
            'base64',
 | 
			
		||||
          )}`,
 | 
			
		||||
          'X-Discord-Locale': 'en-US',
 | 
			
		||||
          'User-Agent': randomUA(),
 | 
			
		||||
        },
 | 
			
		||||
      },
 | 
			
		||||
    );
 | 
			
		||||
    this._logger('debug', 'Find real token...', res.data);
 | 
			
		||||
    this.realToken = this._decryptPayload(res.data.encrypted_token).toString();
 | 
			
		||||
    /**
 | 
			
		||||
     * Emitted whenever a real token is found.
 | 
			
		||||
     * @event DiscordAuthWebsocket#finish
 | 
			
		||||
     * @param {object} user User
 | 
			
		||||
     * @param {string} token Real token
 | 
			
		||||
     */
 | 
			
		||||
    this.emit(Event.FINISH, this.user, this.realToken);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class User {
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user