123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119 |
- const {Session} = require("./Session");
- const {doAuthentication} = require("../network/authenticator");
- const {MtProtoSender} = require("../network/mtprotoSender");
- const {TcpTransport} = require("../network/tcpTransport");
- const {InvokeWithLayerRequest, InitConnectionRequest} = require("../gramjs/tl/functions/index");
- const {GetConfigRequest} = require("../gramjs/tl/functions/help");
- class TelegramClient {
- constructor(sessionUserId, layer, apiId, apiHash) {
- if (apiId === undefined || apiHash === undefined) {
- throw Error("Your API ID or Hash are invalid. Please read \"Requirements\" on README.md");
- }
- this.apiId = apiId;
- this.apiHash = apiHash;
- this.layer = layer;
- this.session = Session.tryLoadOrCreateNew(sessionUserId);
- this.transport = TcpTransport(this.session.serverAddress, this.session.port);
- //These will be set later
- this.dcOptions = undefined;
- this.sender = undefined;
- this.phoneCodeHashes = Array();
- }
- /**
- * Connects to the Telegram servers, executing authentication if required.
- * Note that authenticating to the Telegram servers is not the same as authenticating
- * the app, which requires to send a code first.
- * @param reconnect {Boolean}
- * @returns {Promise<Boolean>}
- */
- async connect(reconnect = false) {
- try {
- if (!this.session.authKey || reconnect) {
- let res = doAuthentication(this.transport);
- this.session.authKey = res.authKey;
- this.session.timeOffset = res.timeOffset;
- this.session.save();
- }
- this.sender = MtProtoSender(this.transport, this.session);
- // Now it's time to send an InitConnectionRequest
- // This must always be invoked with the layer we'll be using
- let query = InitConnectionRequest({
- apiId: this.apiId,
- deviceModel: "PlaceHolder",
- systemVersion: "PlaceHolder",
- appVersion: "0.0.1",
- langCode: "en",
- query: GetConfigRequest()
- });
- let result = await this.invoke(InvokeWithLayerRequest({
- layer: this.layer,
- query: query
- }));
- // We're only interested in the DC options
- // although many other options are available!
- this.dcOptions = result.dcOptions;
- return true;
- } catch (error) {
- console.log('Could not stabilise initial connection: {}'.replace("{}", error));
- return false;
- }
- }
- /**
- * Reconnects to the specified DC ID. This is automatically called after an InvalidDCError is raised
- * @param dc_id {number}
- */
- async reconnect_to_dc(dc_id) {
- if (this.dcOptions === undefined || this.dcOptions.length === 0) {
- throw new Error("Can't reconnect. Stabilise an initial connection first.");
- }
- let dc;
- for (dc of this.dcOptions) {
- if (dc.id === dc_id) {
- break;
- }
- }
- this.transport.close();
- this.transport = new TcpTransport(dc.ipAddress, dc.port);
- this.session.server_address = dc.ipAddress;
- this.session.port = dc.port;
- this.session.save();
- await this.connect(true);
- }
- /**
- * Disconnects from the Telegram server
- * @returns {Promise<void>}
- */
- async disconnect() {
- if (this.sender) {
- await this.sender.disconnect();
- }
- }
- /**
- * Invokes a MTProtoRequest (sends and receives it) and returns its result
- * @param request
- * @returns {Promise}
- */
- async invoke(request) {
- if (!MTProtoRequest.prototype.isPrototypeOf(Object.getPrototypeOf(request).prototype)) {
- throw new Error("You can only invoke MtProtoRequests");
- }
- await this.sender.send(request);
- await this.sender.receive(request);
- return request.result;
- }
- }
- module.exports = TelegramClient;
|