mtproto-core
mtproto-core copied to clipboard
How to authenticate?
Hello,
Fairly new to Node and Telegram so this is a bit overwhelming for me. I've created an "api.js" file and copied the content of your api.js file into it (my api and api_hash are configured in the file).
Next i've created the "example.js" file like this:
var api = require('./api.js');
(async () => {
const user = await getUser();
const phone = '+3xxxxxxxx';
const code = 'XXXXX';
if (!user) {
const { phone_code_hash } = await sendCode(phone);
try {
const signInResult = await signIn({
code,
phone,
phone_code_hash,
});
if (signInResult._ === 'auth.authorizationSignUpRequired') {
await signUp({
phone,
phone_code_hash,
});
}
} catch (error) {
if (error.error_message !== 'SESSION_PASSWORD_NEEDED') {
console.log(`error:`, error);
return;
}
// 2FA
const password = 'MY_PERSONAL_2FA_CODE';
const { srp_id, current_algo, srp_B } = await getPassword();
const { g, p, salt1, salt2 } = current_algo;
const { A, M1 } = await api.mtproto.crypto.getSRPParams({
g,
p,
salt1,
salt2,
gB: srp_B,
password,
});
const checkPasswordResult = await checkPassword({ srp_id, A, M1 });
}
}
})();
async function getUser() {
try {
const user = await api.call('users.getFullUser', {
id: {
_: 'inputUserSelf',
},
});
return user;
} catch (error) {
return null;
}
}
function sendCode(phone) {
return api.call('auth.sendCode', {
phone_number: phone,
settings: {
_: 'codeSettings',
},
});
}
function signIn({ code, phone, phone_code_hash }) {
return api.call('auth.signIn', {
phone_code: code,
phone_number: phone,
phone_code_hash: phone_code_hash,
});
}
function signUp({ phone, phone_code_hash }) {
return api.call('auth.signUp', {
phone_number: phone,
phone_code_hash: phone_code_hash,
first_name: 'MTProto',
last_name: 'Core',
});
}
function getPassword() {
return api.call('account.getPassword');
}
function checkPassword({ srp_id, A, M1 }) {
return api.call('auth.checkPassword', {
password: {
_: 'inputCheckPasswordSRP',
srp_id,
A,
M1,
},
});
}
So I entered my phone number, but can't write anything yet for the "code" variable since I didn't receive the code yet. I also changed the 2FA code to my personal 2FA string. Once I start example.js I get:
users.getFullUser error: { _: 'mt_rpc_error', error_code: 401, error_message: 'SESSION_PASSWORD_NEEDED' } auth.sendCode error: { _: 'mt_rpc_error', error_code: 500, error_message: 'AUTH_RESTART' } (node:3624408) UnhandledPromiseRejectionWarning: #<Object> (Use
node --trace-warnings ...
to show where the warning was created) (node:3624408) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag--unhandled-rejections=strict
(see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 3) (node:3624408) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code
Can anyone point me in the right direction how to get authenticated?
Thanks!
hmm, maybe i'm getting closer now. I've executed this:
function sendCode(phone) {
return api.call('auth.sendCode', {
phone_number: phone,
settings: {
_: 'codeSettings',
},
});
}
and got the code from Telegram. Next I want to execute this:
function signIn({ code, phone, phone_code_hash }) {
return api.call('auth.signIn', {
phone_code: code,
phone_number: phone,
phone_code_hash: phone_code_hash,
});
}
but I don't know what the "phone_code_hash" needs to be? I have the TG code and my phone number of course, but not the "phone_code_hash"...
hmm, maybe i'm getting closer now. I've executed this:
function sendCode(phone) { return api.call('auth.sendCode', { phone_number: phone, settings: { _: 'codeSettings', }, }); }
and got the code from Telegram. Next I want to execute this:
function signIn({ code, phone, phone_code_hash }) { return api.call('auth.signIn', { phone_code: code, phone_number: phone, phone_code_hash: phone_code_hash, }); }
but I don't know what the "phone_code_hash" needs to be? I have the TG code and my phone number of course, but not the "phone_code_hash"...
you will get the phone_code_hash
from the API call to your sendCode
method.
const res = await sendCode('9999XXXXXXX');
const phone_code_hash = res['phone_code_hash'];
Which you can use in the later API call. I hope that helps.
Sorry sir, I still have troubles authenticating against Telegram. Is there someone over here that can show me the exact way how they achieved it?
If I execute the script I receive the Telegram message with an unique code, but can't enter the code into the script since it's already running. So I need to stop the script, enter the "code" I received but I still get an error if I do it that way...
users.getFullUser error: {
_: 'mt_rpc_error',
error_code: 401,
error_message: 'AUTH_KEY_UNREGISTERED'
}
auth.signIn error: {
_: 'mt_rpc_error',
error_code: 401,
error_message: 'SESSION_PASSWORD_NEEDED'
}
Thanks again!
Hey, did you authenticated your app??
I can't... that's the problem :).
I'm adding my phone number to the script, the api_id and api_hash and run it. Once I run it I get the code from Telegram.
I stop the script and add the code into the script and run it again. Next I get are the errors described here above.
So I wonder how you did the authentication process. (friendly reminder, i'm fairly new to Node, so i'm not a daily coder ;-) )
Thanks!
No one that can help me?
This worked for me with my own phone number but it doesn't work with the test settings:
// main.js
const MTProto = require("@mtproto/core");
const prompt = require("prompt");
const API = require("./telegramApi");
const api = new API();
async function main() {
const user = await api.getUser();
console.log("User 1st try: ", user);
// const phone = "+99966XYYYY";
// const code = "XXXXX";
if (!user) {
const { phone } = await prompt.get("phone");
const { phone_code_hash } = await api.sendCode(phone);
const { code } = await prompt.get("code");
try {
const signInResult = await api.signIn({
code,
phone,
phone_code_hash,
});
console.log(signInResult);
if (signInResult._ === "auth.authorizationSignUpRequired") {
const singUpResult = await api.signUp({
phone,
phone_code_hash,
});
console.log(singUpResult);
}
const newUser = await api.getUser();
console.log("User 2nd try: ", newUser);
} catch (error) {
if (error.error_message !== "SESSION_PASSWORD_NEEDED") {
console.log(`error:`, error);
return;
}
// 2FA...
}
}
const result = await api.call("help.getNearestDc");
console.log(result);
process.exit(0);
}
main();
// api.js
const path = require("path");
const MTProto = require("@mtproto/core");
const { sleep } = require("@mtproto/core/src/utils/common");
class API {
constructor({ test } = { test: false }) {
this.mtproto = new MTProto({
api_id: "",
api_hash: "",
test,
storageOptions: {
path: path.resolve(__dirname, "./telegramData.json"),
},
});
}
async call(method, params, options = {}) {
console.log(method);
try {
const result = await this.mtproto.call(method, params, options);
console.log(result);
return result;
} catch (error) {
console.error(error);
const { error_code, error_message } = error;
if (error_code === 420) {
const seconds = Number(error_message.split("FLOOD_WAIT_")[1]);
const ms = seconds * 1000;
await sleep(ms);
return this.call(method, params, options);
}
if (error_code === 303) {
const [type, dcIdAsString] = error_message.split("_MIGRATE_");
const dcId = Number(dcIdAsString);
// If auth.sendCode call on incorrect DC need change default DC, because
// call auth.signIn on incorrect DC return PHONE_CODE_EXPIRED error
if (type === "PHONE") {
await this.mtproto.setDefaultDc(dcId);
} else {
Object.assign(options, { dcId });
}
return this.call(method, params, options);
}
return Promise.reject(error);
}
}
async getUser() {
try {
const user = await this.call("users.getFullUser", {
id: {
_: "inputUserSelf",
},
});
return user;
} catch (error) {
return null;
}
}
sendCode(phone) {
try {
return this.call("auth.sendCode", {
phone_number: phone,
settings: {
_: "codeSettings",
},
});
} catch (error) {
throw error;
}
}
signIn({ code, phone, phone_code_hash }) {
return this.call("auth.signIn", {
phone_code: code,
phone_number: phone,
phone_code_hash: phone_code_hash,
});
}
signUp({ phone, phone_code_hash }) {
return this.call("auth.signUp", {
phone_number: phone,
phone_code_hash: phone_code_hash,
first_name: "MTProto",
last_name: "Core",
});
}
getPassword() {
return this.call("account.getPassword");
}
checkPassword({ srp_id, A, M1 }) {
return this.call("auth.checkPassword", {
password: {
_: "inputCheckPasswordSRP",
srp_id,
A,
M1,
},
});
}
}
module.exports = API;
Install the prompt
library, so you can type in your phone and code:
npm i prompt
I didn't use the 2FA section, so you need to add that yourself.
@andrewszucs what error do you get with test number? I was having problems because docs says that verification code are 5 digits but in fact It was 6 to get my testing number work
@andrewszucs what erro u get with test number? I was having problems because docs says that verification code are 5 digits but in fact It was 6 to get my testing number work
That was my problem too. Thanks a lot @allandiego ! It works now. 🙌
This worked for me with my own phone number but it doesn't work with the test settings:
Install the
prompt
library, so you can type in your phone and code:npm i prompt
I didn't use the 2FA section, so you need to add that yourself.
Hi, I got this error now:
internal/modules/cjs/loader.js:883 throw err; ^
Error: Cannot find module './telegramApi'
Which dependency is this?
Thanks!
This worked for me with my own phone number but it doesn't work with the test settings:
// main.js const MTProto = require("@mtproto/core"); const prompt = require("prompt"); const API = require("./telegramApi"); const api = new API(); async function main() { const user = await api.getUser(); console.log("User 1st try: ", user); // const phone = "+99966XYYYY"; // const code = "XXXXX"; if (!user) { const { phone } = await prompt.get("phone"); const { phone_code_hash } = await api.sendCode(phone); const { code } = await prompt.get("code"); try { const signInResult = await api.signIn({ code, phone, phone_code_hash, }); console.log(signInResult); if (signInResult._ === "auth.authorizationSignUpRequired") { const singUpResult = await api.signUp({ phone, phone_code_hash, }); console.log(singUpResult); } const newUser = await api.getUser(); console.log("User 2nd try: ", newUser); } catch (error) { if (error.error_message !== "SESSION_PASSWORD_NEEDED") { console.log(`error:`, error); return; } // 2FA... } } const result = await api.call("help.getNearestDc"); console.log(result); process.exit(0); } main();
// api.js const path = require("path"); const MTProto = require("@mtproto/core"); const { sleep } = require("@mtproto/core/src/utils/common"); class API { constructor({ test } = { test: false }) { this.mtproto = new MTProto({ api_id: "", api_hash: "", test, storageOptions: { path: path.resolve(__dirname, "./telegramData.json"), }, }); } async call(method, params, options = {}) { console.log(method); try { const result = await this.mtproto.call(method, params, options); console.log(result); return result; } catch (error) { console.error(error); const { error_code, error_message } = error; if (error_code === 420) { const seconds = Number(error_message.split("FLOOD_WAIT_")[1]); const ms = seconds * 1000; await sleep(ms); return this.call(method, params, options); } if (error_code === 303) { const [type, dcIdAsString] = error_message.split("_MIGRATE_"); const dcId = Number(dcIdAsString); // If auth.sendCode call on incorrect DC need change default DC, because // call auth.signIn on incorrect DC return PHONE_CODE_EXPIRED error if (type === "PHONE") { await this.mtproto.setDefaultDc(dcId); } else { Object.assign(options, { dcId }); } return this.call(method, params, options); } return Promise.reject(error); } } async getUser() { try { const user = await this.call("users.getFullUser", { id: { _: "inputUserSelf", }, }); return user; } catch (error) { return null; } } sendCode(phone) { try { return this.call("auth.sendCode", { phone_number: phone, settings: { _: "codeSettings", }, }); } catch (error) { throw error; } } signIn({ code, phone, phone_code_hash }) { return this.call("auth.signIn", { phone_code: code, phone_number: phone, phone_code_hash: phone_code_hash, }); } signUp({ phone, phone_code_hash }) { return this.call("auth.signUp", { phone_number: phone, phone_code_hash: phone_code_hash, first_name: "MTProto", last_name: "Core", }); } getPassword() { return this.call("account.getPassword"); } checkPassword({ srp_id, A, M1 }) { return this.call("auth.checkPassword", { password: { _: "inputCheckPasswordSRP", srp_id, A, M1, }, }); } } module.exports = API;
Install the
prompt
library, so you can type in your phone and code:npm i prompt
I didn't use the 2FA section, so you need to add that yourself.
Adding a prompt for the SMS verification works. This should really be added to the docs here.
@alik0211 Can we add this please to the docs? I'm willing to help.
Does anyone else have an issue with the phone code? I have to keep entering the phone code every time I start node. The data JSON file is being written to, but it does looks like it is being read on start
Finally, deal with it. Official docs btw are better than all this code above. Thank you @alik0211 !
*** HOW TO LOGIN:
- set api_id in api.js file from telegram application
- set api_hash in api.js file
- log in to the account
node auth.js
- prompt phone & prompt auth code given from tg channel of telegram official
- see the updates. successful login. ===================
// API.js
/* eslint-disable no-undef */
const path = require("path");
const MTProto = require("@mtproto/core");
const { sleep } = require("@mtproto/core/src/utils/common");
class API {
constructor() {
this.mtproto = new MTProto({
// lucky
api_id: api_id,
api_hash: api_hash,
storageOptions: {
path: path.resolve(__dirname, "./1.json"),
},
});
}
async call(method, params, options = {}) {
try {
const result = await this.mtproto.call(method, params, options);
return result;
} catch (error) {
console.log(`${method} error:`, error);
const { error_code, error_message } = error;
if (error_code === 420) {
const seconds = Number(error_message.split("FLOOD_WAIT_")[1]);
const ms = seconds * 1000;
await sleep(ms);
return this.call(method, params, options);
}
if (error_code === 303) {
const [type, dcIdAsString] = error_message.split("_MIGRATE_");
const dcId = Number(dcIdAsString);
// If auth.sendCode call on incorrect DC need change default DC, because
// call auth.signIn on incorrect DC return PHONE_CODE_EXPIRED error
if (type === "PHONE") {
await this.mtproto.setDefaultDc(dcId);
} else {
Object.assign(options, { dcId });
}
return this.call(method, params, options);
}
return Promise.reject(error);
}
}
}
const api = new API();
module.exports = api;
auth.js
// AUTH.js
/* eslint-disable no-undef */
const api = require("./api-origin");
const prompt = require("prompt");
const { sendMessage } = require("./updates");
async function getUser() {
try {
const user = await api.call("users.getFullUser", {
id: {
_: "inputUserSelf",
},
});
return user;
} catch (error) {
return null;
}
}
function signIn({ code, phone, phone_code_hash }) {
return api
.call("auth.signIn", {
phone_code: code,
phone_number: phone,
phone_code_hash: phone_code_hash,
})
.then((v) => {
console.log("LOGIN SUCCESS: ", v);
sendMessage();
})
.catch((e) => console.log("LOGIN FAIL: ", e));
}
function sendCode(phone) {
return api.call("auth.sendCode", {
phone_number: phone,
settings: {
_: "codeSettings",
},
});
}
(async () => {
const user = await getUser();
// const phone = "+9XXXXXXXXXX";
if (!user) {
const { phone } = await prompt.get("phone");
const { phone_code_hash } = await sendCode(phone);
const { code } = await prompt.get("code");
try {
const signInResult = await signIn({
code,
phone,
phone_code_hash,
});
if (signInResult._ === "auth.authorizationSignUpRequired") {
await signUp({
phone,
phone_code_hash,
});
}
} catch (error) {
if (error.error_message !== "SESSION_PASSWORD_NEEDED") {
console.log(`error:`, error);
return;
}
// 2FA
const password = "USER_PASSWORD";
const { srp_id, current_algo, srp_B } = await getPassword();
const { g, p, salt1, salt2 } = current_algo;
const { A, M1 } = await api.mtproto.crypto.getSRPParams({
g,
p,
salt1,
salt2,
gB: srp_B,
password,
});
const checkPasswordResult = await checkPassword({ srp_id, A, M1 });
}
}
})();
updates.js
// UPDATES.js
/* eslint-disable no-undef */
const api = require("./api-origin");
api.mtproto.updates.on("updates", (updateInfo) => {
console.log("updates:", updateInfo);
});
function sendMessage() {
api.call("messages.sendMessage", {
clear_draft: true,
peer: {
_: "inputPeerSelf",
},
message: "Hello @mtproto_core",
entities: [
{
_: "messageEntityBold",
offset: 6,
length: 13,
},
],
random_id:
Math.ceil(Math.random() * 0xffffff) + Math.ceil(Math.random() * 0xffffff),
});
}
module.exports = { sendMessage };
@IgorKurkov
I made a smaller version of your script here
/* Example how to create MTProto:
const api = new MTProto({
api_id: Number(process.env.APP_ID),
api_hash: process.env.APP_HASH,
storageOptions: { path: './tempdata.json' }
})
*/
// Inject right after creating MTProto
api.__call = api.call
api.call = async (name, params, options) => {
if(options?.dcId) return api.__call(name, params, options)
if(api.__defaultDc) {
if(!options) options = {}
options.dcId = api.__defaultDc
}
try {
return await api.__call(name, params, options)
} catch(e) {
const migrateRegex = /_MIGRATE_(\d+)$/
if(migrateRegex.test(e?.error_message)) {
api.__defaultDc = Number(e.error_message.match(migrateRegex)[1])
return await api.call(name, params, options)
} else throw e
}
}
Did anybody get 2FA working? To me it seems the script already fails to recognize "SESSION_PASSWORD_NEEDED" but even if this gets bypassed to reach the 2FA section, I end up with error_code: 400, error_message: 'PASSWORD_HASH_INVALID'
Did anybody get 2FA working? To me it seems the script already fails to recognize "SESSION_PASSWORD_NEEDED" but even if this gets bypassed to reach the 2FA section, I end up with error_code: 400, error_message: 'PASSWORD_HASH_INVALID'
See https://www.npmjs.com/package/telegram
i have a error: Please help me! ( const phone = '+99966XYYYY'; const code = 'XXXXXX' )
users.getFullUser error: { _: 'mt_rpc_error', error_code: 401, error_message: 'AUTH_KEY_UNREGISTERED' } auth.sendCode error: { _: 'mt_rpc_error', error_code: 400, error_message: 'PHONE_NUMBER_INVALID' }