feat: Login Discord (email + password)

This commit is contained in:
March 7th
2022-11-08 23:56:17 +07:00
parent 6255db8aa2
commit f5de4de7c0
6 changed files with 75 additions and 13 deletions

View File

@@ -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');
}

View File

@@ -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);

View File

@@ -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,
},
});

View File

@@ -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,
},
});

View File

@@ -154,6 +154,7 @@ class Options extends null {
captchaKey: null,
DMSync: false,
patchVoice: false,
password: null,
waitGuildTimeout: 15_000,
messageCreateEventGuildTimeout: 100,
shardCount: 1,