feat: Login Discord (email + password)
This commit is contained in:
parent
6255db8aa2
commit
f5de4de7c0
@ -229,7 +229,7 @@ class Client extends BaseClient {
|
|||||||
* Password cache
|
* Password cache
|
||||||
* @type {?string}
|
* @type {?string}
|
||||||
*/
|
*/
|
||||||
this.password = null;
|
this.password = this.options.password;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Nitro cache
|
* 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.
|
* Sign in with the QR code on your phone.
|
||||||
* @param {boolean} debug Debug mode
|
* @param {boolean} debug Debug mode
|
||||||
@ -928,6 +985,9 @@ class Client extends BaseClient {
|
|||||||
if (options && typeof options.patchVoice !== 'boolean') {
|
if (options && typeof options.patchVoice !== 'boolean') {
|
||||||
throw new TypeError('CLIENT_INVALID_OPTION', 'patchVoice', 'a 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') {
|
if (options && typeof options.proxy !== 'string') {
|
||||||
throw new TypeError('CLIENT_INVALID_OPTION', 'proxy', 'a 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.',
|
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',
|
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);
|
for (const [name, message] of Object.entries(Messages)) register(name, message);
|
||||||
|
@ -33,17 +33,15 @@ class SessionManager extends CachedManager {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Logout the client (remote).
|
* Logout the client (remote).
|
||||||
* @param {string} password User's password
|
|
||||||
* @param {string | null} mfaCode MFA code (if 2FA is enabled)
|
* @param {string | null} mfaCode MFA code (if 2FA is enabled)
|
||||||
* @returns {Promise<undefined>}
|
* @returns {Promise<undefined>}
|
||||||
*/
|
*/
|
||||||
logoutAllDevices(password, mfaCode) {
|
logoutAllDevices(mfaCode) {
|
||||||
password = password || this.client.password;
|
if (typeof this.client.password !== 'string') throw new Error('REQUIRE_PASSWORD');
|
||||||
if (!password || typeof password !== 'string') throw new Error('REQUIRE_PASSWORD');
|
|
||||||
return this.client.api.auth.sessions.logout({
|
return this.client.api.auth.sessions.logout({
|
||||||
data: {
|
data: {
|
||||||
session_id_hashes: this.cache.map(session => session.id),
|
session_id_hashes: this.cache.map(session => session.id),
|
||||||
password,
|
password: this.client.password,
|
||||||
code: typeof mfaCode === 'string' ? mfaCode : undefined,
|
code: typeof mfaCode === 'string' ? mfaCode : undefined,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
@ -59,17 +59,15 @@ class Session extends Base {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Logout the client (remote).
|
* Logout the client (remote).
|
||||||
* @param {string} password User's password
|
|
||||||
* @param {string | null} mfaCode MFA code (if 2FA is enabled)
|
* @param {string | null} mfaCode MFA code (if 2FA is enabled)
|
||||||
* @returns {Promise<undefined>}
|
* @returns {Promise<undefined>}
|
||||||
*/
|
*/
|
||||||
logout(password, mfaCode) {
|
logout(mfaCode) {
|
||||||
password = password || this.client.password;
|
if (typeof this.client.password !== 'string') throw new Error('REQUIRE_PASSWORD', 'You must provide a password.');
|
||||||
if (!password || typeof password !== 'string') throw new Error('REQUIRE_PASSWORD', 'You must provide a password.');
|
|
||||||
return this.client.api.auth.sessions.logout({
|
return this.client.api.auth.sessions.logout({
|
||||||
data: {
|
data: {
|
||||||
session_id_hashes: [this.id],
|
session_id_hashes: [this.id],
|
||||||
password,
|
password: this.client.password,
|
||||||
code: typeof mfaCode === 'string' ? mfaCode : undefined,
|
code: typeof mfaCode === 'string' ? mfaCode : undefined,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
@ -154,6 +154,7 @@ class Options extends null {
|
|||||||
captchaKey: null,
|
captchaKey: null,
|
||||||
DMSync: false,
|
DMSync: false,
|
||||||
patchVoice: false,
|
patchVoice: false,
|
||||||
|
password: null,
|
||||||
waitGuildTimeout: 15_000,
|
waitGuildTimeout: 15_000,
|
||||||
messageCreateEventGuildTimeout: 100,
|
messageCreateEventGuildTimeout: 100,
|
||||||
shardCount: 1,
|
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 {
|
export abstract class SessionManager extends CachedManager {
|
||||||
constructor(client: Client, iterable?: Iterable<unknown>);
|
constructor(client: Client, iterable?: Iterable<unknown>);
|
||||||
public fetch(): Promise<SessionManager>;
|
public fetch(): Promise<SessionManager>;
|
||||||
public logoutAllDevices(password?: string, mfaCode?: string): Promise<undefined>;
|
public logoutAllDevices(mfaCode?: string): Promise<undefined>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export abstract class Session extends Base {
|
export abstract class Session extends Base {
|
||||||
@ -173,7 +173,7 @@ export abstract class Session extends Base {
|
|||||||
public clientInfo?: SessionClientInfo;
|
public clientInfo?: SessionClientInfo;
|
||||||
public readonly createdTimestamp: number;
|
public readonly createdTimestamp: number;
|
||||||
public readonly createdAt: Date;
|
public readonly createdAt: Date;
|
||||||
public logout(password?: string, mfaCode?: string): Promise<undefined>;
|
public logout(mfaCode?: string): Promise<undefined>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface SessionClientInfo {
|
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 redeemNitro(code: string, channel?: TextChannelResolvable, failIfNotExists?: boolean): object;
|
||||||
public generateInvite(options?: InviteGenerationOptions): string;
|
public generateInvite(options?: InviteGenerationOptions): string;
|
||||||
public login(token?: string): Promise<string>;
|
public login(token?: string): Promise<string>;
|
||||||
|
public normalLogin(username: string, password?: string, mfaCode?: string): Promise<string>;
|
||||||
public QRLogin(debug?: boolean): DiscordAuthWebsocket;
|
public QRLogin(debug?: boolean): DiscordAuthWebsocket;
|
||||||
public remoteAuth(url: string, forceAccept?: boolean): Promise<remoteAuthConfrim | undefined>;
|
public remoteAuth(url: string, forceAccept?: boolean): Promise<remoteAuthConfrim | undefined>;
|
||||||
public createToken(): Promise<string>;
|
public createToken(): Promise<string>;
|
||||||
@ -4705,6 +4706,7 @@ export interface ClientOptions {
|
|||||||
autoCookie?: boolean;
|
autoCookie?: boolean;
|
||||||
autoRedeemNitro?: boolean;
|
autoRedeemNitro?: boolean;
|
||||||
patchVoice?: boolean;
|
patchVoice?: boolean;
|
||||||
|
password?: string;
|
||||||
DMSync?: boolean;
|
DMSync?: boolean;
|
||||||
proxy?: string;
|
proxy?: string;
|
||||||
captchaService?: string;
|
captchaService?: string;
|
||||||
|
Loading…
Reference in New Issue
Block a user