Open pentolbakso opened 3 years ago
Maybe it will help somehow: https://core.telegram.org/api/qr-login
Same for me. Tried 5 different base64 libraries. I thought it was an encoding issue. There is a difference between base64 and base64url. I was happy when I read the doc more carefully. But even with the base64url token doesn't work.
Tried to decode QR code image with an online converter but QR code is correct.
I don't have any ideas to check for now.
@pentolbakso did you solve the issue eventually?
If somebody has any ideas about the problem I will be happy to check.
I've login successfully :) The problem was in the "test: true" MTProto param. I removed the "test: true" and telegram app successfully login me with QR code
And it's ok to use even base64 encoded tokens. Not base64url
@alorian can u paste some example of your code here?
@mrsum I used Nestjs framework for my telegram client implementation. Not sure it will be relevant to anybody because of the application specific code. But I can share some parts if you want. I will try to clean everything unrelevent and simplify my examples
Just regular nestjs controller
import { Controller, Get } from '@nestjs/common';
import { TelegramAuthService } from './auth.service';
@Controller('telegram')
export class TelegramController {
constructor(private readonly authService: TelegramAuthService) {}
@Get('/auth')
async auth() {
const src = await this.authService.getQRCodeBase64();
let result = '';
result += '<img src="' + src + '" alt="qr code for login" />';
return result;
}
}
Simple service
import { Injectable } from '@nestjs/common';
import { TelegramApiService } from './api.service';
import * as buf from 'base64-arraybuffer';
import * as QRCode from 'qrcode';
@Injectable()
export class TelegramAuthService {
constructor(private api: TelegramApiService) {}
async getQRCodeBase64() {
const LoginToken = await this.api.getLoginToken();
const encodedToken = buf.encode(LoginToken.token);
const url = 'tg://login?token=' + encodedToken;
return QRCode.toDataURL(url);
}
}
A service built on top of the mtproto-core
import { Injectable } from '@nestjs/common';
import * as path from 'path';
import * as MTProto from '@mtproto/core/envs/node';
import { sleep } from '@mtproto/core/src/utils/common';
@Injectable()
export class TelegramApiService {
app_id = 0000000;
api_hash = 'hash';
mtproto: MTProto;
constructor() {
this.mtproto = new MTProto({
api_id: this.app_id,
api_hash: this.api_hash,
//test: true,
storageOptions: {
path: path.resolve(__dirname, './data/1.json'),
},
});
this.mtproto.updates.on('updatesTooLong', (updateInfo) => {
console.log('updatesTooLong:', updateInfo);
});
this.mtproto.updates.on('updateShortMessage', (updateInfo) => {
console.log('updateShortMessage:', updateInfo);
});
this.mtproto.updates.on('updateShortChatMessage', (updateInfo) => {
console.log('updateShortChatMessage:', updateInfo);
});
this.mtproto.updates.on('updateShort', (updateInfo) => {
console.log('updateShort:', updateInfo);
});
this.mtproto.updates.on('updatesCombined', (updateInfo) => {
console.log('updatesCombined:', updateInfo);
});
this.mtproto.updates.on('updates', (updateInfo) => {
console.log('updates:', updateInfo);
});
this.mtproto.updates.on('updateShortSentMessage', (updateInfo) => {
console.log('updateShortSentMessage:', updateInfo);
});
}
async getLoginToken() {
return await this.call('auth.exportLoginToken', {
app_id: this.app_id,
api_hash: this.api_hash,
except_ids: [],
});
}
async call(method: string, params, options = {}) {
try {
return await this.mtproto.call(method, params, options);
} 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);
}
}
}
Just tested it and everything works. From the second attempt but works. At the very first time there was an error about wrong QR code but the second attempt logged me in correctly.
Packages in my code: https://www.npmjs.com/package/base64-arraybuffer https://www.npmjs.com/package/qrcode
Hope it will help somebody.
@alorian thank u my friend, your example is very helpfull
Hi @alorian is auth.acceptLoginToken working for you.
I am able to generate QR code perfectly but not able to run auth.acceptLoginToken can you help me with this if possible
Hi,
Has anyone succeed implementing the QR code login flow ? My problem is that i always get the "Invalid QR Code" after scanning the QR code on my phone. I've checked the token etc .. looks normal to me.
Could it be that we need special permission from telegram to use this feature?
Thanks