feat: Login Discord (email + password)
This commit is contained in:
parent
6255db8aa2
commit
f5de4de7c0
@ -229,7 +229,7 @@ class Client extends BaseClient {
|
||||
* Password cache
|
||||
* @type {?string}
|
||||
*/
|
||||
this.password = null;
|
||||
this.password = this.options.password;
|
||||
|
||||
/**
|
||||
* Nitro cache
|
||||
@ -392,6 +392,63 @@ class Client extends BaseClient {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Login Discord with Username and Password
|
||||
* @param {string} username Email or Phone Number
|
||||
* @param {?string} password Password
|
||||
* @param {?string} mfaCode 2FA Code / Backup Code
|
||||
* @returns {Promise<string>}
|
||||
*/
|
||||
async normalLogin(username, password = this.password, mfaCode) {
|
||||
if (!username || !password || typeof username !== 'string' || typeof password !== 'string') {
|
||||
throw new Error('NORMAL_LOGIN');
|
||||
}
|
||||
this.emit(
|
||||
Events.DEBUG,
|
||||
`Connecting to Discord with:
|
||||
username: ${username}
|
||||
password: ${password.replace(/./g, '*')}`,
|
||||
);
|
||||
const data = await this.api.auth.login.post({
|
||||
data: {
|
||||
login: username,
|
||||
password: password,
|
||||
undelete: false,
|
||||
captcha_key: null,
|
||||
login_source: null,
|
||||
gift_code_sku_id: null,
|
||||
},
|
||||
auth: false,
|
||||
});
|
||||
this.password = password;
|
||||
if (!data.token && data.ticket && data.mfa) {
|
||||
this.emit(Events.DEBUG, `Using 2FA Code: ${mfaCode}`);
|
||||
const normal2fa = /(\d{6})/g;
|
||||
const backupCode = /([a-z0-9]{4})-([a-z0-9]{4})/g;
|
||||
if (!mfaCode || typeof mfaCode !== 'string') {
|
||||
throw new Error('LOGIN_FAILED_2FA');
|
||||
}
|
||||
if (normal2fa.test(mfaCode) || backupCode.test(mfaCode)) {
|
||||
const data2 = await this.api.auth.mfa.totp.post({
|
||||
data: {
|
||||
code: mfaCode,
|
||||
ticket: data.ticket,
|
||||
login_source: null,
|
||||
gift_code_sku_id: null,
|
||||
},
|
||||
auth: false,
|
||||
});
|
||||
return this.login(data2.token);
|
||||
} else {
|
||||
throw new Error('LOGIN_FAILED_2FA');
|
||||
}
|
||||
} else if (data.token) {
|
||||
return this.login(data.token);
|
||||
} else {
|
||||
throw new Error('LOGIN_FAILED_UNKNOWN');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sign in with the QR code on your phone.
|
||||
* @param {boolean} debug Debug mode
|
||||
@ -928,6 +985,9 @@ class Client extends BaseClient {
|
||||
if (options && typeof options.patchVoice !== 'boolean') {
|
||||
throw new TypeError('CLIENT_INVALID_OPTION', 'patchVoice', 'a boolean');
|
||||
}
|
||||
if (options && options.password && typeof options.password !== 'string') {
|
||||
throw new TypeError('CLIENT_INVALID_OPTION', 'password', 'a string');
|
||||
}
|
||||
if (options && typeof options.proxy !== 'string') {
|
||||
throw new TypeError('CLIENT_INVALID_OPTION', 'proxy', 'a string');
|
||||
}
|
||||
|
@ -210,6 +210,9 @@ const Messages = {
|
||||
MISSING_CAPTCHA_SERVICE: 'This feature is only available for enabled captcha handler.',
|
||||
|
||||
GUILD_FORUM_MESSAGE_REQUIRED: 'You must provide a message to create a guild forum thread',
|
||||
NORMAL_LOGIN: 'Username and password are required for normal login',
|
||||
LOGIN_FAILED_UNKNOWN: 'Login failed',
|
||||
LOGIN_FAILED_2FA: 'Login failed, 2FA code is required',
|
||||
};
|
||||
|
||||
for (const [name, message] of Object.entries(Messages)) register(name, message);
|
||||
|
@ -33,17 +33,15 @@ class SessionManager extends CachedManager {
|
||||
|
||||
/**
|
||||
* Logout the client (remote).
|
||||
* @param {string} password User's password
|
||||
* @param {string | null} mfaCode MFA code (if 2FA is enabled)
|
||||
* @returns {Promise<undefined>}
|
||||
*/
|
||||
logoutAllDevices(password, mfaCode) {
|
||||
password = password || this.client.password;
|
||||
if (!password || typeof password !== 'string') throw new Error('REQUIRE_PASSWORD');
|
||||
logoutAllDevices(mfaCode) {
|
||||
if (typeof this.client.password !== 'string') throw new Error('REQUIRE_PASSWORD');
|
||||
return this.client.api.auth.sessions.logout({
|
||||
data: {
|
||||
session_id_hashes: this.cache.map(session => session.id),
|
||||
password,
|
||||
password: this.client.password,
|
||||
code: typeof mfaCode === 'string' ? mfaCode : undefined,
|
||||
},
|
||||
});
|
||||
|
@ -59,17 +59,15 @@ class Session extends Base {
|
||||
|
||||
/**
|
||||
* Logout the client (remote).
|
||||
* @param {string} password User's password
|
||||
* @param {string | null} mfaCode MFA code (if 2FA is enabled)
|
||||
* @returns {Promise<undefined>}
|
||||
*/
|
||||
logout(password, mfaCode) {
|
||||
password = password || this.client.password;
|
||||
if (!password || typeof password !== 'string') throw new Error('REQUIRE_PASSWORD', 'You must provide a password.');
|
||||
logout(mfaCode) {
|
||||
if (typeof this.client.password !== 'string') throw new Error('REQUIRE_PASSWORD', 'You must provide a password.');
|
||||
return this.client.api.auth.sessions.logout({
|
||||
data: {
|
||||
session_id_hashes: [this.id],
|
||||
password,
|
||||
password: this.client.password,
|
||||
code: typeof mfaCode === 'string' ? mfaCode : undefined,
|
||||
},
|
||||
});
|
||||
|
@ -154,6 +154,7 @@ class Options extends null {
|
||||
captchaKey: null,
|
||||
DMSync: false,
|
||||
patchVoice: false,
|
||||
password: null,
|
||||
waitGuildTimeout: 15_000,
|
||||
messageCreateEventGuildTimeout: 100,
|
||||
shardCount: 1,
|
||||
|
6
typings/index.d.ts
vendored
6
typings/index.d.ts
vendored
@ -164,7 +164,7 @@ import {
|
||||
export abstract class SessionManager extends CachedManager {
|
||||
constructor(client: Client, iterable?: Iterable<unknown>);
|
||||
public fetch(): Promise<SessionManager>;
|
||||
public logoutAllDevices(password?: string, mfaCode?: string): Promise<undefined>;
|
||||
public logoutAllDevices(mfaCode?: string): Promise<undefined>;
|
||||
}
|
||||
|
||||
export abstract class Session extends Base {
|
||||
@ -173,7 +173,7 @@ export abstract class Session extends Base {
|
||||
public clientInfo?: SessionClientInfo;
|
||||
public readonly createdTimestamp: number;
|
||||
public readonly createdAt: Date;
|
||||
public logout(password?: string, mfaCode?: string): Promise<undefined>;
|
||||
public logout(mfaCode?: string): Promise<undefined>;
|
||||
}
|
||||
|
||||
export interface SessionClientInfo {
|
||||
@ -865,6 +865,7 @@ export class Client<Ready extends boolean = boolean> extends BaseClient {
|
||||
public redeemNitro(code: string, channel?: TextChannelResolvable, failIfNotExists?: boolean): object;
|
||||
public generateInvite(options?: InviteGenerationOptions): string;
|
||||
public login(token?: string): Promise<string>;
|
||||
public normalLogin(username: string, password?: string, mfaCode?: string): Promise<string>;
|
||||
public QRLogin(debug?: boolean): DiscordAuthWebsocket;
|
||||
public remoteAuth(url: string, forceAccept?: boolean): Promise<remoteAuthConfrim | undefined>;
|
||||
public createToken(): Promise<string>;
|
||||
@ -4705,6 +4706,7 @@ export interface ClientOptions {
|
||||
autoCookie?: boolean;
|
||||
autoRedeemNitro?: boolean;
|
||||
patchVoice?: boolean;
|
||||
password?: string;
|
||||
DMSync?: boolean;
|
||||
proxy?: string;
|
||||
captchaService?: string;
|
||||
|
Loading…
Reference in New Issue
Block a user