I have a service that use GramJS. In this service I tried to initialize a connection to telegram using GramJS library. Upon running the code I got this error:
[2024-04-19 15:10:02] (node:11888) UnhandledPromiseRejectionWarning: Error: Connection should be a class not an instance
at new TelegramBaseClient (C:Usersr.trisnosaputraDocumentsACM-NEWtelegram-notification-backend-newnode_modulestelegramclienttelegramBaseClient.js:84:19)
at new TelegramClient (C:Usersr.trisnosaputraDocumentsACM-NEWtelegram-notification-backend-newnode_modulestelegramclientTelegramClient.js:63:9)
at Command.callback (C:Usersr.trisnosaputraDocumentsACM-NEWtelegram-notification-backend-newdistlibappExternalServicestelegramExternalService.js:108:35)
at normal_reply (C:Usersr.trisnosaputraDocumentsACM-NEWtelegram-notification-backend-newnode_modulesredisindex.js:654:21)
at RedisClient.return_reply (C:Usersr.trisnosaputraDocumentsACM-NEWtelegram-notification-backend-newnode_modulesredisindex.js:752:9)
at JavascriptRedisParser.returnReply (C:Usersr.trisnosaputraDocumentsACM-NEWtelegram-notification-backend-newnode_modulesredisindex.js:137:18)
at JavascriptRedisParser.execute (C:Usersr.trisnosaputraDocumentsACM-NEWtelegram-notification-backend-newnode_modulesredis-parserlibparser.js:544:14)
at Socket.<anonymous> (C:Usersr.trisnosaputraDocumentsACM-NEWtelegram-notification-backend-newnode_modulesredisindex.js:218:27)
at Socket.emit (events.js:400:28)
at addChunk (internal/streams/readable.js:293:12)
[2024-04-19 15:10:02] (node:11888) 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: 1)
[2024-04-19 15:10:02] (node:11888) [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.
[2024-04-19 15:10:02] Schedule not found!
Here is the code:
import * as telethon from "telegram";
import { StringSession } from "telegram/sessions";
import { Config } from "../config";
import { Api } from "telegram";
import { IDI } from "../../interface";
import { TelegramClientDto } from "../../dto";
import { Hash } from "../helper";
import { ConnectionTCPObfuscated } from "telegram/network";
export default class TelegramExternalService {
public client: TelegramClientDto;
private config: Config;
private static di: IDI = null;
private static isReady = false;
private static recommendedDc: {
id: number;
ipAddress: string;
port: number;
} = null;
private static sessions: {
[phoneNumber: string]: TelegramClientDto
} = {};
public static get ready(): boolean {
return TelegramExternalService.isReady;
}
public static setDI(di: IDI): void {
if (this.di !== null) {
throw new Error("TelegramExternalService.setDI cannot be called twice");
}
this.di = di;
}
public static getSession(phoneNumber: string): TelegramClientDto {
if (this.sessions[phoneNumber] && this.sessions[phoneNumber].connected) {
return this.sessions[phoneNumber];
}
}
public static async startSession(phoneNumber: string): Promise<{token?: string; status: string;}> {
const telegramExternalService = new TelegramExternalService();
if (this.sessions[phoneNumber] && this.sessions[phoneNumber].connected) {
telegramExternalService.client = this.sessions[phoneNumber];
return({status: "LOGIN_SUCCESS"});
}
await telegramExternalService.initializeSession(phoneNumber);
try {
const status = await telegramExternalService.initializeConnection(phoneNumber);
if (status) {
return({status: "LOGIN_SUCCESS"});
}
console.log(status);
const token = Hash.encode(phoneNumber);
TelegramExternalService.di.redis.setex(`/phone/${phoneNumber}/token`, 999, token);
return({status: "SEND_PHONE_CODE", token});
} catch (e) {
console.log(e);
return {status: e.message};
}
}
private static async getRecommendedDc(config) {
if (TelegramExternalService.recommendedDc !== null) {
return TelegramExternalService.recommendedDc;
}
let recommendedDc;
const client = new telethon.TelegramClient(new StringSession(""), config.appAPIId, config.appAPIHash, {
useIPV6: false,
connectionRetries: 1
});
if (config.telegramEnvironment === "test") {
recommendedDc = {
id: 2,
ipAddress: "149.154.167.40",
port: 443
};
} else {
console.log("Connecting...");
await client.connect();
console.log("Done connecting...");
const nearestDc = await client.invoke(new Api.help.GetNearestDc());
const connectionConfig = await client.invoke(new Api.help.GetConfig());
await client.destroy();
recommendedDc = connectionConfig.dcOptions.find(dc => dc.id === nearestDc.nearestDc && !dc.ipv6);
}
TelegramExternalService.recommendedDc = recommendedDc;
return recommendedDc;
}
private constructor() {
this.config = new Config();
}
private initializeSession(phoneNumber: string): Promise<void> {
return new Promise((resolve) => {
if (TelegramExternalService.sessions[phoneNumber]) {
this.client = TelegramExternalService.sessions[phoneNumber];
console.log(`[${phoneNumber}] uses exising connection`);
resolve();
} else {
console.log(`[${phoneNumber}] attemps to create new connection`);
TelegramExternalService.di.redis.get(`sessions/${phoneNumber}`, async (err, sessionString) => {
let session: StringSession;
if (sessionString) {
console.log(`[${phoneNumber}] has saved session`);
session = new StringSession(sessionString);
} else {
console.log(`[${phoneNumber}] has no saved session`);
session = new StringSession("");
}
this.client = new telethon.TelegramClient(session, this.config.appAPIId, this.config.appAPIHash, {
useIPV6: false,
connectionRetries: 1,
connection: this.config.telegramEnvironment === "test" ? undefined : ConnectionTCPObfuscated
});
resolve();
});
}
});
}
private initializeConnection(phoneNumber: string): Promise<boolean> {
return new Promise((async (initialized, failedToInitialize) => {
const eventName = `/phone/${phoneNumber}/applyCode`;
const recommendedDc = await TelegramExternalService.getRecommendedDc(this.config);
console.log("recommendedDc", recommendedDc);
this.client.session.setDC(recommendedDc.id, recommendedDc.ipAddress, recommendedDc.port);
try {
// @ts-ignore
await this.client.start({
phoneNumber: phoneNumber,
onError: (e) => {
TelegramExternalService.di.redis.emit(`/phone/${phoneNumber}/applyCode/callback`, "false");
console.log(e);
},
phoneCode: () => new Promise((sendPhoneCode) => {
console.log(`Try to listening on event [${eventName}]`);
console.log(`Connected to ${this.client.session.dcId}`);
console.log("HEY! WHeRE IS YOUR CODE?");
TelegramExternalService.di.redis.once(eventName, (phoneCode) => {
console.log(`Phone code of ${phoneNumber} is ${phoneCode}`);
sendPhoneCode(phoneCode);
});
console.log(`Listening on event [${eventName}]`);
initialized(false);
}),
});
console.log(`Phone number [${phoneNumber}] is ready`);
TelegramExternalService.di.redis.emit(`/phone/${phoneNumber}/applyCode/callback`, "true");
const currentUser = await this.client.getMe();
TelegramExternalService.sessions[phoneNumber] = this.client;
TelegramExternalService.sessions[phoneNumber].currentUser = currentUser as any;
this.client.currentUser = currentUser as any;
console.log(currentUser);
console.log("Connected to ", this.client.session.serverAddress);
this.client.session.save();
const session = this.client.session.serverAddress;
if (session) {
const key = `sessions/${phoneNumber}`;
TelegramExternalService.di.redis.setex(key, 999, session);
TelegramExternalService.di.redis.persist(key);
}
TelegramExternalService.isReady = true;
console.log(session);
initialized(true);
} catch (e) {
console.log(e);
failedToInitialize(e);
}
}));
}
}
Anyone knows how to fix the error?
I hope to fix the error in the code.
2
Answers
The problem is that your
undefined
connection value is overwriting the defaults and leading to a false-positive.From the telegramBaseClient source code…
A quick demonstration shows the problem
The Gram.js code could be better and check for undefined values but it doesn’t. The solution here is to not set a value at all for your test environment
Not sure if this is what you need?