fix: Export, Typing, etc.
- Rename `RemoteAuth` > `DiscordAuthWebsocket` - Add new method: Client.remoteAuth() & Client.createToken() - fix: RedeemNitro (wrong Regex)
This commit is contained in:
parent
fe9be92bd2
commit
b1257bc62d
File diff suppressed because one or more lines are too long
4
package-lock.json
generated
4
package-lock.json
generated
@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "discord.js-selfbot-v13",
|
"name": "discord.js-selfbot-v13",
|
||||||
"version": "2.3.7",
|
"version": "2.3.71",
|
||||||
"lockfileVersion": 2,
|
"lockfileVersion": 2,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "discord.js-selfbot-v13",
|
"name": "discord.js-selfbot-v13",
|
||||||
"version": "2.3.7",
|
"version": "2.3.71",
|
||||||
"license": "GNU General Public License v3.0",
|
"license": "GNU General Public License v3.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@aikochan2k6/qrcode-terminal": "^0.12.0",
|
"@aikochan2k6/qrcode-terminal": "^0.12.0",
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "discord.js-selfbot-v13",
|
"name": "discord.js-selfbot-v13",
|
||||||
"version": "2.3.7",
|
"version": "2.3.71",
|
||||||
"description": "A unofficial discord.js fork for creating selfbots [Based on discord.js v13]",
|
"description": "A unofficial discord.js fork for creating selfbots [Based on discord.js v13]",
|
||||||
"main": "./src/index.js",
|
"main": "./src/index.js",
|
||||||
"types": "./typings/index.d.ts",
|
"types": "./typings/index.d.ts",
|
||||||
|
@ -380,6 +380,68 @@ class Client extends BaseClient {
|
|||||||
return QR;
|
return QR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @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<remoteAuthConfrim | void>}
|
||||||
|
*/
|
||||||
|
async remoteAuth(url, forceAccept = false) {
|
||||||
|
if (!this.isReady()) throw new Error('CLIENT_NOT_READY', 'Remote Auth');
|
||||||
|
// Step 1: Parse URL
|
||||||
|
url = new URL(url);
|
||||||
|
if (
|
||||||
|
!['discordapp.com', 'discord.com'].includes(url.hostname) ||
|
||||||
|
!url.pathname.startsWith('/ra/') ||
|
||||||
|
url.pathname.length <= 4
|
||||||
|
) {
|
||||||
|
throw new Error('INVALID_REMOTE_AUTH_URL');
|
||||||
|
}
|
||||||
|
const hash = url.pathname.replace('/ra/', '');
|
||||||
|
// Step 2: Post > Get handshake_token
|
||||||
|
const res = await this.api.users['@me']['remote-auth'].post({
|
||||||
|
data: {
|
||||||
|
fingerprint: hash,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
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,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new token based on the current token
|
||||||
|
* @returns {Promise<string>} Discord Token
|
||||||
|
*/
|
||||||
|
createToken() {
|
||||||
|
return new Promise(resolve => {
|
||||||
|
// Step 1: Create DiscordAuthWebsocket
|
||||||
|
const QR = new DiscordAuthWebsocket(undefined, false, true);
|
||||||
|
// Step 2: Add event
|
||||||
|
QR.on('ready', async url => {
|
||||||
|
await this.remoteAuth(url, true);
|
||||||
|
}).on('success', (user, token) => {
|
||||||
|
resolve(token);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns whether the client has logged in, indicative of being able to access
|
* Returns whether the client has logged in, indicative of being able to access
|
||||||
* properties such as `user` and `application`.
|
* properties such as `user` and `application`.
|
||||||
@ -461,31 +523,35 @@ class Client extends BaseClient {
|
|||||||
* @param {boolean} failIfNotExists Whether to fail if the code doesn't exist
|
* @param {boolean} failIfNotExists Whether to fail if the code doesn't exist
|
||||||
* @returns {Promise<boolean>}
|
* @returns {Promise<boolean>}
|
||||||
*/
|
*/
|
||||||
redeemNitro(nitro, channel, failIfNotExists = true) {
|
async redeemNitro(nitro, channel, failIfNotExists = true) {
|
||||||
if (typeof nitro !== 'string') throw new Error('INVALID_NITRO');
|
if (typeof nitro !== 'string') throw new Error('INVALID_NITRO');
|
||||||
channel = this.channels.resolveId(channel);
|
channel = this.channels.resolveId(channel);
|
||||||
const regex = {
|
const regex = {
|
||||||
gift: /(discord.gift|discord.com|discordapp.com\/gifts)\/\w{16,25}/gim,
|
gift: /(discord.gift|discord.com|discordapp.com\/gifts)\/\w{16,25}/gim,
|
||||||
url: /(discord\.gift\/|discord\.com\/gifts\/|discordapp\.com\/gifts\/)/gim,
|
url: /(discord\.gift\/|discord\.com\/gifts\/|discordapp\.com\/gifts\/)/gim,
|
||||||
};
|
};
|
||||||
const code = DataResolver.resolveCode(nitro, regex.gift);
|
const nitroArray = nitro.match(regex.gift);
|
||||||
if (this.usedCodes.indexOf(code) > -1) return false;
|
if (!nitroArray) return false;
|
||||||
return new Promise((resolve, reject) => {
|
const codeArray = nitroArray.map(code => code.replace(regex.url, ''));
|
||||||
this.api.entitlements['gift-codes'](code)
|
let redeem = false;
|
||||||
|
for await (const code of codeArray) {
|
||||||
|
if (this.usedCodes.indexOf(code) > -1) continue;
|
||||||
|
await this.api.entitlements['gift-codes'](code)
|
||||||
.redeem.post({
|
.redeem.post({
|
||||||
auth: true,
|
auth: true,
|
||||||
data: { channel_id: channel || null, payment_source_id: null },
|
data: { channel_id: channel || null, payment_source_id: null },
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
this.usedCodes.push(code);
|
this.usedCodes.push(code);
|
||||||
resolve(true);
|
redeem = true;
|
||||||
})
|
})
|
||||||
.catch(e => {
|
.catch(e => {
|
||||||
if (failIfNotExists) reject(e);
|
this.usedCodes.push(code);
|
||||||
else resolve(false);
|
if (failIfNotExists) throw e;
|
||||||
});
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
return redeem;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Obtains a template from Discord.
|
* Obtains a template from Discord.
|
||||||
|
@ -192,6 +192,8 @@ const Messages = {
|
|||||||
MODAL_SUBMIT_INTERACTION_FIELD_NOT_FOUND: customId => `Required field with custom id "${customId}" not found.`,
|
MODAL_SUBMIT_INTERACTION_FIELD_NOT_FOUND: customId => `Required field with custom id "${customId}" not found.`,
|
||||||
MODAL_SUBMIT_INTERACTION_FIELD_TYPE: (customId, type, expected) =>
|
MODAL_SUBMIT_INTERACTION_FIELD_TYPE: (customId, type, expected) =>
|
||||||
`Field with custom id "${customId}" is of type: ${type}; expected ${expected}.`,
|
`Field with custom id "${customId}" is of type: ${type}; expected ${expected}.`,
|
||||||
|
|
||||||
|
INVALID_REMOTE_AUTH_URL: 'Invalid remote auth URL (https://discord.com/ra/{hash})',
|
||||||
};
|
};
|
||||||
|
|
||||||
for (const [name, message] of Object.entries(Messages)) register(name, message);
|
for (const [name, message] of Object.entries(Messages)) register(name, message);
|
||||||
|
@ -33,7 +33,6 @@ exports.UserFlags = require('./util/UserFlags');
|
|||||||
exports.Util = require('./util/Util');
|
exports.Util = require('./util/Util');
|
||||||
exports.version = require('../package.json').version;
|
exports.version = require('../package.json').version;
|
||||||
exports.DiscordAuthWebsocket = require('./util/RemoteAuth');
|
exports.DiscordAuthWebsocket = require('./util/RemoteAuth');
|
||||||
exports.RemoteAuth = require('./util/RemoteAuth');
|
|
||||||
exports.PurchasedFlags = require('./util/PurchasedFlags');
|
exports.PurchasedFlags = require('./util/PurchasedFlags');
|
||||||
|
|
||||||
// Managers
|
// Managers
|
||||||
|
@ -24,17 +24,19 @@ class DiscordUser_FromPayload {
|
|||||||
let values = payload.split(':');
|
let values = payload.split(':');
|
||||||
this.id = values[0];
|
this.id = values[0];
|
||||||
this.username = values[3];
|
this.username = values[3];
|
||||||
this.discrim = values[1];
|
this.discriminator = values[1];
|
||||||
this.avatar_hash = values[2];
|
this.avatar = values[2];
|
||||||
|
this.tag = `${this.username}#${this.discriminator}`;
|
||||||
|
this.avatarURL = `https://cdn.discordapp.com/avatars/${this.id}/${this.avatar}.${
|
||||||
|
this.avatar.startsWith('a_') ? 'gif' : 'png'
|
||||||
|
}`;
|
||||||
this.debug = debug;
|
this.debug = debug;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
pretty_print() {
|
pretty_print() {
|
||||||
let out = '';
|
let out = '';
|
||||||
out += `User: ${this.username}#${this.discrim} (${this.id})\n`;
|
out += `User: ${this.tag} (${this.id})\n`;
|
||||||
out += `Avatar URL: https://cdn.discordapp.com/avatars/${this.id}/${this.avatar_hash}.${
|
out += `Avatar URL: ${this.avatarURL}\n`;
|
||||||
this.avatar_hash.startsWith('a_') ? 'gif' : 'png'
|
|
||||||
}\n`;
|
|
||||||
if (this.debug) out += `Token: ${this.token}\n`;
|
if (this.debug) out += `Token: ${this.token}\n`;
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
@ -49,12 +51,14 @@ class DiscordAuthWebsocket extends EventEmitter {
|
|||||||
/**
|
/**
|
||||||
* Creates a new DiscordAuthWebsocket instance.
|
* Creates a new DiscordAuthWebsocket instance.
|
||||||
* @param {?Client} client Discord.Client (Login)
|
* @param {?Client} client Discord.Client (Login)
|
||||||
* @param {boolean} debug Log debug info
|
* @param {?boolean} debug Log debug info
|
||||||
|
* @param {?boolean} hideLog Hide log ?
|
||||||
*/
|
*/
|
||||||
constructor(client, debug = false) {
|
constructor(client, debug = false, hideLog = false) {
|
||||||
super();
|
super();
|
||||||
this.debug = debug;
|
this.debug = debug;
|
||||||
this.client = client;
|
this.client = client;
|
||||||
|
this.hideLog = hideLog;
|
||||||
this.ws = new WebSocket(client?.options?.http?.remoteAuth || 'wss://remote-auth-gateway.discord.gg/?v=1', {
|
this.ws = new WebSocket(client?.options?.http?.remoteAuth || 'wss://remote-auth-gateway.discord.gg/?v=1', {
|
||||||
headers: {
|
headers: {
|
||||||
Origin: 'https://discord.com',
|
Origin: 'https://discord.com',
|
||||||
@ -132,7 +136,7 @@ class DiscordAuthWebsocket extends EventEmitter {
|
|||||||
* @param {string} url DiscordAuthWebsocket
|
* @param {string} url DiscordAuthWebsocket
|
||||||
*/
|
*/
|
||||||
this.emit('ready', this.authURL);
|
this.emit('ready', this.authURL);
|
||||||
this.generate_qr_code(fingerprint);
|
if (!this.hideLog) this.generate_qr_code(fingerprint);
|
||||||
if (this.debug) console.log('[WebSocket] QR Code generated');
|
if (this.debug) console.log('[WebSocket] QR Code generated');
|
||||||
console.log(
|
console.log(
|
||||||
`Please scan the QR code to continue.\nQR Code will expire in ${this.missQR.toLocaleString('vi-VN')}`,
|
`Please scan the QR code to continue.\nQR Code will expire in ${this.missQR.toLocaleString('vi-VN')}`,
|
||||||
@ -142,11 +146,17 @@ class DiscordAuthWebsocket extends EventEmitter {
|
|||||||
let payload = this.decrypt_payload(encrypted_payload);
|
let payload = this.decrypt_payload(encrypted_payload);
|
||||||
const decoder = new StringDecoder('utf-8');
|
const decoder = new StringDecoder('utf-8');
|
||||||
this.user = new DiscordUser_FromPayload(decoder.write(payload), this.debug);
|
this.user = new DiscordUser_FromPayload(decoder.write(payload), this.debug);
|
||||||
console.log('\n');
|
if (!this.hideLog) console.log('\n');
|
||||||
console.log(this.user.pretty_print());
|
if (!this.hideLog) console.log(this.user.pretty_print());
|
||||||
|
/**
|
||||||
|
* Emitted whenever a user is scan QR Code.
|
||||||
|
* @event DiscordAuthWebsocket#pending
|
||||||
|
* @param {object} user Discord User Raw
|
||||||
|
*/
|
||||||
|
this.emit('pending', this.user);
|
||||||
if (this.debug) console.log('[WebSocket] Waiting for user to finish login...');
|
if (this.debug) console.log('[WebSocket] Waiting for user to finish login...');
|
||||||
console.log('\n');
|
if (!this.hideLog) console.log('\n');
|
||||||
console.log('Please check your phone again to confirm login.');
|
if (!this.hideLog) console.log('Please check your phone again to confirm login.');
|
||||||
} else if (op == Messages.FINISH) {
|
} else if (op == Messages.FINISH) {
|
||||||
this.login_state = true;
|
this.login_state = true;
|
||||||
let encrypted_token = data.encrypted_token;
|
let encrypted_token = data.encrypted_token;
|
||||||
@ -158,29 +168,19 @@ class DiscordAuthWebsocket extends EventEmitter {
|
|||||||
/**
|
/**
|
||||||
* Emitted whenever a token is created.
|
* Emitted whenever a token is created.
|
||||||
* @event DiscordAuthWebsocket#success
|
* @event DiscordAuthWebsocket#success
|
||||||
* @param {object} user Discord User
|
* @param {object} user Discord User (Raw)
|
||||||
* @param {string} token Discord Token
|
* @param {string} token Discord Token
|
||||||
*/
|
*/
|
||||||
this.emit(
|
this.emit('success', this.user, this.token);
|
||||||
'success',
|
|
||||||
{
|
|
||||||
id: this.user.id,
|
|
||||||
tag: `${this.user.username}#${this.user.discrim}`,
|
|
||||||
},
|
|
||||||
this.token,
|
|
||||||
);
|
|
||||||
this.client?.login(this.user.token);
|
this.client?.login(this.user.token);
|
||||||
this.destroy();
|
this.destroy();
|
||||||
} else if (op == Messages.CANCEL) {
|
} else if (op == Messages.CANCEL) {
|
||||||
/**
|
/**
|
||||||
* Emitted whenever a user cancels the login process.
|
* Emitted whenever a user cancels the login process.
|
||||||
* @event DiscordAuthWebsocket#cancel
|
* @event DiscordAuthWebsocket#cancel
|
||||||
* @param {object} user User
|
* @param {object} user User (Raw)
|
||||||
*/
|
*/
|
||||||
this.emit('cancel', {
|
this.emit('cancel', this.user);
|
||||||
id: this.user.id,
|
|
||||||
tag: `${this.user.username}#${this.user.discrim}`,
|
|
||||||
});
|
|
||||||
this.destroy();
|
this.destroy();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -200,10 +200,16 @@ class DiscordAuthWebsocket extends EventEmitter {
|
|||||||
this.ws.close();
|
this.ws.close();
|
||||||
clearInterval(this.heartbeat_interval);
|
clearInterval(this.heartbeat_interval);
|
||||||
clearTimeout(this.connectionDestroy);
|
clearTimeout(this.connectionDestroy);
|
||||||
|
/**
|
||||||
|
* Emitted whenever a connection is closed.
|
||||||
|
* @event DiscordAuthWebsocket#closed
|
||||||
|
* @param {boolean} loginState Login state
|
||||||
|
*/
|
||||||
|
this.emit('closed', this.login_state);
|
||||||
if (this.debug) {
|
if (this.debug) {
|
||||||
console.log(`[WebSocket] Connection Destroyed, User login state: ${this.login_state ? 'success' : 'failure'}`);
|
console.log(`[WebSocket] Connection Destroyed, User login state: ${this.login_state ? 'success' : 'failure'}`);
|
||||||
}
|
}
|
||||||
if (!this.login_state) throw new Error('Login failed');
|
if (!this.login_state && this.client) throw new Error('Login failed');
|
||||||
}
|
}
|
||||||
|
|
||||||
public_key() {
|
public_key() {
|
||||||
|
24
typings/index.d.ts
vendored
24
typings/index.d.ts
vendored
@ -162,10 +162,21 @@ import {
|
|||||||
RawWidgetMemberData,
|
RawWidgetMemberData,
|
||||||
} from './rawDataTypes';
|
} from './rawDataTypes';
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
import DiscordAuthWebsocket from '../src/util/RemoteAuth.js';
|
|
||||||
|
|
||||||
//#region Classes
|
//#region Classes
|
||||||
|
export abstract class DiscordAuthWebsocket extends EventEmitter {
|
||||||
|
constructor(client?: Client, debug?: boolean, hideLog?: boolean);
|
||||||
|
public authURL?: string;
|
||||||
|
public token?: string;
|
||||||
|
public user?: RawUserData;
|
||||||
|
public destroy(): void;
|
||||||
|
public generate_qr_code(fingerprint: string): void;
|
||||||
|
public on(event: 'ready', listener: (authURL: string) => void): this;
|
||||||
|
public on(event: 'success', listener: (user: RawUserData, token: string) => void): this;
|
||||||
|
public on(event: 'cancel', listener: (user: RawUserData) => void): this;
|
||||||
|
public on(event: 'pending', listener: (user: RawUserData) => void): this;
|
||||||
|
public on(event: 'closed', listener: (loginState: boolean) => void): this;
|
||||||
|
public on(event: string, listener: (...args: any[]) => Awaitable<void>): this;
|
||||||
|
}
|
||||||
// RPC by aiko-chan-ai
|
// RPC by aiko-chan-ai
|
||||||
export interface RichButton {
|
export interface RichButton {
|
||||||
name: string;
|
name: string;
|
||||||
@ -754,6 +765,11 @@ export abstract class Channel extends Base {
|
|||||||
|
|
||||||
export type If<T extends boolean, A, B = null> = T extends true ? A : T extends false ? B : A | B;
|
export type If<T extends boolean, A, B = null> = T extends true ? A : T extends false ? B : A | B;
|
||||||
|
|
||||||
|
export interface remoteAuthConfrim {
|
||||||
|
yes(): Promise<undefined>;
|
||||||
|
no(): Promise<undefined>;
|
||||||
|
}
|
||||||
|
|
||||||
export class Client<Ready extends boolean = boolean> extends BaseClient {
|
export class Client<Ready extends boolean = boolean> extends BaseClient {
|
||||||
public constructor(options?: ClientOptions); /* Bug report by Mavri#0001 [721347809667973141] */
|
public constructor(options?: ClientOptions); /* Bug report by Mavri#0001 [721347809667973141] */
|
||||||
private actions: unknown;
|
private actions: unknown;
|
||||||
@ -797,6 +813,8 @@ export class Client<Ready extends boolean = boolean> extends BaseClient {
|
|||||||
public generateInvite(options?: InviteGenerationOptions): string;
|
public generateInvite(options?: InviteGenerationOptions): string;
|
||||||
public login(token?: string): Promise<string>;
|
public login(token?: string): Promise<string>;
|
||||||
public QRLogin(debug?: boolean): DiscordAuthWebsocket;
|
public QRLogin(debug?: boolean): DiscordAuthWebsocket;
|
||||||
|
public remoteAuth(url: string, forceAccept?: boolean): Promise<remoteAuthConfrim | undefined>;
|
||||||
|
public createToken(): Promise<string>;
|
||||||
public readonly callVoice: VoiceConnection | undefined;
|
public readonly callVoice: VoiceConnection | undefined;
|
||||||
public isReady(): this is Client<true>;
|
public isReady(): this is Client<true>;
|
||||||
/** @deprecated Use {@link Sweepers#sweepMessages} instead */
|
/** @deprecated Use {@link Sweepers#sweepMessages} instead */
|
||||||
|
Loading…
Reference in New Issue
Block a user